mirror of
https://github.com/chirpstack/chirpstack.git
synced 2025-07-04 04:18:30 +00:00
Compare commits
5 Commits
v4.7.0
...
migrate_ds
Author | SHA1 | Date | |
---|---|---|---|
411cd681a9 | |||
8a986d04ce | |||
da6b7e1b37 | |||
fae182aa3d | |||
5c3624cfbe |
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
@ -32,7 +32,7 @@ jobs:
|
|||||||
key: ${{ runner.os }}-cargo-test-${{ hashFiles('**/Cargo.lock') }}
|
key: ${{ runner.os }}-cargo-test-${{ hashFiles('**/Cargo.lock') }}
|
||||||
-
|
-
|
||||||
name: Start dependency services
|
name: Start dependency services
|
||||||
run: docker compose up -d
|
run: docker-compose up -d
|
||||||
-
|
-
|
||||||
name: Build UI
|
name: Build UI
|
||||||
run: make build-ui
|
run: make build-ui
|
||||||
|
10
Cargo.lock
generated
10
Cargo.lock
generated
@ -570,7 +570,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "backend"
|
name = "backend"
|
||||||
version = "4.7.0"
|
version = "4.7.0-test.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes-kw",
|
"aes-kw",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
@ -787,7 +787,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chirpstack"
|
name = "chirpstack"
|
||||||
version = "4.7.0"
|
version = "4.7.0-test.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes",
|
"aes",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
@ -874,7 +874,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chirpstack_api"
|
name = "chirpstack_api"
|
||||||
version = "4.7.0"
|
version = "4.7.0-test.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"diesel",
|
"diesel",
|
||||||
"hex",
|
"hex",
|
||||||
@ -2434,7 +2434,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lrwn"
|
name = "lrwn"
|
||||||
version = "4.7.0"
|
version = "4.7.0-test.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes",
|
"aes",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
@ -2448,7 +2448,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lrwn_filters"
|
name = "lrwn_filters"
|
||||||
version = "4.7.0"
|
version = "4.7.0-test.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hex",
|
"hex",
|
||||||
"lrwn",
|
"lrwn",
|
||||||
|
6
Makefile
6
Makefile
@ -40,7 +40,7 @@ api: version
|
|||||||
|
|
||||||
# Builds the UI.
|
# Builds the UI.
|
||||||
build-ui:
|
build-ui:
|
||||||
docker compose run --rm --no-deps chirpstack-ui make build
|
docker-compose run --rm --no-deps chirpstack-ui make build
|
||||||
|
|
||||||
# Enter the devshell.
|
# Enter the devshell.
|
||||||
devshell:
|
devshell:
|
||||||
@ -48,11 +48,11 @@ devshell:
|
|||||||
|
|
||||||
# Enters the Docker devshell for ChirpStack development.
|
# Enters the Docker devshell for ChirpStack development.
|
||||||
docker-devshell:
|
docker-devshell:
|
||||||
docker compose run --rm --service-ports --name chirpstack chirpstack
|
docker-compose run --rm --service-ports --name chirpstack chirpstack
|
||||||
|
|
||||||
# Enters the devshell for ChirpStack UI development.
|
# Enters the devshell for ChirpStack UI development.
|
||||||
docker-devshell-ui:
|
docker-devshell-ui:
|
||||||
docker compose run --rm --service-ports --name chirpstack-ui chirpstack-ui bash
|
docker-compose run --rm --service-ports --name chirpstack-ui chirpstack-ui bash
|
||||||
|
|
||||||
# Runs the tests
|
# Runs the tests
|
||||||
test:
|
test:
|
||||||
|
@ -76,7 +76,7 @@ to be running before you can run the tests. You need to start these services
|
|||||||
manually if you started the development shell using `nix-shell`:
|
manually if you started the development shell using `nix-shell`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker compose up -d
|
docker-compose up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Run tests
|
#### Run tests
|
||||||
|
20
api/Makefile
vendored
20
api/Makefile
vendored
@ -1,31 +1,31 @@
|
|||||||
.PHONY: rust grpc-web go js python md java kotlin csharp
|
.PHONY: rust grpc-web go js python md java kotlin csharp
|
||||||
|
|
||||||
all:
|
all:
|
||||||
docker compose up
|
docker-compose up
|
||||||
|
|
||||||
rust:
|
rust:
|
||||||
docker compose run --rm chirpstack-api-rust
|
docker-compose run --rm chirpstack-api-rust
|
||||||
|
|
||||||
grpc-web:
|
grpc-web:
|
||||||
docker compose run --rm chirpstack-api-grpc-web
|
docker-compose run --rm chirpstack-api-grpc-web
|
||||||
|
|
||||||
go:
|
go:
|
||||||
docker compose run --rm chirpstack-api-go
|
docker-compose run --rm chirpstack-api-go
|
||||||
|
|
||||||
js:
|
js:
|
||||||
docker compose run --rm chirpstack-api-js
|
docker-compose run --rm chirpstack-api-js
|
||||||
|
|
||||||
python:
|
python:
|
||||||
docker compose run --rm chirpstack-api-python
|
docker-compose run --rm chirpstack-api-python
|
||||||
|
|
||||||
md:
|
md:
|
||||||
docker compose run --rm chirpstack-api-md
|
docker-compose run --rm chirpstack-api-md
|
||||||
|
|
||||||
java:
|
java:
|
||||||
docker compose run --rm chirpstack-api-java
|
docker-compose run --rm chirpstack-api-java
|
||||||
|
|
||||||
kotlin:
|
kotlin:
|
||||||
docker compose run --rm chirpstack-api-kotlin
|
docker-compose run --rm chirpstack-api-kotlin
|
||||||
|
|
||||||
csharp:
|
csharp:
|
||||||
docker compose run --rm chirpstack-csharp
|
docker-compose run --rm chirpstack-csharp
|
||||||
|
2
api/grpc-web/package.json
vendored
2
api/grpc-web/package.json
vendored
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@chirpstack/chirpstack-api-grpc-web",
|
"name": "@chirpstack/chirpstack-api-grpc-web",
|
||||||
"version": "4.7.0",
|
"version": "4.7.0-test.3",
|
||||||
"description": "Chirpstack gRPC-web API",
|
"description": "Chirpstack gRPC-web API",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
2
api/java/build.gradle.kts
vendored
2
api/java/build.gradle.kts
vendored
@ -8,7 +8,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group = "io.chirpstack"
|
group = "io.chirpstack"
|
||||||
version = "4.7.0"
|
version = "4.7.0-test.3"
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
2
api/js/package.json
vendored
2
api/js/package.json
vendored
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@chirpstack/chirpstack-api",
|
"name": "@chirpstack/chirpstack-api",
|
||||||
"version": "4.7.0",
|
"version": "4.7.0-test.3",
|
||||||
"description": "Chirpstack JS and TS API",
|
"description": "Chirpstack JS and TS API",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
2
api/kotlin/build.gradle.kts
vendored
2
api/kotlin/build.gradle.kts
vendored
@ -9,7 +9,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group = "io.chirpstack"
|
group = "io.chirpstack"
|
||||||
version = "4.7.0"
|
version = "4.7.0-test.3"
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
|
@ -7,9 +7,15 @@ import "chirpstack-api/gw/gw.proto";
|
|||||||
import "google/protobuf/timestamp.proto";
|
import "google/protobuf/timestamp.proto";
|
||||||
|
|
||||||
message DeviceSession {
|
message DeviceSession {
|
||||||
|
// Device EUI.
|
||||||
|
bytes dev_eui = 1;
|
||||||
|
|
||||||
// Device address.
|
// Device address.
|
||||||
bytes dev_addr = 2;
|
bytes dev_addr = 2;
|
||||||
|
|
||||||
|
// Join EUI.
|
||||||
|
bytes join_eui = 3;
|
||||||
|
|
||||||
// LoRaWAN mac-version.
|
// LoRaWAN mac-version.
|
||||||
common.MacVersion mac_version = 4;
|
common.MacVersion mac_version = 4;
|
||||||
|
|
||||||
|
2
api/python/src/setup.py
vendored
2
api/python/src/setup.py
vendored
@ -18,7 +18,7 @@ CLASSIFIERS = [
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='chirpstack-api',
|
name='chirpstack-api',
|
||||||
version = "4.7.0",
|
version = "4.7.0-test.3",
|
||||||
url='https://github.com/brocaar/chirpstack-api',
|
url='https://github.com/brocaar/chirpstack-api',
|
||||||
author='Orne Brocaar',
|
author='Orne Brocaar',
|
||||||
author_email='info@brocaar.com',
|
author_email='info@brocaar.com',
|
||||||
|
57
api/rust/Cargo.lock
generated
vendored
57
api/rust/Cargo.lock
generated
vendored
@ -149,12 +149,6 @@ version = "2.4.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
|
checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "byteorder"
|
|
||||||
version = "1.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
@ -178,9 +172,8 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chirpstack_api"
|
name = "chirpstack_api"
|
||||||
version = "4.7.0"
|
version = "4.7.0-test.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"diesel",
|
|
||||||
"hex",
|
"hex",
|
||||||
"pbjson",
|
"pbjson",
|
||||||
"pbjson-build",
|
"pbjson-build",
|
||||||
@ -203,39 +196,6 @@ dependencies = [
|
|||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "diesel"
|
|
||||||
version = "2.1.4"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "62c6fcf842f17f8c78ecf7c81d75c5ce84436b41ee07e03f490fbb5f5a8731d8"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 2.4.0",
|
|
||||||
"byteorder",
|
|
||||||
"diesel_derives",
|
|
||||||
"itoa",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "diesel_derives"
|
|
||||||
version = "2.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ef8337737574f55a468005a83499da720f20c65586241ffea339db9ecdfd2b44"
|
|
||||||
dependencies = [
|
|
||||||
"diesel_table_macro_syntax",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "diesel_table_macro_syntax"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fc5557efc453706fed5e4fa85006fe9817c224c3f480a34c7e5959fd700921c5"
|
|
||||||
dependencies = [
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dirs"
|
name = "dirs"
|
||||||
version = "5.0.1"
|
version = "5.0.1"
|
||||||
@ -497,6 +457,15 @@ dependencies = [
|
|||||||
"hashbrown 0.14.0",
|
"hashbrown 0.14.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.10.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itertools"
|
name = "itertools"
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
@ -621,7 +590,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "2580e33f2292d34be285c5bc3dba5259542b083cfad6037b6d70345f24dcb735"
|
checksum = "2580e33f2292d34be285c5bc3dba5259542b083cfad6037b6d70345f24dcb735"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"itertools",
|
"itertools 0.11.0",
|
||||||
"prost",
|
"prost",
|
||||||
"prost-types",
|
"prost-types",
|
||||||
]
|
]
|
||||||
@ -732,7 +701,7 @@ checksum = "8bdf592881d821b83d471f8af290226c8d51402259e9bb5be7f9f8bdebbb11ac"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"heck",
|
"heck",
|
||||||
"itertools",
|
"itertools 0.10.5",
|
||||||
"log",
|
"log",
|
||||||
"multimap",
|
"multimap",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
@ -753,7 +722,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "265baba7fabd416cf5078179f7d2cbeca4ce7a9041111900675ea7c4cb8a4c32"
|
checksum = "265baba7fabd416cf5078179f7d2cbeca4ce7a9041111900675ea7c4cb8a4c32"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"itertools",
|
"itertools 0.10.5",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn",
|
||||||
|
2
api/rust/Cargo.toml
vendored
2
api/rust/Cargo.toml
vendored
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "chirpstack_api"
|
name = "chirpstack_api"
|
||||||
description = "ChirpStack Protobuf / gRPC API definitions."
|
description = "ChirpStack Protobuf / gRPC API definitions."
|
||||||
version = "4.7.0"
|
version = "4.7.0-test.3"
|
||||||
authors = ["Orne Brocaar <info@brocaar.com>"]
|
authors = ["Orne Brocaar <info@brocaar.com>"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
homepage = "https://www.chirpstack.io"
|
homepage = "https://www.chirpstack.io"
|
||||||
|
7
api/rust/src/internal.rs
vendored
7
api/rust/src/internal.rs
vendored
@ -2,12 +2,13 @@ include!(concat!(env!("OUT_DIR"), "/internal/internal.rs"));
|
|||||||
#[cfg(feature = "json")]
|
#[cfg(feature = "json")]
|
||||||
include!(concat!(env!("OUT_DIR"), "/internal/internal.serde.rs"));
|
include!(concat!(env!("OUT_DIR"), "/internal/internal.serde.rs"));
|
||||||
|
|
||||||
|
#[cfg(feature = "diesel")]
|
||||||
|
use std::io::Cursor;
|
||||||
#[cfg(feature = "diesel")]
|
#[cfg(feature = "diesel")]
|
||||||
use diesel::{backend::Backend, deserialize, serialize, sql_types::Binary};
|
use diesel::{backend::Backend, deserialize, serialize, sql_types::Binary};
|
||||||
#[cfg(feature = "diesel")]
|
#[cfg(feature = "diesel")]
|
||||||
use prost::Message;
|
use prost::Message;
|
||||||
#[cfg(feature = "diesel")]
|
|
||||||
use std::io::Cursor;
|
|
||||||
|
|
||||||
impl DeviceSession {
|
impl DeviceSession {
|
||||||
pub fn get_a_f_cnt_down(&self) -> u32 {
|
pub fn get_a_f_cnt_down(&self) -> u32 {
|
||||||
@ -48,7 +49,7 @@ impl serialize::ToSql<Binary, diesel::pg::Pg> for DeviceSession
|
|||||||
where
|
where
|
||||||
[u8]: serialize::ToSql<Binary, diesel::pg::Pg>,
|
[u8]: serialize::ToSql<Binary, diesel::pg::Pg>,
|
||||||
{
|
{
|
||||||
fn to_sql(&self, out: &mut serialize::Output<'_, '_, diesel::pg::Pg>) -> serialize::Result {
|
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(
|
<[u8] as serialize::ToSql<Binary, diesel::pg::Pg>>::to_sql(
|
||||||
&self.encode_to_vec(),
|
&self.encode_to_vec(),
|
||||||
&mut out.reborrow(),
|
&mut out.reborrow(),
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "backend"
|
name = "backend"
|
||||||
version = "4.7.0"
|
version = "4.7.0-test.3"
|
||||||
authors = ["Orne Brocaar <info@brocaar.com>"]
|
authors = ["Orne Brocaar <info@brocaar.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
publish = false
|
publish = false
|
||||||
|
@ -423,9 +423,8 @@ impl Client {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Serialize, Deserialize, PartialEq, Eq, Debug, Copy, Clone)]
|
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Copy, Clone)]
|
||||||
pub enum MessageType {
|
pub enum MessageType {
|
||||||
#[default]
|
|
||||||
JoinReq,
|
JoinReq,
|
||||||
JoinAns,
|
JoinAns,
|
||||||
RejoinReq,
|
RejoinReq,
|
||||||
@ -442,9 +441,14 @@ pub enum MessageType {
|
|||||||
XmitDataAns,
|
XmitDataAns,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Serialize, Deserialize, PartialEq, Eq, Debug, Copy, Clone)]
|
impl Default for MessageType {
|
||||||
|
fn default() -> Self {
|
||||||
|
MessageType::JoinReq
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Copy, Clone)]
|
||||||
pub enum ResultCode {
|
pub enum ResultCode {
|
||||||
#[default]
|
|
||||||
Success,
|
Success,
|
||||||
MICFailed,
|
MICFailed,
|
||||||
JoinReqFailed,
|
JoinReqFailed,
|
||||||
@ -467,6 +471,12 @@ pub enum ResultCode {
|
|||||||
Other,
|
Other,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for ResultCode {
|
||||||
|
fn default() -> Self {
|
||||||
|
ResultCode::Success
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Copy, Clone)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Copy, Clone)]
|
||||||
pub enum RatePolicy {
|
pub enum RatePolicy {
|
||||||
Drop,
|
Drop,
|
||||||
|
@ -3,7 +3,7 @@ name = "chirpstack"
|
|||||||
description = "ChirpStack is an open-source LoRaWAN(TM) Network Server"
|
description = "ChirpStack is an open-source LoRaWAN(TM) Network Server"
|
||||||
repository = "https://github.com/chirpstack/chirpstack"
|
repository = "https://github.com/chirpstack/chirpstack"
|
||||||
homepage = "https://www.chirpstack.io/"
|
homepage = "https://www.chirpstack.io/"
|
||||||
version = "4.7.0"
|
version = "4.7.0-test.3"
|
||||||
authors = ["Orne Brocaar <info@brocaar.com>"]
|
authors = ["Orne Brocaar <info@brocaar.com>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
publish = false
|
publish = false
|
||||||
|
@ -1736,7 +1736,7 @@ impl ApplicationService for Application {
|
|||||||
application::IftttConfiguration {
|
application::IftttConfiguration {
|
||||||
key: req_int.key.clone(),
|
key: req_int.key.clone(),
|
||||||
uplink_values: [
|
uplink_values: [
|
||||||
req_int.uplink_values.first().cloned().unwrap_or_default(),
|
req_int.uplink_values.get(0).cloned().unwrap_or_default(),
|
||||||
req_int.uplink_values.get(1).cloned().unwrap_or_default(),
|
req_int.uplink_values.get(1).cloned().unwrap_or_default(),
|
||||||
],
|
],
|
||||||
arbitrary_json: req_int.arbitrary_json,
|
arbitrary_json: req_int.arbitrary_json,
|
||||||
@ -1820,7 +1820,7 @@ impl ApplicationService for Application {
|
|||||||
application::IftttConfiguration {
|
application::IftttConfiguration {
|
||||||
key: req_int.key.clone(),
|
key: req_int.key.clone(),
|
||||||
uplink_values: [
|
uplink_values: [
|
||||||
req_int.uplink_values.first().cloned().unwrap_or_default(),
|
req_int.uplink_values.get(0).cloned().unwrap_or_default(),
|
||||||
req_int.uplink_values.get(1).cloned().unwrap_or_default(),
|
req_int.uplink_values.get(1).cloned().unwrap_or_default(),
|
||||||
],
|
],
|
||||||
arbitrary_json: req_int.arbitrary_json,
|
arbitrary_json: req_int.arbitrary_json,
|
||||||
|
@ -104,7 +104,7 @@ pub async fn _handle_request(bp: BasePayload, b: Vec<u8>) -> http::Response<hype
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
match joinserver::get(sender_id).await {
|
match joinserver::get(sender_id) {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
warn!("Unknown SenderID");
|
warn!("Unknown SenderID");
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
use std::collections::HashMap;
|
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
@ -8,13 +7,12 @@ use openidconnect::core::{
|
|||||||
CoreResponseType,
|
CoreResponseType,
|
||||||
};
|
};
|
||||||
use openidconnect::reqwest::async_http_client;
|
use openidconnect::reqwest::async_http_client;
|
||||||
use openidconnect::{AdditionalClaims, UserInfoClaims};
|
|
||||||
use openidconnect::{
|
use openidconnect::{
|
||||||
AuthenticationFlow, AuthorizationCode, ClientId, ClientSecret, CsrfToken, IssuerUrl, Nonce,
|
AuthenticationFlow, AuthorizationCode, ClientId, ClientSecret, CsrfToken, IssuerUrl, Nonce,
|
||||||
OAuth2TokenResponse, RedirectUrl, Scope,
|
OAuth2TokenResponse, RedirectUrl, Scope,
|
||||||
};
|
};
|
||||||
|
use openidconnect::{EmptyAdditionalClaims, UserInfoClaims};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Value;
|
|
||||||
use tracing::{error, trace};
|
use tracing::{error, trace};
|
||||||
use warp::{Rejection, Reply};
|
use warp::{Rejection, Reply};
|
||||||
|
|
||||||
@ -22,15 +20,7 @@ use crate::config;
|
|||||||
use crate::helpers::errors::PrintFullError;
|
use crate::helpers::errors::PrintFullError;
|
||||||
use crate::storage::{get_async_redis_conn, redis_key};
|
use crate::storage::{get_async_redis_conn, redis_key};
|
||||||
|
|
||||||
pub type User = UserInfoClaims<CustomClaims, CoreGenderClaim>;
|
pub type User = UserInfoClaims<EmptyAdditionalClaims, CoreGenderClaim>;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub struct CustomClaims {
|
|
||||||
#[serde(flatten)]
|
|
||||||
other: HashMap<String, Value>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AdditionalClaims for CustomClaims {}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct CallbackArgs {
|
pub struct CallbackArgs {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use tokio::sync::RwLock;
|
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
|
|
||||||
use crate::{config, stream};
|
use crate::{config, stream};
|
||||||
@ -16,7 +15,7 @@ pub async fn setup() -> Result<()> {
|
|||||||
info!("Setting up Join Server clients");
|
info!("Setting up Join Server clients");
|
||||||
let conf = config::get();
|
let conf = config::get();
|
||||||
|
|
||||||
let mut clients_w = CLIENTS.write().await;
|
let mut clients_w = CLIENTS.write().unwrap();
|
||||||
*clients_w = vec![];
|
*clients_w = vec![];
|
||||||
|
|
||||||
for js in &conf.join_server.servers {
|
for js in &conf.join_server.servers {
|
||||||
@ -39,8 +38,8 @@ pub async fn setup() -> Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get(join_eui: EUI64) -> Result<Arc<Client>> {
|
pub fn get(join_eui: EUI64) -> Result<Arc<Client>> {
|
||||||
let clients_r = CLIENTS.read().await;
|
let clients_r = CLIENTS.read().unwrap();
|
||||||
for client in clients_r.iter() {
|
for client in clients_r.iter() {
|
||||||
if client.0.matches(join_eui) {
|
if client.0.matches(join_eui) {
|
||||||
return Ok(client.1.clone());
|
return Ok(client.1.clone());
|
||||||
@ -54,7 +53,7 @@ pub async fn get(join_eui: EUI64) -> Result<Arc<Client>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub async fn reset() {
|
pub fn reset() {
|
||||||
let mut clients_w = CLIENTS.write().await;
|
let mut clients_w = CLIENTS.write().unwrap();
|
||||||
*clients_w = vec![];
|
*clients_w = vec![];
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ async fn get_ca_cert(ca_cert_file: &str, ca_key_file: &str) -> Result<Certificat
|
|||||||
let params = CertificateParams::from_ca_cert_pem(&ca_cert_s, ca_key)
|
let params = CertificateParams::from_ca_cert_pem(&ca_cert_s, ca_key)
|
||||||
.context("Parse gateway CA certificate")?;
|
.context("Parse gateway CA certificate")?;
|
||||||
|
|
||||||
Certificate::from_params(params).context("Init Certificate struct")
|
Ok(Certificate::from_params(params).context("Init Certificate struct")?)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This returns the CA, certificate and private-key as PEM encoded strings.
|
// This returns the CA, certificate and private-key as PEM encoded strings.
|
||||||
|
@ -185,6 +185,12 @@ pub fn run() {
|
|||||||
{{/each}}
|
{{/each}}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Device session expiration.
|
||||||
|
#
|
||||||
|
# The TTL value defines the time after which a device-session expires
|
||||||
|
# after no activity.
|
||||||
|
device_session_ttl="{{ network.device_session_ttl }}"
|
||||||
|
|
||||||
# Time to wait for uplink de-duplication.
|
# Time to wait for uplink de-duplication.
|
||||||
#
|
#
|
||||||
# This is the time that ChirpStack will wait for other gateways to receive
|
# This is the time that ChirpStack will wait for other gateways to receive
|
||||||
|
@ -363,7 +363,12 @@ impl Data {
|
|||||||
|
|
||||||
let gw_down = helpers::select_downlink_gateway(
|
let gw_down = helpers::select_downlink_gateway(
|
||||||
Some(self.tenant.id),
|
Some(self.tenant.id),
|
||||||
&self.device.get_device_session()?.region_config_id,
|
&self
|
||||||
|
.device
|
||||||
|
.device_session
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.region_config_id,
|
||||||
self.network_conf.gateway_prefer_min_margin,
|
self.network_conf.gateway_prefer_min_margin,
|
||||||
self.device_gateway_rx_info.as_mut().unwrap(),
|
self.device_gateway_rx_info.as_mut().unwrap(),
|
||||||
)?;
|
)?;
|
||||||
@ -623,7 +628,7 @@ impl Data {
|
|||||||
|
|
||||||
let ds = self.device.get_device_session()?;
|
let ds = self.device.get_device_session()?;
|
||||||
|
|
||||||
self.mac_commands = filter_mac_commands(ds, &self.mac_commands);
|
self.mac_commands = filter_mac_commands(&ds, &self.mac_commands);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,8 @@ pub async fn get_geoloc_buffer(
|
|||||||
let rx_info: Vec<gw::UplinkRxInfo> = uplink
|
let rx_info: Vec<gw::UplinkRxInfo> = uplink
|
||||||
.rx_info
|
.rx_info
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|&rx_info| {
|
.cloned()
|
||||||
|
.filter(|rx_info| {
|
||||||
let ts: DateTime<Utc> = match &rx_info.gw_time {
|
let ts: DateTime<Utc> = match &rx_info.gw_time {
|
||||||
None => {
|
None => {
|
||||||
return false;
|
return false;
|
||||||
@ -54,7 +55,6 @@ pub async fn get_geoloc_buffer(
|
|||||||
// The interval between now and then must be smaller than the TTL
|
// The interval between now and then must be smaller than the TTL
|
||||||
(ts - Utc::now()) < ttl
|
(ts - Utc::now()) < ttl
|
||||||
})
|
})
|
||||||
.cloned()
|
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if rx_info.len() > 3 {
|
if rx_info.len() > 3 {
|
||||||
|
@ -134,7 +134,7 @@ impl<'a> Integration<'a> {
|
|||||||
command: r"(?P<command>[\w]+)".to_string(),
|
command: r"(?P<command>[\w]+)".to_string(),
|
||||||
},
|
},
|
||||||
)?)?,
|
)?)?,
|
||||||
qos,
|
qos: qos,
|
||||||
json: conf.json,
|
json: conf.json,
|
||||||
client,
|
client,
|
||||||
templates,
|
templates,
|
||||||
|
@ -119,7 +119,7 @@ pub async fn save(name: &str, record: &Record) -> Result<()> {
|
|||||||
.unwrap(),
|
.unwrap(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let key = get_key(name, a, ts);
|
let key = get_key(&name, a, ts);
|
||||||
|
|
||||||
for (k, v) in &record.metrics {
|
for (k, v) in &record.metrics {
|
||||||
// Passing a reference to hincr will return a runtime error.
|
// Passing a reference to hincr will return a runtime error.
|
||||||
|
@ -119,7 +119,7 @@ pub async fn get_by_email_and_pw(email: &str, pw: &str) -> Result<User, Error> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if verify_password(pw, &u.password_hash) {
|
if verify_password(&pw, &u.password_hash) {
|
||||||
return Ok(u);
|
return Ok(u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ async fn handle_stream(
|
|||||||
k: &str,
|
k: &str,
|
||||||
v: &redis::Value,
|
v: &redis::Value,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
match k {
|
match k.as_ref() {
|
||||||
"up" => {
|
"up" => {
|
||||||
trace!(key = %k, id = %stream_id, "Event-log received from stream");
|
trace!(key = %k, id = %stream_id, "Event-log received from stream");
|
||||||
if let redis::Value::Data(b) = v {
|
if let redis::Value::Data(b) = v {
|
||||||
|
@ -276,7 +276,7 @@ async fn handle_stream(
|
|||||||
k: &str,
|
k: &str,
|
||||||
v: &redis::Value,
|
v: &redis::Value,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
match k {
|
match k.as_ref() {
|
||||||
"up" => {
|
"up" => {
|
||||||
trace!(key = %k, id = %stream_id, "Frame-log received from stream");
|
trace!(key = %k, id = %stream_id, "Frame-log received from stream");
|
||||||
if let redis::Value::Data(b) = v {
|
if let redis::Value::Data(b) = v {
|
||||||
|
@ -167,7 +167,7 @@ async fn test_fns_uplink() {
|
|||||||
sns_pr_start_req_mock.assert();
|
sns_pr_start_req_mock.assert();
|
||||||
sns_pr_start_req_mock.delete();
|
sns_pr_start_req_mock.delete();
|
||||||
|
|
||||||
joinserver::reset().await;
|
joinserver::reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
|
@ -246,7 +246,7 @@ async fn test_fns() {
|
|||||||
})()
|
})()
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
joinserver::reset().await;
|
joinserver::reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
@ -430,7 +430,7 @@ async fn test_sns() {
|
|||||||
pr_start_ans
|
pr_start_ans
|
||||||
);
|
);
|
||||||
|
|
||||||
joinserver::reset().await;
|
joinserver::reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
@ -588,5 +588,5 @@ async fn test_sns_roaming_not_allowed() {
|
|||||||
pr_start_ans
|
pr_start_ans
|
||||||
);
|
);
|
||||||
|
|
||||||
joinserver::reset().await;
|
joinserver::reset();
|
||||||
}
|
}
|
||||||
|
@ -215,7 +215,7 @@ impl Data {
|
|||||||
let mac = if let lrwn::Payload::MACPayload(pl) = &self.phy_payload.payload {
|
let mac = if let lrwn::Payload::MACPayload(pl) = &self.phy_payload.payload {
|
||||||
pl
|
pl
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::Anyhow(anyhow!("Expected MacPayload")));
|
return Err(Error::AnyhowError(anyhow!("Expected MacPayload")));
|
||||||
};
|
};
|
||||||
|
|
||||||
if roaming::is_roaming_dev_addr(mac.fhdr.devaddr) {
|
if roaming::is_roaming_dev_addr(mac.fhdr.devaddr) {
|
||||||
@ -234,7 +234,7 @@ impl Data {
|
|||||||
let dev_addr = if let lrwn::Payload::MACPayload(pl) = &self.phy_payload.payload {
|
let dev_addr = if let lrwn::Payload::MACPayload(pl) = &self.phy_payload.payload {
|
||||||
pl.fhdr.devaddr
|
pl.fhdr.devaddr
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::Anyhow(anyhow!("No MacPayload in PhyPayload")));
|
return Err(Error::AnyhowError(anyhow!("No MacPayload in PhyPayload")));
|
||||||
};
|
};
|
||||||
|
|
||||||
match device::get_for_phypayload_and_incr_f_cnt_up(
|
match device::get_for_phypayload_and_incr_f_cnt_up(
|
||||||
@ -277,7 +277,7 @@ impl Data {
|
|||||||
return Err(Error::Abort);
|
return Err(Error::Abort);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::Anyhow(
|
return Err(Error::AnyhowError(
|
||||||
anyhow::Error::new(e).context("Get device-session"),
|
anyhow::Error::new(e).context("Get device-session"),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -295,7 +295,7 @@ impl Data {
|
|||||||
let dev_addr = if let lrwn::Payload::MACPayload(pl) = &self.phy_payload.payload {
|
let dev_addr = if let lrwn::Payload::MACPayload(pl) = &self.phy_payload.payload {
|
||||||
pl.fhdr.devaddr
|
pl.fhdr.devaddr
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::Anyhow(anyhow!("No MacPayload in PhyPayload")));
|
return Err(Error::AnyhowError(anyhow!("No MacPayload in PhyPayload")));
|
||||||
};
|
};
|
||||||
|
|
||||||
let dr = relay_ctx.req.metadata.dr;
|
let dr = relay_ctx.req.metadata.dr;
|
||||||
@ -334,7 +334,7 @@ impl Data {
|
|||||||
return Err(Error::Abort);
|
return Err(Error::Abort);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::Anyhow(
|
return Err(Error::AnyhowError(
|
||||||
anyhow::Error::new(e).context("Get device-session"),
|
anyhow::Error::new(e).context("Get device-session"),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@ -585,7 +585,13 @@ impl Data {
|
|||||||
|
|
||||||
fn decrypt_f_opts_mac_commands(&mut self) -> Result<()> {
|
fn decrypt_f_opts_mac_commands(&mut self) -> Result<()> {
|
||||||
trace!("Decrypting mac-commands");
|
trace!("Decrypting mac-commands");
|
||||||
let ds = self.device.as_ref().unwrap().get_device_session()?;
|
let ds = self
|
||||||
|
.device
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.device_session
|
||||||
|
.as_ref()
|
||||||
|
.unwrap();
|
||||||
if ds.mac_version().to_string().starts_with("1.0") {
|
if ds.mac_version().to_string().starts_with("1.0") {
|
||||||
if let Err(e) = self.phy_payload.decode_f_opts_to_mac_commands() {
|
if let Err(e) = self.phy_payload.decode_f_opts_to_mac_commands() {
|
||||||
// This avoids failing in case of a corrupted mac-command in the frm_payload.
|
// This avoids failing in case of a corrupted mac-command in the frm_payload.
|
||||||
@ -604,7 +610,13 @@ impl Data {
|
|||||||
|
|
||||||
fn decrypt_frm_payload(&mut self) -> Result<()> {
|
fn decrypt_frm_payload(&mut self) -> Result<()> {
|
||||||
trace!("Decrypting FRMPayload");
|
trace!("Decrypting FRMPayload");
|
||||||
let ds = self.device.as_ref().unwrap().get_device_session()?;
|
let ds = self
|
||||||
|
.device
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.device_session
|
||||||
|
.as_ref()
|
||||||
|
.unwrap();
|
||||||
let mut f_port = 0;
|
let mut f_port = 0;
|
||||||
|
|
||||||
if let lrwn::Payload::MACPayload(pl) = &self.phy_payload.payload {
|
if let lrwn::Payload::MACPayload(pl) = &self.phy_payload.payload {
|
||||||
@ -644,7 +656,13 @@ impl Data {
|
|||||||
|
|
||||||
fn set_adr(&mut self) -> Result<()> {
|
fn set_adr(&mut self) -> Result<()> {
|
||||||
trace!("Set ADR flag in device-session");
|
trace!("Set ADR flag in device-session");
|
||||||
let ds = self.device.as_mut().unwrap().get_device_session_mut()?;
|
let ds = self
|
||||||
|
.device
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.device_session
|
||||||
|
.as_mut()
|
||||||
|
.unwrap();
|
||||||
if let lrwn::Payload::MACPayload(pl) = &self.phy_payload.payload {
|
if let lrwn::Payload::MACPayload(pl) = &self.phy_payload.payload {
|
||||||
ds.adr = pl.fhdr.f_ctrl.adr;
|
ds.adr = pl.fhdr.f_ctrl.adr;
|
||||||
}
|
}
|
||||||
@ -772,7 +790,7 @@ impl Data {
|
|||||||
if let lrwn::Payload::MACPayload(pl) = &self.phy_payload.payload {
|
if let lrwn::Payload::MACPayload(pl) = &self.phy_payload.payload {
|
||||||
if pl.fhdr.f_ctrl.adr_ack_req {
|
if pl.fhdr.f_ctrl.adr_ack_req {
|
||||||
let region_conf = region::get(&self.uplink_frame_set.region_config_id)?;
|
let region_conf = region::get(&self.uplink_frame_set.region_config_id)?;
|
||||||
let ds = d.get_device_session_mut()?;
|
let ds = d.device_session.as_mut().unwrap();
|
||||||
|
|
||||||
// We reset the device-session enabled_uplink_channel_indices and
|
// We reset the device-session enabled_uplink_channel_indices and
|
||||||
// extra_uplink_channels. On the downlink path, the mac-command handling will
|
// extra_uplink_channels. On the downlink path, the mac-command handling will
|
||||||
@ -843,7 +861,13 @@ impl Data {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn append_meta_data_to_uplink_history(&mut self) -> Result<()> {
|
fn append_meta_data_to_uplink_history(&mut self) -> Result<()> {
|
||||||
let ds = self.device.as_mut().unwrap().get_device_session_mut()?;
|
let ds = self
|
||||||
|
.device
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.device_session
|
||||||
|
.as_mut()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// ignore re-transmissions we don't know the source of the
|
// ignore re-transmissions we don't know the source of the
|
||||||
// re-transmission (it might be a replay-attack)
|
// re-transmission (it might be a replay-attack)
|
||||||
@ -888,7 +912,13 @@ impl Data {
|
|||||||
fn append_meta_data_to_uplink_history_relayed(&mut self) -> Result<()> {
|
fn append_meta_data_to_uplink_history_relayed(&mut self) -> Result<()> {
|
||||||
trace!("Apping meta-data of relayed uplink to upink history");
|
trace!("Apping meta-data of relayed uplink to upink history");
|
||||||
|
|
||||||
let ds = self.device.as_mut().unwrap().get_device_session_mut()?;
|
let ds = self
|
||||||
|
.device
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.device_session
|
||||||
|
.as_mut()
|
||||||
|
.unwrap();
|
||||||
let relay_ctx = self.relay_context.as_ref().unwrap();
|
let relay_ctx = self.relay_context.as_ref().unwrap();
|
||||||
|
|
||||||
// ignore re-transmissions we don't know the source of the
|
// ignore re-transmissions we don't know the source of the
|
||||||
@ -1365,10 +1395,13 @@ impl Data {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn _is_end_to_end_encrypted(&self) -> bool {
|
fn _is_end_to_end_encrypted(&self) -> bool {
|
||||||
let ds = match self.device.as_ref().unwrap().get_device_session() {
|
let ds = self
|
||||||
Ok(v) => v,
|
.device
|
||||||
Err(_) => return false,
|
.as_ref()
|
||||||
};
|
.unwrap()
|
||||||
|
.device_session
|
||||||
|
.as_ref()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
if !ds.js_session_key_id.is_empty() {
|
if !ds.js_session_key_id.is_empty() {
|
||||||
return true;
|
return true;
|
||||||
|
@ -9,5 +9,5 @@ pub enum Error {
|
|||||||
RoamingIsNotAllowed,
|
RoamingIsNotAllowed,
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Anyhow(#[from] anyhow::Error),
|
AnyhowError(#[from] anyhow::Error),
|
||||||
}
|
}
|
||||||
|
@ -136,8 +136,8 @@ pub fn get_time_since_gps_epoch_chrono(rx_info: &[gw::UplinkRxInfo]) -> Option<c
|
|||||||
pub fn get_start_location(rx_info: &[gw::UplinkRxInfo]) -> Option<common::Location> {
|
pub fn get_start_location(rx_info: &[gw::UplinkRxInfo]) -> Option<common::Location> {
|
||||||
let mut with_loc: Vec<gw::UplinkRxInfo> = rx_info
|
let mut with_loc: Vec<gw::UplinkRxInfo> = rx_info
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|&i| i.location.is_some())
|
|
||||||
.cloned()
|
.cloned()
|
||||||
|
.filter(|i| i.location.is_some())
|
||||||
.collect();
|
.collect();
|
||||||
with_loc.sort_by(|a, b| a.snr.partial_cmp(&b.snr).unwrap());
|
with_loc.sort_by(|a, b| a.snr.partial_cmp(&b.snr).unwrap());
|
||||||
with_loc
|
with_loc
|
||||||
|
@ -258,7 +258,7 @@ impl JoinRequest {
|
|||||||
|
|
||||||
if self.device_keys.is_none() {
|
if self.device_keys.is_none() {
|
||||||
trace!(join_eui = %jr.join_eui, "Getting Join Server client");
|
trace!(join_eui = %jr.join_eui, "Getting Join Server client");
|
||||||
self.js_client = Some(joinserver::get(jr.join_eui).await?);
|
self.js_client = Some(joinserver::get(jr.join_eui)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -58,7 +58,7 @@ impl JoinRequest {
|
|||||||
trace!("Getting home netid");
|
trace!("Getting home netid");
|
||||||
|
|
||||||
trace!(join_eui = %self.join_request.join_eui, "Trying to get join-server client");
|
trace!(join_eui = %self.join_request.join_eui, "Trying to get join-server client");
|
||||||
let js_client = joinserver::get(self.join_request.join_eui).await?;
|
let js_client = joinserver::get(self.join_request.join_eui)?;
|
||||||
|
|
||||||
let mut home_ns_req = backend::HomeNSReqPayload {
|
let mut home_ns_req = backend::HomeNSReqPayload {
|
||||||
dev_eui: self.join_request.dev_eui.to_vec(),
|
dev_eui: self.join_request.dev_eui.to_vec(),
|
||||||
|
@ -162,7 +162,7 @@ impl JoinRequest {
|
|||||||
|
|
||||||
if self.device_keys.is_none() {
|
if self.device_keys.is_none() {
|
||||||
trace!(join_eui = %jr.join_eui, "Getting Join Server client");
|
trace!(join_eui = %jr.join_eui, "Getting Join Server client");
|
||||||
self.js_client = Some(joinserver::get(jr.join_eui).await?);
|
self.js_client = Some(joinserver::get(jr.join_eui)?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -641,7 +641,13 @@ impl JoinRequest {
|
|||||||
async fn update_device(&mut self) -> Result<()> {
|
async fn update_device(&mut self) -> Result<()> {
|
||||||
trace!("Updating device");
|
trace!("Updating device");
|
||||||
let dp = self.device_profile.as_ref().unwrap();
|
let dp = self.device_profile.as_ref().unwrap();
|
||||||
let ds = self.device.as_ref().unwrap().get_device_session()?;
|
let ds = self
|
||||||
|
.device
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.device_session
|
||||||
|
.as_ref()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
self.device = Some(
|
self.device = Some(
|
||||||
device::partial_update(
|
device::partial_update(
|
||||||
|
@ -248,7 +248,7 @@ async fn deduplicate_put(
|
|||||||
async fn deduplicate_collect(key: &str) -> Result<gw::UplinkFrameSet> {
|
async fn deduplicate_collect(key: &str) -> Result<gw::UplinkFrameSet> {
|
||||||
let items_b: Vec<Vec<u8>> = {
|
let items_b: Vec<Vec<u8>> = {
|
||||||
redis::cmd("SMEMBERS")
|
redis::cmd("SMEMBERS")
|
||||||
.arg(key)
|
.arg(&key)
|
||||||
.query_async(&mut get_async_redis_conn().await?)
|
.query_async(&mut get_async_redis_conn().await?)
|
||||||
.await
|
.await
|
||||||
.context("Deduplication collect")?
|
.context("Deduplication collect")?
|
||||||
@ -285,7 +285,7 @@ async fn deduplicate_collect(key: &str) -> Result<gw::UplinkFrameSet> {
|
|||||||
pub async fn handle_uplink(deduplication_id: Uuid, uplink: gw::UplinkFrameSet) -> Result<()> {
|
pub async fn handle_uplink(deduplication_id: Uuid, uplink: gw::UplinkFrameSet) -> Result<()> {
|
||||||
let rx_info = &uplink
|
let rx_info = &uplink
|
||||||
.rx_info
|
.rx_info
|
||||||
.first()
|
.get(0)
|
||||||
.context("Unable to get first item from rx_info")?;
|
.context("Unable to get first item from rx_info")?;
|
||||||
|
|
||||||
let region_config_id = rx_info
|
let region_config_id = rx_info
|
||||||
|
@ -3,7 +3,7 @@ name = "lrwn_filters"
|
|||||||
description = "Library for filtering LoRaWAN payloads on DevAddr and JoinEUIs prefixes"
|
description = "Library for filtering LoRaWAN payloads on DevAddr and JoinEUIs prefixes"
|
||||||
homepage = "https://www.chirpstack.io/"
|
homepage = "https://www.chirpstack.io/"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
version = "4.7.0"
|
version = "4.7.0-test.3"
|
||||||
authors = ["Orne Brocaar <info@brocaar.com>"]
|
authors = ["Orne Brocaar <info@brocaar.com>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
repository = "https://github.com/chirpstack/chirpstack"
|
repository = "https://github.com/chirpstack/chirpstack"
|
||||||
|
@ -3,7 +3,7 @@ name = "lrwn"
|
|||||||
description = "Library for encoding / decoding LoRaWAN frames."
|
description = "Library for encoding / decoding LoRaWAN frames."
|
||||||
homepage = "https://www.chirpstack.io"
|
homepage = "https://www.chirpstack.io"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
version = "4.7.0"
|
version = "4.7.0-test.3"
|
||||||
authors = ["Orne Brocaar <info@brocaar.com>"]
|
authors = ["Orne Brocaar <info@brocaar.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
repository = "https://github.com/chirpstack/chirpstack"
|
repository = "https://github.com/chirpstack/chirpstack"
|
||||||
|
@ -130,7 +130,7 @@ impl serialize::ToSql<Binary, diesel::pg::Pg> for AES128Key
|
|||||||
where
|
where
|
||||||
[u8]: serialize::ToSql<Binary, diesel::pg::Pg>,
|
[u8]: serialize::ToSql<Binary, diesel::pg::Pg>,
|
||||||
{
|
{
|
||||||
fn to_sql(&self, out: &mut serialize::Output<'_, '_, diesel::pg::Pg>) -> serialize::Result {
|
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(
|
<[u8] as serialize::ToSql<Binary, diesel::pg::Pg>>::to_sql(
|
||||||
&self.to_bytes(),
|
&self.to_bytes(),
|
||||||
&mut out.reborrow(),
|
&mut out.reborrow(),
|
||||||
|
@ -273,7 +273,7 @@ impl serialize::ToSql<Binary, diesel::pg::Pg> for DevAddr
|
|||||||
where
|
where
|
||||||
[u8]: serialize::ToSql<Binary, diesel::pg::Pg>,
|
[u8]: serialize::ToSql<Binary, diesel::pg::Pg>,
|
||||||
{
|
{
|
||||||
fn to_sql(&self, out: &mut serialize::Output<'_, '_, diesel::pg::Pg>) -> serialize::Result {
|
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(
|
<[u8] as serialize::ToSql<Binary, diesel::pg::Pg>>::to_sql(
|
||||||
&self.to_be_bytes(),
|
&self.to_be_bytes(),
|
||||||
&mut out.reborrow(),
|
&mut out.reborrow(),
|
||||||
|
@ -138,7 +138,7 @@ impl serialize::ToSql<Binary, diesel::pg::Pg> for EUI64
|
|||||||
where
|
where
|
||||||
[u8]: serialize::ToSql<Binary, diesel::pg::Pg>,
|
[u8]: serialize::ToSql<Binary, diesel::pg::Pg>,
|
||||||
{
|
{
|
||||||
fn to_sql(&self, out: &mut serialize::Output<'_, '_, diesel::pg::Pg>) -> serialize::Result {
|
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(
|
<[u8] as serialize::ToSql<Binary, diesel::pg::Pg>>::to_sql(
|
||||||
&self.to_be_bytes(),
|
&self.to_be_bytes(),
|
||||||
&mut out.reborrow(),
|
&mut out.reborrow(),
|
||||||
@ -197,7 +197,7 @@ impl FromStr for EUI64Prefix {
|
|||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
let s = s.to_string();
|
let s = s.to_string();
|
||||||
let mut size: u64 = 64;
|
let mut size: u64 = 64;
|
||||||
let parts: Vec<&str> = s.split('/').collect();
|
let parts: Vec<&str> = s.split("/").collect();
|
||||||
if parts.len() == 2 {
|
if parts.len() == 2 {
|
||||||
size = parts[1].parse().map_err(|_| Error::EUI64PrefixFormat)?;
|
size = parts[1].parse().map_err(|_| Error::EUI64PrefixFormat)?;
|
||||||
}
|
}
|
||||||
|
@ -1891,7 +1891,7 @@ impl serialize::ToSql<SmallInt, diesel::pg::Pg> for RelayModeActivation
|
|||||||
where
|
where
|
||||||
i16: serialize::ToSql<SmallInt, diesel::pg::Pg>,
|
i16: serialize::ToSql<SmallInt, diesel::pg::Pg>,
|
||||||
{
|
{
|
||||||
fn to_sql(&self, out: &mut serialize::Output<'_, '_, diesel::pg::Pg>) -> serialize::Result {
|
fn to_sql<'b>(&self, out: &mut serialize::Output<'b, '_, diesel::pg::Pg>) -> serialize::Result {
|
||||||
let i = self.to_u8() as i16;
|
let i = self.to_u8() as i16;
|
||||||
<i16 as serialize::ToSql<SmallInt, diesel::pg::Pg>>::to_sql(&i, &mut out.reborrow())
|
<i16 as serialize::ToSql<SmallInt, diesel::pg::Pg>>::to_sql(&i, &mut out.reborrow())
|
||||||
}
|
}
|
||||||
@ -2191,7 +2191,7 @@ impl PayloadCodec for UpdateUplinkListReqPayload {
|
|||||||
let mut b = [0; 26];
|
let mut b = [0; 26];
|
||||||
cur.read_exact(&mut b)?;
|
cur.read_exact(&mut b)?;
|
||||||
|
|
||||||
Ok(UpdateUplinkListReqPayload {
|
return Ok(UpdateUplinkListReqPayload {
|
||||||
uplink_list_idx: b[0] & 0x0f,
|
uplink_list_idx: b[0] & 0x0f,
|
||||||
uplink_limit: UplinkLimitPL::from_u8(b[1]),
|
uplink_limit: UplinkLimitPL::from_u8(b[1]),
|
||||||
dev_addr: crate::DevAddr::from_le_bytes({
|
dev_addr: crate::DevAddr::from_le_bytes({
|
||||||
@ -2209,7 +2209,7 @@ impl PayloadCodec for UpdateUplinkListReqPayload {
|
|||||||
bb.copy_from_slice(&b[10..26]);
|
bb.copy_from_slice(&b[10..26]);
|
||||||
bb
|
bb
|
||||||
}),
|
}),
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode(&self) -> Result<Vec<u8>> {
|
fn encode(&self) -> Result<Vec<u8>> {
|
||||||
@ -2432,7 +2432,7 @@ impl PowerLevel {
|
|||||||
pub fn from_bytes(b: [u8; 2]) -> Self {
|
pub fn from_bytes(b: [u8; 2]) -> Self {
|
||||||
PowerLevel {
|
PowerLevel {
|
||||||
wor_snr: (b[0] & 0x1f) as isize - 20,
|
wor_snr: (b[0] & 0x1f) as isize - 20,
|
||||||
wor_rssi: -(((b[0] >> 5) | ((b[1] & 0x0f) << 3)) as isize) - 15,
|
wor_rssi: -1 * ((b[0] >> 5) | ((b[1] & 0x0f) << 3)) as isize - 15,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2456,7 +2456,7 @@ impl PowerLevel {
|
|||||||
|
|
||||||
// Encode values
|
// Encode values
|
||||||
let wor_snr = (wor_snr + 20) as u8;
|
let wor_snr = (wor_snr + 20) as u8;
|
||||||
let wor_rssi = -(wor_rssi + 15) as u8;
|
let wor_rssi = ((wor_rssi as isize + 15) * -1) as u8;
|
||||||
|
|
||||||
[wor_snr | wor_rssi << 5, wor_rssi >> 3]
|
[wor_snr | wor_rssi << 5, wor_rssi >> 3]
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,7 @@ impl NetID {
|
|||||||
match self.netid_type() {
|
match self.netid_type() {
|
||||||
0 | 1 => self.get_id(6),
|
0 | 1 => self.get_id(6),
|
||||||
2 => self.get_id(9),
|
2 => self.get_id(9),
|
||||||
3..=7 => self.get_id(21),
|
3 | 4 | 5 | 6 | 7 => self.get_id(21),
|
||||||
_ => vec![],
|
_ => vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1176,7 +1176,11 @@ impl Region for Configuration {
|
|||||||
for pl in pls {
|
for pl in pls {
|
||||||
if pl.redundancy.ch_mask_cntl == 6 || pl.redundancy.ch_mask_cntl == 7 {
|
if pl.redundancy.ch_mask_cntl == 6 || pl.redundancy.ch_mask_cntl == 7 {
|
||||||
for cm in ch_mask.iter_mut().take(64) {
|
for cm in ch_mask.iter_mut().take(64) {
|
||||||
*cm = pl.redundancy.ch_mask_cntl == 6;
|
if pl.redundancy.ch_mask_cntl == 6 {
|
||||||
|
*cm = true;
|
||||||
|
} else {
|
||||||
|
*cm = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i, cm) in pl.ch_mask.into_iter().enumerate() {
|
for (i, cm) in pl.ch_mask.into_iter().enumerate() {
|
||||||
|
@ -864,7 +864,11 @@ impl Region for Configuration {
|
|||||||
for pl in pls {
|
for pl in pls {
|
||||||
if pl.redundancy.ch_mask_cntl == 6 || pl.redundancy.ch_mask_cntl == 7 {
|
if pl.redundancy.ch_mask_cntl == 6 || pl.redundancy.ch_mask_cntl == 7 {
|
||||||
for cm in ch_mask.iter_mut().take(64) {
|
for cm in ch_mask.iter_mut().take(64) {
|
||||||
*cm = pl.redundancy.ch_mask_cntl == 6;
|
if pl.redundancy.ch_mask_cntl == 6 {
|
||||||
|
*cm = true;
|
||||||
|
} else {
|
||||||
|
*cm = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i, cm) in pl.ch_mask.into_iter().enumerate() {
|
for (i, cm) in pl.ch_mask.into_iter().enumerate() {
|
||||||
|
@ -19,7 +19,7 @@ impl UplinkMetadata {
|
|||||||
UplinkMetadata {
|
UplinkMetadata {
|
||||||
dr: b[0] & 0x0f,
|
dr: b[0] & 0x0f,
|
||||||
snr: ((b[0] >> 4) | ((b[1] & 0x01) << 4)) as isize - 20,
|
snr: ((b[0] >> 4) | ((b[1] & 0x01) << 4)) as isize - 20,
|
||||||
rssi: -((b[1] >> 1) as isize) - 15,
|
rssi: -1 * (b[1] >> 1) as isize - 15,
|
||||||
wor_channel: b[2] & 0x03,
|
wor_channel: b[2] & 0x03,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,7 +52,7 @@ impl UplinkMetadata {
|
|||||||
|
|
||||||
// Encode values
|
// Encode values
|
||||||
let snr = (snr + 20) as u8;
|
let snr = (snr + 20) as u8;
|
||||||
let rssi = -(rssi + 15) as u8;
|
let rssi = ((rssi as isize + 15) * -1) as u8;
|
||||||
|
|
||||||
Ok([self.dr | snr << 4, snr >> 4 | rssi << 1, self.wor_channel])
|
Ok([self.dr | snr << 4, snr >> 4 | rssi << 1, self.wor_channel])
|
||||||
}
|
}
|
||||||
@ -97,7 +97,7 @@ pub struct ForwardDownlinkReq {
|
|||||||
impl ForwardDownlinkReq {
|
impl ForwardDownlinkReq {
|
||||||
pub fn from_slice(b: &[u8]) -> Result<Self> {
|
pub fn from_slice(b: &[u8]) -> Result<Self> {
|
||||||
Ok(ForwardDownlinkReq {
|
Ok(ForwardDownlinkReq {
|
||||||
payload: Box::new(PhyPayload::from_slice(b)?),
|
payload: Box::new(PhyPayload::from_slice(&b)?),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
[toolchain]
|
[toolchain]
|
||||||
channel = "1.76.0"
|
channel = "1.74.0"
|
||||||
components = ["rustfmt", "clippy"]
|
components = ["rustfmt", "clippy"]
|
||||||
profile = "default"
|
profile = "default"
|
@ -1,4 +1,4 @@
|
|||||||
{ pkgs ? import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/nixos-23.11.tar.gz") {} }:
|
{ pkgs ? import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/nixos-23.05.tar.gz") {} }:
|
||||||
|
|
||||||
pkgs.mkShell {
|
pkgs.mkShell {
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "chirpstack-ui",
|
"name": "chirpstack-ui",
|
||||||
"version": "4.7.0",
|
"version": "4.7.0-test.3",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ant-design/colors": "^7.0.0",
|
"@ant-design/colors": "^7.0.0",
|
||||||
|
@ -75,11 +75,10 @@ function Header({ user }: { user: User }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let oidcEnabled = settings!.getOpenidConnect()!.getEnabled();
|
let oidcEnabled = settings!.getOpenidConnect()!.getEnabled();
|
||||||
let oAuth2Enabled = settings!.getOauth2()!.getEnabled();
|
|
||||||
|
|
||||||
const menu = (
|
const menu = (
|
||||||
<Menu>
|
<Menu>
|
||||||
{!(oidcEnabled || oAuth2Enabled) && (
|
{!oidcEnabled && (
|
||||||
<Menu.Item>
|
<Menu.Item>
|
||||||
<Link to={`/users/${user.getId()}/password`}>Change password</Link>
|
<Link to={`/users/${user.getId()}/password`}>Change password</Link>
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
|
Reference in New Issue
Block a user