├── .github
├── Contributing.md
├── PULL_REQUEST_TEMPLATE.md
├── dependabot.yml
└── semantic.yml
├── .gitignore
├── .golangci.yml
├── Attribution.txt
├── CHANGLOG.md
├── Dockerfile
├── Jenkinsfile
├── LICENSE
├── Makefile
├── OWNERS.md
├── README.md
├── bin
└── test-attribution-txt.sh
├── cmd
├── main.go
└── res
│ ├── configuration.yaml
│ ├── devices
│ └── Simple-Device.yaml
│ └── profiles
│ └── Simple-Driver.yaml
├── go.mod
├── go.sum
├── internal
└── driver
│ ├── constants.go
│ ├── driver.go
│ ├── driver_test.go
│ ├── readingchecker.go
│ ├── types.go
│ └── utils.go
└── version.go
/.github/Contributing.md:
--------------------------------------------------------------------------------
1 | ## Commit Message Guidelines
2 |
3 | We have very precise rules over how our git commit messages can be formatted. This leads to **more readable messages** that are easy to follow when looking through the **project history**. For full contribution guidelines visit
4 | the [Contributors Guide](https://wiki.edgexfoundry.org/display/FA/Committing+Code+Guidelines#CommittingCodeGuidelines-Commits) on the EdgeX Wiki
5 |
6 | ### Commit Message Format
7 | Each commit message consists of a **header**, a **body** and a **footer**. The header has a special format that includes a **type**, a **scope** and a **subject**:
8 |
9 | ```
10 | ():
11 |
12 |
13 |
14 |
15 | ```
16 |
17 | The **header** with **type** is mandatory. The **scope** of the header is optional. This repository has no predefined scopes. A custom scope can be used for clarity if desired.
18 |
19 | Any line of the commit message cannot be longer 100 characters! This allows the message to be easier to read on GitHub as well as in various git tools.
20 |
21 | The footer should contain a [closing reference to an issue](https://help.github.com/articles/closing-issues-via-commit-messages/) if any.
22 |
23 | Example 1:
24 | ```
25 | feat: add new device wizard
26 | ```
27 |
28 | Example 2:
29 | ```
30 | fix: correct default database port configuration
31 |
32 | Previously configuration used to the wrong default database port. This commit fixes the default database port for Redis in the configuration.
33 |
34 | Closes: #123
35 | ```
36 |
37 | ### Revert
38 | If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit. In the body it should say: `This reverts commit .`, where the hash is the SHA of the commit being reverted.
39 |
40 | ### Type
41 | Must be one of the following:
42 |
43 | * **feat**: A new feature
44 | * **fix**: A bug fix
45 | * **docs**: Documentation only changes
46 | * **style**: Changes that do not affect the meaning of the code (white-space, formatting, etc)
47 | * **refactor**: A code change that neither fixes a bug nor adds a feature
48 | * **perf**: A code change that improves performance
49 | * **test**: Adding missing tests or correcting existing tests
50 | * **build**: Changes that affect the CI/CD pipeline or build system or external dependencies (example scopes: travis, jenkins, makefile)
51 | * **ci**: Changes provided by DevOps for CI purposes.
52 | * **revert**: Reverts a previous commit.
53 |
54 | ### Scope
55 | There are no predefined scopes for this repository. A custom scope can be provided for clarity.
56 |
57 | ### Subject
58 | The subject contains a succinct description of the change:
59 |
60 | * use the imperative, present tense: "change" not "changed" nor "changes"
61 | * don't capitalize the first letter
62 | * no dot (.) at the end
63 |
64 | ### Body
65 | Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes".
66 | The body should include the motivation for the change and contrast this with previous behavior.
67 |
68 | ### Footer
69 | The footer should contain any information about **Breaking Changes** and is also the place to
70 | reference GitHub issues that this commit **Closes**.
71 |
72 | **Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this.
73 |
74 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## PR Checklist
2 | Please check if your PR fulfills the following requirements:
3 |
4 | - [ ] Tests for the changes have been added (for bug fixes / features)
5 | - [ ] Docs have been added / updated (for bug fixes / features)
6 |
7 | **If your build fails** due to your commit message not passing the build checks, please review the guidelines here: https://github.com/edgexfoundry/edgex-examples/blob/master/.github/CONTRIBUTING.md.
8 |
9 | ## What is the current behavior?
10 |
11 |
12 |
13 | ## Issue Number:
14 |
15 |
16 | ## What is the new behavior?
17 |
18 |
19 | ## Does this PR introduce a breaking change?
20 |
21 |
22 | - [ ] Yes
23 | - [ ] No
24 |
25 | ## New Imports
26 | Are there any new imports or modules? If so, what are they used for and why?
27 |
28 | ## Specific Instructions
29 | Are there any specific instructions or things that should be known prior to reviewing?
30 |
31 |
32 | ## Other information
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | # Maintain dependencies for Go modules
4 | - package-ecosystem: "gomod"
5 | directory: "/"
6 | schedule:
7 | interval: "daily"
8 | ignore:
9 | - dependency-name: "github.com/edgexfoundry/go-mod-core-contracts/*"
10 | # Included when device-sdk-go is updated
11 | - dependency-name: "github.com/edgexfoundry/go-mod-messaging/*"
12 | # Included when device-sdk-go is updated
13 | - dependency-name: "github.com/edgexfoundry/go-mod-registry/*"
14 | # Included when device-sdk-go is updated
15 | - dependency-name: "github.com/edgexfoundry/go-mod-secrets/*"
16 | # Included when device-sdk-go is updated
17 | - dependency-name: "github.com/edgexfoundry/go-mod-bootstrap/*"
18 | # Included when device-sdk-go is updated
19 |
--------------------------------------------------------------------------------
/.github/semantic.yml:
--------------------------------------------------------------------------------
1 | allowMergeCommits: true
2 | # Always validate the PR title AND all the commits
3 | titleAndCommits: true
4 | types:
5 | - feat
6 | - fix
7 | - docs
8 | - style
9 | - refactor
10 | - perf
11 | - test
12 | - build
13 | - ci
14 | - revert
15 |
16 |
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Binaries for programs and plugins
2 | *.exe
3 | *.exe~
4 | *.dll
5 | *.so
6 | *.dylib
7 |
8 | # Test binary, build with `go test -c`
9 | *.test
10 |
11 | # Output of the go coverage tool, specifically when used with LiteIDE
12 | *.out
13 |
14 | *.log
15 |
16 | .idea/
17 | vendor/
18 | VERSION
19 | cmd/device-s7
20 |
--------------------------------------------------------------------------------
/.golangci.yml:
--------------------------------------------------------------------------------
1 | linters:
2 | disable:
3 | enable:
4 | - gosec
5 |
--------------------------------------------------------------------------------
/Attribution.txt:
--------------------------------------------------------------------------------
1 | The following open source projects are referenced by Device Service SDK Go:
2 |
3 | gorilla/mux 1.6.2 (BSD-3) https://github.com/gorilla/mux
4 | https://github.com/gorilla/mux/blob/master/LICENSE
5 |
6 | hashicorp/consul 1.1.0 (Mozilla Public License 2.0) https://github.com/hashicorp/consul
7 | https://github.com/hashicorp/consul/blob/master/LICENSE
8 |
9 | hashicorp/go-cleanhttp (Mozilla Public License 2.0) https://github.com/hashicorp/go-cleanhttp
10 | https://github.com/hashicorp/go-cleanhttp/blob/master/LICENSE
11 |
12 | hashicorp/go-rootcerts (Mozilla Public License 2.0) https://github.com/hashicorp/go-rootcerts
13 | https://github.com/hashicorp/go-rootcerts/blob/master/LICENSE
14 |
15 | mitchellh/go-homedir (MIT) https://github.com/mitchellh/go-homedir
16 | https://github.com/mitchellh/go-homedir/blob/master/LICENSE
17 |
18 | mitchellh/mapstructure (MIT) https://github.com/mitchellh/mapstructure
19 | https://github.com/mitchellh/mapstructure/blob/master/LICENSE
20 |
21 | hashicorp/serf (Mozilla Public License 2.0) https://github.com/hashicorp/serf
22 | https://github.com/hashicorp/serf/blob/master/LICENSE
23 |
24 | armon/go-metrics (MIT) https://github.com/armon/go-metrics
25 | https://github.com/armon/go-metrics/blob/master/LICENSE
26 |
27 | hashicorp/go-immutable-radix (Mozilla Public License 2.0) https://github.com/hashicorp/go-immutable-radix
28 | https://github.com/hashicorp/go-immutable-radix/blob/master/LICENSE
29 |
30 | hashicorp/golang-lru (Mozilla Public License 2.0) https://github.com/hashicorp/golang-lru
31 | https://github.com/hashicorp/golang-lru/blob/master/LICENSE
32 |
33 | gopkg.in/yaml.v3 (MIT) https://github.com/go-yaml/yaml/tree/v3
34 | https://github.com/go-yaml/yaml/blob/v3/LICENSE
35 |
36 | google/uuid (BSD-3) https://github.com/google/uuid
37 | https://github.com/google/uuid/blob/master/LICENSE
38 |
39 | OneOfOne/xxhash (Apache 2.0) https://github.com/OneOfOne/xxhash
40 | https://github.com/OneOfOne/xxhash/blob/master/LICENSE
41 |
42 | cenkalti/backoff (MIT) https://github.com/cenkalti/backoff
43 | https://github.com/cenkalti/backoff/blob/v3/LICENSE
44 |
45 | davecgh/go-spew (ISC) https://github.com/davecgh/go-spew
46 | https://github.com/davecgh/go-spew/blob/master/LICENSE
47 |
48 | edgexfoundry/device-sdk-go (Apache 2.0) https://github.com/edgexfoundry/device-sdk-go/v4
49 | https://github.com/edgexfoundry/device-sdk-go/blob/master/LICENSE
50 |
51 | edgexfoundry/go-mod-core-contracts (Apache 2.0) https://github.com/edgexfoundry/go-mod-core-contracts/v4
52 | https://github.com/edgexfoundry/go-mod-core-contracts/blob/master/LICENSE
53 |
54 | edgexfoundry/go-mod-registry (Apache 2.0) https://github.com/edgexfoundry/go-mod-registry/v4
55 | https://github.com/edgexfoundry/go-mod-registry/blob/master/LICENSE
56 |
57 | edgexfoundry/go-mod-messaging (Apache 2.0) https://github.com/edgexfoundry/go-mod-messaging/v4
58 | https://github.com/edgexfoundry/go-mod-messaging/blob/master/LICENSE
59 |
60 | edgexfoundry/go-mod-secrets (Apache 2.0) https://github.com/edgexfoundry/go-mod-secrets/v4
61 | https://github.com/edgexfoundry/go-mod-secrets/blob/master/LICENSE
62 |
63 | edgexfoundry/go-mod-bootstrap (Apache 2.0) https://github.com/edgexfoundry/go-mod-bootstrap/v4
64 | https://github.com/edgexfoundry/go-mod-bootstrap/blob/master/LICENSE
65 |
66 | edgexfoundry/go-mod-secrets (Apache 2.0) https://github.com/edgexfoundry/go-mod-configuration/v4
67 | https://github.com/edgexfoundry/go-mod-configuration/blob/master/LICENSE
68 |
69 | go-logfmt/logfmt (MIT) https://github.com/go-logfmt/logfmt
70 | https://github.com/go-logfmt/logfmt/blob/master/LICENSE
71 |
72 | mitchellh/consulstructure (MIT) https://github.com/mitchellh/consulstructure
73 | https://github.com/mitchellh/consulstructure/blob/master/LICENSE
74 |
75 | mitchellh/copystructure (MIT) https://github.com/mitchellh/copystructure
76 | https://github.com/mitchellh/copystructure/blob/master/LICENSE
77 |
78 | mitchellh/reflectwalk (MIT) https://github.com/mitchellh/reflectwalk
79 | https://github.com/mitchellh/reflectwalk/blob/master/LICENSE
80 |
81 | pelletier/go-toml (MIT) https://github.com/pelletier/go-toml
82 | https://github.com/pelletier/go-toml/blob/master/LICENSE
83 |
84 | pmezard/go-difflib (View) https://github.com/pmezard/go-difflib
85 | https://github.com/pmezard/go-difflib/blob/master/LICENSE
86 |
87 | stretchr/testify (MIT) https://github.com/stretchr/testify
88 | https://github.com/stretchr/testify/blob/master/LICENSE
89 |
90 | kr/logfmt (MIT) https://github.com/kr/logfmt
91 | https://github.com/kr/logfmt/blob/master/Readme
92 |
93 | hashicorp/consul/api (Mozilla Public License 2.0) https://github.com/hashicorp/consul/api
94 | https://github.com/hashicorp/consul/blob/master/LICENSE
95 |
96 | fxamacker/cbor (MIT) https://github.com/fxamacker/cbor/v2
97 | https://github.com/fxamacker/cbor/blob/master/LICENSE
98 |
99 | x448/float16 (MIT) https://github.com/x448/float16
100 | https://github.com/x448/float16/blob/master/LICENSE
101 |
102 | bertimus9/systemstat (MIT) https://bitbucket.org/bertimus9/systemstat/src/master/
103 | https://bitbucket.org/bertimus9/systemstat/src/master/LICENSE
104 |
105 | go-playground/locales (MIT) https://github.com/go-playground/locales
106 | https://github.com/go-playground/locales/blob/master/LICENSE
107 |
108 | go-playground/universal-translator (MIT) https://github.com/go-playground/universal-translator
109 | https://github.com/go-playground/universal-translator/blob/master/LICENSE
110 |
111 | go-playground/validator/v10 (MIT) https://github.com/go-playground/validator/v10
112 | https://github.com/go-playground/validator/blob/master/LICENSE
113 |
114 | leodido/go-urn (MIT) https://github.com/leodido/go-urn
115 | https://github.com/leodido/go-urn/blob/master/LICENSE
116 |
117 | stretchr/objx (MIT) https://github.com/stretchr/objx
118 | https://github.com/stretchr/objx/blob/master/LICENSE
119 |
120 | fatih/color (MIT) https://github.com/fatih/color
121 | https://github.com/fatih/color/bglob/master/LICENSE.md
122 |
123 | hashicorp/go-hclog (MIT) https://github.com/hashicorp/go-hclog
124 | https://github.com/hashicorp/go-hclog/blob/master/LICENSE
125 |
126 | mattn/go-colorable (MIT) https://github.com/mattn/go-colorable
127 | https://github.com/mattn/go-colorable/blob/master/LICENSE
128 |
129 | mattn/go-isatty (MIT) https://github.com/mattn/go-isatty
130 | https://github.com/mattn/go-isatty/blob/master/LICENSE
131 |
132 | golang.org/x/sys (BSD-3) https://github.com/golang/sys
133 | https://github.com/golang/sys/blob/master/LICENSE
134 |
135 | eclipse/paho.mqtt.golang (Eclipse Public License 2.0) https://github.com/eclipse/paho.mqtt.golang
136 | https://github.com/eclipse/paho.mqtt.golang/blob/master/LICENSE
137 |
138 | go-redis/redis (BSD-2) https://github.com/go-redis/redis/v7
139 | https://github.com/go-redis/redis/blob/master/LICENSE
140 |
141 | gorilla/websocket (BSD-2) https://github.com/gorilla/websocket
142 | https://github.com/gorilla/websocket/blob/master/LICENSE
143 |
144 | golang.org/x/net (Unspecified) https://github.com/golang/net
145 | https://github.com/golang/net/blob/master/LICENSE
146 |
147 | golang.org/x/crypto (Unspecified) https://github.com/golang/crypto
148 | https://github.com/golang/crypto/blob/master/LICENSE
149 |
150 | golang.org/x/text (Unspecified) https://github.com/golang/text
151 | https://github.com/golang/text/blob/master/LICENSE
152 |
153 | hashicorp/errwrap (Mozilla Public License 2.0) https://github.com/hashicorp/errwrap
154 | https://github.com/hashicorp/errwrap/blob/master/LICENSE
155 |
156 | hashicorp/go-multierror (Mozilla Public License 2.0) https://github.com/hashicorp/go-multierror
157 | https://github.com/hashicorp/go-multierror/blob/master/LICENSE
158 |
159 | go-kit/log (MIT) https://github.com/go-kit/log
160 | https://github.com/go-kit/log/blob/main/LICENSE
161 |
162 | github.com/golang/protobuf (BSD-3) https://github.com/golang/protobuf
163 | https://github.com/golang/protobuf/blob/master/LICENSE
164 |
165 | github.com/spiffe/go-spiffe/v2 (Apache-2.0 License) github.com/spiffe/go-spiffe/v2
166 | https://github.com/spiffe/go-spiffe/blob/main/LICENSE
167 |
168 | github.com/zeebo/errs (MIT) https://github.com/zeebo/errs
169 | https://github.com/zeebo/errs/blob/master/LICENSE
170 |
171 | google.golang.org/genproto (Apache-2.0) https://github.com/googleapis/go-genproto
172 | https://github.com/googleapis/go-genproto/blob/main/LICENSE
173 |
174 | google.golang.org/grpc (Apache-2.0) https://github.com/grpc/grpc-go
175 | https://github.com/grpc/grpc-go/blob/master/LICENSE
176 |
177 | google.golang.org/protobuf (Unspecified) https://github.com/protocolbuffers/protobuf-go
178 | https://github.com/protocolbuffers/protobuf-go/blob/master/LICENSE
179 |
180 | gopkg.in/square/go-jose.v2 (Apache-2.0) https://github.com/square/go-jose/tree/v2.6.0
181 | https://github.com/square/go-jose/blob/v2.6.0/LICENSE
182 |
183 | github.com/rcrowley/go-metrics (Unspecified) https://github.com/rcrowley/go-metrics
184 | https://github.com/rcrowley/go-metrics/blob/master/LICENSE
185 |
186 | golang.org/x/sync (Unspecified) https://cs.opensource.google/go/x/sync
187 | https://cs.opensource.google/go/x/sync/+/master:LICENSE
188 |
189 | github.com/Microsoft/go-winio (MIT) https://github.com/Microsoft/go-winio
190 | https://github.com/microsoft/go-winio/blob/master/LICENSE
191 |
192 | github.com/nats-io/nats.go (Apache-2.0) https://github.com/nats-io/nats.go
193 | https://github.com/nats-io/nats.go/blob/main/LICENSE
194 |
195 | github.com/nats-io/nkeys (Apache-2.0) https://github.com/nats-io/nkeys
196 | https://github.com/nats-io/nkeys/blob/master/LICENSE
197 |
198 | github.com/nats-io/nuid (Apache-2.0) https://github.com/nats-io/nuid
199 | https://github.com/nats-io/nuid/blob/master/LICENSE
200 |
201 | golang.org/x/mod (BSD-3) https://github.com/golang/mod
202 | https://github.com/golang/mod/blob/master/LICENSE
203 |
204 | golang.org/x/tools (BSD-3) https://github.com/golang/tools
205 | https://github.com/golang/tools/blob/master/LICENSE
206 |
207 | github.com/go-jose/go-jose/v3 (Apache-2.0) https://github.com/go-jose/go-jose
208 | https://github.com/go-jose/go-jose/blob/v3/LICENSE
209 |
210 | github.com/robinson/gos7 (Apache 2.0) https://github.com/robinson/gos7
211 | https://github.com/robinson/gos7/blob/master/LICENSE
212 |
213 | github.com/microsoft/go-winio (Apache 2.0) https://github.com/microsoft/go-winio
214 | https://github.com/microsoft/go-winio/blob/main/LICENSE
215 |
216 | github.com/OneOfOne/xxhash (Apache 2.0) https://github.com/OneOfOne/xxhash
217 | https://github.com/OneOfOne/xxhash/blob/master/LICENSE
218 |
219 | github.com/hashicorp/go-metrics (Apache 2.0) https://github.com/hashicorp/go-metrics
220 | https://github.com/hashicorp/go-metrics/blob/master/LICENSE
221 |
222 | cenkalti/backoff (MIT) https://github.com/cenkalti/backoff
223 | https://github.com/cenkalti/backoff/blob/master/LICENSE
224 |
225 | github.com/spf13/cast (MIT) https://github.com/spf13/cast
226 | https://github.com/spf13/cast/blob/master/LICENSE
227 |
228 | github.com/gabriel-vasile/mimetype (MIT) https://github.com/gabriel-vasile/mimetype
229 | https://github.com/gabriel-vasile/mimetype/blob/master/LICENSE
230 |
231 | github.com/golang-jwt/jwt (MIT) https://github.com/golang-jwt/jwt
232 | https://github.com/golang-jwt/jwt/blob/main/LICENSE
233 |
234 | github.com/klauspost/compress (Apache-2.0) https://github.com/klauspost/compress
235 | https://github.com/klauspost/compress/blob/master/LICENSE
236 |
237 | github.com/labstack/echo/v4 (MIT) https://github.com/labstack/echo
238 | https://github.com/labstack/echo/blob/master/LICENSE
239 |
240 | github.com/labstack/gommon (MIT) https://github.com/labstack/gommon
241 | https://github.com/labstack/gommon/blob/master/LICENSE
242 |
243 | github.com/valyala/bytebufferpool (MIT) https://github.com/valyala/bytebufferpool
244 | https://github.com/valyala/bytebufferpool/blob/master/LICENSE
245 |
246 | github.com/valyala/fasttemplate (MIT) https://github.com/valyala/fasttemplate
247 | https://github.com/valyala/fasttemplate/blob/master/LICENSE
248 |
249 | golang.org/x/exp (BSD-3) https://cs.opensource.google/go/x/exp
250 | https://cs.opensource.google/go/x/exp/+/master:LICENSE
251 |
252 | golang.org/x/time (BSD-3) https://cs.opensource.google/go/x/time
253 | https://cs.opensource.google/go/x/time/+/master:LICENSE
254 |
255 | github.com/go-jose/go-jose/v4 (Apache-2.0) https://github.com/go-jose/go-jose
256 | https://github.com/go-jose/go-jose/blob/main/LICENSE
257 |
258 | google.golang.org/genproto/googleapis/rpc (Apache-2.0) https://github.com/googleapis/go-genproto
259 | https://github.com/googleapis/go-genproto/blob/main/LICENSE
260 |
261 | github.com/asaskevich/govalidator (MIT) https://github.com/asaskevich/govalidator
262 | https://github.com/asaskevich/govalidator/blob/master/LICENSE
263 |
264 | github.com/cenkalti/backoff/v4 (MIT) https://github.com/cenkalti/backoff
265 | https://github.com/cenkalti/backoff/blob/v4/LICENSE
266 |
267 | github.com/fsnotify/fsnotify (BSD-3) https://github.com/fsnotify/fsnotify
268 | https://github.com/fsnotify/fsnotify/blob/main/LICENSE
269 |
270 | github.com/fullsailor/pkcs7 (MIT) https://github.com/fullsailor/pkcs7
271 | https://github.com/fullsailor/pkcs7/blob/master/LICENSE
272 |
273 | github.com/go-logr/logr (Apache-2.0) https://github.com/go-logr/logr
274 | https://github.com/go-logr/logr/blob/master/LICENSE
275 |
276 | github.com/go-logr/stdr (Apache-2.0) https://github.com/go-log/stdr
277 | https://github.com/go-logr/stdr/blob/master/LICENSE
278 |
279 | github.com/go-ole/go-ole (MIT) https://github.com/go-ole/go-ole
280 | https://github.com/go-ole/go-ole/blob/master/LICENSE
281 |
282 | github.com/go-openapi/analysis (Apache-2.0) https://github.com/go-openapi/analysis
283 | https://github.com/go-openapi/analysis/blob/master/LICENSE
284 |
285 | github.com/go-openapi/errors (Apache-2.0) https://github.com/go-openapi/errors
286 | https://github.com/go-openapi/errors/blob/master/LICENSE
287 |
288 | github.com/go-openapi/jsonpointer (Apache-2.0) https://github.com/go-openapi/jsonpointer
289 | https://github.com/go-openapi/jsonpointer/blob/master/LICENSE
290 |
291 | github.com/go-openapi/jsonreference (Apache-2.0) https://github.com/go-openapi/jsonreference
292 | https://github.com/go-openapi/jsonreference/blob/master/LICENSE
293 |
294 | github.com/go-openapi/loads (Apache-2.0) https://github.com/go-openapi/loads
295 | https://github.com/go-openapi/loads/blob/master/LICENSE
296 |
297 | github.com/go-openapi/runtime (Apache-2.0) https://github.com/go-openapi/runtime
298 | https://github.com/go-openapi/runtime/blob/master/LICENSE
299 |
300 | github.com/go-openapi/spec (Apache-2.0) https://github.com/go-openapi/spec
301 | https://github.com/go-openapi/spec/blob/master/LICENSE
302 |
303 | github.com/go-openapi/strfmt (Apache-2.0) https://github.com/go-openapi/strfmt
304 | https://github.com/go-openapi/strfmt/blob/master/LICENSE
305 |
306 | github.com/go-openapi/swag (Apache-2.0) https://github.com/go-openapi/swag
307 | https://github.com/go-openapi/swag/blob/master/LICENSE
308 |
309 | github.com/go-openapi/validate (Apache-2.0) https://github.com/go-openapi/validate
310 | https://github.com/go-openapi/validate/blob/master/LICENSE
311 |
312 | github.com/go-resty/resty/v2 (MIT) https://github.com/go-resty/resty
313 | https://github.com/go-resty/resty/blob/v2/LICENSE
314 |
315 | github.com/golang-jwt/jwt/v5 (MIT) github.com/golang-jwt/jwt
316 | https://github.com/golang-jwt/jwt/blob/main/LICENSE
317 |
318 | github.com/gorilla/schema (BSD-3) https://github.com/gorilla/schema
319 | https://github.com/gorilla/schema/blob/main/LICENSE
320 |
321 | github.com/gorilla/securecookie (BSD-3) https://github.com/gorilla/securecookie
322 | https://github.com/gorilla/securecookie/blob/main/LICENSE
323 |
324 | github.com/josharian/intern (MIT) https://github.com/josharian/intern
325 | https://github.com/josharian/intern/blob/master/LICENSE.md
326 |
327 | github.com/kataras/go-events (MIT) https://github.com/kataras/go-events
328 | https://github.com/kataras/go-events/blob/master/LICENSE
329 |
330 | github.com/lufia/plan9stats (BSD-3) https://github.com/lufia/plan9stats
331 | https://github.com/lufia/plan9stats/blob/main/LICENSE
332 |
333 | github.com/mailru/easyjson (MIT) https://github.com/mailru/easyjson
334 | https://github.com/mailru/easyjson/blob/master/LICENSE
335 |
336 | github.com/mgutz/ansi (MIT) https://github.com/mgutz/ansi
337 | https://github.com/mgutz/ansi/blob/master/LICENSE
338 |
339 | github.com/michaelquigley/pfxlog (MIT) https://github.com/michaelquigley/pfxlog
340 | https://github.com/michaelquigley/pfxlog/blob/main/LICENSE
341 |
342 | github.com/miekg/pkcs11 (BSD-3) https://github.com/miekg/pkcs11
343 | https://github.com/miekg/pkcs11/blob/master/LICENSE
344 |
345 | github.com/mitchellh/go-ps (MIT) https://github.com/mitchellh/go-ps
346 | https://github.com/mitchellh/go-ps/blob/master/LICENSE.md
347 |
348 | github.com/muhlemmer/gu (Unspecified) https://github.com/muhlemmer/gu
349 | https://github.com/muhlemmer/gu/blob/main/LICENSE
350 |
351 | github.com/oklog/ulid (Apache-2.0) https://github.com/oklog/ulid
352 | https://github.com/oklog/ulid/blob/main/LICENSE
353 |
354 | github.com/opentracing/opentracing-go (Apache-2.0) https://github.com/opentracing/opentracing-go
355 | https://github.com/opentracing/opentracing-go/blob/master/LICENSE
356 |
357 | github.com/openziti/channel/v3 (Apache 2.0) - github.com/openziti/channel/v3
358 | https://github.com/openziti/channel/blob/main/LICENSE
359 |
360 | github.com/openziti/edge-api (Apache-2.0) https://github.com/openziti/edge-api
361 | https://github.com/openziti/edge-api/blob/main/LICENSE
362 |
363 | github.com/openziti/foundation/v2 (Apache-2.0) https://github.com/openziti/foundation
364 | https://github.com/openziti/foundation/blob/main/LICENSE
365 |
366 | github.com/openziti/identity (Apache-2.0) https://github.com/openziti/identity
367 | https://github.com/openziti/identity/blob/main/LICENSE
368 |
369 | github.com/openziti/metrics (Apache-2.0) https://github.com/openziti/metrics
370 | https://github.com/openziti/metrics/blob/main/LICENSE
371 |
372 | github.com/openziti/sdk-golang (Apache-2.0) https://github.com/openziti/sdk-golang
373 | https://github.com/openziti/sdk-golang/blob/main/LICENSE
374 |
375 | github.com/openziti/secretstream (MIT) https://github.com/openziti/secretstream
376 | https://github.com/openziti/secretstream/blob/main/LICENSE
377 |
378 | github.com/openziti/transport/v2 (Apache-2.0) https://github.com/openziti/transport
379 | https://github.com/openziti/transport/blob/main/LICENSE
380 |
381 | github.com/orcaman/concurrent-map/v2 (MIT) https://github.com/orcaman/concurrent-map/
382 | https://github.com/orcaman/concurrent-map/blob/master/LICENSE
383 |
384 | github.com/panjf2000/ants/v2 (MIT) https://github.com/panjf2000/ants
385 | https://github.com/panjf2000/ants/blob/dev/LICENSE
386 |
387 | github.com/parallaxsecond/parsec-client-go (Apache-2.0) https://github.com/parallaxsecond/parsec-client-go
388 | https://github.com/parallaxsecond/parsec-client-go/blob/main/LICENSE
389 |
390 | github.com/pkg/errors (BSD-2) https://github.com/pkg/errors
391 | https://github.com/pkg/errors/blob/master/LICENSE
392 |
393 | github.com/power-devops/perfstat (MIT) https://github.com/power-devops/perfstat
394 | https://github.com/power-devops/perfstat/blob/main/LICENSE
395 |
396 | github.com/shirou/gopsutil/v3 (BSD) https://github.com/shirou/gopsutil
397 | https://github.com/shirou/gopsutil/blob/master/LICENSE
398 |
399 | github.com/shoenig/go-m1cpu (Mozilla Public License 2.0) https://github.com/shoenig/go-m1cpu
400 | https://github.com/shoenig/go-m1cpu/blob/main/LICENSE
401 |
402 | github.com/sirupsen/logrus (MIT) https://github.com/sirupsen/logrus
403 | https://github.com/sirupsen/logrus/blob/master/LICENSE
404 |
405 | github.com/speps/go-hashids (MIT) https://github.com/speps/go-hashids
406 | https://github.com/speps/go-hashids/blob/master/LICENSE
407 |
408 | github.com/tklauser/go-sysconf (BSD-3) https://github.com/tklauser/go-sysconf
409 | https://github.com/tklauser/go-sysconf/blob/main/LICENSE
410 |
411 | github.com/tklauser/numcpus (Apache-2.0) https://github.com/tklauser/numcpus
412 | https://github.com/tklauser/numcpus/blob/main/LICENSE
413 |
414 | github.com/yusufpapurcu/wmi (MIT) https://github.com/yusufpapurcu/wmi/
415 | https://github.com/yusufpapurcu/wmi/blob/master/LICENSE
416 |
417 | github.com/zitadel/oidc/v2 (Apache-2.0) https://github.com/zitadel/oidc
418 | https://github.com/zitadel/oidc/blob/main/LICENSE
419 |
420 | go.mongodb.org/mongo-driver (Apache-2.0) https://github.com/mongodb/mongo-go-driver
421 | https://github.com/mongodb/mongo-go-driver/blob/v1/LICENSE
422 |
423 | go.mozilla.org/pkcs7 (MIT) https://github.com/mozilla-services/pkcs7
424 | https://github.com/mozilla-services/pkcs7/blob/master/LICENSE
425 |
426 | go.opentelemetry.io/otel (Apache-2.0) https://github.com/open-telemetry/opentelemetry-go
427 | https://github.com/open-telemetry/opentelemetry-go/blob/main/LICENSE
428 |
429 | go.opentelemetry.io/otel/metric (Apache-2.0) https://github.com/open-telemetry/opentelemetry-go
430 | https://github.com/open-telemetry/opentelemetry-go/blob/main/LICENSE
431 |
432 | go.opentelemetry.io/otel/trace (Apache-2.0) https://github.com/open-telemetry/opentelemetry-go
433 | https://github.com/open-telemetry/opentelemetry-go/blob/main/LICENSE
434 |
435 | golang.org/x/oauth2 (Unspecified) https://cs.opensource.google/go/x/oauth2
436 | https://cs.opensource.google/go/x/oauth2/+/master:LICENSE
437 |
438 | golang.org/x/term (Unspecified) https://cs.opensource.google/go/x/term
439 | https://cs.opensource.google/go/x/term/+/master:LICENSE
440 |
441 | gopkg.in/go-jose/go-jose.v2 (Apache 2.0) - https://github.com/go-jose/go-jose
442 | https://github.com/go-jose/go-jose/blob/v2.6.3/LICENSE
443 |
444 | nhooyr.io/websocket (ISC) https://github.com/nhooyr/websocket
445 | https://github.com/nhooyr/websocket/blob/master/LICENSE.txt
446 |
--------------------------------------------------------------------------------
/CHANGLOG.md:
--------------------------------------------------------------------------------
1 |
2 | ## EdgeX S7 Device Service
3 | [Github repository](https://github.com/edgexfoundry/device-s7)
4 |
5 | ### Change Logs for EdgeX Dependencies
6 | - [go-mod-bootstrap](https://github.com/edgexfoundry/go-mod-bootstrap/blob/main/CHANGELOG.md)
7 | - [go-mod-core-contracts](https://github.com/edgexfoundry/go-mod-core-contracts/blob/main/CHANGELOG.md)
8 | - [go-mod-messaging](https://github.com/edgexfoundry/go-mod-messaging/blob/main/CHANGELOG.md)
9 | - [go-mod-registry](https://github.com/edgexfoundry/go-mod-registry/blob/main/CHANGELOG.md)
10 | - [go-mod-secrets](https://github.com/edgexfoundry/go-mod-secrets/blob/main/CHANGELOG.md) (indirect dependency)
11 | - [go-mod-configuration](https://github.com/edgexfoundry/go-mod-configuration/blob/main/CHANGELOG.md) (indirect dependency)
12 |
13 | ## [4.0.0] Odessa - 2025-03-12 (Only compatible with the 4.x releases)
14 | ### ✨ Features
15 |
16 | - Upgrade go modules to the latest V4 versions ([e01f1b2…](https://github.com/edgexfoundry/device-s7/commit/e01f1b23293b09a895d4cc1df7e2ed2c811e9ccd))
17 | - Optimize invalid address handling and update code to use the s7_errors variable ([f5a0aa0…](https://github.com/edgexfoundry/device-s7/commit/f5a0aa0cc3f0f12ba5a7b7b72ccceb6f71accabe))
18 |
19 | ### ♻ Code Refactoring
20 |
21 | - Update module to v4 ([bec349e…](https://github.com/edgexfoundry/device-s7/commit/bec349e2f9af90d5dee38f24426ea0dece7bc46d))
22 | ```text
23 |
24 | BREAKING CHANGE: update go module to v4
25 |
26 | ```
27 |
28 | ### 👷 Build
29 |
30 | - Upgrade to go-1.23, Linter1.61.0 and Alpine 3.20 ([f7f97db…](https://github.com/edgexfoundry/device-s7/commit/f7f97db7578a3a57d460f2ed62b0c2f6f5792442))
31 |
32 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (C) 2023 YIQISOFT
3 | # Copyright (c) 2024 IOTech Ltd
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 | #
17 |
18 | ARG BASE=golang:1.23-alpine3.20
19 | FROM ${BASE} AS builder
20 |
21 | ARG MAKE=make build
22 |
23 | WORKDIR /device-s7
24 |
25 | LABEL license='SPDX-License-Identifier: Apache-2.0' \
26 | copyright='Copyright (c) 2023: YIQISOFT'
27 |
28 | RUN apk add --update --no-cache make git gcc libc-dev
29 |
30 | COPY go.mod vendor* ./
31 | RUN [ ! -d "vendor" ] && go mod download all || echo "skipping..."
32 |
33 | COPY . .
34 | RUN ${MAKE}
35 |
36 | # Next image - Copy built Go binary into new workspace
37 | FROM alpine:3.20
38 | LABEL license='SPDX-License-Identifier: Apache-2.0' \
39 | copyright='Copyright (c) 2023: YIQISOFT'
40 |
41 | RUN apk add --update --no-cache dumb-init
42 | # Ensure using latest versions of all installed packages to avoid any recent CVEs
43 | RUN apk --no-cache upgrade
44 |
45 | WORKDIR /
46 | COPY --from=builder /device-s7/Attribution.txt /Attribution.txt
47 | COPY --from=builder /device-s7/cmd/device-s7 /device-s7
48 | COPY --from=builder /device-s7/cmd/res /res
49 |
50 | EXPOSE 59994
51 |
52 | ENTRYPOINT ["/device-s7"]
53 | CMD ["-cp=keeper.http://edgex-core-keeper:59890", "--registry"]
54 |
--------------------------------------------------------------------------------
/Jenkinsfile:
--------------------------------------------------------------------------------
1 | //
2 | // Copyright (c) 2023 YIQISOFT
3 | //
4 | // Licensed under the Apache License, Version 2.0 (the "License");
5 | // you may not use this file except in compliance with the License.
6 | // You may obtain a copy of the License at
7 | //
8 | // http://www.apache.org/licenses/LICENSE-2.0
9 | //
10 | // Unless required by applicable law or agreed to in writing, software
11 | // distributed under the License is distributed on an "AS IS" BASIS,
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // See the License for the specific language governing permissions and
14 | // limitations under the License.
15 | //
16 |
17 | edgeXBuildGoApp (
18 | project: 'device-s7',
19 | )
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | .PHONY: build test clean docker unittest lint
2 |
3 | ARCH=$(shell uname -m)
4 |
5 | MICROSERVICES=cmd/device-s7
6 | .PHONY: $(MICROSERVICES)
7 |
8 | VERSION=$(shell cat ./VERSION 2>/dev/null || echo 0.0.0)
9 | SDKVERSION=$(shell cat ./go.mod | grep 'github.com/edgexfoundry/device-sdk-go/v4 v' | sed 's/require//g' | awk '{print $$2}')
10 |
11 | DOCKER_TAG=$(VERSION)-dev
12 |
13 | GOFLAGS=-ldflags "-X github.com/edgexfoundry/device-s7.Version=$(VERSION) \
14 | -X github.com/edgexfoundry/device-sdk-go/v4/internal/common.SDKVersion=$(SDKVERSION)" \
15 | -trimpath -mod=readonly
16 | GOTESTFLAGS?=-race
17 |
18 | GIT_SHA=$(shell git rev-parse HEAD)
19 |
20 | build: $(MICROSERVICES)
21 |
22 | build-nats:
23 | make -e ADD_BUILD_TAGS=include_nats_messaging build
24 |
25 | tidy:
26 | go mod tidy
27 |
28 | # CGO is enabled by default and cause docker builds to fail due to no gcc,
29 | # but is required for test with -race, so must disable it for the builds only
30 | cmd/device-s7:
31 | CGO_ENABLED=1 go build $(GOFLAGS) -o $@ ./cmd
32 |
33 | docker:
34 | docker build \
35 | -f Dockerfile \
36 | --label "git_sha=$(GIT_SHA)" \
37 | -t edgexfoundry/device-s7:$(GIT_SHA) \
38 | -t edgexfoundry/device-s7:$(DOCKER_TAG) \
39 | .
40 |
41 | unittest:
42 | go test $(GOTESTFLAGS) -coverprofile=coverage.out ./...
43 |
44 | lint:
45 | @which golangci-lint >/dev/null || echo "WARNING: go linter not installed. To install, run make install-lint"
46 | @if [ "z${ARCH}" = "zx86_64" ] && which golangci-lint >/dev/null ; then golangci-lint run --config .golangci.yml ; else echo "WARNING: Linting skipped (not on x86_64 or linter not installed)"; fi
47 |
48 | install-lint:
49 | sudo curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $$(go env GOPATH)/bin v1.61.0
50 |
51 | test: unittest lint
52 | go vet ./...
53 | gofmt -l $$(find . -type f -name '*.go'| grep -v "/vendor/")
54 | [ "`gofmt -l $$(find . -type f -name '*.go'| grep -v "/vendor/")`" = "" ]
55 | ./bin/test-attribution-txt.sh
56 |
57 | clean:
58 | rm -f $(MICROSERVICES)
59 |
60 | vendor:
61 | go mod vendor
62 |
--------------------------------------------------------------------------------
/OWNERS.md:
--------------------------------------------------------------------------------
1 | # Repository Owners
2 |
3 | This repository is managed by the EdgeX Device Services Working Group. As such, the **Device Services Working Group** chairman is considered the "owner" of the repository and approves all committers of the repository.
4 |
5 | See the [project Wiki TSC page]() for information on the current EdgeX TSC and who occupies the role of Device Service Working Group chair.
6 |
7 | For a complete list of current committers see: https://github.com/orgs/edgexfoundry/teams/device-s7-committers/members.
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Device Service for Siemens S7 PLC
2 |
3 | > **Warning**
4 | > The **main** branch of this repository contains work-in-progress development code for the upcoming release, and is **not guaranteed to be stable or working**.
5 | > It is only compatible with the [main branch of edgex-compose](https://github.com/edgexfoundry/edgex-compose) which uses the Docker images built from the **main** branch of this repo and other repos.
6 | >
7 | > **The source for the latest release can be found at [Releases](https://github.com/edgexfoundry/device-s7/releases).**
8 |
9 | ## Documentation
10 |
11 | For latest documentation please visit https://docs.edgexfoundry.org/latest/microservices/device/services/device-s7/Purpose
12 |
13 | ## Overview
14 |
15 | S7 Micro Service - device service for connecting Siemens S7(S7-200, S7-300, S7-400, S7-1200, S7-1500) devices by `ISO-on-TCP` to EdgeX.
16 |
17 | - This device service is contributed by [YIQISOFT](https://yiqisoft.cn)
18 | - The sevice has tested on S7-300, S7-400, S7-1200
19 |
20 | ## Features
21 |
22 | - Single Read and Write
23 | - Multiple Read and Write
24 | - High performance, more 2000 items per second(depends on S7 model)
25 | - Use `S7-Device01` sample device configuration, `interval` should be less than `IdelTimeout`
26 | - S7-1200 and S7-1500 preferred
27 | - Create multiple connections to one S7 device use different device name
28 |
29 | ## Prerequisites
30 |
31 | - A Siemens S7 series device with network interface
32 | - Enable ISO-on-TCP connection on the S7 device
33 |
34 | ## Build Instructions
35 |
36 | 1. Clone the device-rest-go repo with the following command:
37 |
38 | git clone https://github.com/edgexfoundry/device-s7.git
39 |
40 | 2. Build a docker image by using the following command:
41 |
42 | make docker
43 |
44 | 3. Alternatively the device service can be built natively:
45 |
46 | make build
47 |
48 | ## Build with NATS Messaging
49 |
50 | Currently, the NATS Messaging capability (NATS MessageBus) is opt-in at build time.
51 | This means that the published Docker images do not include the NATS messaging capability.
52 |
53 | The following make commands will build the local binary or local Docker image with NATS messaging capability included.
54 |
55 | ```shell
56 | make build-nats
57 | make docker-nats
58 | ```
59 |
60 | ## Packaging
61 |
62 | This component is packaged as docker images.
63 |
64 | Please refer to the [Dockerfile](./Dockerfile) and [Docker Compose Builder](https://github.com/edgexfoundry/edgex-compose/tree/main/compose-builder) scripts.
65 |
66 | ## Reference
67 |
68 | - [Gos7](https://github.com/robinson/gos7)
69 |
70 | ## License
71 |
72 | Apache-2.0
73 |
--------------------------------------------------------------------------------
/bin/test-attribution-txt.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash -e
2 |
3 | # get the directory of this script
4 | # snippet from https://stackoverflow.com/a/246128/10102404
5 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
6 | GIT_ROOT=$(dirname "$SCRIPT_DIR")
7 |
8 | EXIT_CODE=0
9 |
10 | cd "$GIT_ROOT"
11 |
12 | if [ ! -f Attribution.txt ]; then
13 | echo "An Attribution.txt file is missing, please add"
14 | EXIT_CODE=1
15 | else
16 | # loop over every library in the go.mod file
17 | while IFS= read -r lib; do
18 | if ! grep -q "$lib" Attribution.txt; then
19 | echo "An attribution for $lib is missing from Attribution.txt, please add"
20 | # need to do this in a bash subshell, see SC2031
21 | (( EXIT_CODE=1 ))
22 | fi
23 | done < <(cat $GIT_ROOT/go.mod | grep -v 'module ' | grep -v TODO | grep '/' | sed 's/require //' | sed 's/replace //' | awk '{print $1}')
24 | fi
--------------------------------------------------------------------------------
/cmd/main.go:
--------------------------------------------------------------------------------
1 | // -*- Mode: Go; indent-tabs-mode: t -*-
2 | //
3 | // Copyright (C) 2023 YIQISOFT
4 | //
5 | // SPDX-License-Identifier: Apache-2.0
6 |
7 | // This package provides a simple example of a S7 device service.
8 | package main
9 |
10 | import (
11 | device_s7 "github.com/edgexfoundry/device-s7"
12 |
13 | "github.com/edgexfoundry/device-s7/internal/driver"
14 | "github.com/edgexfoundry/device-sdk-go/v4/pkg/startup"
15 | )
16 |
17 | const (
18 | serviceName string = "device-s7"
19 | )
20 |
21 | func main() {
22 | sd := driver.NewProtocolDriver()
23 | startup.Bootstrap(serviceName, device_s7.Version, sd)
24 | }
25 |
--------------------------------------------------------------------------------
/cmd/res/configuration.yaml:
--------------------------------------------------------------------------------
1 | Writable:
2 | LogLevel: "INFO"
3 |
4 | Service:
5 | Host: "localhost"
6 | Port: 59994 # 59994 for testing
7 | StartupMsg: "S7 device service started"
8 |
9 | MessageBus:
10 | Optional:
11 | ClientId: "device-s7"
12 |
13 | Device:
14 | # By default, this service doesn't have any profiles or devices.
15 | # The following settings can be overridden with env overrides to apply customized values.
16 | ProfilesDir: ""
17 | DevicesDir: ""
18 |
--------------------------------------------------------------------------------
/cmd/res/devices/Simple-Device.yaml:
--------------------------------------------------------------------------------
1 | deviceList:
2 | - name: S7-Device01
3 | profileName: S7-Device
4 | description: Example of S7 Device
5 | labels: [industrial]
6 | protocols:
7 | s7:
8 | Host: 192.168.123.199
9 | Port: 102
10 | Rack: 0
11 | Slot: 1
12 | Timeout: 30
13 | IdleTimeout: 30
14 | autoEvents:
15 | - interval: 10s
16 | onChange: false
17 | sourceName: AllResource
18 | - name: S7-Device02
19 | profileName: S7-Device
20 | description: Example of S7 Device
21 | labels: [industrial]
22 | protocols:
23 | s7:
24 | Host: 192.168.123.199
25 | Port: 102
26 | Rack: 0
27 | Slot: 1
28 | Timeout: 5
29 | IdleTimeout: 5
30 | autoEvents:
31 | - interval: 10s
32 | onChange: false
33 | sourceName: heartbeat
34 |
--------------------------------------------------------------------------------
/cmd/res/profiles/Simple-Driver.yaml:
--------------------------------------------------------------------------------
1 | name: S7-Device
2 | manufacturer: YIQISOFT
3 | description: Example of S7 Device
4 | model: Siemens S7
5 | labels: [ISO-on-TCP]
6 | deviceResources:
7 | - name: bool
8 | description: PLC bool
9 | isHidden: false
10 | properties:
11 | valueType: Bool
12 | readWrite: RW
13 | attributes:
14 | NodeName: DB4.DBX0.0
15 | - name: byte
16 | description: PLC byte
17 | isHidden: false
18 | properties:
19 | valueType: Uint8
20 | readWrite: RW
21 | attributes:
22 | NodeName: DB4.DBB1
23 | - name: word
24 | description: PLC word
25 | isHidden: false
26 | properties:
27 | valueType: Int16
28 | readWrite: RW
29 | attributes:
30 | NodeName: DB4.DBW2
31 | - name: dword
32 | description: PLC dword
33 | isHidden: false
34 | properties:
35 | valueType: Int32
36 | readWrite: RW
37 | attributes:
38 | NodeName: DB4.DBD4
39 | - name: int
40 | description: PLC int
41 | isHidden: false
42 | properties:
43 | valueType: Int16
44 | readWrite: RW
45 | attributes:
46 | NodeName: DB4.DBW8
47 | - name: dint
48 | description: PLC dint
49 | isHidden: false
50 | properties:
51 | valueType: Int32
52 | readWrite: RW
53 | attributes:
54 | NodeName: DB4.DBW10
55 | - name: real
56 | description: PLC real
57 | isHidden: false
58 | properties:
59 | valueType: Float32
60 | readWrite: RW
61 | attributes:
62 | NodeName: DB4.DBD14
63 | - name: heartbeat
64 | description: PLC heartbeat
65 | isHidden: false
66 | properties:
67 | valueType: Int16
68 | readWrite: RW
69 | attributes:
70 | NodeName: DB1.DBW160
71 | deviceCommands:
72 | - name: AllResource
73 | isHidden: false
74 | readWrite: RW
75 | resourceOperations:
76 | - deviceResource: bool
77 | defaultValue: 'false'
78 | - deviceResource: byte
79 | defaultValue: '0'
80 | - deviceResource: word
81 | defaultValue: '0'
82 | - deviceResource: dword
83 | defaultValue: '0'
84 | - deviceResource: int
85 | defaultValue: '0'
86 | - deviceResource: dint
87 | defaultValue: '0'
88 | - deviceResource: real
89 | defaultValue: '0'
90 | - deviceResource: heartbeat
91 | defaultValue: '0'
92 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/edgexfoundry/device-s7
2 |
3 | go 1.23
4 |
5 | require (
6 | github.com/edgexfoundry/device-sdk-go/v4 v4.0.0
7 | github.com/edgexfoundry/go-mod-core-contracts/v4 v4.0.1
8 | github.com/robinson/gos7 v0.0.0-20231012111941-bdaa10e92e16
9 | github.com/spf13/cast v1.9.2
10 | )
11 |
12 | require (
13 | github.com/Microsoft/go-winio v0.6.2 // indirect
14 | github.com/OneOfOne/xxhash v1.2.8 // indirect
15 | github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
16 | github.com/cenkalti/backoff/v4 v4.3.0 // indirect
17 | github.com/eclipse/paho.mqtt.golang v1.5.0 // indirect
18 | github.com/edgexfoundry/go-mod-bootstrap/v4 v4.0.3 // indirect
19 | github.com/edgexfoundry/go-mod-configuration/v4 v4.0.1 // indirect
20 | github.com/edgexfoundry/go-mod-messaging/v4 v4.0.1 // indirect
21 | github.com/edgexfoundry/go-mod-registry/v4 v4.0.1 // indirect
22 | github.com/edgexfoundry/go-mod-secrets/v4 v4.0.1 // indirect
23 | github.com/fsnotify/fsnotify v1.7.0 // indirect
24 | github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa // indirect
25 | github.com/fxamacker/cbor/v2 v2.7.0 // indirect
26 | github.com/gabriel-vasile/mimetype v1.4.8 // indirect
27 | github.com/go-jose/go-jose/v4 v4.0.5 // indirect
28 | github.com/go-kit/log v0.2.1 // indirect
29 | github.com/go-logfmt/logfmt v0.5.1 // indirect
30 | github.com/go-logr/logr v1.4.2 // indirect
31 | github.com/go-logr/stdr v1.2.2 // indirect
32 | github.com/go-ole/go-ole v1.2.6 // indirect
33 | github.com/go-openapi/analysis v0.23.0 // indirect
34 | github.com/go-openapi/errors v0.22.0 // indirect
35 | github.com/go-openapi/jsonpointer v0.21.0 // indirect
36 | github.com/go-openapi/jsonreference v0.21.0 // indirect
37 | github.com/go-openapi/loads v0.22.0 // indirect
38 | github.com/go-openapi/runtime v0.28.0 // indirect
39 | github.com/go-openapi/spec v0.21.0 // indirect
40 | github.com/go-openapi/strfmt v0.23.0 // indirect
41 | github.com/go-openapi/swag v0.23.0 // indirect
42 | github.com/go-openapi/validate v0.24.0 // indirect
43 | github.com/go-playground/locales v0.14.1 // indirect
44 | github.com/go-playground/universal-translator v0.18.1 // indirect
45 | github.com/go-playground/validator/v10 v10.25.0 // indirect
46 | github.com/go-resty/resty/v2 v2.16.4 // indirect
47 | github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
48 | github.com/google/uuid v1.6.0 // indirect
49 | github.com/gorilla/mux v1.8.1 // indirect
50 | github.com/gorilla/schema v1.4.1 // indirect
51 | github.com/gorilla/securecookie v1.1.2 // indirect
52 | github.com/gorilla/websocket v1.5.3 // indirect
53 | github.com/hashicorp/errwrap v1.1.0 // indirect
54 | github.com/hashicorp/go-multierror v1.1.1 // indirect
55 | github.com/josharian/intern v1.0.0 // indirect
56 | github.com/kataras/go-events v0.0.3 // indirect
57 | github.com/klauspost/compress v1.17.9 // indirect
58 | github.com/labstack/echo/v4 v4.13.3 // indirect
59 | github.com/labstack/gommon v0.4.2 // indirect
60 | github.com/leodido/go-urn v1.4.0 // indirect
61 | github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
62 | github.com/mailru/easyjson v0.7.7 // indirect
63 | github.com/mattn/go-colorable v0.1.14 // indirect
64 | github.com/mattn/go-isatty v0.0.20 // indirect
65 | github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
66 | github.com/michaelquigley/pfxlog v0.6.10 // indirect
67 | github.com/miekg/pkcs11 v1.1.1 // indirect
68 | github.com/mitchellh/copystructure v1.2.0 // indirect
69 | github.com/mitchellh/go-ps v1.0.0 // indirect
70 | github.com/mitchellh/mapstructure v1.5.0 // indirect
71 | github.com/mitchellh/reflectwalk v1.0.2 // indirect
72 | github.com/muhlemmer/gu v0.3.1 // indirect
73 | github.com/nats-io/nats.go v1.39.1 // indirect
74 | github.com/nats-io/nkeys v0.4.9 // indirect
75 | github.com/nats-io/nuid v1.0.1 // indirect
76 | github.com/oklog/ulid v1.3.1 // indirect
77 | github.com/opentracing/opentracing-go v1.2.0 // indirect
78 | github.com/openziti/channel/v3 v3.0.27 // indirect
79 | github.com/openziti/edge-api v0.26.38 // indirect
80 | github.com/openziti/foundation/v2 v2.0.56 // indirect
81 | github.com/openziti/identity v1.0.94 // indirect
82 | github.com/openziti/metrics v1.2.65 // indirect
83 | github.com/openziti/sdk-golang v0.24.1 // indirect
84 | github.com/openziti/secretstream v0.1.28 // indirect
85 | github.com/openziti/transport/v2 v2.0.160 // indirect
86 | github.com/orcaman/concurrent-map/v2 v2.0.1 // indirect
87 | github.com/panjf2000/ants/v2 v2.11.2 // indirect
88 | github.com/parallaxsecond/parsec-client-go v0.0.0-20221025095442-f0a77d263cf9 // indirect
89 | github.com/pkg/errors v0.9.1 // indirect
90 | github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
91 | github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
92 | github.com/shirou/gopsutil/v3 v3.24.5 // indirect
93 | github.com/shoenig/go-m1cpu v0.1.6 // indirect
94 | github.com/sirupsen/logrus v1.9.3 // indirect
95 | github.com/speps/go-hashids v2.0.0+incompatible // indirect
96 | github.com/spiffe/go-spiffe/v2 v2.5.0 // indirect
97 | github.com/tklauser/go-sysconf v0.3.12 // indirect
98 | github.com/tklauser/numcpus v0.6.1 // indirect
99 | github.com/valyala/bytebufferpool v1.0.0 // indirect
100 | github.com/valyala/fasttemplate v1.2.2 // indirect
101 | github.com/x448/float16 v0.8.4 // indirect
102 | github.com/yusufpapurcu/wmi v1.2.4 // indirect
103 | github.com/zeebo/errs v1.4.0 // indirect
104 | github.com/zitadel/oidc/v2 v2.12.2 // indirect
105 | go.mongodb.org/mongo-driver v1.17.0 // indirect
106 | go.mozilla.org/pkcs7 v0.9.0 // indirect
107 | go.opentelemetry.io/otel v1.32.0 // indirect
108 | go.opentelemetry.io/otel/metric v1.32.0 // indirect
109 | go.opentelemetry.io/otel/trace v1.32.0 // indirect
110 | golang.org/x/crypto v0.33.0 // indirect
111 | golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect
112 | golang.org/x/net v0.35.0 // indirect
113 | golang.org/x/oauth2 v0.25.0 // indirect
114 | golang.org/x/sync v0.11.0 // indirect
115 | golang.org/x/sys v0.30.0 // indirect
116 | golang.org/x/term v0.29.0 // indirect
117 | golang.org/x/text v0.22.0 // indirect
118 | golang.org/x/time v0.8.0 // indirect
119 | google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a // indirect
120 | google.golang.org/grpc v1.70.0 // indirect
121 | google.golang.org/protobuf v1.36.3 // indirect
122 | gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect
123 | gopkg.in/yaml.v3 v3.0.1 // indirect
124 | nhooyr.io/websocket v1.8.17 // indirect
125 | )
126 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
2 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
3 | cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
4 | cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
5 | cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
6 | cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
7 | cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
8 | cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
9 | cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
10 | cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
11 | cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
12 | cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
13 | cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
14 | cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
15 | cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
16 | cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
17 | cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
18 | cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
19 | cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
20 | cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
21 | cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
22 | cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
23 | cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
24 | cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
25 | cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
26 | cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
27 | cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
28 | cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
29 | cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
30 | cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
31 | cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
32 | cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
33 | cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
34 | cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
35 | cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
36 | cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
37 | cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
38 | cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
39 | dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
40 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
41 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
42 | github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
43 | github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
44 | github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8=
45 | github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
46 | github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
47 | github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
48 | github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
49 | github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
50 | github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
51 | github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
52 | github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
53 | github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
54 | github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
55 | github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
56 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
57 | github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
58 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
59 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
60 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
61 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
62 | github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
63 | github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
64 | github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
65 | github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
66 | github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
67 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
68 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
69 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
70 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
71 | github.com/eclipse/paho.mqtt.golang v1.5.0 h1:EH+bUVJNgttidWFkLLVKaQPGmkTUfQQqjOsyvMGvD6o=
72 | github.com/eclipse/paho.mqtt.golang v1.5.0/go.mod h1:du/2qNQVqJf/Sqs4MEL77kR8QTqANF7XU7Fk0aOTAgk=
73 | github.com/edgexfoundry/device-sdk-go/v4 v4.0.0 h1:awm3y3ImO2ims17RSF7zroT90tldE4tibTP9HXZmCI0=
74 | github.com/edgexfoundry/device-sdk-go/v4 v4.0.0/go.mod h1:ZU4fg8ufl/FtZfrNNeku480hX52YXKXqB2TEAYLC1X8=
75 | github.com/edgexfoundry/go-mod-bootstrap/v4 v4.0.3 h1:hEZrqu1Q7psVD3U9uXThlhyH+7Si0kKwgy4S88Wr/wc=
76 | github.com/edgexfoundry/go-mod-bootstrap/v4 v4.0.3/go.mod h1:eSj+XlUqX7NmVmj4aTy9Tji0LcjKH1Cidnz9sm+TlpM=
77 | github.com/edgexfoundry/go-mod-configuration/v4 v4.0.1 h1:yU3YhRrxrTzF4ERhf0TUJQ0XhEPWGjQutnAWS2++QT4=
78 | github.com/edgexfoundry/go-mod-configuration/v4 v4.0.1/go.mod h1:exeeN1OQkpWvKCH+FWPHXuBiQIyvzwWIS6LXk8c79aM=
79 | github.com/edgexfoundry/go-mod-core-contracts/v4 v4.0.1 h1:gLgs/oTNdIb0qbyhPGFOhS7t+mNuLmlDvdgu9qVtVnw=
80 | github.com/edgexfoundry/go-mod-core-contracts/v4 v4.0.1/go.mod h1:AF1bbO7aA1ZdtZ7r/lQHV4OjiHtSzK5iDiW+PqWDCUc=
81 | github.com/edgexfoundry/go-mod-messaging/v4 v4.0.1 h1:q2FZ+O1CYs5W2crQaDZ0WYyIWFh9pNUumdbQ2SP0YWs=
82 | github.com/edgexfoundry/go-mod-messaging/v4 v4.0.1/go.mod h1:vlu2E7wnFxhYqmxP/XmryRaX1EdJu0fCMbxS/nb+1dE=
83 | github.com/edgexfoundry/go-mod-registry/v4 v4.0.1 h1:U5HcQ4dChjrC1ZQttzP4SmWZ11xjTUzzKa55Pk3t8Z4=
84 | github.com/edgexfoundry/go-mod-registry/v4 v4.0.1/go.mod h1:qKkvkSOdDDQZMeeDYI4nOhjsx719N1Dp26AhMMvMGuY=
85 | github.com/edgexfoundry/go-mod-secrets/v4 v4.0.1 h1:YUQIUvMzQSZLR/bR4qNLMw6woCZo3RZJWaGd2i/6TsA=
86 | github.com/edgexfoundry/go-mod-secrets/v4 v4.0.1/go.mod h1:kUXKpyOmb2/S5T7eyOleM7cVEil1boFogk2OkJO6WrA=
87 | github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
88 | github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
89 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
90 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
91 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
92 | github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
93 | github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
94 | github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
95 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
96 | github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
97 | github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
98 | github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
99 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
100 | github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
101 | github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
102 | github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
103 | github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa h1:RDBNVkRviHZtvDvId8XSGPu3rmpmSe+wKRcEWNgsfWU=
104 | github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA=
105 | github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
106 | github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
107 | github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
108 | github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
109 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
110 | github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
111 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
112 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
113 | github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
114 | github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
115 | github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU=
116 | github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
117 | github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA=
118 | github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
119 | github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
120 | github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
121 | github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
122 | github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
123 | github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
124 | github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
125 | github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
126 | github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU=
127 | github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo=
128 | github.com/go-openapi/errors v0.22.0 h1:c4xY/OLxUBSTiepAg3j/MHuAv5mJhnf53LLMWFB+u/w=
129 | github.com/go-openapi/errors v0.22.0/go.mod h1:J3DmZScxCDufmIMsdOuDHxJbdOGC0xtUynjIx092vXE=
130 | github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
131 | github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
132 | github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
133 | github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
134 | github.com/go-openapi/loads v0.22.0 h1:ECPGd4jX1U6NApCGG1We+uEozOAvXvJSF4nnwHZ8Aco=
135 | github.com/go-openapi/loads v0.22.0/go.mod h1:yLsaTCS92mnSAZX5WWoxszLj0u+Ojl+Zs5Stn1oF+rs=
136 | github.com/go-openapi/runtime v0.28.0 h1:gpPPmWSNGo214l6n8hzdXYhPuJcGtziTOgUpvsFWGIQ=
137 | github.com/go-openapi/runtime v0.28.0/go.mod h1:QN7OzcS+XuYmkQLw05akXk0jRH/eZ3kb18+1KwW9gyc=
138 | github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY=
139 | github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk=
140 | github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c=
141 | github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4=
142 | github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
143 | github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
144 | github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58=
145 | github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ=
146 | github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
147 | github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
148 | github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
149 | github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
150 | github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
151 | github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
152 | github.com/go-playground/validator/v10 v10.25.0 h1:5Dh7cjvzR7BRZadnsVOzPhWsrwUr0nmsZJxEAnFLNO8=
153 | github.com/go-playground/validator/v10 v10.25.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus=
154 | github.com/go-resty/resty/v2 v2.16.4 h1:81IjtszQKwbz7dot4LLYGwhJNUsNwECD2O7nru5q60E=
155 | github.com/go-resty/resty/v2 v2.16.4/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA=
156 | github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
157 | github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
158 | github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
159 | github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
160 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
161 | github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
162 | github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
163 | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
164 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
165 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
166 | github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
167 | github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
168 | github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
169 | github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
170 | github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
171 | github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
172 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
173 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
174 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
175 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
176 | github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
177 | github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
178 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
179 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
180 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
181 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
182 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
183 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
184 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
185 | github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
186 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
187 | github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
188 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
189 | github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
190 | github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
191 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
192 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
193 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
194 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
195 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
196 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
197 | github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
198 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
199 | github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
200 | github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
201 | github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
202 | github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
203 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
204 | github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
205 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
206 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
207 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
208 | github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
209 | github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
210 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
211 | github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
212 | github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
213 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
214 | github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
215 | github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
216 | github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
217 | github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
218 | github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
219 | github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
220 | github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
221 | github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
222 | github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
223 | github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
224 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
225 | github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
226 | github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
227 | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
228 | github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
229 | github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
230 | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
231 | github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
232 | github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
233 | github.com/gorilla/schema v1.4.1 h1:jUg5hUjCSDZpNGLuXQOgIWGdlgrIdYvgQ0wZtdK1M3E=
234 | github.com/gorilla/schema v1.4.1/go.mod h1:Dg5SSm5PV60mhF2NFaTV1xuYYj8tV8NOPRo4FggUMnM=
235 | github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
236 | github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
237 | github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
238 | github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
239 | github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
240 | github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
241 | github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
242 | github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
243 | github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
244 | github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
245 | github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
246 | github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
247 | github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
248 | github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
249 | github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
250 | github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
251 | github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
252 | github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
253 | github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
254 | github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
255 | github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
256 | github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
257 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
258 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
259 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
260 | github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
261 | github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
262 | github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
263 | github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
264 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
265 | github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
266 | github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
267 | github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
268 | github.com/jeremija/gosubmit v0.2.7 h1:At0OhGCFGPXyjPYAsCchoBUhE099pcBXmsb4iZqROIc=
269 | github.com/jeremija/gosubmit v0.2.7/go.mod h1:Ui+HS073lCFREXBbdfrJzMB57OI/bdxTiLtrDHHhFPI=
270 | github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
271 | github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
272 | github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
273 | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
274 | github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
275 | github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
276 | github.com/kataras/go-events v0.0.3 h1:o5YK53uURXtrlg7qE/vovxd/yKOJcLuFtPQbf1rYMC4=
277 | github.com/kataras/go-events v0.0.3/go.mod h1:bFBgtzwwzrag7kQmGuU1ZaVxhK2qseYPQomXoVEMsj4=
278 | github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
279 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
280 | github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
281 | github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
282 | github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
283 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
284 | github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
285 | github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
286 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
287 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
288 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
289 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
290 | github.com/labstack/echo/v4 v4.13.3 h1:pwhpCPrTl5qry5HRdM5FwdXnhXSLSY+WE+YQSeCaafY=
291 | github.com/labstack/echo/v4 v4.13.3/go.mod h1:o90YNEeQWjDozo584l7AwhJMHN0bOC4tAfg+Xox9q5g=
292 | github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
293 | github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
294 | github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
295 | github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
296 | github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
297 | github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
298 | github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
299 | github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
300 | github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
301 | github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
302 | github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
303 | github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
304 | github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
305 | github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
306 | github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
307 | github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
308 | github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
309 | github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
310 | github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
311 | github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
312 | github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
313 | github.com/michaelquigley/pfxlog v0.6.10 h1:IbC/H3MmSDcPlQHF1UZPQU13Dkrs0+ycWRyQd2ihnjw=
314 | github.com/michaelquigley/pfxlog v0.6.10/go.mod h1:gEiNTfKEX6cJHSwRpOuqBpc8oYrlhMiDK/xMk/gV7D0=
315 | github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
316 | github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU=
317 | github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
318 | github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
319 | github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
320 | github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
321 | github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
322 | github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc=
323 | github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg=
324 | github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
325 | github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
326 | github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
327 | github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
328 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
329 | github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
330 | github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
331 | github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
332 | github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
333 | github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
334 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
335 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
336 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
337 | github.com/muhlemmer/gu v0.3.1 h1:7EAqmFrW7n3hETvuAdmFmn4hS8W+z3LgKtrnow+YzNM=
338 | github.com/muhlemmer/gu v0.3.1/go.mod h1:YHtHR+gxM+bKEIIs7Hmi9sPT3ZDUvTN/i88wQpZkrdM=
339 | github.com/muhlemmer/httpforwarded v0.1.0 h1:x4DLrzXdliq8mprgUMR0olDvHGkou5BJsK/vWUetyzY=
340 | github.com/muhlemmer/httpforwarded v0.1.0/go.mod h1:yo9czKedo2pdZhoXe+yDkGVbU0TJ0q9oQ90BVoDEtw0=
341 | github.com/nats-io/nats.go v1.39.1 h1:oTkfKBmz7W047vRxV762M67ZdXeOtUgvbBaNoQ+3PPk=
342 | github.com/nats-io/nats.go v1.39.1/go.mod h1:MgRb8oOdigA6cYpEPhXJuRVH6UE/V4jblJ2jQ27IXYM=
343 | github.com/nats-io/nkeys v0.4.9 h1:qe9Faq2Gxwi6RZnZMXfmGMZkg3afLLOtrU+gDZJ35b0=
344 | github.com/nats-io/nkeys v0.4.9/go.mod h1:jcMqs+FLG+W5YO36OX6wFIFcmpdAns+w1Wm6D3I/evE=
345 | github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
346 | github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
347 | github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
348 | github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
349 | github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
350 | github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
351 | github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
352 | github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
353 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
354 | github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
355 | github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg=
356 | github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
357 | github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
358 | github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
359 | github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
360 | github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48=
361 | github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak=
362 | github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
363 | github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
364 | github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
365 | github.com/openziti/channel/v3 v3.0.27 h1:Jx56fuxuvlkap+zNXIDPdfLW1mA6GjrnCxjbDqdBgco=
366 | github.com/openziti/channel/v3 v3.0.27/go.mod h1:vmLGw7KS1mhFDBoYal7O4dIcsm6TAVi9WqjI4TvAemQ=
367 | github.com/openziti/edge-api v0.26.38 h1:3xDWC5SFn3qUVR428TIBpRc2lrjVV7Gz0Rx4pQx0JSg=
368 | github.com/openziti/edge-api v0.26.38/go.mod h1:sYHVpm26Jr1u7VooNJzTb2b2nGSlmCHMnbGC8XfWSng=
369 | github.com/openziti/foundation/v2 v2.0.56 h1:YXqBmkrN0fYr3TqIlWZSZGluE2QpJxlA29Z6okZyQ5I=
370 | github.com/openziti/foundation/v2 v2.0.56/go.mod h1:f12R1pwEod348qONZr6esZgackX1ScLGDcEyPF2G5/w=
371 | github.com/openziti/identity v1.0.94 h1:nF4etu/5LmOlbT24lpSKq9p+90A9jeyLr5U23LemgD4=
372 | github.com/openziti/identity v1.0.94/go.mod h1:3VGYqa9E26zPPA8lJwE7eUPvRH2Oz8ZAd46cUCWKz/M=
373 | github.com/openziti/metrics v1.2.65 h1:Jhhbds+BUbywfspxcb9oyz9p9LI/oERT9lbeDpnNpmY=
374 | github.com/openziti/metrics v1.2.65/go.mod h1:GJObRZX05cxCs23mrsEA9fT9Vk5pbXA6/FkUaslVi8k=
375 | github.com/openziti/sdk-golang v0.24.1 h1:5b3BFRspkHWq0UAMQz4J4QbXDDIdWTRy7stqMhmlEJk=
376 | github.com/openziti/sdk-golang v0.24.1/go.mod h1:aYijpXHfoc6r5hFDl5lu3WV9ZTLg97QBhUdhI9c9kOo=
377 | github.com/openziti/secretstream v0.1.28 h1:D+a5TcvbY3i7HOIecoTL0Pq8HJGnJqS0XmUyO1ohObg=
378 | github.com/openziti/secretstream v0.1.28/go.mod h1:BESAWnpyIr9A+ditH4vk15ZVsnP8zdy6vGi8Qr1lgAg=
379 | github.com/openziti/transport/v2 v2.0.160 h1:bYBBj8gqZ8DCF6aCJThq2v89h5ILwqTVaFkyfjFmHpk=
380 | github.com/openziti/transport/v2 v2.0.160/go.mod h1:Hw4TIlDd97D5m8BrlxTZ3bqO01+hwddTDMSOOzz/4cs=
381 | github.com/orcaman/concurrent-map/v2 v2.0.1 h1:jOJ5Pg2w1oeB6PeDurIYf6k9PQ+aTITr/6lP/L/zp6c=
382 | github.com/orcaman/concurrent-map/v2 v2.0.1/go.mod h1:9Eq3TG2oBe5FirmYWQfYO5iH1q0Jv47PLaNK++uCdOM=
383 | github.com/panjf2000/ants/v2 v2.11.2 h1:AVGpMSePxUNpcLaBO34xuIgM1ZdKOiGnpxLXixLi5Jo=
384 | github.com/panjf2000/ants/v2 v2.11.2/go.mod h1:8u92CYMUc6gyvTIw8Ru7Mt7+/ESnJahz5EVtqfrilek=
385 | github.com/parallaxsecond/parsec-client-go v0.0.0-20221025095442-f0a77d263cf9 h1:mOvehYivJ4Aqu2CPe3D3lv8jhqOI9/1o0THxJHBE0qw=
386 | github.com/parallaxsecond/parsec-client-go v0.0.0-20221025095442-f0a77d263cf9/go.mod h1:gLH27qo/dvMhLTVVyMELpe3Tut7sOfkiDg7ZpeqKwsw=
387 | github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
388 | github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
389 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
390 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
391 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
392 | github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
393 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
394 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
395 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
396 | github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
397 | github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
398 | github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
399 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
400 | github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
401 | github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
402 | github.com/robinson/gos7 v0.0.0-20231012111941-bdaa10e92e16 h1:bhgGFmhTZpESybQyk+uxZ+dAd3yNSJSano2fN7HGmlA=
403 | github.com/robinson/gos7 v0.0.0-20231012111941-bdaa10e92e16/go.mod h1:AMHIeh1KJ7Xa2RVOMHdv9jXKrpw0D4EWGGQMHLb2doc=
404 | github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
405 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
406 | github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
407 | github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
408 | github.com/rs/cors v1.11.0 h1:0B9GE/r9Bc2UxRMMtymBkHTenPkHDv0CW4Y98GBY+po=
409 | github.com/rs/cors v1.11.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
410 | github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
411 | github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
412 | github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
413 | github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
414 | github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk=
415 | github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
416 | github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
417 | github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
418 | github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
419 | github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
420 | github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
421 | github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
422 | github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
423 | github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
424 | github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
425 | github.com/speps/go-hashids v2.0.0+incompatible h1:kSfxGfESueJKTx0mpER9Y/1XHl+FVQjtCqRyYcviFbw=
426 | github.com/speps/go-hashids v2.0.0+incompatible/go.mod h1:P7hqPzMdnZOfyIk+xrlG1QaSMw+gCBdHKsBDnhpaZvc=
427 | github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
428 | github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
429 | github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE=
430 | github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
431 | github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
432 | github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
433 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
434 | github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
435 | github.com/spiffe/go-spiffe/v2 v2.5.0 h1:N2I01KCUkv1FAjZXJMwh95KK1ZIQLYbPfhaxw8WS0hE=
436 | github.com/spiffe/go-spiffe/v2 v2.5.0/go.mod h1:P+NxobPc6wXhVtINNtFjNWGBTreew1GBUCwT2wPmb7g=
437 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
438 | github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
439 | github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
440 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
441 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
442 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
443 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
444 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
445 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
446 | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
447 | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
448 | github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
449 | github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
450 | github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
451 | github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
452 | github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
453 | github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
454 | github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
455 | github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
456 | github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
457 | github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
458 | github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
459 | github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
460 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
461 | github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
462 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
463 | github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
464 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
465 | github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
466 | github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
467 | github.com/zeebo/errs v1.4.0 h1:XNdoD/RRMKP7HD0UhJnIzUy74ISdGGxURlYG8HSWSfM=
468 | github.com/zeebo/errs v1.4.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4=
469 | github.com/zitadel/oidc/v2 v2.12.2 h1:3kpckg4rurgw7w7aLJrq7yvRxb2pkNOtD08RH42vPEs=
470 | github.com/zitadel/oidc/v2 v2.12.2/go.mod h1:vhP26g1g4YVntcTi0amMYW3tJuid70nxqxf+kb6XKgg=
471 | go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
472 | go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
473 | go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
474 | go.mongodb.org/mongo-driver v1.17.0 h1:Hp4q2MCjvY19ViwimTs00wHi7G4yzxh4/2+nTx8r40k=
475 | go.mongodb.org/mongo-driver v1.17.0/go.mod h1:wwWm/+BuOddhcq3n68LKRmgk2wXzmF6s0SFOa0GINL4=
476 | go.mozilla.org/pkcs7 v0.9.0 h1:yM4/HS9dYv7ri2biPtxt8ikvB37a980dg69/pKmS+eI=
477 | go.mozilla.org/pkcs7 v0.9.0/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
478 | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
479 | go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
480 | go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
481 | go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
482 | go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
483 | go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
484 | go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
485 | go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U=
486 | go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg=
487 | go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M=
488 | go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8=
489 | go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4=
490 | go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU=
491 | go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU=
492 | go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ=
493 | go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM=
494 | go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8=
495 | go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
496 | go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
497 | go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
498 | golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
499 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
500 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
501 | golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
502 | golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
503 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
504 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
505 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
506 | golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
507 | golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
508 | golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
509 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
510 | golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
511 | golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
512 | golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
513 | golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
514 | golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
515 | golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
516 | golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
517 | golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
518 | golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
519 | golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=
520 | golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
521 | golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
522 | golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
523 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
524 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
525 | golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
526 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
527 | golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
528 | golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
529 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
530 | golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
531 | golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
532 | golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
533 | golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
534 | golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
535 | golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
536 | golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
537 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
538 | golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
539 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
540 | golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
541 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
542 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
543 | golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
544 | golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
545 | golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
546 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
547 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
548 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
549 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
550 | golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
551 | golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
552 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
553 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
554 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
555 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
556 | golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
557 | golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
558 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
559 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
560 | golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
561 | golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
562 | golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
563 | golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
564 | golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
565 | golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
566 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
567 | golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
568 | golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
569 | golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
570 | golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
571 | golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
572 | golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
573 | golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
574 | golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
575 | golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
576 | golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
577 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
578 | golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
579 | golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
580 | golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
581 | golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
582 | golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
583 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
584 | golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
585 | golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
586 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
587 | golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
588 | golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
589 | golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
590 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
591 | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
592 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
593 | golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
594 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
595 | golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
596 | golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
597 | golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
598 | golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
599 | golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
600 | golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
601 | golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
602 | golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70=
603 | golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
604 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
605 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
606 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
607 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
608 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
609 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
610 | golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
611 | golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
612 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
613 | golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
614 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
615 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
616 | golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
617 | golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
618 | golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
619 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
620 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
621 | golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
622 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
623 | golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
624 | golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
625 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
626 | golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
627 | golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
628 | golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
629 | golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
630 | golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
631 | golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
632 | golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
633 | golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
634 | golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
635 | golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
636 | golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
637 | golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
638 | golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
639 | golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
640 | golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
641 | golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
642 | golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
643 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
644 | golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
645 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
646 | golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
647 | golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
648 | golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
649 | golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
650 | golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
651 | golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
652 | golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
653 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
654 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
655 | golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
656 | golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
657 | golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
658 | golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
659 | golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
660 | golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
661 | golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
662 | golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
663 | golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
664 | golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
665 | golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
666 | golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
667 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
668 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
669 | golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
670 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
671 | golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
672 | golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
673 | golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
674 | golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
675 | golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
676 | golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
677 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
678 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
679 | golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
680 | golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
681 | golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
682 | golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
683 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
684 | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
685 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
686 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
687 | golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
688 | golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
689 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
690 | golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
691 | golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
692 | golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
693 | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
694 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
695 | golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
696 | golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg=
697 | golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
698 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
699 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
700 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
701 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
702 | golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
703 | golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
704 | golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
705 | golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
706 | golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
707 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
708 | golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
709 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
710 | golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
711 | golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
712 | golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
713 | golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
714 | golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
715 | golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
716 | golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
717 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
718 | golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
719 | golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
720 | golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
721 | golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
722 | golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
723 | golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
724 | golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
725 | golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
726 | golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
727 | golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
728 | golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
729 | golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
730 | golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
731 | golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
732 | golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
733 | golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
734 | golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
735 | golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
736 | golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
737 | golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
738 | golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
739 | golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
740 | golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
741 | golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
742 | golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
743 | golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
744 | golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
745 | golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
746 | golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
747 | golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
748 | golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
749 | golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
750 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
751 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
752 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
753 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
754 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
755 | google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
756 | google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
757 | google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
758 | google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
759 | google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
760 | google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
761 | google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
762 | google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
763 | google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
764 | google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
765 | google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
766 | google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
767 | google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
768 | google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
769 | google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
770 | google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
771 | google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
772 | google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
773 | google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
774 | google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
775 | google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
776 | google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8=
777 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
778 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
779 | google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
780 | google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
781 | google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
782 | google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
783 | google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
784 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
785 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
786 | google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
787 | google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
788 | google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
789 | google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
790 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
791 | google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
792 | google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
793 | google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
794 | google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
795 | google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
796 | google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
797 | google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
798 | google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
799 | google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
800 | google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
801 | google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
802 | google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
803 | google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
804 | google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
805 | google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
806 | google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
807 | google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
808 | google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
809 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
810 | google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
811 | google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
812 | google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
813 | google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
814 | google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
815 | google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
816 | google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
817 | google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
818 | google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
819 | google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
820 | google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
821 | google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
822 | google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
823 | google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
824 | google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
825 | google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a h1:hgh8P4EuoxpsuKMXX/To36nOFD7vixReXgn8lPGnt+o=
826 | google.golang.org/genproto/googleapis/rpc v0.0.0-20241202173237-19429a94021a/go.mod h1:5uTbfoYQed2U9p3KIj2/Zzm02PYhndfdmML0qC3q3FU=
827 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
828 | google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
829 | google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
830 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
831 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
832 | google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
833 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
834 | google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
835 | google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
836 | google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
837 | google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
838 | google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
839 | google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
840 | google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
841 | google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
842 | google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
843 | google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
844 | google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
845 | google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
846 | google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
847 | google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
848 | google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
849 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
850 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
851 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
852 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
853 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
854 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
855 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
856 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
857 | google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
858 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
859 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
860 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
861 | google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU=
862 | google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
863 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
864 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
865 | gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
866 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
867 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
868 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
869 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
870 | gopkg.in/go-jose/go-jose.v2 v2.6.3 h1:nt80fvSDlhKWQgSWyHyy5CfmlQr+asih51R8PTWNKKs=
871 | gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI=
872 | gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
873 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
874 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
875 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
876 | gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
877 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
878 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
879 | gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
880 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
881 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
882 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
883 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
884 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
885 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
886 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
887 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
888 | honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
889 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
890 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
891 | honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
892 | honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
893 | nhooyr.io/websocket v1.8.17 h1:KEVeLJkUywCKVsnLIDlD/5gtayKp8VoCkksHCGGfT9Y=
894 | nhooyr.io/websocket v1.8.17/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c=
895 | rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
896 | rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
897 | rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
898 |
--------------------------------------------------------------------------------
/internal/driver/constants.go:
--------------------------------------------------------------------------------
1 | // -*- Mode: Go; indent-tabs-mode: t -*-
2 | //
3 | // Copyright (C) 2023 YIQISOFT
4 | //
5 | // SPDX-License-Identifier: Apache-2.0
6 |
7 | package driver
8 |
9 | // Constants related to protocol properties
10 | const (
11 | Protocol = "s7"
12 | )
13 |
14 | const (
15 | HOST = "Host"
16 | PORT = "Port"
17 | RACK = "Rack"
18 | SLOT = "Slot"
19 | ADDRESS_TYPE = "AddressType"
20 | DBADDRESS = "DBAddress"
21 | STARTING_ADDRESS = "StartingAddress"
22 | LENGTH = "Length"
23 | POS = "Pos"
24 | )
25 |
--------------------------------------------------------------------------------
/internal/driver/driver.go:
--------------------------------------------------------------------------------
1 | // -*- Mode: Go; indent-tabs-mode: t -*-
2 | //
3 | // Copyright (C) 2023 YIQISOFT
4 | //
5 | // SPDX-License-Identifier: Apache-2.0
6 |
7 | // This package provides an example implementation of
8 | // S7 interface.
9 | package driver
10 |
11 | import (
12 | "fmt"
13 | "strconv"
14 | "strings"
15 | "sync"
16 | "time"
17 |
18 | "github.com/edgexfoundry/device-sdk-go/v4/pkg/interfaces"
19 | sdkModel "github.com/edgexfoundry/device-sdk-go/v4/pkg/models"
20 | "github.com/edgexfoundry/go-mod-core-contracts/v4/clients/logger"
21 | "github.com/edgexfoundry/go-mod-core-contracts/v4/common"
22 | "github.com/edgexfoundry/go-mod-core-contracts/v4/models"
23 |
24 | "github.com/robinson/gos7"
25 | "github.com/spf13/cast"
26 | )
27 |
28 | const (
29 | // Word Length
30 | s7wlbit = 0x01 // Bit (inside a word)
31 | s7wlbyte = 0x02 // Byte (8 bit)
32 | s7wlChar = 0x03 // Char (8 bit)
33 | s7wlword = 0x04 // Word (16 bit)
34 | s7wlint = 0x05 // Int (16 bit)
35 | s7wldword = 0x06 // Double Word (32 bit)
36 | s7wldint = 0x07 // DInt (32 bit)
37 | s7wlreal = 0x08 // Real (32 bit float)
38 | s7wlcounter = 0x1C // Counter (16 bit)
39 | s7wltimer = 0x1D // Timer (16 bit)
40 | )
41 |
42 | var once sync.Once
43 | var driver *Driver
44 |
45 | type Driver struct {
46 | lc logger.LoggingClient
47 | asyncCh chan<- *sdkModel.AsyncValues
48 | s7Clients map[string]*S7Client
49 | mu sync.Mutex
50 | }
51 |
52 | func NewProtocolDriver() interfaces.ProtocolDriver {
53 | once.Do(func() {
54 | driver = new(Driver)
55 | })
56 | return driver
57 | }
58 |
59 | type CommandInfo struct {
60 | Host string
61 | Port int
62 | Rack int
63 | Slot int
64 | AddressType string
65 | DbAddress int
66 | StartingAddress int
67 | Length int
68 | Pos int
69 | ValueType string
70 | }
71 |
72 | type DBInfo struct {
73 | Area int
74 | DBNumber int
75 | Start int
76 | Amount int
77 | WordLength int
78 | DBArray []string
79 | }
80 |
81 | // Initialize performs protocol-specific initialization for the device
82 | // service.
83 | func (s *Driver) Initialize(sdk interfaces.DeviceServiceSDK) error {
84 | s.lc = sdk.LoggingClient()
85 | s.asyncCh = sdk.AsyncValuesChannel()
86 | s.s7Clients = make(map[string]*S7Client)
87 |
88 | // initialize the all devices connection in the service started
89 | for _, device := range sdk.Devices() {
90 | s7Client := s.NewS7Client(device.Name, device.Protocols)
91 | if s7Client == nil {
92 | s.lc.Errorf("failed to initialize S7 client for '%s' device, skipping this device.", device.Name)
93 | continue
94 | }
95 | s.s7Clients[device.Name] = s7Client
96 | s.lc.Debugf("S7Client connected for device: %s", device.Name)
97 | }
98 |
99 | return nil
100 | }
101 |
102 | // HandleReadCommands triggers a protocol Read operation for the specified device.
103 | func (s *Driver) HandleReadCommands(deviceName string, protocols map[string]models.ProtocolProperties, reqs []sdkModel.CommandRequest) (res []*sdkModel.CommandValue, err error) {
104 | s.lc.Debugf("Driver.HandleReadCommands: protocols: %v, resource: %v, attributes: %v", protocols, reqs[0].DeviceResourceName, reqs[0].Attributes)
105 |
106 | // assume the max batch size is 16, must be less than 20
107 | var batch_size = 16
108 |
109 | var reqs_len = len(reqs)
110 | var s7DataItems = []gos7.S7DataItem{}
111 |
112 | var s7_errors = make([]string, reqs_len)
113 | // two-dimensional array for handle S7DataItems
114 | var dataset = make([][]byte, reqs_len)
115 | for i := range dataset {
116 | dataset[i] = make([]byte, 4) // 4 bytes
117 | }
118 |
119 | // Get S7 device connection information, each Device has its own connection.
120 | s7Client := s.getS7Client(deviceName, protocols)
121 |
122 | // assemble s7DataItems, get items, fetch data
123 |
124 | var times = int(reqs_len / batch_size)
125 | var remains = reqs_len % batch_size
126 | var tmp_reqs []sdkModel.CommandRequest
127 |
128 | outloop:
129 | for j := 0; j <= times; j++ {
130 |
131 | // 1. init array
132 | s7DataItems = s7DataItems[:0] // clear array
133 | tmp_reqs = tmp_reqs[:0] // clear array
134 | if j >= times {
135 | if remains > 0 {
136 | tmp_reqs = reqs[times*batch_size : times*batch_size+remains]
137 | } else {
138 | _ = tmp_reqs
139 | break outloop // load complete, exit loop
140 | }
141 | } else {
142 | tmp_reqs = reqs[j*batch_size : j*batch_size+batch_size]
143 | }
144 |
145 | // 2. get resources from reqs append to items
146 | var count int
147 | for i, req := range tmp_reqs {
148 |
149 | nodename := cast.ToString(req.Attributes["NodeName"])
150 | dbInfo, err := s.getDBInfo(nodename)
151 | if err != nil {
152 | count++
153 | s.lc.Errorf("convert nodeName to dbInfo failed,err =%v", err)
154 | var nilS7DataItem = gos7.S7DataItem{
155 | Area: 0,
156 | WordLen: 0,
157 | DBNumber: 0,
158 | Start: 0,
159 | Amount: 0,
160 | Data: dataset[j*batch_size+i],
161 | }
162 | s7DataItems = append(s7DataItems, nilS7DataItem)
163 | continue
164 | }
165 | var s7DataItem = gos7.S7DataItem{
166 | Area: dbInfo.Area,
167 | WordLen: dbInfo.WordLength,
168 | DBNumber: dbInfo.DBNumber,
169 | Start: dbInfo.Start,
170 | Amount: dbInfo.Amount,
171 | Data: dataset[j*batch_size+i],
172 | }
173 | s7DataItems = append(s7DataItems, s7DataItem)
174 | }
175 | s.lc.Debugf("Read from S7DataItems: %+v", s7DataItems)
176 | if count == len(tmp_reqs) {
177 | s.lc.Errorf("commandRequest %+v is invalid", tmp_reqs)
178 | continue
179 | }
180 |
181 | // 3. use AGReadMulti api to get values from S7 device, if error, try 3 times
182 | retrytimes := 3
183 | for {
184 | err = s7Client.Client.AGReadMulti(s7DataItems, len(s7DataItems))
185 | if err != nil {
186 | s.lc.Errorf("AGReadMulti Error: %s, reconnecting...", err)
187 | s.mu.Lock()
188 | s.s7Clients[deviceName] = nil
189 | s.mu.Unlock()
190 | s7Client = s.getS7Client(deviceName, protocols)
191 | } else {
192 | s.lc.Debugf("AGReadMulti read from 'dataset': ", dataset)
193 | break
194 | }
195 |
196 | retrytimes--
197 | if retrytimes == 0 {
198 | break
199 | }
200 |
201 | }
202 | //4. use s7_errors to record the abnormal error messages of all read points
203 | for i, s7DataItem := range s7DataItems {
204 | if s7_error := s7DataItem.Error; s7_error != "" {
205 | s.lc.Errorf("s7DataItem:%+v,error: %s", s7DataItem, s7_error)
206 | s7_errors[j*batch_size+i] = s7_error
207 | }
208 | }
209 |
210 | }
211 | // end assemble s7DataItems
212 | s.lc.Debugf("Read S7DataItems: %+v", s7DataItems)
213 | // read results from the dataset of s7DataItems
214 | for i, req := range reqs {
215 |
216 | var result *sdkModel.CommandValue
217 | var value any
218 |
219 | if s7_error := s7_errors[i]; s7_error != "" {
220 | s.lc.Errorf("S7 Client AGRead req %+v failed,error: %s", req, s7_error)
221 | continue
222 | }
223 |
224 | value, err := getCommandValueType(dataset[i], req.Type)
225 | if err != nil {
226 | s.lc.Errorf("getCommandValueType error: %s", err)
227 | continue
228 | }
229 |
230 | result, err = getCommandValue(req, value)
231 | if err != nil {
232 | s.lc.Errorf("getCommandValue error: %v", err)
233 | continue
234 | }
235 |
236 | res = append(res, result)
237 | }
238 | if len(res) == 0 {
239 | s.lc.Errorf("read reqs %+v failed", reqs)
240 | return nil, fmt.Errorf("read reqs %+v failed", reqs)
241 | }
242 | s.lc.Debugf("CommandValues: %s", res)
243 |
244 | return
245 | }
246 |
247 | // HandleWriteCommands passes a slice of CommandRequest struct each representing
248 | // a ResourceOperation for a specific device resource.
249 | // Since the commands are actuation commands, params provide parameters for the individual
250 | // command.
251 | func (s *Driver) HandleWriteCommands(deviceName string, protocols map[string]models.ProtocolProperties, reqs []sdkModel.CommandRequest,
252 | params []*sdkModel.CommandValue) error {
253 | s.lc.Debugf("Driver.HandleWriteCommands: protocols: %v, resource: %v, parameters: %v", protocols, reqs[0].DeviceResourceName, params)
254 |
255 | var err error
256 |
257 | // assume the max batch size is 16, must be less than 20
258 | var batch_size = 16
259 |
260 | var reqs_len = len(reqs)
261 | var s7DataItems = []gos7.S7DataItem{}
262 | var helper gos7.Helper
263 |
264 | var s7_errors = make([]string, reqs_len)
265 | // two-dimensional array for handle S7DataItems
266 | var dataset = make([][]byte, reqs_len)
267 | for i := range dataset {
268 | dataset[i] = make([]byte, 4) // 4 bytes
269 | }
270 |
271 | // transfer command values to S7DataItems
272 | var count int
273 | for i, req := range reqs {
274 |
275 | s.lc.Debugf("S7Driver.HandleWriteCommands: protocols: %v, resource: %v, parameters: %v, attributes: %v", protocols, req.DeviceResourceName, params[i], req.Attributes)
276 |
277 | var nodeName = cast.ToString(req.Attributes["NodeName"])
278 | var dbInfo, err = s.getDBInfo(nodeName)
279 | if err != nil {
280 | count++
281 | s.lc.Errorf("convert nodeName %v to dbInfo failed,err =%v", nodeName, err)
282 | dbInfo = &DBInfo{
283 | Area: 0,
284 | DBNumber: 0,
285 | Start: 0,
286 | Amount: 0,
287 | WordLength: 0,
288 | DBArray: []string{nodeName},
289 | }
290 | }
291 |
292 | reading, err := newCommandValue(req.Type, params[i])
293 | if err != nil {
294 | s.lc.Errorf("newCommandValue error: %s", err)
295 | }
296 | helper.SetValueAt(dataset[i], 0, reading)
297 |
298 | // create gos7 DataItem
299 | var s7DataItem = gos7.S7DataItem{
300 | Area: dbInfo.Area,
301 | WordLen: dbInfo.WordLength,
302 | DBNumber: dbInfo.DBNumber,
303 | Start: dbInfo.Start,
304 | Amount: dbInfo.Amount,
305 | Data: dataset[i],
306 | }
307 | s7DataItems = append(s7DataItems, s7DataItem)
308 |
309 | }
310 | if count == len(reqs) {
311 | s.lc.Errorf("commandWrite %+v is invalid", reqs)
312 | return fmt.Errorf("commandWrite %+v is invalid", reqs)
313 | }
314 | s.lc.Debugf("Write to S7DataItems: %s", s7DataItems)
315 |
316 | // send command requests
317 | times := int(reqs_len / batch_size)
318 | remains := reqs_len % batch_size
319 | var tmp_s7DateItems = []gos7.S7DataItem{}
320 |
321 | s7Client := s.getS7Client(deviceName, protocols)
322 |
323 | outloop:
324 | for j := 0; j <= times; j++ {
325 |
326 | tmp_s7DateItems = tmp_s7DateItems[:0] // clear array
327 | if j >= times {
328 | if remains > 0 {
329 | tmp_s7DateItems = s7DataItems[times*batch_size : times*batch_size+remains]
330 | } else {
331 | _ = tmp_s7DateItems
332 | break outloop // load complete, exit loop
333 | }
334 | } else {
335 | tmp_s7DateItems = s7DataItems[j*batch_size : j*batch_size+batch_size]
336 | }
337 |
338 | // write data to S7 device, if error, try 3 times
339 | retrytimes := 3
340 | for {
341 | err = s7Client.Client.AGWriteMulti(tmp_s7DateItems, len(tmp_s7DateItems))
342 | if err != nil {
343 | s.lc.Errorf("AGWriteMulti Error: %s, reconnecting...", err)
344 | s.mu.Lock()
345 | s.s7Clients[deviceName] = nil
346 | s.mu.Unlock()
347 | s7Client = s.getS7Client(deviceName, protocols)
348 | } else {
349 | s.lc.Debugf("AGWriteMulti write from 'dataset': %s", dataset)
350 | break
351 | }
352 |
353 | retrytimes--
354 | if retrytimes == 0 {
355 | break
356 | }
357 | }
358 | // Record all errors
359 | for i, tmp_s7DataItem := range tmp_s7DateItems {
360 | if s7_error := tmp_s7DataItem.Error; s7_error != "" {
361 | s.lc.Errorf("tmp_s7DataItem:%+v,error: %s", tmp_s7DataItem, s7_error)
362 | s7_errors[j*batch_size+i] = s7_error
363 | }
364 | }
365 |
366 | }
367 |
368 | for _, s7_error := range s7_errors {
369 | if s7_error != "" {
370 | s.lc.Errorf("S7 Client AGWriteMulti error: %s", s7_error)
371 | return err
372 | }
373 | }
374 |
375 | return nil
376 | }
377 |
378 | // Stop the protocol-specific DS code to shutdown gracefully, or
379 | // if the force parameter is 'true', immediately. The driver is responsible
380 | // for closing any in-use channels, including the channel used to send async
381 | // readings (if supported).
382 | func (s *Driver) Stop(force bool) error {
383 |
384 | s.mu.Lock()
385 | s.s7Clients = nil
386 | s.mu.Unlock()
387 |
388 | // Then Logging Client might not be initialized
389 | if s.lc != nil {
390 | s.lc.Debugf("Driver.Stop called: force=%v", force)
391 | }
392 | return nil
393 | }
394 |
395 | // AddDevice is a callback function that is invoked
396 | // when a new Device associated with this Device Service is added
397 | func (s *Driver) AddDevice(deviceName string, protocols map[string]models.ProtocolProperties, adminState models.AdminState) error {
398 | s.lc.Debugf("a new Device is added: %s", deviceName)
399 |
400 | s.mu.Lock()
401 | s.s7Clients[deviceName] = nil
402 | s.mu.Unlock()
403 | s7Client := s.getS7Client(deviceName, protocols)
404 | if s7Client == nil {
405 | errt := fmt.Errorf("failed to initialize S7 client for '%s' device, skipping this device", deviceName)
406 | s.lc.Errorf(errt.Error())
407 | return errt
408 | }
409 | s.mu.Lock()
410 | s.s7Clients[deviceName] = s7Client
411 | s.mu.Unlock()
412 | return nil
413 | }
414 |
415 | // UpdateDevice is a callback function that is invoked
416 | // when a Device associated with this Device Service is updated
417 | func (s *Driver) UpdateDevice(deviceName string, protocols map[string]models.ProtocolProperties, adminState models.AdminState) error {
418 | s.lc.Debugf("Device %s is updated", deviceName)
419 |
420 | s7Client := s.NewS7Client(deviceName, protocols)
421 | if s7Client == nil {
422 | errt := fmt.Errorf("failed to initialize S7 client for '%s' device, skipping this device", deviceName)
423 | s.lc.Errorf(errt.Error())
424 | return errt
425 | }
426 | s.mu.Lock()
427 | s.s7Clients[deviceName] = s7Client
428 | s.mu.Unlock()
429 |
430 | return nil
431 | }
432 |
433 | // RemoveDevice is a callback function that is invoked
434 | // when a Device associated with this Device Service is removed
435 | func (s *Driver) RemoveDevice(deviceName string, protocols map[string]models.ProtocolProperties) error {
436 | s.lc.Debugf("Device %s is removed", deviceName)
437 | s.mu.Lock()
438 | delete(s.s7Clients, deviceName)
439 | s.mu.Unlock()
440 | return nil
441 | }
442 |
443 | func (s *Driver) ValidateDevice(device models.Device) error {
444 | s.lc.Debugf("Validating device: %s", device.Name)
445 |
446 | protocols := device.Protocols
447 | pp := protocols[Protocol]
448 | var errt error
449 |
450 | if pp == nil {
451 | errt = fmt.Errorf("%s not found in protocols for device %s", Protocol, device.Name)
452 | s.lc.Error(errt.Error())
453 | return errt
454 | }
455 |
456 | _, errt = cast.ToStringE(pp["Host"])
457 | if errt != nil {
458 | s.lc.Errorf("Host not found or not a string in Protocol, error: %s", errt)
459 | return errt
460 | }
461 | _, errt = cast.ToIntE(pp["Port"])
462 | if errt != nil {
463 | s.lc.Errorf("Port not found or not an integer in Protocol, error: %s", errt)
464 | return errt
465 | }
466 | _, errt = cast.ToIntE(pp["Rack"])
467 | if errt != nil {
468 | s.lc.Errorf("Rack not found or not an integer in Protocol, error: %s", errt)
469 | return errt
470 | }
471 | _, errt = cast.ToIntE(pp["Slot"])
472 | if errt != nil {
473 | s.lc.Errorf("Slot not found or not an integer in Protocol, error: %s", errt)
474 | return errt
475 | }
476 | _, errt = cast.ToIntE(pp["Timeout"])
477 | if errt != nil {
478 | s.lc.Errorf("Timeout not found or not an integer in Protocol, USE DEFAULT 30s error: %s", errt)
479 | pp["Timeout"] = 30
480 | }
481 | _, errt = cast.ToIntE(pp["IdleTimeout"])
482 | if errt != nil {
483 | s.lc.Errorf("IdleTimeout not found or not an ingeger in Protocol, USE DEFAULT 30s, error: %s", errt)
484 | pp["IdleTimeout"] = 30
485 | }
486 |
487 | return nil
488 | }
489 |
490 | // Create S7Client by 'Device' definition
491 | func (s *Driver) NewS7Client(deviceName string, protocol map[string]models.ProtocolProperties) *S7Client {
492 |
493 | pp := protocol[Protocol]
494 |
495 | host, _ := cast.ToStringE(pp["Host"])
496 | port, _ := cast.ToStringE(pp["Port"])
497 | rack, _ := cast.ToIntE(pp["Rack"])
498 | slot, _ := cast.ToIntE(pp["Slot"])
499 | timeout, _ := cast.ToIntE(pp["Timeout"])
500 | idletimeout, _ := cast.ToIntE(pp["IdleTimeout"])
501 |
502 | // create handler: PLC tcp client
503 | handler := gos7.NewTCPClientHandler(host+":"+port, rack, slot)
504 | if handler == nil {
505 | s.lc.Errorf("Cant not create NewTCPClientHandler: %s", handler)
506 | return nil
507 | }
508 | s.lc.Debugf("New TCP Client: %s", handler)
509 |
510 | // handler connect timeout from 'Timeout'
511 | handler.Timeout = time.Duration(timeout) * time.Second
512 |
513 | // handler connect idle timeout from 'IdleTimeout'
514 | handler.IdleTimeout = time.Duration(idletimeout) * time.Second
515 |
516 | // connect to S7
517 | err := handler.Connect()
518 | if err != nil {
519 | s.lc.Errorf("Can't handler S7 Connect: %s, error: %s", deviceName, err)
520 | // return nil
521 | }
522 |
523 | s7client := gos7.NewClient(handler)
524 | client := &S7Client{
525 | DeviceName: deviceName,
526 | Client: s7client,
527 | }
528 | return client
529 |
530 | }
531 |
532 | // Get S7Client by 'DeviceName'
533 | func (s *Driver) getS7Client(deviceName string, protocols map[string]models.ProtocolProperties) *S7Client {
534 | s.mu.Lock()
535 | s7Client := s.s7Clients[deviceName]
536 | s.mu.Unlock()
537 |
538 | if s7Client == nil {
539 | s.lc.Warnf("S7CLient for device %s not found. Creating it...", deviceName)
540 | s7Client = s.NewS7Client(deviceName, protocols)
541 | s.mu.Lock()
542 | s.s7Clients[deviceName] = s7Client
543 | s.mu.Unlock()
544 | }
545 |
546 | return s7Client
547 |
548 | }
549 |
550 | // transfer DBstring to DBInfo
551 | func (s *Driver) getDBInfo(variable string) (dbInfo *DBInfo, err error) {
552 |
553 | // varibale sample: DB2.DBX1.0 / DB2.DBD26 / DB2.DBD826
554 | variable = strings.ToUpper(variable) //upper
555 | variable = strings.Replace(variable, " ", "", -1) //remove spaces
556 |
557 | if variable == "" {
558 | s.lc.Errorf("input [NodeName] variable is empty, variable should be S7 syntax")
559 | return nil, fmt.Errorf("input [NodeName] variable is empty, variable should be S7 syntax")
560 | }
561 |
562 | var area int
563 | var amount int
564 | var wordLen int
565 | var dbNo int64
566 | var dbIndex int64
567 | var dbArray []string
568 |
569 | //var area, dbNumber, start, amount, wordLen int
570 | switch valueArea := variable[0:2]; valueArea {
571 | case "EB": //input byte
572 | case "EW": //input word
573 | case "ED": //Input double-word
574 | case "AB": //Output byte
575 | case "AW": //Output word
576 | case "AD": //Output double-word
577 | case "MB": //Memory byte
578 | case "MW": //Memory word
579 | case "MD": //Memory double-word
580 | case "DB": //Data Block
581 | // Area ID
582 | // s7areape = 0x81 //process inputs
583 | // s7areapa = 0x82 //process outputs
584 | // s7areamk = 0x83 //Merkers
585 | // s7areadb = 0x84 //DB
586 | // s7areact = 0x1C //counters
587 | // s7areatm = 0x1D //timers
588 | area = 0x84
589 | amount = 1
590 | dbArray = strings.Split(variable, ".")
591 | if len(dbArray) < 2 {
592 | s.lc.Errorf("Db Area read variable should not be empty")
593 | return nil, fmt.Errorf("DB variable %+v is invalid", variable)
594 | }
595 | dbNo, err = strconv.ParseInt(string(string(dbArray[0])[2:]), 10, 16)
596 | if err != nil {
597 | s.lc.Errorf("convert dbNo of %+v to int failed.err:%v", variable, err)
598 | return nil, fmt.Errorf("convert dbNo of %+v to int failed.err:%v", variable, err)
599 | }
600 | dbIndex, err = strconv.ParseInt(string(string(dbArray[1])[3:]), 10, 16)
601 | if err != nil {
602 | s.lc.Errorf("convert dbIndex of %+v to int failed.err:%v", variable, err)
603 | return nil, fmt.Errorf("convert dbIndex of %+v to int failed.err:%v", variable, err)
604 | }
605 |
606 | dbType := string(dbArray[1])[0:3]
607 |
608 | switch dbType {
609 | case "DBX": //bit
610 | wordLen = s7wlbit
611 | if length := len(dbArray); length != 3 {
612 | s.lc.Errorf("The point address of %+v is incorrect", variable)
613 | return nil, fmt.Errorf("the point address of %+v is incorrect", variable)
614 | }
615 | // DBIndex = dbIndex + dbBit (DBX12.5 = 12<<3 + 5 = 96+5 = 101 = 0x65)
616 | dbBit, err := strconv.ParseInt(string(string(dbArray[2])), 10, 16)
617 | if err != nil {
618 | s.lc.Errorf("convert dbBit of %+v to int failed.err:%v", variable, err)
619 | return nil, fmt.Errorf("convert dbBit of %+v to int failed.err:%v", variable, err)
620 | }
621 | dbIndex = dbIndex<<3 + dbBit
622 | case "DBB": //byte
623 | wordLen = s7wlbyte
624 | case "DBW": //word
625 | wordLen = s7wlword
626 | // amount = 2
627 | case "DBD": //dword
628 | wordLen = s7wlreal
629 | // amount = 4
630 | default:
631 | s.lc.Errorf("error when parsing dbtype")
632 | return nil, fmt.Errorf("error when parsing dbtype")
633 | }
634 | default:
635 | switch otherArea := variable[0:1]; otherArea {
636 | case "E":
637 | case "I": //input
638 | case "A":
639 | case "0": //output
640 | case "M": //memory
641 | case "T": //timer
642 | return
643 | case "Z":
644 | case "C": //counter
645 | return
646 | default:
647 | s.lc.Errorf("error when parsing db area")
648 | return nil, fmt.Errorf("error when parsing db area")
649 | }
650 |
651 | }
652 | if err != nil {
653 | s.lc.Errorf("convert %+v to int failed.err:%v", variable, err)
654 | return nil, fmt.Errorf("convert %+v to int failed.err:%v", variable, err)
655 | }
656 | return &DBInfo{
657 | Area: area,
658 | DBNumber: int(dbNo),
659 | Start: int(dbIndex),
660 | Amount: amount,
661 | WordLength: wordLen,
662 | DBArray: dbArray,
663 | }, nil
664 |
665 | }
666 |
667 | // Get command value type
668 | func getCommandValueType(buffer []byte, valueType string) (value any, err error) {
669 | var helper gos7.Helper
670 |
671 | switch valueType {
672 | case common.ValueTypeBool:
673 | var commandValue bool
674 | helper.GetValueAt(buffer, 0, &commandValue)
675 | value = commandValue
676 | case common.ValueTypeString:
677 | var commandValue string
678 | helper.GetValueAt(buffer, 0, &commandValue)
679 | value = commandValue
680 | case common.ValueTypeUint8:
681 | var commandValue uint8
682 | helper.GetValueAt(buffer, 0, &commandValue)
683 | value = commandValue
684 | case common.ValueTypeUint16:
685 | var commandValue uint16
686 | helper.GetValueAt(buffer, 0, &commandValue)
687 | value = commandValue
688 | case common.ValueTypeUint32:
689 | var commandValue uint32
690 | helper.GetValueAt(buffer, 0, &commandValue)
691 | value = commandValue
692 | case common.ValueTypeUint64:
693 | var commandValue uint64
694 | helper.GetValueAt(buffer, 0, &commandValue)
695 | value = commandValue
696 | case common.ValueTypeInt8:
697 | var commandValue int8
698 | helper.GetValueAt(buffer, 0, &commandValue)
699 | value = commandValue
700 | case common.ValueTypeInt16:
701 | var commandValue int16
702 | helper.GetValueAt(buffer, 0, &commandValue)
703 | value = commandValue
704 | case common.ValueTypeInt32:
705 | var commandValue int32
706 | helper.GetValueAt(buffer, 0, &commandValue)
707 | value = commandValue
708 | case common.ValueTypeInt64:
709 | var commandValue int64
710 | helper.GetValueAt(buffer, 0, &commandValue)
711 | value = commandValue
712 | case common.ValueTypeFloat32:
713 | var commandValue float32
714 | helper.GetValueAt(buffer, 0, &commandValue)
715 | value = commandValue
716 | case common.ValueTypeFloat64:
717 | var commandValue float64
718 | helper.GetValueAt(buffer, 0, &commandValue)
719 | value = commandValue
720 | default:
721 | err = fmt.Errorf("fail to convert param, none supported value type: %v", valueType)
722 | }
723 |
724 | return value, err
725 | }
726 |
727 | // Create command value
728 | func newCommandValue(valueType string, param *sdkModel.CommandValue) (any, error) {
729 | var commandValue any
730 | var err error
731 | switch valueType {
732 | case common.ValueTypeBool:
733 | commandValue, err = param.BoolValue()
734 | case common.ValueTypeString:
735 | commandValue, err = param.StringValue()
736 | case common.ValueTypeUint8:
737 | commandValue, err = param.Uint8Value()
738 | case common.ValueTypeUint16:
739 | commandValue, err = param.Uint16Value()
740 | case common.ValueTypeUint32:
741 | commandValue, err = param.Uint32Value()
742 | case common.ValueTypeUint64:
743 | commandValue, err = param.Uint64Value()
744 | case common.ValueTypeInt8:
745 | commandValue, err = param.Int8Value()
746 | case common.ValueTypeInt16:
747 | commandValue, err = param.Int16Value()
748 | case common.ValueTypeInt32:
749 | commandValue, err = param.Int32Value()
750 | case common.ValueTypeInt64:
751 | commandValue, err = param.Int64Value()
752 | case common.ValueTypeFloat32:
753 | commandValue, err = param.Float32Value()
754 | case common.ValueTypeFloat64:
755 | commandValue, err = param.Float64Value()
756 | default:
757 | err = fmt.Errorf("fail to convert param, none supported value type: %v", valueType)
758 | }
759 |
760 | return commandValue, err
761 | }
762 |
763 | // Get command value
764 | func getCommandValue(req sdkModel.CommandRequest, reading any) (*sdkModel.CommandValue, error) {
765 | var err error
766 | var result = &sdkModel.CommandValue{}
767 | castError := "fail to parse %v reading, %v"
768 |
769 | if !checkValueInRange(req.Type, reading) {
770 | err = fmt.Errorf("parse reading fail. Reading %v is out of the value type(%v)'s range", reading, req.Type)
771 | driver.lc.Error(err.Error())
772 | return result, err
773 | }
774 |
775 | var val any
776 | switch req.Type {
777 | case common.ValueTypeBool:
778 | val, err = cast.ToBoolE(reading)
779 | if err != nil {
780 | return nil, fmt.Errorf(castError, req.DeviceResourceName, err)
781 | }
782 | case common.ValueTypeString:
783 | val, err = cast.ToStringE(reading)
784 | if err != nil {
785 | return nil, fmt.Errorf(castError, req.DeviceResourceName, err)
786 | }
787 | case common.ValueTypeUint8:
788 | val, err = cast.ToUint8E(reading)
789 | if err != nil {
790 | return nil, fmt.Errorf(castError, req.DeviceResourceName, err)
791 | }
792 | case common.ValueTypeUint16:
793 | val, err = cast.ToUint16E(reading)
794 | if err != nil {
795 | return nil, fmt.Errorf(castError, req.DeviceResourceName, err)
796 | }
797 | case common.ValueTypeUint32:
798 | val, err = cast.ToUint32E(reading)
799 | if err != nil {
800 | return nil, fmt.Errorf(castError, req.DeviceResourceName, err)
801 | }
802 | case common.ValueTypeUint64:
803 | val, err = cast.ToUint64E(reading)
804 | if err != nil {
805 | return nil, fmt.Errorf(castError, req.DeviceResourceName, err)
806 | }
807 | case common.ValueTypeInt8:
808 | val, err = cast.ToInt8E(reading)
809 | if err != nil {
810 | return nil, fmt.Errorf(castError, req.DeviceResourceName, err)
811 | }
812 | case common.ValueTypeInt16:
813 | val, err = cast.ToInt16E(reading)
814 | if err != nil {
815 | return nil, fmt.Errorf(castError, req.DeviceResourceName, err)
816 | }
817 | case common.ValueTypeInt32:
818 | val, err = cast.ToInt32E(reading)
819 | if err != nil {
820 | return nil, fmt.Errorf(castError, req.DeviceResourceName, err)
821 | }
822 | case common.ValueTypeInt64:
823 | val, err = cast.ToInt64E(reading)
824 | if err != nil {
825 | return nil, fmt.Errorf(castError, req.DeviceResourceName, err)
826 | }
827 | case common.ValueTypeFloat32:
828 | val, err = cast.ToFloat32E(reading)
829 | if err != nil {
830 | return nil, fmt.Errorf(castError, req.DeviceResourceName, err)
831 | }
832 | case common.ValueTypeFloat64:
833 | val, err = cast.ToFloat64E(reading)
834 | if err != nil {
835 | return nil, fmt.Errorf(castError, req.DeviceResourceName, err)
836 | }
837 | case common.ValueTypeObject:
838 | val = reading
839 | default:
840 | return nil, fmt.Errorf("return result fail, none supported value type: %v", req.Type)
841 |
842 | }
843 |
844 | result, err = sdkModel.NewCommandValue(req.DeviceResourceName, req.Type, val)
845 | if err != nil {
846 | return nil, err
847 | }
848 | result.Origin = time.Now().UnixNano()
849 |
850 | return result, nil
851 | }
852 |
853 | func (d *Driver) Start() error {
854 |
855 | return nil
856 | }
857 |
858 | func (d *Driver) Discover() error {
859 | return fmt.Errorf("driver's Discover function isn't implemented")
860 | }
861 |
--------------------------------------------------------------------------------
/internal/driver/driver_test.go:
--------------------------------------------------------------------------------
1 | package driver
2 |
3 | import (
4 | "reflect"
5 | "testing"
6 |
7 | sdkModel "github.com/edgexfoundry/device-sdk-go/v4/pkg/models"
8 | "github.com/edgexfoundry/go-mod-core-contracts/v4/clients/logger"
9 | )
10 |
11 | func TestDriver_getDBInfo(t *testing.T) {
12 | type fields struct {
13 | lc logger.LoggingClient
14 | asyncCh chan<- *sdkModel.AsyncValues
15 | s7Clients map[string]*S7Client
16 | }
17 | type args struct {
18 | variable string
19 | }
20 | var driver fields
21 | driver.lc = logger.NewClient("S7", "Error")
22 | tests := []struct {
23 | name string
24 | fields *fields
25 | args args
26 | wantDbInfo *DBInfo
27 | wantErr bool
28 | }{
29 | {
30 | name: "invalid address-DB1.DBX100",
31 | fields: &driver,
32 | args: args{variable: "DB1.DBX100"},
33 | wantDbInfo: nil,
34 | wantErr: true,
35 | },
36 | {
37 | name: "invalid address-DB1.DBX86.2.1",
38 | fields: &driver,
39 | args: args{variable: "DB1.DBX86.2.1"},
40 | wantDbInfo: nil,
41 | wantErr: true,
42 | },
43 | {
44 | name: "invalid address-DBX100",
45 | fields: &driver,
46 | args: args{variable: "DBX100"},
47 | wantDbInfo: nil,
48 | wantErr: true,
49 | },
50 | {
51 | name: "valid address-DB1.DBX100.0",
52 | fields: &driver,
53 | args: args{variable: "DB1.DBX100.0"},
54 | wantDbInfo: &DBInfo{
55 | Area: 0x84,
56 | DBNumber: 1,
57 | Start: 800,
58 | Amount: 1,
59 | WordLength: s7wlbit,
60 | DBArray: []string{"DB1", "DBX100", "0"},
61 | },
62 | wantErr: false,
63 | },
64 | }
65 | for _, tt := range tests {
66 | t.Run(tt.name, func(t *testing.T) {
67 | s := &Driver{
68 | lc: tt.fields.lc,
69 | asyncCh: tt.fields.asyncCh,
70 | s7Clients: tt.fields.s7Clients,
71 | }
72 | gotDbInfo, err := s.getDBInfo(tt.args.variable)
73 | if (err != nil) != tt.wantErr {
74 | t.Errorf("getDBInfo() error = %v, wantErr %v", err, tt.wantErr)
75 | return
76 | }
77 | if !reflect.DeepEqual(gotDbInfo, tt.wantDbInfo) {
78 | t.Errorf("getDBInfo() gotDbInfo = %v, want %v", gotDbInfo, tt.wantDbInfo)
79 | }
80 | })
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/internal/driver/readingchecker.go:
--------------------------------------------------------------------------------
1 | // -*- Mode: Go; indent-tabs-mode: t -*-
2 | //
3 | // Copyright (C) 2023 YIQISOFT
4 | //
5 | // SPDX-License-Identifier: Apache-2.0
6 |
7 | package driver
8 |
9 | import (
10 | "math"
11 |
12 | "github.com/edgexfoundry/go-mod-core-contracts/v4/common"
13 |
14 | "github.com/spf13/cast"
15 | )
16 |
17 | // checkValueInRange checks value range is valid
18 | func checkValueInRange(valueType string, reading any) bool {
19 | isValid := false
20 |
21 | if valueType == common.ValueTypeString || valueType == common.ValueTypeBool || valueType == common.ValueTypeObject {
22 | return true
23 | }
24 |
25 | if valueType == common.ValueTypeInt8 || valueType == common.ValueTypeInt16 ||
26 | valueType == common.ValueTypeInt32 || valueType == common.ValueTypeInt64 {
27 | val := cast.ToInt64(reading)
28 | isValid = checkIntValueRange(valueType, val)
29 | }
30 |
31 | if valueType == common.ValueTypeUint8 || valueType == common.ValueTypeUint16 ||
32 | valueType == common.ValueTypeUint32 || valueType == common.ValueTypeUint64 {
33 | val := cast.ToUint64(reading)
34 | isValid = checkUintValueRange(valueType, val)
35 | }
36 |
37 | if valueType == common.ValueTypeFloat32 || valueType == common.ValueTypeFloat64 {
38 | val := cast.ToFloat64(reading)
39 | isValid = checkFloatValueRange(valueType, val)
40 | }
41 |
42 | return isValid
43 | }
44 |
45 | func checkUintValueRange(valueType string, val uint64) bool {
46 | var isValid = false
47 | switch valueType {
48 | case common.ValueTypeUint8:
49 | if val <= math.MaxUint8 {
50 | isValid = true
51 | }
52 | case common.ValueTypeUint16:
53 | if val <= math.MaxUint16 {
54 | isValid = true
55 | }
56 | case common.ValueTypeUint32:
57 | if val <= math.MaxUint32 {
58 | isValid = true
59 | }
60 | case common.ValueTypeUint64:
61 | maxiMum := uint64(math.MaxUint64)
62 | if val <= maxiMum {
63 | isValid = true
64 | }
65 | }
66 | return isValid
67 | }
68 |
69 | func checkIntValueRange(valueType string, val int64) bool {
70 | var isValid = false
71 | switch valueType {
72 | case common.ValueTypeInt8:
73 | if val >= math.MinInt8 && val <= math.MaxInt8 {
74 | isValid = true
75 | }
76 | case common.ValueTypeInt16:
77 | if val >= math.MinInt16 && val <= math.MaxInt16 {
78 | isValid = true
79 | }
80 | case common.ValueTypeInt32:
81 | if val >= math.MinInt32 && val <= math.MaxInt32 {
82 | isValid = true
83 | }
84 | case common.ValueTypeInt64:
85 | isValid = true
86 | }
87 | return isValid
88 | }
89 |
90 | func checkFloatValueRange(valueType string, val float64) bool {
91 | var isValid = false
92 | switch valueType {
93 | case common.ValueTypeFloat32:
94 | if !math.IsNaN(val) && math.Abs(val) <= math.MaxFloat32 {
95 | isValid = true
96 | }
97 | case common.ValueTypeFloat64:
98 | if !math.IsNaN(val) && !math.IsInf(val, 0) {
99 | isValid = true
100 | }
101 | }
102 | return isValid
103 | }
104 |
--------------------------------------------------------------------------------
/internal/driver/types.go:
--------------------------------------------------------------------------------
1 | // -*- mode: Go; indent-tabs-mode: t -*-
2 | //
3 | // Copyright (C) 2023 YIQISOFT
4 | //
5 | // SPDX-License-Identifier: Apache-2.0
6 |
7 | package driver
8 |
9 | import (
10 | "github.com/robinson/gos7"
11 | )
12 |
13 | type S7Info struct {
14 | // PLC connection info
15 | Host string
16 | Port int
17 | Rack int
18 | Slot int
19 |
20 | // DB address, start, size
21 | DbAddress int
22 | StartAddress int
23 | ReadSize int
24 |
25 | ConnEstablishingRetry int
26 | ConnRetryWaitTime int
27 | }
28 |
29 | type S7Client struct {
30 | DeviceName string
31 | Client gos7.Client
32 | }
33 |
--------------------------------------------------------------------------------
/internal/driver/utils.go:
--------------------------------------------------------------------------------
1 | // -*- Mode: Go; indent-tabs-mode: t -*-
2 | //
3 | // Copyright (C) 2023 YIQISOFT
4 | //
5 | // SPDX-License-Identifier: Apache-2.0
6 |
7 | package driver
8 |
--------------------------------------------------------------------------------
/version.go:
--------------------------------------------------------------------------------
1 | // -*- Mode: Go; indent-tabs-mode: t -*-
2 | //
3 | // Copyright (C) 2023 YIQISOFT
4 | //
5 | // SPDX-License-Identifier: Apache-2.0
6 |
7 | package device_s7
8 |
9 | // Global version for device-sdk-go
10 | var Version string = "to be replaced by makefile"
11 |
--------------------------------------------------------------------------------