diff --git a/chirpstack/Cargo.toml b/chirpstack/Cargo.toml index e0850c1e..d1b23e0f 100644 --- a/chirpstack/Cargo.toml +++ b/chirpstack/Cargo.toml @@ -24,11 +24,7 @@ # Database email_address = "0.2" - diesel = { version = "2.2", features = [ - "chrono", - "numeric", - "64-column-tables", - ] } + diesel = { version = "2.2", features = ["chrono", "numeric"] } diesel_migrations = { version = "2.2" } diesel-async = { version = "0.5", features = [ "deadpool", diff --git a/chirpstack/migrations_postgres/2025-01-13-152218_refactor_device_profile_fields/down.sql b/chirpstack/migrations_postgres/2025-01-13-152218_refactor_device_profile_fields/down.sql index 6fb1ac0f..61ed3b9b 100644 --- a/chirpstack/migrations_postgres/2025-01-13-152218_refactor_device_profile_fields/down.sql +++ b/chirpstack/migrations_postgres/2025-01-13-152218_refactor_device_profile_fields/down.sql @@ -6,7 +6,30 @@ alter table device_profile add column class_b_timeout integer not null default 0, add column class_b_ping_slot_nb_k integer not null default 0, add column class_b_ping_slot_dr smallint not null default 0, - add column class_b_ping_slot_freq bigint not null default 0; + add column class_b_ping_slot_freq bigint not null default 0, + add column class_c_timeout integer not null default 0, + add column is_relay boolean not null default false, + add column is_relay_ed boolean not null default false, + add column relay_ed_relay_only boolean not null default false, + add column relay_enabled boolean not null default false, + add column relay_cad_periodicity smallint not null default 0, + add column relay_default_channel_index smallint not null default 0, + add column relay_second_channel_freq bigint not null default 0, + add column relay_second_channel_dr smallint not null default 0, + add column relay_second_channel_ack_offset smallint not null default 0, + add column relay_ed_activation_mode smallint not null default 0, + add column relay_ed_smart_enable_level smallint not null default 0, + add column relay_ed_back_off smallint not null default 0, + add column relay_ed_uplink_limit_bucket_size smallint not null default 0, + add column relay_ed_uplink_limit_reload_rate smallint not null default 0, + add column relay_join_req_limit_reload_rate smallint not null default 0, + add column relay_notify_limit_reload_rate smallint not null default 0, + add column relay_global_uplink_limit_reload_rate smallint not null default 0, + add column relay_overall_limit_reload_rate smallint not null default 0, + add column relay_join_req_limit_bucket_size smallint not null default 0, + add column relay_notify_limit_bucket_size smallint not null default 0, + add column relay_global_uplink_limit_bucket_size smallint not null default 0, + add column relay_overall_limit_bucket_size smallint not null default 0; update device_profile set @@ -26,7 +49,42 @@ update device_profile where class_b_params is not null; +update device_profile + set + class_c_timeout = (class_c_params->'timeout')::integer + where + class_c_params is not null; + +update device_profile + set + is_relay = (relay_params->'is_relay')::boolean, + is_relay_ed = (relay_params->'is_relay_ed')::boolean, + relay_ed_relay_only = (relay_params->'ed_relay_only')::boolean, + relay_enabled = (relay_params->'relay_enabled')::boolean, + relay_cad_periodicity = (relay_params->'relay_cad_periodicity')::smallint, + relay_default_channel_index = (relay_params->'default_channel_index')::smallint, + relay_second_channel_freq = (relay_params->'second_channel_freq')::bigint, + relay_second_channel_dr = (relay_params->'second_channel_dr')::smallint, + relay_second_channel_ack_offset = (relay_params->'second_channel_ack_offset')::smallint, + relay_ed_activation_mode = (relay_params->'ed_activation_mode')::smallint, + relay_ed_smart_enable_level = (relay_params->'ed_smart_enable_level')::smallint, + relay_ed_back_off = (relay_params->'ed_back_off')::smallint, + relay_ed_uplink_limit_bucket_size = (relay_params->'ed_uplink_limit_bucket_size')::smallint, + relay_ed_uplink_limit_reload_rate = (relay_params->'ed_uplink_limit_reload_rate')::smallint, + relay_join_req_limit_reload_rate = (relay_params->'relay_join_req_limit_reload_rate')::smallint, + relay_notify_limit_reload_rate = (relay_params->'relay_notify_limit_reload_rate')::smallint, + relay_global_uplink_limit_reload_rate = (relay_params->'relay_global_uplink_limit_reload_rate')::smallint, + relay_overall_limit_reload_rate = (relay_params->'relay_overall_limit_reload_rate')::smallint, + relay_join_req_limit_bucket_size = (relay_params->'relay_join_req_limit_bucket_size')::smallint, + relay_notify_limit_bucket_size = (relay_params->'relay_notify_limit_bucket_size')::smallint, + relay_global_uplink_limit_bucket_size = (relay_params->'relay_global_uplink_limit_bucket_size')::smallint, + relay_overall_limit_bucket_size = (relay_params->'relay_overall_limit_bucket_size')::smallint + where + relay_params is not null; + alter table device_profile drop column abp_params, - drop column class_b_params; + drop column class_b_params, + drop column class_c_params, + drop column relay_params; diff --git a/chirpstack/migrations_postgres/2025-01-13-152218_refactor_device_profile_fields/up.sql b/chirpstack/migrations_postgres/2025-01-13-152218_refactor_device_profile_fields/up.sql index 78a5677e..fc637cde 100644 --- a/chirpstack/migrations_postgres/2025-01-13-152218_refactor_device_profile_fields/up.sql +++ b/chirpstack/migrations_postgres/2025-01-13-152218_refactor_device_profile_fields/up.sql @@ -1,7 +1,8 @@ alter table device_profile add column abp_params jsonb null, add column class_b_params jsonb null, - add column class_c_params jsonb null; + add column class_c_params jsonb null, + add column relay_params jsonb null; update device_profile set abp_params = json_build_object( @@ -25,6 +26,33 @@ update device_profile where supports_class_c = true; +update device_profile + set relay_params = json_build_object( + 'is_relay', is_relay, + 'is_relay_ed', is_relay_ed, + 'ed_relay_only', relay_ed_relay_only, + 'relay_enabled', relay_enabled, + 'relay_cad_periodicity', relay_cad_periodicity, + 'default_channel_index', relay_default_channel_index, + 'second_channel_freq', relay_second_channel_freq, + 'second_channel_dr', relay_second_channel_dr, + 'second_channel_ack_offset', relay_second_channel_ack_offset, + 'ed_activation_mode', relay_ed_activation_mode, + 'ed_smart_enable_level', relay_ed_smart_enable_level, + 'ed_back_off', relay_ed_back_off, + 'ed_uplink_limit_bucket_size', relay_ed_uplink_limit_bucket_size, + 'ed_uplink_limit_reload_rate', relay_ed_uplink_limit_reload_rate, + 'relay_join_req_limit_reload_rate', relay_join_req_limit_reload_rate, + 'relay_notify_limit_reload_rate', relay_notify_limit_reload_rate, + 'relay_global_uplink_limit_reload_rate', relay_global_uplink_limit_reload_rate, + 'relay_overall_limit_reload_rate', relay_overall_limit_reload_rate, + 'relay_notify_limit_bucket_size', relay_join_req_limit_bucket_size, + 'relay_notify_limit_bucket_size', relay_notify_limit_bucket_size, + 'relay_global_uplink_limit_bucket_size', relay_global_uplink_limit_bucket_size, + 'relay_overall_limit_bucket_size', relay_overall_limit_bucket_size) + where + is_relay = true or is_relay_ed = true; + alter table device_profile drop column abp_rx1_delay, drop column abp_rx1_dr_offset, @@ -34,5 +62,27 @@ alter table device_profile drop column class_b_ping_slot_nb_k, drop column class_b_ping_slot_dr, drop column class_b_ping_slot_freq, - drop column class_c_timeout; + drop column class_c_timeout, + drop column is_relay, + drop column is_relay_ed, + drop column relay_ed_relay_only, + drop column relay_enabled, + drop column relay_cad_periodicity, + drop column relay_default_channel_index, + drop column relay_second_channel_freq, + drop column relay_second_channel_dr, + drop column relay_second_channel_ack_offset, + drop column relay_ed_activation_mode, + drop column relay_ed_smart_enable_level, + drop column relay_ed_back_off, + drop column relay_ed_uplink_limit_bucket_size, + drop column relay_ed_uplink_limit_reload_rate, + drop column relay_join_req_limit_reload_rate, + drop column relay_notify_limit_reload_rate, + drop column relay_global_uplink_limit_reload_rate, + drop column relay_overall_limit_reload_rate, + drop column relay_join_req_limit_bucket_size, + drop column relay_notify_limit_bucket_size, + drop column relay_global_uplink_limit_bucket_size, + drop column relay_overall_limit_bucket_size; diff --git a/chirpstack/migrations_sqlite/2025-01-13-163304_refactor_device_profile_fields/down.sql b/chirpstack/migrations_sqlite/2025-01-13-163304_refactor_device_profile_fields/down.sql index b14daf94..3c3f9667 100644 --- a/chirpstack/migrations_sqlite/2025-01-13-163304_refactor_device_profile_fields/down.sql +++ b/chirpstack/migrations_sqlite/2025-01-13-163304_refactor_device_profile_fields/down.sql @@ -7,6 +7,28 @@ alter table device_profile add column class_b_ping_slot_nb_k integer not null de alter table device_profile add column class_b_ping_slot_dr smallint not null default 0; alter table device_profile add column class_b_ping_slot_freq bigint not null default 0; alter table device_profile add column class_c_timeout integer not null default 0; +alter table device_profile add column is_relay boolean not null default false; +alter table device_profile add column is_relay_ed boolean not null default false; +alter table device_profile add column relay_ed_relay_only boolean not null default false; +alter table device_profile add column relay_enabled boolean not null default false; +alter table device_profile add column relay_cad_periodicity smallint not null default 0; +alter table device_profile add column relay_default_channel_index smallint not null default 0; +alter table device_profile add column relay_second_channel_freq bigint not null default 0; +alter table device_profile add column relay_second_channel_dr smallint not null default 0; +alter table device_profile add column relay_second_channel_ack_offset smallint not null default 0; +alter table device_profile add column relay_ed_activation_mode smallint not null default 0; +alter table device_profile add column relay_ed_smart_enable_level smallint not null default 0; +alter table device_profile add column relay_ed_back_off smallint not null default 0; +alter table device_profile add column relay_ed_uplink_limit_bucket_size smallint not null default 0; +alter table device_profile add column relay_ed_uplink_limit_reload_rate smallint not null default 0; +alter table device_profile add column relay_join_req_limit_reload_rate smallint not null default 0; +alter table device_profile add column relay_notify_limit_reload_rate smallint not null default 0; +alter table device_profile add column relay_global_uplink_limit_reload_rate smallint not null default 0; +alter table device_profile add column relay_overall_limit_reload_rate smallint not null default 0; +alter table device_profile add column relay_join_req_limit_bucket_size smallint not null default 0; +alter table device_profile add column relay_notify_limit_bucket_size smallint not null default 0; +alter table device_profile add column relay_global_uplink_limit_bucket_size smallint not null default 0; +alter table device_profile add column relay_overall_limit_bucket_size smallint not null default 0; update device_profile set @@ -32,7 +54,35 @@ update device_profile where class_c_params is not null; +update device_profile + set + is_relay = relay_params->'is_relay', + is_relay_ed = relay_params->'is_relay_ed', + relay_ed_relay_only = relay_params->'ed_relay_only', + relay_enabled = relay_params->'relay_enabled', + relay_cad_periodicity = relay_params->'relay_cad_periodicity', + relay_default_channel_index = relay_params->'default_channel_index', + relay_second_channel_freq = relay_params->'second_channel_freq', + relay_second_channel_dr = relay_params->'second_channel_dr', + relay_second_channel_ack_offset = relay_params->'second_channel_ack_offset', + relay_ed_activation_mode = relay_params->'ed_activation_mode', + relay_ed_smart_enable_level = relay_params->'ed_smart_enable_level', + relay_ed_back_off = relay_params->'ed_back_off', + relay_ed_uplink_limit_bucket_size = relay_params->'ed_uplink_limit_bucket_size', + relay_ed_uplink_limit_reload_rate = relay_params->'ed_uplink_limit_reload_rate', + relay_join_req_limit_reload_rate = relay_params->'relay_join_req_limit_reload_rate', + relay_notify_limit_reload_rate = relay_params->'relay_notify_limit_reload_rate', + relay_global_uplink_limit_reload_rate = relay_params->'relay_global_uplink_limit_reload_rate', + relay_overall_limit_reload_rate = relay_params->'relay_overall_limit_reload_rate', + relay_join_req_limit_bucket_size = relay_params->'relay_join_req_limit_bucket_size', + relay_notify_limit_bucket_size = relay_params->'relay_notify_limit_bucket_size', + relay_global_uplink_limit_bucket_size = relay_params->'relay_global_uplink_limit_bucket_size', + relay_overall_limit_bucket_size = relay_params->'relay_overall_limit_bucket_size' + where + relay_params is not null; + alter table device_profile drop column abp_params; alter table device_profile drop column class_b_params; alter table device_profile drop column class_c_params; +alter table device_profile drop column relay_params; diff --git a/chirpstack/migrations_sqlite/2025-01-13-163304_refactor_device_profile_fields/up.sql b/chirpstack/migrations_sqlite/2025-01-13-163304_refactor_device_profile_fields/up.sql index 3fb6dc57..c6402c5b 100644 --- a/chirpstack/migrations_sqlite/2025-01-13-163304_refactor_device_profile_fields/up.sql +++ b/chirpstack/migrations_sqlite/2025-01-13-163304_refactor_device_profile_fields/up.sql @@ -1,6 +1,7 @@ alter table device_profile add column abp_params text null; alter table device_profile add column class_b_params text null; alter table device_profile add column class_c_params text null; +alter table device_profile add column relay_params text null; update device_profile set abp_params = json_object( @@ -23,6 +24,32 @@ update device_profile 'timeout', class_c_timeout) where supports_class_c = true; +update device_profile + set relay_params = json_object( + 'is_relay', is_relay, + 'is_relay_ed', is_relay_ed, + 'ed_relay_only', relay_ed_relay_only, + 'relay_enabled', relay_enabled, + 'relay_cad_periodicity', relay_cad_periodicity, + 'default_channel_index', relay_default_channel_index, + 'second_channel_freq', relay_second_channel_freq, + 'second_channel_dr', relay_second_channel_dr, + 'second_channel_ack_offset', relay_second_channel_ack_offset, + 'ed_activation_mode', relay_ed_activation_mode, + 'ed_smart_enable_level', relay_ed_smart_enable_level, + 'ed_back_off', relay_ed_back_off, + 'ed_uplink_limit_bucket_size', relay_ed_uplink_limit_bucket_size, + 'ed_uplink_limit_reload_rate', relay_ed_uplink_limit_reload_rate, + 'relay_join_req_limit_reload_rate', relay_join_req_limit_reload_rate, + 'relay_notify_limit_reload_rate', relay_notify_limit_reload_rate, + 'relay_global_uplink_limit_reload_rate', relay_global_uplink_limit_reload_rate, + 'relay_overall_limit_reload_rate', relay_overall_limit_reload_rate, + 'relay_notify_limit_bucket_size', relay_join_req_limit_bucket_size, + 'relay_notify_limit_bucket_size', relay_notify_limit_bucket_size, + 'relay_global_uplink_limit_bucket_size', relay_global_uplink_limit_bucket_size, + 'relay_overall_limit_bucket_size', relay_overall_limit_bucket_size) + where is_relay = true or is_relay_ed is true; + alter table device_profile drop column abp_rx1_delay; alter table device_profile drop column abp_rx1_dr_offset; alter table device_profile drop column abp_rx2_dr; @@ -34,3 +61,27 @@ alter table device_profile drop column class_b_ping_slot_dr; alter table device_profile drop column class_b_ping_slot_freq; alter table device_profile drop column class_c_timeout; + +alter table device_profile drop column is_relay; +alter table device_profile drop column is_relay_ed; +alter table device_profile drop column relay_ed_relay_only; +alter table device_profile drop column relay_enabled; +alter table device_profile drop column relay_cad_periodicity; +alter table device_profile drop column relay_default_channel_index; +alter table device_profile drop column relay_second_channel_freq; +alter table device_profile drop column relay_second_channel_dr; +alter table device_profile drop column relay_second_channel_ack_offset; +alter table device_profile drop column relay_ed_activation_mode; +alter table device_profile drop column relay_ed_smart_enable_level; +alter table device_profile drop column relay_ed_back_off; +alter table device_profile drop column relay_ed_uplink_limit_bucket_size; +alter table device_profile drop column relay_ed_uplink_limit_reload_rate; +alter table device_profile drop column relay_join_req_limit_reload_rate; +alter table device_profile drop column relay_notify_limit_reload_rate; +alter table device_profile drop column relay_global_uplink_limit_reload_rate; +alter table device_profile drop column relay_overall_limit_reload_rate; +alter table device_profile drop column relay_join_req_limit_bucket_size; +alter table device_profile drop column relay_notify_limit_bucket_size; +alter table device_profile drop column relay_global_uplink_limit_bucket_size; +alter table device_profile drop column relay_overall_limit_bucket_size; + diff --git a/chirpstack/src/api/device_profile.rs b/chirpstack/src/api/device_profile.rs index 1abf8aec..fdf3013c 100644 --- a/chirpstack/src/api/device_profile.rs +++ b/chirpstack/src/api/device_profile.rs @@ -79,30 +79,6 @@ impl DeviceProfileService for DeviceProfile { auto_detect_measurements: req_dp.auto_detect_measurements, region_config_id: (!req_dp.region_config_id.is_empty()) .then(|| req_dp.region_config_id.clone()), - is_relay: req_dp.is_relay, - is_relay_ed: req_dp.is_relay_ed, - relay_ed_relay_only: req_dp.relay_ed_relay_only, - relay_enabled: req_dp.relay_enabled, - relay_cad_periodicity: req_dp.relay_cad_periodicity as i16, - relay_default_channel_index: req_dp.relay_default_channel_index as i16, - relay_second_channel_freq: req_dp.relay_second_channel_freq as i64, - relay_second_channel_dr: req_dp.relay_second_channel_dr as i16, - relay_second_channel_ack_offset: req_dp.relay_second_channel_ack_offset as i16, - relay_ed_activation_mode: req_dp.relay_ed_activation_mode().from_proto(), - relay_ed_smart_enable_level: req_dp.relay_ed_smart_enable_level as i16, - relay_ed_back_off: req_dp.relay_ed_back_off as i16, - relay_ed_uplink_limit_bucket_size: req_dp.relay_ed_uplink_limit_bucket_size as i16, - relay_ed_uplink_limit_reload_rate: req_dp.relay_ed_uplink_limit_reload_rate as i16, - relay_join_req_limit_reload_rate: req_dp.relay_join_req_limit_reload_rate as i16, - relay_notify_limit_reload_rate: req_dp.relay_notify_limit_reload_rate as i16, - relay_global_uplink_limit_reload_rate: req_dp.relay_global_uplink_limit_reload_rate - as i16, - relay_overall_limit_reload_rate: req_dp.relay_overall_limit_reload_rate as i16, - relay_join_req_limit_bucket_size: req_dp.relay_join_req_limit_bucket_size as i16, - relay_notify_limit_bucket_size: req_dp.relay_notify_limit_bucket_size as i16, - relay_global_uplink_limit_bucket_size: req_dp.relay_global_uplink_limit_bucket_size - as i16, - relay_overall_limit_bucket_size: req_dp.relay_overall_limit_bucket_size as i16, allow_roaming: req_dp.allow_roaming, rx1_delay: req_dp.rx1_delay as i16, abp_params: if req_dp.supports_otaa { @@ -132,6 +108,38 @@ impl DeviceProfileService for DeviceProfile { } else { None }, + relay_params: if req_dp.is_relay || req_dp.is_relay_ed { + Some(fields::RelayParams { + is_relay: req_dp.is_relay, + is_relay_ed: req_dp.is_relay_ed, + ed_relay_only: req_dp.relay_ed_relay_only, + relay_enabled: req_dp.relay_enabled, + relay_cad_periodicity: req_dp.relay_cad_periodicity as u8, + default_channel_index: req_dp.relay_default_channel_index as u8, + second_channel_freq: req_dp.relay_second_channel_freq as u32, + second_channel_dr: req_dp.relay_second_channel_dr as u8, + second_channel_ack_offset: req_dp.relay_second_channel_ack_offset as u8, + ed_activation_mode: req_dp.relay_ed_activation_mode().from_proto(), + ed_smart_enable_level: req_dp.relay_ed_smart_enable_level as u8, + ed_back_off: req_dp.relay_ed_back_off as u8, + ed_uplink_limit_bucket_size: req_dp.relay_ed_uplink_limit_bucket_size as u8, + ed_uplink_limit_reload_rate: req_dp.relay_ed_uplink_limit_reload_rate as u8, + relay_join_req_limit_reload_rate: req_dp.relay_join_req_limit_reload_rate as u8, + relay_notify_limit_reload_rate: req_dp.relay_notify_limit_reload_rate as u8, + relay_global_uplink_limit_reload_rate: req_dp + .relay_global_uplink_limit_reload_rate + as u8, + relay_overall_limit_reload_rate: req_dp.relay_overall_limit_reload_rate as u8, + relay_join_req_limit_bucket_size: req_dp.relay_join_req_limit_bucket_size as u8, + relay_notify_limit_bucket_size: req_dp.relay_notify_limit_bucket_size as u8, + relay_global_uplink_limit_bucket_size: req_dp + .relay_global_uplink_limit_bucket_size + as u8, + relay_overall_limit_bucket_size: req_dp.relay_overall_limit_bucket_size as u8, + }) + } else { + None + }, ..Default::default() }; @@ -166,6 +174,7 @@ impl DeviceProfileService for DeviceProfile { let abp_params = dp.abp_params.clone().unwrap_or_default(); let class_b_params = dp.class_b_params.clone().unwrap_or_default(); let class_c_params = dp.class_c_params.clone().unwrap_or_default(); + let relay_params = dp.relay_params.clone().unwrap_or_default(); let mut resp = Response::new(api::GetDeviceProfileResponse { device_profile: Some(api::DeviceProfile { @@ -211,30 +220,36 @@ impl DeviceProfileService for DeviceProfile { .collect(), auto_detect_measurements: dp.auto_detect_measurements, region_config_id: dp.region_config_id.clone().unwrap_or_default(), - is_relay: dp.is_relay, - is_relay_ed: dp.is_relay_ed, - relay_ed_relay_only: dp.relay_ed_relay_only, - relay_enabled: dp.relay_enabled, - relay_cad_periodicity: dp.relay_cad_periodicity as i32, - relay_default_channel_index: dp.relay_default_channel_index as u32, - relay_second_channel_freq: dp.relay_second_channel_freq as u32, - relay_second_channel_dr: dp.relay_second_channel_dr as u32, - relay_second_channel_ack_offset: dp.relay_second_channel_ack_offset as i32, - relay_ed_activation_mode: dp.relay_ed_activation_mode.to_proto().into(), - relay_ed_smart_enable_level: dp.relay_ed_smart_enable_level as u32, - relay_ed_back_off: dp.relay_ed_back_off as u32, - relay_ed_uplink_limit_bucket_size: dp.relay_ed_uplink_limit_bucket_size as u32, - relay_ed_uplink_limit_reload_rate: dp.relay_ed_uplink_limit_reload_rate as u32, - relay_join_req_limit_reload_rate: dp.relay_join_req_limit_reload_rate as u32, - relay_notify_limit_reload_rate: dp.relay_notify_limit_reload_rate as u32, - relay_global_uplink_limit_reload_rate: dp.relay_global_uplink_limit_reload_rate + is_relay: relay_params.is_relay, + is_relay_ed: relay_params.is_relay_ed, + relay_ed_relay_only: relay_params.ed_relay_only, + relay_enabled: relay_params.relay_enabled, + relay_cad_periodicity: relay_params.relay_cad_periodicity as i32, + relay_default_channel_index: relay_params.default_channel_index as u32, + relay_second_channel_freq: relay_params.second_channel_freq as u32, + relay_second_channel_dr: relay_params.second_channel_dr as u32, + relay_second_channel_ack_offset: relay_params.second_channel_ack_offset as i32, + relay_ed_activation_mode: relay_params.ed_activation_mode.to_proto().into(), + relay_ed_smart_enable_level: relay_params.ed_smart_enable_level as u32, + relay_ed_back_off: relay_params.ed_back_off as u32, + relay_ed_uplink_limit_bucket_size: relay_params.ed_uplink_limit_bucket_size as u32, + relay_ed_uplink_limit_reload_rate: relay_params.ed_uplink_limit_reload_rate as u32, + relay_join_req_limit_reload_rate: relay_params.relay_join_req_limit_reload_rate as u32, - relay_overall_limit_reload_rate: dp.relay_overall_limit_reload_rate as u32, - relay_join_req_limit_bucket_size: dp.relay_join_req_limit_bucket_size as u32, - relay_notify_limit_bucket_size: dp.relay_notify_limit_bucket_size as u32, - relay_global_uplink_limit_bucket_size: dp.relay_global_uplink_limit_bucket_size + relay_notify_limit_reload_rate: relay_params.relay_notify_limit_reload_rate as u32, + relay_global_uplink_limit_reload_rate: relay_params + .relay_global_uplink_limit_reload_rate + as u32, + relay_overall_limit_reload_rate: relay_params.relay_overall_limit_reload_rate + as u32, + relay_join_req_limit_bucket_size: relay_params.relay_join_req_limit_bucket_size + as u32, + relay_notify_limit_bucket_size: relay_params.relay_notify_limit_bucket_size as u32, + relay_global_uplink_limit_bucket_size: relay_params + .relay_global_uplink_limit_bucket_size + as u32, + relay_overall_limit_bucket_size: relay_params.relay_overall_limit_bucket_size as u32, - relay_overall_limit_bucket_size: dp.relay_overall_limit_bucket_size as u32, allow_roaming: dp.allow_roaming, rx1_delay: dp.rx1_delay as u32, }), @@ -302,30 +317,6 @@ impl DeviceProfileService for DeviceProfile { auto_detect_measurements: req_dp.auto_detect_measurements, region_config_id: (!req_dp.region_config_id.is_empty()) .then(|| req_dp.region_config_id.clone()), - is_relay: req_dp.is_relay, - is_relay_ed: req_dp.is_relay_ed, - relay_ed_relay_only: req_dp.relay_ed_relay_only, - relay_enabled: req_dp.relay_enabled, - relay_cad_periodicity: req_dp.relay_cad_periodicity as i16, - relay_default_channel_index: req_dp.relay_default_channel_index as i16, - relay_second_channel_freq: req_dp.relay_second_channel_freq as i64, - relay_second_channel_dr: req_dp.relay_second_channel_dr as i16, - relay_second_channel_ack_offset: req_dp.relay_second_channel_ack_offset as i16, - relay_ed_activation_mode: req_dp.relay_ed_activation_mode().from_proto(), - relay_ed_smart_enable_level: req_dp.relay_ed_smart_enable_level as i16, - relay_ed_back_off: req_dp.relay_ed_back_off as i16, - relay_ed_uplink_limit_bucket_size: req_dp.relay_ed_uplink_limit_bucket_size as i16, - relay_ed_uplink_limit_reload_rate: req_dp.relay_ed_uplink_limit_reload_rate as i16, - relay_join_req_limit_reload_rate: req_dp.relay_join_req_limit_reload_rate as i16, - relay_notify_limit_reload_rate: req_dp.relay_notify_limit_reload_rate as i16, - relay_global_uplink_limit_reload_rate: req_dp.relay_global_uplink_limit_reload_rate - as i16, - relay_overall_limit_reload_rate: req_dp.relay_overall_limit_reload_rate as i16, - relay_join_req_limit_bucket_size: req_dp.relay_join_req_limit_bucket_size as i16, - relay_notify_limit_bucket_size: req_dp.relay_notify_limit_bucket_size as i16, - relay_global_uplink_limit_bucket_size: req_dp.relay_global_uplink_limit_bucket_size - as i16, - relay_overall_limit_bucket_size: req_dp.relay_overall_limit_bucket_size as i16, allow_roaming: req_dp.allow_roaming, rx1_delay: req_dp.rx1_delay as i16, abp_params: if req_dp.supports_otaa { @@ -355,6 +346,38 @@ impl DeviceProfileService for DeviceProfile { } else { None }, + relay_params: if req_dp.is_relay || req_dp.is_relay_ed { + Some(fields::RelayParams { + is_relay: req_dp.is_relay, + is_relay_ed: req_dp.is_relay_ed, + ed_relay_only: req_dp.relay_ed_relay_only, + relay_enabled: req_dp.relay_enabled, + relay_cad_periodicity: req_dp.relay_cad_periodicity as u8, + default_channel_index: req_dp.relay_default_channel_index as u8, + second_channel_freq: req_dp.relay_second_channel_freq as u32, + second_channel_dr: req_dp.relay_second_channel_dr as u8, + second_channel_ack_offset: req_dp.relay_second_channel_ack_offset as u8, + ed_activation_mode: req_dp.relay_ed_activation_mode().from_proto(), + ed_smart_enable_level: req_dp.relay_ed_smart_enable_level as u8, + ed_back_off: req_dp.relay_ed_back_off as u8, + ed_uplink_limit_bucket_size: req_dp.relay_ed_uplink_limit_bucket_size as u8, + ed_uplink_limit_reload_rate: req_dp.relay_ed_uplink_limit_reload_rate as u8, + relay_join_req_limit_reload_rate: req_dp.relay_join_req_limit_reload_rate as u8, + relay_notify_limit_reload_rate: req_dp.relay_notify_limit_reload_rate as u8, + relay_global_uplink_limit_reload_rate: req_dp + .relay_global_uplink_limit_reload_rate + as u8, + relay_overall_limit_reload_rate: req_dp.relay_overall_limit_reload_rate as u8, + relay_join_req_limit_bucket_size: req_dp.relay_join_req_limit_bucket_size as u8, + relay_notify_limit_bucket_size: req_dp.relay_notify_limit_bucket_size as u8, + relay_global_uplink_limit_bucket_size: req_dp + .relay_global_uplink_limit_bucket_size + as u8, + relay_overall_limit_bucket_size: req_dp.relay_overall_limit_bucket_size as u8, + }) + } else { + None + }, ..Default::default() }) .await diff --git a/chirpstack/src/api/relay.rs b/chirpstack/src/api/relay.rs index 7b1e85c3..81d47a2f 100644 --- a/chirpstack/src/api/relay.rs +++ b/chirpstack/src/api/relay.rs @@ -182,7 +182,7 @@ pub mod test { use super::*; use crate::api::auth::validator::RequestValidator; use crate::api::auth::AuthID; - use crate::storage::{application, device, device_profile, tenant, user}; + use crate::storage::{application, device, device_profile, fields, tenant, user}; use crate::test; #[tokio::test] @@ -229,7 +229,10 @@ pub mod test { let dp_relay = device_profile::create(device_profile::DeviceProfile { name: "test-dp".into(), tenant_id: t.id, - is_relay: true, + relay_params: Some(fields::RelayParams { + is_relay: true, + ..Default::default() + }), ..Default::default() }) .await diff --git a/chirpstack/src/downlink/data.rs b/chirpstack/src/downlink/data.rs index df928112..8079dd70 100644 --- a/chirpstack/src/downlink/data.rs +++ b/chirpstack/src/downlink/data.rs @@ -643,16 +643,18 @@ impl Data { self._set_rx_parameters().await?; self._set_tx_parameters().await?; - if self.device_profile.is_relay { - self._update_relay_conf().await?; - self._update_filter_list().await?; - self._update_uplink_list().await?; - self._request_ctrl_uplink_list().await?; - self._configure_fwd_limit_req().await?; - } + if let Some(relay_params) = self.device_profile.relay_params.clone() { + if relay_params.is_relay { + self._update_relay_conf().await?; + self._update_filter_list().await?; + self._update_uplink_list().await?; + self._request_ctrl_uplink_list().await?; + self._configure_fwd_limit_req().await?; + } - if self.device_profile.is_relay_ed { - self._update_end_device_conf().await?; + if relay_params.is_relay_ed { + self._update_end_device_conf().await?; + } } let ds = self.device.get_device_session()?; @@ -1799,6 +1801,7 @@ impl Data { let dev_eui = self.device.dev_eui; let ds = self.device.get_device_session_mut()?; + let relay_params = self.device_profile.relay_params.clone().unwrap_or_default(); // Get the current relay state. let relay = if let Some(r) = &ds.relay { @@ -1807,48 +1810,37 @@ impl Data { internal::Relay::default() }; - if relay.join_req_limit_reload_rate - != self.device_profile.relay_join_req_limit_reload_rate as u32 - || relay.notify_limit_reload_rate - != self.device_profile.relay_notify_limit_reload_rate as u32 + if relay.join_req_limit_reload_rate != relay_params.relay_join_req_limit_reload_rate as u32 + || relay.notify_limit_reload_rate != relay_params.relay_notify_limit_reload_rate as u32 || relay.global_uplink_limit_reload_rate - != self.device_profile.relay_global_uplink_limit_reload_rate as u32 + != relay_params.relay_global_uplink_limit_reload_rate as u32 || relay.overall_limit_reload_rate - != self.device_profile.relay_overall_limit_reload_rate as u32 + != relay_params.relay_overall_limit_reload_rate as u32 || relay.join_req_limit_bucket_size - != self.device_profile.relay_join_req_limit_bucket_size as u32 - || relay.notify_limit_bucket_size - != self.device_profile.relay_notify_limit_bucket_size as u32 + != relay_params.relay_join_req_limit_bucket_size as u32 + || relay.notify_limit_bucket_size != relay_params.relay_notify_limit_bucket_size as u32 || relay.global_uplink_limit_bucket_size - != self.device_profile.relay_global_uplink_limit_bucket_size as u32 + != relay_params.relay_global_uplink_limit_bucket_size as u32 || relay.overall_limit_bucket_size - != self.device_profile.relay_overall_limit_bucket_size as u32 + != relay_params.relay_overall_limit_bucket_size as u32 { let set = lrwn::MACCommandSet::new(vec![lrwn::MACCommand::ConfigureFwdLimitReq( lrwn::ConfigureFwdLimitReqPayload { reload_rate: lrwn::FwdLimitReloadRatePL { - overall_reload_rate: self.device_profile.relay_overall_limit_reload_rate - as u8, - global_uplink_reload_rate: self - .device_profile + overall_reload_rate: relay_params.relay_overall_limit_reload_rate as u8, + global_uplink_reload_rate: relay_params .relay_global_uplink_limit_reload_rate as u8, - notify_reload_rate: self.device_profile.relay_notify_limit_reload_rate - as u8, - join_req_reload_rate: self.device_profile.relay_join_req_limit_reload_rate - as u8, + notify_reload_rate: relay_params.relay_notify_limit_reload_rate as u8, + join_req_reload_rate: relay_params.relay_join_req_limit_reload_rate as u8, reset_limit_counter: lrwn::ResetLimitCounter::NoChange, }, load_capacity: lrwn::FwdLimitLoadCapacityPL { - overall_limit_size: self.device_profile.relay_overall_limit_bucket_size - as u8, - global_uplink_limit_size: self - .device_profile - .relay_global_uplink_limit_bucket_size - as u8, - notify_limit_size: self.device_profile.relay_notify_limit_bucket_size as u8, - join_req_limit_size: self.device_profile.relay_join_req_limit_bucket_size + overall_limit_size: relay_params.relay_overall_limit_bucket_size as u8, + global_uplink_limit_size: relay_params.relay_global_uplink_limit_bucket_size as u8, + notify_limit_size: relay_params.relay_notify_limit_bucket_size as u8, + join_req_limit_size: relay_params.relay_join_req_limit_bucket_size as u8, }, }, )]); @@ -2048,6 +2040,7 @@ impl Data { let dev_eui = self.device.dev_eui; let ds = self.device.get_device_session_mut()?; + let relay_params = self.device_profile.relay_params.clone().unwrap_or_default(); // Get the current relay state. let relay = if let Some(r) = &ds.relay { @@ -2056,33 +2049,31 @@ impl Data { internal::Relay::default() }; - if relay.enabled != self.device_profile.relay_enabled - || relay.cad_periodicity != self.device_profile.relay_cad_periodicity as u32 - || relay.default_channel_index != self.device_profile.relay_default_channel_index as u32 - || relay.second_channel_freq != self.device_profile.relay_second_channel_freq as u32 - || relay.second_channel_dr != self.device_profile.relay_second_channel_dr as u32 - || relay.second_channel_ack_offset - != self.device_profile.relay_second_channel_ack_offset as u32 + if relay.enabled != relay_params.relay_enabled + || relay.cad_periodicity != relay_params.relay_cad_periodicity as u32 + || relay.default_channel_index != relay_params.default_channel_index as u32 + || relay.second_channel_freq != relay_params.second_channel_freq as u32 + || relay.second_channel_dr != relay_params.second_channel_dr as u32 + || relay.second_channel_ack_offset != relay_params.second_channel_ack_offset as u32 { let set = lrwn::MACCommandSet::new(vec![lrwn::MACCommand::RelayConfReq( lrwn::RelayConfReqPayload { channel_settings_relay: lrwn::ChannelSettingsRelay { - start_stop: match self.device_profile.relay_enabled { + start_stop: match relay_params.relay_enabled { true => 1, false => 0, }, - cad_periodicity: self.device_profile.relay_cad_periodicity as u8, - default_ch_idx: self.device_profile.relay_default_channel_index as u8, - second_ch_idx: if self.device_profile.relay_second_channel_freq > 0 { + cad_periodicity: relay_params.relay_cad_periodicity as u8, + default_ch_idx: relay_params.default_channel_index as u8, + second_ch_idx: if relay_params.second_channel_freq > 0 { 1 } else { 0 }, - second_ch_dr: self.device_profile.relay_second_channel_dr as u8, - second_ch_ack_offset: self.device_profile.relay_second_channel_ack_offset - as u8, + second_ch_dr: relay_params.second_channel_dr as u8, + second_ch_ack_offset: relay_params.second_channel_ack_offset as u8, }, - second_ch_freq: self.device_profile.relay_second_channel_freq as u32, + second_ch_freq: relay_params.second_channel_freq as u32, }, )]); mac_command::set_pending(&dev_eui, lrwn::CID::RelayConfReq, &set).await?; @@ -2099,6 +2090,7 @@ impl Data { let dev_eui = self.device.dev_eui; let ds = self.device.get_device_session_mut()?; + let relay_params = self.device_profile.relay_params.clone().unwrap_or_default(); // Get the current relay state. let relay = if let Some(r) = &ds.relay { @@ -2107,32 +2099,30 @@ impl Data { internal::Relay::default() }; - if relay.ed_activation_mode != self.device_profile.relay_ed_activation_mode.to_u8() as u32 - || relay.ed_smart_enable_level != self.device_profile.relay_ed_smart_enable_level as u32 - || relay.ed_back_off != self.device_profile.relay_ed_back_off as u32 - || relay.second_channel_freq != self.device_profile.relay_second_channel_freq as u32 - || relay.second_channel_dr != self.device_profile.relay_second_channel_dr as u32 - || relay.second_channel_ack_offset - != self.device_profile.relay_second_channel_ack_offset as u32 + if relay.ed_activation_mode != relay_params.ed_activation_mode.to_u8() as u32 + || relay.ed_smart_enable_level != relay_params.ed_smart_enable_level as u32 + || relay.ed_back_off != relay_params.ed_back_off as u32 + || relay.second_channel_freq != relay_params.second_channel_freq as u32 + || relay.second_channel_dr != relay_params.second_channel_dr as u32 + || relay.second_channel_ack_offset != relay_params.second_channel_ack_offset as u32 { let set = lrwn::MACCommandSet::new(vec![lrwn::MACCommand::EndDeviceConfReq( lrwn::EndDeviceConfReqPayload { activation_relay_mode: lrwn::ActivationRelayMode { - relay_mode_activation: self.device_profile.relay_ed_activation_mode, - smart_enable_level: self.device_profile.relay_ed_smart_enable_level as u8, + relay_mode_activation: relay_params.ed_activation_mode, + smart_enable_level: relay_params.ed_smart_enable_level as u8, }, channel_settings_ed: lrwn::ChannelSettingsED { - second_ch_ack_offset: self.device_profile.relay_second_channel_ack_offset - as u8, - second_ch_dr: self.device_profile.relay_second_channel_dr as u8, - second_ch_idx: if self.device_profile.relay_second_channel_freq > 0 { + second_ch_ack_offset: relay_params.second_channel_ack_offset as u8, + second_ch_dr: relay_params.second_channel_dr as u8, + second_ch_idx: if relay_params.second_channel_freq > 0 { 1 } else { 0 }, - backoff: self.device_profile.relay_ed_back_off as u8, + backoff: relay_params.ed_back_off as u8, }, - second_ch_freq: self.device_profile.relay_second_channel_freq as u32, + second_ch_freq: relay_params.second_channel_freq as u32, }, )]); mac_command::set_pending(&dev_eui, lrwn::CID::EndDeviceConfReq, &set).await?; @@ -2696,6 +2686,7 @@ fn filter_mac_commands( #[cfg(test)] mod test { use super::*; + use crate::storage::fields; use crate::test; use lrwn::{DevAddr, EUI64}; use tokio::time::sleep; @@ -2715,7 +2706,10 @@ mod test { let dp = device_profile::create(device_profile::DeviceProfile { name: "dp".into(), tenant_id: t.id, - is_relay: true, + relay_params: Some(fields::RelayParams { + is_relay: true, + ..Default::default() + }), ..Default::default() }) .await @@ -3440,7 +3434,10 @@ mod test { let dp_relay = device_profile::create(device_profile::DeviceProfile { name: "dp-relay".into(), tenant_id: t.id, - is_relay: true, + relay_params: Some(fields::RelayParams { + is_relay: true, + ..Default::default() + }), ..Default::default() }) .await @@ -3449,9 +3446,12 @@ mod test { let dp_ed = device_profile::create(device_profile::DeviceProfile { name: "dp-ed".into(), tenant_id: t.id, - is_relay_ed: true, - relay_ed_uplink_limit_bucket_size: 2, - relay_ed_uplink_limit_reload_rate: 1, + relay_params: Some(fields::RelayParams { + is_relay_ed: true, + ed_uplink_limit_bucket_size: 2, + ed_uplink_limit_reload_rate: 1, + ..Default::default() + }), ..Default::default() }) .await @@ -3900,7 +3900,10 @@ mod test { let dp_relay = device_profile::create(device_profile::DeviceProfile { name: "dp-relay".into(), tenant_id: t.id, - is_relay: true, + relay_params: Some(fields::RelayParams { + is_relay: true, + ..Default::default() + }), ..Default::default() }) .await @@ -4023,13 +4026,16 @@ mod test { ..Default::default() }, device_profile: device_profile::DeviceProfile { - is_relay: true, - relay_enabled: true, - relay_cad_periodicity: 1, - relay_default_channel_index: 0, - relay_second_channel_freq: 868300000, - relay_second_channel_dr: 3, - relay_second_channel_ack_offset: 2, + relay_params: Some(fields::RelayParams { + is_relay: true, + relay_enabled: true, + relay_cad_periodicity: 1, + default_channel_index: 0, + second_channel_freq: 868300000, + second_channel_dr: 3, + second_channel_ack_offset: 2, + ..Default::default() + }), ..Default::default() }, expected_mac_commands: vec![], @@ -4049,13 +4055,16 @@ mod test { ..Default::default() }, device_profile: device_profile::DeviceProfile { - is_relay: true, - relay_enabled: true, - relay_cad_periodicity: 1, - relay_default_channel_index: 0, - relay_second_channel_freq: 868500000, - relay_second_channel_dr: 3, - relay_second_channel_ack_offset: 2, + relay_params: Some(fields::RelayParams { + is_relay: true, + relay_enabled: true, + relay_cad_periodicity: 1, + default_channel_index: 0, + second_channel_freq: 868500000, + second_channel_dr: 3, + second_channel_ack_offset: 2, + ..Default::default() + }), ..Default::default() }, expected_mac_commands: vec![lrwn::MACCommandSet::new(vec![ @@ -4134,12 +4143,15 @@ mod test { ..Default::default() }, device_profile: device_profile::DeviceProfile { - relay_ed_activation_mode: lrwn::RelayModeActivation::EnableRelayMode, - relay_ed_smart_enable_level: 1, - relay_ed_back_off: 16, - relay_second_channel_freq: 868100000, - relay_second_channel_dr: 3, - relay_second_channel_ack_offset: 4, + relay_params: Some(fields::RelayParams { + ed_activation_mode: lrwn::RelayModeActivation::EnableRelayMode, + ed_smart_enable_level: 1, + ed_back_off: 16, + second_channel_freq: 868100000, + second_channel_dr: 3, + second_channel_ack_offset: 4, + ..Default::default() + }), ..Default::default() }, expected_mac_commands: vec![], @@ -4159,12 +4171,15 @@ mod test { ..Default::default() }, device_profile: device_profile::DeviceProfile { - relay_ed_activation_mode: lrwn::RelayModeActivation::EnableRelayMode, - relay_ed_smart_enable_level: 1, - relay_ed_back_off: 16, - relay_second_channel_freq: 868100000, - relay_second_channel_dr: 3, - relay_second_channel_ack_offset: 4, + relay_params: Some(fields::RelayParams { + ed_activation_mode: lrwn::RelayModeActivation::EnableRelayMode, + ed_smart_enable_level: 1, + ed_back_off: 16, + second_channel_freq: 868100000, + second_channel_dr: 3, + second_channel_ack_offset: 4, + ..Default::default() + }), ..Default::default() }, expected_mac_commands: vec![lrwn::MACCommandSet::new(vec![ @@ -4247,14 +4262,17 @@ mod test { ..Default::default() }, device_profile: device_profile::DeviceProfile { - relay_join_req_limit_reload_rate: 10, - relay_join_req_limit_bucket_size: 0, - relay_notify_limit_reload_rate: 15, - relay_notify_limit_bucket_size: 1, - relay_global_uplink_limit_reload_rate: 20, - relay_global_uplink_limit_bucket_size: 2, - relay_overall_limit_reload_rate: 25, - relay_overall_limit_bucket_size: 3, + relay_params: Some(fields::RelayParams { + relay_join_req_limit_reload_rate: 10, + relay_join_req_limit_bucket_size: 0, + relay_notify_limit_reload_rate: 15, + relay_notify_limit_bucket_size: 1, + relay_global_uplink_limit_reload_rate: 20, + relay_global_uplink_limit_bucket_size: 2, + relay_overall_limit_reload_rate: 25, + relay_overall_limit_bucket_size: 3, + ..Default::default() + }), ..Default::default() }, expected_mac_commands: vec![], @@ -4276,14 +4294,17 @@ mod test { ..Default::default() }, device_profile: device_profile::DeviceProfile { - relay_join_req_limit_reload_rate: 10, - relay_join_req_limit_bucket_size: 0, - relay_notify_limit_reload_rate: 15, - relay_notify_limit_bucket_size: 1, - relay_global_uplink_limit_reload_rate: 20, - relay_global_uplink_limit_bucket_size: 2, - relay_overall_limit_reload_rate: 25, - relay_overall_limit_bucket_size: 3, + relay_params: Some(fields::RelayParams { + relay_join_req_limit_reload_rate: 10, + relay_join_req_limit_bucket_size: 0, + relay_notify_limit_reload_rate: 15, + relay_notify_limit_bucket_size: 1, + relay_global_uplink_limit_reload_rate: 20, + relay_global_uplink_limit_bucket_size: 2, + relay_overall_limit_reload_rate: 25, + relay_overall_limit_bucket_size: 3, + ..Default::default() + }), ..Default::default() }, expected_mac_commands: vec![lrwn::MACCommandSet::new(vec![ @@ -4521,7 +4542,10 @@ mod test { let dp_relay = device_profile::create(device_profile::DeviceProfile { name: "dp-relay".into(), tenant_id: t.id, - is_relay: true, + relay_params: Some(fields::RelayParams { + is_relay: true, + ..Default::default() + }), ..Default::default() }) .await diff --git a/chirpstack/src/main.rs b/chirpstack/src/main.rs index 64207dc3..12c5971b 100644 --- a/chirpstack/src/main.rs +++ b/chirpstack/src/main.rs @@ -1,6 +1,3 @@ -// Required by rust::table macro. -#![recursion_limit = "256"] - #[macro_use] extern crate lazy_static; extern crate diesel_migrations; diff --git a/chirpstack/src/storage/device_profile.rs b/chirpstack/src/storage/device_profile.rs index 2edd3798..06dbcb9b 100644 --- a/chirpstack/src/storage/device_profile.rs +++ b/chirpstack/src/storage/device_profile.rs @@ -41,33 +41,12 @@ pub struct DeviceProfile { pub measurements: fields::Measurements, pub auto_detect_measurements: bool, pub region_config_id: Option, - pub is_relay: bool, - pub is_relay_ed: bool, - pub relay_ed_relay_only: bool, - pub relay_enabled: bool, - pub relay_cad_periodicity: i16, - pub relay_default_channel_index: i16, - pub relay_second_channel_freq: i64, - pub relay_second_channel_dr: i16, - pub relay_second_channel_ack_offset: i16, - pub relay_ed_activation_mode: lrwn::RelayModeActivation, - pub relay_ed_smart_enable_level: i16, - pub relay_ed_back_off: i16, - pub relay_ed_uplink_limit_bucket_size: i16, - pub relay_ed_uplink_limit_reload_rate: i16, - pub relay_join_req_limit_reload_rate: i16, - pub relay_notify_limit_reload_rate: i16, - pub relay_global_uplink_limit_reload_rate: i16, - pub relay_overall_limit_reload_rate: i16, - pub relay_join_req_limit_bucket_size: i16, - pub relay_notify_limit_bucket_size: i16, - pub relay_global_uplink_limit_bucket_size: i16, - pub relay_overall_limit_bucket_size: i16, pub allow_roaming: bool, pub rx1_delay: i16, pub abp_params: Option, pub class_b_params: Option, pub class_c_params: Option, + pub relay_params: Option, } impl DeviceProfile { @@ -111,33 +90,12 @@ impl Default for DeviceProfile { measurements: fields::Measurements::new(HashMap::new()), auto_detect_measurements: false, region_config_id: None, - is_relay: false, - is_relay_ed: false, - relay_ed_relay_only: false, - relay_enabled: false, - relay_cad_periodicity: 0, - relay_default_channel_index: 0, - relay_second_channel_freq: 0, - relay_second_channel_dr: 0, - relay_second_channel_ack_offset: 0, - relay_ed_activation_mode: lrwn::RelayModeActivation::DisableRelayMode, - relay_ed_smart_enable_level: 0, - relay_ed_back_off: 0, - relay_ed_uplink_limit_bucket_size: 0, - relay_ed_uplink_limit_reload_rate: 0, - relay_join_req_limit_reload_rate: 0, - relay_notify_limit_reload_rate: 0, - relay_global_uplink_limit_reload_rate: 0, - relay_overall_limit_reload_rate: 0, - relay_join_req_limit_bucket_size: 0, - relay_notify_limit_bucket_size: 0, - relay_global_uplink_limit_bucket_size: 0, - relay_overall_limit_bucket_size: 0, allow_roaming: false, rx1_delay: 0, abp_params: None, class_b_params: None, class_c_params: None, + relay_params: None, } } } @@ -153,11 +111,13 @@ impl DeviceProfile { ds.class_b_ping_slot_nb = 1 << class_b_params.ping_slot_nb_k as u32; } - if self.is_relay_ed { - ds.relay = Some(internal::Relay { - ed_relay_only: self.relay_ed_relay_only, - ..Default::default() - }); + if let Some(relay_params) = &self.relay_params { + if relay_params.is_relay_ed { + ds.relay = Some(internal::Relay { + ed_relay_only: relay_params.ed_relay_only, + ..Default::default() + }); + } } if !self.supports_otaa { @@ -242,39 +202,12 @@ pub async fn update(dp: DeviceProfile) -> Result { device_profile::measurements.eq(&dp.measurements), device_profile::auto_detect_measurements.eq(&dp.auto_detect_measurements), device_profile::region_config_id.eq(&dp.region_config_id), - device_profile::is_relay.eq(&dp.is_relay), - device_profile::is_relay_ed.eq(&dp.is_relay_ed), - device_profile::relay_ed_relay_only.eq(&dp.relay_ed_relay_only), - device_profile::relay_enabled.eq(&dp.relay_enabled), - device_profile::relay_cad_periodicity.eq(&dp.relay_cad_periodicity), - device_profile::relay_default_channel_index.eq(&dp.relay_default_channel_index), - device_profile::relay_second_channel_freq.eq(&dp.relay_second_channel_freq), - device_profile::relay_second_channel_dr.eq(&dp.relay_second_channel_dr), - device_profile::relay_second_channel_ack_offset.eq(&dp.relay_second_channel_ack_offset), - device_profile::relay_ed_activation_mode.eq(&dp.relay_ed_activation_mode), - device_profile::relay_ed_smart_enable_level.eq(&dp.relay_ed_smart_enable_level), - device_profile::relay_ed_back_off.eq(&dp.relay_ed_back_off), - device_profile::relay_ed_uplink_limit_bucket_size - .eq(&dp.relay_ed_uplink_limit_bucket_size), - device_profile::relay_ed_uplink_limit_reload_rate - .eq(&dp.relay_ed_uplink_limit_reload_rate), - device_profile::relay_join_req_limit_reload_rate - .eq(&dp.relay_join_req_limit_reload_rate), - device_profile::relay_notify_limit_reload_rate.eq(&dp.relay_notify_limit_reload_rate), - device_profile::relay_global_uplink_limit_reload_rate - .eq(&dp.relay_global_uplink_limit_reload_rate), - device_profile::relay_overall_limit_reload_rate.eq(&dp.relay_overall_limit_reload_rate), - device_profile::relay_join_req_limit_bucket_size - .eq(&dp.relay_join_req_limit_bucket_size), - device_profile::relay_notify_limit_bucket_size.eq(&dp.relay_notify_limit_bucket_size), - device_profile::relay_global_uplink_limit_bucket_size - .eq(&dp.relay_global_uplink_limit_bucket_size), - device_profile::relay_overall_limit_bucket_size.eq(&dp.relay_overall_limit_bucket_size), device_profile::allow_roaming.eq(&dp.allow_roaming), device_profile::rx1_delay.eq(&dp.rx1_delay), device_profile::abp_params.eq(&dp.abp_params), device_profile::class_b_params.eq(&dp.class_b_params), device_profile::class_c_params.eq(&dp.class_c_params), + device_profile::relay_params.eq(&dp.relay_params), )) .get_result(&mut get_async_db_conn().await?) .await diff --git a/chirpstack/src/storage/fields/device_profile.rs b/chirpstack/src/storage/fields/device_profile.rs index d703b513..b079b114 100644 --- a/chirpstack/src/storage/fields/device_profile.rs +++ b/chirpstack/src/storage/fields/device_profile.rs @@ -146,3 +146,91 @@ impl serialize::ToSql for ClassCParams { Ok(serialize::IsNull::No) } } + +#[derive( + Default, Debug, Clone, PartialEq, Eq, Deserialize, Serialize, AsExpression, FromSqlRow, +)] +#[cfg_attr(feature = "postgres", diesel(sql_type = Jsonb))] +#[cfg_attr(feature = "sqlite", diesel(sql_type = Text))] +pub struct RelayParams { + pub is_relay: bool, + pub is_relay_ed: bool, + pub ed_relay_only: bool, + pub relay_enabled: bool, + pub relay_cad_periodicity: u8, + pub default_channel_index: u8, + pub second_channel_freq: u32, + pub second_channel_dr: u8, + pub second_channel_ack_offset: u8, + #[serde(with = "ed_activation_mode")] + pub ed_activation_mode: lrwn::RelayModeActivation, + pub ed_smart_enable_level: u8, + pub ed_back_off: u8, + pub ed_uplink_limit_bucket_size: u8, + pub ed_uplink_limit_reload_rate: u8, + pub relay_join_req_limit_reload_rate: u8, + pub relay_notify_limit_reload_rate: u8, + pub relay_global_uplink_limit_reload_rate: u8, + pub relay_overall_limit_reload_rate: u8, + pub relay_join_req_limit_bucket_size: u8, + pub relay_notify_limit_bucket_size: u8, + pub relay_global_uplink_limit_bucket_size: u8, + pub relay_overall_limit_bucket_size: u8, +} + +#[cfg(feature = "postgres")] +impl deserialize::FromSql for RelayParams { + 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 RelayParams { + 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 RelayParams +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 RelayParams { + 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) + } +} + +mod ed_activation_mode { + use serde::{self, Deserialize, Deserializer, Serializer}; + + pub fn serialize(v: &lrwn::RelayModeActivation, serializer: S) -> Result + where + S: Serializer, + { + serializer.serialize_u8(v.to_u8()) + } + + pub fn deserialize<'de, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let v = u8::deserialize(deserializer)?; + let v = lrwn::RelayModeActivation::from_u8(v) + .map_err(|e| serde::de::Error::custom(e.to_string()))?; + Ok(v) + } +} diff --git a/chirpstack/src/storage/fields/mod.rs b/chirpstack/src/storage/fields/mod.rs index b58d045a..fe3f8ce9 100644 --- a/chirpstack/src/storage/fields/mod.rs +++ b/chirpstack/src/storage/fields/mod.rs @@ -9,7 +9,7 @@ mod uuid; pub use big_decimal::BigDecimal; pub use dev_nonces::DevNonces; -pub use device_profile::{AbpParams, ClassBParams, ClassCParams}; +pub use device_profile::{AbpParams, ClassBParams, ClassCParams, RelayParams}; pub use device_session::DeviceSession; pub use key_value::KeyValue; pub use measurements::*; diff --git a/chirpstack/src/storage/relay.rs b/chirpstack/src/storage/relay.rs index b82553d7..5ee11f9b 100644 --- a/chirpstack/src/storage/relay.rs +++ b/chirpstack/src/storage/relay.rs @@ -1,6 +1,6 @@ use anyhow::Result; use chrono::{DateTime, Utc}; -use diesel::{dsl, prelude::*}; +use diesel::{dsl, prelude::*, sql_types}; use diesel_async::RunQueryDsl; use tracing::info; use uuid::Uuid; @@ -43,10 +43,24 @@ pub struct DeviceListItem { } pub async fn get_relay_count(filters: &RelayFilters) -> Result { - let mut q = device::dsl::device + let q = device::dsl::device .select(dsl::count_star()) - .inner_join(device_profile::table) - .filter(device_profile::dsl::is_relay.eq(true)) + .inner_join(device_profile::table); + + #[cfg(feature = "postgres")] + let mut q = q + .filter( + dsl::sql::("(relay_params->'is_relay')::boolean =") + .bind::(true), + ) + .into_boxed(); + + #[cfg(feature = "sqlite")] + let mut q = q + .filter( + dsl::sql::("relay_params->>'is_relay' =") + .bind::(true), + ) .into_boxed(); if let Some(application_id) = &filters.application_id { @@ -61,10 +75,24 @@ pub async fn list_relays( offset: i64, filters: &RelayFilters, ) -> Result, Error> { - let mut q = device::dsl::device + let q = device::dsl::device .inner_join(device_profile::table) - .select((device::dev_eui, device::name)) - .filter(device_profile::dsl::is_relay.eq(true)) + .select((device::dev_eui, device::name)); + + #[cfg(feature = "postgres")] + let mut q = q + .filter( + dsl::sql::("(relay_params->'is_relay')::boolean =") + .bind::(true), + ) + .into_boxed(); + + #[cfg(feature = "sqlite")] + let mut q = q + .filter( + dsl::sql::("relay_params->>'is_relay' =") + .bind::(true), + ) .into_boxed(); if let Some(application_id) = &filters.application_id { @@ -98,19 +126,43 @@ pub async fn list_devices( offset: i64, filters: &DeviceFilters, ) -> Result, Error> { - let mut q = relay_device::dsl::relay_device + let q = relay_device::dsl::relay_device .inner_join(device::table.on(relay_device::dsl::dev_eui.eq(device::dsl::dev_eui))) .inner_join( device_profile::table.on(device::dsl::device_profile_id.eq(device_profile::dsl::id)), - ) + ); + + #[cfg(feature = "postgres")] + let mut q = q .select(( relay_device::dev_eui, device::join_eui, device::dev_addr, relay_device::created_at, device::name, - device_profile::relay_ed_uplink_limit_bucket_size, - device_profile::relay_ed_uplink_limit_reload_rate, + dsl::sql::( + "coalesce((relay_params->'ed_uplink_limit_bucket_size')::smallint, 0::smallint)", + ), + dsl::sql::( + "coalesce((relay_params->'ed_uplink_limit_reload_rate')::smallint, 0::smallint)", + ), + )) + .into_boxed(); + + #[cfg(feature = "sqlite")] + let mut q = q + .select(( + relay_device::dev_eui, + device::join_eui, + device::dev_addr, + relay_device::created_at, + device::name, + dsl::sql::( + "coalesce(relay_params->>'ed_uplink_limit_bucket_size', 0)", + ), + dsl::sql::( + "coalesce(relay_params->>'ed_uplink_limit_reload_rate', 0)", + ), )) .into_boxed(); @@ -145,7 +197,13 @@ pub async fn add_device(relay_dev_eui: EUI64, device_dev_eui: EUI64) -> Result<( .get_result(c) .await .map_err(|e| Error::from_diesel(e, rd.device_profile_id.to_string()))?; - if !rdp.is_relay { + + if !rdp + .relay_params + .as_ref() + .map(|v| v.is_relay) + .unwrap_or_default() + { return Err(Error::Validation("Device is not a relay".to_string())); } @@ -175,8 +233,10 @@ pub async fn add_device(relay_dev_eui: EUI64, device_dev_eui: EUI64) -> Result<( } // Validate that the device is not a relay. - if dp.is_relay { - return Err(Error::Validation("Can not add relay to a relay".into())); + if let Some(relay_params) = &dp.relay_params { + if relay_params.is_relay { + return Err(Error::Validation("Can not add relay to a relay".into())); + } } // Validate max. number of devices. @@ -248,7 +308,10 @@ pub mod test { let dp_relay = storage::device_profile::create(storage::device_profile::DeviceProfile { tenant_id: dp.tenant_id, name: "relay".into(), - is_relay: true, + relay_params: Some(fields::RelayParams { + is_relay: true, + ..Default::default() + }), ..Default::default() }) .await diff --git a/chirpstack/src/storage/schema_postgres.rs b/chirpstack/src/storage/schema_postgres.rs index 300a47e2..3ad43aef 100644 --- a/chirpstack/src/storage/schema_postgres.rs +++ b/chirpstack/src/storage/schema_postgres.rs @@ -111,33 +111,12 @@ diesel::table! { auto_detect_measurements -> Bool, #[max_length = 100] region_config_id -> Nullable, - is_relay -> Bool, - is_relay_ed -> Bool, - relay_ed_relay_only -> Bool, - relay_enabled -> Bool, - relay_cad_periodicity -> Int2, - relay_default_channel_index -> Int2, - relay_second_channel_freq -> Int8, - relay_second_channel_dr -> Int2, - relay_second_channel_ack_offset -> Int2, - relay_ed_activation_mode -> Int2, - relay_ed_smart_enable_level -> Int2, - relay_ed_back_off -> Int2, - relay_ed_uplink_limit_bucket_size -> Int2, - relay_ed_uplink_limit_reload_rate -> Int2, - relay_join_req_limit_reload_rate -> Int2, - relay_notify_limit_reload_rate -> Int2, - relay_global_uplink_limit_reload_rate -> Int2, - relay_overall_limit_reload_rate -> Int2, - relay_join_req_limit_bucket_size -> Int2, - relay_notify_limit_bucket_size -> Int2, - relay_global_uplink_limit_bucket_size -> Int2, - relay_overall_limit_bucket_size -> Int2, allow_roaming -> Bool, rx1_delay -> Int2, abp_params -> Nullable, class_b_params -> Nullable, class_c_params -> Nullable, + relay_params -> Nullable, } } diff --git a/chirpstack/src/storage/schema_sqlite.rs b/chirpstack/src/storage/schema_sqlite.rs index 1fca2d14..e316d0ab 100644 --- a/chirpstack/src/storage/schema_sqlite.rs +++ b/chirpstack/src/storage/schema_sqlite.rs @@ -99,33 +99,12 @@ diesel::table! { measurements -> Text, auto_detect_measurements -> Bool, region_config_id -> Nullable, - is_relay -> Bool, - is_relay_ed -> Bool, - relay_ed_relay_only -> Bool, - relay_enabled -> Bool, - relay_cad_periodicity -> SmallInt, - relay_default_channel_index -> SmallInt, - relay_second_channel_freq -> BigInt, - relay_second_channel_dr -> SmallInt, - relay_second_channel_ack_offset -> SmallInt, - relay_ed_activation_mode -> SmallInt, - relay_ed_smart_enable_level -> SmallInt, - relay_ed_back_off -> SmallInt, - relay_ed_uplink_limit_bucket_size -> SmallInt, - relay_ed_uplink_limit_reload_rate -> SmallInt, - relay_join_req_limit_reload_rate -> SmallInt, - relay_notify_limit_reload_rate -> SmallInt, - relay_global_uplink_limit_reload_rate -> SmallInt, - relay_overall_limit_reload_rate -> SmallInt, - relay_join_req_limit_bucket_size -> SmallInt, - relay_notify_limit_bucket_size -> SmallInt, - relay_global_uplink_limit_bucket_size -> SmallInt, - relay_overall_limit_bucket_size -> SmallInt, allow_roaming -> Bool, rx1_delay -> SmallInt, abp_params -> Nullable, class_b_params -> Nullable, class_c_params -> Nullable, + relay_params -> Nullable, } } diff --git a/chirpstack/src/test/relay_class_a_test.rs b/chirpstack/src/test/relay_class_a_test.rs index b0aba525..a98c5e1b 100644 --- a/chirpstack/src/test/relay_class_a_test.rs +++ b/chirpstack/src/test/relay_class_a_test.rs @@ -62,8 +62,11 @@ async fn test_lorawan_10() { mac_version: lrwn::region::MacVersion::LORAWAN_1_0_4, reg_params_revision: lrwn::region::Revision::RP002_1_0_3, supports_otaa: true, - is_relay: true, - relay_enabled: true, + relay_params: Some(fields::RelayParams { + is_relay: true, + relay_enabled: true, + ..Default::default() + }), ..Default::default() }) .await @@ -76,7 +79,10 @@ async fn test_lorawan_10() { mac_version: lrwn::region::MacVersion::LORAWAN_1_0_4, reg_params_revision: lrwn::region::Revision::RP002_1_0_3, supports_otaa: true, - is_relay_ed: true, + relay_params: Some(fields::RelayParams { + is_relay_ed: true, + ..Default::default() + }), ..Default::default() }) .await diff --git a/chirpstack/src/test/relay_otaa_test.rs b/chirpstack/src/test/relay_otaa_test.rs index f162b541..89c45604 100644 --- a/chirpstack/src/test/relay_otaa_test.rs +++ b/chirpstack/src/test/relay_otaa_test.rs @@ -6,7 +6,7 @@ use super::assert; use crate::storage::{ application, device::{self, DeviceClass}, - device_keys, device_profile, gateway, tenant, + device_keys, device_profile, fields, gateway, tenant, }; use crate::{gateway::backend as gateway_backend, integration, test, uplink}; use chirpstack_api::{common, gw, internal}; @@ -66,7 +66,10 @@ async fn test_lorawan_10() { mac_version: lrwn::region::MacVersion::LORAWAN_1_0_2, reg_params_revision: lrwn::region::Revision::A, supports_otaa: true, - is_relay: true, + relay_params: Some(fields::RelayParams { + is_relay: true, + ..Default::default() + }), ..Default::default() }) .await diff --git a/chirpstack/src/uplink/data.rs b/chirpstack/src/uplink/data.rs index 9e0517f6..844edeb8 100644 --- a/chirpstack/src/uplink/data.rs +++ b/chirpstack/src/uplink/data.rs @@ -1396,8 +1396,10 @@ impl Data { let dp = self.device_profile.as_ref().unwrap(); if let lrwn::Payload::MACPayload(pl) = &self.phy_payload.payload { - if dp.is_relay && pl.f_port.unwrap_or(0) == lrwn::LA_FPORT_RELAY { - return true; + if let Some(relay_params) = &dp.relay_params { + if relay_params.is_relay && pl.f_port.unwrap_or(0) == lrwn::LA_FPORT_RELAY { + return true; + } } } diff --git a/chirpstack/src/uplink/join.rs b/chirpstack/src/uplink/join.rs index 6f1132bb..92cbc96b 100644 --- a/chirpstack/src/uplink/join.rs +++ b/chirpstack/src/uplink/join.rs @@ -381,10 +381,11 @@ impl JoinRequest { fn abort_on_relay_only_comm(&self) -> Result<(), Error> { // In case the relay context is not set and relay_ed_relay_only is set, abort. - if self.relay_context.is_none() && self.device_profile.as_ref().unwrap().relay_ed_relay_only - { - info!(dev_eui = %self.device.as_ref().unwrap().dev_eui, "Only communication through relay is allowed"); - return Err(Error::Abort); + if let Some(relay_params) = &self.device_profile.as_ref().unwrap().relay_params { + if self.relay_context.is_none() && relay_params.ed_relay_only { + info!(dev_eui = %self.device.as_ref().unwrap().dev_eui, "Only communication through relay is allowed"); + return Err(Error::Abort); + } } Ok(()) } diff --git a/lrwn/src/maccommand.rs b/lrwn/src/maccommand.rs index 5f527d04..6340e396 100644 --- a/lrwn/src/maccommand.rs +++ b/lrwn/src/maccommand.rs @@ -4,12 +4,8 @@ use std::ops::{Deref, DerefMut}; use std::time::Duration; use anyhow::Result; -#[cfg(feature = "sqlite")] -use diesel::sqlite::Sqlite; -#[cfg(feature = "diesel")] -use diesel::{backend::Backend, deserialize, serialize, sql_types::SmallInt}; #[cfg(feature = "serde")] -use serde::Serialize; +use serde::{Deserialize, Serialize}; use crate::cflist::ChMask; use crate::dl_settings::DLSettings; @@ -1811,10 +1807,10 @@ impl PayloadCodec for RelayConfAnsPayload { } } -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -#[cfg_attr(feature = "serde", derive(Serialize))] -#[cfg_attr(feature = "diesel", derive(AsExpression, FromSqlRow), diesel(sql_type = diesel::sql_types::SmallInt))] +#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub enum RelayModeActivation { + #[default] DisableRelayMode, EnableRelayMode, Dynamic, @@ -1876,37 +1872,6 @@ impl ResetLimitCounter { } } -#[cfg(feature = "diesel")] -impl deserialize::FromSql for RelayModeActivation -where - DB: Backend, - i16: deserialize::FromSql, -{ - fn from_sql(value: ::RawValue<'_>) -> deserialize::Result { - let i = i16::from_sql(value)?; - Ok(RelayModeActivation::from_u8(i as u8)?) - } -} - -#[cfg(feature = "postgres")] -impl serialize::ToSql for RelayModeActivation -where - i16: serialize::ToSql, -{ - fn to_sql(&self, out: &mut serialize::Output<'_, '_, diesel::pg::Pg>) -> serialize::Result { - let i = self.to_u8() as i16; - >::to_sql(&i, &mut out.reborrow()) - } -} - -#[cfg(feature = "sqlite")] -impl serialize::ToSql for RelayModeActivation { - fn to_sql<'b>(&'b self, out: &mut serialize::Output<'b, '_, Sqlite>) -> serialize::Result { - out.set_value(self.to_u8() as i32); - Ok(serialize::IsNull::No) - } -} - #[derive(Debug, PartialEq, Eq, Clone)] #[cfg_attr(feature = "serde", derive(Serialize))] pub struct ActivationRelayMode {