From 236b468aa423e02c9ac5460786a72a2cf4a8f535 Mon Sep 17 00:00:00 2001 From: Orne Brocaar Date: Mon, 24 Mar 2025 11:30:17 +0000 Subject: [PATCH] Store and increase TS004 session_cnt per device. For TS004 v2.0.0, the session_cnt must be incremented for every fragmentation-session. --- .../down.sql | 3 + .../up.sql | 6 ++ .../down.sql | 3 + .../up.sql | 3 + chirpstack/src/applayer/fuota/flow.rs | 18 +++++- chirpstack/src/storage/device.rs | 4 ++ chirpstack/src/storage/fields/device.rs | 59 +++++++++++++++++++ chirpstack/src/storage/fields/mod.rs | 1 + chirpstack/src/storage/schema_postgres.rs | 1 + chirpstack/src/storage/schema_sqlite.rs | 1 + 10 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 chirpstack/src/storage/fields/device.rs diff --git a/chirpstack/migrations_postgres/2025-01-21-093745_add_fuota_support/down.sql b/chirpstack/migrations_postgres/2025-01-21-093745_add_fuota_support/down.sql index 4fa3c925..2c05e792 100644 --- a/chirpstack/migrations_postgres/2025-01-21-093745_add_fuota_support/down.sql +++ b/chirpstack/migrations_postgres/2025-01-21-093745_add_fuota_support/down.sql @@ -1,3 +1,6 @@ +alter table device + drop column app_layer_params; + alter table device_keys drop column gen_app_key; diff --git a/chirpstack/migrations_postgres/2025-01-21-093745_add_fuota_support/up.sql b/chirpstack/migrations_postgres/2025-01-21-093745_add_fuota_support/up.sql index 87390a97..b4df1500 100644 --- a/chirpstack/migrations_postgres/2025-01-21-093745_add_fuota_support/up.sql +++ b/chirpstack/migrations_postgres/2025-01-21-093745_add_fuota_support/up.sql @@ -73,3 +73,9 @@ alter table device_keys alter table device_keys alter column gen_app_key drop default; + +alter table device + add column app_layer_params jsonb not null default '{}'; + +alter table device + alter column app_layer_params drop default; diff --git a/chirpstack/migrations_sqlite/2025-01-27-100007_add_fuota_support/down.sql b/chirpstack/migrations_sqlite/2025-01-27-100007_add_fuota_support/down.sql index 4fa3c925..2c05e792 100644 --- a/chirpstack/migrations_sqlite/2025-01-27-100007_add_fuota_support/down.sql +++ b/chirpstack/migrations_sqlite/2025-01-27-100007_add_fuota_support/down.sql @@ -1,3 +1,6 @@ +alter table device + drop column app_layer_params; + alter table device_keys drop column gen_app_key; diff --git a/chirpstack/migrations_sqlite/2025-01-27-100007_add_fuota_support/up.sql b/chirpstack/migrations_sqlite/2025-01-27-100007_add_fuota_support/up.sql index d4642388..a3cc2e5f 100644 --- a/chirpstack/migrations_sqlite/2025-01-27-100007_add_fuota_support/up.sql +++ b/chirpstack/migrations_sqlite/2025-01-27-100007_add_fuota_support/up.sql @@ -70,3 +70,6 @@ create index idx_fuota_deployment_job_scheduler_run_after on fuota_deployment_jo alter table device_keys add column gen_app_key blob not null default x'00000000000000000000000000000000'; + +alter table device + add column all_layer_params text not null default '{}'; diff --git a/chirpstack/src/applayer/fuota/flow.rs b/chirpstack/src/applayer/fuota/flow.rs index 0e368ebd..dcd8150b 100644 --- a/chirpstack/src/applayer/fuota/flow.rs +++ b/chirpstack/src/applayer/fuota/flow.rs @@ -397,6 +397,20 @@ impl Flow { ) .to_vec()?, Some(Ts004Version::V200) => { + let dev = device::get(&fuota_dev.dev_eui).await?; + let session_cnt = dev.app_layer_params.ts004_session_cnt[0]; + let mut app_layer_params = dev.app_layer_params.clone(); + app_layer_params.ts004_session_cnt[0] += 1; + + device::partial_update( + fuota_dev.dev_eui, + &device::DeviceChangeset { + app_layer_params: Some(app_layer_params), + ..Default::default() + }, + ) + .await?; + let dev_keys = device_keys::get(&fuota_dev.dev_eui).await?; let data_block_int_key = match self.device_profile.mac_version { MacVersion::LORAWAN_1_0_0 @@ -412,7 +426,7 @@ impl Flow { }; let mic = fragmentation::v2::calculate_mic( data_block_int_key, - 0, + session_cnt, 0, [0, 0, 0, 0], &self.fuota_deployment.payload, @@ -434,7 +448,7 @@ impl Flow { }, descriptor: [0, 0, 0, 0], mic, - session_cnt: 0, + session_cnt, }, ) .to_vec()? diff --git a/chirpstack/src/storage/device.rs b/chirpstack/src/storage/device.rs index da357689..d33c77a8 100644 --- a/chirpstack/src/storage/device.rs +++ b/chirpstack/src/storage/device.rs @@ -116,6 +116,7 @@ pub struct Device { pub join_eui: EUI64, pub secondary_dev_addr: Option, pub device_session: Option, + pub app_layer_params: fields::device::AppLayerParams, } #[derive(AsChangeset, Debug, Clone, Default)] @@ -133,6 +134,7 @@ pub struct DeviceChangeset { pub battery_level: Option>, pub scheduler_run_after: Option>>, pub is_disabled: Option, + pub app_layer_params: Option, } impl Device { @@ -190,6 +192,7 @@ impl Default for Device { join_eui: EUI64::default(), secondary_dev_addr: None, device_session: None, + app_layer_params: Default::default(), } } } @@ -552,6 +555,7 @@ pub async fn update(d: Device) -> Result { device::tags.eq(&d.tags), device::variables.eq(&d.variables), device::join_eui.eq(&d.join_eui), + device::app_layer_params.eq(&d.app_layer_params), )) .get_result(&mut get_async_db_conn().await?) .await diff --git a/chirpstack/src/storage/fields/device.rs b/chirpstack/src/storage/fields/device.rs new file mode 100644 index 00000000..74a75340 --- /dev/null +++ b/chirpstack/src/storage/fields/device.rs @@ -0,0 +1,59 @@ +use diesel::backend::Backend; +use diesel::{deserialize, serialize}; +#[cfg(feature = "postgres")] +use diesel::{pg::Pg, sql_types::Jsonb}; +#[cfg(feature = "sqlite")] +use diesel::{sql_types::Text, sqlite::Sqlite}; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize, AsExpression, FromSqlRow)] +#[cfg_attr(feature = "postgres", diesel(sql_type = Jsonb))] +#[cfg_attr(feature = "sqlite", diesel(sql_type = Text))] +#[serde(default)] +pub struct AppLayerParams { + pub ts004_session_cnt: [u16; 4], +} + +impl Default for AppLayerParams { + fn default() -> Self { + Self { + ts004_session_cnt: [0, 0, 0, 0], + } + } +} + +#[cfg(feature = "postgres")] +impl deserialize::FromSql for AppLayerParams { + fn from_sql(value: ::RawValue<'_>) -> deserialize::Result { + let value = >::from_sql(value)?; + Ok(serde_json::from_value(value)?) + } +} + +#[cfg(feature = "postgres")] +impl serialize::ToSql for AppLayerParams { + fn to_sql<'b>(&'b self, out: &mut serialize::Output<'b, '_, Pg>) -> serialize::Result { + let value = serde_json::to_value(&self)?; + >::to_sql(&value, &mut out.reborrow()) + } +} + +#[cfg(feature = "sqlite")] +impl deserialize::FromSql for AppLayerParams +where + *const str: deserialize::FromSql, +{ + fn from_sql(value: ::RawValue<'_>) -> deserialize::Result { + let s = + <*const str as deserialize::FromSql>::from_sql(value)?; + Ok(serde_json::from_str(unsafe { &*s })?) + } +} + +#[cfg(feature = "sqlite")] +impl serialize::ToSql for AppLayerParams { + fn to_sql<'b>(&'b self, out: &mut serialize::Output<'b, '_, Sqlite>) -> serialize::Result { + out.set_value(serde_json::to_string(&self)?); + Ok(serialize::IsNull::No) + } +} diff --git a/chirpstack/src/storage/fields/mod.rs b/chirpstack/src/storage/fields/mod.rs index 77ff8a85..d97d2d17 100644 --- a/chirpstack/src/storage/fields/mod.rs +++ b/chirpstack/src/storage/fields/mod.rs @@ -1,5 +1,6 @@ mod big_decimal; mod dev_nonces; +pub mod device; pub mod device_profile; mod device_session; mod fuota; diff --git a/chirpstack/src/storage/schema_postgres.rs b/chirpstack/src/storage/schema_postgres.rs index 029de77d..f605e5d0 100644 --- a/chirpstack/src/storage/schema_postgres.rs +++ b/chirpstack/src/storage/schema_postgres.rs @@ -65,6 +65,7 @@ diesel::table! { join_eui -> Bytea, secondary_dev_addr -> Nullable, device_session -> Nullable, + app_layer_params -> Jsonb, } } diff --git a/chirpstack/src/storage/schema_sqlite.rs b/chirpstack/src/storage/schema_sqlite.rs index 74ef1b72..96c8f6e7 100644 --- a/chirpstack/src/storage/schema_sqlite.rs +++ b/chirpstack/src/storage/schema_sqlite.rs @@ -60,6 +60,7 @@ diesel::table! { join_eui -> Binary, secondary_dev_addr -> Nullable, device_session -> Nullable, + all_layer_params -> Text, } }