mirror of
https://github.com/chirpstack/chirpstack.git
synced 2025-06-25 02:29:14 +00:00
Compare commits
10 Commits
v4.0.0-tes
...
api/go/v4.
Author | SHA1 | Date | |
---|---|---|---|
e7432986cd | |||
69e3b672ac | |||
067869e4f0 | |||
3cbc2eba9b | |||
5436582f03 | |||
9db867906d | |||
954c408247 | |||
cbb1449868 | |||
634aea6a71 | |||
11d433a394 |
5
.cargo/config.toml
Normal file
5
.cargo/config.toml
Normal file
@ -0,0 +1,5 @@
|
||||
[target.armv7-unknown-linux-gnueabihf]
|
||||
linker = "arm-linux-gnueabihf-gcc"
|
||||
|
||||
[target.aarch64-unknown-linux-gnu]
|
||||
linker = "aarch64-linux-gnu-gcc"
|
@ -1,5 +1,6 @@
|
||||
.git
|
||||
.cargo
|
||||
.rust
|
||||
**/target
|
||||
**/node_modules
|
||||
Dockerfile
|
||||
|
2
.github/buildkitd.toml
vendored
Normal file
2
.github/buildkitd.toml
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
[worker.oci]
|
||||
max-parallelism = 1
|
29
.github/workflows/main.yml
vendored
29
.github/workflows/main.yml
vendored
@ -14,12 +14,22 @@ jobs:
|
||||
-
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Cargo cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: .rust/
|
||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
-
|
||||
name: Build UI
|
||||
run: make build-ui
|
||||
-
|
||||
name: Run tests
|
||||
run: make test
|
||||
-
|
||||
name: Make cache accessible to caching action
|
||||
run: |
|
||||
sudo chown $(whoami):$(whoami) -R .rust
|
||||
|
||||
dist:
|
||||
needs: tests
|
||||
@ -30,11 +40,11 @@ jobs:
|
||||
name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
-
|
||||
name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
name: Cargo cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: .rust/
|
||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||
-
|
||||
name: Build UI
|
||||
run: make build-ui
|
||||
@ -52,6 +62,11 @@ jobs:
|
||||
name: Upload binaries to S3
|
||||
run: |
|
||||
aws s3 sync dist s3://builds.loraserver.io/chirpstack
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
-
|
||||
name: Make cache accessible to caching action
|
||||
run: |
|
||||
sudo chown $(whoami):$(whoami) -R .rust
|
||||
|
||||
docker:
|
||||
needs: tests
|
||||
@ -78,6 +93,8 @@ jobs:
|
||||
-
|
||||
name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
with:
|
||||
config: .github/buildkitd.toml
|
||||
-
|
||||
name: Login to DockerHub
|
||||
uses: docker/login-action@v1
|
||||
@ -89,7 +106,7 @@ jobs:
|
||||
id: docker_build
|
||||
uses: docker/build-push-action@v2
|
||||
with:
|
||||
platforms: linux/amd64,linux/arm64
|
||||
platforms: linux/amd64,linux/arm/v7,linux/arm64
|
||||
push: ${{ startsWith(github.ref, 'refs/tags/v') }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,6 +1,7 @@
|
||||
# hidden files
|
||||
.*
|
||||
!/chirpstack/.rpm
|
||||
!/.cargo
|
||||
|
||||
# Log files
|
||||
*.log
|
||||
|
95
Cargo.lock
generated
95
Cargo.lock
generated
@ -635,7 +635,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "backend"
|
||||
version = "4.0.0-test.7"
|
||||
version = "4.0.0-test.11"
|
||||
dependencies = [
|
||||
"aes-kw",
|
||||
"anyhow",
|
||||
@ -676,11 +676,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "bigdecimal"
|
||||
version = "0.1.2"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1374191e2dd25f9ae02e3aa95041ed5d747fc77b3c102b49fe2dd9a8117a6244"
|
||||
checksum = "6aaf33151a6429fe9211d1b276eafdf70cdff28b071e76c0b0e1503221ea3744"
|
||||
dependencies = [
|
||||
"num-bigint 0.2.6",
|
||||
"num-bigint",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
@ -821,9 +821,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.1.0"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
|
||||
checksum = "f0b3de4a0c5e67e16066a0715723abd91edc2f9001d09c46e1dca929351e130e"
|
||||
|
||||
[[package]]
|
||||
name = "bytes-utils"
|
||||
@ -879,7 +879,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chirpstack"
|
||||
version = "4.0.0-test.7"
|
||||
version = "4.0.0-test.11"
|
||||
dependencies = [
|
||||
"aes 0.7.5",
|
||||
"anyhow",
|
||||
@ -958,7 +958,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "chirpstack_api"
|
||||
version = "4.0.0-test.7"
|
||||
version = "4.0.0-test.11"
|
||||
dependencies = [
|
||||
"hex",
|
||||
"pbjson",
|
||||
@ -1238,16 +1238,17 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "diesel"
|
||||
version = "1.4.8"
|
||||
version = "2.0.0-rc.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b28135ecf6b7d446b43e27e225622a038cc4e2930a1022f51cdb97ada19b8e4d"
|
||||
checksum = "e531d0abf8147036383c88ce3785d9cda6fe1b8b1183021ffa01cf49c5819d24"
|
||||
dependencies = [
|
||||
"bigdecimal",
|
||||
"bitflags",
|
||||
"byteorder",
|
||||
"chrono",
|
||||
"diesel_derives",
|
||||
"num-bigint 0.2.6",
|
||||
"itoa 1.0.2",
|
||||
"num-bigint",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"pq-sys",
|
||||
@ -1258,10 +1259,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "diesel_derives"
|
||||
version = "1.4.1"
|
||||
version = "2.0.0-rc.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3"
|
||||
checksum = "212ba0cdc611523c37f26c7b3b4aedb4af7cbfe9239c4e7736a8a7c82284d77b"
|
||||
dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
@ -1269,10 +1271,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "diesel_migrations"
|
||||
version = "1.4.0"
|
||||
version = "2.0.0-rc.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf3cde8413353dc7f5d72fa8ce0b99a560a359d2c5ef1e5817ca731cd9008f4c"
|
||||
checksum = "e2edcb7e9cff76af48e7fa33cc4680acc7df19e58a4a4aaed3e2b67fb83bc06d"
|
||||
dependencies = [
|
||||
"diesel",
|
||||
"migrations_internals",
|
||||
"migrations_macros",
|
||||
]
|
||||
@ -2209,7 +2212,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "lrwn"
|
||||
version = "4.0.0-test.7"
|
||||
version = "4.0.0-test.11"
|
||||
dependencies = [
|
||||
"aes 0.7.5",
|
||||
"anyhow",
|
||||
@ -2256,23 +2259,23 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
|
||||
|
||||
[[package]]
|
||||
name = "migrations_internals"
|
||||
version = "1.4.1"
|
||||
version = "2.0.0-rc.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b4fc84e4af020b837029e017966f86a1c2d5e83e64b589963d5047525995860"
|
||||
checksum = "61e2226081f9176165a49b006a0729de8cafa749615b349e15c444dbd39e4d9d"
|
||||
dependencies = [
|
||||
"diesel",
|
||||
"serde",
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "migrations_macros"
|
||||
version = "1.4.2"
|
||||
version = "2.0.0-rc.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9753f12909fd8d923f75ae5c3258cae1ed3c8ec052e1b38c93c21a6d157f789c"
|
||||
checksum = "37dbadac6f186c134552cd9a0ec14b157cf4f04eacacebd5e6c1bfc6aeb158b3"
|
||||
dependencies = [
|
||||
"migrations_internals",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2367,17 +2370,6 @@ dependencies = [
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.3"
|
||||
@ -2497,7 +2489,7 @@ dependencies = [
|
||||
"http",
|
||||
"itertools",
|
||||
"log",
|
||||
"num-bigint 0.4.3",
|
||||
"num-bigint",
|
||||
"oauth2",
|
||||
"rand",
|
||||
"ring",
|
||||
@ -2880,9 +2872,9 @@ checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
|
||||
|
||||
[[package]]
|
||||
name = "pq-sys"
|
||||
version = "0.4.6"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ac25eee5a0582f45a67e837e350d784e7003bd29a5f460796772061ca49ffda"
|
||||
checksum = "3b845d6d8ec554f972a2c5298aad68953fd64e7441e846075450b44656a016d1"
|
||||
dependencies = [
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
@ -2914,6 +2906,30 @@ dependencies = [
|
||||
"toml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.40"
|
||||
@ -3089,6 +3105,7 @@ version = "4.2.0+1.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e542c6863b04ce0fa0c5719bc6b7b348cf8dd21af1bb03c9db5f9805b2a6473"
|
||||
dependencies = [
|
||||
"cmake",
|
||||
"libc",
|
||||
"libz-sys",
|
||||
"num_enum",
|
||||
@ -3714,7 +3731,7 @@ version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085"
|
||||
dependencies = [
|
||||
"num-bigint 0.4.3",
|
||||
"num-bigint",
|
||||
"num-traits",
|
||||
"thiserror",
|
||||
"time 0.3.11",
|
||||
@ -4492,9 +4509,9 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "0.8.2"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
|
||||
checksum = "dd6469f4314d5f1ffec476e05f17cc9a78bc7a27a6a857842170bdf8d6f98d2f"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"serde",
|
||||
|
61
Dockerfile
61
Dockerfile
@ -1,4 +1,5 @@
|
||||
FROM alpine:3.15.0 AS ui-build
|
||||
# UI build stage
|
||||
FROM --platform=$BUILDPLATFORM alpine:3.15.0 AS ui-build
|
||||
|
||||
ENV PROJECT_PATH=/chirpstack
|
||||
|
||||
@ -9,15 +10,61 @@ COPY ./api/grpc-web $PROJECT_PATH/api/grpc-web
|
||||
COPY ./ui $PROJECT_PATH/ui
|
||||
|
||||
RUN cd $PROJECT_PATH/ui && \
|
||||
yarn install --network-timeout 600000 && \
|
||||
yarn build
|
||||
yarn install --network-timeout 600000 && \
|
||||
yarn build
|
||||
|
||||
FROM chirpstack/chirpstack-dev-cache:latest AS rust-build
|
||||
|
||||
# ChirpStack build stage
|
||||
FROM --platform=$BUILDPLATFORM rust:1.62.0-buster AS rust-build
|
||||
|
||||
ENV PROJECT_PATH=/chirpstack
|
||||
RUN mkdir -p $PROJECT_PATH
|
||||
|
||||
RUN dpkg --add-architecture armhf
|
||||
RUN dpkg --add-architecture arm64
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y \
|
||||
make \
|
||||
cmake \
|
||||
git \
|
||||
libpq-dev \
|
||||
clang \
|
||||
libclang-3.9-dev \
|
||||
jq \
|
||||
gcc-arm-linux-gnueabihf \
|
||||
g++-arm-linux-gnueabihf \
|
||||
gcc-aarch64-linux-gnu \
|
||||
g++-aarch64-linux-gnu \
|
||||
zlib1g-dev:armhf \
|
||||
zlib1g-dev:arm64
|
||||
|
||||
RUN rustup target add armv7-unknown-linux-gnueabihf
|
||||
RUN rustup target add aarch64-unknown-linux-gnu
|
||||
|
||||
ARG TARGETPLATFORM
|
||||
RUN mkdir -p /release/$TARGETPLATFORM
|
||||
|
||||
COPY . $PROJECT_PATH
|
||||
COPY --from=ui-build $PROJECT_PATH/ui/build $PROJECT_PATH/ui/build
|
||||
RUN cd $PROJECT_PATH/chirpstack && cargo build --release
|
||||
|
||||
RUN case "$TARGETPLATFORM" in \
|
||||
"linux/amd64") \
|
||||
cd $PROJECT_PATH/chirpstack && make release-amd64; \
|
||||
cp $PROJECT_PATH/target/release/chirpstack /release/$TARGETPLATFORM; \
|
||||
;; \
|
||||
"linux/arm/v7") \
|
||||
cd $PROJECT_PATH/chirpstack && make release-armv7hf; \
|
||||
cp $PROJECT_PATH/target/armv7-unknown-linux-gnueabihf/release/chirpstack /release/$TARGETPLATFORM; \
|
||||
;; \
|
||||
"linux/arm64") \
|
||||
cd $PROJECT_PATH/chirpstack && make release-arm64; \
|
||||
cp $PROJECT_PATH/target/aarch64-unknown-linux-gnu/release/chirpstack /release/$TARGETPLATFORM; \
|
||||
;; \
|
||||
esac;
|
||||
|
||||
|
||||
# Final stage
|
||||
FROM debian:buster-slim as production
|
||||
|
||||
RUN apt-get update && \
|
||||
@ -26,7 +73,9 @@ RUN apt-get update && \
|
||||
libpq5 \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY --from=rust-build /target/release/chirpstack /usr/bin/chirpstack
|
||||
ARG TARGETPLATFORM
|
||||
|
||||
COPY --from=rust-build /release/$TARGETPLATFORM/chirpstack /usr/bin/chirpstack
|
||||
COPY --from=rust-build /chirpstack/chirpstack/configuration/* /etc/chirpstack/
|
||||
USER nobody:nogroup
|
||||
ENTRYPOINT ["/usr/bin/chirpstack"]
|
||||
|
@ -1,36 +0,0 @@
|
||||
FROM rust:1.62.0-buster
|
||||
|
||||
ENV PROJECT_PATH=/chirpstack
|
||||
ENV CARGO_TARGET_DIR=/target
|
||||
|
||||
RUN mkdir -p $PROJECT_PATH
|
||||
RUN mkdir -p $CARGO_TARGET_DIR
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y \
|
||||
make \
|
||||
cmake \
|
||||
git \
|
||||
bash \
|
||||
screen \
|
||||
postgresql-client \
|
||||
libpq-dev \
|
||||
mosquitto-clients \
|
||||
redis-tools \
|
||||
rpm \
|
||||
clang \
|
||||
golang-cfssl \
|
||||
jq \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN rustup component add rustfmt clippy
|
||||
|
||||
RUN cargo install diesel_cli --no-default-features --features postgres
|
||||
RUN cargo install cargo-deb
|
||||
RUN cargo install cargo-rpm
|
||||
|
||||
COPY . $PROJECT_PATH
|
||||
|
||||
WORKDIR $PROJECT_PATH/chirpstack
|
||||
RUN cargo build --release
|
||||
RUN rm -rf $PROJECT_PATH/*
|
40
Dockerfile-devel
Normal file
40
Dockerfile-devel
Normal file
@ -0,0 +1,40 @@
|
||||
FROM rust:1.62.0-buster
|
||||
|
||||
ENV PROJECT_PATH=/chirpstack
|
||||
RUN mkdir -p $PROJECT_PATH
|
||||
|
||||
RUN dpkg --add-architecture armhf
|
||||
RUN dpkg --add-architecture arm64
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y \
|
||||
make \
|
||||
cmake \
|
||||
git \
|
||||
bash \
|
||||
screen \
|
||||
postgresql-client \
|
||||
libpq-dev \
|
||||
mosquitto-clients \
|
||||
redis-tools \
|
||||
rpm \
|
||||
clang \
|
||||
libclang-3.9-dev \
|
||||
golang-cfssl \
|
||||
jq \
|
||||
gcc-arm-linux-gnueabihf \
|
||||
g++-arm-linux-gnueabihf \
|
||||
gcc-aarch64-linux-gnu \
|
||||
g++-aarch64-linux-gnu \
|
||||
zlib1g-dev:armhf \
|
||||
zlib1g-dev:arm64
|
||||
|
||||
RUN rustup component add rustfmt clippy
|
||||
RUN rustup target add armv7-unknown-linux-gnueabihf
|
||||
RUN rustup target add aarch64-unknown-linux-gnu
|
||||
|
||||
RUN cargo install diesel_cli --version 2.0.0-rc.0 --no-default-features --features postgres
|
||||
RUN cargo install cargo-deb
|
||||
RUN cargo install cargo-rpm
|
||||
|
||||
WORKDIR $PROJECT_PATH/chirpstack
|
16
Makefile
16
Makefile
@ -1,18 +1,8 @@
|
||||
.PHONY: dist api
|
||||
|
||||
# Builds a debug / development binary.
|
||||
build-debug:
|
||||
docker-compose run --rm chirpstack make debug
|
||||
|
||||
# Builds a release binary.
|
||||
build-release:
|
||||
docker-compose run --rm chirpstack make release
|
||||
|
||||
# Build distributable binaries.
|
||||
dist:
|
||||
# The pull is needed as else the specified platform is not respected.
|
||||
docker-compose pull chirpstack-build-amd64 && docker-compose run --rm chirpstack-build-amd64 make dist
|
||||
docker-compose pull chirpstack-build-arm64 && docker-compose run --rm chirpstack-build-arm64 make dist
|
||||
docker-compose run --rm --no-deps chirpstack make dist
|
||||
|
||||
# Set the versions
|
||||
version:
|
||||
@ -31,7 +21,7 @@ api: version
|
||||
|
||||
# Builds the UI.
|
||||
build-ui:
|
||||
docker-compose run --rm chirpstack-ui make build
|
||||
docker-compose run --rm --no-deps chirpstack-ui make build
|
||||
|
||||
# Enters the devshell for ChirpStack development.
|
||||
devshell:
|
||||
@ -52,5 +42,5 @@ test-server: build-ui
|
||||
|
||||
# Update the Docker development images
|
||||
update-images:
|
||||
docker-compose pull chirpstack
|
||||
docker-compose build chirpstack
|
||||
docker-compose build chirpstack-ui
|
||||
|
1042
api/go/gw/gw.pb.go
vendored
1042
api/go/gw/gw.pb.go
vendored
File diff suppressed because it is too large
Load Diff
2
api/grpc-web/package.json
vendored
2
api/grpc-web/package.json
vendored
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@chirpstack/chirpstack-api-grpc-web",
|
||||
"version": "4.0.0-test.7",
|
||||
"version": "4.0.0-test.11",
|
||||
"description": "Chirpstack gRPC-web API",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
|
160
api/js/gw/gw_pb.d.ts
vendored
160
api/js/gw/gw_pb.d.ts
vendored
@ -268,13 +268,13 @@ export namespace PlainFineTimestamp {
|
||||
}
|
||||
|
||||
export class GatewayStats extends jspb.Message {
|
||||
getGatewayId(): Uint8Array | string;
|
||||
getGatewayId_asU8(): Uint8Array;
|
||||
getGatewayId_asB64(): string;
|
||||
setGatewayId(value: Uint8Array | string): void;
|
||||
getGatewayIdLegacy(): Uint8Array | string;
|
||||
getGatewayIdLegacy_asU8(): Uint8Array;
|
||||
getGatewayIdLegacy_asB64(): string;
|
||||
setGatewayIdLegacy(value: Uint8Array | string): void;
|
||||
|
||||
getIp(): string;
|
||||
setIp(value: string): void;
|
||||
getGatewayId(): string;
|
||||
setGatewayId(value: string): void;
|
||||
|
||||
hasTime(): boolean;
|
||||
clearTime(): void;
|
||||
@ -303,11 +303,6 @@ export class GatewayStats extends jspb.Message {
|
||||
|
||||
getMetaDataMap(): jspb.Map<string, string>;
|
||||
clearMetaDataMap(): void;
|
||||
getStatsId(): Uint8Array | string;
|
||||
getStatsId_asU8(): Uint8Array;
|
||||
getStatsId_asB64(): string;
|
||||
setStatsId(value: Uint8Array | string): void;
|
||||
|
||||
getTxPacketsPerFrequencyMap(): jspb.Map<number, number>;
|
||||
clearTxPacketsPerFrequencyMap(): void;
|
||||
getRxPacketsPerFrequencyMap(): jspb.Map<number, number>;
|
||||
@ -336,8 +331,8 @@ export class GatewayStats extends jspb.Message {
|
||||
|
||||
export namespace GatewayStats {
|
||||
export type AsObject = {
|
||||
gatewayId: Uint8Array | string,
|
||||
ip: string,
|
||||
gatewayIdLegacy: Uint8Array | string,
|
||||
gatewayId: string,
|
||||
time?: google_protobuf_timestamp_pb.Timestamp.AsObject,
|
||||
location?: common_common_pb.Location.AsObject,
|
||||
configVersion: string,
|
||||
@ -346,7 +341,6 @@ export namespace GatewayStats {
|
||||
txPacketsReceived: number,
|
||||
txPacketsEmitted: number,
|
||||
metaDataMap: Array<[string, string]>,
|
||||
statsId: Uint8Array | string,
|
||||
txPacketsPerFrequencyMap: Array<[number, number]>,
|
||||
rxPacketsPerFrequencyMap: Array<[number, number]>,
|
||||
txPacketsPerModulationList: Array<PerModulationCount.AsObject>,
|
||||
@ -1031,10 +1025,13 @@ export namespace DownlinkTxAckItem {
|
||||
}
|
||||
|
||||
export class GatewayConfiguration extends jspb.Message {
|
||||
getGatewayId(): Uint8Array | string;
|
||||
getGatewayId_asU8(): Uint8Array;
|
||||
getGatewayId_asB64(): string;
|
||||
setGatewayId(value: Uint8Array | string): void;
|
||||
getGatewayIdLegacy(): Uint8Array | string;
|
||||
getGatewayIdLegacy_asU8(): Uint8Array;
|
||||
getGatewayIdLegacy_asB64(): string;
|
||||
setGatewayIdLegacy(value: Uint8Array | string): void;
|
||||
|
||||
getGatewayId(): string;
|
||||
setGatewayId(value: string): void;
|
||||
|
||||
getVersion(): string;
|
||||
setVersion(value: string): void;
|
||||
@ -1061,7 +1058,8 @@ export class GatewayConfiguration extends jspb.Message {
|
||||
|
||||
export namespace GatewayConfiguration {
|
||||
export type AsObject = {
|
||||
gatewayId: Uint8Array | string,
|
||||
gatewayIdLegacy: Uint8Array | string,
|
||||
gatewayId: string,
|
||||
version: string,
|
||||
channelsList: Array<ChannelConfiguration.AsObject>,
|
||||
statsInterval?: google_protobuf_duration_pb.Duration.AsObject,
|
||||
@ -1072,18 +1070,18 @@ export class ChannelConfiguration extends jspb.Message {
|
||||
getFrequency(): number;
|
||||
setFrequency(value: number): void;
|
||||
|
||||
getModulation(): common_common_pb.ModulationMap[keyof common_common_pb.ModulationMap];
|
||||
setModulation(value: common_common_pb.ModulationMap[keyof common_common_pb.ModulationMap]): void;
|
||||
getModulationLegacy(): common_common_pb.ModulationMap[keyof common_common_pb.ModulationMap];
|
||||
setModulationLegacy(value: common_common_pb.ModulationMap[keyof common_common_pb.ModulationMap]): void;
|
||||
|
||||
hasLoraModulationConfig(): boolean;
|
||||
clearLoraModulationConfig(): void;
|
||||
getLoraModulationConfig(): LoRaModulationConfig | undefined;
|
||||
setLoraModulationConfig(value?: LoRaModulationConfig): void;
|
||||
getLoraModulationConfig(): LoraModulationConfig | undefined;
|
||||
setLoraModulationConfig(value?: LoraModulationConfig): void;
|
||||
|
||||
hasFskModulationConfig(): boolean;
|
||||
clearFskModulationConfig(): void;
|
||||
getFskModulationConfig(): FSKModulationConfig | undefined;
|
||||
setFskModulationConfig(value?: FSKModulationConfig): void;
|
||||
getFskModulationConfig(): FskModulationConfig | undefined;
|
||||
setFskModulationConfig(value?: FskModulationConfig): void;
|
||||
|
||||
getBoard(): number;
|
||||
setBoard(value: number): void;
|
||||
@ -1105,9 +1103,9 @@ export class ChannelConfiguration extends jspb.Message {
|
||||
export namespace ChannelConfiguration {
|
||||
export type AsObject = {
|
||||
frequency: number,
|
||||
modulation: common_common_pb.ModulationMap[keyof common_common_pb.ModulationMap],
|
||||
loraModulationConfig?: LoRaModulationConfig.AsObject,
|
||||
fskModulationConfig?: FSKModulationConfig.AsObject,
|
||||
modulationLegacy: common_common_pb.ModulationMap[keyof common_common_pb.ModulationMap],
|
||||
loraModulationConfig?: LoraModulationConfig.AsObject,
|
||||
fskModulationConfig?: FskModulationConfig.AsObject,
|
||||
board: number,
|
||||
demodulator: number,
|
||||
}
|
||||
@ -1119,7 +1117,10 @@ export namespace ChannelConfiguration {
|
||||
}
|
||||
}
|
||||
|
||||
export class LoRaModulationConfig extends jspb.Message {
|
||||
export class LoraModulationConfig extends jspb.Message {
|
||||
getBandwidthLegacy(): number;
|
||||
setBandwidthLegacy(value: number): void;
|
||||
|
||||
getBandwidth(): number;
|
||||
setBandwidth(value: number): void;
|
||||
|
||||
@ -1129,23 +1130,27 @@ export class LoRaModulationConfig extends jspb.Message {
|
||||
addSpreadingFactors(value: number, index?: number): number;
|
||||
|
||||
serializeBinary(): Uint8Array;
|
||||
toObject(includeInstance?: boolean): LoRaModulationConfig.AsObject;
|
||||
static toObject(includeInstance: boolean, msg: LoRaModulationConfig): LoRaModulationConfig.AsObject;
|
||||
toObject(includeInstance?: boolean): LoraModulationConfig.AsObject;
|
||||
static toObject(includeInstance: boolean, msg: LoraModulationConfig): LoraModulationConfig.AsObject;
|
||||
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
|
||||
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
|
||||
static serializeBinaryToWriter(message: LoRaModulationConfig, writer: jspb.BinaryWriter): void;
|
||||
static deserializeBinary(bytes: Uint8Array): LoRaModulationConfig;
|
||||
static deserializeBinaryFromReader(message: LoRaModulationConfig, reader: jspb.BinaryReader): LoRaModulationConfig;
|
||||
static serializeBinaryToWriter(message: LoraModulationConfig, writer: jspb.BinaryWriter): void;
|
||||
static deserializeBinary(bytes: Uint8Array): LoraModulationConfig;
|
||||
static deserializeBinaryFromReader(message: LoraModulationConfig, reader: jspb.BinaryReader): LoraModulationConfig;
|
||||
}
|
||||
|
||||
export namespace LoRaModulationConfig {
|
||||
export namespace LoraModulationConfig {
|
||||
export type AsObject = {
|
||||
bandwidthLegacy: number,
|
||||
bandwidth: number,
|
||||
spreadingFactorsList: Array<number>,
|
||||
}
|
||||
}
|
||||
|
||||
export class FSKModulationConfig extends jspb.Message {
|
||||
export class FskModulationConfig extends jspb.Message {
|
||||
getBandwidthLegacy(): number;
|
||||
setBandwidthLegacy(value: number): void;
|
||||
|
||||
getBandwidth(): number;
|
||||
setBandwidth(value: number): void;
|
||||
|
||||
@ -1153,27 +1158,31 @@ export class FSKModulationConfig extends jspb.Message {
|
||||
setBitrate(value: number): void;
|
||||
|
||||
serializeBinary(): Uint8Array;
|
||||
toObject(includeInstance?: boolean): FSKModulationConfig.AsObject;
|
||||
static toObject(includeInstance: boolean, msg: FSKModulationConfig): FSKModulationConfig.AsObject;
|
||||
toObject(includeInstance?: boolean): FskModulationConfig.AsObject;
|
||||
static toObject(includeInstance: boolean, msg: FskModulationConfig): FskModulationConfig.AsObject;
|
||||
static extensions: {[key: number]: jspb.ExtensionFieldInfo<jspb.Message>};
|
||||
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
|
||||
static serializeBinaryToWriter(message: FSKModulationConfig, writer: jspb.BinaryWriter): void;
|
||||
static deserializeBinary(bytes: Uint8Array): FSKModulationConfig;
|
||||
static deserializeBinaryFromReader(message: FSKModulationConfig, reader: jspb.BinaryReader): FSKModulationConfig;
|
||||
static serializeBinaryToWriter(message: FskModulationConfig, writer: jspb.BinaryWriter): void;
|
||||
static deserializeBinary(bytes: Uint8Array): FskModulationConfig;
|
||||
static deserializeBinaryFromReader(message: FskModulationConfig, reader: jspb.BinaryReader): FskModulationConfig;
|
||||
}
|
||||
|
||||
export namespace FSKModulationConfig {
|
||||
export namespace FskModulationConfig {
|
||||
export type AsObject = {
|
||||
bandwidthLegacy: number,
|
||||
bandwidth: number,
|
||||
bitrate: number,
|
||||
}
|
||||
}
|
||||
|
||||
export class GatewayCommandExecRequest extends jspb.Message {
|
||||
getGatewayId(): Uint8Array | string;
|
||||
getGatewayId_asU8(): Uint8Array;
|
||||
getGatewayId_asB64(): string;
|
||||
setGatewayId(value: Uint8Array | string): void;
|
||||
getGatewayIdLegacy(): Uint8Array | string;
|
||||
getGatewayIdLegacy_asU8(): Uint8Array;
|
||||
getGatewayIdLegacy_asB64(): string;
|
||||
setGatewayIdLegacy(value: Uint8Array | string): void;
|
||||
|
||||
getGatewayId(): string;
|
||||
setGatewayId(value: string): void;
|
||||
|
||||
getCommand(): string;
|
||||
setCommand(value: string): void;
|
||||
@ -1202,7 +1211,8 @@ export class GatewayCommandExecRequest extends jspb.Message {
|
||||
|
||||
export namespace GatewayCommandExecRequest {
|
||||
export type AsObject = {
|
||||
gatewayId: Uint8Array | string,
|
||||
gatewayIdLegacy: Uint8Array | string,
|
||||
gatewayId: string,
|
||||
command: string,
|
||||
execid: Uint8Array | string,
|
||||
stdin: Uint8Array | string,
|
||||
@ -1211,10 +1221,13 @@ export namespace GatewayCommandExecRequest {
|
||||
}
|
||||
|
||||
export class GatewayCommandExecResponse extends jspb.Message {
|
||||
getGatewayId(): Uint8Array | string;
|
||||
getGatewayId_asU8(): Uint8Array;
|
||||
getGatewayId_asB64(): string;
|
||||
setGatewayId(value: Uint8Array | string): void;
|
||||
getGatewayIdLegacy(): Uint8Array | string;
|
||||
getGatewayIdLegacy_asU8(): Uint8Array;
|
||||
getGatewayIdLegacy_asB64(): string;
|
||||
setGatewayIdLegacy(value: Uint8Array | string): void;
|
||||
|
||||
getGatewayId(): string;
|
||||
setGatewayId(value: string): void;
|
||||
|
||||
getExecId(): Uint8Array | string;
|
||||
getExecId_asU8(): Uint8Array;
|
||||
@ -1246,7 +1259,8 @@ export class GatewayCommandExecResponse extends jspb.Message {
|
||||
|
||||
export namespace GatewayCommandExecResponse {
|
||||
export type AsObject = {
|
||||
gatewayId: Uint8Array | string,
|
||||
gatewayIdLegacy: Uint8Array | string,
|
||||
gatewayId: string,
|
||||
execId: Uint8Array | string,
|
||||
stdout: Uint8Array | string,
|
||||
stderr: Uint8Array | string,
|
||||
@ -1255,10 +1269,13 @@ export namespace GatewayCommandExecResponse {
|
||||
}
|
||||
|
||||
export class RawPacketForwarderEvent extends jspb.Message {
|
||||
getGatewayId(): Uint8Array | string;
|
||||
getGatewayId_asU8(): Uint8Array;
|
||||
getGatewayId_asB64(): string;
|
||||
setGatewayId(value: Uint8Array | string): void;
|
||||
getGatewayIdLegacy(): Uint8Array | string;
|
||||
getGatewayIdLegacy_asU8(): Uint8Array;
|
||||
getGatewayIdLegacy_asB64(): string;
|
||||
setGatewayIdLegacy(value: Uint8Array | string): void;
|
||||
|
||||
getGatewayId(): string;
|
||||
setGatewayId(value: string): void;
|
||||
|
||||
getRawId(): Uint8Array | string;
|
||||
getRawId_asU8(): Uint8Array;
|
||||
@ -1282,17 +1299,21 @@ export class RawPacketForwarderEvent extends jspb.Message {
|
||||
|
||||
export namespace RawPacketForwarderEvent {
|
||||
export type AsObject = {
|
||||
gatewayId: Uint8Array | string,
|
||||
gatewayIdLegacy: Uint8Array | string,
|
||||
gatewayId: string,
|
||||
rawId: Uint8Array | string,
|
||||
payload: Uint8Array | string,
|
||||
}
|
||||
}
|
||||
|
||||
export class RawPacketForwarderCommand extends jspb.Message {
|
||||
getGatewayId(): Uint8Array | string;
|
||||
getGatewayId_asU8(): Uint8Array;
|
||||
getGatewayId_asB64(): string;
|
||||
setGatewayId(value: Uint8Array | string): void;
|
||||
getGatewayIdLegacy(): Uint8Array | string;
|
||||
getGatewayIdLegacy_asU8(): Uint8Array;
|
||||
getGatewayIdLegacy_asB64(): string;
|
||||
setGatewayIdLegacy(value: Uint8Array | string): void;
|
||||
|
||||
getGatewayId(): string;
|
||||
setGatewayId(value: string): void;
|
||||
|
||||
getRawId(): Uint8Array | string;
|
||||
getRawId_asU8(): Uint8Array;
|
||||
@ -1316,17 +1337,21 @@ export class RawPacketForwarderCommand extends jspb.Message {
|
||||
|
||||
export namespace RawPacketForwarderCommand {
|
||||
export type AsObject = {
|
||||
gatewayId: Uint8Array | string,
|
||||
gatewayIdLegacy: Uint8Array | string,
|
||||
gatewayId: string,
|
||||
rawId: Uint8Array | string,
|
||||
payload: Uint8Array | string,
|
||||
}
|
||||
}
|
||||
|
||||
export class ConnState extends jspb.Message {
|
||||
getGatewayId(): Uint8Array | string;
|
||||
getGatewayId_asU8(): Uint8Array;
|
||||
getGatewayId_asB64(): string;
|
||||
setGatewayId(value: Uint8Array | string): void;
|
||||
getGatewayIdLegacy(): Uint8Array | string;
|
||||
getGatewayIdLegacy_asU8(): Uint8Array;
|
||||
getGatewayIdLegacy_asB64(): string;
|
||||
setGatewayIdLegacy(value: Uint8Array | string): void;
|
||||
|
||||
getGatewayId(): string;
|
||||
setGatewayId(value: string): void;
|
||||
|
||||
getState(): ConnState.StateMap[keyof ConnState.StateMap];
|
||||
setState(value: ConnState.StateMap[keyof ConnState.StateMap]): void;
|
||||
@ -1343,7 +1368,8 @@ export class ConnState extends jspb.Message {
|
||||
|
||||
export namespace ConnState {
|
||||
export type AsObject = {
|
||||
gatewayId: Uint8Array | string,
|
||||
gatewayIdLegacy: Uint8Array | string,
|
||||
gatewayId: string,
|
||||
state: ConnState.StateMap[keyof ConnState.StateMap],
|
||||
}
|
||||
|
||||
|
637
api/js/gw/gw_pb.js
vendored
637
api/js/gw/gw_pb.js
vendored
File diff suppressed because it is too large
Load Diff
2
api/js/package.json
vendored
2
api/js/package.json
vendored
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@chirpstack/chirpstack-api",
|
||||
"version": "4.0.0-test.7",
|
||||
"version": "4.0.0-test.11",
|
||||
"description": "Chirpstack JS and TS API",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
|
77
api/proto/gw/gw.proto
vendored
77
api/proto/gw/gw.proto
vendored
@ -183,10 +183,11 @@ message PlainFineTimestamp {
|
||||
|
||||
message GatewayStats {
|
||||
// Gateway ID.
|
||||
bytes gateway_id = 1;
|
||||
// Deprecated: use gateway_id.
|
||||
bytes gateway_id_legacy = 1;
|
||||
|
||||
// Gateway IP.
|
||||
string ip = 9;
|
||||
// Gateway ID.
|
||||
string gateway_id = 17;
|
||||
|
||||
// Gateway time.
|
||||
google.protobuf.Timestamp time = 2;
|
||||
@ -195,7 +196,7 @@ message GatewayStats {
|
||||
common.Location location = 3;
|
||||
|
||||
// Gateway configuration version (this maps to the config_version sent
|
||||
// by LoRa Server to the gateway).
|
||||
// by ChirpStack to the gateway).
|
||||
string config_version = 4;
|
||||
|
||||
// Number of radio packets received.
|
||||
@ -213,10 +214,6 @@ message GatewayStats {
|
||||
// Additional gateway meta-data.
|
||||
map<string, string> meta_data = 10;
|
||||
|
||||
// Stats ID (UUID).
|
||||
// Unique identifier for the gateway stats.
|
||||
bytes stats_id = 11;
|
||||
|
||||
// Tx packets per frequency.
|
||||
map<uint32, uint32> tx_packets_per_frequency = 12;
|
||||
|
||||
@ -528,7 +525,11 @@ message DownlinkTxAckItem {
|
||||
|
||||
message GatewayConfiguration {
|
||||
// Gateway ID.
|
||||
bytes gateway_id = 1;
|
||||
// Deprecated: use gateway_id.
|
||||
bytes gateway_id_legacy = 1;
|
||||
|
||||
// Gateway ID.
|
||||
string gateway_id = 5;
|
||||
|
||||
// Configuration version.
|
||||
string version = 2;
|
||||
@ -544,15 +545,15 @@ message ChannelConfiguration {
|
||||
// Frequency (Hz).
|
||||
uint32 frequency = 1;
|
||||
|
||||
// Channel modulation.
|
||||
common.Modulation modulation = 2;
|
||||
// Modulation (deprecated).
|
||||
common.Modulation modulation_legacy = 2;
|
||||
|
||||
oneof modulation_config {
|
||||
// LoRa modulation config.
|
||||
LoRaModulationConfig lora_modulation_config = 3;
|
||||
LoraModulationConfig lora_modulation_config = 3;
|
||||
|
||||
// FSK modulation config.
|
||||
FSKModulationConfig fsk_modulation_config = 4;
|
||||
FskModulationConfig fsk_modulation_config = 4;
|
||||
}
|
||||
|
||||
// Board index.
|
||||
@ -562,17 +563,25 @@ message ChannelConfiguration {
|
||||
uint32 demodulator = 6;
|
||||
}
|
||||
|
||||
message LoRaModulationConfig {
|
||||
// Bandwidth.
|
||||
uint32 bandwidth = 1;
|
||||
message LoraModulationConfig {
|
||||
// Bandwidth (kHz).
|
||||
// Deprecated: use bandwidth.
|
||||
uint32 bandwidth_legacy = 1;
|
||||
|
||||
// Bandwidth (Hz).
|
||||
uint32 bandwidth = 3;
|
||||
|
||||
// Spreading-factors.
|
||||
repeated uint32 spreading_factors = 2;
|
||||
}
|
||||
|
||||
message FSKModulationConfig {
|
||||
// Bandwidth.
|
||||
uint32 bandwidth = 1;
|
||||
message FskModulationConfig {
|
||||
// Bandwidth (kHz).
|
||||
// Deprecated: use bandwidth.
|
||||
uint32 bandwidth_legacy = 1;
|
||||
|
||||
// Bandwidth (Hz).
|
||||
uint32 bandwidth = 3;
|
||||
|
||||
// Bitrate.
|
||||
uint32 bitrate = 2;
|
||||
@ -580,7 +589,11 @@ message FSKModulationConfig {
|
||||
|
||||
message GatewayCommandExecRequest {
|
||||
// Gateway ID.
|
||||
bytes gateway_id = 1;
|
||||
// Deprecated: use gateway_id.
|
||||
bytes gateway_id_legacy = 1;
|
||||
|
||||
// Gateway ID.
|
||||
string gateway_id = 6;
|
||||
|
||||
// Command to execute.
|
||||
// This command must be pre-configured in the LoRa Gateway Bridge configuration.
|
||||
@ -600,7 +613,11 @@ message GatewayCommandExecRequest {
|
||||
|
||||
message GatewayCommandExecResponse {
|
||||
// Gateway ID.
|
||||
bytes gateway_id = 1;
|
||||
// Deprecated: use gateway_id.
|
||||
bytes gateway_id_legacy = 1;
|
||||
|
||||
// Gateway ID.
|
||||
string gateway_id = 6;
|
||||
|
||||
// Execution request ID (UUID).
|
||||
bytes exec_id = 2;
|
||||
@ -620,7 +637,11 @@ message GatewayCommandExecResponse {
|
||||
// integrated with the ChirpStack Gateway Bridge.
|
||||
message RawPacketForwarderEvent {
|
||||
// Gateway ID.
|
||||
bytes gateway_id = 1;
|
||||
// Deprecated: use gateway_id.
|
||||
bytes gateway_id_legacy = 1;
|
||||
|
||||
// Gateway ID.
|
||||
string gateway_id = 4;
|
||||
|
||||
// Raw ID (UUID).
|
||||
bytes raw_id = 2;
|
||||
@ -634,7 +655,11 @@ message RawPacketForwarderEvent {
|
||||
// integrated with the ChirpStack Gateway Bridge.
|
||||
message RawPacketForwarderCommand {
|
||||
// Gateway ID.
|
||||
bytes gateway_id = 1;
|
||||
// Deprecated: use gateway_id.
|
||||
bytes gateway_id_legacy = 1;
|
||||
|
||||
// Gateway ID.
|
||||
string gateway_id = 4;
|
||||
|
||||
// Raw ID (UUID).
|
||||
bytes raw_id = 2;
|
||||
@ -646,7 +671,11 @@ message RawPacketForwarderCommand {
|
||||
// ConnState contains the connection state of a gateway.
|
||||
message ConnState {
|
||||
// Gateway ID.
|
||||
bytes gateway_id = 1;
|
||||
// Deprecated: use gateway_id.
|
||||
bytes gateway_id_legacy = 1;
|
||||
|
||||
// Gateway ID.
|
||||
string gateway_id = 3;
|
||||
|
||||
enum State {
|
||||
OFFLINE = 0;
|
||||
|
77
api/python/proto/chirpstack-api/gw/gw.proto
vendored
77
api/python/proto/chirpstack-api/gw/gw.proto
vendored
@ -183,10 +183,11 @@ message PlainFineTimestamp {
|
||||
|
||||
message GatewayStats {
|
||||
// Gateway ID.
|
||||
bytes gateway_id = 1;
|
||||
// Deprecated: use gateway_id.
|
||||
bytes gateway_id_legacy = 1;
|
||||
|
||||
// Gateway IP.
|
||||
string ip = 9;
|
||||
// Gateway ID.
|
||||
string gateway_id = 17;
|
||||
|
||||
// Gateway time.
|
||||
google.protobuf.Timestamp time = 2;
|
||||
@ -195,7 +196,7 @@ message GatewayStats {
|
||||
common.Location location = 3;
|
||||
|
||||
// Gateway configuration version (this maps to the config_version sent
|
||||
// by LoRa Server to the gateway).
|
||||
// by ChirpStack to the gateway).
|
||||
string config_version = 4;
|
||||
|
||||
// Number of radio packets received.
|
||||
@ -213,10 +214,6 @@ message GatewayStats {
|
||||
// Additional gateway meta-data.
|
||||
map<string, string> meta_data = 10;
|
||||
|
||||
// Stats ID (UUID).
|
||||
// Unique identifier for the gateway stats.
|
||||
bytes stats_id = 11;
|
||||
|
||||
// Tx packets per frequency.
|
||||
map<uint32, uint32> tx_packets_per_frequency = 12;
|
||||
|
||||
@ -528,7 +525,11 @@ message DownlinkTxAckItem {
|
||||
|
||||
message GatewayConfiguration {
|
||||
// Gateway ID.
|
||||
bytes gateway_id = 1;
|
||||
// Deprecated: use gateway_id.
|
||||
bytes gateway_id_legacy = 1;
|
||||
|
||||
// Gateway ID.
|
||||
string gateway_id = 5;
|
||||
|
||||
// Configuration version.
|
||||
string version = 2;
|
||||
@ -544,15 +545,15 @@ message ChannelConfiguration {
|
||||
// Frequency (Hz).
|
||||
uint32 frequency = 1;
|
||||
|
||||
// Channel modulation.
|
||||
common.Modulation modulation = 2;
|
||||
// Modulation (deprecated).
|
||||
common.Modulation modulation_legacy = 2;
|
||||
|
||||
oneof modulation_config {
|
||||
// LoRa modulation config.
|
||||
LoRaModulationConfig lora_modulation_config = 3;
|
||||
LoraModulationConfig lora_modulation_config = 3;
|
||||
|
||||
// FSK modulation config.
|
||||
FSKModulationConfig fsk_modulation_config = 4;
|
||||
FskModulationConfig fsk_modulation_config = 4;
|
||||
}
|
||||
|
||||
// Board index.
|
||||
@ -562,17 +563,25 @@ message ChannelConfiguration {
|
||||
uint32 demodulator = 6;
|
||||
}
|
||||
|
||||
message LoRaModulationConfig {
|
||||
// Bandwidth.
|
||||
uint32 bandwidth = 1;
|
||||
message LoraModulationConfig {
|
||||
// Bandwidth (kHz).
|
||||
// Deprecated: use bandwidth.
|
||||
uint32 bandwidth_legacy = 1;
|
||||
|
||||
// Bandwidth (Hz).
|
||||
uint32 bandwidth = 3;
|
||||
|
||||
// Spreading-factors.
|
||||
repeated uint32 spreading_factors = 2;
|
||||
}
|
||||
|
||||
message FSKModulationConfig {
|
||||
// Bandwidth.
|
||||
uint32 bandwidth = 1;
|
||||
message FskModulationConfig {
|
||||
// Bandwidth (kHz).
|
||||
// Deprecated: use bandwidth.
|
||||
uint32 bandwidth_legacy = 1;
|
||||
|
||||
// Bandwidth (Hz).
|
||||
uint32 bandwidth = 3;
|
||||
|
||||
// Bitrate.
|
||||
uint32 bitrate = 2;
|
||||
@ -580,7 +589,11 @@ message FSKModulationConfig {
|
||||
|
||||
message GatewayCommandExecRequest {
|
||||
// Gateway ID.
|
||||
bytes gateway_id = 1;
|
||||
// Deprecated: use gateway_id.
|
||||
bytes gateway_id_legacy = 1;
|
||||
|
||||
// Gateway ID.
|
||||
string gateway_id = 6;
|
||||
|
||||
// Command to execute.
|
||||
// This command must be pre-configured in the LoRa Gateway Bridge configuration.
|
||||
@ -600,7 +613,11 @@ message GatewayCommandExecRequest {
|
||||
|
||||
message GatewayCommandExecResponse {
|
||||
// Gateway ID.
|
||||
bytes gateway_id = 1;
|
||||
// Deprecated: use gateway_id.
|
||||
bytes gateway_id_legacy = 1;
|
||||
|
||||
// Gateway ID.
|
||||
string gateway_id = 6;
|
||||
|
||||
// Execution request ID (UUID).
|
||||
bytes exec_id = 2;
|
||||
@ -620,7 +637,11 @@ message GatewayCommandExecResponse {
|
||||
// integrated with the ChirpStack Gateway Bridge.
|
||||
message RawPacketForwarderEvent {
|
||||
// Gateway ID.
|
||||
bytes gateway_id = 1;
|
||||
// Deprecated: use gateway_id.
|
||||
bytes gateway_id_legacy = 1;
|
||||
|
||||
// Gateway ID.
|
||||
string gateway_id = 4;
|
||||
|
||||
// Raw ID (UUID).
|
||||
bytes raw_id = 2;
|
||||
@ -634,7 +655,11 @@ message RawPacketForwarderEvent {
|
||||
// integrated with the ChirpStack Gateway Bridge.
|
||||
message RawPacketForwarderCommand {
|
||||
// Gateway ID.
|
||||
bytes gateway_id = 1;
|
||||
// Deprecated: use gateway_id.
|
||||
bytes gateway_id_legacy = 1;
|
||||
|
||||
// Gateway ID.
|
||||
string gateway_id = 4;
|
||||
|
||||
// Raw ID (UUID).
|
||||
bytes raw_id = 2;
|
||||
@ -646,7 +671,11 @@ message RawPacketForwarderCommand {
|
||||
// ConnState contains the connection state of a gateway.
|
||||
message ConnState {
|
||||
// Gateway ID.
|
||||
bytes gateway_id = 1;
|
||||
// Deprecated: use gateway_id.
|
||||
bytes gateway_id_legacy = 1;
|
||||
|
||||
// Gateway ID.
|
||||
string gateway_id = 3;
|
||||
|
||||
enum State {
|
||||
OFFLINE = 0;
|
||||
|
164
api/python/src/chirpstack_api/gw/gw_pb2.py
vendored
164
api/python/src/chirpstack_api/gw/gw_pb2.py
vendored
File diff suppressed because one or more lines are too long
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.0.0-test.7",
|
||||
version = "4.0.0-test.11",
|
||||
url='https://github.com/brocaar/chirpstack-api',
|
||||
author='Orne Brocaar',
|
||||
author_email='info@brocaar.com',
|
||||
|
2
api/rust/Cargo.lock
generated
vendored
2
api/rust/Cargo.lock
generated
vendored
@ -121,7 +121,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chirpstack_api"
|
||||
version = "4.0.0-test.7"
|
||||
version = "4.0.0-test.11"
|
||||
dependencies = [
|
||||
"hex",
|
||||
"pbjson",
|
||||
|
2
api/rust/Cargo.toml
vendored
2
api/rust/Cargo.toml
vendored
@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "chirpstack_api"
|
||||
description = "ChirpStack Protobuf / gRPC API definitions."
|
||||
version = "4.0.0-test.7"
|
||||
version = "4.0.0-test.11"
|
||||
authors = ["Orne Brocaar <info@brocaar.com>"]
|
||||
license = "MIT"
|
||||
homepage = "https://www.chirpstack.io"
|
||||
|
77
api/rust/proto/chirpstack/gw/gw.proto
vendored
77
api/rust/proto/chirpstack/gw/gw.proto
vendored
@ -183,10 +183,11 @@ message PlainFineTimestamp {
|
||||
|
||||
message GatewayStats {
|
||||
// Gateway ID.
|
||||
bytes gateway_id = 1;
|
||||
// Deprecated: use gateway_id.
|
||||
bytes gateway_id_legacy = 1;
|
||||
|
||||
// Gateway IP.
|
||||
string ip = 9;
|
||||
// Gateway ID.
|
||||
string gateway_id = 17;
|
||||
|
||||
// Gateway time.
|
||||
google.protobuf.Timestamp time = 2;
|
||||
@ -195,7 +196,7 @@ message GatewayStats {
|
||||
common.Location location = 3;
|
||||
|
||||
// Gateway configuration version (this maps to the config_version sent
|
||||
// by LoRa Server to the gateway).
|
||||
// by ChirpStack to the gateway).
|
||||
string config_version = 4;
|
||||
|
||||
// Number of radio packets received.
|
||||
@ -213,10 +214,6 @@ message GatewayStats {
|
||||
// Additional gateway meta-data.
|
||||
map<string, string> meta_data = 10;
|
||||
|
||||
// Stats ID (UUID).
|
||||
// Unique identifier for the gateway stats.
|
||||
bytes stats_id = 11;
|
||||
|
||||
// Tx packets per frequency.
|
||||
map<uint32, uint32> tx_packets_per_frequency = 12;
|
||||
|
||||
@ -528,7 +525,11 @@ message DownlinkTxAckItem {
|
||||
|
||||
message GatewayConfiguration {
|
||||
// Gateway ID.
|
||||
bytes gateway_id = 1;
|
||||
// Deprecated: use gateway_id.
|
||||
bytes gateway_id_legacy = 1;
|
||||
|
||||
// Gateway ID.
|
||||
string gateway_id = 5;
|
||||
|
||||
// Configuration version.
|
||||
string version = 2;
|
||||
@ -544,15 +545,15 @@ message ChannelConfiguration {
|
||||
// Frequency (Hz).
|
||||
uint32 frequency = 1;
|
||||
|
||||
// Channel modulation.
|
||||
common.Modulation modulation = 2;
|
||||
// Modulation (deprecated).
|
||||
common.Modulation modulation_legacy = 2;
|
||||
|
||||
oneof modulation_config {
|
||||
// LoRa modulation config.
|
||||
LoRaModulationConfig lora_modulation_config = 3;
|
||||
LoraModulationConfig lora_modulation_config = 3;
|
||||
|
||||
// FSK modulation config.
|
||||
FSKModulationConfig fsk_modulation_config = 4;
|
||||
FskModulationConfig fsk_modulation_config = 4;
|
||||
}
|
||||
|
||||
// Board index.
|
||||
@ -562,17 +563,25 @@ message ChannelConfiguration {
|
||||
uint32 demodulator = 6;
|
||||
}
|
||||
|
||||
message LoRaModulationConfig {
|
||||
// Bandwidth.
|
||||
uint32 bandwidth = 1;
|
||||
message LoraModulationConfig {
|
||||
// Bandwidth (kHz).
|
||||
// Deprecated: use bandwidth.
|
||||
uint32 bandwidth_legacy = 1;
|
||||
|
||||
// Bandwidth (Hz).
|
||||
uint32 bandwidth = 3;
|
||||
|
||||
// Spreading-factors.
|
||||
repeated uint32 spreading_factors = 2;
|
||||
}
|
||||
|
||||
message FSKModulationConfig {
|
||||
// Bandwidth.
|
||||
uint32 bandwidth = 1;
|
||||
message FskModulationConfig {
|
||||
// Bandwidth (kHz).
|
||||
// Deprecated: use bandwidth.
|
||||
uint32 bandwidth_legacy = 1;
|
||||
|
||||
// Bandwidth (Hz).
|
||||
uint32 bandwidth = 3;
|
||||
|
||||
// Bitrate.
|
||||
uint32 bitrate = 2;
|
||||
@ -580,7 +589,11 @@ message FSKModulationConfig {
|
||||
|
||||
message GatewayCommandExecRequest {
|
||||
// Gateway ID.
|
||||
bytes gateway_id = 1;
|
||||
// Deprecated: use gateway_id.
|
||||
bytes gateway_id_legacy = 1;
|
||||
|
||||
// Gateway ID.
|
||||
string gateway_id = 6;
|
||||
|
||||
// Command to execute.
|
||||
// This command must be pre-configured in the LoRa Gateway Bridge configuration.
|
||||
@ -600,7 +613,11 @@ message GatewayCommandExecRequest {
|
||||
|
||||
message GatewayCommandExecResponse {
|
||||
// Gateway ID.
|
||||
bytes gateway_id = 1;
|
||||
// Deprecated: use gateway_id.
|
||||
bytes gateway_id_legacy = 1;
|
||||
|
||||
// Gateway ID.
|
||||
string gateway_id = 6;
|
||||
|
||||
// Execution request ID (UUID).
|
||||
bytes exec_id = 2;
|
||||
@ -620,7 +637,11 @@ message GatewayCommandExecResponse {
|
||||
// integrated with the ChirpStack Gateway Bridge.
|
||||
message RawPacketForwarderEvent {
|
||||
// Gateway ID.
|
||||
bytes gateway_id = 1;
|
||||
// Deprecated: use gateway_id.
|
||||
bytes gateway_id_legacy = 1;
|
||||
|
||||
// Gateway ID.
|
||||
string gateway_id = 4;
|
||||
|
||||
// Raw ID (UUID).
|
||||
bytes raw_id = 2;
|
||||
@ -634,7 +655,11 @@ message RawPacketForwarderEvent {
|
||||
// integrated with the ChirpStack Gateway Bridge.
|
||||
message RawPacketForwarderCommand {
|
||||
// Gateway ID.
|
||||
bytes gateway_id = 1;
|
||||
// Deprecated: use gateway_id.
|
||||
bytes gateway_id_legacy = 1;
|
||||
|
||||
// Gateway ID.
|
||||
string gateway_id = 4;
|
||||
|
||||
// Raw ID (UUID).
|
||||
bytes raw_id = 2;
|
||||
@ -646,7 +671,11 @@ message RawPacketForwarderCommand {
|
||||
// ConnState contains the connection state of a gateway.
|
||||
message ConnState {
|
||||
// Gateway ID.
|
||||
bytes gateway_id = 1;
|
||||
// Deprecated: use gateway_id.
|
||||
bytes gateway_id_legacy = 1;
|
||||
|
||||
// Gateway ID.
|
||||
string gateway_id = 3;
|
||||
|
||||
enum State {
|
||||
OFFLINE = 0;
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "backend"
|
||||
version = "4.0.0-test.7"
|
||||
version = "4.0.0-test.11"
|
||||
authors = ["Orne Brocaar <info@brocaar.com>"]
|
||||
edition = "2018"
|
||||
publish = false
|
||||
|
@ -3,7 +3,7 @@ name = "chirpstack"
|
||||
description = "ChirpStack is an open-source LoRaWAN(TM) Network Server"
|
||||
repository = "https://github.com/chirpstack/chirpstack"
|
||||
homepage="https://www.chirpstack.io/"
|
||||
version = "4.0.0-test.7"
|
||||
version = "4.0.0-test.11"
|
||||
authors = ["Orne Brocaar <info@brocaar.com>"]
|
||||
edition = "2021"
|
||||
publish = false
|
||||
@ -23,10 +23,10 @@ handlebars = "4.1"
|
||||
|
||||
# Database
|
||||
validator = "0.13"
|
||||
diesel = { version = "1.4", features = [ "chrono", "postgres", "r2d2", "uuidv07", "serde_json", "numeric" ] }
|
||||
diesel_migrations = { version = "1.4" }
|
||||
diesel = { version = "2.0.0-rc.0", features = [ "chrono", "postgres", "r2d2", "uuid", "serde_json", "numeric" ] }
|
||||
diesel_migrations = { version = "2.0.0-rc.0" }
|
||||
r2d2 = "0.8"
|
||||
bigdecimal = "0.1.2"
|
||||
bigdecimal = "0.3"
|
||||
redis = { version = "0.21", features = ["r2d2", "cluster"] }
|
||||
pq-sys = { version = "0.4.6", features = ["pkg-config"] }
|
||||
|
||||
@ -54,7 +54,7 @@ gcp_auth = "0.7.2"
|
||||
lapin = "2.1.1"
|
||||
tokio-executor-trait = "2.1.0"
|
||||
tokio-reactor-trait = "1.1.0"
|
||||
rdkafka = "0.28.0"
|
||||
rdkafka = { version = "0.28.0", features = ["cmake-build"]}
|
||||
|
||||
# gRPC and Protobuf
|
||||
tonic = "0.7"
|
||||
@ -98,7 +98,7 @@ rquickjs = { version = "0.1.6", features = ["bindgen", "loader", "array-buffer",
|
||||
|
||||
# Misc
|
||||
lazy_static = "1.4"
|
||||
uuid = { version = "0.8", features = [ "v4", "serde" ] }
|
||||
uuid = { version = "1.1", features = [ "v4", "serde" ] }
|
||||
chrono = "0.4"
|
||||
async-trait = "0.1"
|
||||
aes = "0.7"
|
||||
|
@ -1,29 +1,107 @@
|
||||
.PHONY: debug release release-deb test test-server dbshell dist
|
||||
.PHONY: dist
|
||||
|
||||
TARGET_ARCH := $(shell rustc --print cfg |grep target_arch |sed 's/target_arch="\(.*\)"/\1/')
|
||||
PKG_VERSION := $(shell cargo metadata --no-deps --format-version 1 | jq -r '.packages[0].version')
|
||||
|
||||
debug:
|
||||
debug-amd64:
|
||||
apt update && apt install -y libpq-dev:amd64
|
||||
cargo build
|
||||
|
||||
release:
|
||||
debug-armv7hf:
|
||||
# We can not install this by default, as only one libpq-dev version can be
|
||||
# installed at a time.
|
||||
apt update && apt install -y libpq-dev:armhf
|
||||
BINDGEN_EXTRA_CLANG_ARGS="--sysroot=/usr/arm-linux-gnueabihf" \
|
||||
PKG_CONFIG_SYSROOT_DIR="/usr/arm-linux-gnueabihf" \
|
||||
cargo build --target armv7-unknown-linux-gnueabihf
|
||||
|
||||
debug-arm64:
|
||||
apt update && apt install -y libpq-dev:arm64
|
||||
BINDGEN_EXTRA_CLANG_ARGS="--sysroot=/usr/aarch64-linux-gnu" \
|
||||
PKG_CONFIG_SYSROOT_DIR="/usr/aarch64-linux-gnu" \
|
||||
cargo build --target aarch64-unknown-linux-gnu
|
||||
|
||||
release-amd64:
|
||||
apt update && apt install -y libpq-dev:amd64
|
||||
cargo build --release
|
||||
|
||||
dist: release-deb release-rpm release-targz
|
||||
release-armv7hf:
|
||||
apt update && apt install -y libpq-dev:armhf
|
||||
BINDGEN_EXTRA_CLANG_ARGS="--sysroot=/usr/arm-linux-gnueabihf" \
|
||||
PKG_CONFIG_SYSROOT_DIR="/usr/arm-linux-gnueabihf" \
|
||||
cargo build --target armv7-unknown-linux-gnueabihf --release
|
||||
|
||||
release-deb:
|
||||
release-arm64:
|
||||
apt update && apt install -y libpq-dev:arm64
|
||||
BINDGEN_EXTRA_CLANG_ARGS="--sysroot=/usr/aarch64-linux-gnu" \
|
||||
PKG_CONFIG_SYSROOT_DIR="/usr/aarch64-linux-gnu" \
|
||||
cargo build --target aarch64-unknown-linux-gnu --release
|
||||
|
||||
dist: release-deb-amd64 \
|
||||
release-deb-armv7hf \
|
||||
release-deb-arm64 \
|
||||
release-rpm-amd64 \
|
||||
release-rpm-armv7hf \
|
||||
release-rpm-arm64 \
|
||||
release-targz-amd64 \
|
||||
release-targz-armv7hf \
|
||||
release-targz-arm64 \
|
||||
|
||||
release-deb-amd64:
|
||||
apt update && apt install -y libpq-dev:amd64
|
||||
mkdir -p /chirpstack/dist
|
||||
cargo deb
|
||||
cp /target/debian/*.deb /chirpstack/dist
|
||||
cp ../target/debian/*.deb /chirpstack/dist
|
||||
|
||||
release-rpm:
|
||||
release-deb-armv7hf:
|
||||
apt update && apt install -y libpq-dev:armhf
|
||||
mkdir -p /chirpstack/dist
|
||||
BINDGEN_EXTRA_CLANG_ARGS="--sysroot=/usr/arm-linux-gnueabihf" \
|
||||
PKG_CONFIG_SYSROOT_DIR="/usr/arm-linux-gnueabihf" \
|
||||
cargo deb --target armv7-unknown-linux-gnueabihf
|
||||
cp ../target/armv7-unknown-linux-gnueabihf/debian/*.deb /chirpstack/dist
|
||||
|
||||
release-deb-arm64:
|
||||
apt update && apt install -y libpq-dev:arm64
|
||||
mkdir -p /chirpstack/dist
|
||||
BINDGEN_EXTRA_CLANG_ARGS="--sysroot=/usr/aarch64-linux-gnu" \
|
||||
PKG_CONFIG_SYSROOT_DIR="/usr/aarch64-linux-gnu" \
|
||||
cargo deb --target aarch64-unknown-linux-gnu
|
||||
cp ../target/aarch64-unknown-linux-gnu/debian/*.deb /chirpstack/dist
|
||||
|
||||
release-rpm-amd64:
|
||||
apt update && apt install -y libpq-dev:amd64
|
||||
mkdir -p /chirpstack/dist
|
||||
cargo rpm build
|
||||
find /target/release/rpmbuild/RPMS -type f -exec cp {} /chirpstack/dist \;
|
||||
find ../target/release/rpmbuild/RPMS -type f -exec cp {} /chirpstack/dist \;
|
||||
|
||||
release-targz:
|
||||
release-rpm-armv7hf:
|
||||
apt update && apt install -y libpq-dev:armhf
|
||||
mkdir -p /chirpstack/dist
|
||||
tar -czvf /chirpstack/dist/chirpstack_$(PKG_VERSION)_$(TARGET_ARCH).tar.gz -C /target/release chirpstack
|
||||
BINDGEN_EXTRA_CLANG_ARGS="--sysroot=/usr/arm-linux-gnueabihf" \
|
||||
PKG_CONFIG_SYSROOT_DIR="/usr/arm-linux-gnueabihf" \
|
||||
cargo rpm build --target armv7-unknown-linux-gnueabihf
|
||||
find ../target/armv7-unknown-linux-gnueabihf/release/rpmbuild/RPMS -type f -exec cp {} /chirpstack/dist \;
|
||||
|
||||
release-rpm-arm64:
|
||||
apt update && apt install -y libpq-dev:arm64
|
||||
mkdir -p /chirpstack/dist
|
||||
BINDGEN_EXTRA_CLANG_ARGS="--sysroot=/usr/aarch64-linux-gnu" \
|
||||
PKG_CONFIG_SYSROOT_DIR="/usr/aarch64-linux-gnu" \
|
||||
cargo rpm build --target aarch64-unknown-linux-gnu
|
||||
find ../target/aarch64-unknown-linux-gnu/release/rpmbuild/RPMS -type f -exec cp {} /chirpstack/dist \;
|
||||
|
||||
release-targz-amd64: release-amd64
|
||||
mkdir -p /chirpstack/dist
|
||||
tar -czvf /chirpstack/dist/chirpstack_$(PKG_VERSION)_amd64.tar.gz -C ../target/release chirpstack
|
||||
|
||||
release-targz-armv7hf: release-armv7hf
|
||||
mkdir -p /chirpstack/dist
|
||||
tar -czvf /chirpstack/dist/chirpstack_$(PKG_VERSION)_armv7hf.tar.gz -C ../target/armv7-unknown-linux-gnueabihf/release chirpstack
|
||||
|
||||
release-targz-arm64: release-arm64
|
||||
mkdir -p /chirpstack/dist
|
||||
tar -czvf /chirpstack/dist/chirpstack_$(PKG_VERSION)_arm64.tar.gz -C ../target/aarch64-unknown-linux-gnu/release chirpstack
|
||||
|
||||
test:
|
||||
cargo fmt --check
|
||||
@ -33,8 +111,8 @@ test:
|
||||
test-lrwn:
|
||||
cd ../lrwn && make test
|
||||
|
||||
test-server: debug configuration/certs/ca.pem
|
||||
/target/debug/chirpstack -c ./configuration
|
||||
test-server: debug-amd64 configuration/certs/ca.pem
|
||||
../target/debug/chirpstack -c ./configuration
|
||||
|
||||
dbshell:
|
||||
psql -h postgres -U chirpstack chirpstack
|
||||
|
@ -96,12 +96,12 @@ impl Validator for ValidateActiveUser {
|
||||
let id = *id;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let count = user::dsl::user
|
||||
.select(dsl::count_star())
|
||||
.find(id)
|
||||
.filter(user::dsl::is_active.eq(true))
|
||||
.first(&c)?;
|
||||
.first(&mut c)?;
|
||||
Ok(count)
|
||||
}
|
||||
})
|
||||
@ -128,7 +128,7 @@ impl Validator for ValidateIsAdmin {
|
||||
let id = *id;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let count = user::dsl::user
|
||||
.select(dsl::count_star())
|
||||
.find(id)
|
||||
@ -137,7 +137,7 @@ impl Validator for ValidateIsAdmin {
|
||||
.eq(true)
|
||||
.and(user::dsl::is_admin.eq(true)),
|
||||
)
|
||||
.first(&c)?;
|
||||
.first(&mut c)?;
|
||||
Ok(count)
|
||||
}
|
||||
})
|
||||
@ -163,7 +163,7 @@ impl Validator for ValidateUsersAccess {
|
||||
let flag = self.flag;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = user::dsl::user
|
||||
.select(dsl::count_star())
|
||||
.find(&id)
|
||||
@ -180,7 +180,7 @@ impl Validator for ValidateUsersAccess {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -190,13 +190,13 @@ impl Validator for ValidateUsersAccess {
|
||||
task::spawn_blocking({
|
||||
let id = *id;
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
// admin api key
|
||||
let count = api_key::dsl::api_key
|
||||
.select(dsl::count_star())
|
||||
.find(&id)
|
||||
.filter(api_key::dsl::is_admin.eq(true))
|
||||
.first(&c)?;
|
||||
.first(&mut c)?;
|
||||
Ok(count)
|
||||
}
|
||||
})
|
||||
@ -224,7 +224,7 @@ impl Validator for ValidateUserAccess {
|
||||
let flag = self.flag;
|
||||
|
||||
move || {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = user::dsl::user
|
||||
.select(dsl::count_star())
|
||||
.find(&id)
|
||||
@ -246,7 +246,7 @@ impl Validator for ValidateUserAccess {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -256,13 +256,13 @@ impl Validator for ValidateUserAccess {
|
||||
task::spawn_blocking({
|
||||
let id = *id;
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
// admin api key
|
||||
let count = api_key::dsl::api_key
|
||||
.select(dsl::count_star())
|
||||
.find(&id)
|
||||
.filter(api_key::dsl::is_admin.eq(true))
|
||||
.first(&c)?;
|
||||
.first(&mut c)?;
|
||||
Ok(count)
|
||||
}
|
||||
})
|
||||
@ -296,7 +296,7 @@ impl Validator for ValidateApiKeysAccess {
|
||||
let flag = self.flag;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
|
||||
let mut q = user::dsl::user
|
||||
.select(dsl::count_star())
|
||||
@ -328,7 +328,7 @@ impl Validator for ValidateApiKeysAccess {
|
||||
}
|
||||
};
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -359,7 +359,7 @@ impl Validator for ValidateApiKeyAccess {
|
||||
let flag = self.flag;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
|
||||
let mut q = user::dsl::user
|
||||
.select(dsl::count_star())
|
||||
@ -384,7 +384,7 @@ impl Validator for ValidateApiKeyAccess {
|
||||
}
|
||||
};
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -413,7 +413,7 @@ impl Validator for ValidateTenantsAccess {
|
||||
let flag = self.flag;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
|
||||
let mut q = user::dsl::user
|
||||
.select(dsl::count_star())
|
||||
@ -433,7 +433,7 @@ impl Validator for ValidateTenantsAccess {
|
||||
}
|
||||
};
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -443,13 +443,13 @@ impl Validator for ValidateTenantsAccess {
|
||||
task::spawn_blocking({
|
||||
let id = *id;
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
// admin api key
|
||||
let count = api_key::dsl::api_key
|
||||
.select(dsl::count_star())
|
||||
.find(&id)
|
||||
.filter(api_key::dsl::is_admin.eq(true))
|
||||
.first(&c)?;
|
||||
.first(&mut c)?;
|
||||
Ok(count)
|
||||
}
|
||||
})
|
||||
@ -477,7 +477,7 @@ impl Validator for ValidateTenantAccess {
|
||||
let tenant_id = self.tenant_id;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
|
||||
let mut q = user::dsl::user
|
||||
.select(dsl::count_star())
|
||||
@ -501,7 +501,7 @@ impl Validator for ValidateTenantAccess {
|
||||
}
|
||||
};
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -514,7 +514,7 @@ impl Validator for ValidateTenantAccess {
|
||||
let tenant_id = self.tenant_id;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
|
||||
let mut q = api_key::dsl::api_key
|
||||
.select(dsl::count_star())
|
||||
@ -540,7 +540,7 @@ impl Validator for ValidateTenantAccess {
|
||||
}
|
||||
};
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -567,7 +567,7 @@ impl Validator for ValidateTenantUsersAccess {
|
||||
let tenant_id = self.tenant_id;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = user::dsl::user
|
||||
.select(dsl::count_star())
|
||||
.left_join(tenant_user::table.left_join(tenant::table))
|
||||
@ -598,7 +598,7 @@ impl Validator for ValidateTenantUsersAccess {
|
||||
}
|
||||
};
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -611,7 +611,7 @@ impl Validator for ValidateTenantUsersAccess {
|
||||
let tenant_id = self.tenant_id;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = api_key::dsl::api_key
|
||||
.select(dsl::count_star())
|
||||
.find(&id)
|
||||
@ -632,7 +632,7 @@ impl Validator for ValidateTenantUsersAccess {
|
||||
}
|
||||
};
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -665,7 +665,7 @@ impl Validator for ValidateTenantUserAccess {
|
||||
let user_id = self.user_id;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = user::dsl::user
|
||||
.select(dsl::count_star())
|
||||
.left_join(tenant_user::table.left_join(tenant::table))
|
||||
@ -702,7 +702,7 @@ impl Validator for ValidateTenantUserAccess {
|
||||
}
|
||||
};
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -715,7 +715,7 @@ impl Validator for ValidateTenantUserAccess {
|
||||
let tenant_id = self.tenant_id;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = api_key::dsl::api_key
|
||||
.select(dsl::count_star())
|
||||
.find(&id)
|
||||
@ -736,7 +736,7 @@ impl Validator for ValidateTenantUserAccess {
|
||||
}
|
||||
};
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -763,7 +763,7 @@ impl Validator for ValidateApplicationsAccess {
|
||||
let tenant_id = self.tenant_id;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = user::dsl::user
|
||||
.select(dsl::count_star())
|
||||
.left_join(tenant_user::table.left_join(tenant::table))
|
||||
@ -800,7 +800,7 @@ impl Validator for ValidateApplicationsAccess {
|
||||
}
|
||||
};
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -813,7 +813,7 @@ impl Validator for ValidateApplicationsAccess {
|
||||
let tenant_id = self.tenant_id;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = api_key::dsl::api_key
|
||||
.select(dsl::count_star())
|
||||
.find(&id)
|
||||
@ -843,7 +843,7 @@ impl Validator for ValidateApplicationsAccess {
|
||||
}
|
||||
};
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -873,7 +873,7 @@ impl Validator for ValidateApplicationAccess {
|
||||
let application_id = self.application_id;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = user::dsl::user
|
||||
.select(dsl::count_star())
|
||||
.left_join(
|
||||
@ -915,7 +915,7 @@ impl Validator for ValidateApplicationAccess {
|
||||
}
|
||||
};
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -928,7 +928,7 @@ impl Validator for ValidateApplicationAccess {
|
||||
let application_id = self.application_id;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = api_key::dsl::api_key
|
||||
.select(dsl::count_star())
|
||||
.left_join(
|
||||
@ -953,7 +953,7 @@ impl Validator for ValidateApplicationAccess {
|
||||
}
|
||||
};
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -978,7 +978,7 @@ impl Validator for ValidateDeviceProfileTemplatesAccess {
|
||||
let flag = self.flag;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = user::dsl::user
|
||||
.select(dsl::count_star())
|
||||
.filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true)))
|
||||
@ -996,7 +996,7 @@ impl Validator for ValidateDeviceProfileTemplatesAccess {
|
||||
}
|
||||
};
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -1008,7 +1008,7 @@ impl Validator for ValidateDeviceProfileTemplatesAccess {
|
||||
let flag = self.flag;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = api_key::dsl::api_key
|
||||
.select(dsl::count_star())
|
||||
.find(&id)
|
||||
@ -1026,7 +1026,7 @@ impl Validator for ValidateDeviceProfileTemplatesAccess {
|
||||
}
|
||||
};
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -1056,7 +1056,7 @@ impl Validator for ValidateDeviceProfileTemplateAccess {
|
||||
let flag = self.flag;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = user::dsl::user
|
||||
.select(dsl::count_star())
|
||||
.filter(user::dsl::id.eq(&id).and(user::dsl::is_active.eq(true)))
|
||||
@ -1074,7 +1074,7 @@ impl Validator for ValidateDeviceProfileTemplateAccess {
|
||||
}
|
||||
};
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -1086,7 +1086,7 @@ impl Validator for ValidateDeviceProfileTemplateAccess {
|
||||
let flag = self.flag;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = api_key::dsl::api_key
|
||||
.select(dsl::count_star())
|
||||
.find(&id)
|
||||
@ -1104,7 +1104,7 @@ impl Validator for ValidateDeviceProfileTemplateAccess {
|
||||
}
|
||||
};
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -1131,7 +1131,7 @@ impl Validator for ValidateDeviceProfilesAccess {
|
||||
let tenant_id = self.tenant_id;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = user::dsl::user
|
||||
.select(dsl::count_star())
|
||||
.left_join(tenant_user::table)
|
||||
@ -1168,7 +1168,7 @@ impl Validator for ValidateDeviceProfilesAccess {
|
||||
}
|
||||
};
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -1181,7 +1181,7 @@ impl Validator for ValidateDeviceProfilesAccess {
|
||||
let tenant_id = self.tenant_id;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = api_key::dsl::api_key
|
||||
.select(dsl::count_star())
|
||||
.find(&id)
|
||||
@ -1202,7 +1202,7 @@ impl Validator for ValidateDeviceProfilesAccess {
|
||||
}
|
||||
};
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -1232,7 +1232,7 @@ impl Validator for ValidateDeviceProfileAccess {
|
||||
let device_profile_id = self.device_profile_id;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = user::dsl::user
|
||||
.select(dsl::count_star())
|
||||
.left_join(
|
||||
@ -1276,7 +1276,7 @@ impl Validator for ValidateDeviceProfileAccess {
|
||||
}
|
||||
};
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -1289,7 +1289,7 @@ impl Validator for ValidateDeviceProfileAccess {
|
||||
let device_profile_id = self.device_profile_id;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q =
|
||||
api_key::dsl::api_key
|
||||
.select(dsl::count_star())
|
||||
@ -1314,7 +1314,7 @@ impl Validator for ValidateDeviceProfileAccess {
|
||||
}
|
||||
};
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -1344,7 +1344,7 @@ impl Validator for ValidateDevicesAccess {
|
||||
let application_id = self.application_id;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = user::dsl::user
|
||||
.select(dsl::count_star())
|
||||
.left_join(
|
||||
@ -1386,7 +1386,7 @@ impl Validator for ValidateDevicesAccess {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -1399,7 +1399,7 @@ impl Validator for ValidateDevicesAccess {
|
||||
let application_id = self.application_id;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = api_key::dsl::api_key
|
||||
.select(dsl::count_star())
|
||||
.left_join(
|
||||
@ -1424,7 +1424,7 @@ impl Validator for ValidateDevicesAccess {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -1451,7 +1451,7 @@ impl Validator for ValidateDeviceAccess {
|
||||
let dev_eui = self.dev_eui;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = user::dsl::user
|
||||
.select(dsl::count_star())
|
||||
.left_join(
|
||||
@ -1496,7 +1496,7 @@ impl Validator for ValidateDeviceAccess {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -1509,7 +1509,7 @@ impl Validator for ValidateDeviceAccess {
|
||||
let dev_eui = self.dev_eui;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = api_key::dsl::api_key
|
||||
.select(dsl::count_star())
|
||||
.left_join(
|
||||
@ -1537,7 +1537,7 @@ impl Validator for ValidateDeviceAccess {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -1564,7 +1564,7 @@ impl Validator for ValidateDeviceQueueAccess {
|
||||
let dev_eui = self.dev_eui;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = user::dsl::user
|
||||
.select(dsl::count_star())
|
||||
.left_join(
|
||||
@ -1594,7 +1594,7 @@ impl Validator for ValidateDeviceQueueAccess {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -1607,7 +1607,7 @@ impl Validator for ValidateDeviceQueueAccess {
|
||||
let dev_eui = self.dev_eui;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = api_key::dsl::api_key
|
||||
.select(dsl::count_star())
|
||||
.left_join(
|
||||
@ -1635,7 +1635,7 @@ impl Validator for ValidateDeviceQueueAccess {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -1662,7 +1662,7 @@ impl Validator for ValidateGatewaysAccess {
|
||||
let tenant_id = self.tenant_id;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = user::dsl::user
|
||||
.select(dsl::count_star())
|
||||
.left_join(tenant_user::table.left_join(tenant::table))
|
||||
@ -1699,7 +1699,7 @@ impl Validator for ValidateGatewaysAccess {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -1712,7 +1712,7 @@ impl Validator for ValidateGatewaysAccess {
|
||||
let tenant_id = self.tenant_id;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = api_key::dsl::api_key
|
||||
.select(dsl::count_star())
|
||||
.find(&id)
|
||||
@ -1733,7 +1733,7 @@ impl Validator for ValidateGatewaysAccess {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -1760,7 +1760,7 @@ impl Validator for ValidateGatewayAccess {
|
||||
let gateway_id = self.gateway_id;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = user::dsl::user
|
||||
.select(dsl::count_star())
|
||||
.left_join(
|
||||
@ -1799,7 +1799,7 @@ impl Validator for ValidateGatewayAccess {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -1812,7 +1812,7 @@ impl Validator for ValidateGatewayAccess {
|
||||
let gateway_id = self.gateway_id;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = api_key::dsl::api_key
|
||||
.select(dsl::count_star())
|
||||
.left_join(
|
||||
@ -1837,7 +1837,7 @@ impl Validator for ValidateGatewayAccess {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -1867,7 +1867,7 @@ impl Validator for ValidateMulticastGroupsAccess {
|
||||
let application_id = self.application_id;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = user::dsl::user
|
||||
.select(dsl::count_star())
|
||||
.left_join(
|
||||
@ -1909,7 +1909,7 @@ impl Validator for ValidateMulticastGroupsAccess {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -1922,7 +1922,7 @@ impl Validator for ValidateMulticastGroupsAccess {
|
||||
let application_id = self.application_id;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = api_key::dsl::api_key
|
||||
.select(dsl::count_star())
|
||||
.left_join(
|
||||
@ -1947,7 +1947,7 @@ impl Validator for ValidateMulticastGroupsAccess {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -1977,7 +1977,7 @@ impl Validator for ValidateMulticastGroupAccess {
|
||||
let multicast_group_id = self.multicast_group_id;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = user::dsl::user
|
||||
.select(dsl::count_star())
|
||||
.left_join(
|
||||
@ -2023,7 +2023,7 @@ impl Validator for ValidateMulticastGroupAccess {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -2036,7 +2036,7 @@ impl Validator for ValidateMulticastGroupAccess {
|
||||
let multicast_group_id = self.multicast_group_id;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = api_key::dsl::api_key
|
||||
.select(dsl::count_star())
|
||||
.left_join(
|
||||
@ -2065,7 +2065,7 @@ impl Validator for ValidateMulticastGroupAccess {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -2095,7 +2095,7 @@ impl Validator for ValidateMulticastGroupQueueAccess {
|
||||
let multicast_group_id = self.multicast_group_id;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = user::dsl::user
|
||||
.select(dsl::count_star())
|
||||
.left_join(
|
||||
@ -2141,7 +2141,7 @@ impl Validator for ValidateMulticastGroupQueueAccess {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -2154,7 +2154,7 @@ impl Validator for ValidateMulticastGroupQueueAccess {
|
||||
let multicast_group_id = self.multicast_group_id;
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = api_key::dsl::api_key
|
||||
.select(dsl::count_star())
|
||||
.left_join(
|
||||
@ -2183,7 +2183,7 @@ impl Validator for ValidateMulticastGroupQueueAccess {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
|
@ -56,9 +56,9 @@ async fn _health_handler() -> Result<()> {
|
||||
return Err(anyhow!("Redis connection error"));
|
||||
}
|
||||
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
diesel::sql_query("select 1")
|
||||
.execute(&c)
|
||||
.execute(&mut c)
|
||||
.context("PostgreSQL connection error")?;
|
||||
|
||||
Ok(())
|
||||
|
@ -1,11 +1,11 @@
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use std::io::Write;
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use chrono::{DateTime, Utc};
|
||||
use diesel::backend::Backend;
|
||||
use diesel::backend::{self, Backend};
|
||||
use diesel::pg::Pg;
|
||||
use diesel::sql_types::Text;
|
||||
use diesel::{deserialize, serialize};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -16,7 +16,7 @@ mod js;
|
||||
|
||||
#[derive(Deserialize, Serialize, Copy, Clone, Debug, Eq, PartialEq, AsExpression, FromSqlRow)]
|
||||
#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
|
||||
#[sql_type = "diesel::sql_types::Text"]
|
||||
#[diesel(sql_type = diesel::sql_types::Text)]
|
||||
pub enum Codec {
|
||||
NONE,
|
||||
CAYENNE_LPP,
|
||||
@ -29,24 +29,23 @@ impl fmt::Display for Codec {
|
||||
}
|
||||
}
|
||||
|
||||
impl<ST, DB> deserialize::FromSql<ST, DB> for Codec
|
||||
impl<DB> deserialize::FromSql<Text, DB> for Codec
|
||||
where
|
||||
DB: Backend,
|
||||
*const str: deserialize::FromSql<ST, DB>,
|
||||
*const str: deserialize::FromSql<Text, DB>,
|
||||
{
|
||||
fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
|
||||
let string = String::from_sql(bytes)?;
|
||||
fn from_sql(value: backend::RawValue<DB>) -> deserialize::Result<Self> {
|
||||
let string = String::from_sql(value)?;
|
||||
Ok(Codec::from_str(&string)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB> serialize::ToSql<Text, DB> for Codec
|
||||
impl serialize::ToSql<Text, Pg> for Codec
|
||||
where
|
||||
DB: Backend,
|
||||
str: serialize::ToSql<Text, DB>,
|
||||
str: serialize::ToSql<Text, Pg>,
|
||||
{
|
||||
fn to_sql<W: Write>(&self, out: &mut serialize::Output<W, DB>) -> serialize::Result {
|
||||
self.to_string().as_str().to_sql(out)
|
||||
fn to_sql<'b>(&self, out: &mut serialize::Output<'b, '_, Pg>) -> serialize::Result {
|
||||
<str as serialize::ToSql<Text, Pg>>::to_sql(&self.to_string(), &mut out.reborrow())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,13 +13,11 @@ use prost::Message;
|
||||
use serde::Serialize;
|
||||
use tracing::{error, info, trace};
|
||||
|
||||
use super::GatewayBackend;
|
||||
use crate::config::GatewayBackendMqtt;
|
||||
use crate::monitoring::prometheus;
|
||||
use crate::{downlink, uplink};
|
||||
use lrwn::region::CommonName;
|
||||
use lrwn::EUI64;
|
||||
|
||||
use super::GatewayBackend;
|
||||
|
||||
#[derive(Clone, Hash, PartialEq, Eq, Encode)]
|
||||
struct EventLabels {
|
||||
@ -216,11 +214,10 @@ impl GatewayBackend for MqttBackend<'_> {
|
||||
command: "config".to_string(),
|
||||
})
|
||||
.inc();
|
||||
let gateway_id = EUI64::from_slice(&gw_conf.gateway_id)?;
|
||||
let topic = self.get_command_topic(&gateway_id.to_string(), "config")?;
|
||||
let topic = self.get_command_topic(&gw_conf.gateway_id, "config")?;
|
||||
let b = gw_conf.encode_to_vec();
|
||||
|
||||
info!(gateway_id = %gateway_id, topic = %topic, "Sending gateway configuration");
|
||||
info!(gateway_id = %gw_conf.gateway_id, topic = %topic, "Sending gateway configuration");
|
||||
let msg = mqtt::Message::new(topic, b, self.qos as i32);
|
||||
self.client.publish(msg).await?;
|
||||
trace!("Message sent");
|
||||
|
@ -7,7 +7,7 @@ use chrono::{DateTime, Utc};
|
||||
use diesel::pg::PgConnection;
|
||||
use diesel::prelude::*;
|
||||
use diesel::r2d2::{ConnectionManager, Pool, PooledConnection};
|
||||
use diesel_migrations::embed_migrations;
|
||||
use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness};
|
||||
use tokio::task;
|
||||
use tracing::info;
|
||||
use uuid::Uuid;
|
||||
@ -22,13 +22,14 @@ use schema::{
|
||||
|
||||
mod schema;
|
||||
|
||||
embed_migrations!("./src/integration/postgresql/migrations");
|
||||
pub const MIGRATIONS: EmbeddedMigrations =
|
||||
embed_migrations!("./src/integration/postgresql/migrations");
|
||||
|
||||
type PgPool = Pool<ConnectionManager<PgConnection>>;
|
||||
type PgPoolConnection = PooledConnection<ConnectionManager<PgConnection>>;
|
||||
|
||||
#[derive(Insertable)]
|
||||
#[table_name = "event_up"]
|
||||
#[diesel(table_name = event_up)]
|
||||
struct EventUp {
|
||||
pub deduplication_id: Uuid,
|
||||
pub time: DateTime<Utc>,
|
||||
@ -54,7 +55,7 @@ struct EventUp {
|
||||
}
|
||||
|
||||
#[derive(Insertable)]
|
||||
#[table_name = "event_join"]
|
||||
#[diesel(table_name = event_join)]
|
||||
struct EventJoin {
|
||||
pub deduplication_id: Uuid,
|
||||
pub time: DateTime<Utc>,
|
||||
@ -71,7 +72,7 @@ struct EventJoin {
|
||||
}
|
||||
|
||||
#[derive(Insertable)]
|
||||
#[table_name = "event_ack"]
|
||||
#[diesel(table_name = event_ack)]
|
||||
struct EventAck {
|
||||
pub queue_item_id: Uuid,
|
||||
pub deduplication_id: Uuid,
|
||||
@ -90,7 +91,7 @@ struct EventAck {
|
||||
}
|
||||
|
||||
#[derive(Insertable)]
|
||||
#[table_name = "event_tx_ack"]
|
||||
#[diesel(table_name = event_tx_ack)]
|
||||
struct EventTxAck {
|
||||
pub queue_item_id: Uuid,
|
||||
pub downlink_id: i64,
|
||||
@ -110,7 +111,7 @@ struct EventTxAck {
|
||||
}
|
||||
|
||||
#[derive(Insertable)]
|
||||
#[table_name = "event_log"]
|
||||
#[diesel(table_name = event_log)]
|
||||
struct EventLog {
|
||||
pub time: DateTime<Utc>,
|
||||
pub tenant_id: Uuid,
|
||||
@ -129,7 +130,7 @@ struct EventLog {
|
||||
}
|
||||
|
||||
#[derive(Insertable)]
|
||||
#[table_name = "event_status"]
|
||||
#[diesel(table_name = event_status)]
|
||||
struct EventStatus {
|
||||
pub deduplication_id: Uuid,
|
||||
pub time: DateTime<Utc>,
|
||||
@ -149,7 +150,7 @@ struct EventStatus {
|
||||
}
|
||||
|
||||
#[derive(Insertable)]
|
||||
#[table_name = "event_location"]
|
||||
#[diesel(table_name = event_location)]
|
||||
struct EventLocation {
|
||||
pub deduplication_id: Uuid,
|
||||
pub time: DateTime<Utc>,
|
||||
@ -170,7 +171,7 @@ struct EventLocation {
|
||||
}
|
||||
|
||||
#[derive(Insertable)]
|
||||
#[table_name = "event_integration"]
|
||||
#[diesel(table_name = event_integration)]
|
||||
struct EventIntegration {
|
||||
pub deduplication_id: Uuid,
|
||||
pub time: DateTime<Utc>,
|
||||
@ -204,10 +205,12 @@ impl Integration {
|
||||
})
|
||||
.build(ConnectionManager::new(&conf.dsn))
|
||||
.context("Setup PostgreSQL connection pool error")?;
|
||||
let db_conn = pg_pool.get()?;
|
||||
let mut db_conn = pg_pool.get()?;
|
||||
|
||||
info!("Applying schema migrations");
|
||||
embedded_migrations::run(&db_conn).context("Run migrations error")?;
|
||||
db_conn
|
||||
.run_pending_migrations(MIGRATIONS)
|
||||
.map_err(|e| anyhow!("{}", e))?;
|
||||
|
||||
Ok(Integration { pg_pool })
|
||||
}
|
||||
@ -246,12 +249,12 @@ impl IntegrationTrait for Integration {
|
||||
rx_info: serde_json::to_value(&pl.rx_info)?,
|
||||
tx_info: serde_json::to_value(&pl.tx_info)?,
|
||||
};
|
||||
let c = self.pg_pool.get()?;
|
||||
let mut c = self.pg_pool.get()?;
|
||||
|
||||
task::spawn_blocking(move || -> Result<()> {
|
||||
diesel::insert_into(event_up::table)
|
||||
.values(&e)
|
||||
.execute(&c)?;
|
||||
.execute(&mut c)?;
|
||||
Ok(())
|
||||
})
|
||||
.await??;
|
||||
@ -281,12 +284,12 @@ impl IntegrationTrait for Integration {
|
||||
tags: serde_json::to_value(&di.tags)?,
|
||||
dev_addr: pl.dev_addr.clone(),
|
||||
};
|
||||
let c = self.pg_pool.get()?;
|
||||
let mut c = self.pg_pool.get()?;
|
||||
|
||||
task::spawn_blocking(move || -> Result<()> {
|
||||
diesel::insert_into(event_join::table)
|
||||
.values(&e)
|
||||
.execute(&c)?;
|
||||
.execute(&mut c)?;
|
||||
Ok(())
|
||||
})
|
||||
.await??;
|
||||
@ -318,12 +321,12 @@ impl IntegrationTrait for Integration {
|
||||
acknowledged: pl.acknowledged,
|
||||
f_cnt_down: pl.f_cnt_down as i64,
|
||||
};
|
||||
let c = self.pg_pool.get()?;
|
||||
let mut c = self.pg_pool.get()?;
|
||||
|
||||
task::spawn_blocking(move || -> Result<()> {
|
||||
diesel::insert_into(event_ack::table)
|
||||
.values(&e)
|
||||
.execute(&c)?;
|
||||
.execute(&mut c)?;
|
||||
Ok(())
|
||||
})
|
||||
.await??;
|
||||
@ -356,12 +359,12 @@ impl IntegrationTrait for Integration {
|
||||
gateway_id: pl.gateway_id.clone(),
|
||||
tx_info: serde_json::to_value(&pl.tx_info)?,
|
||||
};
|
||||
let c = self.pg_pool.get()?;
|
||||
let mut c = self.pg_pool.get()?;
|
||||
|
||||
task::spawn_blocking(move || -> Result<()> {
|
||||
diesel::insert_into(event_tx_ack::table)
|
||||
.values(&e)
|
||||
.execute(&c)?;
|
||||
.execute(&mut c)?;
|
||||
Ok(())
|
||||
})
|
||||
.await??;
|
||||
@ -393,12 +396,12 @@ impl IntegrationTrait for Integration {
|
||||
description: pl.description.clone(),
|
||||
context: serde_json::to_value(&pl.context)?,
|
||||
};
|
||||
let c = self.pg_pool.get()?;
|
||||
let mut c = self.pg_pool.get()?;
|
||||
|
||||
task::spawn_blocking(move || -> Result<()> {
|
||||
diesel::insert_into(event_log::table)
|
||||
.values(&e)
|
||||
.execute(&c)?;
|
||||
.execute(&mut c)?;
|
||||
Ok(())
|
||||
})
|
||||
.await??;
|
||||
@ -431,12 +434,12 @@ impl IntegrationTrait for Integration {
|
||||
battery_level_unavailable: pl.battery_level_unavailable,
|
||||
battery_level: pl.battery_level,
|
||||
};
|
||||
let c = self.pg_pool.get()?;
|
||||
let mut c = self.pg_pool.get()?;
|
||||
|
||||
task::spawn_blocking(move || -> Result<()> {
|
||||
diesel::insert_into(event_status::table)
|
||||
.values(&e)
|
||||
.execute(&c)?;
|
||||
.execute(&mut c)?;
|
||||
Ok(())
|
||||
})
|
||||
.await??;
|
||||
@ -470,12 +473,12 @@ impl IntegrationTrait for Integration {
|
||||
source: loc.source.to_string(),
|
||||
accuracy: loc.accuracy,
|
||||
};
|
||||
let c = self.pg_pool.get()?;
|
||||
let mut c = self.pg_pool.get()?;
|
||||
|
||||
task::spawn_blocking(move || -> Result<()> {
|
||||
diesel::insert_into(event_location::table)
|
||||
.values(&e)
|
||||
.execute(&c)?;
|
||||
.execute(&mut c)?;
|
||||
Ok(())
|
||||
})
|
||||
.await??;
|
||||
@ -507,12 +510,12 @@ impl IntegrationTrait for Integration {
|
||||
event_type: pl.event_type.clone(),
|
||||
object: serde_json::to_value(&pl.object)?,
|
||||
};
|
||||
let c = self.pg_pool.get()?;
|
||||
let mut c = self.pg_pool.get()?;
|
||||
|
||||
task::spawn_blocking(move || -> Result<()> {
|
||||
diesel::insert_into(event_integration::table)
|
||||
.values(&e)
|
||||
.execute(&c)?;
|
||||
.execute(&mut c)?;
|
||||
Ok(())
|
||||
})
|
||||
.await??;
|
||||
|
@ -32,7 +32,7 @@ pub async fn handle(
|
||||
pl.margin as i32,
|
||||
pl.battery == 0,
|
||||
if pl.battery > 0 && pl.battery < 255 {
|
||||
let v: BigDecimal = ((pl.battery as f32) / 254.0 * 100.0).into();
|
||||
let v: BigDecimal = ((pl.battery as f32) / 254.0 * 100.0).try_into()?;
|
||||
Some(v.with_scale(2))
|
||||
} else {
|
||||
None
|
||||
|
@ -1,7 +1,6 @@
|
||||
#![allow(dead_code)]
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
#[macro_use]
|
||||
extern crate diesel_migrations;
|
||||
#[macro_use]
|
||||
extern crate diesel;
|
||||
|
@ -11,7 +11,7 @@ use super::schema::api_key;
|
||||
use super::{error, get_db_conn};
|
||||
|
||||
#[derive(Queryable, Insertable, AsChangeset, PartialEq, Debug)]
|
||||
#[table_name = "api_key"]
|
||||
#[diesel(table_name = api_key)]
|
||||
pub struct ApiKey {
|
||||
pub id: Uuid,
|
||||
pub created_at: DateTime<Utc>,
|
||||
@ -52,10 +52,10 @@ pub async fn create(ak: ApiKey) -> Result<ApiKey, Error> {
|
||||
ak.validate()?;
|
||||
|
||||
let ak = task::spawn_blocking(move || -> Result<ApiKey, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
diesel::insert_into(api_key::table)
|
||||
.values(&ak)
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| error::Error::from_diesel(e, ak.id.to_string()))
|
||||
})
|
||||
.await??;
|
||||
@ -68,10 +68,10 @@ pub async fn get(id: &Uuid) -> Result<ApiKey, Error> {
|
||||
let id = *id;
|
||||
|
||||
move || -> Result<ApiKey, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
api_key::dsl::api_key
|
||||
.find(&id)
|
||||
.first(&c)
|
||||
.first(&mut c)
|
||||
.map_err(|e| error::Error::from_diesel(e, id.to_string()))
|
||||
}
|
||||
})
|
||||
@ -83,8 +83,8 @@ pub async fn delete(id: &Uuid) -> Result<(), Error> {
|
||||
let id = *id;
|
||||
|
||||
move || -> Result<(), Error> {
|
||||
let c = get_db_conn()?;
|
||||
let ra = diesel::delete(api_key::dsl::api_key.find(&id)).execute(&c)?;
|
||||
let mut c = get_db_conn()?;
|
||||
let ra = diesel::delete(api_key::dsl::api_key.find(&id)).execute(&mut c)?;
|
||||
if ra == 0 {
|
||||
return Err(Error::NotFound(id.to_string()));
|
||||
}
|
||||
@ -100,7 +100,7 @@ pub async fn get_count(filters: &Filters) -> Result<i64, Error> {
|
||||
let filters = filters.clone();
|
||||
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
|
||||
let mut q = api_key::dsl::api_key
|
||||
.select(dsl::count_star())
|
||||
@ -111,7 +111,7 @@ pub async fn get_count(filters: &Filters) -> Result<i64, Error> {
|
||||
q = q.filter(api_key::dsl::tenant_id.eq(tenant_id));
|
||||
}
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -122,7 +122,7 @@ pub async fn list(limit: i64, offset: i64, filters: &Filters) -> Result<Vec<ApiK
|
||||
let filters = filters.clone();
|
||||
|
||||
move || -> Result<Vec<ApiKey>, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
|
||||
let mut q = api_key::dsl::api_key
|
||||
.filter(api_key::dsl::is_admin.eq(filters.is_admin))
|
||||
@ -136,7 +136,7 @@ pub async fn list(limit: i64, offset: i64, filters: &Filters) -> Result<Vec<ApiK
|
||||
.order_by(api_key::dsl::name)
|
||||
.limit(limit)
|
||||
.offset(offset)
|
||||
.load(&c)?;
|
||||
.load(&mut c)?;
|
||||
Ok(items)
|
||||
}
|
||||
})
|
||||
|
@ -1,16 +1,14 @@
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
use std::io::Write;
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::Result;
|
||||
use chrono::{DateTime, Utc};
|
||||
use diesel::backend::Backend;
|
||||
use diesel::backend::{self, Backend};
|
||||
use diesel::dsl;
|
||||
use diesel::pg::types::sql_types::Jsonb;
|
||||
use diesel::pg::Pg;
|
||||
use diesel::prelude::*;
|
||||
use diesel::sql_types::Text;
|
||||
use diesel::sql_types::{Jsonb, Text};
|
||||
use diesel::{deserialize, serialize};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tokio::task;
|
||||
@ -22,7 +20,7 @@ use super::get_db_conn;
|
||||
use super::schema::{application, application_integration};
|
||||
|
||||
#[derive(Clone, Queryable, Insertable, AsChangeset, PartialEq, Debug)]
|
||||
#[table_name = "application"]
|
||||
#[diesel(table_name = application)]
|
||||
pub struct Application {
|
||||
pub id: Uuid,
|
||||
pub tenant_id: Uuid,
|
||||
@ -74,7 +72,7 @@ pub struct ApplicationListItem {
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize, Copy, Clone, Debug, Eq, PartialEq, AsExpression, FromSqlRow)]
|
||||
#[sql_type = "Text"]
|
||||
#[diesel(sql_type = Text)]
|
||||
pub enum IntegrationKind {
|
||||
Http,
|
||||
InfluxDb,
|
||||
@ -116,29 +114,28 @@ impl FromStr for IntegrationKind {
|
||||
}
|
||||
}
|
||||
|
||||
impl<ST, DB> deserialize::FromSql<ST, DB> for IntegrationKind
|
||||
impl<DB> deserialize::FromSql<Text, DB> for IntegrationKind
|
||||
where
|
||||
DB: Backend,
|
||||
*const str: deserialize::FromSql<ST, DB>,
|
||||
*const str: deserialize::FromSql<Text, DB>,
|
||||
{
|
||||
fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
|
||||
let string = String::from_sql(bytes)?;
|
||||
fn from_sql(value: backend::RawValue<DB>) -> deserialize::Result<Self> {
|
||||
let string = String::from_sql(value)?;
|
||||
Ok(IntegrationKind::from_str(&string)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB> serialize::ToSql<Text, DB> for IntegrationKind
|
||||
impl serialize::ToSql<Text, Pg> for IntegrationKind
|
||||
where
|
||||
DB: Backend,
|
||||
str: serialize::ToSql<Text, DB>,
|
||||
str: serialize::ToSql<Text, Pg>,
|
||||
{
|
||||
fn to_sql<W: Write>(&self, out: &mut serialize::Output<W, DB>) -> serialize::Result {
|
||||
self.to_string().as_str().to_sql(out)
|
||||
fn to_sql<'b>(&self, out: &mut serialize::Output<'b, '_, Pg>) -> serialize::Result {
|
||||
<str as serialize::ToSql<Text, Pg>>::to_sql(&self.to_string(), &mut out.reborrow())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, AsExpression, FromSqlRow, Serialize, Deserialize)]
|
||||
#[sql_type = "Jsonb"]
|
||||
#[diesel(sql_type = Jsonb)]
|
||||
pub enum IntegrationConfiguration {
|
||||
None,
|
||||
Http(HttpConfiguration),
|
||||
@ -154,16 +151,16 @@ pub enum IntegrationConfiguration {
|
||||
}
|
||||
|
||||
impl deserialize::FromSql<Jsonb, Pg> for IntegrationConfiguration {
|
||||
fn from_sql(bytes: Option<&[u8]>) -> deserialize::Result<Self> {
|
||||
let value = <serde_json::Value as deserialize::FromSql<Jsonb, Pg>>::from_sql(bytes)?;
|
||||
fn from_sql(value: backend::RawValue<Pg>) -> deserialize::Result<Self> {
|
||||
let value = <serde_json::Value as deserialize::FromSql<Jsonb, Pg>>::from_sql(value)?;
|
||||
Ok(serde_json::from_value(value)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl serialize::ToSql<Jsonb, Pg> for IntegrationConfiguration {
|
||||
fn to_sql<W: Write>(&self, out: &mut serialize::Output<W, Pg>) -> serialize::Result {
|
||||
fn to_sql<'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, out)
|
||||
<serde_json::Value as serialize::ToSql<Jsonb, Pg>>::to_sql(&value, &mut out.reborrow())
|
||||
}
|
||||
}
|
||||
|
||||
@ -259,7 +256,7 @@ pub struct IftttConfiguration {
|
||||
}
|
||||
|
||||
#[derive(Clone, Queryable, Insertable, AsChangeset, PartialEq, Debug)]
|
||||
#[table_name = "application_integration"]
|
||||
#[diesel(table_name = application_integration)]
|
||||
pub struct Integration {
|
||||
pub application_id: Uuid,
|
||||
pub kind: IntegrationKind,
|
||||
@ -286,10 +283,10 @@ pub async fn create(a: Application) -> Result<Application, Error> {
|
||||
a.validate()?;
|
||||
task::spawn_blocking({
|
||||
move || -> Result<Application, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let a: Application = diesel::insert_into(application::table)
|
||||
.values(&a)
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, a.id.to_string()))?;
|
||||
|
||||
info!(id = %a.id, "Application created");
|
||||
@ -304,10 +301,10 @@ pub async fn get(id: &Uuid) -> Result<Application, Error> {
|
||||
task::spawn_blocking({
|
||||
let id = *id;
|
||||
move || -> Result<Application, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let a = application::dsl::application
|
||||
.find(&id)
|
||||
.first(&c)
|
||||
.first(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, id.to_string()))?;
|
||||
Ok(a)
|
||||
}
|
||||
@ -319,14 +316,14 @@ pub async fn update(a: Application) -> Result<Application, Error> {
|
||||
a.validate()?;
|
||||
task::spawn_blocking({
|
||||
move || -> Result<Application, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let a: Application = diesel::update(application::dsl::application.find(&a.id))
|
||||
.set((
|
||||
application::updated_at.eq(Utc::now()),
|
||||
application::name.eq(&a.name),
|
||||
application::description.eq(&a.description),
|
||||
))
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, a.id.to_string()))?;
|
||||
|
||||
info!(
|
||||
@ -345,10 +342,10 @@ pub async fn update_mqtt_cls_cert(id: &Uuid, cert: &[u8]) -> Result<Application,
|
||||
let id = *id;
|
||||
let cert = cert.to_vec();
|
||||
move || -> Result<Application, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let app: Application = diesel::update(application::dsl::application.find(&id))
|
||||
.set(application::mqtt_tls_cert.eq(cert))
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, id.to_string()))?;
|
||||
Ok(app)
|
||||
}
|
||||
@ -367,8 +364,8 @@ pub async fn delete(id: &Uuid) -> Result<(), Error> {
|
||||
task::spawn_blocking({
|
||||
let id = *id;
|
||||
move || -> Result<(), Error> {
|
||||
let c = get_db_conn()?;
|
||||
let ra = diesel::delete(application::dsl::application.find(&id)).execute(&c)?;
|
||||
let mut c = get_db_conn()?;
|
||||
let ra = diesel::delete(application::dsl::application.find(&id)).execute(&mut c)?;
|
||||
if ra == 0 {
|
||||
return Err(Error::NotFound(id.to_string()));
|
||||
}
|
||||
@ -388,7 +385,7 @@ pub async fn get_count(filters: &Filters) -> Result<i64, Error> {
|
||||
task::spawn_blocking({
|
||||
let filters = filters.clone();
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = application::dsl::application
|
||||
.select(dsl::count_star())
|
||||
.into_boxed();
|
||||
@ -401,7 +398,7 @@ pub async fn get_count(filters: &Filters) -> Result<i64, Error> {
|
||||
q = q.filter(application::dsl::name.ilike(format!("%{}%", search)));
|
||||
}
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -415,7 +412,7 @@ pub async fn list(
|
||||
task::spawn_blocking({
|
||||
let filters = filters.clone();
|
||||
move || -> Result<Vec<ApplicationListItem>, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = application::dsl::application
|
||||
.select((
|
||||
application::id,
|
||||
@ -438,7 +435,7 @@ pub async fn list(
|
||||
.order_by(application::dsl::name)
|
||||
.limit(limit)
|
||||
.offset(offset)
|
||||
.load(&c)?;
|
||||
.load(&mut c)?;
|
||||
Ok(items)
|
||||
}
|
||||
})
|
||||
@ -448,10 +445,10 @@ pub async fn list(
|
||||
pub async fn create_integration(i: Integration) -> Result<Integration, Error> {
|
||||
task::spawn_blocking({
|
||||
move || -> Result<Integration, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let i: Integration = diesel::insert_into(application_integration::table)
|
||||
.values(&i)
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, i.kind.to_string()))?;
|
||||
|
||||
info!(application_id = %i.application_id, kind = %i.kind, "Integration created");
|
||||
@ -468,14 +465,14 @@ pub async fn get_integration(
|
||||
task::spawn_blocking({
|
||||
let application_id = *application_id;
|
||||
move || -> Result<Integration, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let i: Integration = application_integration::dsl::application_integration
|
||||
.filter(
|
||||
application_integration::dsl::application_id
|
||||
.eq(application_id)
|
||||
.and(application_integration::dsl::kind.eq(kind)),
|
||||
)
|
||||
.first(&c)
|
||||
.first(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, application_id.to_string()))?;
|
||||
Ok(i)
|
||||
}
|
||||
@ -486,7 +483,7 @@ pub async fn get_integration(
|
||||
pub async fn update_integration(i: Integration) -> Result<Integration, Error> {
|
||||
task::spawn_blocking({
|
||||
move || -> Result<Integration, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let i: Integration = diesel::update(
|
||||
application_integration::dsl::application_integration.filter(
|
||||
application_integration::dsl::application_id
|
||||
@ -498,7 +495,7 @@ pub async fn update_integration(i: Integration) -> Result<Integration, Error> {
|
||||
application_integration::updated_at.eq(Utc::now()),
|
||||
application_integration::configuration.eq(&i.configuration),
|
||||
))
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, i.application_id.to_string()))?;
|
||||
|
||||
info!(application_id = %i.application_id, kind = %i.kind, "Integration updated");
|
||||
@ -513,7 +510,7 @@ pub async fn delete_integration(application_id: &Uuid, kind: IntegrationKind) ->
|
||||
task::spawn_blocking({
|
||||
let application_id = *application_id;
|
||||
move || -> Result<(), Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let ra = diesel::delete(
|
||||
application_integration::dsl::application_integration.filter(
|
||||
application_integration::dsl::application_id
|
||||
@ -521,7 +518,7 @@ pub async fn delete_integration(application_id: &Uuid, kind: IntegrationKind) ->
|
||||
.and(application_integration::dsl::kind.eq(&kind)),
|
||||
),
|
||||
)
|
||||
.execute(&c)?;
|
||||
.execute(&mut c)?;
|
||||
|
||||
if ra == 0 {
|
||||
return Err(Error::NotFound(application_id.to_string()));
|
||||
@ -540,11 +537,11 @@ pub async fn get_integrations_for_application(
|
||||
task::spawn_blocking({
|
||||
let application_id = *application_id;
|
||||
move || -> Result<Vec<Integration>, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let items: Vec<Integration> = application_integration::dsl::application_integration
|
||||
.filter(application_integration::dsl::application_id.eq(&application_id))
|
||||
.order_by(application_integration::dsl::kind)
|
||||
.load(&c)?;
|
||||
.load(&mut c)?;
|
||||
Ok(items)
|
||||
}
|
||||
})
|
||||
@ -554,14 +551,14 @@ pub async fn get_integrations_for_application(
|
||||
pub async fn get_measurement_keys(application_id: &Uuid) -> Result<Vec<String>, Error> {
|
||||
#[derive(QueryableByName)]
|
||||
struct Measurement {
|
||||
#[sql_type = "diesel::sql_types::Text"]
|
||||
#[diesel(sql_type = diesel::sql_types::Text)]
|
||||
pub key: String,
|
||||
}
|
||||
|
||||
task::spawn_blocking({
|
||||
let application_id = *application_id;
|
||||
move || -> Result<Vec<String>, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let keys: Vec<Measurement> = diesel::sql_query(
|
||||
r#"
|
||||
select
|
||||
@ -576,8 +573,8 @@ pub async fn get_measurement_keys(application_id: &Uuid) -> Result<Vec<String>,
|
||||
key
|
||||
"#,
|
||||
)
|
||||
.bind::<diesel::pg::types::sql_types::Uuid, _>(application_id)
|
||||
.load(&c)
|
||||
.bind::<diesel::sql_types::Uuid, _>(application_id)
|
||||
.load(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, application_id.to_string()))?;
|
||||
Ok(keys.iter().map(|k| k.key.clone()).collect())
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ use super::{error::Error, fields, get_db_conn, get_redis_conn, redis_key};
|
||||
use crate::config;
|
||||
|
||||
#[derive(Queryable, QueryableByName, Insertable, AsChangeset, PartialEq, Debug, Clone)]
|
||||
#[table_name = "device"]
|
||||
#[diesel(table_name = device)]
|
||||
pub struct Device {
|
||||
pub dev_eui: EUI64,
|
||||
pub application_id: Uuid,
|
||||
@ -106,11 +106,11 @@ pub struct Filters {
|
||||
|
||||
#[derive(QueryableByName, PartialEq, Debug)]
|
||||
pub struct DevicesActiveInactive {
|
||||
#[sql_type = "diesel::sql_types::BigInt"]
|
||||
#[diesel(sql_type = diesel::sql_types::BigInt)]
|
||||
pub never_seen_count: i64,
|
||||
#[sql_type = "diesel::sql_types::BigInt"]
|
||||
#[diesel(sql_type = diesel::sql_types::BigInt)]
|
||||
pub active_count: i64,
|
||||
#[sql_type = "diesel::sql_types::BigInt"]
|
||||
#[diesel(sql_type = diesel::sql_types::BigInt)]
|
||||
pub inactive_count: i64,
|
||||
}
|
||||
|
||||
@ -124,8 +124,8 @@ pub async fn create(d: Device) -> Result<Device, Error> {
|
||||
d.validate()?;
|
||||
let d = task::spawn_blocking({
|
||||
move || -> Result<Device, Error> {
|
||||
let c = get_db_conn()?;
|
||||
c.transaction::<Device, Error, _>(|| {
|
||||
let mut c = get_db_conn()?;
|
||||
c.transaction::<Device, Error, _>(|c| {
|
||||
// use for update to lock the tenant
|
||||
let t: super::tenant::Tenant = tenant::dsl::tenant
|
||||
.select((
|
||||
@ -141,13 +141,13 @@ pub async fn create(d: Device) -> Result<Device, Error> {
|
||||
))
|
||||
.inner_join(application::table)
|
||||
.filter(application::dsl::id.eq(&d.application_id))
|
||||
.first(&c)?;
|
||||
.first(c)?;
|
||||
|
||||
let dev_count: i64 = device::dsl::device
|
||||
.select(dsl::count_star())
|
||||
.inner_join(application::table)
|
||||
.filter(application::dsl::tenant_id.eq(&t.id))
|
||||
.first(&c)?;
|
||||
.first(c)?;
|
||||
|
||||
if t.max_device_count != 0 && dev_count as i32 >= t.max_device_count {
|
||||
return Err(Error::NotAllowed(
|
||||
@ -157,7 +157,7 @@ pub async fn create(d: Device) -> Result<Device, Error> {
|
||||
|
||||
diesel::insert_into(device::table)
|
||||
.values(&d)
|
||||
.get_result(&c)
|
||||
.get_result(c)
|
||||
.map_err(|e| Error::from_diesel(e, d.dev_eui.to_string()))
|
||||
})
|
||||
}
|
||||
@ -171,10 +171,10 @@ pub async fn get(dev_eui: &EUI64) -> Result<Device, Error> {
|
||||
task::spawn_blocking({
|
||||
let dev_eui = *dev_eui;
|
||||
move || -> Result<Device, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let d = device::dsl::device
|
||||
.find(&dev_eui)
|
||||
.first(&c)
|
||||
.first(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, dev_eui.to_string()))?;
|
||||
Ok(d)
|
||||
}
|
||||
@ -186,7 +186,7 @@ pub async fn update(d: Device) -> Result<Device, Error> {
|
||||
d.validate()?;
|
||||
let d = task::spawn_blocking({
|
||||
move || -> Result<Device, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
diesel::update(device::dsl::device.find(&d.dev_eui))
|
||||
.set((
|
||||
device::updated_at.eq(Utc::now()),
|
||||
@ -199,7 +199,7 @@ pub async fn update(d: Device) -> Result<Device, Error> {
|
||||
device::tags.eq(&d.tags),
|
||||
device::variables.eq(&d.variables),
|
||||
))
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, d.dev_eui.to_string()))
|
||||
}
|
||||
})
|
||||
@ -213,10 +213,10 @@ pub async fn set_enabled_class(dev_eui: &EUI64, mode: &str) -> Result<Device, Er
|
||||
let dev_eui = *dev_eui;
|
||||
let mode = mode.to_string();
|
||||
move || -> Result<Device, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
diesel::update(device::dsl::device.find(&dev_eui))
|
||||
.set(device::enabled_class.eq(&mode))
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, dev_eui.to_string()))
|
||||
}
|
||||
})
|
||||
@ -236,10 +236,10 @@ pub async fn set_scheduler_run_after(
|
||||
task::spawn_blocking({
|
||||
let dev_eui = *dev_eui;
|
||||
move || -> Result<Device, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
diesel::update(device::dsl::device.find(&dev_eui))
|
||||
.set(device::scheduler_run_after.eq(&new_ts))
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, dev_eui.to_string()))
|
||||
}
|
||||
})
|
||||
@ -250,13 +250,13 @@ pub async fn set_last_seen_dr(dev_eui: &EUI64, dr: u8) -> Result<Device, Error>
|
||||
let d = task::spawn_blocking({
|
||||
let dev_eui = *dev_eui;
|
||||
move || -> Result<Device, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
diesel::update(device::dsl::device.find(&dev_eui))
|
||||
.set((
|
||||
device::last_seen_at.eq(Utc::now()),
|
||||
device::dr.eq(dr as i16),
|
||||
))
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, dev_eui.to_string()))
|
||||
}
|
||||
})
|
||||
@ -274,14 +274,14 @@ pub async fn set_status(
|
||||
let d = task::spawn_blocking({
|
||||
let dev_eui = *dev_eui;
|
||||
move || -> Result<Device, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
diesel::update(device::dsl::device.find(&dev_eui))
|
||||
.set((
|
||||
device::margin.eq(Some(margin)),
|
||||
device::external_power_source.eq(external_power_source),
|
||||
device::battery_level.eq(battery_level),
|
||||
))
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, dev_eui.to_string()))
|
||||
}
|
||||
})
|
||||
@ -294,8 +294,8 @@ pub async fn delete(dev_eui: &EUI64) -> Result<(), Error> {
|
||||
task::spawn_blocking({
|
||||
let dev_eui = *dev_eui;
|
||||
move || -> Result<(), Error> {
|
||||
let c = get_db_conn()?;
|
||||
let ra = diesel::delete(device::dsl::device.find(&dev_eui)).execute(&c)?;
|
||||
let mut c = get_db_conn()?;
|
||||
let ra = diesel::delete(device::dsl::device.find(&dev_eui)).execute(&mut c)?;
|
||||
if ra == 0 {
|
||||
return Err(Error::NotFound(dev_eui.to_string()));
|
||||
}
|
||||
@ -311,7 +311,7 @@ pub async fn get_count(filters: &Filters) -> Result<i64, Error> {
|
||||
task::spawn_blocking({
|
||||
let filters = filters.clone();
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = device::dsl::device
|
||||
.select(dsl::count_star())
|
||||
.distinct()
|
||||
@ -331,7 +331,7 @@ pub async fn get_count(filters: &Filters) -> Result<i64, Error> {
|
||||
.filter(multicast_group_device::dsl::multicast_group_id.eq(multicast_group_id));
|
||||
}
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -345,7 +345,7 @@ pub async fn list(
|
||||
task::spawn_blocking({
|
||||
let filters = filters.clone();
|
||||
move || -> Result<Vec<DeviceListItem>, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = device::dsl::device
|
||||
.inner_join(device_profile::table)
|
||||
.left_join(multicast_group_device::table)
|
||||
@ -381,7 +381,7 @@ pub async fn list(
|
||||
q.order_by(device::dsl::name)
|
||||
.limit(limit)
|
||||
.offset(offset)
|
||||
.load(&c)
|
||||
.load(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, "".into()))
|
||||
}
|
||||
})
|
||||
@ -392,7 +392,7 @@ pub async fn get_active_inactive(tenant_id: &Option<Uuid>) -> Result<DevicesActi
|
||||
task::spawn_blocking({
|
||||
let tenant_id = *tenant_id;
|
||||
move || -> Result<DevicesActiveInactive, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
diesel::sql_query(r#"
|
||||
with device_active_inactive as (
|
||||
select
|
||||
@ -412,8 +412,8 @@ pub async fn get_active_inactive(tenant_id: &Option<Uuid>) -> Result<DevicesActi
|
||||
from
|
||||
device_active_inactive
|
||||
"#)
|
||||
.bind::<diesel::sql_types::Nullable<diesel::pg::types::sql_types::Uuid>, _>(tenant_id)
|
||||
.get_result(&c)
|
||||
.bind::<diesel::sql_types::Nullable<diesel::sql_types::Uuid>, _>(tenant_id)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, "".into()))
|
||||
}
|
||||
})
|
||||
@ -424,7 +424,7 @@ pub async fn get_data_rates(tenant_id: &Option<Uuid>) -> Result<Vec<DevicesDataR
|
||||
task::spawn_blocking({
|
||||
let tenant_id = *tenant_id;
|
||||
move || -> Result<Vec<DevicesDataRate>, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = device::dsl::device
|
||||
.inner_join(device_profile::table)
|
||||
//.select((device::dr, dsl::count_star()))
|
||||
@ -432,6 +432,7 @@ pub async fn get_data_rates(tenant_id: &Option<Uuid>) -> Result<Vec<DevicesDataR
|
||||
device::dr,
|
||||
diesel::dsl::sql::<diesel::sql_types::BigInt>("count(1)"),
|
||||
))
|
||||
.group_by(device::dr)
|
||||
.filter(device::dsl::dr.is_not_null())
|
||||
.into_boxed();
|
||||
|
||||
@ -439,9 +440,7 @@ pub async fn get_data_rates(tenant_id: &Option<Uuid>) -> Result<Vec<DevicesDataR
|
||||
q = q.filter(device_profile::dsl::tenant_id.eq(id));
|
||||
}
|
||||
|
||||
q.group_by(device::dr)
|
||||
.load(&c)
|
||||
.map_err(|e| Error::from_diesel(e, "".into()))
|
||||
q.load(&mut c).map_err(|e| Error::from_diesel(e, "".into()))
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -449,8 +448,8 @@ pub async fn get_data_rates(tenant_id: &Option<Uuid>) -> Result<Vec<DevicesDataR
|
||||
|
||||
pub async fn get_with_class_b_c_queue_items(limit: usize) -> Result<Vec<Device>> {
|
||||
task::spawn_blocking(move || -> Result<Vec<Device>> {
|
||||
let c = get_db_conn()?;
|
||||
c.transaction::<Vec<Device>, Error, _>(|| {
|
||||
let mut c = get_db_conn()?;
|
||||
c.transaction::<Vec<Device>, Error, _>(|c| {
|
||||
let conf = config::get();
|
||||
diesel::sql_query(
|
||||
r#"
|
||||
@ -490,7 +489,7 @@ pub async fn get_with_class_b_c_queue_items(limit: usize) -> Result<Vec<Device>>
|
||||
.bind::<diesel::sql_types::Timestamptz, _>(
|
||||
Utc::now() + Duration::from_std(2 * conf.network.scheduler.interval).unwrap(),
|
||||
)
|
||||
.load(&c)
|
||||
.load(c)
|
||||
.map_err(|e| Error::from_diesel(e, "".into()))
|
||||
})
|
||||
.context("Get with Class B/C queue-items transaction")
|
||||
|
@ -11,14 +11,14 @@ use super::get_db_conn;
|
||||
use super::schema::device_keys;
|
||||
|
||||
#[derive(Queryable, Insertable, AsChangeset, PartialEq, Debug, Clone)]
|
||||
#[table_name = "device_keys"]
|
||||
#[diesel(table_name = device_keys)]
|
||||
pub struct DeviceKeys {
|
||||
pub dev_eui: EUI64,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
pub nwk_key: AES128Key,
|
||||
pub app_key: AES128Key,
|
||||
pub dev_nonces: Vec<i32>,
|
||||
pub dev_nonces: Vec<Option<i32>>,
|
||||
pub join_nonce: i32,
|
||||
}
|
||||
|
||||
@ -47,10 +47,10 @@ impl Default for DeviceKeys {
|
||||
pub async fn create(dk: DeviceKeys) -> Result<DeviceKeys, Error> {
|
||||
let dk = task::spawn_blocking({
|
||||
move || -> Result<DeviceKeys, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
diesel::insert_into(device_keys::table)
|
||||
.values(&dk)
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, dk.dev_eui.to_string()))
|
||||
}
|
||||
})
|
||||
@ -66,10 +66,10 @@ pub async fn get(dev_eui: &EUI64) -> Result<DeviceKeys, Error> {
|
||||
task::spawn_blocking({
|
||||
let dev_eui = *dev_eui;
|
||||
move || -> Result<DeviceKeys, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let dk = device_keys::dsl::device_keys
|
||||
.find(&dev_eui)
|
||||
.first(&c)
|
||||
.first(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, dev_eui.to_string()))?;
|
||||
Ok(dk)
|
||||
}
|
||||
@ -80,10 +80,10 @@ pub async fn get(dev_eui: &EUI64) -> Result<DeviceKeys, Error> {
|
||||
pub async fn update(dk: DeviceKeys) -> Result<DeviceKeys, Error> {
|
||||
let dk = task::spawn_blocking({
|
||||
move || -> Result<DeviceKeys, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
diesel::update(device_keys::dsl::device_keys.find(&dk.dev_eui))
|
||||
.set(&dk)
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, dk.dev_eui.to_string()))
|
||||
}
|
||||
})
|
||||
@ -99,8 +99,9 @@ pub async fn delete(dev_eui: &EUI64) -> Result<(), Error> {
|
||||
task::spawn_blocking({
|
||||
let dev_eui = *dev_eui;
|
||||
move || -> Result<(), Error> {
|
||||
let c = get_db_conn()?;
|
||||
let ra = diesel::delete(device_keys::dsl::device_keys.find(&dev_eui)).execute(&c)?;
|
||||
let mut c = get_db_conn()?;
|
||||
let ra =
|
||||
diesel::delete(device_keys::dsl::device_keys.find(&dev_eui)).execute(&mut c)?;
|
||||
if ra == 0 {
|
||||
return Err(Error::NotFound(dev_eui.to_string()));
|
||||
}
|
||||
@ -120,10 +121,10 @@ pub async fn set_dev_nonces(dev_eui: &EUI64, nonces: &[i32]) -> Result<DeviceKey
|
||||
let dev_eui = *dev_eui;
|
||||
let nonces = nonces.to_vec();
|
||||
move || -> Result<DeviceKeys, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
diesel::update(device_keys::dsl::device_keys.find(&dev_eui))
|
||||
.set(device_keys::dev_nonces.eq(&nonces))
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, dev_eui.to_string()))
|
||||
}
|
||||
})
|
||||
@ -139,13 +140,13 @@ pub async fn reset_nonces(dev_eui: &EUI64) -> Result<DeviceKeys, Error> {
|
||||
let dk = task::spawn_blocking({
|
||||
let dev_eui = *dev_eui;
|
||||
move || -> Result<DeviceKeys, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
diesel::update(device_keys::dsl::device_keys.find(&dev_eui))
|
||||
.set((
|
||||
device_keys::dev_nonces.eq::<Vec<i32>>(Vec::new()),
|
||||
device_keys::join_nonce.eq(0),
|
||||
))
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, dev_eui.to_string()))
|
||||
}
|
||||
})
|
||||
@ -164,26 +165,26 @@ pub async fn validate_and_store_dev_nonce(
|
||||
let dk = task::spawn_blocking({
|
||||
let dev_eui = *dev_eui;
|
||||
move || -> Result<DeviceKeys, Error> {
|
||||
let c = get_db_conn()?;
|
||||
c.transaction::<DeviceKeys, Error, _>(|| {
|
||||
let mut c = get_db_conn()?;
|
||||
c.transaction::<DeviceKeys, Error, _>(|c| {
|
||||
let mut dk: DeviceKeys = device_keys::dsl::device_keys
|
||||
.find(&dev_eui)
|
||||
.for_update()
|
||||
.first(&c)
|
||||
.first(c)
|
||||
.map_err(|e| Error::from_diesel(e, dev_eui.to_string()))?;
|
||||
|
||||
if dk.dev_nonces.contains(&(dev_nonce)) {
|
||||
if dk.dev_nonces.contains(&(Some(dev_nonce))) {
|
||||
return Err(Error::InvalidDevNonce);
|
||||
}
|
||||
|
||||
dk.dev_nonces.push(dev_nonce);
|
||||
dk.dev_nonces.push(Some(dev_nonce));
|
||||
|
||||
diesel::update(device_keys::dsl::device_keys.find(&dev_eui))
|
||||
.set((
|
||||
device_keys::updated_at.eq(Utc::now()),
|
||||
device_keys::dev_nonces.eq(&dk.dev_nonces),
|
||||
))
|
||||
.get_result(&c)
|
||||
.get_result(c)
|
||||
.map_err(|e| Error::from_diesel(e, dev_eui.to_string()))
|
||||
})
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ use crate::codec::Codec;
|
||||
use chirpstack_api::internal;
|
||||
|
||||
#[derive(Clone, Queryable, Insertable, AsChangeset, Debug, PartialEq)]
|
||||
#[table_name = "device_profile"]
|
||||
#[diesel(table_name = device_profile)]
|
||||
pub struct DeviceProfile {
|
||||
pub id: Uuid,
|
||||
pub tenant_id: Uuid,
|
||||
@ -146,10 +146,10 @@ pub async fn create(dp: DeviceProfile) -> Result<DeviceProfile, Error> {
|
||||
dp.validate()?;
|
||||
let dp = task::spawn_blocking({
|
||||
move || -> Result<DeviceProfile, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
diesel::insert_into(device_profile::table)
|
||||
.values(&dp)
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| error::Error::from_diesel(e, dp.id.to_string()))
|
||||
}
|
||||
})
|
||||
@ -162,10 +162,10 @@ pub async fn get(id: &Uuid) -> Result<DeviceProfile, Error> {
|
||||
task::spawn_blocking({
|
||||
let id = *id;
|
||||
move || -> Result<DeviceProfile, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let dp = device_profile::dsl::device_profile
|
||||
.find(&id)
|
||||
.first(&c)
|
||||
.first(&mut c)
|
||||
.map_err(|e| error::Error::from_diesel(e, id.to_string()))?;
|
||||
Ok(dp)
|
||||
}
|
||||
@ -177,7 +177,7 @@ pub async fn update(dp: DeviceProfile) -> Result<DeviceProfile, Error> {
|
||||
dp.validate()?;
|
||||
let dp = task::spawn_blocking({
|
||||
move || -> Result<DeviceProfile, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
|
||||
diesel::update(device_profile::dsl::device_profile.find(&dp.id))
|
||||
.set((
|
||||
@ -208,7 +208,7 @@ pub async fn update(dp: DeviceProfile) -> Result<DeviceProfile, Error> {
|
||||
device_profile::tags.eq(&dp.tags),
|
||||
device_profile::measurements.eq(&dp.measurements),
|
||||
))
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| error::Error::from_diesel(e, dp.id.to_string()))
|
||||
}
|
||||
})
|
||||
@ -221,10 +221,10 @@ pub async fn set_measurements(id: Uuid, m: &fields::Measurements) -> Result<Devi
|
||||
let dp = task::spawn_blocking({
|
||||
let m = m.clone();
|
||||
move || -> Result<DeviceProfile, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
diesel::update(device_profile::dsl::device_profile.find(&id))
|
||||
.set(device_profile::measurements.eq(m))
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, id.to_string()))
|
||||
}
|
||||
})
|
||||
@ -237,8 +237,9 @@ pub async fn delete(id: &Uuid) -> Result<(), Error> {
|
||||
task::spawn_blocking({
|
||||
let id = *id;
|
||||
move || -> Result<(), Error> {
|
||||
let c = get_db_conn()?;
|
||||
let ra = diesel::delete(device_profile::dsl::device_profile.find(&id)).execute(&c)?;
|
||||
let mut c = get_db_conn()?;
|
||||
let ra =
|
||||
diesel::delete(device_profile::dsl::device_profile.find(&id)).execute(&mut c)?;
|
||||
if ra == 0 {
|
||||
return Err(error::Error::NotFound(id.to_string()));
|
||||
}
|
||||
@ -254,7 +255,7 @@ pub async fn get_count(filters: &Filters) -> Result<i64, Error> {
|
||||
task::spawn_blocking({
|
||||
let filters = filters.clone();
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = device_profile::dsl::device_profile
|
||||
.select(dsl::count_star())
|
||||
.into_boxed();
|
||||
@ -267,7 +268,7 @@ pub async fn get_count(filters: &Filters) -> Result<i64, Error> {
|
||||
q = q.filter(device_profile::dsl::name.ilike(format!("%{}%", search)));
|
||||
}
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -281,7 +282,7 @@ pub async fn list(
|
||||
task::spawn_blocking({
|
||||
let filters = filters.clone();
|
||||
move || -> Result<Vec<DeviceProfileListItem>, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = device_profile::dsl::device_profile
|
||||
.select((
|
||||
device_profile::id,
|
||||
@ -309,7 +310,7 @@ pub async fn list(
|
||||
.order_by(device_profile::dsl::name)
|
||||
.limit(limit)
|
||||
.offset(offset)
|
||||
.load(&c)?;
|
||||
.load(&mut c)?;
|
||||
Ok(items)
|
||||
}
|
||||
})
|
||||
|
@ -16,7 +16,7 @@ use super::{error, fields, get_db_conn};
|
||||
use crate::codec::Codec;
|
||||
|
||||
#[derive(Clone, Queryable, Insertable, AsChangeset, Debug, PartialEq)]
|
||||
#[table_name = "device_profile_template"]
|
||||
#[diesel(table_name = device_profile_template)]
|
||||
pub struct DeviceProfileTemplate {
|
||||
pub id: String,
|
||||
pub created_at: DateTime<Utc>,
|
||||
@ -134,10 +134,10 @@ pub async fn create(dp: DeviceProfileTemplate) -> Result<DeviceProfileTemplate,
|
||||
dp.validate()?;
|
||||
let dp = task::spawn_blocking({
|
||||
move || -> Result<DeviceProfileTemplate, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
diesel::insert_into(device_profile_template::table)
|
||||
.values(&dp)
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| error::Error::from_diesel(e, dp.id.to_string()))
|
||||
}
|
||||
})
|
||||
@ -150,7 +150,7 @@ pub async fn upsert(dp: DeviceProfileTemplate) -> Result<DeviceProfileTemplate,
|
||||
dp.validate()?;
|
||||
let dp = task::spawn_blocking({
|
||||
move || -> Result<DeviceProfileTemplate, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
diesel::insert_into(device_profile_template::table)
|
||||
.values(&dp)
|
||||
.on_conflict(device_profile_template::id)
|
||||
@ -188,7 +188,7 @@ pub async fn upsert(dp: DeviceProfileTemplate) -> Result<DeviceProfileTemplate,
|
||||
device_profile_template::tags.eq(&dp.tags),
|
||||
device_profile_template::measurements.eq(&dp.measurements),
|
||||
))
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| error::Error::from_diesel(e, dp.id.to_string()))
|
||||
}
|
||||
})
|
||||
@ -201,10 +201,10 @@ pub async fn get(id: &str) -> Result<DeviceProfileTemplate, Error> {
|
||||
task::spawn_blocking({
|
||||
let id = id.to_string();
|
||||
move || -> Result<DeviceProfileTemplate, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let dp = device_profile_template::dsl::device_profile_template
|
||||
.find(&id)
|
||||
.first(&c)
|
||||
.first(&mut c)
|
||||
.map_err(|e| error::Error::from_diesel(e, id.clone()))?;
|
||||
Ok(dp)
|
||||
}
|
||||
@ -216,7 +216,7 @@ pub async fn update(dp: DeviceProfileTemplate) -> Result<DeviceProfileTemplate,
|
||||
dp.validate()?;
|
||||
let dp = task::spawn_blocking({
|
||||
move || -> Result<DeviceProfileTemplate, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
|
||||
diesel::update(device_profile_template::dsl::device_profile_template.find(&dp.id))
|
||||
.set((
|
||||
@ -251,7 +251,7 @@ pub async fn update(dp: DeviceProfileTemplate) -> Result<DeviceProfileTemplate,
|
||||
device_profile_template::abp_rx2_freq.eq(&dp.abp_rx2_freq),
|
||||
device_profile_template::tags.eq(&dp.tags),
|
||||
))
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| error::Error::from_diesel(e, dp.id.clone()))
|
||||
}
|
||||
})
|
||||
@ -264,10 +264,10 @@ pub async fn delete(id: &str) -> Result<(), Error> {
|
||||
task::spawn_blocking({
|
||||
let id = id.to_string();
|
||||
move || -> Result<(), Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let ra =
|
||||
diesel::delete(device_profile_template::dsl::device_profile_template.find(&id))
|
||||
.execute(&c)?;
|
||||
.execute(&mut c)?;
|
||||
if ra == 0 {
|
||||
return Err(error::Error::NotFound(id));
|
||||
}
|
||||
@ -282,10 +282,10 @@ pub async fn delete(id: &str) -> Result<(), Error> {
|
||||
pub async fn get_count() -> Result<i64, Error> {
|
||||
task::spawn_blocking({
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
Ok(device_profile_template::dsl::device_profile_template
|
||||
.select(dsl::count_star())
|
||||
.first(&c)?)
|
||||
.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -294,7 +294,7 @@ pub async fn get_count() -> Result<i64, Error> {
|
||||
pub async fn list(limit: i64, offset: i64) -> Result<Vec<DeviceProfileTemplateListItem>, Error> {
|
||||
task::spawn_blocking({
|
||||
move || -> Result<Vec<DeviceProfileTemplateListItem>, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let items = device_profile_template::dsl::device_profile_template
|
||||
.select((
|
||||
device_profile_template::id,
|
||||
@ -318,7 +318,7 @@ pub async fn list(limit: i64, offset: i64) -> Result<Vec<DeviceProfileTemplateLi
|
||||
))
|
||||
.limit(limit)
|
||||
.offset(offset)
|
||||
.load(&c)?;
|
||||
.load(&mut c)?;
|
||||
Ok(items)
|
||||
}
|
||||
})
|
||||
|
@ -11,7 +11,7 @@ use super::schema::device_queue_item;
|
||||
use lrwn::EUI64;
|
||||
|
||||
#[derive(Queryable, Insertable, AsChangeset, PartialEq, Debug, Clone)]
|
||||
#[table_name = "device_queue_item"]
|
||||
#[diesel(table_name = device_queue_item)]
|
||||
pub struct DeviceQueueItem {
|
||||
pub id: Uuid,
|
||||
pub dev_eui: EUI64,
|
||||
@ -45,10 +45,10 @@ impl Default for DeviceQueueItem {
|
||||
pub async fn enqueue_item(qi: DeviceQueueItem) -> Result<DeviceQueueItem, Error> {
|
||||
let qi = task::spawn_blocking({
|
||||
move || -> Result<DeviceQueueItem, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
diesel::insert_into(device_queue_item::table)
|
||||
.values(&qi)
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, qi.id.to_string()))
|
||||
}
|
||||
})
|
||||
@ -61,10 +61,10 @@ pub async fn get_item(id: &Uuid) -> Result<DeviceQueueItem, Error> {
|
||||
task::spawn_blocking({
|
||||
let id = *id;
|
||||
move || -> Result<DeviceQueueItem, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let qi = device_queue_item::dsl::device_queue_item
|
||||
.find(&id)
|
||||
.first(&c)
|
||||
.first(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, id.to_string()))?;
|
||||
Ok(qi)
|
||||
}
|
||||
@ -75,14 +75,14 @@ pub async fn get_item(id: &Uuid) -> Result<DeviceQueueItem, Error> {
|
||||
pub async fn update_item(qi: DeviceQueueItem) -> Result<DeviceQueueItem, Error> {
|
||||
let qi = task::spawn_blocking({
|
||||
move || -> Result<DeviceQueueItem, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
diesel::update(device_queue_item::dsl::device_queue_item.find(&qi.id))
|
||||
.set((
|
||||
device_queue_item::is_pending.eq(&qi.is_pending),
|
||||
device_queue_item::f_cnt_down.eq(&qi.f_cnt_down),
|
||||
device_queue_item::timeout_after.eq(&qi.timeout_after),
|
||||
))
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, qi.id.to_string()))
|
||||
}
|
||||
})
|
||||
@ -95,9 +95,9 @@ pub async fn delete_item(id: &Uuid) -> Result<(), Error> {
|
||||
task::spawn_blocking({
|
||||
let id = *id;
|
||||
move || -> Result<(), Error> {
|
||||
let c = get_db_conn()?;
|
||||
let ra =
|
||||
diesel::delete(device_queue_item::dsl::device_queue_item.find(&id)).execute(&c)?;
|
||||
let mut c = get_db_conn()?;
|
||||
let ra = diesel::delete(device_queue_item::dsl::device_queue_item.find(&id))
|
||||
.execute(&mut c)?;
|
||||
if ra == 0 {
|
||||
return Err(Error::NotFound(id.to_string()));
|
||||
}
|
||||
@ -114,12 +114,12 @@ pub async fn get_next_for_dev_eui(dev_eui: &EUI64) -> Result<(DeviceQueueItem, b
|
||||
task::spawn_blocking({
|
||||
let dev_eui = *dev_eui;
|
||||
move || -> Result<(DeviceQueueItem, bool), Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let items: Vec<DeviceQueueItem> = device_queue_item::dsl::device_queue_item
|
||||
.filter(device_queue_item::dev_eui.eq(&dev_eui))
|
||||
.order_by(device_queue_item::created_at)
|
||||
.limit(2)
|
||||
.load(&c)
|
||||
.load(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, dev_eui.to_string()))?;
|
||||
|
||||
// Return NotFound on empty Vec.
|
||||
@ -148,11 +148,11 @@ pub async fn get_for_dev_eui(dev_eui: &EUI64) -> Result<Vec<DeviceQueueItem>, Er
|
||||
task::spawn_blocking({
|
||||
let dev_eui = *dev_eui;
|
||||
move || -> Result<Vec<DeviceQueueItem>, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let items = device_queue_item::dsl::device_queue_item
|
||||
.filter(device_queue_item::dev_eui.eq(&dev_eui))
|
||||
.order_by(device_queue_item::created_at)
|
||||
.load(&c)
|
||||
.load(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, dev_eui.to_string()))?;
|
||||
Ok(items)
|
||||
}
|
||||
@ -164,12 +164,12 @@ pub async fn flush_for_dev_eui(dev_eui: &EUI64) -> Result<(), Error> {
|
||||
let count = task::spawn_blocking({
|
||||
let dev_eui = *dev_eui;
|
||||
move || -> Result<usize, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
diesel::delete(
|
||||
device_queue_item::dsl::device_queue_item
|
||||
.filter(device_queue_item::dev_eui.eq(&dev_eui)),
|
||||
)
|
||||
.execute(&c)
|
||||
.execute(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, dev_eui.to_string()))
|
||||
}
|
||||
})
|
||||
@ -182,14 +182,14 @@ pub async fn get_pending_for_dev_eui(dev_eui: &EUI64) -> Result<DeviceQueueItem,
|
||||
task::spawn_blocking({
|
||||
let dev_eui = *dev_eui;
|
||||
move || -> Result<DeviceQueueItem, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let qi = device_queue_item::dsl::device_queue_item
|
||||
.filter(
|
||||
device_queue_item::dev_eui
|
||||
.eq(&dev_eui)
|
||||
.and(device_queue_item::is_pending.eq(true)),
|
||||
)
|
||||
.first(&c)
|
||||
.first(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, dev_eui.to_string()))?;
|
||||
Ok(qi)
|
||||
}
|
||||
|
@ -1,14 +1,14 @@
|
||||
use std::collections::HashMap;
|
||||
use std::io::Write;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use diesel::pg::types::sql_types::Jsonb;
|
||||
use diesel::backend;
|
||||
use diesel::pg::Pg;
|
||||
use diesel::sql_types::Jsonb;
|
||||
use diesel::{deserialize, serialize};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, AsExpression, FromSqlRow)]
|
||||
#[sql_type = "Jsonb"]
|
||||
#[diesel(sql_type = Jsonb)]
|
||||
pub struct KeyValue(HashMap<String, String>);
|
||||
|
||||
impl KeyValue {
|
||||
@ -37,22 +37,22 @@ impl DerefMut for KeyValue {
|
||||
}
|
||||
|
||||
impl deserialize::FromSql<Jsonb, Pg> for KeyValue {
|
||||
fn from_sql(bytes: Option<&[u8]>) -> deserialize::Result<Self> {
|
||||
let value = <serde_json::Value as deserialize::FromSql<Jsonb, Pg>>::from_sql(bytes)?;
|
||||
fn from_sql(value: backend::RawValue<Pg>) -> deserialize::Result<Self> {
|
||||
let value = <serde_json::Value as deserialize::FromSql<Jsonb, Pg>>::from_sql(value)?;
|
||||
let kv: HashMap<String, String> = serde_json::from_value(value)?;
|
||||
Ok(KeyValue(kv))
|
||||
}
|
||||
}
|
||||
|
||||
impl serialize::ToSql<Jsonb, Pg> for KeyValue {
|
||||
fn to_sql<W: Write>(&self, out: &mut serialize::Output<W, Pg>) -> serialize::Result {
|
||||
fn to_sql<'b>(&'b self, out: &mut serialize::Output<'b, '_, Pg>) -> serialize::Result {
|
||||
let value = serde_json::to_value(&self.0)?;
|
||||
<serde_json::Value as serialize::ToSql<Jsonb, Pg>>::to_sql(&value, out)
|
||||
<serde_json::Value as serialize::ToSql<Jsonb, Pg>>::to_sql(&value, &mut out.reborrow())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, AsExpression, FromSqlRow, PartialEq)]
|
||||
#[sql_type = "Jsonb"]
|
||||
#[diesel(sql_type = Jsonb)]
|
||||
pub struct Measurements(HashMap<String, Measurement>);
|
||||
|
||||
impl Measurements {
|
||||
@ -81,17 +81,17 @@ impl DerefMut for Measurements {
|
||||
}
|
||||
|
||||
impl deserialize::FromSql<Jsonb, Pg> for Measurements {
|
||||
fn from_sql(bytes: Option<&[u8]>) -> deserialize::Result<Self> {
|
||||
let value = <serde_json::Value as deserialize::FromSql<Jsonb, Pg>>::from_sql(bytes)?;
|
||||
fn from_sql(value: backend::RawValue<Pg>) -> deserialize::Result<Self> {
|
||||
let value = <serde_json::Value as deserialize::FromSql<Jsonb, Pg>>::from_sql(value)?;
|
||||
let kv: HashMap<String, Measurement> = serde_json::from_value(value)?;
|
||||
Ok(Measurements::new(kv))
|
||||
}
|
||||
}
|
||||
|
||||
impl serialize::ToSql<Jsonb, Pg> for Measurements {
|
||||
fn to_sql<W: Write>(&self, out: &mut serialize::Output<W, Pg>) -> serialize::Result {
|
||||
fn to_sql<'b>(&self, out: &mut serialize::Output<'b, '_, Pg>) -> serialize::Result {
|
||||
let value = serde_json::to_value(&self.0)?;
|
||||
<serde_json::Value as serialize::ToSql<Jsonb, Pg>>::to_sql(&value, out)
|
||||
<serde_json::Value as serialize::ToSql<Jsonb, Pg>>::to_sql(&value, &mut out.reborrow())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ use super::schema::{gateway, tenant};
|
||||
use super::{error::Error, fields, get_db_conn};
|
||||
|
||||
#[derive(Queryable, Insertable, AsChangeset, PartialEq, Debug)]
|
||||
#[table_name = "gateway"]
|
||||
#[diesel(table_name = gateway)]
|
||||
pub struct Gateway {
|
||||
pub gateway_id: EUI64,
|
||||
pub tenant_id: Uuid,
|
||||
@ -74,11 +74,11 @@ pub struct Filters {
|
||||
|
||||
#[derive(QueryableByName, PartialEq, Debug)]
|
||||
pub struct GatewaysActiveInactive {
|
||||
#[sql_type = "diesel::sql_types::BigInt"]
|
||||
#[diesel(sql_type = diesel::sql_types::BigInt)]
|
||||
pub never_seen_count: i64,
|
||||
#[sql_type = "diesel::sql_types::BigInt"]
|
||||
#[diesel(sql_type = diesel::sql_types::BigInt)]
|
||||
pub active_count: i64,
|
||||
#[sql_type = "diesel::sql_types::BigInt"]
|
||||
#[diesel(sql_type = diesel::sql_types::BigInt)]
|
||||
pub inactive_count: i64,
|
||||
}
|
||||
|
||||
@ -109,13 +109,13 @@ pub async fn create(gw: Gateway) -> Result<Gateway, Error> {
|
||||
gw.validate()?;
|
||||
let gw = task::spawn_blocking({
|
||||
move || -> Result<Gateway, Error> {
|
||||
let c = get_db_conn()?;
|
||||
c.transaction::<Gateway, Error, _>(|| {
|
||||
let mut c = get_db_conn()?;
|
||||
c.transaction::<Gateway, Error, _>(|c| {
|
||||
// use for_update to lock the tenant.
|
||||
let t: super::tenant::Tenant = tenant::dsl::tenant
|
||||
.find(&gw.tenant_id)
|
||||
.for_update()
|
||||
.get_result(&c)
|
||||
.get_result(c)
|
||||
.map_err(|e| Error::from_diesel(e, gw.tenant_id.to_string()))?;
|
||||
|
||||
if !t.can_have_gateways {
|
||||
@ -125,7 +125,7 @@ pub async fn create(gw: Gateway) -> Result<Gateway, Error> {
|
||||
let gw_count: i64 = gateway::dsl::gateway
|
||||
.select(dsl::count_star())
|
||||
.filter(gateway::dsl::tenant_id.eq(&gw.tenant_id))
|
||||
.first(&c)?;
|
||||
.first(c)?;
|
||||
|
||||
if t.max_gateway_count != 0 && gw_count as i32 >= t.max_gateway_count {
|
||||
return Err(Error::NotAllowed(
|
||||
@ -135,7 +135,7 @@ pub async fn create(gw: Gateway) -> Result<Gateway, Error> {
|
||||
|
||||
diesel::insert_into(gateway::table)
|
||||
.values(&gw)
|
||||
.get_result(&c)
|
||||
.get_result(c)
|
||||
.map_err(|e| Error::from_diesel(e, gw.gateway_id.to_string()))
|
||||
})
|
||||
}
|
||||
@ -152,10 +152,10 @@ pub async fn get(gateway_id: &EUI64) -> Result<Gateway, Error> {
|
||||
task::spawn_blocking({
|
||||
let gateway_id = *gateway_id;
|
||||
move || -> Result<Gateway, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let gw = gateway::dsl::gateway
|
||||
.find(&gateway_id)
|
||||
.first(&c)
|
||||
.first(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, gateway_id.to_string()))?;
|
||||
Ok(gw)
|
||||
}
|
||||
@ -167,7 +167,7 @@ pub async fn update(gw: Gateway) -> Result<Gateway, Error> {
|
||||
gw.validate()?;
|
||||
let gw = task::spawn_blocking({
|
||||
move || -> Result<Gateway, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
diesel::update(gateway::dsl::gateway.find(&gw.gateway_id))
|
||||
.set((
|
||||
gateway::updated_at.eq(Utc::now()),
|
||||
@ -179,7 +179,7 @@ pub async fn update(gw: Gateway) -> Result<Gateway, Error> {
|
||||
gateway::stats_interval_secs.eq(&gw.stats_interval_secs),
|
||||
gateway::tags.eq(&gw.tags),
|
||||
))
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, gw.gateway_id.to_string()))
|
||||
}
|
||||
})
|
||||
@ -196,13 +196,13 @@ pub async fn update_state(id: &EUI64, props: &HashMap<String, String>) -> Result
|
||||
let id = *id;
|
||||
let props = fields::KeyValue::new(props.clone());
|
||||
move || -> Result<Gateway, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let gw: Gateway = diesel::update(gateway::dsl::gateway.find(&id))
|
||||
.set((
|
||||
gateway::last_seen_at.eq(Some(Utc::now())),
|
||||
gateway::properties.eq(props),
|
||||
))
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, id.to_string()))?;
|
||||
|
||||
Ok(gw)
|
||||
@ -229,7 +229,7 @@ pub async fn update_state_and_loc(
|
||||
let id = *id;
|
||||
let props = fields::KeyValue::new(props.clone());
|
||||
move || -> Result<Gateway, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let gw: Gateway = diesel::update(gateway::dsl::gateway.find(&id))
|
||||
.set((
|
||||
gateway::last_seen_at.eq(Some(Utc::now())),
|
||||
@ -238,7 +238,7 @@ pub async fn update_state_and_loc(
|
||||
gateway::altitude.eq(alt),
|
||||
gateway::properties.eq(props),
|
||||
))
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, id.to_string()))?;
|
||||
|
||||
Ok(gw)
|
||||
@ -259,10 +259,10 @@ pub async fn update_tls_cert(id: &EUI64, cert: &[u8]) -> Result<Gateway, Error>
|
||||
let id = *id;
|
||||
let cert = cert.to_vec();
|
||||
move || -> Result<Gateway, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let gw: Gateway = diesel::update(gateway::dsl::gateway.find(&id))
|
||||
.set(gateway::tls_certificate.eq(cert))
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, id.to_string()))?;
|
||||
Ok(gw)
|
||||
}
|
||||
@ -281,8 +281,8 @@ pub async fn delete(gateway_id: &EUI64) -> Result<(), Error> {
|
||||
task::spawn_blocking({
|
||||
let gateway_id = *gateway_id;
|
||||
move || -> Result<(), Error> {
|
||||
let c = get_db_conn()?;
|
||||
let ra = diesel::delete(gateway::dsl::gateway.find(&gateway_id)).execute(&c)?;
|
||||
let mut c = get_db_conn()?;
|
||||
let ra = diesel::delete(gateway::dsl::gateway.find(&gateway_id)).execute(&mut c)?;
|
||||
if ra == 0 {
|
||||
return Err(Error::NotFound(gateway_id.to_string()));
|
||||
}
|
||||
@ -301,7 +301,7 @@ pub async fn get_count(filters: &Filters) -> Result<i64, Error> {
|
||||
task::spawn_blocking({
|
||||
let filters = filters.clone();
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = gateway::dsl::gateway.select(dsl::count_star()).into_boxed();
|
||||
|
||||
if let Some(tenant_id) = &filters.tenant_id {
|
||||
@ -312,7 +312,7 @@ pub async fn get_count(filters: &Filters) -> Result<i64, Error> {
|
||||
q = q.filter(gateway::dsl::name.ilike(format!("%{}%", search)));
|
||||
}
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(q.first(&mut c)?)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -326,7 +326,7 @@ pub async fn list(
|
||||
task::spawn_blocking({
|
||||
let filters = filters.clone();
|
||||
move || -> Result<Vec<GatewayListItem>, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = gateway::dsl::gateway
|
||||
.select((
|
||||
gateway::tenant_id,
|
||||
@ -355,7 +355,7 @@ pub async fn list(
|
||||
.order_by(gateway::dsl::name)
|
||||
.limit(limit)
|
||||
.offset(offset)
|
||||
.load(&c)?;
|
||||
.load(&mut c)?;
|
||||
Ok(items)
|
||||
}
|
||||
})
|
||||
@ -366,7 +366,7 @@ pub async fn get_meta(gateway_id: &EUI64) -> Result<GatewayMeta, Error> {
|
||||
task::spawn_blocking({
|
||||
let gateway_id = *gateway_id;
|
||||
move || -> Result<GatewayMeta, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let meta = gateway::dsl::gateway
|
||||
.inner_join(tenant::table)
|
||||
.select((
|
||||
@ -378,7 +378,7 @@ pub async fn get_meta(gateway_id: &EUI64) -> Result<GatewayMeta, Error> {
|
||||
tenant::private_gateways,
|
||||
))
|
||||
.filter(gateway::dsl::gateway_id.eq(&gateway_id))
|
||||
.first(&c)
|
||||
.first(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, gateway_id.to_string()))?;
|
||||
|
||||
Ok(meta)
|
||||
@ -393,7 +393,7 @@ pub async fn get_active_inactive(
|
||||
task::spawn_blocking({
|
||||
let tenant_id = *tenant_id;
|
||||
move || -> Result<GatewaysActiveInactive, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let ai: GatewaysActiveInactive = diesel::sql_query(r#"
|
||||
select
|
||||
coalesce(sum(case when last_seen_at is null then 1 end), 0) as never_seen_count,
|
||||
@ -403,7 +403,7 @@ pub async fn get_active_inactive(
|
||||
gateway
|
||||
where
|
||||
$1 is null or tenant_id = $1
|
||||
"#).bind::<diesel::sql_types::Nullable<diesel::pg::types::sql_types::Uuid>, _>(tenant_id).get_result(&c)?;
|
||||
"#).bind::<diesel::sql_types::Nullable<diesel::sql_types::Uuid>, _>(tenant_id).get_result(&mut c)?;
|
||||
Ok(ai)
|
||||
}
|
||||
}).await?
|
||||
|
@ -5,7 +5,7 @@ use anyhow::Context;
|
||||
use anyhow::Result;
|
||||
use diesel::pg::PgConnection;
|
||||
use diesel::r2d2::{ConnectionManager, Pool, PooledConnection};
|
||||
use diesel_migrations::embed_migrations;
|
||||
use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness};
|
||||
use tracing::info;
|
||||
|
||||
use crate::config;
|
||||
@ -40,7 +40,7 @@ lazy_static! {
|
||||
static ref REDIS_POOL: RwLock<Option<RedisPool>> = RwLock::new(None);
|
||||
}
|
||||
|
||||
embed_migrations!("./migrations");
|
||||
pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("./migrations");
|
||||
|
||||
pub enum RedisPool {
|
||||
Client(Pool<redis::Client>),
|
||||
@ -87,10 +87,12 @@ pub async fn setup() -> Result<()> {
|
||||
.build(ConnectionManager::new(&conf.postgresql.dsn))
|
||||
.context("Setup PostgreSQL connection pool error")?;
|
||||
set_db_pool(pg_pool);
|
||||
let pg_conn = get_db_conn()?;
|
||||
let mut pg_conn = get_db_conn()?;
|
||||
|
||||
info!("Applying schema migrations");
|
||||
embedded_migrations::run(&pg_conn).context("Run migrations error")?;
|
||||
pg_conn
|
||||
.run_pending_migrations(MIGRATIONS)
|
||||
.map_err(|e| anyhow!("{}", e))?;
|
||||
|
||||
info!("Setting up Redis client");
|
||||
if conf.redis.cluster {
|
||||
@ -158,20 +160,11 @@ pub fn redis_key(s: String) -> String {
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn reset_db() -> Result<()> {
|
||||
use diesel_migrations::{revert_latest_migration, run_pending_migrations};
|
||||
let conn = get_db_conn()?;
|
||||
|
||||
loop {
|
||||
match revert_latest_migration(&conn) {
|
||||
Ok(_) => {}
|
||||
Err(_) => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// and forward again
|
||||
run_pending_migrations(&conn)?;
|
||||
let mut conn = get_db_conn()?;
|
||||
conn.revert_all_migrations(MIGRATIONS)
|
||||
.map_err(|e| anyhow!("{}", e))?;
|
||||
conn.run_pending_migrations(MIGRATIONS)
|
||||
.map_err(|e| anyhow!("{}", e))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ use crate::downlink::classb;
|
||||
use crate::{config, gpstime::ToDateTime, gpstime::ToGpsTime};
|
||||
|
||||
#[derive(Clone, Queryable, Insertable, AsChangeset, Debug, PartialEq)]
|
||||
#[table_name = "multicast_group"]
|
||||
#[diesel(table_name = multicast_group)]
|
||||
pub struct MulticastGroup {
|
||||
pub id: Uuid,
|
||||
pub application_id: Uuid,
|
||||
@ -83,7 +83,7 @@ pub struct Filters {
|
||||
}
|
||||
|
||||
#[derive(Clone, Queryable, QueryableByName, Insertable, AsChangeset, Debug, PartialEq)]
|
||||
#[table_name = "multicast_group_queue_item"]
|
||||
#[diesel(table_name = multicast_group_queue_item)]
|
||||
pub struct MulticastGroupQueueItem {
|
||||
pub id: Uuid,
|
||||
pub created_at: DateTime<Utc>,
|
||||
@ -118,10 +118,10 @@ pub async fn create(mg: MulticastGroup) -> Result<MulticastGroup, Error> {
|
||||
mg.validate()?;
|
||||
let mg = task::spawn_blocking({
|
||||
move || -> Result<MulticastGroup, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
diesel::insert_into(multicast_group::table)
|
||||
.values(&mg)
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, mg.id.to_string()))
|
||||
}
|
||||
})
|
||||
@ -134,10 +134,10 @@ pub async fn get(id: &Uuid) -> Result<MulticastGroup, Error> {
|
||||
task::spawn_blocking({
|
||||
let id = *id;
|
||||
move || -> Result<MulticastGroup, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
multicast_group::dsl::multicast_group
|
||||
.find(&id)
|
||||
.first(&c)
|
||||
.first(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, id.to_string()))
|
||||
}
|
||||
})
|
||||
@ -148,7 +148,7 @@ pub async fn update(mg: MulticastGroup) -> Result<MulticastGroup, Error> {
|
||||
mg.validate()?;
|
||||
let mg = task::spawn_blocking({
|
||||
move || -> Result<MulticastGroup, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
|
||||
diesel::update(multicast_group::dsl::multicast_group.find(&mg.id))
|
||||
.set((
|
||||
@ -164,7 +164,7 @@ pub async fn update(mg: MulticastGroup) -> Result<MulticastGroup, Error> {
|
||||
multicast_group::frequency.eq(&mg.frequency),
|
||||
multicast_group::class_b_ping_slot_period.eq(&mg.class_b_ping_slot_period),
|
||||
))
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, mg.id.to_string()))
|
||||
}
|
||||
})
|
||||
@ -177,8 +177,9 @@ pub async fn delete(id: &Uuid) -> Result<(), Error> {
|
||||
task::spawn_blocking({
|
||||
let id = *id;
|
||||
move || -> Result<(), Error> {
|
||||
let c = get_db_conn()?;
|
||||
let ra = diesel::delete(multicast_group::dsl::multicast_group.find(&id)).execute(&c)?;
|
||||
let mut c = get_db_conn()?;
|
||||
let ra =
|
||||
diesel::delete(multicast_group::dsl::multicast_group.find(&id)).execute(&mut c)?;
|
||||
if ra == 0 {
|
||||
return Err(Error::NotFound(id.to_string()));
|
||||
}
|
||||
@ -194,7 +195,7 @@ pub async fn get_count(filters: &Filters) -> Result<i64, Error> {
|
||||
task::spawn_blocking({
|
||||
let filters = filters.clone();
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = multicast_group::dsl::multicast_group
|
||||
.select(dsl::count_star())
|
||||
.into_boxed();
|
||||
@ -207,7 +208,8 @@ pub async fn get_count(filters: &Filters) -> Result<i64, Error> {
|
||||
q = q.filter(multicast_group::dsl::name.ilike(format!("%{}%", search)));
|
||||
}
|
||||
|
||||
q.first(&c).map_err(|e| Error::from_diesel(e, "".into()))
|
||||
q.first(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, "".into()))
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -221,7 +223,7 @@ pub async fn list(
|
||||
task::spawn_blocking({
|
||||
let filters = filters.clone();
|
||||
move || -> Result<Vec<MulticastGroupListItem>, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = multicast_group::dsl::multicast_group
|
||||
.select((
|
||||
multicast_group::id,
|
||||
@ -244,7 +246,7 @@ pub async fn list(
|
||||
q.order_by(multicast_group::dsl::name)
|
||||
.limit(limit)
|
||||
.offset(offset)
|
||||
.load(&c)
|
||||
.load(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, "".into()))
|
||||
}
|
||||
})
|
||||
@ -256,18 +258,18 @@ pub async fn add_device(group_id: &Uuid, dev_eui: &EUI64) -> Result<(), Error> {
|
||||
let group_id = *group_id;
|
||||
let dev_eui = *dev_eui;
|
||||
move || -> Result<(), Error> {
|
||||
let c = get_db_conn()?;
|
||||
c.transaction::<(), Error, _>(|| {
|
||||
let mut c = get_db_conn()?;
|
||||
c.transaction::<(), Error, _>(|c| {
|
||||
let d: super::device::Device = device::dsl::device
|
||||
.find(&dev_eui)
|
||||
.for_update()
|
||||
.get_result(&c)
|
||||
.get_result(c)
|
||||
.map_err(|e| Error::from_diesel(e, dev_eui.to_string()))?;
|
||||
|
||||
let mg: MulticastGroup = multicast_group::dsl::multicast_group
|
||||
.find(&group_id)
|
||||
.for_update()
|
||||
.get_result(&c)
|
||||
.get_result(c)
|
||||
.map_err(|e| Error::from_diesel(e, group_id.to_string()))?;
|
||||
|
||||
if d.application_id != mg.application_id {
|
||||
@ -281,7 +283,7 @@ pub async fn add_device(group_id: &Uuid, dev_eui: &EUI64) -> Result<(), Error> {
|
||||
multicast_group_device::dev_eui.eq(&dev_eui),
|
||||
multicast_group_device::created_at.eq(Utc::now()),
|
||||
))
|
||||
.execute(&c)
|
||||
.execute(c)
|
||||
.map_err(|e| Error::from_diesel(e, "".into()))?;
|
||||
Ok(())
|
||||
})
|
||||
@ -297,13 +299,13 @@ pub async fn remove_device(group_id: &Uuid, dev_eui: &EUI64) -> Result<(), Error
|
||||
let group_id = *group_id;
|
||||
let dev_eui = *dev_eui;
|
||||
move || -> Result<(), Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let ra = diesel::delete(
|
||||
multicast_group_device::dsl::multicast_group_device
|
||||
.filter(multicast_group_device::multicast_group_id.eq(&group_id))
|
||||
.filter(multicast_group_device::dev_eui.eq(&dev_eui)),
|
||||
)
|
||||
.execute(&c)?;
|
||||
.execute(&mut c)?;
|
||||
if ra == 0 {
|
||||
return Err(Error::NotFound(format!(
|
||||
"multicast-group: {}, device: {}",
|
||||
@ -322,11 +324,11 @@ pub async fn get_dev_euis(group_id: &Uuid) -> Result<Vec<EUI64>, Error> {
|
||||
task::spawn_blocking({
|
||||
let group_id = *group_id;
|
||||
move || -> Result<Vec<EUI64>, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
multicast_group_device::dsl::multicast_group_device
|
||||
.select(multicast_group_device::dev_eui)
|
||||
.filter(multicast_group_device::dsl::multicast_group_id.eq(&group_id))
|
||||
.load(&c)
|
||||
.load(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, group_id.to_string()))
|
||||
}
|
||||
})
|
||||
@ -344,14 +346,14 @@ pub async fn enqueue(
|
||||
let (ids, f_cnt) = task::spawn_blocking({
|
||||
let gateway_ids = gateway_ids.to_vec();
|
||||
move || -> Result<(Vec<Uuid>, u32), Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let conf = config::get();
|
||||
c.transaction::<(Vec<Uuid>, u32), Error, _>(|| {
|
||||
c.transaction::<(Vec<Uuid>, u32), Error, _>(|c| {
|
||||
let mut ids: Vec<Uuid> = Vec::new();
|
||||
let mg: MulticastGroup = multicast_group::dsl::multicast_group
|
||||
.find(&qi.multicast_group_id)
|
||||
.for_update()
|
||||
.get_result(&c)
|
||||
.get_result(c)
|
||||
.map_err(|e| Error::from_diesel(e, qi.multicast_group_id.to_string()))?;
|
||||
|
||||
match mg.group_type.as_ref() {
|
||||
@ -373,7 +375,7 @@ pub async fn enqueue(
|
||||
multicast_group_queue_item::dsl::multicast_group_id
|
||||
.eq(&qi.multicast_group_id),
|
||||
)
|
||||
.first(&c)?;
|
||||
.first(c)?;
|
||||
|
||||
// Get timestamp after which we must generate the next ping-slot.
|
||||
let ping_slot_after_gps_time = match res {
|
||||
@ -412,7 +414,7 @@ pub async fn enqueue(
|
||||
let qi: MulticastGroupQueueItem =
|
||||
diesel::insert_into(multicast_group_queue_item::table)
|
||||
.values(&qi)
|
||||
.get_result(&c)
|
||||
.get_result(c)
|
||||
.map_err(|e| Error::from_diesel(e, mg.id.to_string()))?;
|
||||
ids.push(qi.id);
|
||||
}
|
||||
@ -428,7 +430,7 @@ pub async fn enqueue(
|
||||
multicast_group_queue_item::dsl::multicast_group_id
|
||||
.eq(&qi.multicast_group_id),
|
||||
)
|
||||
.first(&c)?;
|
||||
.first(c)?;
|
||||
|
||||
let mut scheduler_run_after_ts = match res {
|
||||
Some(v) => {
|
||||
@ -470,7 +472,7 @@ pub async fn enqueue(
|
||||
let qi: MulticastGroupQueueItem =
|
||||
diesel::insert_into(multicast_group_queue_item::table)
|
||||
.values(&qi)
|
||||
.get_result(&c)
|
||||
.get_result(c)
|
||||
.map_err(|e| Error::from_diesel(e, mg.id.to_string()))?;
|
||||
ids.push(qi.id);
|
||||
|
||||
@ -494,7 +496,7 @@ pub async fn enqueue(
|
||||
|
||||
diesel::update(multicast_group::dsl::multicast_group.find(&qi.multicast_group_id))
|
||||
.set(multicast_group::f_cnt.eq(mg.f_cnt + 1))
|
||||
.execute(&c)
|
||||
.execute(c)
|
||||
.map_err(|e| Error::from_diesel(e, qi.multicast_group_id.to_string()))?;
|
||||
|
||||
// Return value before it was incremented
|
||||
@ -511,10 +513,10 @@ pub async fn get_queue_item(id: &Uuid) -> Result<MulticastGroupQueueItem, Error>
|
||||
task::spawn_blocking({
|
||||
let id = *id;
|
||||
move || -> Result<MulticastGroupQueueItem, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
multicast_group_queue_item::dsl::multicast_group_queue_item
|
||||
.find(&id)
|
||||
.first(&c)
|
||||
.first(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, id.to_string()))
|
||||
}
|
||||
})
|
||||
@ -525,11 +527,11 @@ pub async fn delete_queue_item(id: &Uuid) -> Result<(), Error> {
|
||||
task::spawn_blocking({
|
||||
let id = *id;
|
||||
move || -> Result<(), Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let ra = diesel::delete(
|
||||
multicast_group_queue_item::dsl::multicast_group_queue_item.find(&id),
|
||||
)
|
||||
.execute(&c)?;
|
||||
.execute(&mut c)?;
|
||||
if ra == 0 {
|
||||
return Err(Error::NotFound(id.to_string()));
|
||||
}
|
||||
@ -545,12 +547,12 @@ pub async fn flush_queue(multicast_group_id: &Uuid) -> Result<(), Error> {
|
||||
task::spawn_blocking({
|
||||
let multicast_group_id = *multicast_group_id;
|
||||
move || -> Result<(), Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let _ = diesel::delete(
|
||||
multicast_group_queue_item::dsl::multicast_group_queue_item
|
||||
.filter(multicast_group_queue_item::multicast_group_id.eq(&multicast_group_id)),
|
||||
)
|
||||
.execute(&c)
|
||||
.execute(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, multicast_group_id.to_string()))?;
|
||||
Ok(())
|
||||
}
|
||||
@ -564,11 +566,11 @@ pub async fn get_queue(multicast_group_id: &Uuid) -> Result<Vec<MulticastGroupQu
|
||||
task::spawn_blocking({
|
||||
let multicast_group_id = *multicast_group_id;
|
||||
move || -> Result<Vec<MulticastGroupQueueItem>, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
multicast_group_queue_item::dsl::multicast_group_queue_item
|
||||
.filter(multicast_group_queue_item::dsl::multicast_group_id.eq(&multicast_group_id))
|
||||
.order_by(multicast_group_queue_item::created_at)
|
||||
.load(&c)
|
||||
.load(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, multicast_group_id.to_string()))
|
||||
}
|
||||
})
|
||||
@ -578,8 +580,8 @@ pub async fn get_queue(multicast_group_id: &Uuid) -> Result<Vec<MulticastGroupQu
|
||||
pub async fn get_schedulable_queue_items(limit: usize) -> Result<Vec<MulticastGroupQueueItem>> {
|
||||
task::spawn_blocking({
|
||||
move || -> Result<Vec<MulticastGroupQueueItem>> {
|
||||
let c = get_db_conn()?;
|
||||
c.transaction::<Vec<MulticastGroupQueueItem>, Error, _>(|| {
|
||||
let mut c = get_db_conn()?;
|
||||
c.transaction::<Vec<MulticastGroupQueueItem>, Error, _>(|c| {
|
||||
let conf = config::get();
|
||||
diesel::sql_query(
|
||||
r#"
|
||||
@ -607,7 +609,7 @@ pub async fn get_schedulable_queue_items(limit: usize) -> Result<Vec<MulticastGr
|
||||
.bind::<diesel::sql_types::Timestamptz, _>(
|
||||
Utc::now() + Duration::from_std(2 * conf.network.scheduler.interval).unwrap(),
|
||||
)
|
||||
.load(&c)
|
||||
.load(c)
|
||||
.map_err(|e| Error::from_diesel(e, "".into()))
|
||||
})
|
||||
.context("Get schedulable multicast-group queue items")
|
||||
|
@ -1,4 +1,6 @@
|
||||
table! {
|
||||
// @generated automatically by Diesel CLI.
|
||||
|
||||
diesel::table! {
|
||||
api_key (id) {
|
||||
id -> Uuid,
|
||||
created_at -> Timestamptz,
|
||||
@ -8,7 +10,7 @@ table! {
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
diesel::table! {
|
||||
application (id) {
|
||||
id -> Uuid,
|
||||
tenant_id -> Uuid,
|
||||
@ -20,7 +22,7 @@ table! {
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
diesel::table! {
|
||||
application_integration (application_id, kind) {
|
||||
application_id -> Uuid,
|
||||
kind -> Varchar,
|
||||
@ -30,7 +32,7 @@ table! {
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
diesel::table! {
|
||||
device (dev_eui) {
|
||||
dev_eui -> Bytea,
|
||||
application_id -> Uuid,
|
||||
@ -57,19 +59,19 @@ table! {
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
diesel::table! {
|
||||
device_keys (dev_eui) {
|
||||
dev_eui -> Bytea,
|
||||
created_at -> Timestamptz,
|
||||
updated_at -> Timestamptz,
|
||||
nwk_key -> Bytea,
|
||||
app_key -> Bytea,
|
||||
dev_nonces -> Array<Int4>,
|
||||
dev_nonces -> Array<Nullable<Int4>>,
|
||||
join_nonce -> Int4,
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
diesel::table! {
|
||||
device_profile (id) {
|
||||
id -> Uuid,
|
||||
tenant_id -> Uuid,
|
||||
@ -103,7 +105,7 @@ table! {
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
diesel::table! {
|
||||
device_profile_template (id) {
|
||||
id -> Text,
|
||||
created_at -> Timestamptz,
|
||||
@ -138,7 +140,7 @@ table! {
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
diesel::table! {
|
||||
device_queue_item (id) {
|
||||
id -> Uuid,
|
||||
dev_eui -> Bytea,
|
||||
@ -152,7 +154,7 @@ table! {
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
diesel::table! {
|
||||
gateway (gateway_id) {
|
||||
gateway_id -> Bytea,
|
||||
tenant_id -> Uuid,
|
||||
@ -171,7 +173,7 @@ table! {
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
diesel::table! {
|
||||
multicast_group (id) {
|
||||
id -> Uuid,
|
||||
application_id -> Uuid,
|
||||
@ -190,7 +192,7 @@ table! {
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
diesel::table! {
|
||||
multicast_group_device (multicast_group_id, dev_eui) {
|
||||
multicast_group_id -> Uuid,
|
||||
dev_eui -> Bytea,
|
||||
@ -198,7 +200,7 @@ table! {
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
diesel::table! {
|
||||
multicast_group_queue_item (id) {
|
||||
id -> Uuid,
|
||||
created_at -> Timestamptz,
|
||||
@ -212,7 +214,7 @@ table! {
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
diesel::table! {
|
||||
tenant (id) {
|
||||
id -> Uuid,
|
||||
created_at -> Timestamptz,
|
||||
@ -226,7 +228,7 @@ table! {
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
diesel::table! {
|
||||
tenant_user (tenant_id, user_id) {
|
||||
tenant_id -> Uuid,
|
||||
user_id -> Uuid,
|
||||
@ -238,7 +240,7 @@ table! {
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
diesel::table! {
|
||||
user (id) {
|
||||
id -> Uuid,
|
||||
external_id -> Nullable<Text>,
|
||||
@ -253,24 +255,24 @@ table! {
|
||||
}
|
||||
}
|
||||
|
||||
joinable!(api_key -> tenant (tenant_id));
|
||||
joinable!(application -> tenant (tenant_id));
|
||||
joinable!(application_integration -> application (application_id));
|
||||
joinable!(device -> application (application_id));
|
||||
joinable!(device -> device_profile (device_profile_id));
|
||||
joinable!(device_keys -> device (dev_eui));
|
||||
joinable!(device_profile -> tenant (tenant_id));
|
||||
joinable!(device_queue_item -> device (dev_eui));
|
||||
joinable!(gateway -> tenant (tenant_id));
|
||||
joinable!(multicast_group -> application (application_id));
|
||||
joinable!(multicast_group_device -> device (dev_eui));
|
||||
joinable!(multicast_group_device -> multicast_group (multicast_group_id));
|
||||
joinable!(multicast_group_queue_item -> gateway (gateway_id));
|
||||
joinable!(multicast_group_queue_item -> multicast_group (multicast_group_id));
|
||||
joinable!(tenant_user -> tenant (tenant_id));
|
||||
joinable!(tenant_user -> user (user_id));
|
||||
diesel::joinable!(api_key -> tenant (tenant_id));
|
||||
diesel::joinable!(application -> tenant (tenant_id));
|
||||
diesel::joinable!(application_integration -> application (application_id));
|
||||
diesel::joinable!(device -> application (application_id));
|
||||
diesel::joinable!(device -> device_profile (device_profile_id));
|
||||
diesel::joinable!(device_keys -> device (dev_eui));
|
||||
diesel::joinable!(device_profile -> tenant (tenant_id));
|
||||
diesel::joinable!(device_queue_item -> device (dev_eui));
|
||||
diesel::joinable!(gateway -> tenant (tenant_id));
|
||||
diesel::joinable!(multicast_group -> application (application_id));
|
||||
diesel::joinable!(multicast_group_device -> device (dev_eui));
|
||||
diesel::joinable!(multicast_group_device -> multicast_group (multicast_group_id));
|
||||
diesel::joinable!(multicast_group_queue_item -> gateway (gateway_id));
|
||||
diesel::joinable!(multicast_group_queue_item -> multicast_group (multicast_group_id));
|
||||
diesel::joinable!(tenant_user -> tenant (tenant_id));
|
||||
diesel::joinable!(tenant_user -> user (user_id));
|
||||
|
||||
allow_tables_to_appear_in_same_query!(
|
||||
diesel::allow_tables_to_appear_in_same_query!(
|
||||
api_key,
|
||||
application,
|
||||
application_integration,
|
||||
|
@ -16,25 +16,25 @@ lazy_static! {
|
||||
|
||||
#[derive(QueryableByName, PartialEq, Debug)]
|
||||
pub struct SearchResult {
|
||||
#[sql_type = "diesel::sql_types::Text"]
|
||||
#[diesel(sql_type = diesel::sql_types::Text)]
|
||||
pub kind: String,
|
||||
#[sql_type = "diesel::sql_types::Float"]
|
||||
#[diesel(sql_type = diesel::sql_types::Float)]
|
||||
pub score: f32,
|
||||
#[sql_type = "diesel::sql_types::Nullable<diesel::sql_types::Uuid>"]
|
||||
#[diesel(sql_type = diesel::sql_types::Nullable<diesel::sql_types::Uuid>)]
|
||||
pub tenant_id: Option<Uuid>,
|
||||
#[sql_type = "diesel::sql_types::Nullable<diesel::sql_types::Text>"]
|
||||
#[diesel(sql_type = diesel::sql_types::Nullable<diesel::sql_types::Text>)]
|
||||
pub tenant_name: Option<String>,
|
||||
#[sql_type = "diesel::sql_types::Nullable<diesel::sql_types::Uuid>"]
|
||||
#[diesel(sql_type = diesel::sql_types::Nullable<diesel::sql_types::Uuid>)]
|
||||
pub application_id: Option<Uuid>,
|
||||
#[sql_type = "diesel::sql_types::Nullable<diesel::sql_types::Text>"]
|
||||
#[diesel(sql_type = diesel::sql_types::Nullable<diesel::sql_types::Text>)]
|
||||
pub application_name: Option<String>,
|
||||
#[sql_type = "diesel::sql_types::Nullable<diesel::sql_types::Binary>"]
|
||||
#[diesel(sql_type = diesel::sql_types::Nullable<diesel::sql_types::Binary>)]
|
||||
pub device_dev_eui: Option<EUI64>,
|
||||
#[sql_type = "diesel::sql_types::Nullable<diesel::sql_types::Text>"]
|
||||
#[diesel(sql_type = diesel::sql_types::Nullable<diesel::sql_types::Text>)]
|
||||
pub device_name: Option<String>,
|
||||
#[sql_type = "diesel::sql_types::Nullable<diesel::sql_types::Binary>"]
|
||||
#[diesel(sql_type = diesel::sql_types::Nullable<diesel::sql_types::Binary>)]
|
||||
pub gateway_id: Option<EUI64>,
|
||||
#[sql_type = "diesel::sql_types::Nullable<diesel::sql_types::Text>"]
|
||||
#[diesel(sql_type = diesel::sql_types::Nullable<diesel::sql_types::Text>)]
|
||||
pub gateway_name: Option<String>,
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ pub async fn global_search(
|
||||
let tags = serde_json::to_value(&tags).context("To serde_json value")?;
|
||||
|
||||
move || -> Result<Vec<SearchResult>, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let res = diesel::sql_query(
|
||||
r#"
|
||||
-- device
|
||||
@ -163,7 +163,7 @@ pub async fn global_search(
|
||||
.bind::<diesel::sql_types::BigInt, _>(limit as i64)
|
||||
.bind::<diesel::sql_types::BigInt, _>(offset as i64)
|
||||
.bind::<diesel::sql_types::Jsonb, _>(tags)
|
||||
.load(&c)?;
|
||||
.load(&mut c)?;
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ use super::get_db_conn;
|
||||
use super::schema::{tenant, tenant_user, user};
|
||||
|
||||
#[derive(Queryable, Insertable, AsChangeset, PartialEq, Debug, Clone)]
|
||||
#[table_name = "tenant"]
|
||||
#[diesel(table_name = tenant)]
|
||||
pub struct Tenant {
|
||||
pub id: Uuid,
|
||||
pub created_at: DateTime<Utc>,
|
||||
@ -52,7 +52,7 @@ impl Default for Tenant {
|
||||
}
|
||||
|
||||
#[derive(Queryable, Insertable, AsChangeset, PartialEq, Debug)]
|
||||
#[table_name = "tenant_user"]
|
||||
#[diesel(table_name = tenant_user)]
|
||||
pub struct TenantUser {
|
||||
pub tenant_id: Uuid,
|
||||
pub user_id: Uuid,
|
||||
@ -101,10 +101,10 @@ pub async fn create(t: Tenant) -> Result<Tenant, Error> {
|
||||
t.validate()?;
|
||||
let t = task::spawn_blocking({
|
||||
move || -> Result<Tenant, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
diesel::insert_into(tenant::table)
|
||||
.values(&t)
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, t.id.to_string()))
|
||||
}
|
||||
})
|
||||
@ -117,10 +117,10 @@ pub async fn get(id: &Uuid) -> Result<Tenant, Error> {
|
||||
task::spawn_blocking({
|
||||
let id = *id;
|
||||
move || -> Result<Tenant, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let t = tenant::dsl::tenant
|
||||
.find(&id)
|
||||
.first(&c)
|
||||
.first(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, id.to_string()))?;
|
||||
Ok(t)
|
||||
}
|
||||
@ -132,7 +132,7 @@ pub async fn update(t: Tenant) -> Result<Tenant, Error> {
|
||||
t.validate()?;
|
||||
let t = task::spawn_blocking({
|
||||
move || -> Result<Tenant, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
diesel::update(tenant::dsl::tenant.find(&t.id))
|
||||
.set((
|
||||
tenant::updated_at.eq(Utc::now()),
|
||||
@ -143,7 +143,7 @@ pub async fn update(t: Tenant) -> Result<Tenant, Error> {
|
||||
tenant::max_gateway_count.eq(&t.max_gateway_count),
|
||||
tenant::private_gateways.eq(&t.private_gateways),
|
||||
))
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, t.id.to_string()))
|
||||
}
|
||||
})
|
||||
@ -156,9 +156,9 @@ pub async fn delete(id: &Uuid) -> Result<(), Error> {
|
||||
task::spawn_blocking({
|
||||
let id = *id;
|
||||
move || -> Result<(), Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let ra = diesel::delete(tenant::dsl::tenant.find(&id))
|
||||
.execute(&c)
|
||||
.execute(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, id.to_string()))?;
|
||||
|
||||
if ra == 0 {
|
||||
@ -176,10 +176,9 @@ pub async fn get_count(filters: &Filters) -> Result<i64, Error> {
|
||||
task::spawn_blocking({
|
||||
let filters = filters.clone();
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = tenant::dsl::tenant
|
||||
.left_join(tenant_user::table)
|
||||
.select(dsl::sql("count(distinct id)"))
|
||||
.into_boxed();
|
||||
|
||||
if let Some(user_id) = &filters.user_id {
|
||||
@ -190,7 +189,10 @@ pub async fn get_count(filters: &Filters) -> Result<i64, Error> {
|
||||
q = q.filter(tenant::dsl::name.ilike(format!("%{}%", search)));
|
||||
}
|
||||
|
||||
Ok(q.first(&c)?)
|
||||
Ok(
|
||||
q.select(dsl::sql::<diesel::sql_types::BigInt>("count(distinct id)"))
|
||||
.first(&mut c)?,
|
||||
)
|
||||
}
|
||||
})
|
||||
.await?
|
||||
@ -200,9 +202,14 @@ pub async fn list(limit: i64, offset: i64, filters: &Filters) -> Result<Vec<Tena
|
||||
task::spawn_blocking({
|
||||
let filters = filters.clone();
|
||||
move || -> Result<Vec<Tenant>, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let mut q = tenant::dsl::tenant
|
||||
.left_join(tenant_user::table)
|
||||
.select(tenant::all_columns)
|
||||
.group_by(tenant::dsl::id)
|
||||
.order_by(tenant::dsl::name)
|
||||
.limit(limit)
|
||||
.offset(offset)
|
||||
.into_boxed();
|
||||
|
||||
if let Some(user_id) = &filters.user_id {
|
||||
@ -213,13 +220,7 @@ pub async fn list(limit: i64, offset: i64, filters: &Filters) -> Result<Vec<Tena
|
||||
q = q.filter(tenant::dsl::name.ilike(format!("%{}%", search)));
|
||||
}
|
||||
|
||||
let items = q
|
||||
.select(tenant::all_columns)
|
||||
.group_by(tenant::dsl::id)
|
||||
.order_by(tenant::dsl::name)
|
||||
.limit(limit)
|
||||
.offset(offset)
|
||||
.load(&c)?;
|
||||
let items = q.load(&mut c)?;
|
||||
|
||||
Ok(items)
|
||||
}
|
||||
@ -230,10 +231,10 @@ pub async fn list(limit: i64, offset: i64, filters: &Filters) -> Result<Vec<Tena
|
||||
pub async fn add_user(tu: TenantUser) -> Result<TenantUser, Error> {
|
||||
let tu = task::spawn_blocking({
|
||||
move || -> Result<TenantUser, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
diesel::insert_into(tenant_user::table)
|
||||
.values(&tu)
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, tu.user_id.to_string()))
|
||||
}
|
||||
})
|
||||
@ -249,14 +250,14 @@ pub async fn add_user(tu: TenantUser) -> Result<TenantUser, Error> {
|
||||
pub async fn update_user(tu: TenantUser) -> Result<TenantUser, Error> {
|
||||
let tu = task::spawn_blocking({
|
||||
move || -> Result<TenantUser, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
diesel::update(
|
||||
tenant_user::dsl::tenant_user
|
||||
.filter(tenant_user::dsl::tenant_id.eq(&tu.tenant_id))
|
||||
.filter(tenant_user::dsl::user_id.eq(&tu.user_id)),
|
||||
)
|
||||
.set(&tu)
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, tu.user_id.to_string()))
|
||||
}
|
||||
})
|
||||
@ -274,11 +275,11 @@ pub async fn get_user(tenant_id: &Uuid, user_id: &Uuid) -> Result<TenantUser, Er
|
||||
let tenant_id = *tenant_id;
|
||||
let user_id = *user_id;
|
||||
move || -> Result<TenantUser, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let tu: TenantUser = tenant_user::dsl::tenant_user
|
||||
.filter(tenant_user::dsl::tenant_id.eq(&tenant_id))
|
||||
.filter(tenant_user::dsl::user_id.eq(&user_id))
|
||||
.first(&c)
|
||||
.first(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, user_id.to_string()))?;
|
||||
Ok(tu)
|
||||
}
|
||||
@ -290,11 +291,11 @@ pub async fn get_user_count(tenant_id: &Uuid) -> Result<i64, Error> {
|
||||
task::spawn_blocking({
|
||||
let tenant_id = *tenant_id;
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let count = tenant_user::dsl::tenant_user
|
||||
.select(dsl::count_star())
|
||||
.filter(tenant_user::dsl::tenant_id.eq(&tenant_id))
|
||||
.first(&c)?;
|
||||
.first(&mut c)?;
|
||||
Ok(count)
|
||||
}
|
||||
})
|
||||
@ -309,7 +310,7 @@ pub async fn get_users(
|
||||
task::spawn_blocking({
|
||||
let tenant_id = *tenant_id;
|
||||
move || -> Result<Vec<TenantUserListItem>, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let items = tenant_user::dsl::tenant_user
|
||||
.inner_join(user::table)
|
||||
.select((
|
||||
@ -326,7 +327,7 @@ pub async fn get_users(
|
||||
.order_by(user::dsl::email)
|
||||
.limit(limit)
|
||||
.offset(offset)
|
||||
.load(&c)?;
|
||||
.load(&mut c)?;
|
||||
|
||||
Ok(items)
|
||||
}
|
||||
@ -339,13 +340,13 @@ pub async fn delete_user(tenant_id: &Uuid, user_id: &Uuid) -> Result<(), Error>
|
||||
let tenant_id = *tenant_id;
|
||||
let user_id = *user_id;
|
||||
move || -> Result<(), Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let ra = diesel::delete(
|
||||
tenant_user::dsl::tenant_user
|
||||
.filter(tenant_user::dsl::tenant_id.eq(&tenant_id))
|
||||
.filter(tenant_user::dsl::user_id.eq(&user_id)),
|
||||
)
|
||||
.execute(&c)?;
|
||||
.execute(&mut c)?;
|
||||
if ra == 0 {
|
||||
return Err(Error::NotFound(user_id.to_string()));
|
||||
}
|
||||
@ -365,10 +366,10 @@ pub async fn get_tenant_users_for_user(user_id: &Uuid) -> Result<Vec<TenantUser>
|
||||
task::spawn_blocking({
|
||||
let user_id = *user_id;
|
||||
move || -> Result<Vec<TenantUser>, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let items = tenant_user::dsl::tenant_user
|
||||
.filter(tenant_user::dsl::user_id.eq(&user_id))
|
||||
.load(&c)?;
|
||||
.load(&mut c)?;
|
||||
Ok(items)
|
||||
}
|
||||
})
|
||||
|
@ -17,7 +17,7 @@ use super::get_db_conn;
|
||||
use super::schema::user;
|
||||
|
||||
#[derive(Queryable, Insertable, AsChangeset, PartialEq, Debug, Clone)]
|
||||
#[table_name = "user"]
|
||||
#[diesel(table_name = user)]
|
||||
pub struct User {
|
||||
pub id: Uuid,
|
||||
pub external_id: Option<String>,
|
||||
@ -69,11 +69,11 @@ pub async fn create(u: User) -> Result<User, Error> {
|
||||
u.validate()?;
|
||||
let u = task::spawn_blocking({
|
||||
move || -> Result<User, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
|
||||
diesel::insert_into(user::table)
|
||||
.values(&u)
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, u.id.to_string()))
|
||||
}
|
||||
})
|
||||
@ -86,10 +86,10 @@ pub async fn get(id: &Uuid) -> Result<User, Error> {
|
||||
task::spawn_blocking({
|
||||
let id = *id;
|
||||
move || -> Result<User, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let u = user::dsl::user
|
||||
.find(&id)
|
||||
.first(&c)
|
||||
.first(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, id.to_string()))?;
|
||||
Ok(u)
|
||||
}
|
||||
@ -101,10 +101,10 @@ pub async fn get_by_email(email: &str) -> Result<User, Error> {
|
||||
task::spawn_blocking({
|
||||
let email = email.to_string();
|
||||
move || -> Result<User, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let u = user::dsl::user
|
||||
.filter(user::dsl::email.eq(&email))
|
||||
.first(&c)
|
||||
.first(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, email))?;
|
||||
Ok(u)
|
||||
}
|
||||
@ -116,10 +116,10 @@ pub async fn get_by_external_id(external_id: &str) -> Result<User, Error> {
|
||||
task::spawn_blocking({
|
||||
let external_id = external_id.to_string();
|
||||
move || -> Result<User, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let u = user::dsl::user
|
||||
.filter(user::dsl::external_id.eq(&external_id))
|
||||
.first(&c)
|
||||
.first(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, external_id))?;
|
||||
Ok(u)
|
||||
}
|
||||
@ -132,10 +132,10 @@ pub async fn get_by_email_and_pw(email: &str, pw: &str) -> Result<User, Error> {
|
||||
let email = email.to_string();
|
||||
let pw = pw.to_string();
|
||||
move || -> Result<User, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let u: User = match user::dsl::user
|
||||
.filter(user::dsl::email.eq(&email))
|
||||
.first(&c)
|
||||
.first(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, email))
|
||||
{
|
||||
Ok(v) => v,
|
||||
@ -161,7 +161,7 @@ pub async fn update(u: User) -> Result<User, Error> {
|
||||
u.validate()?;
|
||||
let u = task::spawn_blocking({
|
||||
move || -> Result<User, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
diesel::update(user::dsl::user.find(&u.id))
|
||||
.set((
|
||||
user::updated_at.eq(Utc::now()),
|
||||
@ -172,7 +172,7 @@ pub async fn update(u: User) -> Result<User, Error> {
|
||||
user::note.eq(&u.note),
|
||||
user::external_id.eq(&u.external_id),
|
||||
))
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, u.id.to_string()))
|
||||
}
|
||||
})
|
||||
@ -186,10 +186,10 @@ pub async fn set_password_hash(id: &Uuid, hash: &str) -> Result<User, Error> {
|
||||
let id = *id;
|
||||
let hash = hash.to_string();
|
||||
move || -> Result<User, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
diesel::update(user::dsl::user.find(&id))
|
||||
.set(user::password_hash.eq(&hash))
|
||||
.get_result(&c)
|
||||
.get_result(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, id.to_string()))
|
||||
}
|
||||
})
|
||||
@ -202,9 +202,9 @@ pub async fn delete(id: &Uuid) -> Result<(), Error> {
|
||||
task::spawn_blocking({
|
||||
let id = *id;
|
||||
move || -> Result<(), Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let ra = diesel::delete(user::dsl::user.find(&id))
|
||||
.execute(&c)
|
||||
.execute(&mut c)
|
||||
.map_err(|e| Error::from_diesel(e, id.to_string()))?;
|
||||
|
||||
if ra == 0 {
|
||||
@ -221,8 +221,8 @@ pub async fn delete(id: &Uuid) -> Result<(), Error> {
|
||||
pub async fn get_count() -> Result<i64, Error> {
|
||||
task::spawn_blocking({
|
||||
move || -> Result<i64, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let count = user::dsl::user.select(dsl::count_star()).first(&c)?;
|
||||
let mut c = get_db_conn()?;
|
||||
let count = user::dsl::user.select(dsl::count_star()).first(&mut c)?;
|
||||
Ok(count)
|
||||
}
|
||||
})
|
||||
@ -232,12 +232,12 @@ pub async fn get_count() -> Result<i64, Error> {
|
||||
pub async fn list(limit: i64, offset: i64) -> Result<Vec<User>, Error> {
|
||||
task::spawn_blocking({
|
||||
move || -> Result<Vec<User>, Error> {
|
||||
let c = get_db_conn()?;
|
||||
let mut c = get_db_conn()?;
|
||||
let items = user::dsl::user
|
||||
.order_by(user::dsl::email)
|
||||
.limit(limit)
|
||||
.offset(offset)
|
||||
.load(&c)?;
|
||||
.load(&mut c)?;
|
||||
Ok(items)
|
||||
}
|
||||
})
|
||||
|
@ -98,7 +98,7 @@ async fn test_gateway_filtering() {
|
||||
let dk = device_keys::create(device_keys::DeviceKeys {
|
||||
dev_eui: dev.dev_eui.clone(),
|
||||
nwk_key: AES128Key::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]),
|
||||
dev_nonces: vec![258],
|
||||
dev_nonces: vec![Some(258)],
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
@ -259,7 +259,7 @@ async fn test_lorawan_10() {
|
||||
let dk = device_keys::create(device_keys::DeviceKeys {
|
||||
dev_eui: dev.dev_eui.clone(),
|
||||
nwk_key: AES128Key::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]),
|
||||
dev_nonces: vec![258],
|
||||
dev_nonces: vec![Some(258)],
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
@ -902,7 +902,7 @@ async fn test_lorawan_11() {
|
||||
dev_eui: dev.dev_eui.clone(),
|
||||
nwk_key: AES128Key::from_bytes([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]),
|
||||
app_key: AES128Key::from_bytes([16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]),
|
||||
dev_nonces: vec![258],
|
||||
dev_nonces: vec![Some(258)],
|
||||
..Default::default()
|
||||
})
|
||||
.await
|
||||
|
@ -1,11 +1,11 @@
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::collections::HashMap;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use chrono::{DateTime, Local};
|
||||
use tracing::{error, info, span, trace, Instrument, Level};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::gateway::backend as gateway_backend;
|
||||
use crate::storage::{gateway, metrics};
|
||||
@ -14,7 +14,6 @@ use chirpstack_api::{common, gw};
|
||||
use lrwn::EUI64;
|
||||
|
||||
pub struct Stats {
|
||||
id: Uuid,
|
||||
gateway_id: EUI64,
|
||||
stats: gw::GatewayStats,
|
||||
gateway: Option<gateway::Gateway>,
|
||||
@ -22,22 +21,28 @@ pub struct Stats {
|
||||
|
||||
impl Stats {
|
||||
pub async fn handle(s: gw::GatewayStats) {
|
||||
let id = match Uuid::from_slice(&s.stats_id) {
|
||||
let gateway_id = match if !s.gateway_id.is_empty() {
|
||||
EUI64::from_str(&s.gateway_id)
|
||||
} else {
|
||||
EUI64::from_slice(&s.gateway_id_legacy)
|
||||
} {
|
||||
Ok(v) => v,
|
||||
Err(_) => Uuid::nil(),
|
||||
Err(e) => {
|
||||
error!(error = %e, "Decode stats gateway_id error");
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let span = span!(Level::INFO, "stats", stats_id = %id);
|
||||
let span = span!(Level::INFO, "stats", gateway_id = %gateway_id);
|
||||
|
||||
if let Err(e) = Stats::_handle(id, s).instrument(span).await {
|
||||
if let Err(e) = Stats::_handle(gateway_id, s).instrument(span).await {
|
||||
error!(error = %e, "Handle gateway stats error");
|
||||
}
|
||||
}
|
||||
|
||||
async fn _handle(id: Uuid, s: gw::GatewayStats) -> Result<()> {
|
||||
async fn _handle(gateway_id: EUI64, s: gw::GatewayStats) -> Result<()> {
|
||||
let mut ctx = Stats {
|
||||
id,
|
||||
gateway_id: EUI64::from_slice(&s.gateway_id)?,
|
||||
gateway_id: gateway_id,
|
||||
stats: s,
|
||||
gateway: None,
|
||||
};
|
||||
@ -180,13 +185,14 @@ impl Stats {
|
||||
|
||||
let gw_conf = gw::GatewayConfiguration {
|
||||
gateway_id: self.stats.gateway_id.clone(),
|
||||
gateway_id_legacy: self.stats.gateway_id_legacy.clone(),
|
||||
version: hash,
|
||||
channels: gateway_conf
|
||||
.channels
|
||||
.iter()
|
||||
.map(|c| gw::ChannelConfiguration {
|
||||
frequency: c.frequency,
|
||||
modulation: match c.modulation {
|
||||
modulation_legacy: match c.modulation {
|
||||
config::GatewayChannelModulation::LORA => common::Modulation::Lora,
|
||||
config::GatewayChannelModulation::FSK => common::Modulation::Fsk,
|
||||
}
|
||||
@ -194,8 +200,9 @@ impl Stats {
|
||||
modulation_config: Some(match c.modulation {
|
||||
config::GatewayChannelModulation::LORA => {
|
||||
gw::channel_configuration::ModulationConfig::LoraModulationConfig(
|
||||
gw::LoRaModulationConfig {
|
||||
bandwidth: c.bandwidth / 1000,
|
||||
gw::LoraModulationConfig {
|
||||
bandwidth_legacy: c.bandwidth / 1000,
|
||||
bandwidth: c.bandwidth,
|
||||
spreading_factors: c.spreading_factors.clone(),
|
||||
},
|
||||
)
|
||||
@ -203,7 +210,8 @@ impl Stats {
|
||||
config::GatewayChannelModulation::FSK => {
|
||||
gw::channel_configuration::ModulationConfig::FskModulationConfig(
|
||||
gw::FskModulationConfig {
|
||||
bandwidth: c.bandwidth / 1000,
|
||||
bandwidth_legacy: c.bandwidth / 1000,
|
||||
bandwidth: c.bandwidth,
|
||||
bitrate: c.datarate,
|
||||
},
|
||||
)
|
||||
|
@ -1,9 +1,14 @@
|
||||
services:
|
||||
chirpstack:
|
||||
image: chirpstack/chirpstack-dev-cache:latest
|
||||
platform: linux/amd64
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile-devel
|
||||
volumes:
|
||||
- ./:/chirpstack
|
||||
- ./.rust/target:/chirpstack/target
|
||||
- ./.rust/.cargo/registry/index:/usr/local/cargo/registry/index
|
||||
- ./.rust/.cargo/registry/cache:/usr/local/cargo/registry/cache
|
||||
- ./.rust/.cargo/git/db:/usr/local/cargo/git/db
|
||||
depends_on:
|
||||
- postgres
|
||||
- redis
|
||||
|
@ -3,7 +3,7 @@ name = "lrwn"
|
||||
description = "Library for encoding / decoding LoRaWAN frames."
|
||||
homepage = "https://www.chirpstack.io"
|
||||
license = "MIT"
|
||||
version = "4.0.0-test.7"
|
||||
version = "4.0.0-test.11"
|
||||
authors = ["Orne Brocaar <info@brocaar.com>"]
|
||||
edition = "2018"
|
||||
repository = "https://github.com/chirpstack/chirpstack"
|
||||
@ -13,7 +13,7 @@ hex = "0.4"
|
||||
cmac = "0.6"
|
||||
aes = "0.7"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
diesel = { version = "1.4", features = [ "postgres" ] }
|
||||
diesel = { version = "2.0.0-rc.0", features = [ "postgres" ] }
|
||||
|
||||
# Error handling
|
||||
thiserror = "1.0"
|
||||
|
@ -1,9 +1,8 @@
|
||||
use std::fmt;
|
||||
use std::io::Write;
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::Result;
|
||||
use diesel::backend::Backend;
|
||||
use diesel::backend::{self, Backend};
|
||||
use diesel::sql_types::Binary;
|
||||
use diesel::{deserialize, serialize};
|
||||
use serde::de::{self, Visitor};
|
||||
@ -12,7 +11,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use crate::Error;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, AsExpression, FromSqlRow, Default)]
|
||||
#[sql_type = "diesel::sql_types::Binary"]
|
||||
#[diesel(sql_type = diesel::sql_types::Binary)]
|
||||
pub struct AES128Key([u8; 16]);
|
||||
|
||||
impl AES128Key {
|
||||
@ -100,13 +99,13 @@ impl<'de> Visitor<'de> for Aes128KeyVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
impl<ST, DB> deserialize::FromSql<ST, DB> for AES128Key
|
||||
impl<DB> deserialize::FromSql<Binary, DB> for AES128Key
|
||||
where
|
||||
DB: Backend,
|
||||
*const [u8]: deserialize::FromSql<ST, DB>,
|
||||
*const [u8]: deserialize::FromSql<Binary, DB>,
|
||||
{
|
||||
fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
|
||||
let bytes = Vec::<u8>::from_sql(bytes)?;
|
||||
fn from_sql(value: backend::RawValue<DB>) -> deserialize::Result<Self> {
|
||||
let bytes = Vec::<u8>::from_sql(value)?;
|
||||
if bytes.len() != 16 {
|
||||
return Err("AES128Key type expects exactly 16 bytes".into());
|
||||
}
|
||||
@ -118,13 +117,15 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB> serialize::ToSql<Binary, DB> for AES128Key
|
||||
impl serialize::ToSql<Binary, diesel::pg::Pg> for AES128Key
|
||||
where
|
||||
DB: Backend,
|
||||
[u8]: serialize::ToSql<Binary, DB>,
|
||||
[u8]: serialize::ToSql<Binary, diesel::pg::Pg>,
|
||||
{
|
||||
fn to_sql<W: Write>(&self, out: &mut serialize::Output<W, DB>) -> serialize::Result {
|
||||
(&self.to_bytes() as &[u8]).to_sql(out)
|
||||
fn to_sql<'b>(&self, out: &mut serialize::Output<'b, '_, diesel::pg::Pg>) -> serialize::Result {
|
||||
<[u8] as serialize::ToSql<Binary, diesel::pg::Pg>>::to_sql(
|
||||
&self.to_bytes(),
|
||||
&mut out.reborrow(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ use super::netid::NetID;
|
||||
use crate::Error;
|
||||
|
||||
#[derive(PartialEq, Copy, Clone, AsExpression, FromSqlRow, Default)]
|
||||
#[sql_type = "diesel::sql_types::Binary"]
|
||||
#[diesel(sql_type = diesel::sql_types::Binary)]
|
||||
pub struct DevAddr([u8; 4]);
|
||||
|
||||
impl DevAddr {
|
||||
@ -174,19 +174,17 @@ impl Serialize for DevAddr {
|
||||
}
|
||||
}
|
||||
|
||||
use std::io::Write;
|
||||
|
||||
use diesel::backend::Backend;
|
||||
use diesel::backend::{self, Backend};
|
||||
use diesel::sql_types::Binary;
|
||||
use diesel::{deserialize, serialize};
|
||||
|
||||
impl<ST, DB> deserialize::FromSql<ST, DB> for DevAddr
|
||||
impl<DB> deserialize::FromSql<Binary, DB> for DevAddr
|
||||
where
|
||||
DB: Backend,
|
||||
*const [u8]: deserialize::FromSql<ST, DB>,
|
||||
*const [u8]: deserialize::FromSql<Binary, DB>,
|
||||
{
|
||||
fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
|
||||
let bytes = Vec::<u8>::from_sql(bytes)?;
|
||||
fn from_sql(value: backend::RawValue<DB>) -> deserialize::Result<Self> {
|
||||
let bytes = Vec::<u8>::from_sql(value)?;
|
||||
if bytes.len() != 4 {
|
||||
return Err("DevAddr type expects exactly 4 bytes".into());
|
||||
}
|
||||
@ -198,13 +196,15 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB> serialize::ToSql<Binary, DB> for DevAddr
|
||||
impl serialize::ToSql<Binary, diesel::pg::Pg> for DevAddr
|
||||
where
|
||||
DB: Backend,
|
||||
[u8]: serialize::ToSql<Binary, DB>,
|
||||
[u8]: serialize::ToSql<Binary, diesel::pg::Pg>,
|
||||
{
|
||||
fn to_sql<W: Write>(&self, out: &mut serialize::Output<W, DB>) -> serialize::Result {
|
||||
(&self.to_be_bytes() as &[u8]).to_sql(out)
|
||||
fn to_sql<'b>(&self, out: &mut serialize::Output<'b, '_, diesel::pg::Pg>) -> serialize::Result {
|
||||
<[u8] as serialize::ToSql<Binary, diesel::pg::Pg>>::to_sql(
|
||||
&self.to_be_bytes(),
|
||||
&mut out.reborrow(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use crate::Error;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, AsExpression, FromSqlRow, Default)]
|
||||
#[sql_type = "diesel::sql_types::Binary"]
|
||||
#[diesel(sql_type = diesel::sql_types::Binary)]
|
||||
pub struct EUI64([u8; 8]);
|
||||
|
||||
impl EUI64 {
|
||||
@ -104,19 +104,17 @@ impl<'de> Visitor<'de> for Eui64Visitor {
|
||||
}
|
||||
}
|
||||
|
||||
use std::io::Write;
|
||||
|
||||
use diesel::backend::Backend;
|
||||
use diesel::backend::{self, Backend};
|
||||
use diesel::sql_types::Binary;
|
||||
use diesel::{deserialize, serialize};
|
||||
|
||||
impl<DB> deserialize::FromSql<diesel::sql_types::Binary, DB> for EUI64
|
||||
impl<DB> deserialize::FromSql<Binary, DB> for EUI64
|
||||
where
|
||||
DB: Backend,
|
||||
*const [u8]: deserialize::FromSql<diesel::sql_types::Binary, DB>,
|
||||
*const [u8]: deserialize::FromSql<Binary, DB>,
|
||||
{
|
||||
fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
|
||||
let bytes = Vec::<u8>::from_sql(bytes)?;
|
||||
fn from_sql(value: backend::RawValue<DB>) -> deserialize::Result<Self> {
|
||||
let bytes = Vec::<u8>::from_sql(value)?;
|
||||
if bytes.len() != 8 {
|
||||
return Err("EUI64 type expects exactly 8 bytes".into());
|
||||
}
|
||||
@ -128,17 +126,21 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB> serialize::ToSql<Binary, DB> for EUI64
|
||||
impl serialize::ToSql<Binary, diesel::pg::Pg> for EUI64
|
||||
where
|
||||
DB: Backend,
|
||||
[u8]: serialize::ToSql<Binary, DB>,
|
||||
[u8]: serialize::ToSql<Binary, diesel::pg::Pg>,
|
||||
{
|
||||
fn to_sql<W: Write>(&self, out: &mut serialize::Output<W, DB>) -> serialize::Result {
|
||||
(&self.to_be_bytes() as &[u8]).to_sql(out)
|
||||
fn to_sql<'b>(&self, out: &mut serialize::Output<'b, '_, diesel::pg::Pg>) -> serialize::Result {
|
||||
<[u8] as serialize::ToSql<Binary, diesel::pg::Pg>>::to_sql(
|
||||
&self.to_be_bytes(),
|
||||
&mut out.reborrow(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl diesel::sql_types::NotNull for EUI64 {}
|
||||
impl diesel::sql_types::SqlType for EUI64 {
|
||||
type IsNull = diesel::sql_types::is_nullable::NotNull;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
@ -1,11 +1,10 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fmt;
|
||||
use std::io::Write;
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use diesel::backend::Backend;
|
||||
use diesel::backend::{self, Backend};
|
||||
use diesel::sql_types::Text;
|
||||
use diesel::{deserialize, serialize};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -28,7 +27,7 @@ pub mod us915;
|
||||
|
||||
#[derive(Deserialize, Serialize, Copy, Clone, Debug, Eq, PartialEq, AsExpression, FromSqlRow)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[sql_type = "diesel::sql_types::Text"]
|
||||
#[diesel(sql_type = diesel::sql_types::Text)]
|
||||
pub enum CommonName {
|
||||
EU868,
|
||||
US915,
|
||||
@ -52,24 +51,29 @@ impl fmt::Display for CommonName {
|
||||
}
|
||||
}
|
||||
|
||||
impl<ST, DB> deserialize::FromSql<ST, DB> for CommonName
|
||||
impl<DB> deserialize::FromSql<Text, DB> for CommonName
|
||||
where
|
||||
DB: Backend,
|
||||
*const str: deserialize::FromSql<ST, DB>,
|
||||
*const str: deserialize::FromSql<Text, DB>,
|
||||
{
|
||||
fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
|
||||
let string = String::from_sql(bytes)?;
|
||||
fn from_sql(value: backend::RawValue<DB>) -> deserialize::Result<Self> {
|
||||
let string = String::from_sql(value)?;
|
||||
Ok(CommonName::from_str(&string)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB> serialize::ToSql<Text, DB> for CommonName
|
||||
impl serialize::ToSql<Text, diesel::pg::Pg> for CommonName
|
||||
where
|
||||
DB: Backend,
|
||||
str: serialize::ToSql<Text, DB>,
|
||||
str: serialize::ToSql<Text, diesel::pg::Pg>,
|
||||
{
|
||||
fn to_sql<W: Write>(&self, out: &mut serialize::Output<W, DB>) -> serialize::Result {
|
||||
self.to_string().as_str().to_sql(out)
|
||||
fn to_sql<'b>(
|
||||
&'b self,
|
||||
out: &mut serialize::Output<'b, '_, diesel::pg::Pg>,
|
||||
) -> serialize::Result {
|
||||
<str as serialize::ToSql<Text, diesel::pg::Pg>>::to_sql(
|
||||
&self.to_string(),
|
||||
&mut out.reborrow(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,7 +105,7 @@ impl FromStr for CommonName {
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, AsExpression, FromSqlRow)]
|
||||
#[sql_type = "diesel::sql_types::Text"]
|
||||
#[diesel(sql_type = diesel::sql_types::Text)]
|
||||
pub enum Revision {
|
||||
Latest,
|
||||
A,
|
||||
@ -155,30 +159,35 @@ impl FromStr for Revision {
|
||||
}
|
||||
}
|
||||
|
||||
impl<ST, DB> deserialize::FromSql<ST, DB> for Revision
|
||||
impl<DB> deserialize::FromSql<Text, DB> for Revision
|
||||
where
|
||||
DB: Backend,
|
||||
*const str: deserialize::FromSql<ST, DB>,
|
||||
*const str: deserialize::FromSql<Text, DB>,
|
||||
{
|
||||
fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
|
||||
let string = String::from_sql(bytes)?;
|
||||
fn from_sql(value: backend::RawValue<DB>) -> deserialize::Result<Self> {
|
||||
let string = String::from_sql(value)?;
|
||||
Ok(Revision::from_str(&string)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB> serialize::ToSql<Text, DB> for Revision
|
||||
impl serialize::ToSql<Text, diesel::pg::Pg> for Revision
|
||||
where
|
||||
DB: Backend,
|
||||
str: serialize::ToSql<Text, DB>,
|
||||
str: serialize::ToSql<Text, diesel::pg::Pg>,
|
||||
{
|
||||
fn to_sql<W: Write>(&self, out: &mut serialize::Output<W, DB>) -> serialize::Result {
|
||||
self.to_string().as_str().to_sql(out)
|
||||
fn to_sql<'b>(
|
||||
&'b self,
|
||||
out: &mut serialize::Output<'b, '_, diesel::pg::Pg>,
|
||||
) -> serialize::Result {
|
||||
<str as serialize::ToSql<Text, diesel::pg::Pg>>::to_sql(
|
||||
&self.to_string(),
|
||||
&mut out.reborrow(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, AsExpression, FromSqlRow)]
|
||||
#[sql_type = "diesel::sql_types::Text"]
|
||||
#[diesel(sql_type = diesel::sql_types::Text)]
|
||||
pub enum MacVersion {
|
||||
Latest,
|
||||
LORAWAN_1_0_0,
|
||||
@ -232,24 +241,29 @@ impl FromStr for MacVersion {
|
||||
}
|
||||
}
|
||||
|
||||
impl<ST, DB> deserialize::FromSql<ST, DB> for MacVersion
|
||||
impl<DB> deserialize::FromSql<Text, DB> for MacVersion
|
||||
where
|
||||
DB: Backend,
|
||||
*const str: deserialize::FromSql<ST, DB>,
|
||||
*const str: deserialize::FromSql<Text, DB>,
|
||||
{
|
||||
fn from_sql(bytes: Option<&DB::RawValue>) -> deserialize::Result<Self> {
|
||||
let string = String::from_sql(bytes)?;
|
||||
fn from_sql(value: backend::RawValue<DB>) -> deserialize::Result<Self> {
|
||||
let string = String::from_sql(value)?;
|
||||
Ok(MacVersion::from_str(&string)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB> serialize::ToSql<Text, DB> for MacVersion
|
||||
impl serialize::ToSql<Text, diesel::pg::Pg> for MacVersion
|
||||
where
|
||||
DB: Backend,
|
||||
str: serialize::ToSql<Text, DB>,
|
||||
str: serialize::ToSql<Text, diesel::pg::Pg>,
|
||||
{
|
||||
fn to_sql<W: Write>(&self, out: &mut serialize::Output<W, DB>) -> serialize::Result {
|
||||
self.to_string().as_str().to_sql(out)
|
||||
fn to_sql<'b>(
|
||||
&'b self,
|
||||
out: &mut serialize::Output<'b, '_, diesel::pg::Pg>,
|
||||
) -> serialize::Result {
|
||||
<str as serialize::ToSql<Text, diesel::pg::Pg>>::to_sql(
|
||||
&self.to_string(),
|
||||
&mut out.reborrow(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "chirpstack-ui",
|
||||
"version": "4.0.0-test.7",
|
||||
"version": "4.0.0-test.11",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@ant-design/colors": "^6.0.0",
|
||||
|
@ -3,7 +3,7 @@ import { Link } from "react-router-dom";
|
||||
|
||||
import moment from "moment";
|
||||
import { ReloadOutlined } from "@ant-design/icons";
|
||||
import { Descriptions, Space, Card, Statistic, Row, Col, Tabs, Radio, RadioChangeEvent, Button } from "antd";
|
||||
import { Descriptions, Space, Card, Statistic, Row, Col, Tabs, Radio, RadioChangeEvent, Button, Spin } from "antd";
|
||||
import { Timestamp } from "google-protobuf/google/protobuf/timestamp_pb";
|
||||
|
||||
import {
|
||||
@ -31,6 +31,8 @@ interface IState {
|
||||
metricsAggregation: Aggregation;
|
||||
deviceMetrics?: GetDeviceMetricsResponse;
|
||||
deviceLinkMetrics?: GetDeviceLinkMetricsResponse;
|
||||
deviceMetricsLoaded: boolean;
|
||||
deviceLinkMetricsLoaded: boolean;
|
||||
}
|
||||
|
||||
class DeviceDashboard extends Component<IProps, IState> {
|
||||
@ -39,6 +41,8 @@ class DeviceDashboard extends Component<IProps, IState> {
|
||||
|
||||
this.state = {
|
||||
metricsAggregation: Aggregation.DAY,
|
||||
deviceMetricsLoaded: false,
|
||||
deviceLinkMetricsLoaded: false,
|
||||
};
|
||||
}
|
||||
|
||||
@ -59,8 +63,16 @@ class DeviceDashboard extends Component<IProps, IState> {
|
||||
start = start.subtract(12, "months");
|
||||
}
|
||||
|
||||
this.loadLinkMetrics(start.toDate(), end.toDate(), agg);
|
||||
this.loadDeviceMetrics(start.toDate(), end.toDate(), agg);
|
||||
this.setState(
|
||||
{
|
||||
deviceMetricsLoaded: false,
|
||||
deviceLinkMetricsLoaded: false,
|
||||
},
|
||||
() => {
|
||||
this.loadLinkMetrics(start.toDate(), end.toDate(), agg);
|
||||
this.loadDeviceMetrics(start.toDate(), end.toDate(), agg);
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
loadDeviceMetrics = (start: Date, end: Date, agg: Aggregation) => {
|
||||
@ -79,6 +91,7 @@ class DeviceDashboard extends Component<IProps, IState> {
|
||||
DeviceStore.getMetrics(req, (resp: GetDeviceMetricsResponse) => {
|
||||
this.setState({
|
||||
deviceMetrics: resp,
|
||||
deviceMetricsLoaded: true,
|
||||
});
|
||||
});
|
||||
};
|
||||
@ -99,6 +112,7 @@ class DeviceDashboard extends Component<IProps, IState> {
|
||||
DeviceStore.getLinkMetrics(req, (resp: GetDeviceLinkMetricsResponse) => {
|
||||
this.setState({
|
||||
deviceLinkMetrics: resp,
|
||||
deviceLinkMetricsLoaded: true,
|
||||
});
|
||||
});
|
||||
};
|
||||
@ -164,14 +178,23 @@ class DeviceDashboard extends Component<IProps, IState> {
|
||||
lastSeenAt = moment(this.props.lastSeenAt).format("YYYY-MM-DD HH:mm:ss");
|
||||
}
|
||||
|
||||
const loading = !this.state.deviceLinkMetricsLoaded || !this.state.deviceMetrics;
|
||||
|
||||
const aggregations = (
|
||||
<Space direction="horizontal">
|
||||
{loading && <Spin size="small" />}
|
||||
<Radio.Group value={this.state.metricsAggregation} onChange={this.onMetricsAggregationChange} size="small">
|
||||
<Radio.Button value={Aggregation.HOUR}>24h</Radio.Button>
|
||||
<Radio.Button value={Aggregation.DAY}>31d</Radio.Button>
|
||||
<Radio.Button value={Aggregation.MONTH}>1y</Radio.Button>
|
||||
<Radio.Button value={Aggregation.HOUR} disabled={loading}>
|
||||
24h
|
||||
</Radio.Button>
|
||||
<Radio.Button value={Aggregation.DAY} disabled={loading}>
|
||||
31d
|
||||
</Radio.Button>
|
||||
<Radio.Button value={Aggregation.MONTH} disabled={loading}>
|
||||
1y
|
||||
</Radio.Button>
|
||||
</Radio.Group>
|
||||
<Button type="primary" size="small" icon={<ReloadOutlined />} onClick={this.loadMetrics} />
|
||||
<Button type="primary" size="small" icon={<ReloadOutlined />} onClick={this.loadMetrics} disabled={loading} />
|
||||
</Space>
|
||||
);
|
||||
|
||||
|
74
ui/yarn.lock
74
ui/yarn.lock
@ -1881,7 +1881,7 @@
|
||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||
|
||||
"@chirpstack/chirpstack-api-grpc-web@file:../api/grpc-web":
|
||||
version "4.0.0-test.7"
|
||||
version "4.0.0-test.9"
|
||||
dependencies:
|
||||
"@types/google-protobuf" "^3.15.2"
|
||||
google-protobuf "^3.17.3"
|
||||
@ -2261,25 +2261,47 @@
|
||||
"@jridgewell/set-array" "^1.0.0"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||
|
||||
"@jridgewell/gen-mapping@^0.3.0":
|
||||
version "0.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9"
|
||||
integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==
|
||||
dependencies:
|
||||
"@jridgewell/set-array" "^1.0.1"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||
"@jridgewell/trace-mapping" "^0.3.9"
|
||||
|
||||
"@jridgewell/resolve-uri@^3.0.3":
|
||||
version "3.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.6.tgz#4ac237f4dabc8dd93330386907b97591801f7352"
|
||||
integrity sha512-R7xHtBSNm+9SyvpJkdQl+qrM3Hm2fea3Ef197M3mUug+v+yR+Rhfbs7PBtcBUVnIWJ4JcAdjvij+c8hXS9p5aw==
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78"
|
||||
integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==
|
||||
|
||||
"@jridgewell/set-array@^1.0.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.0.tgz#1179863356ac8fbea64a5a4bcde93a4871012c01"
|
||||
integrity sha512-SfJxIxNVYLTsKwzB3MoOQ1yxf4w/E6MdkvTgrgAt1bfxjSrLUoHMKrDOykwN14q65waezZIdqDneUIPh4/sKxg==
|
||||
|
||||
"@jridgewell/set-array@^1.0.1":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
|
||||
integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
|
||||
|
||||
"@jridgewell/source-map@^0.3.2":
|
||||
version "0.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb"
|
||||
integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==
|
||||
dependencies:
|
||||
"@jridgewell/gen-mapping" "^0.3.0"
|
||||
"@jridgewell/trace-mapping" "^0.3.9"
|
||||
|
||||
"@jridgewell/sourcemap-codec@^1.4.10":
|
||||
version "1.4.11"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz#771a1d8d744eeb71b6adb35808e1a6c7b9b8c8ec"
|
||||
integrity sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==
|
||||
version "1.4.14"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
|
||||
integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
|
||||
|
||||
"@jridgewell/trace-mapping@^0.3.9":
|
||||
version "0.3.9"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9"
|
||||
integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==
|
||||
version "0.3.14"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz#b231a081d8f66796e475ad588a1ef473112701ed"
|
||||
integrity sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==
|
||||
dependencies:
|
||||
"@jridgewell/resolve-uri" "^3.0.3"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||
@ -3253,9 +3275,9 @@ acorn@^7.0.0, acorn@^7.1.1:
|
||||
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
|
||||
|
||||
acorn@^8.2.4, acorn@^8.4.1, acorn@^8.5.0, acorn@^8.7.0:
|
||||
version "8.7.1"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30"
|
||||
integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==
|
||||
version "8.8.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8"
|
||||
integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==
|
||||
|
||||
address@^1.0.1:
|
||||
version "1.1.2"
|
||||
@ -3854,9 +3876,9 @@ bser@2.1.1:
|
||||
node-int64 "^0.4.0"
|
||||
|
||||
buffer-from@^1.0.0:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
|
||||
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
|
||||
integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
|
||||
|
||||
buffer@^6.0.3:
|
||||
version "6.0.3"
|
||||
@ -9844,15 +9866,7 @@ source-map-resolve@^0.6.0:
|
||||
atob "^2.1.2"
|
||||
decode-uri-component "^0.2.0"
|
||||
|
||||
source-map-support@^0.5.6:
|
||||
version "0.5.19"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61"
|
||||
integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==
|
||||
dependencies:
|
||||
buffer-from "^1.0.0"
|
||||
source-map "^0.6.0"
|
||||
|
||||
source-map-support@~0.5.20:
|
||||
source-map-support@^0.5.6, source-map-support@~0.5.20:
|
||||
version "0.5.21"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
|
||||
integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==
|
||||
@ -9875,7 +9889,7 @@ source-map@^0.7.3:
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
|
||||
integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
|
||||
|
||||
source-map@^0.8.0-beta.0, source-map@~0.8.0-beta.0:
|
||||
source-map@^0.8.0-beta.0:
|
||||
version "0.8.0-beta.0"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.8.0-beta.0.tgz#d4c1bb42c3f7ee925f005927ba10709e0d1d1f11"
|
||||
integrity sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==
|
||||
@ -10260,13 +10274,13 @@ terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.2.5:
|
||||
terser "^5.7.2"
|
||||
|
||||
terser@^5.0.0, terser@^5.10.0, terser@^5.7.2:
|
||||
version "5.13.1"
|
||||
resolved "https://registry.yarnpkg.com/terser/-/terser-5.13.1.tgz#66332cdc5a01b04a224c9fad449fc1a18eaa1799"
|
||||
integrity sha512-hn4WKOfwnwbYfe48NgrQjqNOH9jzLqRcIfbYytOXCOv46LBfWr9bDS17MQqOi+BWGD0sJK3Sj5NC/gJjiojaoA==
|
||||
version "5.14.2"
|
||||
resolved "https://registry.yarnpkg.com/terser/-/terser-5.14.2.tgz#9ac9f22b06994d736174f4091aa368db896f1c10"
|
||||
integrity sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==
|
||||
dependencies:
|
||||
"@jridgewell/source-map" "^0.3.2"
|
||||
acorn "^8.5.0"
|
||||
commander "^2.20.0"
|
||||
source-map "~0.8.0-beta.0"
|
||||
source-map-support "~0.5.20"
|
||||
|
||||
test-exclude@^6.0.0:
|
||||
|
Reference in New Issue
Block a user