mirror of
https://github.com/chirpstack/chirpstack.git
synced 2025-04-15 15:49:15 +00:00
Compare commits
11 Commits
v4.4.0
...
api/go/v4.
Author | SHA1 | Date | |
---|---|---|---|
f66186bb7b | |||
3f8f746dc5 | |||
57ab993a88 | |||
a975cf3223 | |||
9d543603d5 | |||
e9be79e948 | |||
0c9e22d255 | |||
4031c5cb95 | |||
258e103f22 | |||
3aa8bdbecc | |||
96767e954f |
790
Cargo.lock
generated
790
Cargo.lock
generated
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.4.0",
|
||||
"version": "4.4.2",
|
||||
"description": "Chirpstack gRPC-web API",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
|
2
api/java/build.gradle.kts
vendored
2
api/java/build.gradle.kts
vendored
@ -8,7 +8,7 @@ plugins {
|
||||
}
|
||||
|
||||
group = "io.chirpstack"
|
||||
version = "4.4.0"
|
||||
version = "4.4.2"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
2
api/js/package.json
vendored
2
api/js/package.json
vendored
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@chirpstack/chirpstack-api",
|
||||
"version": "4.4.0",
|
||||
"version": "4.4.2",
|
||||
"description": "Chirpstack JS and TS API",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
|
2
api/kotlin/build.gradle.kts
vendored
2
api/kotlin/build.gradle.kts
vendored
@ -9,7 +9,7 @@ plugins {
|
||||
}
|
||||
|
||||
group = "io.chirpstack"
|
||||
version = "4.4.0"
|
||||
version = "4.4.2"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
|
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.4.0",
|
||||
version = "4.4.2",
|
||||
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
@ -108,7 +108,7 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chirpstack_api"
|
||||
version = "4.4.0"
|
||||
version = "4.4.2"
|
||||
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.4.0"
|
||||
version = "4.4.2"
|
||||
authors = ["Orne Brocaar <info@brocaar.com>"]
|
||||
license = "MIT"
|
||||
homepage = "https://www.chirpstack.io"
|
||||
|
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "backend"
|
||||
version = "4.4.0"
|
||||
version = "4.4.2"
|
||||
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.4.0"
|
||||
version = "4.4.2"
|
||||
authors = ["Orne Brocaar <info@brocaar.com>"]
|
||||
edition = "2021"
|
||||
publish = false
|
||||
@ -42,6 +42,7 @@ tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = [
|
||||
"fmt",
|
||||
"ansi",
|
||||
"json",
|
||||
], default-features = true }
|
||||
|
||||
# ChirpStack API definitions
|
||||
@ -64,7 +65,7 @@ hmac = "0.12"
|
||||
sha2 = "0.10"
|
||||
urlencoding = "2.1"
|
||||
geohash = "0.13"
|
||||
gcp_auth = "0.8"
|
||||
gcp_auth = "0.9"
|
||||
lapin = "2.1"
|
||||
tokio-executor-trait = "2.1"
|
||||
tokio-reactor-trait = "1.1"
|
||||
@ -87,7 +88,7 @@ tower = "0.4"
|
||||
futures = "0.3"
|
||||
http = "0.2"
|
||||
http-body = "0.4"
|
||||
rust-embed = "6.6"
|
||||
rust-embed = "6.8"
|
||||
mime_guess = "2.0"
|
||||
tower-http = { version = "0.4", features = ["trace", "auth"] }
|
||||
|
||||
@ -100,14 +101,14 @@ pbkdf2 = { version = "0.12", features = ["simple"] }
|
||||
rand_core = { version = "0.6", features = ["std"] }
|
||||
jsonwebtoken = "8.2"
|
||||
openssl = { version = "0.10" }
|
||||
openidconnect = { version = "3.1", features = ["accept-rfc3339-timestamps"] }
|
||||
openidconnect = { version = "3.3", features = ["accept-rfc3339-timestamps"] }
|
||||
|
||||
# MQTT
|
||||
paho-mqtt = { version = "0.12", features = ["ssl"] }
|
||||
hex = "0.4"
|
||||
|
||||
# Codecs
|
||||
rquickjs = { version = "0.1", features = [
|
||||
rquickjs = { version = "0.3", features = [
|
||||
"bindgen",
|
||||
"loader",
|
||||
"array-buffer",
|
||||
@ -123,7 +124,7 @@ aes = "0.8"
|
||||
rand = "0.8"
|
||||
base64 = "0.21"
|
||||
async-recursion = "1.0"
|
||||
regex = "1.7"
|
||||
regex = "1.9"
|
||||
petgraph = "0.6"
|
||||
prometheus-client = "0.21"
|
||||
pin-project = "1.0"
|
||||
|
@ -41,9 +41,9 @@ dist:
|
||||
test:
|
||||
cargo fmt --check
|
||||
cargo clippy --no-deps
|
||||
cargo test
|
||||
TZ=UTC cargo test
|
||||
|
||||
test-all:
|
||||
cargo fmt --check
|
||||
cargo clippy --no-deps
|
||||
cargo test --features test-all-integrations
|
||||
TZ=UTC cargo test --features test-all-integrations
|
@ -4,6 +4,23 @@ use super::super::config;
|
||||
|
||||
pub fn run() {
|
||||
let template = r#"
|
||||
# Logging configuration
|
||||
[logging]
|
||||
|
||||
# Log level.
|
||||
#
|
||||
# Valid options are:
|
||||
# * TRACE
|
||||
# * DEBUG
|
||||
# * INFO
|
||||
# * WARN
|
||||
# * ERROR
|
||||
# * OFF
|
||||
level="{{ logging.level }}"
|
||||
|
||||
# Log as JSON.
|
||||
json={{ logging.json }}
|
||||
|
||||
# PostgreSQL configuration.
|
||||
[postgresql]
|
||||
|
||||
@ -180,6 +197,17 @@ pub fn run() {
|
||||
# Mac-commands disabled.
|
||||
mac_commands_disabled={{ network.mac_commands_disabled }}
|
||||
|
||||
# Custom ADR plugins.
|
||||
#
|
||||
# The custom ADR plugin must be implemented in JavaScript. For an example
|
||||
# skeleton, please see:
|
||||
# https://github.com/chirpstack/chirpstack/blob/master/examples/adr_plugins/plugin_skeleton.js
|
||||
adr_plugins=[
|
||||
{{#each network.adr_plugins}}
|
||||
"{{this}}",
|
||||
{{/each}}
|
||||
]
|
||||
|
||||
|
||||
# Scheduler settings.
|
||||
[network.scheduler]
|
||||
|
25
chirpstack/src/cmd/create_api_key.rs
Normal file
25
chirpstack/src/cmd/create_api_key.rs
Normal file
@ -0,0 +1,25 @@
|
||||
use anyhow::Result;
|
||||
|
||||
use crate::api::auth::claims;
|
||||
use crate::config;
|
||||
use crate::storage::api_key;
|
||||
|
||||
pub async fn run(name: &str) -> Result<()> {
|
||||
let conf = config::get();
|
||||
|
||||
crate::storage::setup().await?;
|
||||
|
||||
let key = api_key::create(api_key::ApiKey {
|
||||
name: name.to_string(),
|
||||
is_admin: true,
|
||||
..Default::default()
|
||||
})
|
||||
.await?;
|
||||
|
||||
let token = claims::AuthClaim::new_for_api_key(&key.id).encode(conf.api.secret.as_ref())?;
|
||||
|
||||
println!("id: {}", key.id);
|
||||
println!("token: {}", token);
|
||||
|
||||
Ok(())
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
pub mod configfile;
|
||||
pub mod create_api_key;
|
||||
pub mod import_legacy_lorawan_devices_repository;
|
||||
pub mod print_ds;
|
||||
pub mod root;
|
||||
|
@ -22,11 +22,11 @@ pub async fn decode(
|
||||
let conf = config::get();
|
||||
let max_run_ts = SystemTime::now() + conf.codec.js.max_execution_time;
|
||||
|
||||
let resolver = rquickjs::BuiltinResolver::default()
|
||||
let resolver = rquickjs::loader::BuiltinResolver::default()
|
||||
.with_module("base64-js")
|
||||
.with_module("ieee754")
|
||||
.with_module("buffer");
|
||||
let loader = rquickjs::BuiltinLoader::default()
|
||||
let loader = rquickjs::loader::BuiltinLoader::default()
|
||||
.with_module("base64-js", vendor_base64_js::SCRIPT)
|
||||
.with_module("ieee754", vendor_ieee754::SCRIPT)
|
||||
.with_module("buffer", vendor_buffer::SCRIPT);
|
||||
@ -71,7 +71,7 @@ pub async fn decode(
|
||||
|
||||
let res: rquickjs::Object = ctx.eval_with_options(
|
||||
script,
|
||||
rquickjs::EvalOptions {
|
||||
rquickjs::context::EvalOptions {
|
||||
strict: false,
|
||||
..Default::default()
|
||||
},
|
||||
@ -107,11 +107,11 @@ pub async fn encode(
|
||||
let conf = config::get();
|
||||
let max_run_ts = SystemTime::now() + conf.codec.js.max_execution_time;
|
||||
|
||||
let resolver = rquickjs::BuiltinResolver::default()
|
||||
let resolver = rquickjs::loader::BuiltinResolver::default()
|
||||
.with_module("base64-js")
|
||||
.with_module("ieee754")
|
||||
.with_module("buffer");
|
||||
let loader = rquickjs::BuiltinLoader::default()
|
||||
let loader = rquickjs::loader::BuiltinLoader::default()
|
||||
.with_module("base64-js", vendor_base64_js::SCRIPT)
|
||||
.with_module("ieee754", vendor_ieee754::SCRIPT)
|
||||
.with_module("buffer", vendor_buffer::SCRIPT);
|
||||
@ -154,7 +154,7 @@ pub async fn encode(
|
||||
|
||||
let res: rquickjs::Object = ctx.eval_with_options(
|
||||
script,
|
||||
rquickjs::EvalOptions {
|
||||
rquickjs::context::EvalOptions {
|
||||
strict: false,
|
||||
..Default::default()
|
||||
},
|
||||
|
@ -37,12 +37,14 @@ pub struct Configuration {
|
||||
#[serde(default)]
|
||||
pub struct Logging {
|
||||
pub level: String,
|
||||
pub json: bool,
|
||||
}
|
||||
|
||||
impl Default for Logging {
|
||||
fn default() -> Self {
|
||||
Logging {
|
||||
level: "info".into(),
|
||||
json: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1788,6 +1788,11 @@ impl Data {
|
||||
dev_eui: device.dev_eui.to_vec(),
|
||||
provisioned: false,
|
||||
});
|
||||
|
||||
// Return because we can't add multiple sets and if we would combine
|
||||
// multiple commands as a single set, it might not fit in a single
|
||||
// downlink.
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,6 @@ extern crate diesel;
|
||||
extern crate anyhow;
|
||||
|
||||
use std::path::Path;
|
||||
use std::process;
|
||||
use std::str::FromStr;
|
||||
|
||||
use anyhow::Result;
|
||||
@ -78,6 +77,13 @@ enum Commands {
|
||||
#[arg(short, long, value_name = "DIR")]
|
||||
dir: String,
|
||||
},
|
||||
|
||||
/// Create global API key.
|
||||
CreateApiKey {
|
||||
/// Name.
|
||||
#[arg(short, long, value_name = "NAME")]
|
||||
name: String,
|
||||
},
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
@ -92,30 +98,32 @@ async fn main() -> Result<()> {
|
||||
("lrwn", Level::from_str(&conf.logging.level).unwrap()),
|
||||
]);
|
||||
|
||||
tracing_subscriber::registry()
|
||||
.with(tracing_subscriber::fmt::layer())
|
||||
.with(filter)
|
||||
.init();
|
||||
|
||||
if let Some(Commands::Configfile {}) = &cli.command {
|
||||
cmd::configfile::run();
|
||||
process::exit(0);
|
||||
if conf.logging.json {
|
||||
tracing_subscriber::registry()
|
||||
.with(tracing_subscriber::fmt::layer().json())
|
||||
.with(filter)
|
||||
.init();
|
||||
} else {
|
||||
tracing_subscriber::registry()
|
||||
.with(tracing_subscriber::fmt::layer())
|
||||
.with(filter)
|
||||
.init();
|
||||
}
|
||||
|
||||
if let Some(Commands::PrintDs { dev_eui }) = &cli.command {
|
||||
let dev_eui = EUI64::from_str(dev_eui).unwrap();
|
||||
cmd::print_ds::run(&dev_eui).await.unwrap();
|
||||
process::exit(0);
|
||||
match &cli.command {
|
||||
Some(Commands::Configfile {}) => cmd::configfile::run(),
|
||||
Some(Commands::PrintDs { dev_eui }) => {
|
||||
let dev_eui = EUI64::from_str(dev_eui).unwrap();
|
||||
cmd::print_ds::run(&dev_eui).await.unwrap();
|
||||
}
|
||||
Some(Commands::ImportLegacyLorawanDevicesRepository { dir }) => {
|
||||
cmd::import_legacy_lorawan_devices_repository::run(Path::new(&dir))
|
||||
.await
|
||||
.unwrap()
|
||||
}
|
||||
Some(Commands::CreateApiKey { name }) => cmd::create_api_key::run(&name).await?,
|
||||
None => cmd::root::run().await?,
|
||||
}
|
||||
|
||||
if let Some(Commands::ImportLegacyLorawanDevicesRepository { dir }) = &cli.command {
|
||||
cmd::import_legacy_lorawan_devices_repository::run(Path::new(&dir))
|
||||
.await
|
||||
.unwrap();
|
||||
process::exit(0);
|
||||
}
|
||||
|
||||
cmd::root::run().await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -791,35 +791,48 @@ impl JoinRequest {
|
||||
|
||||
device_profile.reset_session_to_boot_params(&mut ds);
|
||||
|
||||
if let Some(CFList::Channels(channels)) =
|
||||
region_conf.get_cf_list(device_profile.mac_version)
|
||||
{
|
||||
for f in channels.iter().cloned() {
|
||||
if f == 0 {
|
||||
continue;
|
||||
match region_conf.get_cf_list(device_profile.mac_version) {
|
||||
Some(CFList::Channels(channels)) => {
|
||||
for f in channels.iter().cloned() {
|
||||
if f == 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let i = region_conf
|
||||
.get_uplink_channel_index(f, true)
|
||||
.context("Unknown cf_list frequency")?;
|
||||
|
||||
ds.enabled_uplink_channel_indices.push(i as u32);
|
||||
|
||||
// add extra channel to extra uplink channels, so that we can
|
||||
// keep track on frequency and data-rate changes
|
||||
let c = region_conf
|
||||
.get_uplink_channel(i)
|
||||
.context("Get uplink channel error")?;
|
||||
|
||||
ds.extra_uplink_channels.insert(
|
||||
i as u32,
|
||||
internal::DeviceSessionChannel {
|
||||
frequency: c.frequency,
|
||||
min_dr: c.min_dr as u32,
|
||||
max_dr: c.max_dr as u32,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
let i = region_conf
|
||||
.get_uplink_channel_index(f, true)
|
||||
.context("Unknown cf_list frequency")?;
|
||||
|
||||
ds.enabled_uplink_channel_indices.push(i as u32);
|
||||
|
||||
// add extra channel to extra uplink channels, so that we can
|
||||
// keep track on frequency and data-rate changes
|
||||
let c = region_conf
|
||||
.get_uplink_channel(i)
|
||||
.context("Get uplink channel error")?;
|
||||
|
||||
ds.extra_uplink_channels.insert(
|
||||
i as u32,
|
||||
internal::DeviceSessionChannel {
|
||||
frequency: c.frequency,
|
||||
min_dr: c.min_dr as u32,
|
||||
max_dr: c.max_dr as u32,
|
||||
},
|
||||
);
|
||||
}
|
||||
Some(CFList::ChannelMask(masks)) => {
|
||||
ds.enabled_uplink_channel_indices = vec![];
|
||||
|
||||
for (block_i, block) in masks.iter().enumerate() {
|
||||
for (channel_i, enabled) in block.into_iter().enumerate() {
|
||||
if enabled {
|
||||
ds.enabled_uplink_channel_indices
|
||||
.push((channel_i + (block_i * 16)) as u32);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
|
||||
device_session::save(&ds)
|
||||
|
@ -3,7 +3,7 @@ name = "lrwn_filters"
|
||||
description = "Library for filtering LoRaWAN payloads on DevAddr and JoinEUIs prefixes"
|
||||
homepage = "https://www.chirpstack.io/"
|
||||
license = "MIT"
|
||||
version = "4.4.0"
|
||||
version = "4.4.2"
|
||||
authors = ["Orne Brocaar <info@brocaar.com>"]
|
||||
edition = "2021"
|
||||
repository = "https://github.com/chirpstack/chirpstack"
|
||||
|
@ -3,7 +3,7 @@ name = "lrwn"
|
||||
description = "Library for encoding / decoding LoRaWAN frames."
|
||||
homepage = "https://www.chirpstack.io"
|
||||
license = "MIT"
|
||||
version = "4.4.0"
|
||||
version = "4.4.2"
|
||||
authors = ["Orne Brocaar <info@brocaar.com>"]
|
||||
edition = "2018"
|
||||
repository = "https://github.com/chirpstack/chirpstack"
|
||||
|
@ -141,6 +141,10 @@ impl CFListChannelMasks {
|
||||
|
||||
Ok(b)
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> std::slice::Iter<'_, ChMask> {
|
||||
self.0.iter()
|
||||
}
|
||||
}
|
||||
|
||||
/// ChMask encodes the channels usable for uplink access. 0 = channel 1,
|
||||
|
@ -18,5 +18,4 @@ pkgs.mkShell {
|
||||
BINDGEN_EXTRA_CLANG_ARGS = "-I${pkgs.llvmPackages.libclang.lib}/lib/clang/${pkgs.llvmPackages.libclang.version}/include";
|
||||
DOCKER_BUILDKIT = "1";
|
||||
NIX_STORE = "/nix/store";
|
||||
TZ="UTC";
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "chirpstack-ui",
|
||||
"version": "4.4.0",
|
||||
"version": "4.4.2",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@ant-design/colors": "^6.0.0",
|
||||
|
Reference in New Issue
Block a user