Compare commits

...

16 Commits

Author SHA1 Message Date
Orne Brocaar
6d084b3b21 Add option to pass auth. header to join-server.
Some checks failed
CI / tests (postgres) (push) Has been cancelled
CI / tests (sqlite) (push) Has been cancelled
CI / dist (postgres) (push) Has been cancelled
CI / dist (sqlite) (push) Has been cancelled
2025-04-16 10:55:08 +01:00
Orne Brocaar
75e9106bbb Remove lazy_static dependency. 2025-04-16 09:51:49 +01:00
Orne Brocaar
4ce4828a78 lrwn: Remove lazy_static dependency.
Some checks are pending
CI / tests (postgres) (push) Waiting to run
CI / tests (sqlite) (push) Waiting to run
CI / dist (postgres) (push) Blocked by required conditions
CI / dist (sqlite) (push) Blocked by required conditions
2025-04-15 16:06:03 +01:00
Orne Brocaar
9ecf4fef1b ui: Update vite to v6.2.6. 2025-04-15 15:54:17 +01:00
dependabot[bot]
8f9316af2c
Bump golang.org/x/net from 0.33.0 to 0.36.0 in /examples/frame_log/go (#651)
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.33.0 to 0.36.0.
- [Commits](https://github.com/golang/net/compare/v0.33.0...v0.36.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-version: 0.36.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-15 15:28:32 +01:00
dependabot[bot]
1f2a7d390a
Bump vite from 5.4.12 to 5.4.18 in /ui (#652)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.4.12 to 5.4.18.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.4.18/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.4.18/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 5.4.18
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-15 15:28:19 +01:00
Orne Brocaar
990bf57da5 Update dependencies. 2025-04-15 15:07:10 +01:00
Orne Brocaar
b336690a65 Update tonic to 0.13. 2025-04-15 15:00:23 +01:00
Orne Brocaar
7597bcaabf Replace tenant UUID by gen_random_uuid() in pg migration.
This should have been part of 5fd57de6ce7e5682a6b8e908acd28510cd4ba550.
2025-04-15 13:51:53 +01:00
Orne Brocaar
0ae1294a63 Show origin in case of parse error.
Fixes #632.
2025-04-15 13:32:01 +01:00
Orne Brocaar
8e0a29ed55 Update PostgreSQL to v13 in tests.
This is oldest version that is still supported.
2025-04-15 12:41:49 +01:00
Orne Brocaar
5fd57de6ce Replace static UUID by gen_random_uuid() in pg migration.
Fixes #634.
2025-04-15 12:28:44 +01:00
Orne Brocaar
d91fb77617 Install cargo-deb through shell.nix. 2025-04-15 11:29:01 +01:00
Orne Brocaar
fa63c306fd Add default ADR example in JS. 2025-04-15 10:16:17 +01:00
dependabot[bot]
7d1e85e575
Bump golang.org/x/net from 0.33.0 to 0.36.0 in /api/go (#639)
Some checks failed
CI / tests (postgres) (push) Has been cancelled
CI / tests (sqlite) (push) Has been cancelled
CI / dist (postgres) (push) Has been cancelled
CI / dist (sqlite) (push) Has been cancelled
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.33.0 to 0.36.0.
- [Commits](https://github.com/golang/net/compare/v0.33.0...v0.36.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-26 11:40:20 +00:00
Orne Brocaar
e392f52444 Update prometheus-client dependency. 2025-03-26 11:34:22 +00:00
43 changed files with 1402 additions and 1427 deletions

479
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -6,9 +6,7 @@ dist:
cd chirpstack && make dist
# Install dev dependencies
# TODO: test latest cargo-deb and move it to shell.nix.
dev-dependencies:
cargo install cargo-deb --version 1.43.1 --locked
cargo install cargo-generate-rpm --version 0.12.1 --locked
# Set the versions

7
api/go/go.mod vendored
View File

@ -1,6 +1,7 @@
module github.com/chirpstack/chirpstack/api/go/v4
go 1.21
toolchain go1.24.1
require (
google.golang.org/genproto/googleapis/api v0.0.0-20240325203815-454cdb8f5daa
@ -10,8 +11,8 @@ require (
require (
github.com/golang/protobuf v1.5.4 // indirect
golang.org/x/net v0.33.0 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/text v0.21.0 // indirect
golang.org/x/net v0.36.0 // indirect
golang.org/x/sys v0.30.0 // indirect
golang.org/x/text v0.22.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240325203815-454cdb8f5daa // indirect
)

12
api/go/go.sum vendored
View File

@ -2,12 +2,12 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA=
golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
google.golang.org/genproto/googleapis/api v0.0.0-20240325203815-454cdb8f5daa h1:Jt1XW5PaLXF1/ePZrznsh/aAUvI7Adfc3LY1dAKlzRs=
google.golang.org/genproto/googleapis/api v0.0.0-20240325203815-454cdb8f5daa/go.mod h1:K4kfzHtI0kqWA79gecJarFtDn/Mls+GxQcg3Zox91Ac=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240325203815-454cdb8f5daa h1:RBgMaUMP+6soRkik4VoN8ojR2nex2TqZwjSSogic+eo=

4
api/rust/Cargo.toml vendored
View File

@ -19,7 +19,7 @@
prost-types = "0.13"
hex = "0.4"
rand = "0.9"
tonic = { version = "0.12", features = [
tonic = { version = "0.13", features = [
"codegen",
"prost",
], default-features = false, optional = true }
@ -29,7 +29,7 @@
serde = { version = "1.0", optional = true }
[build-dependencies]
tonic-build = { version = "0.12", features = [
tonic-build = { version = "0.13", features = [
"prost",
], default-features = false }
pbjson-build = "0.7"

View File

@ -24,6 +24,5 @@
async-trait = "0.1"
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1.44", features = ["macros", "rt-multi-thread"] }
lazy_static = "1.5"
serde_json = "1.0"
toml = "0.8"

View File

@ -1,8 +1,6 @@
#[macro_use]
extern crate lazy_static;
use std::io::Cursor;
use std::str::FromStr;
use std::sync::LazyLock;
use anyhow::Result;
use async_trait::async_trait;
@ -13,10 +11,8 @@ use tracing_subscriber::{filter, prelude::*};
use chirpstack_api::{integration as integration_pb, prost::Message};
lazy_static! {
static ref INTEGRATION: RwLock<Option<Box<dyn IntegrationTrait + Sync + Send>>> =
RwLock::new(None);
}
static INTEGRATION: LazyLock<RwLock<Option<Box<dyn IntegrationTrait + Sync + Send>>>> =
LazyLock::new(|| RwLock::new(None));
#[derive(Default, Deserialize, Clone)]
#[serde(default)]

View File

@ -78,9 +78,9 @@
] }
# gRPC and Protobuf
tonic = "0.12"
tonic-web = "0.12"
tonic-reflection = "0.12"
tonic = "0.13"
tonic-web = "0.13"
tonic-reflection = "0.13"
tokio = { version = "1.44", features = ["macros", "rt-multi-thread"] }
tokio-stream = "0.1"
prost-types = "0.13"
@ -95,7 +95,7 @@
futures-util = "0.3"
http = "1.3"
http-body = "1.0"
rust-embed = "8.6"
rust-embed = "8.7"
mime_guess = "2.0"
tower-http = { version = "0.6", features = ["trace", "auth"] }
@ -137,7 +137,6 @@
] }
# Misc
lazy_static = "1.5"
uuid = { version = "1.16", features = ["v4", "serde"] }
chrono = "0.4"
async-trait = "0.1"
@ -147,7 +146,7 @@
async-recursion = "1.1"
regex = "1.11"
petgraph = "0.7"
prometheus-client = "0.22"
prometheus-client = "0.23"
pin-project = "1.1"
scoped-futures = { version = "0.1", features = ["std"] }
signal-hook = "0.3"

View File

@ -26,7 +26,7 @@ insert into "user" (
password_hash,
note
) values (
'05244f12-6daf-4e1f-8315-c66783a0ab56',
gen_random_uuid(),
now(),
now(),
true,
@ -63,7 +63,7 @@ insert into "tenant" (
max_gateway_count,
private_gateways
) values (
'52f14cd4-c6f1-4fbd-8f87-4025e1d49242',
gen_random_uuid(),
now(),
now(),
'ChirpStack',

View File

@ -1,4 +1,5 @@
use std::collections::HashMap;
use std::sync::LazyLock;
use anyhow::Result;
use async_trait::async_trait;
@ -14,10 +15,8 @@ pub mod lora_lr_fhss;
pub mod lr_fhss;
pub mod plugin;
lazy_static! {
static ref ADR_ALGORITHMS: RwLock<HashMap<String, Box<dyn Handler + Sync + Send>>> =
RwLock::new(HashMap::new());
}
static ADR_ALGORITHMS: LazyLock<RwLock<HashMap<String, Box<dyn Handler + Sync + Send>>>> =
LazyLock::new(|| RwLock::new(HashMap::new()));
pub async fn setup() -> Result<()> {
info!("Setting up adr algorithms");

View File

@ -1,3 +1,4 @@
use std::sync::LazyLock;
use std::time::{Duration, Instant};
use std::{
future::Future,
@ -5,7 +6,7 @@ use std::{
task::{Context, Poll},
};
use anyhow::Result;
use anyhow::{Context as AnyhowContext, Result};
use axum::{response::IntoResponse, routing::get, Router};
use http::{
header::{self, HeaderMap, HeaderValue},
@ -67,33 +68,31 @@ pub mod relay;
pub mod tenant;
pub mod user;
lazy_static! {
static ref GRPC_COUNTER: Family<GrpcLabels, Counter> = {
let counter = Family::<GrpcLabels, Counter>::default();
prometheus::register(
"api_requests_handled",
"Number of API requests handled by service, method and status code",
counter.clone(),
);
counter
};
static ref GRPC_HISTOGRAM: Family<GrpcLabels, Histogram> = {
let histogram = Family::<GrpcLabels, Histogram>::new_with_constructor(|| {
Histogram::new(
[
0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0,
]
.into_iter(),
)
});
prometheus::register(
"api_requests_handled_seconds",
"Duration of API requests handled by service, method and status code",
histogram.clone(),
);
histogram
};
}
static GRPC_COUNTER: LazyLock<Family<GrpcLabels, Counter>> = LazyLock::new(|| {
let counter = Family::<GrpcLabels, Counter>::default();
prometheus::register(
"api_requests_handled",
"Number of API requests handled by service, method and status code",
counter.clone(),
);
counter
});
static GRPC_HISTOGRAM: LazyLock<Family<GrpcLabels, Histogram>> = LazyLock::new(|| {
let histogram = Family::<GrpcLabels, Histogram>::new_with_constructor(|| {
Histogram::new(
[
0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0,
]
.into_iter(),
)
});
prometheus::register(
"api_requests_handled_seconds",
"Duration of API requests handled by service, method and status code",
histogram.clone(),
);
histogram
});
#[derive(RustEmbed)]
#[folder = "../ui/build"]
@ -103,7 +102,7 @@ type BoxError = Box<dyn std::error::Error + Send + Sync>;
pub async fn setup() -> Result<()> {
let conf = config::get();
let bind = conf.api.bind.parse()?;
let bind = conf.api.bind.parse().context("Parse api.bind config")?;
info!(bind = %bind, "Setting up API interface");
@ -114,7 +113,7 @@ pub async fn setup() -> Result<()> {
.route("/auth/oauth2/callback", get(oauth2::callback_handler))
.fallback(service_static_handler)
.into_service()
.map_response(|r| r.map(tonic::body::boxed));
.map_response(|r| r.map(tonic::body::Body::new));
let grpc = TonicServer::builder()
.accept_http1(true)

View File

@ -1,4 +1,4 @@
use std::sync::Arc;
use std::sync::{Arc, LazyLock};
use anyhow::Result;
use tokio::sync::RwLock;
@ -8,9 +8,8 @@ use crate::{config, stream};
use backend::{Client, ClientConfig};
use lrwn::{EUI64Prefix, EUI64};
lazy_static! {
static ref CLIENTS: RwLock<Vec<(EUI64Prefix, Arc<Client>)>> = RwLock::new(vec![]);
}
static CLIENTS: LazyLock<RwLock<Vec<(EUI64Prefix, Arc<Client>)>>> =
LazyLock::new(|| RwLock::new(vec![]));
pub async fn setup() -> Result<()> {
info!("Setting up Join Server clients");
@ -30,6 +29,11 @@ pub async fn setup() -> Result<()> {
tls_key: js.tls_key.clone(),
async_timeout: js.async_timeout,
request_log_sender: stream::backend_interfaces::get_log_sender().await,
authorization: if js.authorization_header.is_empty() {
None
} else {
Some(js.authorization_header.clone())
},
..Default::default()
})?;

View File

@ -1,7 +1,7 @@
use std::collections::HashMap;
use std::io::Cursor;
use std::str::FromStr;
use std::sync::Arc;
use std::sync::{Arc, LazyLock};
use anyhow::Result;
use chrono::{Duration, DurationRound};
@ -15,9 +15,8 @@ use backend::{Client, ClientConfig, GWInfoElement, ULMetaData};
use chirpstack_api::{common, gw};
use lrwn::{region, DevAddr, NetID, EUI64};
lazy_static! {
static ref CLIENTS: RwLock<HashMap<NetID, Arc<Client>>> = RwLock::new(HashMap::new());
}
static CLIENTS: LazyLock<RwLock<HashMap<NetID, Arc<Client>>>> =
LazyLock::new(|| RwLock::new(HashMap::new()));
pub async fn setup() -> Result<()> {
info!("Setting up roaming clients");

View File

@ -797,6 +797,11 @@ pub fn run() {
# #
# # Set this to enable client-certificate authentication with the join-server.
# tls_key="/path/to/tls_key.pem"
# # Authorization header.
# #
# # Optional value of the Authorization header, e.g. token or password.
# authorization_header="Bearer sometoken"
{{#each join_server.servers}}
[[join_server.servers]]
@ -807,6 +812,7 @@ pub fn run() {
ca_cert="{{ this.ca_cert }}"
tls_cert="{{ this.tls_cert }}"
tls_key="{{ this.tls_key }}"
authorization_header="{{ this.authorization_header }}"
{{/each}}

View File

@ -1,5 +1,5 @@
use std::path::Path;
use std::sync::{Arc, Mutex};
use std::sync::{Arc, LazyLock, Mutex};
use std::time::Duration;
use std::{env, fs};
@ -9,9 +9,8 @@ use serde::{Deserialize, Serialize};
use lrwn::region::CommonName;
use lrwn::{AES128Key, DevAddrPrefix, EUI64Prefix, NetID};
lazy_static! {
static ref CONFIG: Mutex<Arc<Configuration>> = Mutex::new(Arc::new(Default::default()));
}
static CONFIG: LazyLock<Mutex<Arc<Configuration>>> =
LazyLock::new(|| Mutex::new(Arc::new(Default::default())));
#[derive(Default, Serialize, Deserialize, Clone)]
#[serde(default)]
@ -525,6 +524,7 @@ pub struct JoinServerServer {
pub ca_cert: String,
pub tls_cert: String,
pub tls_key: String,
pub authorization_header: String,
}
#[derive(Serialize, Deserialize, Default, Clone)]

View File

@ -1,3 +1,5 @@
use std::sync::LazyLock;
use aes::cipher::generic_array::GenericArray;
use aes::cipher::{BlockEncrypt, KeyInit};
use aes::{Aes128, Block};
@ -7,14 +9,11 @@ use tracing::debug;
use lrwn::DevAddr;
lazy_static! {
static ref BEACON_PERIOD: Duration = Duration::try_seconds(128).unwrap();
static ref BEACON_RESERVED: Duration = Duration::try_milliseconds(2120).unwrap();
static ref BEACON_GUARD: Duration = Duration::try_seconds(3).unwrap();
static ref BEACON_WINDOW: Duration = Duration::try_milliseconds(122880).unwrap();
static ref PING_PERIOD_BASE: usize = 1 << 12;
static ref SLOT_LEN: Duration = Duration::try_milliseconds(30).unwrap();
}
static BEACON_PERIOD: LazyLock<Duration> = LazyLock::new(|| Duration::try_seconds(128).unwrap());
static BEACON_RESERVED: LazyLock<Duration> =
LazyLock::new(|| Duration::try_milliseconds(2120).unwrap());
static PING_PERIOD_BASE: usize = 1 << 12;
static SLOT_LEN: LazyLock<Duration> = LazyLock::new(|| Duration::try_milliseconds(30).unwrap());
pub fn get_beacon_start(ts: Duration) -> Duration {
Duration::try_seconds(ts.num_seconds() - (ts.num_seconds() % BEACON_PERIOD.num_seconds()))
@ -26,7 +25,7 @@ pub fn get_ping_offset(beacon_ts: Duration, dev_addr: &DevAddr, ping_nb: usize)
return Err(anyhow!("ping_nb must be > 0"));
}
let ping_period = *PING_PERIOD_BASE / ping_nb;
let ping_period = PING_PERIOD_BASE / ping_nb;
let beacon_time = (beacon_ts.num_seconds() % (1 << 32)) as u32;
let key_bytes: [u8; 16] = [0x00; 16];
@ -54,7 +53,7 @@ pub fn get_next_ping_slot_after(
}
let mut beacon_start_ts = get_beacon_start(after_gps_epoch_ts);
let ping_period = *PING_PERIOD_BASE / ping_nb;
let ping_period = PING_PERIOD_BASE / ping_nb;
loop {
let ping_offset = get_ping_offset(beacon_start_ts, dev_addr, ping_nb)?;
@ -122,7 +121,7 @@ pub mod test {
for k in 0..8 {
let mut beacon_ts = Duration::zero();
let ping_nb: usize = 1 << k;
let ping_period = *PING_PERIOD_BASE / ping_nb;
let ping_period = PING_PERIOD_BASE / ping_nb;
let dev_addr = DevAddr::from_be_bytes([0, 0, 0, 0]);
for _ in 0..100000 {

View File

@ -1,3 +1,5 @@
use std::sync::LazyLock;
use anyhow::Result;
use async_trait::async_trait;
use tokio::sync::RwLock;
@ -6,11 +8,10 @@ use chirpstack_api::gw;
use super::GatewayBackend;
lazy_static! {
static ref DOWNLINK_FRAMES: RwLock<Vec<gw::DownlinkFrame>> = RwLock::new(Vec::new());
static ref GATEWAY_CONFIGURATIONS: RwLock<Vec<gw::GatewayConfiguration>> =
RwLock::new(Vec::new());
}
static DOWNLINK_FRAMES: LazyLock<RwLock<Vec<gw::DownlinkFrame>>> =
LazyLock::new(|| RwLock::new(Vec::new()));
static GATEWAY_CONFIGURATIONS: LazyLock<RwLock<Vec<gw::GatewayConfiguration>>> =
LazyLock::new(|| RwLock::new(Vec::new()));
pub async fn reset() {
DOWNLINK_FRAMES.write().await.drain(..);

View File

@ -1,4 +1,5 @@
use std::collections::HashMap;
use std::sync::LazyLock;
use anyhow::{Context, Result};
use async_trait::async_trait;
@ -11,10 +12,8 @@ use crate::config;
pub mod mock;
mod mqtt;
lazy_static! {
static ref BACKENDS: RwLock<HashMap<String, Box<dyn GatewayBackend + Sync + Send>>> =
RwLock::new(HashMap::new());
}
static BACKENDS: LazyLock<RwLock<HashMap<String, Box<dyn GatewayBackend + Sync + Send>>>> =
LazyLock::new(|| RwLock::new(HashMap::new()));
#[async_trait]
pub trait GatewayBackend {

View File

@ -1,6 +1,6 @@
use std::collections::HashMap;
use std::io::Cursor;
use std::sync::RwLock;
use std::sync::{LazyLock, RwLock};
use std::time::Duration;
use anyhow::Result;
@ -38,27 +38,26 @@ struct CommandLabels {
command: String,
}
lazy_static! {
static ref EVENT_COUNTER: Family<EventLabels, Counter> = {
let counter = Family::<EventLabels, Counter>::default();
prometheus::register(
"gateway_backend_mqtt_events",
"Number of events received",
counter.clone(),
);
counter
};
static ref COMMAND_COUNTER: Family<CommandLabels, Counter> = {
let counter = Family::<CommandLabels, Counter>::default();
prometheus::register(
"gateway_backend_mqtt_commands",
"Number of commands sent",
counter.clone(),
);
counter
};
static ref GATEWAY_JSON: RwLock<HashMap<String, bool>> = RwLock::new(HashMap::new());
}
static EVENT_COUNTER: LazyLock<Family<EventLabels, Counter>> = LazyLock::new(|| {
let counter = Family::<EventLabels, Counter>::default();
prometheus::register(
"gateway_backend_mqtt_events",
"Number of events received",
counter.clone(),
);
counter
});
static COMMAND_COUNTER: LazyLock<Family<CommandLabels, Counter>> = LazyLock::new(|| {
let counter = Family::<CommandLabels, Counter>::default();
prometheus::register(
"gateway_backend_mqtt_commands",
"Number of commands sent",
counter.clone(),
);
counter
});
static GATEWAY_JSON: LazyLock<RwLock<HashMap<String, bool>>> =
LazyLock::new(|| RwLock::new(HashMap::new()));
pub struct MqttBackend<'a> {
client: AsyncClient,

View File

@ -1,82 +1,85 @@
use std::sync::LazyLock;
use chrono::{DateTime, Duration, TimeZone, Utc};
lazy_static! {
static ref GPS_EPOCH_TIME: DateTime<Utc> = Utc.with_ymd_and_hms(1980, 1, 6, 0, 0, 0).unwrap();
static ref LEAP_SECONDS_TABLE: Vec<(DateTime<Utc>, Duration)> = vec![
static GPS_EPOCH_TIME: LazyLock<DateTime<Utc>> =
LazyLock::new(|| Utc.with_ymd_and_hms(1980, 1, 6, 0, 0, 0).unwrap());
static LEAP_SECONDS_TABLE: LazyLock<Vec<(DateTime<Utc>, Duration)>> = LazyLock::new(|| {
vec![
(
Utc.with_ymd_and_hms(1981, 6, 30, 23, 59, 59).unwrap(),
Duration::try_seconds(1).unwrap()
Duration::try_seconds(1).unwrap(),
),
(
Utc.with_ymd_and_hms(1982, 6, 30, 23, 59, 59).unwrap(),
Duration::try_seconds(1).unwrap()
Duration::try_seconds(1).unwrap(),
),
(
Utc.with_ymd_and_hms(1983, 6, 30, 23, 59, 59).unwrap(),
Duration::try_seconds(1).unwrap()
Duration::try_seconds(1).unwrap(),
),
(
Utc.with_ymd_and_hms(1985, 6, 30, 23, 59, 59).unwrap(),
Duration::try_seconds(1).unwrap()
Duration::try_seconds(1).unwrap(),
),
(
Utc.with_ymd_and_hms(1987, 12, 31, 23, 59, 59).unwrap(),
Duration::try_seconds(1).unwrap()
Duration::try_seconds(1).unwrap(),
),
(
Utc.with_ymd_and_hms(1989, 12, 31, 23, 59, 59).unwrap(),
Duration::try_seconds(1).unwrap()
Duration::try_seconds(1).unwrap(),
),
(
Utc.with_ymd_and_hms(1990, 12, 31, 23, 59, 59).unwrap(),
Duration::try_seconds(1).unwrap()
Duration::try_seconds(1).unwrap(),
),
(
Utc.with_ymd_and_hms(1992, 6, 30, 23, 59, 59).unwrap(),
Duration::try_seconds(1).unwrap()
Duration::try_seconds(1).unwrap(),
),
(
Utc.with_ymd_and_hms(1993, 6, 30, 23, 59, 59).unwrap(),
Duration::try_seconds(1).unwrap()
Duration::try_seconds(1).unwrap(),
),
(
Utc.with_ymd_and_hms(1994, 6, 30, 23, 59, 59).unwrap(),
Duration::try_seconds(1).unwrap()
Duration::try_seconds(1).unwrap(),
),
(
Utc.with_ymd_and_hms(1995, 12, 31, 23, 59, 59).unwrap(),
Duration::try_seconds(1).unwrap()
Duration::try_seconds(1).unwrap(),
),
(
Utc.with_ymd_and_hms(1997, 6, 30, 23, 59, 59).unwrap(),
Duration::try_seconds(1).unwrap()
Duration::try_seconds(1).unwrap(),
),
(
Utc.with_ymd_and_hms(1998, 12, 31, 23, 59, 59).unwrap(),
Duration::try_seconds(1).unwrap()
Duration::try_seconds(1).unwrap(),
),
(
Utc.with_ymd_and_hms(2005, 12, 31, 23, 59, 59).unwrap(),
Duration::try_seconds(1).unwrap()
Duration::try_seconds(1).unwrap(),
),
(
Utc.with_ymd_and_hms(2008, 12, 31, 23, 59, 59).unwrap(),
Duration::try_seconds(1).unwrap()
Duration::try_seconds(1).unwrap(),
),
(
Utc.with_ymd_and_hms(2012, 6, 30, 23, 59, 59).unwrap(),
Duration::try_seconds(1).unwrap()
Duration::try_seconds(1).unwrap(),
),
(
Utc.with_ymd_and_hms(2015, 6, 30, 23, 59, 59).unwrap(),
Duration::try_seconds(1).unwrap()
Duration::try_seconds(1).unwrap(),
),
(
Utc.with_ymd_and_hms(2016, 12, 31, 23, 59, 59).unwrap(),
Duration::try_seconds(1).unwrap()
Duration::try_seconds(1).unwrap(),
),
];
}
]
});
pub trait ToGpsTime {
fn to_gps_time(&self) -> Duration;

View File

@ -1,4 +1,5 @@
use std::collections::HashMap;
use std::sync::LazyLock;
use anyhow::Result;
use async_trait::async_trait;
@ -19,10 +20,8 @@ use chirpstack_api::integration;
// implement re-connect on error. To reconnect within the Integration struct would require
// mutability of the Integration struct, which is not possible without changing the
// IntegrationTrait as we would need to change the (&self, ...) signatures to (&mut self, ...).
lazy_static! {
static ref CONNECTION: RwLock<Option<Connection>> = RwLock::new(None);
static ref CHANNEL: RwLock<Option<Channel>> = RwLock::new(None);
}
static CONNECTION: LazyLock<RwLock<Option<Connection>>> = LazyLock::new(|| RwLock::new(None));
static CHANNEL: LazyLock<RwLock<Option<Channel>>> = LazyLock::new(|| RwLock::new(None));
pub struct Integration<'a> {
templates: Handlebars<'a>,

View File

@ -1,4 +1,5 @@
use std::collections::HashMap;
use std::sync::LazyLock;
use anyhow::Result;
use async_trait::async_trait;
@ -8,17 +9,22 @@ use chirpstack_api::integration;
use super::Integration as IntegrationTrait;
lazy_static! {
static ref UPLINK_EVENTS: RwLock<Vec<integration::UplinkEvent>> = RwLock::new(Vec::new());
static ref JOIN_EVENTS: RwLock<Vec<integration::JoinEvent>> = RwLock::new(Vec::new());
static ref ACK_EVENTS: RwLock<Vec<integration::AckEvent>> = RwLock::new(Vec::new());
static ref TXACK_EVENTS: RwLock<Vec<integration::TxAckEvent>> = RwLock::new(Vec::new());
static ref LOG_EVENTS: RwLock<Vec<integration::LogEvent>> = RwLock::new(Vec::new());
static ref STATUS_EVENTS: RwLock<Vec<integration::StatusEvent>> = RwLock::new(Vec::new());
static ref LOCATION_EVENTS: RwLock<Vec<integration::LocationEvent>> = RwLock::new(Vec::new());
static ref INTEGRATION_EVENTS: RwLock<Vec<integration::IntegrationEvent>> =
RwLock::new(Vec::new());
}
static UPLINK_EVENTS: LazyLock<RwLock<Vec<integration::UplinkEvent>>> =
LazyLock::new(|| RwLock::new(Vec::new()));
static JOIN_EVENTS: LazyLock<RwLock<Vec<integration::JoinEvent>>> =
LazyLock::new(|| RwLock::new(Vec::new()));
static ACK_EVENTS: LazyLock<RwLock<Vec<integration::AckEvent>>> =
LazyLock::new(|| RwLock::new(Vec::new()));
static TXACK_EVENTS: LazyLock<RwLock<Vec<integration::TxAckEvent>>> =
LazyLock::new(|| RwLock::new(Vec::new()));
static LOG_EVENTS: LazyLock<RwLock<Vec<integration::LogEvent>>> =
LazyLock::new(|| RwLock::new(Vec::new()));
static STATUS_EVENTS: LazyLock<RwLock<Vec<integration::StatusEvent>>> =
LazyLock::new(|| RwLock::new(Vec::new()));
static LOCATION_EVENTS: LazyLock<RwLock<Vec<integration::LocationEvent>>> =
LazyLock::new(|| RwLock::new(Vec::new()));
static INTEGRATION_EVENTS: LazyLock<RwLock<Vec<integration::IntegrationEvent>>> =
LazyLock::new(|| RwLock::new(Vec::new()));
pub async fn reset() {
UPLINK_EVENTS.write().await.drain(..);

View File

@ -1,5 +1,6 @@
use std::collections::HashMap;
use std::str::FromStr;
use std::sync::LazyLock;
use anyhow::{Context, Result};
use async_trait::async_trait;
@ -33,11 +34,11 @@ mod postgresql;
mod redis;
mod thingsboard;
lazy_static! {
static ref GLOBAL_INTEGRATIONS: RwLock<Vec<Box<dyn Integration + Sync + Send>>> =
RwLock::new(Vec::new());
static ref MOCK_INTEGRATION: RwLock<bool> = RwLock::new(false);
}
static GLOBAL_INTEGRATIONS: LazyLock<RwLock<Vec<Box<dyn Integration + Sync + Send>>>> =
LazyLock::new(|| RwLock::new(Vec::new()));
#[cfg(test)]
static MOCK_INTEGRATION: LazyLock<RwLock<bool>> = LazyLock::new(|| RwLock::new(false));
pub async fn setup() -> Result<()> {
info!("Setting up global integrations");

View File

@ -1,7 +1,5 @@
#![recursion_limit = "256"]
#[macro_use]
extern crate lazy_static;
extern crate diesel_migrations;
#[macro_use]
extern crate diesel;

View File

@ -1,12 +1,10 @@
use std::sync::RwLock;
use std::sync::{LazyLock, RwLock};
use anyhow::Result;
use prometheus_client::encoding::text::encode;
use prometheus_client::registry::{Metric, Registry};
lazy_static! {
static ref REGISTRY: RwLock<Registry> = RwLock::new(<Registry>::default());
}
static REGISTRY: LazyLock<RwLock<Registry>> = LazyLock::new(|| RwLock::new(<Registry>::default()));
pub fn encode_to_string() -> Result<String> {
let registry_r = REGISTRY.read().unwrap();

View File

@ -1,5 +1,5 @@
use std::collections::HashMap;
use std::sync::{Arc, RwLock};
use std::sync::{Arc, LazyLock, RwLock};
use anyhow::{Context, Result};
use tracing::{info, span, trace, Level};
@ -7,10 +7,8 @@ use tracing::{info, span, trace, Level};
use crate::config;
use lrwn::region;
lazy_static! {
static ref REGIONS: RwLock<HashMap<String, Arc<Box<dyn region::Region + Sync + Send>>>> =
RwLock::new(HashMap::new());
}
static REGIONS: LazyLock<RwLock<HashMap<String, Arc<Box<dyn region::Region + Sync + Send>>>>> =
LazyLock::new(|| RwLock::new(HashMap::new()));
pub fn setup() -> Result<()> {
info!("Setting up regions");

View File

@ -1,3 +1,4 @@
use std::sync::LazyLock;
use std::sync::RwLock;
use std::time::Instant;
@ -47,19 +48,18 @@ pub mod user;
use crate::monitoring::prometheus;
lazy_static! {
static ref ASYNC_REDIS_POOL: TokioRwLock<Option<AsyncRedisPool>> = TokioRwLock::new(None);
static ref REDIS_PREFIX: RwLock<String> = RwLock::new("".to_string());
static ref STORAGE_REDIS_CONN_GET: Histogram = {
let histogram = Histogram::new(exponential_buckets(0.001, 2.0, 12));
prometheus::register(
"storage_redis_conn_get_duration_seconds",
"Time between requesting a Redis connection and the connection-pool returning it",
histogram.clone(),
);
histogram
};
}
static ASYNC_REDIS_POOL: LazyLock<TokioRwLock<Option<AsyncRedisPool>>> =
LazyLock::new(|| TokioRwLock::new(None));
static REDIS_PREFIX: LazyLock<RwLock<String>> = LazyLock::new(|| RwLock::new("".to_string()));
static STORAGE_REDIS_CONN_GET: LazyLock<Histogram> = LazyLock::new(|| {
let histogram = Histogram::new(exponential_buckets(0.001, 2.0, 12));
prometheus::register(
"storage_redis_conn_get_duration_seconds",
"Time between requesting a Redis connection and the connection-pool returning it",
histogram.clone(),
);
histogram
});
#[cfg(feature = "postgres")]
pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("./migrations_postgres");

View File

@ -1,4 +1,4 @@
use std::sync::RwLock;
use std::sync::{LazyLock, RwLock};
use std::time::Instant;
use anyhow::Result;
@ -20,18 +20,16 @@ use crate::helpers::tls::get_root_certs;
pub type AsyncPgPool = DeadpoolPool<AsyncPgConnection>;
pub type AsyncPgPoolConnection = DeadpoolObject<AsyncPgConnection>;
lazy_static! {
static ref ASYNC_PG_POOL: RwLock<Option<AsyncPgPool>> = RwLock::new(None);
static ref STORAGE_PG_CONN_GET: Histogram = {
let histogram = Histogram::new(exponential_buckets(0.001, 2.0, 12));
prometheus::register(
"storage_pg_conn_get_duration_seconds",
"Time between requesting a PostgreSQL connection and the connection-pool returning it",
histogram.clone(),
);
histogram
};
}
static ASYNC_PG_POOL: LazyLock<RwLock<Option<AsyncPgPool>>> = LazyLock::new(|| RwLock::new(None));
static STORAGE_PG_CONN_GET: LazyLock<Histogram> = LazyLock::new(|| {
let histogram = Histogram::new(exponential_buckets(0.001, 2.0, 12));
prometheus::register(
"storage_pg_conn_get_duration_seconds",
"Time between requesting a PostgreSQL connection and the connection-pool returning it",
histogram.clone(),
);
histogram
});
pub fn setup(conf: &config::Postgresql) -> Result<()> {
info!("Setting up PostgreSQL connection pool");

View File

@ -1,4 +1,5 @@
use std::collections::HashMap;
use std::sync::LazyLock;
use anyhow::{Context, Result};
use diesel_async::RunQueryDsl;
@ -8,9 +9,7 @@ use uuid::Uuid;
use super::{error::Error, fields, get_async_db_conn};
use lrwn::EUI64;
lazy_static! {
static ref SEARCH_TAG_RE: Regex = Regex::new(r"([^ ]+):([^ ]+)").unwrap();
}
static SEARCH_TAG_RE: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"([^ ]+):([^ ]+)").unwrap());
#[derive(QueryableByName, PartialEq, Debug)]
pub struct SearchResult {

View File

@ -1,4 +1,4 @@
use std::sync::RwLock;
use std::sync::{LazyLock, RwLock};
use std::time::Instant;
use anyhow::Result;
@ -19,18 +19,17 @@ use crate::config;
pub type AsyncSqlitePool = DeadpoolPool<SyncConnectionWrapper<SqliteConnection>>;
pub type AsyncSqlitePoolConnection = DeadpoolObject<SyncConnectionWrapper<SqliteConnection>>;
lazy_static! {
static ref ASYNC_SQLITE_POOL: RwLock<Option<AsyncSqlitePool>> = RwLock::new(None);
static ref STORAGE_SQLITE_CONN_GET: Histogram = {
let histogram = Histogram::new(exponential_buckets(0.001, 2.0, 12));
prometheus::register(
"storage_sqlite_conn_get_duration_seconds",
"Time between requesting a SQLite connection and the connection-pool returning it",
histogram.clone(),
);
histogram
};
}
static ASYNC_SQLITE_POOL: LazyLock<RwLock<Option<AsyncSqlitePool>>> =
LazyLock::new(|| RwLock::new(None));
static STORAGE_SQLITE_CONN_GET: LazyLock<Histogram> = LazyLock::new(|| {
let histogram = Histogram::new(exponential_buckets(0.001, 2.0, 12));
prometheus::register(
"storage_sqlite_conn_get_duration_seconds",
"Time between requesting a SQLite connection and the connection-pool returning it",
histogram.clone(),
);
histogram
});
pub fn setup(conf: &config::Sqlite) -> Result<()> {
info!("Setting up SQLite connection pool");

View File

@ -325,7 +325,6 @@ pub mod test {
use crate::storage::user::test::create_user;
use crate::test;
use chrono::SubsecRound;
use std::str::FromStr;
use uuid::Uuid;
struct FilterTest<'a> {
@ -357,10 +356,19 @@ pub mod test {
async fn test_tenant() {
let _guard = test::prepare().await;
// delete default tenant
delete(&Uuid::from_str("52f14cd4-c6f1-4fbd-8f87-4025e1d49242").unwrap())
.await
.unwrap();
// delete existing tenants.
let tenants = list(
10,
0,
&Filters {
..Default::default()
},
)
.await
.unwrap();
for t in &tenants {
delete(&t.id).await.unwrap();
}
let mut t = create_tenant().await;

View File

@ -1,6 +1,7 @@
use std::future::Future;
use std::io::Cursor;
use std::pin::Pin;
use std::sync::LazyLock;
use std::time::Duration;
use prost::Message;
@ -17,9 +18,7 @@ use crate::storage::{
use chirpstack_api::{gw, integration as integration_pb, internal, stream};
use lrwn::EUI64;
lazy_static! {
static ref LAST_DOWNLINK_ID: RwLock<u32> = RwLock::new(0);
}
static LAST_DOWNLINK_ID: LazyLock<RwLock<u32>> = LazyLock::new(|| RwLock::new(0));
pub type Validator = Box<dyn Fn() -> Pin<Box<dyn Future<Output = ()>>>>;

View File

@ -1,5 +1,5 @@
use std::env;
use std::sync::{Mutex, Once};
use std::sync::{LazyLock, Mutex, Once};
use crate::{adr, config, region, storage};
@ -17,9 +17,7 @@ mod relay_otaa_test;
static TRACING_INIT: Once = Once::new();
lazy_static! {
static ref TEST_MUX: Mutex<()> = Mutex::new(());
}
static TEST_MUX: LazyLock<Mutex<()>> = LazyLock::new(|| Mutex::new(()));
pub async fn prepare<'a>() -> std::sync::MutexGuard<'a, ()> {
dotenv::dotenv().ok();

View File

@ -2,6 +2,7 @@ use std::collections::HashMap;
use std::convert::{TryFrom, TryInto};
use std::io::Cursor;
use std::str::FromStr;
use std::sync::LazyLock;
use std::time::Duration;
use anyhow::{Context, Result};
@ -41,35 +42,33 @@ struct UplinkLabels {
m_type: String,
}
lazy_static! {
static ref UPLINK_COUNTER: Family<UplinkLabels, Counter> = {
let counter = Family::<UplinkLabels, Counter>::default();
prometheus::register(
"uplink_count",
"Number of received uplinks (after deduplication)",
counter.clone(),
);
counter
};
static ref DEDUPLICATE_LOCKED_COUNTER: Family<(), Counter> = {
let counter = Family::<(), Counter>::default();
prometheus::register(
static UPLINK_COUNTER: LazyLock<Family<UplinkLabels, Counter>> = LazyLock::new(|| {
let counter = Family::<UplinkLabels, Counter>::default();
prometheus::register(
"uplink_count",
"Number of received uplinks (after deduplication)",
counter.clone(),
);
counter
});
static DEDUPLICATE_LOCKED_COUNTER: LazyLock<Counter> = LazyLock::new(|| {
let counter = Counter::default();
prometheus::register(
"deduplicate_locked_count",
"Number of times the deduplication function was called and the deduplication was already locked",
counter.clone(),
);
counter
};
static ref DEDUPLICATE_NO_LOCK_COUNTER: Family<(), Counter> = {
let counter = Family::<(), Counter>::default();
prometheus::register(
"deduplicate_no_lock_count",
"Number of times the deduplication function was called and it was not yet locked",
counter.clone(),
);
counter
};
}
counter
});
static DEDUPLICATE_NO_LOCK_COUNTER: LazyLock<Counter> = LazyLock::new(|| {
let counter = Counter::default();
prometheus::register(
"deduplicate_no_lock_count",
"Number of times the deduplication function was called and it was not yet locked",
counter.clone(),
);
counter
});
#[derive(Clone)]
pub struct RelayContext {
@ -203,12 +202,12 @@ async fn _deduplicate_uplink(
"Deduplication is already locked by an other process"
);
DEDUPLICATE_LOCKED_COUNTER.get_or_create(&()).inc();
DEDUPLICATE_LOCKED_COUNTER.inc();
return Ok(());
}
DEDUPLICATE_NO_LOCK_COUNTER.get_or_create(&()).inc();
DEDUPLICATE_NO_LOCK_COUNTER.inc();
trace!(
key = key.as_str(),

View File

@ -25,7 +25,7 @@ services:
- "8080:8080"
postgres:
image: postgres:11-alpine
image: postgres:13-alpine
volumes:
- ./.docker-compose/postgresql/initdb:/docker-entrypoint-initdb.d
environment:

View File

@ -0,0 +1,145 @@
export function name() {
return "JS example for default ADR algorithm";
}
export function id() {
return "js_example_default";
}
export function handle(req) {
let resp = {
dr: req.dr,
txPowerIndex: req.txPowerIndex,
nbTrans: req.nbTrans,
};
if (!req.adr) {
return resp;
}
if (req.dr > req.maxDr) {
resp.dr = req.maxDr;
}
// Set the new Nb Trans.
resp.nbTrans = getNbTrans(req.nbTrans, getPacketLossPercentage(req));
// Calculate the number of steps.
let snrMax = getMaxSnr(req);
let snrMargin = snrMax - req.requiredSnrForDr - req.installationMargin;
let nStep = Math.floor(snrMargin / 3);
// In case of negative steps the ADR algorithm will increase the TxPower
// if possible. To avoid up / down / up / down TxPower changes, wait until
// we have at least the required number of uplink history elements.
if (nStep < 0 && getHistoryCount(req) != requiredHistoryCount()) {
return resp;
}
let [desiredTxPowerIndex, desiredDr] = getIdealTxPowerIndexAndDr(
nStep,
resp.txPowerIndex,
resp.dr,
req.maxTxPowerIndex,
req.maxDr,
);
resp.dr = desiredDr;
resp.txPowerIndex = desiredTxPowerIndex;
return resp;
}
function getIdealTxPowerIndexAndDr(nbStep, txPowerIndex, dr, maxTxPowerIndex, maxDr) {
while (nbStep !== 0) {
if (nbStep > 0) {
if (dr < maxDr) {
// Increase the DR.
dr++;
} else if (txPowerIndex < maxTxPowerIndex) {
// Decrease the Tx Power.
txPowerIndex++;
}
nbStep--;
} else {
// Incease the TxPower.
if (txPowerIndex > 0) {
txPowerIndex--;
}
nbStep++;
}
}
return [txPowerIndex, dr];
}
function requiredHistoryCount() {
return 20;
}
function getHistoryCount(req) {
let count = 0;
for (let uh of req.uplinkHistory) {
if (uh.txPowerIndex === req.txPowerIndex) {
count++;
}
}
return count;
}
function getMaxSnr(req) {
let maxSnr = -999.0;
for (let uh of req.uplinkHistory) {
if (uh.maxSnr > maxSnr) {
maxSnr = uh.maxSnr;
}
}
return maxSnr;
}
function getNbTrans(currentNbTrans, pktLossRate) {
const pktLossTable = [
[1, 1, 2],
[1, 2, 3],
[2, 3, 3],
[3, 3, 3],
];
if (currentNbTrans < 1) {
currentNbTrans = 1;
}
if (currentNbTrans > 3) {
currentNbTrans = 3;
}
const nbTransIndex = currentNbTrans - 1;
if (pktLossRate < 5.0) {
return pktLossTable[0][nbTransIndex];
} else if (pktLossRate < 10.0) {
return pktLossTable[1][nbTransIndex];
} else if (pktLossRate < 30.0) {
return pktLossTable[2][nbTransIndex];
}
return pktLossTable[3][nbTransIndex];
}
function getPacketLossPercentage(req) {
if (req.uplinkHistory.length < requiredHistoryCount()) {
return 0.0;
}
let lostPackets = 0;
let previousFCnt = req.uplinkHistory[0].fCnt;
for (let uh of req.uplinkHistory.slice(1)) {
lostPackets += uh.fCnt - previousFCnt - 1;
previousFCnt = uh.fCnt;
}
return lostPackets / req.uplinkHistory.length * 100.0;
}

View File

@ -12,6 +12,6 @@ require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/google/go-cmp v0.5.9 // indirect
golang.org/x/net v0.33.0 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/net v0.36.0 // indirect
golang.org/x/sys v0.30.0 // indirect
)

View File

@ -12,11 +12,11 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA=
golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=

View File

@ -22,9 +22,6 @@
thiserror = "2.0"
anyhow = "1.0"
# Misc
lazy_static = "1.5"
[features]
default = []
diesel = ["dep:diesel", "serde"]

View File

@ -3,8 +3,6 @@
extern crate diesel;
#[macro_use]
extern crate anyhow;
#[macro_use]
extern crate lazy_static;
pub use self::aes128::*;
pub use self::cflist::*;
@ -43,26 +41,24 @@ mod relay;
pub const LA_FPORT_RELAY: u8 = 226;
lazy_static! {
static ref EIRP_INDEX: Vec<f32> = vec![
8.0, // 0
10.0, // 1
12.0, // 2
13.0, // 3
14.0, // 4
16.0, // 5
18.0, // 6
20.0, // 7
21.0, // 8
24.0, // 9
26.0, // 10
27.0, // 11
29.0, // 12
30.0, // 13
33.0, // 14
36.0, // 15
];
}
const EIRP_INDEX: [f32; 16] = [
8.0, // 0
10.0, // 1
12.0, // 2
13.0, // 3
14.0, // 4
16.0, // 5
18.0, // 6
20.0, // 7
21.0, // 8
24.0, // 9
26.0, // 10
27.0, // 11
29.0, // 12
30.0, // 13
33.0, // 14
36.0, // 15
];
pub fn get_tx_param_setup_eirp_index(eirp: f32) -> u8 {
let mut out: u8 = 0;

View File

@ -21,6 +21,7 @@ pkgs.mkShell {
pkgs.sqlite # sqlite binary + library for diesel
pkgs.postgresql # psql binary + library for diesel
pkgs.cargo-cross # cross-compiling
pkgs.cargo-deb # deb packaging
pkgs.diesel-cli # diesel cli
];
LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib";

View File

@ -51,12 +51,12 @@
"@types/react-dom": "^18.3.0",
"@typescript-eslint/eslint-plugin": "^7.13.1",
"@typescript-eslint/parser": "^7.13.1",
"@vitejs/plugin-react-swc": "^3.5.0",
"@vitejs/plugin-react-swc": "^3.9.0",
"eslint": "^8.57.0",
"eslint-plugin-react-hooks": "^4.6.2",
"eslint-plugin-react-refresh": "^0.4.7",
"prettier": "^3.3.2",
"typescript": "^5.2.2",
"vite": "^5.4.12"
"vite": "^6.2.6"
}
}

File diff suppressed because it is too large Load Diff