mirror of
https://github.com/chirpstack/chirpstack.git
synced 2025-06-25 02:29:14 +00:00
Compare commits
50 Commits
api/go/v4.
...
dependabot
Author | SHA1 | Date | |
---|---|---|---|
aec51d2229 | |||
8804f774fb | |||
3a0de8196f | |||
46bb01ccdc | |||
26cca09ce8 | |||
c016cd1f7d | |||
1ead82e8a5 | |||
e8d001441c | |||
10e7907251 | |||
39df55afb4 | |||
038e45e8f0 | |||
5cf1120f20 | |||
b8e14058f2 | |||
10731c2be5 | |||
f1d46b1bc9 | |||
c954cd3645 | |||
188ef3d8f3 | |||
0cff864f60 | |||
156f42ab82 | |||
c8b496d33f | |||
8d2faf2d15 | |||
55d9ce0359 | |||
d002f5c97b | |||
9cf12a187c | |||
1b5e5972f4 | |||
330f5dcae0 | |||
92b2439377 | |||
6d084b3b21 | |||
75e9106bbb | |||
4ce4828a78 | |||
9ecf4fef1b | |||
8f9316af2c | |||
1f2a7d390a | |||
990bf57da5 | |||
b336690a65 | |||
7597bcaabf | |||
0ae1294a63 | |||
8e0a29ed55 | |||
5fd57de6ce | |||
d91fb77617 | |||
fa63c306fd | |||
7d1e85e575 | |||
e392f52444 | |||
e30a2e0e77 | |||
b2adac5a49 | |||
ca7b0a2e61 | |||
849d27f148 | |||
5ce35eef5e | |||
236b468aa4 | |||
c130be9dd0 |
4
.github/workflows/main.yml
vendored
4
.github/workflows/main.yml
vendored
@ -28,7 +28,7 @@ jobs:
|
||||
name: Install Nix
|
||||
uses: cachix/install-nix-action@v27
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-24.11
|
||||
nix_path: nixpkgs=channel:nixos-25.05
|
||||
-
|
||||
name: Cargo cache
|
||||
uses: actions/cache@v4
|
||||
@ -69,7 +69,7 @@ jobs:
|
||||
name: Install Nix
|
||||
uses: cachix/install-nix-action@v27
|
||||
with:
|
||||
nix_path: nixpkgs=channel:nixos-24.11
|
||||
nix_path: nixpkgs=channel:nixos-25.05
|
||||
-
|
||||
name: Cargo cache
|
||||
uses: actions/cache@v4
|
||||
|
1037
Cargo.lock
generated
1037
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
2
Makefile
2
Makefile
@ -6,9 +6,7 @@ dist:
|
||||
cd chirpstack && make dist
|
||||
|
||||
# Install dev dependencies
|
||||
# TODO: test latest cargo-deb and move it to shell.nix.
|
||||
dev-dependencies:
|
||||
cargo install cargo-deb --version 1.43.1 --locked
|
||||
cargo install cargo-generate-rpm --version 0.12.1 --locked
|
||||
|
||||
# Set the versions
|
||||
|
7
api/go/go.mod
vendored
7
api/go/go.mod
vendored
@ -1,6 +1,7 @@
|
||||
module github.com/chirpstack/chirpstack/api/go/v4
|
||||
|
||||
go 1.21
|
||||
toolchain go1.24.1
|
||||
|
||||
require (
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240325203815-454cdb8f5daa
|
||||
@ -10,8 +11,8 @@ require (
|
||||
|
||||
require (
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
golang.org/x/net v0.33.0 // indirect
|
||||
golang.org/x/sys v0.28.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
golang.org/x/net v0.38.0 // indirect
|
||||
golang.org/x/sys v0.31.0 // indirect
|
||||
golang.org/x/text v0.23.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240325203815-454cdb8f5daa // indirect
|
||||
)
|
||||
|
12
api/go/go.sum
vendored
12
api/go/go.sum
vendored
@ -2,12 +2,12 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
|
||||
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240325203815-454cdb8f5daa h1:Jt1XW5PaLXF1/ePZrznsh/aAUvI7Adfc3LY1dAKlzRs=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240325203815-454cdb8f5daa/go.mod h1:K4kfzHtI0kqWA79gecJarFtDn/Mls+GxQcg3Zox91Ac=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240325203815-454cdb8f5daa h1:RBgMaUMP+6soRkik4VoN8ojR2nex2TqZwjSSogic+eo=
|
||||
|
2532
api/go/gw/gw.pb.go
vendored
2532
api/go/gw/gw.pb.go
vendored
File diff suppressed because it is too large
Load Diff
8
api/grpc-web/package.json
vendored
8
api/grpc-web/package.json
vendored
@ -1,16 +1,16 @@
|
||||
{
|
||||
"name": "@chirpstack/chirpstack-api-grpc-web",
|
||||
"version": "4.12.0-test.2",
|
||||
"version": "4.13.0-test.1",
|
||||
"description": "Chirpstack gRPC-web API",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"grpc-tools": "^1.12.4",
|
||||
"grpc-tools": "^1.13.0",
|
||||
"ts-protoc-gen": "^0.15.0",
|
||||
"typescript": "^5.1.6"
|
||||
"typescript": "^5.8.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/google-protobuf": "^3.15.12",
|
||||
"google-protobuf": "^3.21.2",
|
||||
"google-protobuf": "^3.21.4",
|
||||
"grpc-web": "^1.5.0"
|
||||
}
|
||||
}
|
||||
|
23
api/grpc-web/yarn.lock
vendored
23
api/grpc-web/yarn.lock
vendored
@ -146,15 +146,20 @@ glob@^7.1.3:
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
google-protobuf@^3.15.5, google-protobuf@^3.21.2:
|
||||
google-protobuf@^3.15.5:
|
||||
version "3.21.2"
|
||||
resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.21.2.tgz#4580a2bea8bbb291ee579d1fefb14d6fa3070ea4"
|
||||
integrity sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==
|
||||
|
||||
grpc-tools@^1.12.4:
|
||||
version "1.12.4"
|
||||
resolved "https://registry.yarnpkg.com/grpc-tools/-/grpc-tools-1.12.4.tgz#a044c9e8157941033ea7a5f144c2dc9dc4501de4"
|
||||
integrity sha512-5+mLAJJma3BjnW/KQp6JBjUMgvu7Mu3dBvBPd1dcbNIb+qiR0817zDpgPjS7gRb+l/8EVNIa3cB02xI9JLToKg==
|
||||
google-protobuf@^3.21.4:
|
||||
version "3.21.4"
|
||||
resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.21.4.tgz#2f933e8b6e5e9f8edde66b7be0024b68f77da6c9"
|
||||
integrity sha512-MnG7N936zcKTco4Jd2PX2U96Kf9PxygAPKBug+74LHzmHXmceN16MmRcdgZv+DGef/S9YvQAfRsNCn4cjf9yyQ==
|
||||
|
||||
grpc-tools@^1.13.0:
|
||||
version "1.13.0"
|
||||
resolved "https://registry.yarnpkg.com/grpc-tools/-/grpc-tools-1.13.0.tgz#a4fea8eebce51fb9fec00055a3e52016dfd5af89"
|
||||
integrity sha512-7CbkJ1yWPfX0nHjbYG58BQThNhbICXBZynzCUxCb3LzX5X9B3hQbRY2STiRgIEiLILlK9fgl0z0QVGwPCdXf5g==
|
||||
dependencies:
|
||||
"@mapbox/node-pre-gyp" "^1.0.5"
|
||||
|
||||
@ -376,10 +381,10 @@ ts-protoc-gen@^0.15.0:
|
||||
dependencies:
|
||||
google-protobuf "^3.15.5"
|
||||
|
||||
typescript@^5.1.6:
|
||||
version "5.4.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.3.tgz#5c6fedd4c87bee01cd7a528a30145521f8e0feff"
|
||||
integrity sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==
|
||||
typescript@^5.8.3:
|
||||
version "5.8.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e"
|
||||
integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==
|
||||
|
||||
util-deprecate@^1.0.1:
|
||||
version "1.0.2"
|
||||
|
2
api/java/build.gradle.kts
vendored
2
api/java/build.gradle.kts
vendored
@ -8,7 +8,7 @@ plugins {
|
||||
}
|
||||
|
||||
group = "io.chirpstack"
|
||||
version = "4.12.0-test.2"
|
||||
version = "4.13.0-test.1"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
12
api/js/package.json
vendored
12
api/js/package.json
vendored
@ -1,17 +1,17 @@
|
||||
{
|
||||
"name": "@chirpstack/chirpstack-api",
|
||||
"version": "4.12.0-test.2",
|
||||
"version": "4.13.0-test.1",
|
||||
"description": "Chirpstack JS and TS API",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"grpc-tools": "^1.12.4",
|
||||
"grpc-tools": "^1.13.0",
|
||||
"ts-protoc-gen": "^0.15.0",
|
||||
"typescript": "^5.1.6"
|
||||
"typescript": "^5.8.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@grpc/grpc-js": "^1.10.4",
|
||||
"@grpc/grpc-js": "^1.13.3",
|
||||
"@mapbox/node-pre-gyp": "^1.0.11",
|
||||
"@types/google-protobuf": "^3.15.6",
|
||||
"google-protobuf": "^3.21.2"
|
||||
"@types/google-protobuf": "^3.15.12",
|
||||
"google-protobuf": "^3.21.4"
|
||||
}
|
||||
}
|
||||
|
39
api/js/yarn.lock
vendored
39
api/js/yarn.lock
vendored
@ -2,10 +2,10 @@
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@grpc/grpc-js@^1.10.4":
|
||||
version "1.10.9"
|
||||
resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.10.9.tgz#468cc1549a3fe37b760a16745fb7685d91f4f10c"
|
||||
integrity sha512-5tcgUctCG0qoNyfChZifz2tJqbRbXVO9J7X6duFcOjY3HUNCxg5D0ZCK7EP9vIcZ0zRpLU9bWkyCqVCLZ46IbQ==
|
||||
"@grpc/grpc-js@^1.13.3":
|
||||
version "1.13.3"
|
||||
resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.13.3.tgz#6ad08d186c2a8651697085f790c5c68eaca45904"
|
||||
integrity sha512-FTXHdOoPbZrBjlVLHuKbDZnsTxXv2BlHF57xw6LuThXacXvtkahEPED0CKMk6obZDf65Hv4k3z62eyPNpvinIg==
|
||||
dependencies:
|
||||
"@grpc/proto-loader" "^0.7.13"
|
||||
"@js-sdsl/ordered-map" "^4.4.2"
|
||||
@ -93,10 +93,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570"
|
||||
integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==
|
||||
|
||||
"@types/google-protobuf@^3.15.6":
|
||||
version "3.15.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/google-protobuf/-/google-protobuf-3.15.6.tgz#674a69493ef2c849b95eafe69167ea59079eb504"
|
||||
integrity sha512-pYVNNJ+winC4aek+lZp93sIKxnXt5qMkuKmaqS3WGuTq0Bw1ZDYNBgzG5kkdtwcv+GmYJGo3yEg6z2cKKAiEdw==
|
||||
"@types/google-protobuf@^3.15.12":
|
||||
version "3.15.12"
|
||||
resolved "https://registry.yarnpkg.com/@types/google-protobuf/-/google-protobuf-3.15.12.tgz#eb2ba0eddd65712211a2b455dc6071d665ccf49b"
|
||||
integrity sha512-40um9QqwHjRS92qnOaDpL7RmDK15NuZYo9HihiJRbYkMQZlWnuH8AdvbMy8/o6lgLmKbDUKa+OALCltHdbOTpQ==
|
||||
|
||||
"@types/node@>=13.7.0":
|
||||
version "20.4.8"
|
||||
@ -265,15 +265,20 @@ glob@^7.1.3:
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
google-protobuf@^3.15.5, google-protobuf@^3.21.2:
|
||||
google-protobuf@^3.15.5:
|
||||
version "3.21.2"
|
||||
resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.21.2.tgz#4580a2bea8bbb291ee579d1fefb14d6fa3070ea4"
|
||||
integrity sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==
|
||||
|
||||
grpc-tools@^1.12.4:
|
||||
version "1.12.4"
|
||||
resolved "https://registry.yarnpkg.com/grpc-tools/-/grpc-tools-1.12.4.tgz#a044c9e8157941033ea7a5f144c2dc9dc4501de4"
|
||||
integrity sha512-5+mLAJJma3BjnW/KQp6JBjUMgvu7Mu3dBvBPd1dcbNIb+qiR0817zDpgPjS7gRb+l/8EVNIa3cB02xI9JLToKg==
|
||||
google-protobuf@^3.21.4:
|
||||
version "3.21.4"
|
||||
resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.21.4.tgz#2f933e8b6e5e9f8edde66b7be0024b68f77da6c9"
|
||||
integrity sha512-MnG7N936zcKTco4Jd2PX2U96Kf9PxygAPKBug+74LHzmHXmceN16MmRcdgZv+DGef/S9YvQAfRsNCn4cjf9yyQ==
|
||||
|
||||
grpc-tools@^1.13.0:
|
||||
version "1.13.0"
|
||||
resolved "https://registry.yarnpkg.com/grpc-tools/-/grpc-tools-1.13.0.tgz#a4fea8eebce51fb9fec00055a3e52016dfd5af89"
|
||||
integrity sha512-7CbkJ1yWPfX0nHjbYG58BQThNhbICXBZynzCUxCb3LzX5X9B3hQbRY2STiRgIEiLILlK9fgl0z0QVGwPCdXf5g==
|
||||
dependencies:
|
||||
"@mapbox/node-pre-gyp" "^1.0.5"
|
||||
|
||||
@ -523,10 +528,10 @@ ts-protoc-gen@^0.15.0:
|
||||
dependencies:
|
||||
google-protobuf "^3.15.5"
|
||||
|
||||
typescript@^5.1.6:
|
||||
version "5.1.6"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.1.6.tgz#02f8ac202b6dad2c0dd5e0913745b47a37998274"
|
||||
integrity sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==
|
||||
typescript@^5.8.3:
|
||||
version "5.8.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e"
|
||||
integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==
|
||||
|
||||
util-deprecate@^1.0.1:
|
||||
version "1.0.2"
|
||||
|
2
api/kotlin/build.gradle.kts
vendored
2
api/kotlin/build.gradle.kts
vendored
@ -9,7 +9,7 @@ plugins {
|
||||
}
|
||||
|
||||
group = "io.chirpstack"
|
||||
version = "4.12.0-test.2"
|
||||
version = "4.13.0-test.1"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
2
api/php/composer.json
vendored
2
api/php/composer.json
vendored
@ -3,7 +3,7 @@
|
||||
"description": "Chirpstack PHP API",
|
||||
"license": "MIT",
|
||||
"type": "library",
|
||||
"version": "4.12.0-test.2",
|
||||
"version": "4.13.0-test.1",
|
||||
"require": {
|
||||
"php": ">=7.0.0",
|
||||
"grpc/grpc": "^v1.57.0",
|
||||
|
2
api/proto/common/common.proto
vendored
2
api/proto/common/common.proto
vendored
@ -67,7 +67,7 @@ enum Region {
|
||||
ISM2400 = 11;
|
||||
}
|
||||
|
||||
enum MType {
|
||||
enum FType {
|
||||
// JoinRequest.
|
||||
JOIN_REQUEST = 0;
|
||||
|
||||
|
125
api/proto/gw/gw.proto
vendored
125
api/proto/gw/gw.proto
vendored
@ -104,6 +104,82 @@ enum TxAckStatus {
|
||||
DUTY_CYCLE_OVERFLOW = 11;
|
||||
}
|
||||
|
||||
// Gateway events as reported by the ChirpStack Concentratord ZMQ interface.
|
||||
message Event {
|
||||
oneof event {
|
||||
// Uplink frame.
|
||||
UplinkFrame uplink_frame = 1;
|
||||
|
||||
// Gateway stats.
|
||||
GatewayStats gateway_stats = 2;
|
||||
|
||||
// Gateway Mesh Event.
|
||||
MeshEvent mesh = 3;
|
||||
}
|
||||
}
|
||||
|
||||
// Commands that can be sent to the ChirpStack Concentratord ZMQ interface.
|
||||
message Command {
|
||||
oneof command {
|
||||
// Downlink frame.
|
||||
DownlinkFrame send_downlink_frame = 1;
|
||||
|
||||
// Gateway configuration.
|
||||
GatewayConfiguration set_gateway_configuration = 2;
|
||||
|
||||
// Get Gateway ID.
|
||||
GetGatewayIdRequest get_gateway_id = 3;
|
||||
|
||||
// Get location.
|
||||
GetLocationRequest get_location = 4;
|
||||
|
||||
// Gateway Mesh Command.
|
||||
MeshCommand mesh = 5;
|
||||
}
|
||||
}
|
||||
|
||||
message MeshEvent {
|
||||
// Gateway ID (of the Border Gateway).
|
||||
string gateway_id = 1;
|
||||
|
||||
// Relay ID.
|
||||
string relay_id = 2;
|
||||
|
||||
// Timestamp (second precision).
|
||||
google.protobuf.Timestamp time = 3;
|
||||
|
||||
// Mesh events.
|
||||
repeated MeshEventItem events = 4;
|
||||
}
|
||||
|
||||
message MeshEventItem {
|
||||
oneof event {
|
||||
// Proprietary Mesh event.
|
||||
MeshEventProprietary proprietary = 1;
|
||||
|
||||
// Mesh heartbeat.
|
||||
MeshEventHeartbeat heartbeat = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message MeshCommand {
|
||||
// Gateway ID (of the Border Gateway).
|
||||
string gateway_id = 1;
|
||||
|
||||
// Relay ID.
|
||||
string relay_id = 2;
|
||||
|
||||
// Mesh events.
|
||||
repeated MeshCommandItem commands = 3;
|
||||
}
|
||||
|
||||
message MeshCommandItem {
|
||||
oneof command {
|
||||
// Proprietary Mesh command.
|
||||
MeshCommandProprietary proprietary = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message Modulation {
|
||||
oneof parameters {
|
||||
// LoRa modulation information.
|
||||
@ -611,6 +687,23 @@ message GatewayConfiguration {
|
||||
google.protobuf.Duration stats_interval = 4;
|
||||
}
|
||||
|
||||
message GetGatewayIdRequest {}
|
||||
|
||||
message GetGatewayIdResponse {
|
||||
// Gateway ID.
|
||||
string gateway_id = 1;
|
||||
}
|
||||
|
||||
message GetLocationRequest {}
|
||||
|
||||
message GetLocationResponse {
|
||||
// Location.
|
||||
common.Location location = 1;
|
||||
|
||||
// Last updated at.
|
||||
google.protobuf.Timestamp updated_at = 2;
|
||||
}
|
||||
|
||||
message ChannelConfiguration {
|
||||
// Frequency (Hz).
|
||||
uint32 frequency = 1;
|
||||
@ -751,21 +844,13 @@ message ConnState {
|
||||
}
|
||||
|
||||
// Gateway Mesh heartbeat (sent periodically by the Relay Gateways).
|
||||
message MeshHeartbeat {
|
||||
// Gateway ID (of the Border Gateway).
|
||||
string gateway_id = 1;
|
||||
|
||||
// Relay ID.
|
||||
string relay_id = 2;
|
||||
|
||||
// Timestamp (second precision).
|
||||
google.protobuf.Timestamp time = 3;
|
||||
message MeshEventHeartbeat {
|
||||
|
||||
// Relay path.
|
||||
repeated MeshHeartbeatRelayPath relay_path = 4;
|
||||
repeated MeshEventHeartbeatRelayPath relay_path = 4;
|
||||
}
|
||||
|
||||
message MeshHeartbeatRelayPath {
|
||||
message MeshEventHeartbeatRelayPath {
|
||||
// Relay ID.
|
||||
string relay_id = 1;
|
||||
|
||||
@ -775,3 +860,21 @@ message MeshHeartbeatRelayPath {
|
||||
// SNR.
|
||||
int32 snr = 3;
|
||||
}
|
||||
|
||||
// Proprietary mesh event.
|
||||
message MeshEventProprietary {
|
||||
// Event type.
|
||||
uint32 event_type = 1;
|
||||
|
||||
// Payload.
|
||||
bytes payload = 2;
|
||||
}
|
||||
|
||||
// Proprietary mesh command.
|
||||
message MeshCommandProprietary {
|
||||
// Command type.
|
||||
uint32 command_type = 1;
|
||||
|
||||
// Payload.
|
||||
bytes payload = 2;
|
||||
}
|
||||
|
3
api/proto/internal/internal.proto
vendored
3
api/proto/internal/internal.proto
vendored
@ -142,6 +142,9 @@ message DeviceSession {
|
||||
|
||||
// Relay state.
|
||||
Relay relay = 41;
|
||||
|
||||
// Pending mac-commands.
|
||||
map<uint32, bytes> mac_command_pending = 43;
|
||||
}
|
||||
|
||||
message UplinkAdrHistory {
|
||||
|
8
api/proto/stream/frame.proto
vendored
8
api/proto/stream/frame.proto
vendored
@ -24,8 +24,8 @@ message UplinkFrameLog {
|
||||
// RX meta-data.
|
||||
repeated gw.UplinkRxInfo rx_info = 3;
|
||||
|
||||
// Message type.
|
||||
common.MType m_type = 4;
|
||||
// Frame type.
|
||||
common.FType f_type = 4;
|
||||
|
||||
// Device address (optional).
|
||||
string dev_addr = 5;
|
||||
@ -59,8 +59,8 @@ message DownlinkFrameLog {
|
||||
// Gateway ID (EUI64).
|
||||
string gateway_id = 5;
|
||||
|
||||
// Message type.
|
||||
common.MType m_type = 6;
|
||||
// Frame type.
|
||||
common.FType f_type = 6;
|
||||
|
||||
// Device address (optional).
|
||||
string dev_addr = 7;
|
||||
|
8
api/proto/stream/meta.proto
vendored
8
api/proto/stream/meta.proto
vendored
@ -32,8 +32,8 @@ message UplinkMeta {
|
||||
// Application payload byte count.
|
||||
uint32 application_payload_byte_count = 6;
|
||||
|
||||
// Message type.
|
||||
common.MType message_type = 7;
|
||||
// Frame type.
|
||||
common.FType frame_type = 7;
|
||||
}
|
||||
|
||||
message DownlinkMeta {
|
||||
@ -55,8 +55,8 @@ message DownlinkMeta {
|
||||
// Application payload byte count.
|
||||
uint32 application_payload_byte_count = 6;
|
||||
|
||||
// Message type.
|
||||
common.MType message_type = 7;
|
||||
// Frame type.
|
||||
common.FType frame_type = 7;
|
||||
|
||||
// Gateway ID (EUI64).
|
||||
string gateway_id = 8;
|
||||
|
2
api/python/src/setup.py
vendored
2
api/python/src/setup.py
vendored
@ -18,7 +18,7 @@ CLASSIFIERS = [
|
||||
|
||||
setup(
|
||||
name='chirpstack-api',
|
||||
version = "4.12.0-test.2",
|
||||
version = "4.13.0-test.1",
|
||||
url='https://github.com/brocaar/chirpstack-api',
|
||||
author='Orne Brocaar',
|
||||
author_email='info@brocaar.com',
|
||||
|
6
api/rust/Cargo.toml
vendored
6
api/rust/Cargo.toml
vendored
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "chirpstack_api"
|
||||
description = "ChirpStack Protobuf / gRPC API definitions."
|
||||
version = "4.12.0-test.2"
|
||||
version = "4.13.0-test.1"
|
||||
authors = ["Orne Brocaar <info@brocaar.com>"]
|
||||
license = "MIT"
|
||||
homepage = "https://www.chirpstack.io"
|
||||
@ -19,7 +19,7 @@
|
||||
prost-types = "0.13"
|
||||
hex = "0.4"
|
||||
rand = "0.9"
|
||||
tonic = { version = "0.12", features = [
|
||||
tonic = { version = "0.13", features = [
|
||||
"codegen",
|
||||
"prost",
|
||||
], default-features = false, optional = true }
|
||||
@ -29,7 +29,7 @@
|
||||
serde = { version = "1.0", optional = true }
|
||||
|
||||
[build-dependencies]
|
||||
tonic-build = { version = "0.12", features = [
|
||||
tonic-build = { version = "0.13", features = [
|
||||
"prost",
|
||||
], default-features = false }
|
||||
pbjson-build = "0.7"
|
||||
|
@ -67,7 +67,7 @@ enum Region {
|
||||
ISM2400 = 11;
|
||||
}
|
||||
|
||||
enum MType {
|
||||
enum FType {
|
||||
// JoinRequest.
|
||||
JOIN_REQUEST = 0;
|
||||
|
||||
|
125
api/rust/proto/chirpstack/gw/gw.proto
vendored
125
api/rust/proto/chirpstack/gw/gw.proto
vendored
@ -104,6 +104,82 @@ enum TxAckStatus {
|
||||
DUTY_CYCLE_OVERFLOW = 11;
|
||||
}
|
||||
|
||||
// Gateway events as reported by the ChirpStack Concentratord ZMQ interface.
|
||||
message Event {
|
||||
oneof event {
|
||||
// Uplink frame.
|
||||
UplinkFrame uplink_frame = 1;
|
||||
|
||||
// Gateway stats.
|
||||
GatewayStats gateway_stats = 2;
|
||||
|
||||
// Gateway Mesh Event.
|
||||
MeshEvent mesh = 3;
|
||||
}
|
||||
}
|
||||
|
||||
// Commands that can be sent to the ChirpStack Concentratord ZMQ interface.
|
||||
message Command {
|
||||
oneof command {
|
||||
// Downlink frame.
|
||||
DownlinkFrame send_downlink_frame = 1;
|
||||
|
||||
// Gateway configuration.
|
||||
GatewayConfiguration set_gateway_configuration = 2;
|
||||
|
||||
// Get Gateway ID.
|
||||
GetGatewayIdRequest get_gateway_id = 3;
|
||||
|
||||
// Get location.
|
||||
GetLocationRequest get_location = 4;
|
||||
|
||||
// Gateway Mesh Command.
|
||||
MeshCommand mesh = 5;
|
||||
}
|
||||
}
|
||||
|
||||
message MeshEvent {
|
||||
// Gateway ID (of the Border Gateway).
|
||||
string gateway_id = 1;
|
||||
|
||||
// Relay ID.
|
||||
string relay_id = 2;
|
||||
|
||||
// Timestamp (second precision).
|
||||
google.protobuf.Timestamp time = 3;
|
||||
|
||||
// Mesh events.
|
||||
repeated MeshEventItem events = 4;
|
||||
}
|
||||
|
||||
message MeshEventItem {
|
||||
oneof event {
|
||||
// Proprietary Mesh event.
|
||||
MeshEventProprietary proprietary = 1;
|
||||
|
||||
// Mesh heartbeat.
|
||||
MeshEventHeartbeat heartbeat = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message MeshCommand {
|
||||
// Gateway ID (of the Border Gateway).
|
||||
string gateway_id = 1;
|
||||
|
||||
// Relay ID.
|
||||
string relay_id = 2;
|
||||
|
||||
// Mesh events.
|
||||
repeated MeshCommandItem commands = 3;
|
||||
}
|
||||
|
||||
message MeshCommandItem {
|
||||
oneof command {
|
||||
// Proprietary Mesh command.
|
||||
MeshCommandProprietary proprietary = 1;
|
||||
}
|
||||
}
|
||||
|
||||
message Modulation {
|
||||
oneof parameters {
|
||||
// LoRa modulation information.
|
||||
@ -611,6 +687,23 @@ message GatewayConfiguration {
|
||||
google.protobuf.Duration stats_interval = 4;
|
||||
}
|
||||
|
||||
message GetGatewayIdRequest {}
|
||||
|
||||
message GetGatewayIdResponse {
|
||||
// Gateway ID.
|
||||
string gateway_id = 1;
|
||||
}
|
||||
|
||||
message GetLocationRequest {}
|
||||
|
||||
message GetLocationResponse {
|
||||
// Location.
|
||||
common.Location location = 1;
|
||||
|
||||
// Last updated at.
|
||||
google.protobuf.Timestamp updated_at = 2;
|
||||
}
|
||||
|
||||
message ChannelConfiguration {
|
||||
// Frequency (Hz).
|
||||
uint32 frequency = 1;
|
||||
@ -751,21 +844,13 @@ message ConnState {
|
||||
}
|
||||
|
||||
// Gateway Mesh heartbeat (sent periodically by the Relay Gateways).
|
||||
message MeshHeartbeat {
|
||||
// Gateway ID (of the Border Gateway).
|
||||
string gateway_id = 1;
|
||||
|
||||
// Relay ID.
|
||||
string relay_id = 2;
|
||||
|
||||
// Timestamp (second precision).
|
||||
google.protobuf.Timestamp time = 3;
|
||||
message MeshEventHeartbeat {
|
||||
|
||||
// Relay path.
|
||||
repeated MeshHeartbeatRelayPath relay_path = 4;
|
||||
repeated MeshEventHeartbeatRelayPath relay_path = 4;
|
||||
}
|
||||
|
||||
message MeshHeartbeatRelayPath {
|
||||
message MeshEventHeartbeatRelayPath {
|
||||
// Relay ID.
|
||||
string relay_id = 1;
|
||||
|
||||
@ -775,3 +860,21 @@ message MeshHeartbeatRelayPath {
|
||||
// SNR.
|
||||
int32 snr = 3;
|
||||
}
|
||||
|
||||
// Proprietary mesh event.
|
||||
message MeshEventProprietary {
|
||||
// Event type.
|
||||
uint32 event_type = 1;
|
||||
|
||||
// Payload.
|
||||
bytes payload = 2;
|
||||
}
|
||||
|
||||
// Proprietary mesh command.
|
||||
message MeshCommandProprietary {
|
||||
// Command type.
|
||||
uint32 command_type = 1;
|
||||
|
||||
// Payload.
|
||||
bytes payload = 2;
|
||||
}
|
||||
|
@ -142,6 +142,9 @@ message DeviceSession {
|
||||
|
||||
// Relay state.
|
||||
Relay relay = 41;
|
||||
|
||||
// Pending mac-commands.
|
||||
map<uint32, bytes> mac_command_pending = 43;
|
||||
}
|
||||
|
||||
message UplinkAdrHistory {
|
||||
|
8
api/rust/proto/chirpstack/stream/frame.proto
vendored
8
api/rust/proto/chirpstack/stream/frame.proto
vendored
@ -24,8 +24,8 @@ message UplinkFrameLog {
|
||||
// RX meta-data.
|
||||
repeated gw.UplinkRxInfo rx_info = 3;
|
||||
|
||||
// Message type.
|
||||
common.MType m_type = 4;
|
||||
// Frame type.
|
||||
common.FType f_type = 4;
|
||||
|
||||
// Device address (optional).
|
||||
string dev_addr = 5;
|
||||
@ -59,8 +59,8 @@ message DownlinkFrameLog {
|
||||
// Gateway ID (EUI64).
|
||||
string gateway_id = 5;
|
||||
|
||||
// Message type.
|
||||
common.MType m_type = 6;
|
||||
// Frame type.
|
||||
common.FType f_type = 6;
|
||||
|
||||
// Device address (optional).
|
||||
string dev_addr = 7;
|
||||
|
8
api/rust/proto/chirpstack/stream/meta.proto
vendored
8
api/rust/proto/chirpstack/stream/meta.proto
vendored
@ -32,8 +32,8 @@ message UplinkMeta {
|
||||
// Application payload byte count.
|
||||
uint32 application_payload_byte_count = 6;
|
||||
|
||||
// Message type.
|
||||
common.MType message_type = 7;
|
||||
// Frame type.
|
||||
common.FType frame_type = 7;
|
||||
}
|
||||
|
||||
message DownlinkMeta {
|
||||
@ -55,8 +55,8 @@ message DownlinkMeta {
|
||||
// Application payload byte count.
|
||||
uint32 application_payload_byte_count = 6;
|
||||
|
||||
// Message type.
|
||||
common.MType message_type = 7;
|
||||
// Frame type.
|
||||
common.FType frame_type = 7;
|
||||
|
||||
// Gateway ID (EUI64).
|
||||
string gateway_id = 8;
|
||||
|
18
api/rust/src/common.rs
vendored
18
api/rust/src/common.rs
vendored
@ -7,17 +7,17 @@ include!(concat!(env!("OUT_DIR"), "/common/common.rs"));
|
||||
include!(concat!(env!("OUT_DIR"), "/common/common.serde.rs"));
|
||||
|
||||
#[allow(clippy::from_over_into)]
|
||||
impl Into<String> for MType {
|
||||
impl Into<String> for FType {
|
||||
fn into(self) -> String {
|
||||
match self {
|
||||
MType::JoinRequest => "JoinRequest",
|
||||
MType::JoinAccept => "JoinAccept",
|
||||
MType::UnconfirmedDataUp => "UnconfirmedDataUp",
|
||||
MType::UnconfirmedDataDown => "UnconfirmedDataDown",
|
||||
MType::ConfirmedDataUp => "ConfirmedDataUp",
|
||||
MType::ConfirmedDataDown => "ConfirmedDataDown",
|
||||
MType::RejoinRequest => "RejoinRequest",
|
||||
MType::Proprietary => "Proprietary",
|
||||
FType::JoinRequest => "JoinRequest",
|
||||
FType::JoinAccept => "JoinAccept",
|
||||
FType::UnconfirmedDataUp => "UnconfirmedDataUp",
|
||||
FType::UnconfirmedDataDown => "UnconfirmedDataDown",
|
||||
FType::ConfirmedDataUp => "ConfirmedDataUp",
|
||||
FType::ConfirmedDataDown => "ConfirmedDataDown",
|
||||
FType::RejoinRequest => "RejoinRequest",
|
||||
FType::Proprietary => "Proprietary",
|
||||
}
|
||||
.to_string()
|
||||
}
|
||||
|
9
api/rust/src/lib.rs
vendored
9
api/rust/src/lib.rs
vendored
@ -1,14 +1,17 @@
|
||||
pub use prost;
|
||||
pub use prost_types;
|
||||
|
||||
#[cfg(feature = "json")]
|
||||
pub use pbjson_types;
|
||||
pub use prost;
|
||||
#[cfg(feature = "api")]
|
||||
pub use tonic;
|
||||
|
||||
#[cfg(feature = "api")]
|
||||
pub mod api;
|
||||
#[cfg(feature = "internal")]
|
||||
pub mod internal;
|
||||
|
||||
pub mod common;
|
||||
pub mod gw;
|
||||
pub mod integration;
|
||||
#[cfg(feature = "internal")]
|
||||
pub mod internal;
|
||||
pub mod stream;
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "backend"
|
||||
version = "4.12.0-test.2"
|
||||
version = "4.13.0-test.1"
|
||||
authors = ["Orne Brocaar <info@brocaar.com>"]
|
||||
edition = "2018"
|
||||
publish = false
|
||||
|
@ -3,14 +3,14 @@
|
||||
description = "Library for building external ChirpStack integrations"
|
||||
homepage = "https://www.chirpstack.io/"
|
||||
license = "MIT"
|
||||
version = "4.12.0-test.2"
|
||||
version = "4.13.0-test.1"
|
||||
authors = ["Orne Brocaar <info@brocaar.com>"]
|
||||
edition = "2021"
|
||||
repository = "https://github.com/chirpstack/chirpstack"
|
||||
|
||||
[dependencies]
|
||||
chirpstack_api = { path = "../api/rust", version = "4.12.0-test.2" }
|
||||
redis = { version = "0.29", features = [
|
||||
chirpstack_api = { path = "../api/rust", version = "4.13.0-test.1" }
|
||||
redis = { version = "0.31", features = [
|
||||
"cluster-async",
|
||||
"tokio-rustls-comp",
|
||||
] }
|
||||
@ -24,6 +24,5 @@
|
||||
async-trait = "0.1"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
tokio = { version = "1.44", features = ["macros", "rt-multi-thread"] }
|
||||
lazy_static = "1.5"
|
||||
serde_json = "1.0"
|
||||
toml = "0.8"
|
||||
|
@ -1,8 +1,6 @@
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
|
||||
use std::io::Cursor;
|
||||
use std::str::FromStr;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use anyhow::Result;
|
||||
use async_trait::async_trait;
|
||||
@ -13,10 +11,8 @@ use tracing_subscriber::{filter, prelude::*};
|
||||
|
||||
use chirpstack_api::{integration as integration_pb, prost::Message};
|
||||
|
||||
lazy_static! {
|
||||
static ref INTEGRATION: RwLock<Option<Box<dyn IntegrationTrait + Sync + Send>>> =
|
||||
RwLock::new(None);
|
||||
}
|
||||
static INTEGRATION: LazyLock<RwLock<Option<Box<dyn IntegrationTrait + Sync + Send>>>> =
|
||||
LazyLock::new(|| RwLock::new(None));
|
||||
|
||||
#[derive(Default, Deserialize, Clone)]
|
||||
#[serde(default)]
|
||||
@ -203,7 +199,7 @@ impl Integration {
|
||||
|
||||
for stream_key in &srr.keys {
|
||||
for stream_id in &stream_key.ids {
|
||||
redis::cmd("XACK")
|
||||
let _: () = redis::cmd("XACK")
|
||||
.arg(&key)
|
||||
.arg(&self.consumer_group)
|
||||
.arg(&stream_id.id)
|
||||
|
@ -3,7 +3,7 @@
|
||||
description = "ChirpStack is an open-source LoRaWAN(TM) Network Server"
|
||||
repository = "https://github.com/chirpstack/chirpstack"
|
||||
homepage = "https://www.chirpstack.io/"
|
||||
version = "4.12.0-test.2"
|
||||
version = "4.13.0-test.1"
|
||||
authors = ["Orne Brocaar <info@brocaar.com>"]
|
||||
edition = "2021"
|
||||
publish = false
|
||||
@ -34,8 +34,8 @@
|
||||
tokio-postgres = { version = "0.7", optional = true }
|
||||
tokio-postgres-rustls = { version = "0.13", optional = true }
|
||||
bigdecimal = "0.4"
|
||||
redis = { version = "0.29", features = ["tls-rustls", "tokio-rustls-comp"] }
|
||||
deadpool-redis = { version = "0.20", features = ["cluster", "serde"] }
|
||||
redis = { version = "0.31", features = ["tls-rustls", "tokio-rustls-comp"] }
|
||||
deadpool-redis = { version = "0.21", features = ["cluster", "serde"] }
|
||||
|
||||
# Logging
|
||||
tracing = "0.1"
|
||||
@ -78,9 +78,9 @@
|
||||
] }
|
||||
|
||||
# gRPC and Protobuf
|
||||
tonic = "0.12"
|
||||
tonic-web = "0.12"
|
||||
tonic-reflection = "0.12"
|
||||
tonic = "0.13"
|
||||
tonic-web = "0.13"
|
||||
tonic-reflection = "0.13"
|
||||
tokio = { version = "1.44", features = ["macros", "rt-multi-thread"] }
|
||||
tokio-stream = "0.1"
|
||||
prost-types = "0.13"
|
||||
@ -95,7 +95,7 @@
|
||||
futures-util = "0.3"
|
||||
http = "1.3"
|
||||
http-body = "1.0"
|
||||
rust-embed = "8.6"
|
||||
rust-embed = "8.7"
|
||||
mime_guess = "2.0"
|
||||
tower-http = { version = "0.6", features = ["trace", "auth"] }
|
||||
|
||||
@ -137,8 +137,7 @@
|
||||
] }
|
||||
|
||||
# Misc
|
||||
lazy_static = "1.5"
|
||||
uuid = { version = "1.16", features = ["v4", "serde"] }
|
||||
uuid = { version = "1.17", features = ["v4", "serde"] }
|
||||
chrono = "0.4"
|
||||
async-trait = "0.1"
|
||||
aes = "0.8"
|
||||
@ -146,8 +145,8 @@
|
||||
base64 = "0.22"
|
||||
async-recursion = "1.1"
|
||||
regex = "1.11"
|
||||
petgraph = "0.7"
|
||||
prometheus-client = "0.22"
|
||||
petgraph = "0.8"
|
||||
prometheus-client = "0.23"
|
||||
pin-project = "1.1"
|
||||
scoped-futures = { version = "0.1", features = ["std"] }
|
||||
signal-hook = "0.3"
|
||||
|
@ -26,7 +26,7 @@ insert into "user" (
|
||||
password_hash,
|
||||
note
|
||||
) values (
|
||||
'05244f12-6daf-4e1f-8315-c66783a0ab56',
|
||||
gen_random_uuid(),
|
||||
now(),
|
||||
now(),
|
||||
true,
|
||||
@ -63,7 +63,7 @@ insert into "tenant" (
|
||||
max_gateway_count,
|
||||
private_gateways
|
||||
) values (
|
||||
'52f14cd4-c6f1-4fbd-8f87-4025e1d49242',
|
||||
gen_random_uuid(),
|
||||
now(),
|
||||
now(),
|
||||
'ChirpStack',
|
||||
|
@ -1,3 +1,6 @@
|
||||
alter table device
|
||||
drop column app_layer_params;
|
||||
|
||||
alter table device_keys
|
||||
drop column gen_app_key;
|
||||
|
||||
|
@ -73,3 +73,9 @@ alter table device_keys
|
||||
|
||||
alter table device_keys
|
||||
alter column gen_app_key drop default;
|
||||
|
||||
alter table device
|
||||
add column app_layer_params jsonb not null default '{}';
|
||||
|
||||
alter table device
|
||||
alter column app_layer_params drop default;
|
||||
|
@ -1,3 +1,6 @@
|
||||
alter table device
|
||||
drop column app_layer_params;
|
||||
|
||||
alter table device_keys
|
||||
drop column gen_app_key;
|
||||
|
||||
|
@ -70,3 +70,6 @@ create index idx_fuota_deployment_job_scheduler_run_after on fuota_deployment_jo
|
||||
|
||||
alter table device_keys
|
||||
add column gen_app_key blob not null default x'00000000000000000000000000000000';
|
||||
|
||||
alter table device
|
||||
add column app_layer_params text not null default '{}';
|
||||
|
@ -1,4 +1,5 @@
|
||||
use std::collections::HashMap;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use anyhow::Result;
|
||||
use async_trait::async_trait;
|
||||
@ -14,10 +15,8 @@ pub mod lora_lr_fhss;
|
||||
pub mod lr_fhss;
|
||||
pub mod plugin;
|
||||
|
||||
lazy_static! {
|
||||
static ref ADR_ALGORITHMS: RwLock<HashMap<String, Box<dyn Handler + Sync + Send>>> =
|
||||
RwLock::new(HashMap::new());
|
||||
}
|
||||
static ADR_ALGORITHMS: LazyLock<RwLock<HashMap<String, Box<dyn Handler + Sync + Send>>>> =
|
||||
LazyLock::new(|| RwLock::new(HashMap::new()));
|
||||
|
||||
pub async fn setup() -> Result<()> {
|
||||
info!("Setting up adr algorithms");
|
||||
|
@ -2010,7 +2010,7 @@ pub mod test {
|
||||
let mut create_req = Request::new(create_req);
|
||||
create_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let create_resp = service.create(create_req).await.unwrap();
|
||||
let create_resp = create_resp.get_ref();
|
||||
|
||||
@ -2021,7 +2021,7 @@ pub mod test {
|
||||
let mut get_req = Request::new(get_req);
|
||||
get_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let get_resp = service.get(get_req).await.unwrap();
|
||||
assert_eq!(
|
||||
Some(api::Application {
|
||||
@ -2045,7 +2045,7 @@ pub mod test {
|
||||
let mut up_req = Request::new(up_req);
|
||||
up_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let _ = service.update(up_req).await.unwrap();
|
||||
|
||||
//get
|
||||
@ -2055,7 +2055,7 @@ pub mod test {
|
||||
let mut get_req = Request::new(get_req);
|
||||
get_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let get_resp = service.get(get_req).await.unwrap();
|
||||
assert_eq!(
|
||||
Some(api::Application {
|
||||
@ -2077,7 +2077,7 @@ pub mod test {
|
||||
let mut list_req = Request::new(list_req);
|
||||
list_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let list_resp = service.list(list_req).await.unwrap();
|
||||
assert_eq!(1, list_resp.get_ref().total_count);
|
||||
assert_eq!(1, list_resp.get_ref().result.len());
|
||||
@ -2089,7 +2089,7 @@ pub mod test {
|
||||
let mut del_req = Request::new(del_req);
|
||||
del_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let _ = service.delete(del_req).await.unwrap();
|
||||
|
||||
let del_req = api::DeleteApplicationRequest {
|
||||
@ -2098,7 +2098,7 @@ pub mod test {
|
||||
let mut del_req = Request::new(del_req);
|
||||
del_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let del_resp = service.delete(del_req).await;
|
||||
assert!(del_resp.is_err());
|
||||
}
|
||||
|
@ -2483,7 +2483,7 @@ pub mod test {
|
||||
|
||||
tenant::add_user(tenant::TenantUser {
|
||||
tenant_id: tenant_a.id,
|
||||
user_id: tenant_user.id.into(),
|
||||
user_id: tenant_user.id,
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
@ -2491,7 +2491,7 @@ pub mod test {
|
||||
|
||||
tenant::add_user(tenant::TenantUser {
|
||||
tenant_id: tenant_a.id,
|
||||
user_id: tenant_admin.id.into(),
|
||||
user_id: tenant_admin.id,
|
||||
is_admin: true,
|
||||
..Default::default()
|
||||
})
|
||||
@ -2727,7 +2727,7 @@ pub mod test {
|
||||
|
||||
tenant::add_user(tenant::TenantUser {
|
||||
tenant_id: tenant_a.id,
|
||||
user_id: tenant_admin.id.into(),
|
||||
user_id: tenant_admin.id,
|
||||
is_admin: true,
|
||||
..Default::default()
|
||||
})
|
||||
@ -2735,21 +2735,21 @@ pub mod test {
|
||||
.unwrap();
|
||||
tenant::add_user(tenant::TenantUser {
|
||||
tenant_id: tenant_a.id,
|
||||
user_id: tenant_user.id.into(),
|
||||
user_id: tenant_user.id,
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
tenant::add_user(tenant::TenantUser {
|
||||
tenant_id: api_key_tenant.tenant_id.unwrap().into(),
|
||||
user_id: tenant_user.id.into(),
|
||||
tenant_id: api_key_tenant.tenant_id.unwrap(),
|
||||
user_id: tenant_user.id,
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
tenant::add_user(tenant::TenantUser {
|
||||
tenant_id: tenant_a.id,
|
||||
user_id: tenant_user_other.id.into(),
|
||||
user_id: tenant_user_other.id,
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
@ -3091,7 +3091,7 @@ pub mod test {
|
||||
|
||||
tenant::add_user(tenant::TenantUser {
|
||||
tenant_id: tenant_a.id,
|
||||
user_id: tenant_admin.id.into(),
|
||||
user_id: tenant_admin.id,
|
||||
is_admin: true,
|
||||
..Default::default()
|
||||
})
|
||||
@ -3099,7 +3099,7 @@ pub mod test {
|
||||
.unwrap();
|
||||
tenant::add_user(tenant::TenantUser {
|
||||
tenant_id: tenant_a.id,
|
||||
user_id: tenant_device_admin.id.into(),
|
||||
user_id: tenant_device_admin.id,
|
||||
is_device_admin: true,
|
||||
..Default::default()
|
||||
})
|
||||
@ -3107,7 +3107,7 @@ pub mod test {
|
||||
.unwrap();
|
||||
tenant::add_user(tenant::TenantUser {
|
||||
tenant_id: tenant_a.id,
|
||||
user_id: tenant_gateway_admin.id.into(),
|
||||
user_id: tenant_gateway_admin.id,
|
||||
is_gateway_admin: true,
|
||||
..Default::default()
|
||||
})
|
||||
@ -3115,7 +3115,7 @@ pub mod test {
|
||||
.unwrap();
|
||||
tenant::add_user(tenant::TenantUser {
|
||||
tenant_id: tenant_a.id,
|
||||
user_id: tenant_user.id.into(),
|
||||
user_id: tenant_user.id,
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
@ -3538,7 +3538,7 @@ pub mod test {
|
||||
|
||||
tenant::add_user(tenant::TenantUser {
|
||||
tenant_id: tenant_a.id,
|
||||
user_id: tenant_admin.id.into(),
|
||||
user_id: tenant_admin.id,
|
||||
is_admin: true,
|
||||
..Default::default()
|
||||
})
|
||||
@ -3546,7 +3546,7 @@ pub mod test {
|
||||
.unwrap();
|
||||
tenant::add_user(tenant::TenantUser {
|
||||
tenant_id: tenant_a.id,
|
||||
user_id: tenant_device_admin.id.into(),
|
||||
user_id: tenant_device_admin.id,
|
||||
is_device_admin: true,
|
||||
..Default::default()
|
||||
})
|
||||
@ -3554,7 +3554,7 @@ pub mod test {
|
||||
.unwrap();
|
||||
tenant::add_user(tenant::TenantUser {
|
||||
tenant_id: tenant_a.id,
|
||||
user_id: tenant_gateway_admin.id.into(),
|
||||
user_id: tenant_gateway_admin.id,
|
||||
is_gateway_admin: true,
|
||||
..Default::default()
|
||||
})
|
||||
@ -3562,7 +3562,7 @@ pub mod test {
|
||||
.unwrap();
|
||||
tenant::add_user(tenant::TenantUser {
|
||||
tenant_id: tenant_a.id,
|
||||
user_id: tenant_user.id.into(),
|
||||
user_id: tenant_user.id,
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
@ -3840,32 +3840,32 @@ pub mod test {
|
||||
.await;
|
||||
|
||||
tenant::add_user(tenant::TenantUser {
|
||||
tenant_id: api_key_tenant.tenant_id.unwrap().into(),
|
||||
user_id: tenant_admin.id.into(),
|
||||
tenant_id: api_key_tenant.tenant_id.unwrap(),
|
||||
user_id: tenant_admin.id,
|
||||
is_admin: true,
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
tenant::add_user(tenant::TenantUser {
|
||||
tenant_id: api_key_tenant.tenant_id.unwrap().into(),
|
||||
user_id: tenant_device_admin.id.into(),
|
||||
tenant_id: api_key_tenant.tenant_id.unwrap(),
|
||||
user_id: tenant_device_admin.id,
|
||||
is_device_admin: true,
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
tenant::add_user(tenant::TenantUser {
|
||||
tenant_id: api_key_tenant.tenant_id.unwrap().into(),
|
||||
user_id: tenant_gateway_admin.id.into(),
|
||||
tenant_id: api_key_tenant.tenant_id.unwrap(),
|
||||
user_id: tenant_gateway_admin.id,
|
||||
is_gateway_admin: true,
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
tenant::add_user(tenant::TenantUser {
|
||||
tenant_id: api_key_tenant.tenant_id.unwrap().into(),
|
||||
user_id: tenant_user.id.into(),
|
||||
tenant_id: api_key_tenant.tenant_id.unwrap(),
|
||||
user_id: tenant_user.id,
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
@ -4093,8 +4093,8 @@ pub mod test {
|
||||
.await;
|
||||
|
||||
tenant::add_user(tenant::TenantUser {
|
||||
tenant_id: api_key_tenant.tenant_id.unwrap().into(),
|
||||
user_id: tenant_user.id.into(),
|
||||
tenant_id: api_key_tenant.tenant_id.unwrap(),
|
||||
user_id: tenant_user.id,
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
@ -4237,7 +4237,7 @@ pub mod test {
|
||||
let gw_api_key_tenant = gateway::create(gateway::Gateway {
|
||||
name: "test-gw-tenant".into(),
|
||||
gateway_id: EUI64::from_str("0202030405060708").unwrap(),
|
||||
tenant_id: api_key_tenant.tenant_id.unwrap().into(),
|
||||
tenant_id: api_key_tenant.tenant_id.unwrap(),
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
@ -4245,7 +4245,7 @@ pub mod test {
|
||||
|
||||
tenant::add_user(tenant::TenantUser {
|
||||
tenant_id: tenant_a.id,
|
||||
user_id: tenant_admin.id.into(),
|
||||
user_id: tenant_admin.id,
|
||||
is_admin: true,
|
||||
..Default::default()
|
||||
})
|
||||
@ -4253,7 +4253,7 @@ pub mod test {
|
||||
.unwrap();
|
||||
tenant::add_user(tenant::TenantUser {
|
||||
tenant_id: tenant_a.id,
|
||||
user_id: tenant_gateway_admin.id.into(),
|
||||
user_id: tenant_gateway_admin.id,
|
||||
is_gateway_admin: true,
|
||||
..Default::default()
|
||||
})
|
||||
@ -4261,7 +4261,7 @@ pub mod test {
|
||||
.unwrap();
|
||||
tenant::add_user(tenant::TenantUser {
|
||||
tenant_id: tenant_a.id,
|
||||
user_id: tenant_user.id.into(),
|
||||
user_id: tenant_user.id,
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
@ -4513,32 +4513,32 @@ pub mod test {
|
||||
.await;
|
||||
|
||||
tenant::add_user(tenant::TenantUser {
|
||||
tenant_id: api_key_tenant.tenant_id.unwrap().into(),
|
||||
user_id: tenant_admin.id.into(),
|
||||
tenant_id: api_key_tenant.tenant_id.unwrap(),
|
||||
user_id: tenant_admin.id,
|
||||
is_admin: true,
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
tenant::add_user(tenant::TenantUser {
|
||||
tenant_id: api_key_tenant.tenant_id.unwrap().into(),
|
||||
user_id: tenant_device_admin.id.into(),
|
||||
tenant_id: api_key_tenant.tenant_id.unwrap(),
|
||||
user_id: tenant_device_admin.id,
|
||||
is_device_admin: true,
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
tenant::add_user(tenant::TenantUser {
|
||||
tenant_id: api_key_tenant.tenant_id.unwrap().into(),
|
||||
user_id: tenant_gateway_admin.id.into(),
|
||||
tenant_id: api_key_tenant.tenant_id.unwrap(),
|
||||
user_id: tenant_gateway_admin.id,
|
||||
is_gateway_admin: true,
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
tenant::add_user(tenant::TenantUser {
|
||||
tenant_id: api_key_tenant.tenant_id.unwrap().into(),
|
||||
user_id: tenant_user.id.into(),
|
||||
tenant_id: api_key_tenant.tenant_id.unwrap(),
|
||||
user_id: tenant_user.id,
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
@ -4901,7 +4901,7 @@ pub mod test {
|
||||
.await
|
||||
.unwrap();
|
||||
tenant::add_user(tenant::TenantUser {
|
||||
tenant_id: api_key_tenant.tenant_id.unwrap().into(),
|
||||
tenant_id: api_key_tenant.tenant_id.unwrap(),
|
||||
user_id: tenant_device_admin.id,
|
||||
is_device_admin: true,
|
||||
..Default::default()
|
||||
|
@ -252,7 +252,7 @@ async fn _handle_pr_start_req(b: &[u8]) -> Result<backend::PRStartAnsPayload> {
|
||||
let pl: backend::PRStartReqPayload = serde_json::from_slice(b)?;
|
||||
let phy = lrwn::PhyPayload::from_slice(&pl.phy_payload)?;
|
||||
|
||||
if phy.mhdr.m_type == lrwn::MType::JoinRequest {
|
||||
if phy.mhdr.f_type == lrwn::FType::JoinRequest {
|
||||
_handle_pr_start_req_join(pl, phy).await
|
||||
} else {
|
||||
_handle_pr_start_req_data(pl, phy).await
|
||||
|
@ -88,7 +88,7 @@ impl DeviceProfileService for DeviceProfile {
|
||||
rx1_delay: req_dp.abp_rx1_delay as u8,
|
||||
rx1_dr_offset: req_dp.abp_rx1_dr_offset as u8,
|
||||
rx2_dr: req_dp.abp_rx2_dr as u8,
|
||||
rx2_freq: req_dp.abp_rx2_freq as u32,
|
||||
rx2_freq: req_dp.abp_rx2_freq,
|
||||
})
|
||||
},
|
||||
class_b_params: if req_dp.supports_class_b {
|
||||
@ -96,7 +96,7 @@ impl DeviceProfileService for DeviceProfile {
|
||||
timeout: req_dp.class_b_timeout as u16,
|
||||
ping_slot_nb_k: req_dp.class_b_ping_slot_nb_k as u8,
|
||||
ping_slot_dr: req_dp.class_b_ping_slot_dr as u8,
|
||||
ping_slot_freq: req_dp.class_b_ping_slot_freq as u32,
|
||||
ping_slot_freq: req_dp.class_b_ping_slot_freq,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
@ -116,7 +116,7 @@ impl DeviceProfileService for DeviceProfile {
|
||||
relay_enabled: req_dp.relay_enabled,
|
||||
relay_cad_periodicity: req_dp.relay_cad_periodicity as u8,
|
||||
default_channel_index: req_dp.relay_default_channel_index as u8,
|
||||
second_channel_freq: req_dp.relay_second_channel_freq as u32,
|
||||
second_channel_freq: req_dp.relay_second_channel_freq,
|
||||
second_channel_dr: req_dp.relay_second_channel_dr as u8,
|
||||
second_channel_ack_offset: req_dp.relay_second_channel_ack_offset as u8,
|
||||
ed_activation_mode: req_dp.relay_ed_activation_mode().from_proto(),
|
||||
@ -344,7 +344,7 @@ impl DeviceProfileService for DeviceProfile {
|
||||
rx1_delay: req_dp.abp_rx1_delay as u8,
|
||||
rx1_dr_offset: req_dp.abp_rx1_dr_offset as u8,
|
||||
rx2_dr: req_dp.abp_rx2_dr as u8,
|
||||
rx2_freq: req_dp.abp_rx2_freq as u32,
|
||||
rx2_freq: req_dp.abp_rx2_freq,
|
||||
})
|
||||
},
|
||||
class_b_params: if req_dp.supports_class_b {
|
||||
@ -352,7 +352,7 @@ impl DeviceProfileService for DeviceProfile {
|
||||
timeout: req_dp.class_b_timeout as u16,
|
||||
ping_slot_nb_k: req_dp.class_b_ping_slot_nb_k as u8,
|
||||
ping_slot_dr: req_dp.class_b_ping_slot_dr as u8,
|
||||
ping_slot_freq: req_dp.class_b_ping_slot_freq as u32,
|
||||
ping_slot_freq: req_dp.class_b_ping_slot_freq,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
@ -372,7 +372,7 @@ impl DeviceProfileService for DeviceProfile {
|
||||
relay_enabled: req_dp.relay_enabled,
|
||||
relay_cad_periodicity: req_dp.relay_cad_periodicity as u8,
|
||||
default_channel_index: req_dp.relay_default_channel_index as u8,
|
||||
second_channel_freq: req_dp.relay_second_channel_freq as u32,
|
||||
second_channel_freq: req_dp.relay_second_channel_freq,
|
||||
second_channel_dr: req_dp.relay_second_channel_dr as u8,
|
||||
second_channel_ack_offset: req_dp.relay_second_channel_ack_offset as u8,
|
||||
ed_activation_mode: req_dp.relay_ed_activation_mode().from_proto(),
|
||||
@ -406,7 +406,6 @@ impl DeviceProfileService for DeviceProfile {
|
||||
ts004_f_port: app_layer_params.ts004_f_port as u8,
|
||||
ts005_version: app_layer_params.ts005_version().from_proto(),
|
||||
ts005_f_port: app_layer_params.ts005_f_port as u8,
|
||||
..Default::default()
|
||||
}
|
||||
},
|
||||
..Default::default()
|
||||
|
@ -50,9 +50,9 @@ impl ToStatus for storage::error::Error {
|
||||
storage::error::Error::ValidatorValidate(_) => {
|
||||
Status::new(Code::InvalidArgument, format!("{:#}", self))
|
||||
}
|
||||
storage::error::Error::MultiError(errors) => {
|
||||
storage::error::Error::Multi(errors) => {
|
||||
let errors = errors
|
||||
.into_iter()
|
||||
.iter()
|
||||
.map(|e| e.to_string())
|
||||
.collect::<Vec<String>>()
|
||||
.join(", ");
|
||||
|
@ -346,11 +346,11 @@ impl FuotaService for Fuota {
|
||||
started_at: d
|
||||
.started_at
|
||||
.as_ref()
|
||||
.map(|ts| helpers::datetime_to_prost_timestamp(ts)),
|
||||
.map(helpers::datetime_to_prost_timestamp),
|
||||
completed_at: d
|
||||
.completed_at
|
||||
.as_ref()
|
||||
.map(|ts| helpers::datetime_to_prost_timestamp(ts)),
|
||||
.map(helpers::datetime_to_prost_timestamp),
|
||||
name: d.name.clone(),
|
||||
})
|
||||
.collect(),
|
||||
@ -462,23 +462,23 @@ impl FuotaService for Fuota {
|
||||
completed_at: d
|
||||
.completed_at
|
||||
.as_ref()
|
||||
.map(|ts| helpers::datetime_to_prost_timestamp(ts)),
|
||||
.map(helpers::datetime_to_prost_timestamp),
|
||||
mc_group_setup_completed_at: d
|
||||
.mc_group_setup_completed_at
|
||||
.as_ref()
|
||||
.map(|ts| helpers::datetime_to_prost_timestamp(ts)),
|
||||
.map(helpers::datetime_to_prost_timestamp),
|
||||
mc_session_completed_at: d
|
||||
.mc_session_completed_at
|
||||
.as_ref()
|
||||
.map(|ts| helpers::datetime_to_prost_timestamp(ts)),
|
||||
.map(helpers::datetime_to_prost_timestamp),
|
||||
frag_session_setup_completed_at: d
|
||||
.frag_session_setup_completed_at
|
||||
.as_ref()
|
||||
.map(|ts| helpers::datetime_to_prost_timestamp(ts)),
|
||||
.map(helpers::datetime_to_prost_timestamp),
|
||||
frag_status_completed_at: d
|
||||
.frag_status_completed_at
|
||||
.as_ref()
|
||||
.map(|ts| helpers::datetime_to_prost_timestamp(ts)),
|
||||
.map(helpers::datetime_to_prost_timestamp),
|
||||
error_msg: d.error_msg.clone(),
|
||||
})
|
||||
.collect(),
|
||||
@ -624,7 +624,7 @@ impl FuotaService for Fuota {
|
||||
completed_at: j
|
||||
.completed_at
|
||||
.as_ref()
|
||||
.map(|ts| helpers::datetime_to_prost_timestamp(ts)),
|
||||
.map(helpers::datetime_to_prost_timestamp),
|
||||
max_retry_count: j.max_retry_count as u32,
|
||||
attempt_count: j.attempt_count as u32,
|
||||
scheduler_run_after: Some(helpers::datetime_to_prost_timestamp(
|
||||
|
@ -1036,7 +1036,7 @@ pub mod test {
|
||||
let mut create_req = Request::new(create_req);
|
||||
create_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let _ = service.create(create_req).await.unwrap();
|
||||
|
||||
// get
|
||||
@ -1046,7 +1046,7 @@ pub mod test {
|
||||
let mut get_req = Request::new(get_req);
|
||||
get_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let get_resp = service.get(get_req).await.unwrap();
|
||||
assert_eq!(
|
||||
Some(api::Gateway {
|
||||
@ -1082,7 +1082,7 @@ pub mod test {
|
||||
let mut up_req = Request::new(up_req);
|
||||
up_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let _ = service.update(up_req).await.unwrap();
|
||||
|
||||
// get
|
||||
@ -1092,7 +1092,7 @@ pub mod test {
|
||||
let mut get_req = Request::new(get_req);
|
||||
get_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let get_resp = service.get(get_req).await.unwrap();
|
||||
assert_eq!(
|
||||
Some(api::Gateway {
|
||||
@ -1121,7 +1121,7 @@ pub mod test {
|
||||
let mut list_req = Request::new(list_req);
|
||||
list_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let list_resp = service.list(list_req).await.unwrap();
|
||||
assert_eq!(1, list_resp.get_ref().total_count);
|
||||
assert_eq!(1, list_resp.get_ref().result.len());
|
||||
@ -1133,7 +1133,7 @@ pub mod test {
|
||||
let mut del_req = Request::new(del_req);
|
||||
del_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let _ = service.delete(del_req).await.unwrap();
|
||||
|
||||
let del_req = api::DeleteGatewayRequest {
|
||||
@ -1142,7 +1142,7 @@ pub mod test {
|
||||
let mut del_req = Request::new(del_req);
|
||||
del_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let del_resp = service.delete(del_req).await;
|
||||
assert!(del_resp.is_err());
|
||||
}
|
||||
@ -1220,7 +1220,7 @@ pub mod test {
|
||||
let mut stats_req = Request::new(stats_req);
|
||||
stats_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let stats_resp = service.get_metrics(stats_req).await.unwrap();
|
||||
let stats_resp = stats_resp.get_ref();
|
||||
assert_eq!(
|
||||
|
@ -193,17 +193,17 @@ impl FromProto<Aggregation> for common::Aggregation {
|
||||
}
|
||||
}
|
||||
|
||||
impl ToProto<common::MType> for lrwn::MType {
|
||||
fn to_proto(self) -> common::MType {
|
||||
impl ToProto<common::FType> for lrwn::FType {
|
||||
fn to_proto(self) -> common::FType {
|
||||
match self {
|
||||
lrwn::MType::JoinRequest => common::MType::JoinRequest,
|
||||
lrwn::MType::JoinAccept => common::MType::JoinAccept,
|
||||
lrwn::MType::UnconfirmedDataUp => common::MType::UnconfirmedDataUp,
|
||||
lrwn::MType::UnconfirmedDataDown => common::MType::UnconfirmedDataDown,
|
||||
lrwn::MType::ConfirmedDataUp => common::MType::ConfirmedDataUp,
|
||||
lrwn::MType::ConfirmedDataDown => common::MType::ConfirmedDataDown,
|
||||
lrwn::MType::RejoinRequest => common::MType::RejoinRequest,
|
||||
lrwn::MType::Proprietary => common::MType::Proprietary,
|
||||
lrwn::FType::JoinRequest => common::FType::JoinRequest,
|
||||
lrwn::FType::JoinAccept => common::FType::JoinAccept,
|
||||
lrwn::FType::UnconfirmedDataUp => common::FType::UnconfirmedDataUp,
|
||||
lrwn::FType::UnconfirmedDataDown => common::FType::UnconfirmedDataDown,
|
||||
lrwn::FType::ConfirmedDataUp => common::FType::ConfirmedDataUp,
|
||||
lrwn::FType::ConfirmedDataDown => common::FType::ConfirmedDataDown,
|
||||
lrwn::FType::RejoinRequest => common::FType::RejoinRequest,
|
||||
lrwn::FType::Proprietary => common::FType::Proprietary,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
use std::sync::LazyLock;
|
||||
use std::time::{Duration, Instant};
|
||||
use std::{
|
||||
future::Future,
|
||||
@ -5,7 +6,7 @@ use std::{
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
use anyhow::Result;
|
||||
use anyhow::{Context as AnyhowContext, Result};
|
||||
use axum::{response::IntoResponse, routing::get, Router};
|
||||
use http::{
|
||||
header::{self, HeaderMap, HeaderValue},
|
||||
@ -67,33 +68,31 @@ pub mod relay;
|
||||
pub mod tenant;
|
||||
pub mod user;
|
||||
|
||||
lazy_static! {
|
||||
static ref GRPC_COUNTER: Family<GrpcLabels, Counter> = {
|
||||
let counter = Family::<GrpcLabels, Counter>::default();
|
||||
prometheus::register(
|
||||
"api_requests_handled",
|
||||
"Number of API requests handled by service, method and status code",
|
||||
counter.clone(),
|
||||
);
|
||||
counter
|
||||
};
|
||||
static ref GRPC_HISTOGRAM: Family<GrpcLabels, Histogram> = {
|
||||
let histogram = Family::<GrpcLabels, Histogram>::new_with_constructor(|| {
|
||||
Histogram::new(
|
||||
[
|
||||
0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0,
|
||||
]
|
||||
.into_iter(),
|
||||
)
|
||||
});
|
||||
prometheus::register(
|
||||
"api_requests_handled_seconds",
|
||||
"Duration of API requests handled by service, method and status code",
|
||||
histogram.clone(),
|
||||
);
|
||||
histogram
|
||||
};
|
||||
}
|
||||
static GRPC_COUNTER: LazyLock<Family<GrpcLabels, Counter>> = LazyLock::new(|| {
|
||||
let counter = Family::<GrpcLabels, Counter>::default();
|
||||
prometheus::register(
|
||||
"api_requests_handled",
|
||||
"Number of API requests handled by service, method and status code",
|
||||
counter.clone(),
|
||||
);
|
||||
counter
|
||||
});
|
||||
static GRPC_HISTOGRAM: LazyLock<Family<GrpcLabels, Histogram>> = LazyLock::new(|| {
|
||||
let histogram = Family::<GrpcLabels, Histogram>::new_with_constructor(|| {
|
||||
Histogram::new(
|
||||
[
|
||||
0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0,
|
||||
]
|
||||
.into_iter(),
|
||||
)
|
||||
});
|
||||
prometheus::register(
|
||||
"api_requests_handled_seconds",
|
||||
"Duration of API requests handled by service, method and status code",
|
||||
histogram.clone(),
|
||||
);
|
||||
histogram
|
||||
});
|
||||
|
||||
#[derive(RustEmbed)]
|
||||
#[folder = "../ui/build"]
|
||||
@ -103,7 +102,7 @@ type BoxError = Box<dyn std::error::Error + Send + Sync>;
|
||||
|
||||
pub async fn setup() -> Result<()> {
|
||||
let conf = config::get();
|
||||
let bind = conf.api.bind.parse()?;
|
||||
let bind = conf.api.bind.parse().context("Parse api.bind config")?;
|
||||
|
||||
info!(bind = %bind, "Setting up API interface");
|
||||
|
||||
@ -114,7 +113,7 @@ pub async fn setup() -> Result<()> {
|
||||
.route("/auth/oauth2/callback", get(oauth2::callback_handler))
|
||||
.fallback(service_static_handler)
|
||||
.into_service()
|
||||
.map_response(|r| r.map(tonic::body::boxed));
|
||||
.map_response(|r| r.map(tonic::body::Body::new));
|
||||
|
||||
let grpc = TonicServer::builder()
|
||||
.accept_http1(true)
|
||||
|
@ -484,7 +484,7 @@ pub mod test {
|
||||
let mut create_req = Request::new(create_req);
|
||||
create_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let create_resp = service.create(create_req).await.unwrap();
|
||||
|
||||
// get
|
||||
@ -494,7 +494,7 @@ pub mod test {
|
||||
let mut get_req = Request::new(get_req);
|
||||
get_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let get_resp = service.get(get_req).await.unwrap();
|
||||
assert_eq!(
|
||||
Some(api::Tenant {
|
||||
@ -524,7 +524,7 @@ pub mod test {
|
||||
let mut up_req = Request::new(up_req);
|
||||
up_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let _ = service.update(up_req).await.unwrap();
|
||||
|
||||
// get
|
||||
@ -534,7 +534,7 @@ pub mod test {
|
||||
let mut get_req = Request::new(get_req);
|
||||
get_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let get_resp = service.get(get_req).await.unwrap();
|
||||
assert_eq!(
|
||||
Some(api::Tenant {
|
||||
@ -559,7 +559,7 @@ pub mod test {
|
||||
let mut list_req = Request::new(list_req);
|
||||
list_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let list_resp = service.list(list_req).await.unwrap();
|
||||
assert_eq!(1, list_resp.get_ref().total_count);
|
||||
assert_eq!(1, list_resp.get_ref().result.len());
|
||||
@ -571,7 +571,7 @@ pub mod test {
|
||||
let mut del_req = Request::new(del_req);
|
||||
del_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let _ = service.delete(del_req).await.unwrap();
|
||||
|
||||
let del_req = api::DeleteTenantRequest {
|
||||
@ -580,7 +580,7 @@ pub mod test {
|
||||
let mut del_req = Request::new(del_req);
|
||||
del_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let del_resp = service.delete(del_req).await;
|
||||
assert!(del_resp.is_err());
|
||||
}
|
||||
|
@ -294,7 +294,7 @@ pub mod test {
|
||||
let mut create_req = Request::new(create_req);
|
||||
create_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let create_resp = service.create(create_req).await.unwrap();
|
||||
|
||||
// get
|
||||
@ -304,7 +304,7 @@ pub mod test {
|
||||
let mut get_req = Request::new(get_req);
|
||||
get_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let get_resp = service.get(get_req).await.unwrap();
|
||||
assert_eq!(
|
||||
Some(api::User {
|
||||
@ -332,7 +332,7 @@ pub mod test {
|
||||
let mut up_req = Request::new(up_req);
|
||||
up_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let _ = service.update(up_req).await.unwrap();
|
||||
|
||||
// get
|
||||
@ -342,7 +342,7 @@ pub mod test {
|
||||
let mut get_req = Request::new(get_req);
|
||||
get_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let get_resp = service.get(get_req).await.unwrap();
|
||||
assert_eq!(
|
||||
Some(api::User {
|
||||
@ -364,7 +364,7 @@ pub mod test {
|
||||
let mut up_req = Request::new(up_req);
|
||||
up_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let _ = service.update_password(up_req).await.unwrap();
|
||||
|
||||
// list
|
||||
@ -375,7 +375,7 @@ pub mod test {
|
||||
let mut list_req = Request::new(list_req);
|
||||
list_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let list_resp = service.list(list_req).await.unwrap();
|
||||
// * Admin from migrations
|
||||
// * User that we created for auth
|
||||
@ -390,7 +390,7 @@ pub mod test {
|
||||
let mut del_req = Request::new(del_req);
|
||||
del_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let _ = service.delete(del_req).await.unwrap();
|
||||
|
||||
let del_req = api::DeleteUserRequest {
|
||||
@ -399,7 +399,7 @@ pub mod test {
|
||||
let mut del_req = Request::new(del_req);
|
||||
del_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let del_resp = service.delete(del_req).await;
|
||||
assert!(del_resp.is_err());
|
||||
|
||||
@ -409,7 +409,7 @@ pub mod test {
|
||||
let mut del_req = Request::new(del_req);
|
||||
del_req
|
||||
.extensions_mut()
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id).clone()));
|
||||
.insert(AuthID::User(Into::<uuid::Uuid>::into(u.id)));
|
||||
let del_resp = service.delete(del_req).await;
|
||||
assert!(del_resp.is_err());
|
||||
}
|
||||
|
@ -33,11 +33,8 @@ async fn handle_uplink_v100(
|
||||
) -> Result<()> {
|
||||
let pl = clocksync::v1::Payload::from_slice(true, data)?;
|
||||
|
||||
match pl {
|
||||
clocksync::v1::Payload::AppTimeReq(pl) => {
|
||||
handle_v1_app_time_req(dev, dp, rx_info, pl).await?
|
||||
}
|
||||
_ => {}
|
||||
if let clocksync::v1::Payload::AppTimeReq(pl) = pl {
|
||||
handle_v1_app_time_req(dev, dp, rx_info, pl).await?
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -51,11 +48,8 @@ async fn handle_uplink_v200(
|
||||
) -> Result<()> {
|
||||
let pl = clocksync::v2::Payload::from_slice(true, data)?;
|
||||
|
||||
match pl {
|
||||
clocksync::v2::Payload::AppTimeReq(pl) => {
|
||||
handle_v2_app_time_req(dev, dp, rx_info, pl).await?
|
||||
}
|
||||
_ => {}
|
||||
if let clocksync::v2::Payload::AppTimeReq(pl) = pl {
|
||||
handle_v2_app_time_req(dev, dp, rx_info, pl).await?
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -181,7 +175,7 @@ mod test {
|
||||
Test {
|
||||
name: "device synced".into(),
|
||||
rx_info: gw::UplinkRxInfo {
|
||||
time_since_gps_epoch: Some(Duration::from_secs(1234).try_into().unwrap()),
|
||||
time_since_gps_epoch: Some(Duration::from_secs(1234).into()),
|
||||
..Default::default()
|
||||
},
|
||||
req: clocksync::v1::AppTimeReqPayload {
|
||||
@ -196,7 +190,7 @@ mod test {
|
||||
Test {
|
||||
name: "device synced - ans required".into(),
|
||||
rx_info: gw::UplinkRxInfo {
|
||||
time_since_gps_epoch: Some(Duration::from_secs(1234).try_into().unwrap()),
|
||||
time_since_gps_epoch: Some(Duration::from_secs(1234).into()),
|
||||
..Default::default()
|
||||
},
|
||||
req: clocksync::v1::AppTimeReqPayload {
|
||||
@ -214,7 +208,7 @@ mod test {
|
||||
Test {
|
||||
name: "device not synced (positive correction)".into(),
|
||||
rx_info: gw::UplinkRxInfo {
|
||||
time_since_gps_epoch: Some(Duration::from_secs(1234).try_into().unwrap()),
|
||||
time_since_gps_epoch: Some(Duration::from_secs(1234).into()),
|
||||
..Default::default()
|
||||
},
|
||||
req: clocksync::v1::AppTimeReqPayload {
|
||||
@ -232,7 +226,7 @@ mod test {
|
||||
Test {
|
||||
name: "device not synced (negative correction)".into(),
|
||||
rx_info: gw::UplinkRxInfo {
|
||||
time_since_gps_epoch: Some(Duration::from_secs(1200).try_into().unwrap()),
|
||||
time_since_gps_epoch: Some(Duration::from_secs(1200).into()),
|
||||
..Default::default()
|
||||
},
|
||||
req: clocksync::v1::AppTimeReqPayload {
|
||||
@ -330,7 +324,7 @@ mod test {
|
||||
Test {
|
||||
name: "device synced".into(),
|
||||
rx_info: gw::UplinkRxInfo {
|
||||
time_since_gps_epoch: Some(Duration::from_secs(1234).try_into().unwrap()),
|
||||
time_since_gps_epoch: Some(Duration::from_secs(1234).into()),
|
||||
..Default::default()
|
||||
},
|
||||
req: clocksync::v2::AppTimeReqPayload {
|
||||
@ -345,7 +339,7 @@ mod test {
|
||||
Test {
|
||||
name: "device synced - ans required".into(),
|
||||
rx_info: gw::UplinkRxInfo {
|
||||
time_since_gps_epoch: Some(Duration::from_secs(1234).try_into().unwrap()),
|
||||
time_since_gps_epoch: Some(Duration::from_secs(1234).into()),
|
||||
..Default::default()
|
||||
},
|
||||
req: clocksync::v2::AppTimeReqPayload {
|
||||
@ -363,7 +357,7 @@ mod test {
|
||||
Test {
|
||||
name: "device not synced (positive correction)".into(),
|
||||
rx_info: gw::UplinkRxInfo {
|
||||
time_since_gps_epoch: Some(Duration::from_secs(1234).try_into().unwrap()),
|
||||
time_since_gps_epoch: Some(Duration::from_secs(1234).into()),
|
||||
..Default::default()
|
||||
},
|
||||
req: clocksync::v2::AppTimeReqPayload {
|
||||
@ -381,7 +375,7 @@ mod test {
|
||||
Test {
|
||||
name: "device not synced (negative correction)".into(),
|
||||
rx_info: gw::UplinkRxInfo {
|
||||
time_since_gps_epoch: Some(Duration::from_secs(1200).try_into().unwrap()),
|
||||
time_since_gps_epoch: Some(Duration::from_secs(1200).into()),
|
||||
..Default::default()
|
||||
},
|
||||
req: clocksync::v2::AppTimeReqPayload {
|
||||
|
@ -397,6 +397,20 @@ impl Flow {
|
||||
)
|
||||
.to_vec()?,
|
||||
Some(Ts004Version::V200) => {
|
||||
let dev = device::get(&fuota_dev.dev_eui).await?;
|
||||
let session_cnt = dev.app_layer_params.ts004_session_cnt[0];
|
||||
let mut app_layer_params = dev.app_layer_params.clone();
|
||||
app_layer_params.ts004_session_cnt[0] += 1;
|
||||
|
||||
device::partial_update(
|
||||
fuota_dev.dev_eui,
|
||||
&device::DeviceChangeset {
|
||||
app_layer_params: Some(app_layer_params),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
||||
let dev_keys = device_keys::get(&fuota_dev.dev_eui).await?;
|
||||
let data_block_int_key = match self.device_profile.mac_version {
|
||||
MacVersion::LORAWAN_1_0_0
|
||||
@ -412,7 +426,7 @@ impl Flow {
|
||||
};
|
||||
let mic = fragmentation::v2::calculate_mic(
|
||||
data_block_int_key,
|
||||
0,
|
||||
session_cnt,
|
||||
0,
|
||||
[0, 0, 0, 0],
|
||||
&self.fuota_deployment.payload,
|
||||
@ -434,7 +448,7 @@ impl Flow {
|
||||
},
|
||||
descriptor: [0, 0, 0, 0],
|
||||
mic,
|
||||
session_cnt: 0,
|
||||
session_cnt,
|
||||
},
|
||||
)
|
||||
.to_vec()?
|
||||
@ -500,7 +514,7 @@ impl Flow {
|
||||
FuotaJob::Enqueue,
|
||||
self.fuota_deployment
|
||||
.multicast_session_start
|
||||
.unwrap_or_else(|| Utc::now()),
|
||||
.unwrap_or_else(Utc::now),
|
||||
)));
|
||||
}
|
||||
|
||||
@ -657,7 +671,7 @@ impl Flow {
|
||||
FuotaJob::Enqueue,
|
||||
self.fuota_deployment
|
||||
.multicast_session_start
|
||||
.unwrap_or_else(|| Utc::now()),
|
||||
.unwrap_or_else(Utc::now),
|
||||
)))
|
||||
}
|
||||
}
|
||||
@ -756,7 +770,7 @@ impl Flow {
|
||||
FuotaJob::DeleteMcGroup,
|
||||
self.fuota_deployment
|
||||
.multicast_session_end
|
||||
.unwrap_or_else(|| Utc::now()),
|
||||
.unwrap_or_else(Utc::now),
|
||||
))),
|
||||
RequestFragmentationSessionStatus::AfterFragEnqueue => {
|
||||
Ok(Some((FuotaJob::FragStatus, Utc::now())))
|
||||
@ -765,7 +779,7 @@ impl Flow {
|
||||
FuotaJob::FragStatus,
|
||||
self.fuota_deployment
|
||||
.multicast_session_end
|
||||
.unwrap_or_else(|| Utc::now()),
|
||||
.unwrap_or_else(Utc::now),
|
||||
))),
|
||||
}
|
||||
}
|
||||
@ -852,7 +866,7 @@ impl Flow {
|
||||
FuotaJob::DeleteMcGroup,
|
||||
self.fuota_deployment
|
||||
.multicast_session_end
|
||||
.unwrap_or_else(|| Utc::now()),
|
||||
.unwrap_or_else(Utc::now),
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::sync::Arc;
|
||||
use std::sync::{Arc, LazyLock};
|
||||
|
||||
use anyhow::Result;
|
||||
use tokio::sync::RwLock;
|
||||
@ -8,9 +8,8 @@ use crate::{config, stream};
|
||||
use backend::{Client, ClientConfig};
|
||||
use lrwn::{EUI64Prefix, EUI64};
|
||||
|
||||
lazy_static! {
|
||||
static ref CLIENTS: RwLock<Vec<(EUI64Prefix, Arc<Client>)>> = RwLock::new(vec![]);
|
||||
}
|
||||
static CLIENTS: LazyLock<RwLock<Vec<(EUI64Prefix, Arc<Client>)>>> =
|
||||
LazyLock::new(|| RwLock::new(vec![]));
|
||||
|
||||
pub async fn setup() -> Result<()> {
|
||||
info!("Setting up Join Server clients");
|
||||
@ -30,6 +29,11 @@ pub async fn setup() -> Result<()> {
|
||||
tls_key: js.tls_key.clone(),
|
||||
async_timeout: js.async_timeout,
|
||||
request_log_sender: stream::backend_interfaces::get_log_sender().await,
|
||||
authorization: if js.authorization_header.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(js.authorization_header.clone())
|
||||
},
|
||||
..Default::default()
|
||||
})?;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::collections::HashMap;
|
||||
use std::io::Cursor;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use std::sync::{Arc, LazyLock};
|
||||
|
||||
use anyhow::Result;
|
||||
use chrono::{Duration, DurationRound};
|
||||
@ -15,9 +15,8 @@ use backend::{Client, ClientConfig, GWInfoElement, ULMetaData};
|
||||
use chirpstack_api::{common, gw};
|
||||
use lrwn::{region, DevAddr, NetID, EUI64};
|
||||
|
||||
lazy_static! {
|
||||
static ref CLIENTS: RwLock<HashMap<NetID, Arc<Client>>> = RwLock::new(HashMap::new());
|
||||
}
|
||||
static CLIENTS: LazyLock<RwLock<HashMap<NetID, Arc<Client>>>> =
|
||||
LazyLock::new(|| RwLock::new(HashMap::new()));
|
||||
|
||||
pub async fn setup() -> Result<()> {
|
||||
info!("Setting up roaming clients");
|
||||
|
@ -797,6 +797,11 @@ pub fn run() {
|
||||
# #
|
||||
# # Set this to enable client-certificate authentication with the join-server.
|
||||
# tls_key="/path/to/tls_key.pem"
|
||||
|
||||
# # Authorization header.
|
||||
# #
|
||||
# # Optional value of the Authorization header, e.g. token or password.
|
||||
# authorization_header="Bearer sometoken"
|
||||
{{#each join_server.servers}}
|
||||
|
||||
[[join_server.servers]]
|
||||
@ -807,6 +812,7 @@ pub fn run() {
|
||||
ca_cert="{{ this.ca_cert }}"
|
||||
tls_cert="{{ this.tls_cert }}"
|
||||
tls_key="{{ this.tls_key }}"
|
||||
authorization_header="{{ this.authorization_header }}"
|
||||
{{/each}}
|
||||
|
||||
|
||||
@ -1000,7 +1006,7 @@ pub fn run() {
|
||||
let conf = config::get();
|
||||
println!(
|
||||
"{}",
|
||||
reg.render_template(&template, &conf)
|
||||
reg.render_template(template, &conf)
|
||||
.expect("render configfile error")
|
||||
);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use std::path::Path;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::{Arc, LazyLock, Mutex};
|
||||
use std::time::Duration;
|
||||
use std::{env, fs};
|
||||
|
||||
@ -9,9 +9,8 @@ use serde::{Deserialize, Serialize};
|
||||
use lrwn::region::CommonName;
|
||||
use lrwn::{AES128Key, DevAddrPrefix, EUI64Prefix, NetID};
|
||||
|
||||
lazy_static! {
|
||||
static ref CONFIG: Mutex<Arc<Configuration>> = Mutex::new(Arc::new(Default::default()));
|
||||
}
|
||||
static CONFIG: LazyLock<Mutex<Arc<Configuration>>> =
|
||||
LazyLock::new(|| Mutex::new(Arc::new(Default::default())));
|
||||
|
||||
#[derive(Default, Serialize, Deserialize, Clone)]
|
||||
#[serde(default)]
|
||||
@ -353,6 +352,7 @@ pub struct AmqpIntegration {
|
||||
pub url: String,
|
||||
pub json: bool,
|
||||
pub event_routing_key: String,
|
||||
pub exchange: String,
|
||||
}
|
||||
|
||||
impl Default for AmqpIntegration {
|
||||
@ -362,6 +362,7 @@ impl Default for AmqpIntegration {
|
||||
json: true,
|
||||
event_routing_key: "application.{{application_id}}.device.{{dev_eui}}.event.{{event}}"
|
||||
.to_string(),
|
||||
exchange: "amq.topic".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -525,6 +526,7 @@ pub struct JoinServerServer {
|
||||
pub ca_cert: String,
|
||||
pub tls_cert: String,
|
||||
pub tls_key: String,
|
||||
pub authorization_header: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Default, Clone)]
|
||||
|
@ -1,3 +1,5 @@
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use aes::cipher::generic_array::GenericArray;
|
||||
use aes::cipher::{BlockEncrypt, KeyInit};
|
||||
use aes::{Aes128, Block};
|
||||
@ -7,14 +9,11 @@ use tracing::debug;
|
||||
|
||||
use lrwn::DevAddr;
|
||||
|
||||
lazy_static! {
|
||||
static ref BEACON_PERIOD: Duration = Duration::try_seconds(128).unwrap();
|
||||
static ref BEACON_RESERVED: Duration = Duration::try_milliseconds(2120).unwrap();
|
||||
static ref BEACON_GUARD: Duration = Duration::try_seconds(3).unwrap();
|
||||
static ref BEACON_WINDOW: Duration = Duration::try_milliseconds(122880).unwrap();
|
||||
static ref PING_PERIOD_BASE: usize = 1 << 12;
|
||||
static ref SLOT_LEN: Duration = Duration::try_milliseconds(30).unwrap();
|
||||
}
|
||||
static BEACON_PERIOD: LazyLock<Duration> = LazyLock::new(|| Duration::try_seconds(128).unwrap());
|
||||
static BEACON_RESERVED: LazyLock<Duration> =
|
||||
LazyLock::new(|| Duration::try_milliseconds(2120).unwrap());
|
||||
static PING_PERIOD_BASE: usize = 1 << 12;
|
||||
static SLOT_LEN: LazyLock<Duration> = LazyLock::new(|| Duration::try_milliseconds(30).unwrap());
|
||||
|
||||
pub fn get_beacon_start(ts: Duration) -> Duration {
|
||||
Duration::try_seconds(ts.num_seconds() - (ts.num_seconds() % BEACON_PERIOD.num_seconds()))
|
||||
@ -26,7 +25,7 @@ pub fn get_ping_offset(beacon_ts: Duration, dev_addr: &DevAddr, ping_nb: usize)
|
||||
return Err(anyhow!("ping_nb must be > 0"));
|
||||
}
|
||||
|
||||
let ping_period = *PING_PERIOD_BASE / ping_nb;
|
||||
let ping_period = PING_PERIOD_BASE / ping_nb;
|
||||
let beacon_time = (beacon_ts.num_seconds() % (1 << 32)) as u32;
|
||||
|
||||
let key_bytes: [u8; 16] = [0x00; 16];
|
||||
@ -54,7 +53,7 @@ pub fn get_next_ping_slot_after(
|
||||
}
|
||||
|
||||
let mut beacon_start_ts = get_beacon_start(after_gps_epoch_ts);
|
||||
let ping_period = *PING_PERIOD_BASE / ping_nb;
|
||||
let ping_period = PING_PERIOD_BASE / ping_nb;
|
||||
|
||||
loop {
|
||||
let ping_offset = get_ping_offset(beacon_start_ts, dev_addr, ping_nb)?;
|
||||
@ -122,7 +121,7 @@ pub mod test {
|
||||
for k in 0..8 {
|
||||
let mut beacon_ts = Duration::zero();
|
||||
let ping_nb: usize = 1 << k;
|
||||
let ping_period = *PING_PERIOD_BASE / ping_nb;
|
||||
let ping_period = PING_PERIOD_BASE / ping_nb;
|
||||
let dev_addr = DevAddr::from_be_bytes([0, 0, 0, 0]);
|
||||
|
||||
for _ in 0..100000 {
|
||||
|
@ -707,7 +707,8 @@ impl Data {
|
||||
fn set_phy_payloads(&mut self) -> Result<()> {
|
||||
trace!("Setting downlink PHYPayloads");
|
||||
let mut f_pending = self.more_device_queue_items;
|
||||
let ds = self.device.get_device_session()?;
|
||||
let dev_addr = self.device.get_dev_addr()?;
|
||||
let ds = self.device.get_device_session_mut()?;
|
||||
|
||||
for item in self.downlink_frame_items.iter_mut() {
|
||||
let mut mac_size: usize = 0;
|
||||
@ -729,18 +730,20 @@ impl Data {
|
||||
for mac in &**mac_set {
|
||||
mac_commands.push(mac.clone());
|
||||
}
|
||||
|
||||
mac_command::set_pending(ds, mac_set)?;
|
||||
}
|
||||
|
||||
// LoRaWAN MHDR
|
||||
let mut mhdr = lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
};
|
||||
|
||||
// LoRaWAN MAC payload
|
||||
let mut mac_pl = lrwn::MACPayload {
|
||||
fhdr: lrwn::FHDR {
|
||||
devaddr: self.device.get_dev_addr()?,
|
||||
devaddr: dev_addr,
|
||||
f_cnt: ds.n_f_cnt_down,
|
||||
f_ctrl: lrwn::FCtrl {
|
||||
adr: !self.network_conf.adr_disabled,
|
||||
@ -791,7 +794,7 @@ impl Data {
|
||||
mac_pl.frm_payload = Some(lrwn::FRMPayload::Raw(qi.data.clone()));
|
||||
|
||||
if qi.confirmed {
|
||||
mhdr.m_type = lrwn::MType::ConfirmedDataDown;
|
||||
mhdr.f_type = lrwn::FType::ConfirmedDataDown;
|
||||
}
|
||||
|
||||
item.remaining_payload_size -= qi.data.len();
|
||||
@ -864,7 +867,7 @@ impl Data {
|
||||
for item in self.downlink_frame.items.iter_mut() {
|
||||
let mut relay_phy = lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -912,7 +915,7 @@ impl Data {
|
||||
for item in self.downlink_frame_items.iter_mut() {
|
||||
let mut relay_phy = lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -1196,8 +1199,6 @@ impl Data {
|
||||
if let Some(block) =
|
||||
maccommand::new_channel::request(3, ¤t_channels, &wanted_channels)
|
||||
{
|
||||
mac_command::set_pending(&self.device.dev_eui, lrwn::CID::NewChannelReq, &block)
|
||||
.await?;
|
||||
self.mac_commands.push(block);
|
||||
}
|
||||
|
||||
@ -1207,7 +1208,7 @@ impl Data {
|
||||
// Note: this must come before ADR!
|
||||
async fn _request_channel_mask_reconfiguration(&mut self) -> Result<()> {
|
||||
trace!("Requesting channel-mask reconfiguration");
|
||||
let ds = self.device.get_device_session()?;
|
||||
let ds = self.device.get_device_session_mut()?;
|
||||
|
||||
let enabled_uplink_channel_indices: Vec<usize> = ds
|
||||
.enabled_uplink_channel_indices
|
||||
@ -1239,7 +1240,6 @@ impl Data {
|
||||
.collect(),
|
||||
);
|
||||
|
||||
mac_command::set_pending(&self.device.dev_eui, lrwn::CID::LinkADRReq, &set).await?;
|
||||
self.mac_commands.push(set);
|
||||
|
||||
Ok(())
|
||||
@ -1257,12 +1257,15 @@ impl Data {
|
||||
.get_data_rate(self.uplink_frame_set.as_ref().unwrap().dr)?;
|
||||
|
||||
let ufs = self.uplink_frame_set.as_ref().unwrap();
|
||||
let ds = self.device.get_device_session()?;
|
||||
let dev_eui = self.device.dev_eui;
|
||||
let device_variables = self.device.variables.into_hashmap();
|
||||
let ds = self.device.get_device_session_mut()?;
|
||||
|
||||
let req = adr::Request {
|
||||
dev_eui,
|
||||
device_variables,
|
||||
region_config_id: ufs.region_config_id.clone(),
|
||||
region_common_name: ufs.region_common_name,
|
||||
dev_eui: self.device.dev_eui,
|
||||
mac_version: self.device_profile.mac_version,
|
||||
reg_params_revision: self.device_profile.reg_params_revision,
|
||||
adr: ds.adr,
|
||||
@ -1291,7 +1294,6 @@ impl Data {
|
||||
max_dr: self.network_conf.max_dr,
|
||||
uplink_history: ds.uplink_adr_history.clone(),
|
||||
skip_f_cnt_check: ds.skip_f_cnt_check,
|
||||
device_variables: self.device.variables.into_hashmap(),
|
||||
};
|
||||
|
||||
let resp = adr::handle(&self.device_profile.adr_algorithm_id, &req).await;
|
||||
@ -1304,24 +1306,14 @@ impl Data {
|
||||
{
|
||||
let mut adr_set = false;
|
||||
for set in self.mac_commands.iter_mut() {
|
||||
let mut is_link_adr_set = false;
|
||||
|
||||
for mac in &mut **set {
|
||||
if let lrwn::MACCommand::LinkADRReq(pl) = mac {
|
||||
pl.dr = resp.dr;
|
||||
pl.tx_power = resp.tx_power_index;
|
||||
pl.redundancy.nb_rep = resp.nb_trans;
|
||||
|
||||
adr_set = true;
|
||||
is_link_adr_set = true;
|
||||
}
|
||||
}
|
||||
|
||||
if is_link_adr_set {
|
||||
// We need to update the pending mac-command.
|
||||
mac_command::set_pending(&self.device.dev_eui, lrwn::CID::LinkADRReq, set)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
|
||||
// There was no existing LinkADRReq to be sent, we need to construct a new one.
|
||||
@ -1358,7 +1350,6 @@ impl Data {
|
||||
},
|
||||
)]);
|
||||
|
||||
mac_command::set_pending(&self.device.dev_eui, lrwn::CID::LinkADRReq, &set).await?;
|
||||
self.mac_commands.push(set);
|
||||
}
|
||||
}
|
||||
@ -1406,7 +1397,7 @@ impl Data {
|
||||
async fn _request_rejoin_param_setup(&mut self) -> Result<()> {
|
||||
trace!("Requesting rejoin param setup");
|
||||
|
||||
let ds = self.device.get_device_session()?;
|
||||
let ds = self.device.get_device_session_mut()?;
|
||||
|
||||
// Rejoin-request is disabled or device does not support LoRaWAN 1.1.
|
||||
if !self.network_conf.rejoin_request.enabled
|
||||
@ -1423,8 +1414,6 @@ impl Data {
|
||||
self.network_conf.rejoin_request.max_time_n,
|
||||
self.network_conf.rejoin_request.max_count_n,
|
||||
);
|
||||
mac_command::set_pending(&self.device.dev_eui, lrwn::CID::RejoinParamSetupReq, &set)
|
||||
.await?;
|
||||
self.mac_commands.push(set);
|
||||
}
|
||||
|
||||
@ -1434,7 +1423,7 @@ impl Data {
|
||||
async fn _set_ping_slot_parameters(&mut self) -> Result<()> {
|
||||
trace!("Setting ping-slot parameters");
|
||||
|
||||
let ds = self.device.get_device_session()?;
|
||||
let ds = self.device.get_device_session_mut()?;
|
||||
|
||||
if !self.device_profile.supports_class_b {
|
||||
return Ok(());
|
||||
@ -1447,8 +1436,6 @@ impl Data {
|
||||
self.network_conf.class_b.ping_slot_dr,
|
||||
self.network_conf.class_b.ping_slot_frequency,
|
||||
);
|
||||
mac_command::set_pending(&self.device.dev_eui, lrwn::CID::PingSlotChannelReq, &set)
|
||||
.await?;
|
||||
self.mac_commands.push(set);
|
||||
}
|
||||
|
||||
@ -1457,7 +1444,7 @@ impl Data {
|
||||
|
||||
async fn _set_rx_parameters(&mut self) -> Result<()> {
|
||||
trace!("Setting rx parameters");
|
||||
let ds = self.device.get_device_session()?;
|
||||
let ds = self.device.get_device_session_mut()?;
|
||||
|
||||
if ds.rx2_frequency != self.network_conf.rx2_frequency
|
||||
|| ds.rx2_dr as u8 != self.network_conf.rx2_dr
|
||||
@ -1468,8 +1455,6 @@ impl Data {
|
||||
self.network_conf.rx2_frequency,
|
||||
self.network_conf.rx2_dr,
|
||||
);
|
||||
mac_command::set_pending(&self.device.dev_eui, lrwn::CID::RxParamSetupReq, &set)
|
||||
.await?;
|
||||
self.mac_commands.push(set);
|
||||
}
|
||||
|
||||
@ -1481,8 +1466,6 @@ impl Data {
|
||||
|
||||
if dev_rx1_delay != req_rx1_delay {
|
||||
let set = maccommand::rx_timing_setup::request(req_rx1_delay);
|
||||
mac_command::set_pending(&self.device.dev_eui, lrwn::CID::RxTimingSetupReq, &set)
|
||||
.await?;
|
||||
self.mac_commands.push(set);
|
||||
}
|
||||
|
||||
@ -1491,7 +1474,7 @@ impl Data {
|
||||
|
||||
async fn _set_tx_parameters(&mut self) -> Result<()> {
|
||||
trace!("Setting tx parameters");
|
||||
let ds = self.device.get_device_session()?;
|
||||
let ds = self.device.get_device_session_mut()?;
|
||||
|
||||
if !self
|
||||
.region_conf
|
||||
@ -1512,8 +1495,6 @@ impl Data {
|
||||
self.network_conf.downlink_dwell_time_400ms,
|
||||
uplink_eirp_index,
|
||||
);
|
||||
mac_command::set_pending(&self.device.dev_eui, lrwn::CID::TxParamSetupReq, &set)
|
||||
.await?;
|
||||
self.mac_commands.push(set);
|
||||
}
|
||||
|
||||
@ -1567,8 +1548,8 @@ impl Data {
|
||||
|| rd.uplink_limit_reload_rate
|
||||
!= device.relay_ed_uplink_limit_reload_rate as u32
|
||||
{
|
||||
let d = device::get(&device.dev_eui).await?;
|
||||
let ds = match d.get_device_session() {
|
||||
let mut d = device::get(&device.dev_eui).await?;
|
||||
let ds = match d.get_device_session_mut() {
|
||||
Ok(v) => v,
|
||||
Err(_) => {
|
||||
// It is valid that the device is no longer activated.
|
||||
@ -1595,13 +1576,17 @@ impl Data {
|
||||
},
|
||||
),
|
||||
]);
|
||||
mac_command::set_pending(
|
||||
&dev_eui,
|
||||
lrwn::CID::UpdateUplinkListReq,
|
||||
&set,
|
||||
self.mac_commands.push(set);
|
||||
|
||||
// Update device-session of device.
|
||||
device::partial_update(
|
||||
d.dev_eui,
|
||||
&device::DeviceChangeset {
|
||||
device_session: Some(d.device_session.clone()),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
self.mac_commands.push(set);
|
||||
|
||||
rd.dev_addr = dev_addr.to_vec();
|
||||
rd.root_wor_s_key = root_wor_s_key.to_vec();
|
||||
@ -1651,8 +1636,6 @@ impl Data {
|
||||
root_wor_s_key,
|
||||
},
|
||||
)]);
|
||||
mac_command::set_pending(&dev_eui, lrwn::CID::UpdateUplinkListReq, &set)
|
||||
.await?;
|
||||
self.mac_commands.push(set);
|
||||
|
||||
ds.relay
|
||||
@ -1788,8 +1771,6 @@ impl Data {
|
||||
|
||||
if !commands.is_empty() {
|
||||
let set = lrwn::MACCommandSet::new(commands);
|
||||
mac_command::set_pending(&self.device.dev_eui, lrwn::CID::CtrlUplinkListReq, &set)
|
||||
.await?;
|
||||
self.mac_commands.push(set);
|
||||
}
|
||||
|
||||
@ -1799,7 +1780,6 @@ impl Data {
|
||||
async fn _configure_fwd_limit_req(&mut self) -> Result<()> {
|
||||
trace!("Configuring Relay Fwd Limit");
|
||||
|
||||
let dev_eui = self.device.dev_eui;
|
||||
let ds = self.device.get_device_session_mut()?;
|
||||
let relay_params = self.device_profile.relay_params.clone().unwrap_or_default();
|
||||
|
||||
@ -1827,24 +1807,22 @@ impl Data {
|
||||
let set = lrwn::MACCommandSet::new(vec![lrwn::MACCommand::ConfigureFwdLimitReq(
|
||||
lrwn::ConfigureFwdLimitReqPayload {
|
||||
reload_rate: lrwn::FwdLimitReloadRatePL {
|
||||
overall_reload_rate: relay_params.relay_overall_limit_reload_rate as u8,
|
||||
overall_reload_rate: relay_params.relay_overall_limit_reload_rate,
|
||||
global_uplink_reload_rate: relay_params
|
||||
.relay_global_uplink_limit_reload_rate
|
||||
as u8,
|
||||
notify_reload_rate: relay_params.relay_notify_limit_reload_rate as u8,
|
||||
join_req_reload_rate: relay_params.relay_join_req_limit_reload_rate as u8,
|
||||
.relay_global_uplink_limit_reload_rate,
|
||||
notify_reload_rate: relay_params.relay_notify_limit_reload_rate,
|
||||
join_req_reload_rate: relay_params.relay_join_req_limit_reload_rate,
|
||||
reset_limit_counter: lrwn::ResetLimitCounter::NoChange,
|
||||
},
|
||||
load_capacity: lrwn::FwdLimitLoadCapacityPL {
|
||||
overall_limit_size: relay_params.relay_overall_limit_bucket_size as u8,
|
||||
global_uplink_limit_size: relay_params.relay_global_uplink_limit_bucket_size
|
||||
as u8,
|
||||
notify_limit_size: relay_params.relay_notify_limit_bucket_size as u8,
|
||||
join_req_limit_size: relay_params.relay_join_req_limit_bucket_size as u8,
|
||||
overall_limit_size: relay_params.relay_overall_limit_bucket_size,
|
||||
global_uplink_limit_size: relay_params
|
||||
.relay_global_uplink_limit_bucket_size,
|
||||
notify_limit_size: relay_params.relay_notify_limit_bucket_size,
|
||||
join_req_limit_size: relay_params.relay_join_req_limit_bucket_size,
|
||||
},
|
||||
},
|
||||
)]);
|
||||
mac_command::set_pending(&dev_eui, lrwn::CID::ConfigureFwdLimitReq, &set).await?;
|
||||
self.mac_commands.push(set);
|
||||
}
|
||||
|
||||
@ -1916,7 +1894,6 @@ impl Data {
|
||||
}
|
||||
|
||||
let set = lrwn::MACCommandSet::new(commands);
|
||||
mac_command::set_pending(&self.device.dev_eui, lrwn::CID::FilterListReq, &set).await?;
|
||||
self.mac_commands.push(set);
|
||||
|
||||
// The deletes needs to be processed before we can add new entries.
|
||||
@ -1945,8 +1922,6 @@ impl Data {
|
||||
filter_list_eui: vec![],
|
||||
},
|
||||
)]);
|
||||
mac_command::set_pending(&self.device.dev_eui, lrwn::CID::FilterListReq, &set)
|
||||
.await?;
|
||||
self.mac_commands.push(set);
|
||||
|
||||
// Return because we can't add multiple sets and if we would combine
|
||||
@ -1978,7 +1953,6 @@ impl Data {
|
||||
filter_list_eui: eui,
|
||||
},
|
||||
)]);
|
||||
mac_command::set_pending(&dev_eui, lrwn::CID::FilterListReq, &set).await?;
|
||||
self.mac_commands.push(set);
|
||||
|
||||
f.join_eui = device.join_eui.to_vec();
|
||||
@ -2010,7 +1984,6 @@ impl Data {
|
||||
filter_list_eui: eui,
|
||||
},
|
||||
)]);
|
||||
mac_command::set_pending(&dev_eui, lrwn::CID::FilterListReq, &set).await?;
|
||||
self.mac_commands.push(set);
|
||||
|
||||
ds.relay
|
||||
@ -2038,7 +2011,6 @@ impl Data {
|
||||
async fn _update_relay_conf(&mut self) -> Result<()> {
|
||||
trace!("Updating Relay Conf");
|
||||
|
||||
let dev_eui = self.device.dev_eui;
|
||||
let ds = self.device.get_device_session_mut()?;
|
||||
let relay_params = self.device_profile.relay_params.clone().unwrap_or_default();
|
||||
|
||||
@ -2052,7 +2024,7 @@ impl Data {
|
||||
if relay.enabled != relay_params.relay_enabled
|
||||
|| relay.cad_periodicity != relay_params.relay_cad_periodicity as u32
|
||||
|| relay.default_channel_index != relay_params.default_channel_index as u32
|
||||
|| relay.second_channel_freq != relay_params.second_channel_freq as u32
|
||||
|| relay.second_channel_freq != relay_params.second_channel_freq
|
||||
|| relay.second_channel_dr != relay_params.second_channel_dr as u32
|
||||
|| relay.second_channel_ack_offset != relay_params.second_channel_ack_offset as u32
|
||||
{
|
||||
@ -2063,20 +2035,19 @@ impl Data {
|
||||
true => 1,
|
||||
false => 0,
|
||||
},
|
||||
cad_periodicity: relay_params.relay_cad_periodicity as u8,
|
||||
default_ch_idx: relay_params.default_channel_index as u8,
|
||||
cad_periodicity: relay_params.relay_cad_periodicity,
|
||||
default_ch_idx: relay_params.default_channel_index,
|
||||
second_ch_idx: if relay_params.second_channel_freq > 0 {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
},
|
||||
second_ch_dr: relay_params.second_channel_dr as u8,
|
||||
second_ch_ack_offset: relay_params.second_channel_ack_offset as u8,
|
||||
second_ch_dr: relay_params.second_channel_dr,
|
||||
second_ch_ack_offset: relay_params.second_channel_ack_offset,
|
||||
},
|
||||
second_ch_freq: relay_params.second_channel_freq as u32,
|
||||
second_ch_freq: relay_params.second_channel_freq,
|
||||
},
|
||||
)]);
|
||||
mac_command::set_pending(&dev_eui, lrwn::CID::RelayConfReq, &set).await?;
|
||||
self.mac_commands.push(set);
|
||||
}
|
||||
|
||||
@ -2088,7 +2059,6 @@ impl Data {
|
||||
async fn _update_end_device_conf(&mut self) -> Result<()> {
|
||||
trace!("Updating End Device Conf");
|
||||
|
||||
let dev_eui = self.device.dev_eui;
|
||||
let ds = self.device.get_device_session_mut()?;
|
||||
let relay_params = self.device_profile.relay_params.clone().unwrap_or_default();
|
||||
|
||||
@ -2102,7 +2072,7 @@ impl Data {
|
||||
if relay.ed_activation_mode != relay_params.ed_activation_mode.to_u8() as u32
|
||||
|| relay.ed_smart_enable_level != relay_params.ed_smart_enable_level as u32
|
||||
|| relay.ed_back_off != relay_params.ed_back_off as u32
|
||||
|| relay.second_channel_freq != relay_params.second_channel_freq as u32
|
||||
|| relay.second_channel_freq != relay_params.second_channel_freq
|
||||
|| relay.second_channel_dr != relay_params.second_channel_dr as u32
|
||||
|| relay.second_channel_ack_offset != relay_params.second_channel_ack_offset as u32
|
||||
{
|
||||
@ -2110,22 +2080,21 @@ impl Data {
|
||||
lrwn::EndDeviceConfReqPayload {
|
||||
activation_relay_mode: lrwn::ActivationRelayMode {
|
||||
relay_mode_activation: relay_params.ed_activation_mode,
|
||||
smart_enable_level: relay_params.ed_smart_enable_level as u8,
|
||||
smart_enable_level: relay_params.ed_smart_enable_level,
|
||||
},
|
||||
channel_settings_ed: lrwn::ChannelSettingsED {
|
||||
second_ch_ack_offset: relay_params.second_channel_ack_offset as u8,
|
||||
second_ch_dr: relay_params.second_channel_dr as u8,
|
||||
second_ch_ack_offset: relay_params.second_channel_ack_offset,
|
||||
second_ch_dr: relay_params.second_channel_dr,
|
||||
second_ch_idx: if relay_params.second_channel_freq > 0 {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
},
|
||||
backoff: relay_params.ed_back_off as u8,
|
||||
backoff: relay_params.ed_back_off,
|
||||
},
|
||||
second_ch_freq: relay_params.second_channel_freq as u32,
|
||||
second_ch_freq: relay_params.second_channel_freq,
|
||||
},
|
||||
)]);
|
||||
mac_command::set_pending(&dev_eui, lrwn::CID::EndDeviceConfReq, &set).await?;
|
||||
self.mac_commands.push(set);
|
||||
}
|
||||
|
||||
|
@ -466,7 +466,7 @@ impl JoinAccept<'_> {
|
||||
|
||||
let mut relay_phy = lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
|
@ -199,7 +199,7 @@ impl Multicast {
|
||||
|
||||
let mut phy = lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
|
@ -3,7 +3,7 @@ use chrono::{Duration, Utc};
|
||||
use tracing::{error, info, span, trace, Instrument, Level};
|
||||
use uuid::Uuid;
|
||||
|
||||
use lrwn::{AES128Key, MType, Payload, PhyPayload, EUI64};
|
||||
use lrwn::{AES128Key, FType, Payload, PhyPayload, EUI64};
|
||||
|
||||
use crate::api::helpers::ToProto;
|
||||
use crate::storage::{
|
||||
@ -589,13 +589,13 @@ impl TxAck {
|
||||
tx_info: dfi.tx_info.clone(),
|
||||
downlink_id: gw_df.downlink_id,
|
||||
gateway_id: gw_df.gateway_id.clone(),
|
||||
m_type: match &phy.mhdr.m_type {
|
||||
MType::JoinAccept => common::MType::JoinAccept,
|
||||
MType::UnconfirmedDataDown => common::MType::UnconfirmedDataDown,
|
||||
MType::ConfirmedDataDown => common::MType::ConfirmedDataDown,
|
||||
MType::Proprietary => common::MType::Proprietary,
|
||||
f_type: match &phy.mhdr.f_type {
|
||||
FType::JoinAccept => common::FType::JoinAccept,
|
||||
FType::UnconfirmedDataDown => common::FType::UnconfirmedDataDown,
|
||||
FType::ConfirmedDataDown => common::FType::ConfirmedDataDown,
|
||||
FType::Proprietary => common::FType::Proprietary,
|
||||
_ => {
|
||||
return Err(anyhow!("Unepxected MType: {}", phy.mhdr.m_type));
|
||||
return Err(anyhow!("Unepxected FType: {}", phy.mhdr.f_type));
|
||||
}
|
||||
}
|
||||
.into(),
|
||||
@ -658,7 +658,7 @@ impl TxAck {
|
||||
tx_info: dfl.tx_info.clone(),
|
||||
downlink_id: dfl.downlink_id,
|
||||
gateway_id: dfl.gateway_id.clone(),
|
||||
m_type: dfl.m_type,
|
||||
f_type: dfl.f_type,
|
||||
dev_addr: dfl.dev_addr.clone(),
|
||||
dev_eui: dfl.dev_eui.clone(),
|
||||
plaintext_f_opts: true,
|
||||
@ -719,7 +719,7 @@ impl TxAck {
|
||||
} else {
|
||||
0
|
||||
} as u32,
|
||||
message_type: phy.mhdr.m_type.to_proto().into(),
|
||||
frame_type: phy.mhdr.f_type.to_proto().into(),
|
||||
gateway_id: df.downlink_frame.as_ref().unwrap().gateway_id.clone(),
|
||||
};
|
||||
|
||||
@ -803,15 +803,15 @@ impl TxAck {
|
||||
}
|
||||
|
||||
fn is_unconfirmed_downlink(&self) -> bool {
|
||||
if self.phy_payload.as_ref().unwrap().mhdr.m_type == lrwn::MType::UnconfirmedDataDown {
|
||||
if self.phy_payload.as_ref().unwrap().mhdr.f_type == lrwn::FType::UnconfirmedDataDown {
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn is_unconfirmed_downlink_relayed(&self) -> bool {
|
||||
if self.phy_payload_relayed.as_ref().unwrap().mhdr.m_type
|
||||
== lrwn::MType::UnconfirmedDataDown
|
||||
if self.phy_payload_relayed.as_ref().unwrap().mhdr.f_type
|
||||
== lrwn::FType::UnconfirmedDataDown
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -819,14 +819,14 @@ impl TxAck {
|
||||
}
|
||||
|
||||
fn is_confirmed_downlink(&self) -> bool {
|
||||
if self.phy_payload.as_ref().unwrap().mhdr.m_type == lrwn::MType::ConfirmedDataDown {
|
||||
if self.phy_payload.as_ref().unwrap().mhdr.f_type == lrwn::FType::ConfirmedDataDown {
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn is_confirmed_downlink_relayed(&self) -> bool {
|
||||
if self.phy_payload_relayed.as_ref().unwrap().mhdr.m_type == lrwn::MType::ConfirmedDataDown
|
||||
if self.phy_payload_relayed.as_ref().unwrap().mhdr.f_type == lrwn::FType::ConfirmedDataDown
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use anyhow::Result;
|
||||
use async_trait::async_trait;
|
||||
use tokio::sync::RwLock;
|
||||
@ -6,11 +8,10 @@ use chirpstack_api::gw;
|
||||
|
||||
use super::GatewayBackend;
|
||||
|
||||
lazy_static! {
|
||||
static ref DOWNLINK_FRAMES: RwLock<Vec<gw::DownlinkFrame>> = RwLock::new(Vec::new());
|
||||
static ref GATEWAY_CONFIGURATIONS: RwLock<Vec<gw::GatewayConfiguration>> =
|
||||
RwLock::new(Vec::new());
|
||||
}
|
||||
static DOWNLINK_FRAMES: LazyLock<RwLock<Vec<gw::DownlinkFrame>>> =
|
||||
LazyLock::new(|| RwLock::new(Vec::new()));
|
||||
static GATEWAY_CONFIGURATIONS: LazyLock<RwLock<Vec<gw::GatewayConfiguration>>> =
|
||||
LazyLock::new(|| RwLock::new(Vec::new()));
|
||||
|
||||
pub async fn reset() {
|
||||
DOWNLINK_FRAMES.write().await.drain(..);
|
||||
|
@ -1,4 +1,5 @@
|
||||
use std::collections::HashMap;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use async_trait::async_trait;
|
||||
@ -11,10 +12,8 @@ use crate::config;
|
||||
pub mod mock;
|
||||
mod mqtt;
|
||||
|
||||
lazy_static! {
|
||||
static ref BACKENDS: RwLock<HashMap<String, Box<dyn GatewayBackend + Sync + Send>>> =
|
||||
RwLock::new(HashMap::new());
|
||||
}
|
||||
static BACKENDS: LazyLock<RwLock<HashMap<String, Box<dyn GatewayBackend + Sync + Send>>>> =
|
||||
LazyLock::new(|| RwLock::new(HashMap::new()));
|
||||
|
||||
#[async_trait]
|
||||
pub trait GatewayBackend {
|
||||
|
@ -1,6 +1,5 @@
|
||||
use std::collections::HashMap;
|
||||
use std::io::Cursor;
|
||||
use std::sync::RwLock;
|
||||
use std::sync::{LazyLock, RwLock};
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::Result;
|
||||
@ -38,27 +37,26 @@ struct CommandLabels {
|
||||
command: String,
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref EVENT_COUNTER: Family<EventLabels, Counter> = {
|
||||
let counter = Family::<EventLabels, Counter>::default();
|
||||
prometheus::register(
|
||||
"gateway_backend_mqtt_events",
|
||||
"Number of events received",
|
||||
counter.clone(),
|
||||
);
|
||||
counter
|
||||
};
|
||||
static ref COMMAND_COUNTER: Family<CommandLabels, Counter> = {
|
||||
let counter = Family::<CommandLabels, Counter>::default();
|
||||
prometheus::register(
|
||||
"gateway_backend_mqtt_commands",
|
||||
"Number of commands sent",
|
||||
counter.clone(),
|
||||
);
|
||||
counter
|
||||
};
|
||||
static ref GATEWAY_JSON: RwLock<HashMap<String, bool>> = RwLock::new(HashMap::new());
|
||||
}
|
||||
static EVENT_COUNTER: LazyLock<Family<EventLabels, Counter>> = LazyLock::new(|| {
|
||||
let counter = Family::<EventLabels, Counter>::default();
|
||||
prometheus::register(
|
||||
"gateway_backend_mqtt_events",
|
||||
"Number of events received",
|
||||
counter.clone(),
|
||||
);
|
||||
counter
|
||||
});
|
||||
static COMMAND_COUNTER: LazyLock<Family<CommandLabels, Counter>> = LazyLock::new(|| {
|
||||
let counter = Family::<CommandLabels, Counter>::default();
|
||||
prometheus::register(
|
||||
"gateway_backend_mqtt_commands",
|
||||
"Number of commands sent",
|
||||
counter.clone(),
|
||||
);
|
||||
counter
|
||||
});
|
||||
static GATEWAY_JSON: LazyLock<RwLock<HashMap<String, bool>>> =
|
||||
LazyLock::new(|| RwLock::new(HashMap::new()));
|
||||
|
||||
pub struct MqttBackend<'a> {
|
||||
client: AsyncClient,
|
||||
@ -353,7 +351,7 @@ async fn message_callback(
|
||||
.inc();
|
||||
let mut event = match json {
|
||||
true => serde_json::from_slice(&p.payload)?,
|
||||
false => chirpstack_api::gw::UplinkFrame::decode(&mut Cursor::new(&p.payload))?,
|
||||
false => chirpstack_api::gw::UplinkFrame::decode(p.payload.as_ref())?,
|
||||
};
|
||||
|
||||
if v4_migrate {
|
||||
@ -378,7 +376,7 @@ async fn message_callback(
|
||||
.inc();
|
||||
let mut event = match json {
|
||||
true => serde_json::from_slice(&p.payload)?,
|
||||
false => chirpstack_api::gw::GatewayStats::decode(&mut Cursor::new(&p.payload))?,
|
||||
false => chirpstack_api::gw::GatewayStats::decode(p.payload.as_ref())?,
|
||||
};
|
||||
|
||||
if v4_migrate {
|
||||
@ -402,7 +400,7 @@ async fn message_callback(
|
||||
.inc();
|
||||
let mut event = match json {
|
||||
true => serde_json::from_slice(&p.payload)?,
|
||||
false => chirpstack_api::gw::DownlinkTxAck::decode(&mut Cursor::new(&p.payload))?,
|
||||
false => chirpstack_api::gw::DownlinkTxAck::decode(p.payload.as_ref())?,
|
||||
};
|
||||
|
||||
if v4_migrate {
|
||||
@ -411,18 +409,18 @@ async fn message_callback(
|
||||
|
||||
set_gateway_json(&event.gateway_id, json);
|
||||
tokio::spawn(downlink::tx_ack::TxAck::handle(event));
|
||||
} else if topic.ends_with("/mesh-heartbeat") {
|
||||
} else if topic.ends_with("/mesh") {
|
||||
EVENT_COUNTER
|
||||
.get_or_create(&EventLabels {
|
||||
event: "mesh-heartbeat".to_string(),
|
||||
event: "mesh".to_string(),
|
||||
})
|
||||
.inc();
|
||||
let event = match json {
|
||||
true => serde_json::from_slice(&p.payload)?,
|
||||
false => chirpstack_api::gw::MeshHeartbeat::decode(&mut Cursor::new(&p.payload))?,
|
||||
false => chirpstack_api::gw::MeshEvent::decode(p.payload.as_ref())?,
|
||||
};
|
||||
|
||||
tokio::spawn(uplink::mesh::MeshHeartbeat::handle(event));
|
||||
tokio::spawn(uplink::mesh::Mesh::handle(event));
|
||||
} else {
|
||||
return Err(anyhow!("Unknown event type"));
|
||||
}
|
||||
|
@ -1,82 +1,85 @@
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use chrono::{DateTime, Duration, TimeZone, Utc};
|
||||
|
||||
lazy_static! {
|
||||
static ref GPS_EPOCH_TIME: DateTime<Utc> = Utc.with_ymd_and_hms(1980, 1, 6, 0, 0, 0).unwrap();
|
||||
static ref LEAP_SECONDS_TABLE: Vec<(DateTime<Utc>, Duration)> = vec![
|
||||
static GPS_EPOCH_TIME: LazyLock<DateTime<Utc>> =
|
||||
LazyLock::new(|| Utc.with_ymd_and_hms(1980, 1, 6, 0, 0, 0).unwrap());
|
||||
static LEAP_SECONDS_TABLE: LazyLock<Vec<(DateTime<Utc>, Duration)>> = LazyLock::new(|| {
|
||||
vec![
|
||||
(
|
||||
Utc.with_ymd_and_hms(1981, 6, 30, 23, 59, 59).unwrap(),
|
||||
Duration::try_seconds(1).unwrap()
|
||||
Duration::try_seconds(1).unwrap(),
|
||||
),
|
||||
(
|
||||
Utc.with_ymd_and_hms(1982, 6, 30, 23, 59, 59).unwrap(),
|
||||
Duration::try_seconds(1).unwrap()
|
||||
Duration::try_seconds(1).unwrap(),
|
||||
),
|
||||
(
|
||||
Utc.with_ymd_and_hms(1983, 6, 30, 23, 59, 59).unwrap(),
|
||||
Duration::try_seconds(1).unwrap()
|
||||
Duration::try_seconds(1).unwrap(),
|
||||
),
|
||||
(
|
||||
Utc.with_ymd_and_hms(1985, 6, 30, 23, 59, 59).unwrap(),
|
||||
Duration::try_seconds(1).unwrap()
|
||||
Duration::try_seconds(1).unwrap(),
|
||||
),
|
||||
(
|
||||
Utc.with_ymd_and_hms(1987, 12, 31, 23, 59, 59).unwrap(),
|
||||
Duration::try_seconds(1).unwrap()
|
||||
Duration::try_seconds(1).unwrap(),
|
||||
),
|
||||
(
|
||||
Utc.with_ymd_and_hms(1989, 12, 31, 23, 59, 59).unwrap(),
|
||||
Duration::try_seconds(1).unwrap()
|
||||
Duration::try_seconds(1).unwrap(),
|
||||
),
|
||||
(
|
||||
Utc.with_ymd_and_hms(1990, 12, 31, 23, 59, 59).unwrap(),
|
||||
Duration::try_seconds(1).unwrap()
|
||||
Duration::try_seconds(1).unwrap(),
|
||||
),
|
||||
(
|
||||
Utc.with_ymd_and_hms(1992, 6, 30, 23, 59, 59).unwrap(),
|
||||
Duration::try_seconds(1).unwrap()
|
||||
Duration::try_seconds(1).unwrap(),
|
||||
),
|
||||
(
|
||||
Utc.with_ymd_and_hms(1993, 6, 30, 23, 59, 59).unwrap(),
|
||||
Duration::try_seconds(1).unwrap()
|
||||
Duration::try_seconds(1).unwrap(),
|
||||
),
|
||||
(
|
||||
Utc.with_ymd_and_hms(1994, 6, 30, 23, 59, 59).unwrap(),
|
||||
Duration::try_seconds(1).unwrap()
|
||||
Duration::try_seconds(1).unwrap(),
|
||||
),
|
||||
(
|
||||
Utc.with_ymd_and_hms(1995, 12, 31, 23, 59, 59).unwrap(),
|
||||
Duration::try_seconds(1).unwrap()
|
||||
Duration::try_seconds(1).unwrap(),
|
||||
),
|
||||
(
|
||||
Utc.with_ymd_and_hms(1997, 6, 30, 23, 59, 59).unwrap(),
|
||||
Duration::try_seconds(1).unwrap()
|
||||
Duration::try_seconds(1).unwrap(),
|
||||
),
|
||||
(
|
||||
Utc.with_ymd_and_hms(1998, 12, 31, 23, 59, 59).unwrap(),
|
||||
Duration::try_seconds(1).unwrap()
|
||||
Duration::try_seconds(1).unwrap(),
|
||||
),
|
||||
(
|
||||
Utc.with_ymd_and_hms(2005, 12, 31, 23, 59, 59).unwrap(),
|
||||
Duration::try_seconds(1).unwrap()
|
||||
Duration::try_seconds(1).unwrap(),
|
||||
),
|
||||
(
|
||||
Utc.with_ymd_and_hms(2008, 12, 31, 23, 59, 59).unwrap(),
|
||||
Duration::try_seconds(1).unwrap()
|
||||
Duration::try_seconds(1).unwrap(),
|
||||
),
|
||||
(
|
||||
Utc.with_ymd_and_hms(2012, 6, 30, 23, 59, 59).unwrap(),
|
||||
Duration::try_seconds(1).unwrap()
|
||||
Duration::try_seconds(1).unwrap(),
|
||||
),
|
||||
(
|
||||
Utc.with_ymd_and_hms(2015, 6, 30, 23, 59, 59).unwrap(),
|
||||
Duration::try_seconds(1).unwrap()
|
||||
Duration::try_seconds(1).unwrap(),
|
||||
),
|
||||
(
|
||||
Utc.with_ymd_and_hms(2016, 12, 31, 23, 59, 59).unwrap(),
|
||||
Duration::try_seconds(1).unwrap()
|
||||
Duration::try_seconds(1).unwrap(),
|
||||
),
|
||||
];
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
pub trait ToGpsTime {
|
||||
fn to_gps_time(&self) -> Duration;
|
||||
|
@ -1,4 +1,5 @@
|
||||
use std::collections::HashMap;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use anyhow::Result;
|
||||
use async_trait::async_trait;
|
||||
@ -19,15 +20,14 @@ use chirpstack_api::integration;
|
||||
// implement re-connect on error. To reconnect within the Integration struct would require
|
||||
// mutability of the Integration struct, which is not possible without changing the
|
||||
// IntegrationTrait as we would need to change the (&self, ...) signatures to (&mut self, ...).
|
||||
lazy_static! {
|
||||
static ref CONNECTION: RwLock<Option<Connection>> = RwLock::new(None);
|
||||
static ref CHANNEL: RwLock<Option<Channel>> = RwLock::new(None);
|
||||
}
|
||||
static CONNECTION: LazyLock<RwLock<Option<Connection>>> = LazyLock::new(|| RwLock::new(None));
|
||||
static CHANNEL: LazyLock<RwLock<Option<Channel>>> = LazyLock::new(|| RwLock::new(None));
|
||||
|
||||
pub struct Integration<'a> {
|
||||
templates: Handlebars<'a>,
|
||||
json: bool,
|
||||
url: String,
|
||||
exchange: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
@ -50,6 +50,7 @@ impl<'a> Integration<'a> {
|
||||
templates,
|
||||
url: conf.url.clone(),
|
||||
json: conf.json,
|
||||
exchange: conf.exchange.clone(),
|
||||
};
|
||||
i.connect().await?;
|
||||
|
||||
@ -91,7 +92,7 @@ impl<'a> Integration<'a> {
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.basic_publish(
|
||||
"amq.topic",
|
||||
&self.exchange,
|
||||
&routing_key,
|
||||
BasicPublishOptions::default(),
|
||||
b,
|
||||
@ -128,7 +129,7 @@ impl<'a> Integration<'a> {
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<'a> IntegrationTrait for Integration<'a> {
|
||||
impl IntegrationTrait for Integration<'_> {
|
||||
async fn uplink_event(
|
||||
&self,
|
||||
_vars: &HashMap<String, String>,
|
||||
|
@ -20,6 +20,7 @@ fn get_client() -> Client {
|
||||
.get_or_init(|| {
|
||||
Client::builder()
|
||||
.timeout(Duration::from_secs(5))
|
||||
.use_rustls_tls()
|
||||
.build()
|
||||
.unwrap()
|
||||
})
|
||||
|
@ -107,7 +107,7 @@ impl<'a> Integration<'a> {
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<'a> IntegrationTrait for Integration<'a> {
|
||||
impl IntegrationTrait for Integration<'_> {
|
||||
async fn uplink_event(
|
||||
&self,
|
||||
_vars: &HashMap<String, String>,
|
||||
|
@ -539,7 +539,7 @@ impl<'de> Deserialize<'de> for Eui64Wrapper {
|
||||
|
||||
struct Eui64WrapperVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for Eui64WrapperVisitor {
|
||||
impl Visitor<'_> for Eui64WrapperVisitor {
|
||||
type Value = Eui64Wrapper;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
|
@ -1,4 +1,5 @@
|
||||
use std::collections::HashMap;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use anyhow::Result;
|
||||
use async_trait::async_trait;
|
||||
@ -8,17 +9,22 @@ use chirpstack_api::integration;
|
||||
|
||||
use super::Integration as IntegrationTrait;
|
||||
|
||||
lazy_static! {
|
||||
static ref UPLINK_EVENTS: RwLock<Vec<integration::UplinkEvent>> = RwLock::new(Vec::new());
|
||||
static ref JOIN_EVENTS: RwLock<Vec<integration::JoinEvent>> = RwLock::new(Vec::new());
|
||||
static ref ACK_EVENTS: RwLock<Vec<integration::AckEvent>> = RwLock::new(Vec::new());
|
||||
static ref TXACK_EVENTS: RwLock<Vec<integration::TxAckEvent>> = RwLock::new(Vec::new());
|
||||
static ref LOG_EVENTS: RwLock<Vec<integration::LogEvent>> = RwLock::new(Vec::new());
|
||||
static ref STATUS_EVENTS: RwLock<Vec<integration::StatusEvent>> = RwLock::new(Vec::new());
|
||||
static ref LOCATION_EVENTS: RwLock<Vec<integration::LocationEvent>> = RwLock::new(Vec::new());
|
||||
static ref INTEGRATION_EVENTS: RwLock<Vec<integration::IntegrationEvent>> =
|
||||
RwLock::new(Vec::new());
|
||||
}
|
||||
static UPLINK_EVENTS: LazyLock<RwLock<Vec<integration::UplinkEvent>>> =
|
||||
LazyLock::new(|| RwLock::new(Vec::new()));
|
||||
static JOIN_EVENTS: LazyLock<RwLock<Vec<integration::JoinEvent>>> =
|
||||
LazyLock::new(|| RwLock::new(Vec::new()));
|
||||
static ACK_EVENTS: LazyLock<RwLock<Vec<integration::AckEvent>>> =
|
||||
LazyLock::new(|| RwLock::new(Vec::new()));
|
||||
static TXACK_EVENTS: LazyLock<RwLock<Vec<integration::TxAckEvent>>> =
|
||||
LazyLock::new(|| RwLock::new(Vec::new()));
|
||||
static LOG_EVENTS: LazyLock<RwLock<Vec<integration::LogEvent>>> =
|
||||
LazyLock::new(|| RwLock::new(Vec::new()));
|
||||
static STATUS_EVENTS: LazyLock<RwLock<Vec<integration::StatusEvent>>> =
|
||||
LazyLock::new(|| RwLock::new(Vec::new()));
|
||||
static LOCATION_EVENTS: LazyLock<RwLock<Vec<integration::LocationEvent>>> =
|
||||
LazyLock::new(|| RwLock::new(Vec::new()));
|
||||
static INTEGRATION_EVENTS: LazyLock<RwLock<Vec<integration::IntegrationEvent>>> =
|
||||
LazyLock::new(|| RwLock::new(Vec::new()));
|
||||
|
||||
pub async fn reset() {
|
||||
UPLINK_EVENTS.write().await.drain(..);
|
||||
|
@ -1,5 +1,6 @@
|
||||
use std::collections::HashMap;
|
||||
use std::str::FromStr;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use async_trait::async_trait;
|
||||
@ -33,11 +34,11 @@ mod postgresql;
|
||||
mod redis;
|
||||
mod thingsboard;
|
||||
|
||||
lazy_static! {
|
||||
static ref GLOBAL_INTEGRATIONS: RwLock<Vec<Box<dyn Integration + Sync + Send>>> =
|
||||
RwLock::new(Vec::new());
|
||||
static ref MOCK_INTEGRATION: RwLock<bool> = RwLock::new(false);
|
||||
}
|
||||
static GLOBAL_INTEGRATIONS: LazyLock<RwLock<Vec<Box<dyn Integration + Sync + Send>>>> =
|
||||
LazyLock::new(|| RwLock::new(Vec::new()));
|
||||
|
||||
#[cfg(test)]
|
||||
static MOCK_INTEGRATION: LazyLock<RwLock<bool>> = LazyLock::new(|| RwLock::new(false));
|
||||
|
||||
pub async fn setup() -> Result<()> {
|
||||
info!("Setting up global integrations");
|
||||
|
@ -106,7 +106,7 @@ pub mod test {
|
||||
ch: 0,
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
|
@ -53,7 +53,7 @@ pub mod test {
|
||||
ch: 0,
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
|
@ -338,7 +338,7 @@ pub mod test {
|
||||
ch: 0,
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
|
@ -77,7 +77,7 @@ pub mod test {
|
||||
ch: 0,
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
|
@ -33,7 +33,7 @@ pub mod update_uplink_list;
|
||||
// This returns the mac-commands which must be sent back to the device as response and a bool
|
||||
// indicating if a downlink must be sent. For some mac-commands, no mac-command answer is required,
|
||||
// but the device expects a downlink as confirmation, even if the downlink frame is empty.
|
||||
pub async fn handle_uplink<'a>(
|
||||
pub async fn handle_uplink(
|
||||
uplink_frame_set: &UplinkFrameSet,
|
||||
cmds: &lrwn::MACCommandSet,
|
||||
tenant: &tenant::Tenant,
|
||||
@ -77,7 +77,7 @@ pub async fn handle_uplink<'a>(
|
||||
);
|
||||
|
||||
// Get pending mac-command block, this could return None.
|
||||
let pending = match mac_command::get_pending(&dev.dev_eui, cid).await {
|
||||
let pending = match mac_command::get_pending(dev.get_device_session_mut()?, cid).await {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
error!(dev_eui = %dev.dev_eui, cid = %cid, error = %e, "Get pending mac-command block error");
|
||||
@ -85,13 +85,6 @@ pub async fn handle_uplink<'a>(
|
||||
}
|
||||
};
|
||||
|
||||
// Delete the pending mac-command.
|
||||
if pending.is_some() {
|
||||
if let Err(e) = mac_command::delete_pending(&dev.dev_eui, cid).await {
|
||||
error!(dev_eui = %dev.dev_eui, cid = %cid, error = %e, "Delete pending mac-command error");
|
||||
}
|
||||
}
|
||||
|
||||
// Handle the mac-command, which might return a block to answer the uplink mac-command
|
||||
// request.
|
||||
let res = match handle(
|
||||
@ -182,7 +175,7 @@ pub mod test {
|
||||
ch: 0,
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
|
@ -1,7 +1,5 @@
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
extern crate diesel_migrations;
|
||||
#[macro_use]
|
||||
extern crate diesel;
|
||||
|
@ -1,12 +1,10 @@
|
||||
use std::sync::RwLock;
|
||||
use std::sync::{LazyLock, RwLock};
|
||||
|
||||
use anyhow::Result;
|
||||
use prometheus_client::encoding::text::encode;
|
||||
use prometheus_client::registry::{Metric, Registry};
|
||||
|
||||
lazy_static! {
|
||||
static ref REGISTRY: RwLock<Registry> = RwLock::new(<Registry>::default());
|
||||
}
|
||||
static REGISTRY: LazyLock<RwLock<Registry>> = LazyLock::new(|| RwLock::new(<Registry>::default()));
|
||||
|
||||
pub fn encode_to_string() -> Result<String> {
|
||||
let registry_r = REGISTRY.read().unwrap();
|
||||
|
@ -1,5 +1,5 @@
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use std::sync::{Arc, LazyLock, RwLock};
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use tracing::{info, span, trace, Level};
|
||||
@ -7,10 +7,8 @@ use tracing::{info, span, trace, Level};
|
||||
use crate::config;
|
||||
use lrwn::region;
|
||||
|
||||
lazy_static! {
|
||||
static ref REGIONS: RwLock<HashMap<String, Arc<Box<dyn region::Region + Sync + Send>>>> =
|
||||
RwLock::new(HashMap::new());
|
||||
}
|
||||
static REGIONS: LazyLock<RwLock<HashMap<String, Arc<Box<dyn region::Region + Sync + Send>>>>> =
|
||||
LazyLock::new(|| RwLock::new(HashMap::new()));
|
||||
|
||||
pub fn setup() -> Result<()> {
|
||||
info!("Setting up regions");
|
||||
|
@ -116,6 +116,7 @@ pub struct Device {
|
||||
pub join_eui: EUI64,
|
||||
pub secondary_dev_addr: Option<DevAddr>,
|
||||
pub device_session: Option<fields::DeviceSession>,
|
||||
pub app_layer_params: fields::device::AppLayerParams,
|
||||
}
|
||||
|
||||
#[derive(AsChangeset, Debug, Clone, Default)]
|
||||
@ -133,6 +134,7 @@ pub struct DeviceChangeset {
|
||||
pub battery_level: Option<Option<fields::BigDecimal>>,
|
||||
pub scheduler_run_after: Option<Option<DateTime<Utc>>>,
|
||||
pub is_disabled: Option<bool>,
|
||||
pub app_layer_params: Option<fields::device::AppLayerParams>,
|
||||
}
|
||||
|
||||
impl Device {
|
||||
@ -190,6 +192,7 @@ impl Default for Device {
|
||||
join_eui: EUI64::default(),
|
||||
secondary_dev_addr: None,
|
||||
device_session: None,
|
||||
app_layer_params: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -324,6 +327,15 @@ pub async fn get_for_phypayload_and_incr_f_cnt_up(
|
||||
return Err(Error::InvalidPayload("MacPayload".to_string()));
|
||||
};
|
||||
|
||||
// We calculate the scheduler_run_after timestamp, such that we can update
|
||||
// it directly when updating the device-session (to update the frame-counter).
|
||||
// This way, we limit the risk of overlapping Class-A downlinks with Class-B / -C
|
||||
// downlinks.
|
||||
let conf = config::get();
|
||||
let scheduler_run_after = Utc::now()
|
||||
+ Duration::from_std(conf.network.scheduler.class_a_lock_duration)
|
||||
.map_err(anyhow::Error::new)?;
|
||||
|
||||
let mut c = get_async_db_conn().await?;
|
||||
|
||||
db_transaction::<ValidationStatus, Error, _>(&mut c, |c| {
|
||||
@ -424,10 +436,20 @@ pub async fn get_for_phypayload_and_incr_f_cnt_up(
|
||||
let ds_f_cnt_up = ds.f_cnt_up;
|
||||
ds.f_cnt_up = full_f_cnt + 1;
|
||||
|
||||
let _ = diesel::update(device::dsl::device.find(d.dev_eui))
|
||||
.set(device::device_session.eq(&ds.clone()))
|
||||
.execute(c)
|
||||
.await?;
|
||||
if scheduler_run_after > d.scheduler_run_after.unwrap_or_default() {
|
||||
let _ = diesel::update(device::dsl::device.find(d.dev_eui))
|
||||
.set((
|
||||
device::device_session.eq(&ds.clone()),
|
||||
device::scheduler_run_after.eq(&scheduler_run_after),
|
||||
))
|
||||
.execute(c)
|
||||
.await?;
|
||||
} else {
|
||||
let _ = diesel::update(device::dsl::device.find(d.dev_eui))
|
||||
.set(device::device_session.eq(&ds.clone()))
|
||||
.execute(c)
|
||||
.await?;
|
||||
}
|
||||
|
||||
// We do return the device-session with original frame-counter
|
||||
ds.f_cnt_up = ds_f_cnt_up;
|
||||
@ -552,6 +574,7 @@ pub async fn update(d: Device) -> Result<Device, Error> {
|
||||
device::tags.eq(&d.tags),
|
||||
device::variables.eq(&d.variables),
|
||||
device::join_eui.eq(&d.join_eui),
|
||||
device::app_layer_params.eq(&d.app_layer_params),
|
||||
))
|
||||
.get_result(&mut get_async_db_conn().await?)
|
||||
.await
|
||||
@ -707,17 +730,37 @@ pub async fn list(
|
||||
true => match order_by {
|
||||
OrderBy::Name => q.order_by(device::dsl::name.desc()),
|
||||
OrderBy::DevEui => q.order_by(device::dsl::dev_eui.desc()),
|
||||
OrderBy::LastSeenAt => q
|
||||
.order_by(device::dsl::last_seen_at.desc())
|
||||
.then_order_by(device::dsl::name),
|
||||
OrderBy::LastSeenAt => {
|
||||
#[cfg(feature = "postgres")]
|
||||
{
|
||||
q.order_by(device::dsl::last_seen_at.desc().nulls_last())
|
||||
.then_order_by(device::dsl::name)
|
||||
}
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
{
|
||||
q.order_by(device::dsl::last_seen_at.desc())
|
||||
.then_order_by(device::dsl::name)
|
||||
}
|
||||
}
|
||||
OrderBy::DeviceProfileName => q.order_by(device_profile::dsl::name.desc()),
|
||||
},
|
||||
false => match order_by {
|
||||
OrderBy::Name => q.order_by(device::dsl::name),
|
||||
OrderBy::DevEui => q.order_by(device::dsl::dev_eui),
|
||||
OrderBy::LastSeenAt => q
|
||||
.order_by(device::dsl::last_seen_at)
|
||||
.then_order_by(device::dsl::name),
|
||||
OrderBy::LastSeenAt => {
|
||||
#[cfg(feature = "postgres")]
|
||||
{
|
||||
q.order_by(device::dsl::last_seen_at.asc().nulls_first())
|
||||
.then_order_by(device::dsl::name)
|
||||
}
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
{
|
||||
q.order_by(device::dsl::last_seen_at.asc())
|
||||
.then_order_by(device::dsl::name)
|
||||
}
|
||||
}
|
||||
OrderBy::DeviceProfileName => q.order_by(device_profile::dsl::name),
|
||||
},
|
||||
};
|
||||
@ -1639,7 +1682,7 @@ pub mod test {
|
||||
println!("> {}", tst.name);
|
||||
let mut phy = lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
|
@ -109,7 +109,7 @@ impl DeviceProfile {
|
||||
|
||||
if let Some(class_b_params) = &self.class_b_params {
|
||||
ds.class_b_ping_slot_dr = class_b_params.ping_slot_dr as u32;
|
||||
ds.class_b_ping_slot_freq = class_b_params.ping_slot_freq as u32;
|
||||
ds.class_b_ping_slot_freq = class_b_params.ping_slot_freq;
|
||||
ds.class_b_ping_slot_nb = 1 << class_b_params.ping_slot_nb_k as u32;
|
||||
}
|
||||
|
||||
@ -133,7 +133,7 @@ impl DeviceProfile {
|
||||
ds.rx1_delay = abp_params.rx1_delay as u32;
|
||||
ds.rx1_dr_offset = abp_params.rx1_dr_offset as u32;
|
||||
ds.rx2_dr = abp_params.rx2_dr as u32;
|
||||
ds.rx2_frequency = abp_params.rx2_freq as u32;
|
||||
ds.rx2_frequency = abp_params.rx2_freq;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,10 @@ pub async fn save(df: &internal::DownlinkFrame) -> Result<()> {
|
||||
|
||||
pub async fn get_and_del(id: u32) -> Result<internal::DownlinkFrame, Error> {
|
||||
let key = redis_key(format!("frame:{}", id));
|
||||
let v: Vec<u8> = redis::cmd("GETDEL")
|
||||
let (v, _): (Vec<u8>, u8) = redis::pipe()
|
||||
.cmd("GET")
|
||||
.arg(key.clone())
|
||||
.cmd("DEL")
|
||||
.arg(key)
|
||||
.query_async(&mut get_async_redis_conn().await?)
|
||||
.await?;
|
||||
|
@ -34,7 +34,7 @@ pub enum Error {
|
||||
NotAllowed(String),
|
||||
|
||||
#[error("Multiple errors")]
|
||||
MultiError(Vec<Error>),
|
||||
Multi(Vec<Error>),
|
||||
|
||||
#[error(transparent)]
|
||||
Diesel(#[from] diesel::result::Error),
|
||||
|
52
chirpstack/src/storage/fields/device.rs
Normal file
52
chirpstack/src/storage/fields/device.rs
Normal file
@ -0,0 +1,52 @@
|
||||
use diesel::backend::Backend;
|
||||
use diesel::{deserialize, serialize};
|
||||
#[cfg(feature = "postgres")]
|
||||
use diesel::{pg::Pg, sql_types::Jsonb};
|
||||
#[cfg(feature = "sqlite")]
|
||||
use diesel::{sql_types::Text, sqlite::Sqlite};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, AsExpression, FromSqlRow)]
|
||||
#[cfg_attr(feature = "postgres", diesel(sql_type = Jsonb))]
|
||||
#[cfg_attr(feature = "sqlite", diesel(sql_type = Text))]
|
||||
#[serde(default)]
|
||||
#[derive(Default)]
|
||||
pub struct AppLayerParams {
|
||||
pub ts004_session_cnt: [u16; 4],
|
||||
}
|
||||
|
||||
#[cfg(feature = "postgres")]
|
||||
impl deserialize::FromSql<Jsonb, Pg> for AppLayerParams {
|
||||
fn from_sql(value: <Pg as Backend>::RawValue<'_>) -> deserialize::Result<Self> {
|
||||
let value = <serde_json::Value as deserialize::FromSql<Jsonb, Pg>>::from_sql(value)?;
|
||||
Ok(serde_json::from_value(value)?)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "postgres")]
|
||||
impl serialize::ToSql<Jsonb, Pg> for AppLayerParams {
|
||||
fn to_sql<'b>(&'b self, out: &mut serialize::Output<'b, '_, Pg>) -> serialize::Result {
|
||||
let value = serde_json::to_value(self)?;
|
||||
<serde_json::Value as serialize::ToSql<Jsonb, Pg>>::to_sql(&value, &mut out.reborrow())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
impl deserialize::FromSql<Text, Sqlite> for AppLayerParams
|
||||
where
|
||||
*const str: deserialize::FromSql<Text, Sqlite>,
|
||||
{
|
||||
fn from_sql(value: <Sqlite as Backend>::RawValue<'_>) -> deserialize::Result<Self> {
|
||||
let s =
|
||||
<*const str as deserialize::FromSql<diesel::sql_types::Text, Sqlite>>::from_sql(value)?;
|
||||
Ok(serde_json::from_str(unsafe { &*s })?)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
impl serialize::ToSql<Text, Sqlite> for AppLayerParams {
|
||||
fn to_sql<'b>(&'b self, out: &mut serialize::Output<'b, '_, Sqlite>) -> serialize::Result {
|
||||
out.set_value(serde_json::to_string(&self)?);
|
||||
Ok(serialize::IsNull::No)
|
||||
}
|
||||
}
|
@ -29,7 +29,7 @@ impl deserialize::FromSql<Jsonb, Pg> for AbpParams {
|
||||
#[cfg(feature = "postgres")]
|
||||
impl serialize::ToSql<Jsonb, Pg> for AbpParams {
|
||||
fn to_sql<'b>(&'b self, out: &mut serialize::Output<'b, '_, Pg>) -> serialize::Result {
|
||||
let value = serde_json::to_value(&self)?;
|
||||
let value = serde_json::to_value(self)?;
|
||||
<serde_json::Value as serialize::ToSql<Jsonb, Pg>>::to_sql(&value, &mut out.reborrow())
|
||||
}
|
||||
}
|
||||
@ -77,7 +77,7 @@ impl deserialize::FromSql<Jsonb, Pg> for ClassBParams {
|
||||
#[cfg(feature = "postgres")]
|
||||
impl serialize::ToSql<Jsonb, Pg> for ClassBParams {
|
||||
fn to_sql<'b>(&'b self, out: &mut serialize::Output<'b, '_, Pg>) -> serialize::Result {
|
||||
let value = serde_json::to_value(&self)?;
|
||||
let value = serde_json::to_value(self)?;
|
||||
<serde_json::Value as serialize::ToSql<Jsonb, Pg>>::to_sql(&value, &mut out.reborrow())
|
||||
}
|
||||
}
|
||||
@ -122,7 +122,7 @@ impl deserialize::FromSql<Jsonb, Pg> for ClassCParams {
|
||||
#[cfg(feature = "postgres")]
|
||||
impl serialize::ToSql<Jsonb, Pg> for ClassCParams {
|
||||
fn to_sql<'b>(&'b self, out: &mut serialize::Output<'b, '_, Pg>) -> serialize::Result {
|
||||
let value = serde_json::to_value(&self)?;
|
||||
let value = serde_json::to_value(self)?;
|
||||
<serde_json::Value as serialize::ToSql<Jsonb, Pg>>::to_sql(&value, &mut out.reborrow())
|
||||
}
|
||||
}
|
||||
@ -189,7 +189,7 @@ impl deserialize::FromSql<Jsonb, Pg> for RelayParams {
|
||||
#[cfg(feature = "postgres")]
|
||||
impl serialize::ToSql<Jsonb, Pg> for RelayParams {
|
||||
fn to_sql<'b>(&'b self, out: &mut serialize::Output<'b, '_, Pg>) -> serialize::Result {
|
||||
let value = serde_json::to_value(&self)?;
|
||||
let value = serde_json::to_value(self)?;
|
||||
<serde_json::Value as serialize::ToSql<Jsonb, Pg>>::to_sql(&value, &mut out.reborrow())
|
||||
}
|
||||
}
|
||||
@ -263,14 +263,9 @@ impl Default for AppLayerParams {
|
||||
|
||||
impl AppLayerParams {
|
||||
pub fn is_app_layer_f_port(&self, f_port: u8) -> bool {
|
||||
if (self.ts003_version.is_some() && self.ts003_f_port == f_port)
|
||||
(self.ts003_version.is_some() && self.ts003_f_port == f_port)
|
||||
|| (self.ts004_version.is_some() && self.ts004_f_port == f_port)
|
||||
|| (self.ts005_version.is_some() && self.ts005_f_port == f_port)
|
||||
{
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -285,7 +280,7 @@ impl deserialize::FromSql<Jsonb, Pg> for AppLayerParams {
|
||||
#[cfg(feature = "postgres")]
|
||||
impl serialize::ToSql<Jsonb, Pg> for AppLayerParams {
|
||||
fn to_sql<'b>(&'b self, out: &mut serialize::Output<'b, '_, Pg>) -> serialize::Result {
|
||||
let value = serde_json::to_value(&self)?;
|
||||
let value = serde_json::to_value(self)?;
|
||||
<serde_json::Value as serialize::ToSql<Jsonb, Pg>>::to_sql(&value, &mut out.reborrow())
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
mod big_decimal;
|
||||
mod dev_nonces;
|
||||
pub mod device;
|
||||
pub mod device_profile;
|
||||
mod device_session;
|
||||
mod fuota;
|
||||
|
@ -336,7 +336,7 @@ pub async fn add_devices(fuota_deployment_id: Uuid, dev_euis: Vec<EUI64>) -> Res
|
||||
if errors.is_empty() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::MultiError(errors))
|
||||
Err(Error::Multi(errors))
|
||||
}
|
||||
}
|
||||
|
||||
@ -552,7 +552,7 @@ pub async fn add_gateways(fuota_deployment_id: Uuid, gateway_ids: Vec<EUI64>) ->
|
||||
if errors.is_empty() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::MultiError(errors))
|
||||
Err(Error::Multi(errors))
|
||||
}
|
||||
}
|
||||
|
||||
@ -789,7 +789,7 @@ pub fn get_multicast_timeout(d: &FuotaDeployment) -> Result<usize> {
|
||||
conf.network.scheduler.multicast_class_c_margin.as_secs() as usize;
|
||||
|
||||
// Multiply by the number of fragments (+1 for additional margin).
|
||||
let mc_class_c_duration_secs = mc_class_c_margin_secs * (total_fragments + 1 as usize);
|
||||
let mc_class_c_duration_secs = mc_class_c_margin_secs * (total_fragments + 1);
|
||||
|
||||
// Calculate the timeout value. In case of Class-C, timeout is defined as seconds,
|
||||
// where the number of seconds is 2^timeout.
|
||||
|
@ -365,16 +365,36 @@ pub async fn list(
|
||||
true => match order_by {
|
||||
OrderBy::Name => q.order_by(gateway::dsl::name.desc()),
|
||||
OrderBy::GatewayId => q.order_by(gateway::dsl::gateway_id.desc()),
|
||||
OrderBy::LastSeenAt => q
|
||||
.order_by(gateway::dsl::last_seen_at.desc())
|
||||
.then_order_by(gateway::dsl::name),
|
||||
OrderBy::LastSeenAt => {
|
||||
#[cfg(feature = "postgres")]
|
||||
{
|
||||
q.order_by(gateway::dsl::last_seen_at.desc().nulls_last())
|
||||
.then_order_by(gateway::dsl::name)
|
||||
}
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
{
|
||||
q.order_by(gateway::dsl::last_seen_at.desc())
|
||||
.then_order_by(gateway::dsl::name)
|
||||
}
|
||||
}
|
||||
},
|
||||
false => match order_by {
|
||||
OrderBy::Name => q.order_by(gateway::dsl::name),
|
||||
OrderBy::GatewayId => q.order_by(gateway::dsl::gateway_id),
|
||||
OrderBy::LastSeenAt => q
|
||||
.order_by(gateway::dsl::last_seen_at)
|
||||
.then_order_by(gateway::dsl::name),
|
||||
OrderBy::LastSeenAt => {
|
||||
#[cfg(feature = "postgres")]
|
||||
{
|
||||
q.order_by(gateway::dsl::last_seen_at.asc().nulls_first())
|
||||
.then_order_by(gateway::dsl::name)
|
||||
}
|
||||
|
||||
#[cfg(feature = "sqlite")]
|
||||
{
|
||||
q.order_by(gateway::dsl::last_seen_at.asc())
|
||||
.then_order_by(gateway::dsl::name)
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -1,34 +1,24 @@
|
||||
use anyhow::Result;
|
||||
use tracing::info;
|
||||
|
||||
use super::{get_async_redis_conn, redis_key};
|
||||
use crate::config;
|
||||
use lrwn::EUI64;
|
||||
use chirpstack_api::internal;
|
||||
|
||||
pub async fn set_pending(dev_eui: &EUI64, cid: lrwn::CID, set: &lrwn::MACCommandSet) -> Result<()> {
|
||||
let conf = config::get();
|
||||
|
||||
let key = redis_key(format!("device:{}:mac:pending:{}", dev_eui, cid.to_u8()));
|
||||
let ttl = conf.network.device_session_ttl.as_millis() as usize;
|
||||
pub fn set_pending(ds: &mut internal::DeviceSession, set: &lrwn::MACCommandSet) -> Result<()> {
|
||||
let cid = set.cid()?;
|
||||
let b = set.to_vec()?;
|
||||
|
||||
() = redis::cmd("PSETEX")
|
||||
.arg(key)
|
||||
.arg(ttl)
|
||||
.arg(b)
|
||||
.query_async(&mut get_async_redis_conn().await?)
|
||||
.await?;
|
||||
|
||||
info!(dev_eui = %dev_eui, cid = %cid, "Pending mac-command block set");
|
||||
ds.mac_command_pending.insert(cid.to_u8().into(), b);
|
||||
info!(cid = %cid, "Pending mac-command block set");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn get_pending(dev_eui: &EUI64, cid: lrwn::CID) -> Result<Option<lrwn::MACCommandSet>> {
|
||||
let key = redis_key(format!("device:{}:mac:pending:{}", dev_eui, cid.to_u8()));
|
||||
let b: Vec<u8> = redis::cmd("GET")
|
||||
.arg(key)
|
||||
.query_async(&mut get_async_redis_conn().await?)
|
||||
.await?;
|
||||
pub async fn get_pending(
|
||||
ds: &mut internal::DeviceSession,
|
||||
cid: lrwn::CID,
|
||||
) -> Result<Option<lrwn::MACCommandSet>> {
|
||||
let b = ds
|
||||
.mac_command_pending
|
||||
.remove(&cid.to_u8().into())
|
||||
.unwrap_or_default();
|
||||
|
||||
let out = if !b.is_empty() {
|
||||
let mut mac = lrwn::MACCommandSet::from_slice(&b);
|
||||
@ -44,49 +34,3 @@ pub async fn get_pending(dev_eui: &EUI64, cid: lrwn::CID) -> Result<Option<lrwn:
|
||||
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
pub async fn delete_pending(dev_eui: &EUI64, cid: lrwn::CID) -> Result<()> {
|
||||
let key = redis_key(format!("device:{}:mac:pending:{}", dev_eui, cid.to_u8()));
|
||||
|
||||
() = redis::cmd("DEL")
|
||||
.arg(key)
|
||||
.query_async(&mut get_async_redis_conn().await?)
|
||||
.await?;
|
||||
|
||||
info!(dev_eui = %dev_eui, cid = %cid, "Pending mac-command block deleted");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use super::*;
|
||||
use crate::test;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_mac_command() {
|
||||
let _guard = test::prepare().await;
|
||||
|
||||
let dev_eui = EUI64::from_be_bytes([1, 2, 3, 4, 5, 6, 7, 8]);
|
||||
let mac = lrwn::MACCommandSet::new(vec![lrwn::MACCommand::DevStatusReq]);
|
||||
|
||||
// set
|
||||
set_pending(&dev_eui, lrwn::CID::DevStatusReq, &mac)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// get
|
||||
let mac_get = get_pending(&dev_eui, lrwn::CID::DevStatusReq)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(mac, mac_get.unwrap());
|
||||
|
||||
// delete
|
||||
delete_pending(&dev_eui, lrwn::CID::DevStatusReq)
|
||||
.await
|
||||
.unwrap();
|
||||
let resp = get_pending(&dev_eui, lrwn::CID::DevStatusReq)
|
||||
.await
|
||||
.unwrap();
|
||||
assert!(resp.is_none());
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
use std::sync::LazyLock;
|
||||
use std::sync::RwLock;
|
||||
use std::time::Instant;
|
||||
|
||||
@ -47,19 +48,18 @@ pub mod user;
|
||||
|
||||
use crate::monitoring::prometheus;
|
||||
|
||||
lazy_static! {
|
||||
static ref ASYNC_REDIS_POOL: TokioRwLock<Option<AsyncRedisPool>> = TokioRwLock::new(None);
|
||||
static ref REDIS_PREFIX: RwLock<String> = RwLock::new("".to_string());
|
||||
static ref STORAGE_REDIS_CONN_GET: Histogram = {
|
||||
let histogram = Histogram::new(exponential_buckets(0.001, 2.0, 12));
|
||||
prometheus::register(
|
||||
"storage_redis_conn_get_duration_seconds",
|
||||
"Time between requesting a Redis connection and the connection-pool returning it",
|
||||
histogram.clone(),
|
||||
);
|
||||
histogram
|
||||
};
|
||||
}
|
||||
static ASYNC_REDIS_POOL: LazyLock<TokioRwLock<Option<AsyncRedisPool>>> =
|
||||
LazyLock::new(|| TokioRwLock::new(None));
|
||||
static REDIS_PREFIX: LazyLock<RwLock<String>> = LazyLock::new(|| RwLock::new("".to_string()));
|
||||
static STORAGE_REDIS_CONN_GET: LazyLock<Histogram> = LazyLock::new(|| {
|
||||
let histogram = Histogram::new(exponential_buckets(0.001, 2.0, 12));
|
||||
prometheus::register(
|
||||
"storage_redis_conn_get_duration_seconds",
|
||||
"Time between requesting a Redis connection and the connection-pool returning it",
|
||||
histogram.clone(),
|
||||
);
|
||||
histogram
|
||||
});
|
||||
|
||||
#[cfg(feature = "postgres")]
|
||||
pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("./migrations_postgres");
|
||||
|
@ -1012,7 +1012,7 @@ pub mod test {
|
||||
// invalid f_port
|
||||
assert!(enqueue(
|
||||
MulticastGroupQueueItem {
|
||||
multicast_group_id: mg.id.into(),
|
||||
multicast_group_id: mg.id,
|
||||
gateway_id: gw.gateway_id,
|
||||
f_cnt: 1,
|
||||
f_port: 0,
|
||||
@ -1026,7 +1026,7 @@ pub mod test {
|
||||
|
||||
assert!(enqueue(
|
||||
MulticastGroupQueueItem {
|
||||
multicast_group_id: mg.id.into(),
|
||||
multicast_group_id: mg.id,
|
||||
gateway_id: gw.gateway_id,
|
||||
f_cnt: 1,
|
||||
f_port: 256,
|
||||
@ -1041,7 +1041,7 @@ pub mod test {
|
||||
// Enqueue (Class-C) (delay)
|
||||
let (ids, f_cnt) = enqueue(
|
||||
MulticastGroupQueueItem {
|
||||
multicast_group_id: mg.id.into(),
|
||||
multicast_group_id: mg.id,
|
||||
gateway_id: gw.gateway_id,
|
||||
f_cnt: 1,
|
||||
f_port: 2,
|
||||
@ -1071,7 +1071,7 @@ pub mod test {
|
||||
let mut mg = update(mg).await.unwrap();
|
||||
let (ids, f_cnt) = enqueue(
|
||||
MulticastGroupQueueItem {
|
||||
multicast_group_id: mg.id.into(),
|
||||
multicast_group_id: mg.id,
|
||||
gateway_id: gw.gateway_id,
|
||||
f_cnt: 1,
|
||||
f_port: 2,
|
||||
@ -1098,7 +1098,7 @@ pub mod test {
|
||||
let mg = update(mg).await.unwrap();
|
||||
let (ids, f_cnt) = enqueue(
|
||||
MulticastGroupQueueItem {
|
||||
multicast_group_id: mg.id.into(),
|
||||
multicast_group_id: mg.id,
|
||||
gateway_id: gw.gateway_id,
|
||||
f_cnt: 1,
|
||||
f_port: 2,
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::sync::RwLock;
|
||||
use std::sync::{LazyLock, RwLock};
|
||||
use std::time::Instant;
|
||||
|
||||
use anyhow::Result;
|
||||
@ -20,18 +20,16 @@ use crate::helpers::tls::get_root_certs;
|
||||
pub type AsyncPgPool = DeadpoolPool<AsyncPgConnection>;
|
||||
pub type AsyncPgPoolConnection = DeadpoolObject<AsyncPgConnection>;
|
||||
|
||||
lazy_static! {
|
||||
static ref ASYNC_PG_POOL: RwLock<Option<AsyncPgPool>> = RwLock::new(None);
|
||||
static ref STORAGE_PG_CONN_GET: Histogram = {
|
||||
let histogram = Histogram::new(exponential_buckets(0.001, 2.0, 12));
|
||||
prometheus::register(
|
||||
"storage_pg_conn_get_duration_seconds",
|
||||
"Time between requesting a PostgreSQL connection and the connection-pool returning it",
|
||||
histogram.clone(),
|
||||
);
|
||||
histogram
|
||||
};
|
||||
}
|
||||
static ASYNC_PG_POOL: LazyLock<RwLock<Option<AsyncPgPool>>> = LazyLock::new(|| RwLock::new(None));
|
||||
static STORAGE_PG_CONN_GET: LazyLock<Histogram> = LazyLock::new(|| {
|
||||
let histogram = Histogram::new(exponential_buckets(0.001, 2.0, 12));
|
||||
prometheus::register(
|
||||
"storage_pg_conn_get_duration_seconds",
|
||||
"Time between requesting a PostgreSQL connection and the connection-pool returning it",
|
||||
histogram.clone(),
|
||||
);
|
||||
histogram
|
||||
});
|
||||
|
||||
pub fn setup(conf: &config::Postgresql) -> Result<()> {
|
||||
info!("Setting up PostgreSQL connection pool");
|
||||
|
@ -65,6 +65,7 @@ diesel::table! {
|
||||
join_eui -> Bytea,
|
||||
secondary_dev_addr -> Nullable<Bytea>,
|
||||
device_session -> Nullable<Bytea>,
|
||||
app_layer_params -> Jsonb,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,6 +60,7 @@ diesel::table! {
|
||||
join_eui -> Binary,
|
||||
secondary_dev_addr -> Nullable<Binary>,
|
||||
device_session -> Nullable<Binary>,
|
||||
app_layer_params -> Text,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
use std::collections::HashMap;
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use diesel_async::RunQueryDsl;
|
||||
@ -8,9 +9,7 @@ use uuid::Uuid;
|
||||
use super::{error::Error, fields, get_async_db_conn};
|
||||
use lrwn::EUI64;
|
||||
|
||||
lazy_static! {
|
||||
static ref SEARCH_TAG_RE: Regex = Regex::new(r"([^ ]+):([^ ]+)").unwrap();
|
||||
}
|
||||
static SEARCH_TAG_RE: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"([^ ]+):([^ ]+)").unwrap());
|
||||
|
||||
#[derive(QueryableByName, PartialEq, Debug)]
|
||||
pub struct SearchResult {
|
||||
@ -449,8 +448,8 @@ pub mod test {
|
||||
let _d = device::create(device::Device {
|
||||
dev_eui: EUI64::from_str("0203040506070809").unwrap(),
|
||||
name: "test-device".into(),
|
||||
application_id: a.id.clone(),
|
||||
device_profile_id: dp.id.clone(),
|
||||
application_id: a.id,
|
||||
device_profile_id: dp.id,
|
||||
tags: build_tags(&[("common_tag", "value"), ("mytag", "dev_value")]),
|
||||
..Default::default()
|
||||
})
|
||||
|
@ -1,4 +1,4 @@
|
||||
use std::sync::RwLock;
|
||||
use std::sync::{LazyLock, RwLock};
|
||||
use std::time::Instant;
|
||||
|
||||
use anyhow::Result;
|
||||
@ -19,18 +19,17 @@ use crate::config;
|
||||
pub type AsyncSqlitePool = DeadpoolPool<SyncConnectionWrapper<SqliteConnection>>;
|
||||
pub type AsyncSqlitePoolConnection = DeadpoolObject<SyncConnectionWrapper<SqliteConnection>>;
|
||||
|
||||
lazy_static! {
|
||||
static ref ASYNC_SQLITE_POOL: RwLock<Option<AsyncSqlitePool>> = RwLock::new(None);
|
||||
static ref STORAGE_SQLITE_CONN_GET: Histogram = {
|
||||
let histogram = Histogram::new(exponential_buckets(0.001, 2.0, 12));
|
||||
prometheus::register(
|
||||
"storage_sqlite_conn_get_duration_seconds",
|
||||
"Time between requesting a SQLite connection and the connection-pool returning it",
|
||||
histogram.clone(),
|
||||
);
|
||||
histogram
|
||||
};
|
||||
}
|
||||
static ASYNC_SQLITE_POOL: LazyLock<RwLock<Option<AsyncSqlitePool>>> =
|
||||
LazyLock::new(|| RwLock::new(None));
|
||||
static STORAGE_SQLITE_CONN_GET: LazyLock<Histogram> = LazyLock::new(|| {
|
||||
let histogram = Histogram::new(exponential_buckets(0.001, 2.0, 12));
|
||||
prometheus::register(
|
||||
"storage_sqlite_conn_get_duration_seconds",
|
||||
"Time between requesting a SQLite connection and the connection-pool returning it",
|
||||
histogram.clone(),
|
||||
);
|
||||
histogram
|
||||
});
|
||||
|
||||
pub fn setup(conf: &config::Sqlite) -> Result<()> {
|
||||
info!("Setting up SQLite connection pool");
|
||||
|
@ -325,7 +325,6 @@ pub mod test {
|
||||
use crate::storage::user::test::create_user;
|
||||
use crate::test;
|
||||
use chrono::SubsecRound;
|
||||
use std::str::FromStr;
|
||||
use uuid::Uuid;
|
||||
|
||||
struct FilterTest<'a> {
|
||||
@ -357,10 +356,19 @@ pub mod test {
|
||||
async fn test_tenant() {
|
||||
let _guard = test::prepare().await;
|
||||
|
||||
// delete default tenant
|
||||
delete(&Uuid::from_str("52f14cd4-c6f1-4fbd-8f87-4025e1d49242").unwrap())
|
||||
.await
|
||||
.unwrap();
|
||||
// delete existing tenants.
|
||||
let tenants = list(
|
||||
10,
|
||||
0,
|
||||
&Filters {
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
for t in &tenants {
|
||||
delete(&t.id).await.unwrap();
|
||||
}
|
||||
|
||||
let mut t = create_tenant().await;
|
||||
|
||||
@ -379,7 +387,7 @@ pub mod test {
|
||||
|
||||
let tu = TenantUser {
|
||||
tenant_id: t.id,
|
||||
user_id: user.id.into(),
|
||||
user_id: user.id,
|
||||
is_admin: true,
|
||||
..Default::default()
|
||||
};
|
||||
@ -480,7 +488,7 @@ pub mod test {
|
||||
|
||||
let tu = TenantUser {
|
||||
tenant_id: t.id,
|
||||
user_id: user.id.into(),
|
||||
user_id: user.id,
|
||||
is_admin: true,
|
||||
..Default::default()
|
||||
};
|
||||
|
@ -14,7 +14,6 @@ use crate::storage::{get_async_redis_conn, redis_key};
|
||||
use chirpstack_api::{api, integration};
|
||||
|
||||
#[allow(clippy::enum_variant_names)]
|
||||
|
||||
pub async fn log_event_for_device(typ: &str, dev_eui: &str, b: &[u8]) -> Result<()> {
|
||||
let conf = config::get();
|
||||
|
||||
|
@ -27,7 +27,7 @@ pub async fn log_uplink_for_gateways(ufl: &stream::UplinkFrameLog) -> Result<()>
|
||||
phy_payload: ufl.phy_payload.clone(),
|
||||
tx_info: ufl.tx_info.clone(),
|
||||
rx_info: vec![rx_info.clone()],
|
||||
m_type: ufl.m_type,
|
||||
f_type: ufl.f_type,
|
||||
dev_addr: ufl.dev_addr.clone(),
|
||||
dev_eui: ufl.dev_eui.clone(),
|
||||
time: ufl.time,
|
||||
@ -299,7 +299,7 @@ async fn handle_stream(
|
||||
seconds: t.seconds,
|
||||
nanos: t.nanos,
|
||||
}),
|
||||
description: pl.m_type().into(),
|
||||
description: pl.f_type().into(),
|
||||
body: json!({
|
||||
"phy_payload": phy,
|
||||
"tx_info": pl.tx_info,
|
||||
@ -340,7 +340,7 @@ async fn handle_stream(
|
||||
seconds: t.seconds,
|
||||
nanos: t.nanos,
|
||||
}),
|
||||
description: pl.m_type().into(),
|
||||
description: pl.f_type().into(),
|
||||
body: json!({
|
||||
"phy_payload": phy,
|
||||
"tx_info": pl.tx_info,
|
||||
|
@ -1,6 +1,7 @@
|
||||
use std::future::Future;
|
||||
use std::io::Cursor;
|
||||
use std::pin::Pin;
|
||||
use std::sync::LazyLock;
|
||||
use std::time::Duration;
|
||||
|
||||
use prost::Message;
|
||||
@ -17,9 +18,7 @@ use crate::storage::{
|
||||
use chirpstack_api::{gw, integration as integration_pb, internal, stream};
|
||||
use lrwn::EUI64;
|
||||
|
||||
lazy_static! {
|
||||
static ref LAST_DOWNLINK_ID: RwLock<u32> = RwLock::new(0);
|
||||
}
|
||||
static LAST_DOWNLINK_ID: LazyLock<RwLock<u32>> = LazyLock::new(|| RwLock::new(0));
|
||||
|
||||
pub type Validator = Box<dyn Fn() -> Pin<Box<dyn Future<Output = ()>>>>;
|
||||
|
||||
|
@ -80,7 +80,7 @@ async fn test_fns_uplink() {
|
||||
|
||||
let data_phy = lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -150,7 +150,7 @@ async fn test_fns_uplink() {
|
||||
// Simulate uplink
|
||||
uplink::handle_uplink(
|
||||
CommonName::EU868,
|
||||
"eu868".into(),
|
||||
"eu868",
|
||||
Uuid::new_v4(),
|
||||
gw::UplinkFrameSet {
|
||||
phy_payload: data_phy.to_vec().unwrap(),
|
||||
@ -266,7 +266,7 @@ async fn test_sns_uplink() {
|
||||
|
||||
let mut data_phy = lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -508,7 +508,7 @@ async fn test_sns_roaming_not_allowed() {
|
||||
|
||||
let mut data_phy = lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -631,7 +631,7 @@ async fn test_sns_dev_not_found() {
|
||||
|
||||
let data_phy = lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
|
@ -150,7 +150,7 @@ async fn test_gateway_filtering() {
|
||||
rx_info: rx_info_a.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -177,7 +177,7 @@ async fn test_gateway_filtering() {
|
||||
rx_info: rx_info_b.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -292,7 +292,7 @@ async fn test_lorawan_10_errors() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -325,7 +325,7 @@ async fn test_lorawan_10_errors() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -357,7 +357,7 @@ async fn test_lorawan_10_errors() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -379,7 +379,7 @@ async fn test_lorawan_10_errors() {
|
||||
rx_info: vec![rx_info.clone()],
|
||||
dev_eui: "0000000000000000".into(),
|
||||
dev_addr: "01020304".into(),
|
||||
m_type: common::MType::UnconfirmedDataUp.into(),
|
||||
f_type: common::FType::UnconfirmedDataUp.into(),
|
||||
..Default::default()
|
||||
}),
|
||||
],
|
||||
@ -489,7 +489,7 @@ async fn test_lorawan_11_errors() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -516,7 +516,7 @@ async fn test_lorawan_11_errors() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -633,7 +633,7 @@ async fn test_lorawan_10_skip_f_cnt() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -683,7 +683,7 @@ async fn test_lorawan_10_skip_f_cnt() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -821,7 +821,7 @@ async fn test_lorawan_10_device_disabled() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -949,7 +949,7 @@ async fn test_lorawan_10_uplink() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -1022,7 +1022,7 @@ async fn test_lorawan_10_uplink() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -1081,7 +1081,7 @@ async fn test_lorawan_10_uplink() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -1154,7 +1154,7 @@ async fn test_lorawan_10_uplink() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -1206,7 +1206,7 @@ async fn test_lorawan_10_uplink() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::ConfirmedDataUp,
|
||||
f_type: lrwn::FType::ConfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -1319,7 +1319,7 @@ async fn test_lorawan_10_uplink() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::ConfirmedDataUp,
|
||||
f_type: lrwn::FType::ConfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -1457,7 +1457,7 @@ async fn test_lorawan_10_uplink() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -1597,7 +1597,7 @@ async fn test_lorawan_10_end_to_end_enc() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -1649,7 +1649,7 @@ async fn test_lorawan_10_end_to_end_enc() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -1712,7 +1712,7 @@ async fn test_lorawan_10_end_to_end_enc() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -1761,7 +1761,7 @@ async fn test_lorawan_10_end_to_end_enc() {
|
||||
assert::downlink_phy_payloads(vec![
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -1781,7 +1781,7 @@ async fn test_lorawan_10_end_to_end_enc() {
|
||||
},
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -1912,7 +1912,7 @@ async fn test_lorawan_11_uplink() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -1971,7 +1971,7 @@ async fn test_lorawan_11_uplink() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -2145,7 +2145,7 @@ async fn test_lorawan_10_rx_delay() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::ConfirmedDataUp,
|
||||
f_type: lrwn::FType::ConfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -2267,7 +2267,7 @@ async fn test_lorawan_10_rx_delay() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::ConfirmedDataUp,
|
||||
f_type: lrwn::FType::ConfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -2389,7 +2389,7 @@ async fn test_lorawan_10_rx_delay() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::ConfirmedDataUp,
|
||||
f_type: lrwn::FType::ConfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -2431,7 +2431,7 @@ async fn test_lorawan_10_rx_delay() {
|
||||
assert::downlink_phy_payloads(vec![
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -2455,7 +2455,7 @@ async fn test_lorawan_10_rx_delay() {
|
||||
},
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -2602,7 +2602,7 @@ async fn test_lorawan_10_mac_commands() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -2622,7 +2622,7 @@ async fn test_lorawan_10_mac_commands() {
|
||||
assert::downlink_phy_payloads(vec![
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -2645,7 +2645,7 @@ async fn test_lorawan_10_mac_commands() {
|
||||
},
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -2701,7 +2701,7 @@ async fn test_lorawan_10_mac_commands() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -2721,7 +2721,7 @@ async fn test_lorawan_10_mac_commands() {
|
||||
assert::downlink_phy_payloads(vec![
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -2744,7 +2744,7 @@ async fn test_lorawan_10_mac_commands() {
|
||||
},
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -2779,7 +2779,7 @@ async fn test_lorawan_10_mac_commands() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -2803,7 +2803,7 @@ async fn test_lorawan_10_mac_commands() {
|
||||
assert::downlink_phy_payloads(vec![
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -2823,7 +2823,7 @@ async fn test_lorawan_10_mac_commands() {
|
||||
},
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -2937,7 +2937,7 @@ async fn test_lorawan_11_mac_commands() {
|
||||
|
||||
let mut phy = lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -2984,7 +2984,7 @@ async fn test_lorawan_11_mac_commands() {
|
||||
assert::downlink_phy_payloads(vec![
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -3008,7 +3008,7 @@ async fn test_lorawan_11_mac_commands() {
|
||||
},
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -3141,7 +3141,7 @@ async fn test_lorawan_10_device_queue() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -3161,7 +3161,7 @@ async fn test_lorawan_10_device_queue() {
|
||||
assert::downlink_phy_payloads(vec![
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -3181,7 +3181,7 @@ async fn test_lorawan_10_device_queue() {
|
||||
},
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -3228,7 +3228,7 @@ async fn test_lorawan_10_device_queue() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -3248,7 +3248,7 @@ async fn test_lorawan_10_device_queue() {
|
||||
assert::downlink_phy_payloads(vec![
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -3270,7 +3270,7 @@ async fn test_lorawan_10_device_queue() {
|
||||
},
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -3311,7 +3311,7 @@ async fn test_lorawan_10_device_queue() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -3331,7 +3331,7 @@ async fn test_lorawan_10_device_queue() {
|
||||
assert::downlink_phy_payloads(vec![
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::ConfirmedDataDown,
|
||||
f_type: lrwn::FType::ConfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -3351,7 +3351,7 @@ async fn test_lorawan_10_device_queue() {
|
||||
},
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::ConfirmedDataDown,
|
||||
f_type: lrwn::FType::ConfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -3389,7 +3389,7 @@ async fn test_lorawan_10_device_queue() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -3426,7 +3426,7 @@ async fn test_lorawan_10_device_queue() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -3450,7 +3450,7 @@ async fn test_lorawan_10_device_queue() {
|
||||
assert::downlink_phy_payloads(vec![
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -3476,7 +3476,7 @@ async fn test_lorawan_10_device_queue() {
|
||||
},
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -3613,7 +3613,7 @@ async fn test_lorawan_11_device_queue() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -3633,7 +3633,7 @@ async fn test_lorawan_11_device_queue() {
|
||||
assert::downlink_phy_payloads(vec![
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -3653,7 +3653,7 @@ async fn test_lorawan_11_device_queue() {
|
||||
},
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -3700,7 +3700,7 @@ async fn test_lorawan_11_device_queue() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -3720,7 +3720,7 @@ async fn test_lorawan_11_device_queue() {
|
||||
assert::downlink_phy_payloads(vec![
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -3742,7 +3742,7 @@ async fn test_lorawan_11_device_queue() {
|
||||
},
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -3783,7 +3783,7 @@ async fn test_lorawan_11_device_queue() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -3803,7 +3803,7 @@ async fn test_lorawan_11_device_queue() {
|
||||
assert::downlink_phy_payloads(vec![
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::ConfirmedDataDown,
|
||||
f_type: lrwn::FType::ConfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -3823,7 +3823,7 @@ async fn test_lorawan_11_device_queue() {
|
||||
},
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::ConfirmedDataDown,
|
||||
f_type: lrwn::FType::ConfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -3861,7 +3861,7 @@ async fn test_lorawan_11_device_queue() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -3898,7 +3898,7 @@ async fn test_lorawan_11_device_queue() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -3924,7 +3924,7 @@ async fn test_lorawan_11_device_queue() {
|
||||
assert::downlink_phy_payloads(vec![
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -3950,7 +3950,7 @@ async fn test_lorawan_11_device_queue() {
|
||||
},
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -4099,7 +4099,7 @@ async fn test_lorawan_10_adr() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -4123,7 +4123,7 @@ async fn test_lorawan_10_adr() {
|
||||
assert::downlink_phy_payloads_decoded_f_opts(vec![
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -4157,7 +4157,7 @@ async fn test_lorawan_10_adr() {
|
||||
},
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -4203,7 +4203,7 @@ async fn test_lorawan_10_adr() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -4230,38 +4230,35 @@ async fn test_lorawan_10_adr() {
|
||||
name: "acknowledgement of pending adr request".into(),
|
||||
dev_eui: dev.dev_eui,
|
||||
device_queue_items: vec![],
|
||||
before_func: Some(Box::new(move || {
|
||||
let dev_eui = dev.dev_eui;
|
||||
Box::pin(async move {
|
||||
mac_command::set_pending(
|
||||
&dev_eui,
|
||||
lrwn::CID::LinkADRReq,
|
||||
&lrwn::MACCommandSet::new(vec![lrwn::MACCommand::LinkADRReq(
|
||||
lrwn::LinkADRReqPayload {
|
||||
dr: 0,
|
||||
tx_power: 3,
|
||||
ch_mask: lrwn::ChMask::new([
|
||||
true, true, true, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false,
|
||||
]),
|
||||
redundancy: lrwn::Redundancy {
|
||||
ch_mask_cntl: 0,
|
||||
nb_rep: 1,
|
||||
},
|
||||
},
|
||||
)]),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
})
|
||||
})),
|
||||
before_func: None,
|
||||
after_func: None,
|
||||
device_session: Some(ds.clone()),
|
||||
device_session: Some({
|
||||
let mut ds = ds.clone();
|
||||
mac_command::set_pending(
|
||||
&mut ds,
|
||||
&lrwn::MACCommandSet::new(vec![lrwn::MACCommand::LinkADRReq(
|
||||
lrwn::LinkADRReqPayload {
|
||||
dr: 0,
|
||||
tx_power: 3,
|
||||
ch_mask: lrwn::ChMask::new([
|
||||
true, true, true, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false,
|
||||
]),
|
||||
redundancy: lrwn::Redundancy {
|
||||
ch_mask_cntl: 0,
|
||||
nb_rep: 1,
|
||||
},
|
||||
},
|
||||
)]),
|
||||
)
|
||||
.unwrap();
|
||||
ds
|
||||
}),
|
||||
tx_info: tx_info.clone(),
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -4298,38 +4295,35 @@ async fn test_lorawan_10_adr() {
|
||||
name: "negative acknowledgement of pending adr request".into(),
|
||||
dev_eui: dev.dev_eui,
|
||||
device_queue_items: vec![],
|
||||
before_func: Some(Box::new(move || {
|
||||
let dev_eui = dev.dev_eui;
|
||||
Box::pin(async move {
|
||||
mac_command::set_pending(
|
||||
&dev_eui,
|
||||
lrwn::CID::LinkADRReq,
|
||||
&lrwn::MACCommandSet::new(vec![lrwn::MACCommand::LinkADRReq(
|
||||
lrwn::LinkADRReqPayload {
|
||||
dr: 0,
|
||||
tx_power: 3,
|
||||
ch_mask: lrwn::ChMask::new([
|
||||
true, true, true, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false,
|
||||
]),
|
||||
redundancy: lrwn::Redundancy {
|
||||
ch_mask_cntl: 0,
|
||||
nb_rep: 1,
|
||||
},
|
||||
},
|
||||
)]),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
})
|
||||
})),
|
||||
before_func: None,
|
||||
after_func: None,
|
||||
device_session: Some(ds.clone()),
|
||||
device_session: Some({
|
||||
let mut ds = ds.clone();
|
||||
mac_command::set_pending(
|
||||
&mut ds,
|
||||
&lrwn::MACCommandSet::new(vec![lrwn::MACCommand::LinkADRReq(
|
||||
lrwn::LinkADRReqPayload {
|
||||
dr: 0,
|
||||
tx_power: 3,
|
||||
ch_mask: lrwn::ChMask::new([
|
||||
true, true, true, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false,
|
||||
]),
|
||||
redundancy: lrwn::Redundancy {
|
||||
ch_mask_cntl: 0,
|
||||
nb_rep: 1,
|
||||
},
|
||||
},
|
||||
)]),
|
||||
)
|
||||
.unwrap();
|
||||
ds
|
||||
}),
|
||||
tx_info: tx_info.clone(),
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -4373,7 +4367,7 @@ async fn test_lorawan_10_adr() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -4398,7 +4392,7 @@ async fn test_lorawan_10_adr() {
|
||||
assert::downlink_phy_payloads(vec![
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -4418,7 +4412,7 @@ async fn test_lorawan_10_adr() {
|
||||
},
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -4450,7 +4444,7 @@ async fn test_lorawan_10_adr() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -4470,7 +4464,7 @@ async fn test_lorawan_10_adr() {
|
||||
assert::downlink_phy_payloads_decoded_f_opts(vec![
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -4502,7 +4496,7 @@ async fn test_lorawan_10_adr() {
|
||||
},
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -4540,38 +4534,35 @@ async fn test_lorawan_10_adr() {
|
||||
name: "new channel re-configuration ack-ed".into(),
|
||||
dev_eui: dev.dev_eui,
|
||||
device_queue_items: vec![],
|
||||
before_func: Some(Box::new(move || {
|
||||
let dev_eui = dev.dev_eui;
|
||||
Box::pin(async move {
|
||||
mac_command::set_pending(
|
||||
&dev_eui,
|
||||
lrwn::CID::LinkADRReq,
|
||||
&lrwn::MACCommandSet::new(vec![lrwn::MACCommand::LinkADRReq(
|
||||
lrwn::LinkADRReqPayload {
|
||||
dr: 0,
|
||||
tx_power: 1,
|
||||
ch_mask: lrwn::ChMask::new([
|
||||
true, true, true, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false,
|
||||
]),
|
||||
redundancy: lrwn::Redundancy {
|
||||
ch_mask_cntl: 0,
|
||||
nb_rep: 0,
|
||||
},
|
||||
},
|
||||
)]),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
})
|
||||
})),
|
||||
before_func: None,
|
||||
after_func: None,
|
||||
device_session: Some(ds_7chan.clone()),
|
||||
device_session: Some({
|
||||
let mut ds = ds_7chan.clone();
|
||||
mac_command::set_pending(
|
||||
&mut ds,
|
||||
&lrwn::MACCommandSet::new(vec![lrwn::MACCommand::LinkADRReq(
|
||||
lrwn::LinkADRReqPayload {
|
||||
dr: 0,
|
||||
tx_power: 1,
|
||||
ch_mask: lrwn::ChMask::new([
|
||||
true, true, true, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false,
|
||||
]),
|
||||
redundancy: lrwn::Redundancy {
|
||||
ch_mask_cntl: 0,
|
||||
nb_rep: 0,
|
||||
},
|
||||
},
|
||||
)]),
|
||||
)
|
||||
.unwrap();
|
||||
ds
|
||||
}),
|
||||
tx_info: tx_info.clone(),
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -4606,38 +4597,35 @@ async fn test_lorawan_10_adr() {
|
||||
name: "new channel re-configuration not ack-ed".into(),
|
||||
dev_eui: dev.dev_eui,
|
||||
device_queue_items: vec![],
|
||||
before_func: Some(Box::new(move || {
|
||||
let dev_eui = dev.dev_eui;
|
||||
Box::pin(async move {
|
||||
mac_command::set_pending(
|
||||
&dev_eui,
|
||||
lrwn::CID::LinkADRReq,
|
||||
&lrwn::MACCommandSet::new(vec![lrwn::MACCommand::LinkADRReq(
|
||||
lrwn::LinkADRReqPayload {
|
||||
dr: 0,
|
||||
tx_power: 1,
|
||||
ch_mask: lrwn::ChMask::new([
|
||||
true, true, true, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false,
|
||||
]),
|
||||
redundancy: lrwn::Redundancy {
|
||||
ch_mask_cntl: 0,
|
||||
nb_rep: 0,
|
||||
},
|
||||
},
|
||||
)]),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
})
|
||||
})),
|
||||
before_func: None,
|
||||
after_func: None,
|
||||
device_session: Some(ds_7chan.clone()),
|
||||
device_session: Some({
|
||||
let mut ds = ds_7chan.clone();
|
||||
mac_command::set_pending(
|
||||
&mut ds,
|
||||
&lrwn::MACCommandSet::new(vec![lrwn::MACCommand::LinkADRReq(
|
||||
lrwn::LinkADRReqPayload {
|
||||
dr: 0,
|
||||
tx_power: 1,
|
||||
ch_mask: lrwn::ChMask::new([
|
||||
true, true, true, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false,
|
||||
]),
|
||||
redundancy: lrwn::Redundancy {
|
||||
ch_mask_cntl: 0,
|
||||
nb_rep: 0,
|
||||
},
|
||||
},
|
||||
)]),
|
||||
)
|
||||
.unwrap();
|
||||
ds
|
||||
}),
|
||||
tx_info: tx_info.clone(),
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -4678,7 +4666,7 @@ async fn test_lorawan_10_adr() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -4703,7 +4691,7 @@ async fn test_lorawan_10_adr() {
|
||||
assert::downlink_phy_payloads_decoded_f_opts(vec![
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -4735,7 +4723,7 @@ async fn test_lorawan_10_adr() {
|
||||
},
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -4780,7 +4768,7 @@ async fn test_lorawan_10_adr() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -4923,7 +4911,7 @@ async fn test_lorawan_10_device_status_request() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -4942,7 +4930,7 @@ async fn test_lorawan_10_device_status_request() {
|
||||
assert::downlink_phy_payloads_decoded_f_opts(vec![
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -4965,7 +4953,7 @@ async fn test_lorawan_10_device_status_request() {
|
||||
},
|
||||
lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataDown,
|
||||
f_type: lrwn::FType::UnconfirmedDataDown,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -5000,7 +4988,7 @@ async fn test_lorawan_10_device_status_request() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -5031,7 +5019,7 @@ async fn test_lorawan_10_device_status_request() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -5193,7 +5181,7 @@ async fn test_lorawan_11_receive_window_selection() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -5263,7 +5251,7 @@ async fn test_lorawan_11_receive_window_selection() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -5333,7 +5321,7 @@ async fn test_lorawan_11_receive_window_selection() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -5432,7 +5420,7 @@ async fn test_lorawan_11_receive_window_selection() {
|
||||
rx_info: rx_info.clone(),
|
||||
phy_payload: lrwn::PhyPayload {
|
||||
mhdr: lrwn::MHDR {
|
||||
m_type: lrwn::MType::UnconfirmedDataUp,
|
||||
f_type: lrwn::FType::UnconfirmedDataUp,
|
||||
major: lrwn::Major::LoRaWANR1,
|
||||
},
|
||||
payload: lrwn::Payload::MACPayload(lrwn::MACPayload {
|
||||
@ -5558,7 +5546,7 @@ async fn run_test(t: &Test) {
|
||||
|
||||
uplink::handle_uplink(
|
||||
CommonName::EU868,
|
||||
"eu868".into(),
|
||||
"eu868",
|
||||
Uuid::new_v4(),
|
||||
gw::UplinkFrameSet {
|
||||
phy_payload: t.phy_payload.to_vec().unwrap(),
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user