Align multicast class-b ping-slot config.

This aligns the multicast class-b ping-slot configuration with the way
how it is configured in the device-profile. This deprecates the
class_b_ping_slot_period field in favor of the class_b_ping_slot_nb_k
field, which should be a value between 0 - 7 (this is defined and
explained by the LoRaWAN specification).

Closes #255.
This commit is contained in:
Orne Brocaar 2024-03-26 16:45:24 +00:00
parent e96e828d3f
commit c71b856c78
10 changed files with 77 additions and 33 deletions

View File

@ -164,8 +164,15 @@ message MulticastGroup {
uint32 frequency = 11; uint32 frequency = 11;
// Ping-slot period (only for Class-B). // Ping-slot period (only for Class-B).
// Deprecated: use class_b_ping_slot_nb_k.
uint32 class_b_ping_slot_period = 12; uint32 class_b_ping_slot_period = 12;
// Class-B ping-slots per beacon period (only for Class-B).
// Valid options are: 0 - 7;
//
// The actual number of ping-slots per beacon period equals to 2^k.
uint32 class_b_ping_slot_nb_k = 14;
// Scheduling type (only for Class-C). // Scheduling type (only for Class-C).
MulticastGroupSchedulingType class_c_scheduling_type = 13; MulticastGroupSchedulingType class_c_scheduling_type = 13;
} }

View File

@ -164,8 +164,15 @@ message MulticastGroup {
uint32 frequency = 11; uint32 frequency = 11;
// Ping-slot period (only for Class-B). // Ping-slot period (only for Class-B).
// Deprecated: use class_b_ping_slot_nb_k.
uint32 class_b_ping_slot_period = 12; uint32 class_b_ping_slot_period = 12;
// Class-B ping-slots per beacon period (only for Class-B).
// Valid options are: 0 - 7;
//
// The actual number of ping-slots per beacon period equals to 2^k.
uint32 class_b_ping_slot_nb_k = 14;
// Scheduling type (only for Class-C). // Scheduling type (only for Class-C).
MulticastGroupSchedulingType class_c_scheduling_type = 13; MulticastGroupSchedulingType class_c_scheduling_type = 13;
} }

View File

@ -0,0 +1,8 @@
alter table multicast_group
alter column class_b_ping_slot_nb_k type integer;
update multicast_group set class_b_ping_slot_nb_k = pow(2, class_b_ping_slot_nb_k) * 32;
alter table multicast_group
rename column class_b_ping_slot_nb_k to class_b_ping_slot_period;

View File

@ -0,0 +1,8 @@
alter table multicast_group
rename column class_b_ping_slot_period to class_b_ping_slot_nb_k;
update multicast_group set class_b_ping_slot_nb_k = log(2, class_b_ping_slot_nb_k / 32);
alter table multicast_group
alter column class_b_ping_slot_nb_k type smallint;

View File

@ -61,7 +61,14 @@ impl MulticastGroupService for MulticastGroup {
.to_string(), .to_string(),
dr: req_mg.dr as i16, dr: req_mg.dr as i16,
frequency: req_mg.frequency as i64, frequency: req_mg.frequency as i64,
class_b_ping_slot_period: req_mg.class_b_ping_slot_period as i32, class_b_ping_slot_nb_k: if req_mg.class_b_ping_slot_period != 0 {
// For backwards compatibility.
(req_mg.class_b_ping_slot_period / 32)
.checked_ilog2()
.unwrap_or_default()
} else {
req_mg.class_b_ping_slot_nb_k
} as i16,
class_c_scheduling_type: req_mg.class_c_scheduling_type().from_proto(), class_c_scheduling_type: req_mg.class_c_scheduling_type().from_proto(),
..Default::default() ..Default::default()
}; };
@ -114,7 +121,8 @@ impl MulticastGroupService for MulticastGroup {
.into(), .into(),
dr: mg.dr as u32, dr: mg.dr as u32,
frequency: mg.frequency as u32, frequency: mg.frequency as u32,
class_b_ping_slot_period: mg.class_b_ping_slot_period as u32, class_b_ping_slot_period: (1 << (mg.class_b_ping_slot_nb_k as u32)) * 32,
class_b_ping_slot_nb_k: mg.class_b_ping_slot_nb_k as u32,
class_c_scheduling_type: mg.class_c_scheduling_type.to_proto().into(), class_c_scheduling_type: mg.class_c_scheduling_type.to_proto().into(),
}), }),
created_at: Some(helpers::datetime_to_prost_timestamp(&mg.created_at)), created_at: Some(helpers::datetime_to_prost_timestamp(&mg.created_at)),
@ -160,7 +168,14 @@ impl MulticastGroupService for MulticastGroup {
.to_string(), .to_string(),
dr: req_mg.dr as i16, dr: req_mg.dr as i16,
frequency: req_mg.frequency as i64, frequency: req_mg.frequency as i64,
class_b_ping_slot_period: req_mg.class_b_ping_slot_period as i32, class_b_ping_slot_nb_k: if req_mg.class_b_ping_slot_period != 0 {
// For backwards compatibility.
(req_mg.class_b_ping_slot_period / 32)
.checked_ilog2()
.unwrap_or_default()
} else {
req_mg.class_b_ping_slot_nb_k
} as i16,
class_c_scheduling_type: req_mg.class_c_scheduling_type().from_proto(), class_c_scheduling_type: req_mg.class_c_scheduling_type().from_proto(),
..Default::default() ..Default::default()
}) })
@ -579,7 +594,7 @@ pub mod test {
group_type: api::MulticastGroupType::ClassC.into(), group_type: api::MulticastGroupType::ClassC.into(),
dr: 3, dr: 3,
frequency: 868300000, frequency: 868300000,
class_b_ping_slot_period: 1, class_b_ping_slot_nb_k: 1,
class_c_scheduling_type: api::MulticastGroupSchedulingType::GpsTime.into(), class_c_scheduling_type: api::MulticastGroupSchedulingType::GpsTime.into(),
..Default::default() ..Default::default()
}), }),
@ -609,7 +624,8 @@ pub mod test {
group_type: api::MulticastGroupType::ClassC.into(), group_type: api::MulticastGroupType::ClassC.into(),
dr: 3, dr: 3,
frequency: 868300000, frequency: 868300000,
class_b_ping_slot_period: 1, class_b_ping_slot_nb_k: 1,
class_b_ping_slot_period: 64,
class_c_scheduling_type: api::MulticastGroupSchedulingType::GpsTime.into(), class_c_scheduling_type: api::MulticastGroupSchedulingType::GpsTime.into(),
}), }),
get_resp.get_ref().multicast_group get_resp.get_ref().multicast_group
@ -631,7 +647,8 @@ pub mod test {
group_type: api::MulticastGroupType::ClassB.into(), group_type: api::MulticastGroupType::ClassB.into(),
dr: 2, dr: 2,
frequency: 868200000, frequency: 868200000,
class_b_ping_slot_period: 2, class_b_ping_slot_nb_k: 2,
class_b_ping_slot_period: 0,
class_c_scheduling_type: api::MulticastGroupSchedulingType::Delay.into(), class_c_scheduling_type: api::MulticastGroupSchedulingType::Delay.into(),
}), }),
}, },
@ -659,7 +676,8 @@ pub mod test {
group_type: api::MulticastGroupType::ClassB.into(), group_type: api::MulticastGroupType::ClassB.into(),
dr: 2, dr: 2,
frequency: 868200000, frequency: 868200000,
class_b_ping_slot_period: 2, class_b_ping_slot_nb_k: 2,
class_b_ping_slot_period: 128,
class_c_scheduling_type: api::MulticastGroupSchedulingType::Delay.into(), class_c_scheduling_type: api::MulticastGroupSchedulingType::Delay.into(),
}), }),
get_resp.get_ref().multicast_group get_resp.get_ref().multicast_group

View File

@ -376,7 +376,7 @@ pub mod test {
group_type: "C".into(), group_type: "C".into(),
dr: 1, dr: 1,
frequency: 868100000, frequency: 868100000,
class_b_ping_slot_period: 1, class_b_ping_slot_nb_k: 1,
..Default::default() ..Default::default()
}) })
.await .await

View File

@ -33,7 +33,7 @@ pub struct MulticastGroup {
pub group_type: String, pub group_type: String,
pub dr: i16, pub dr: i16,
pub frequency: i64, pub frequency: i64,
pub class_b_ping_slot_period: i32, pub class_b_ping_slot_nb_k: i16,
pub class_c_scheduling_type: fields::MulticastGroupSchedulingType, pub class_c_scheduling_type: fields::MulticastGroupSchedulingType,
} }
@ -64,7 +64,7 @@ impl Default for MulticastGroup {
group_type: "".into(), group_type: "".into(),
dr: 0, dr: 0,
frequency: 0, frequency: 0,
class_b_ping_slot_period: 0, class_b_ping_slot_nb_k: 0,
class_c_scheduling_type: fields::MulticastGroupSchedulingType::DELAY, class_c_scheduling_type: fields::MulticastGroupSchedulingType::DELAY,
} }
} }
@ -165,7 +165,7 @@ pub async fn update(mg: MulticastGroup) -> Result<MulticastGroup, Error> {
multicast_group::group_type.eq(&mg.group_type), multicast_group::group_type.eq(&mg.group_type),
multicast_group::dr.eq(&mg.dr), multicast_group::dr.eq(&mg.dr),
multicast_group::frequency.eq(&mg.frequency), multicast_group::frequency.eq(&mg.frequency),
multicast_group::class_b_ping_slot_period.eq(&mg.class_b_ping_slot_period), multicast_group::class_b_ping_slot_nb_k.eq(&mg.class_b_ping_slot_nb_k),
multicast_group::class_c_scheduling_type.eq(&mg.class_c_scheduling_type), multicast_group::class_c_scheduling_type.eq(&mg.class_c_scheduling_type),
)) ))
.get_result(&mut get_async_db_conn().await?) .get_result(&mut get_async_db_conn().await?)
@ -405,11 +405,7 @@ pub async fn enqueue(
match mg.group_type.as_ref() { match mg.group_type.as_ref() {
"B" => { "B" => {
// get ping nb // get ping nb
let ping_nb = if mg.class_b_ping_slot_period != 0 { let ping_nb = 1 << mg.class_b_ping_slot_nb_k as usize;
(1 << 12) / mg.class_b_ping_slot_period
} else {
0
} as usize;
// get max. gps epoch time. // get max. gps epoch time.
let res: Option<i64> = let res: Option<i64> =
@ -684,7 +680,7 @@ pub mod test {
group_type: "C".into(), group_type: "C".into(),
dr: 1, dr: 1,
frequency: 868100000, frequency: 868100000,
class_b_ping_slot_period: 1, class_b_ping_slot_nb_k: 1,
..Default::default() ..Default::default()
}) })
.await .await
@ -697,7 +693,7 @@ pub mod test {
// update // update
mg.name = "test-mg-updated".into(); mg.name = "test-mg-updated".into();
mg.group_type = "B".into(); mg.group_type = "B".into();
mg.class_b_ping_slot_period = 3; mg.class_b_ping_slot_nb_k = 4;
mg = update(mg).await.unwrap(); mg = update(mg).await.unwrap();
let mg_get = get(&mg.id).await.unwrap(); let mg_get = get(&mg.id).await.unwrap();
assert_eq!(mg, mg_get); assert_eq!(mg, mg_get);
@ -822,7 +818,7 @@ pub mod test {
group_type: "C".into(), group_type: "C".into(),
dr: 1, dr: 1,
frequency: 868100000, frequency: 868100000,
class_b_ping_slot_period: 1, class_b_ping_slot_nb_k: 1,
..Default::default() ..Default::default()
}) })
.await .await
@ -880,7 +876,7 @@ pub mod test {
group_type: "C".into(), group_type: "C".into(),
dr: 1, dr: 1,
frequency: 868100000, frequency: 868100000,
class_b_ping_slot_period: 1, class_b_ping_slot_nb_k: 1,
..Default::default() ..Default::default()
}) })
.await .await
@ -938,7 +934,7 @@ pub mod test {
group_type: "C".into(), group_type: "C".into(),
dr: 1, dr: 1,
frequency: 868100000, frequency: 868100000,
class_b_ping_slot_period: 1, class_b_ping_slot_nb_k: 1,
class_c_scheduling_type: fields::MulticastGroupSchedulingType::DELAY, class_c_scheduling_type: fields::MulticastGroupSchedulingType::DELAY,
..Default::default() ..Default::default()
}) })

View File

@ -243,7 +243,7 @@ diesel::table! {
group_type -> Bpchar, group_type -> Bpchar,
dr -> Int2, dr -> Int2,
frequency -> Int8, frequency -> Int8,
class_b_ping_slot_period -> Int4, class_b_ping_slot_nb_k -> Int2,
#[max_length = 20] #[max_length = 20]
class_c_scheduling_type -> Varchar, class_c_scheduling_type -> Varchar,
} }

View File

@ -82,7 +82,7 @@ async fn test_multicast() {
group_type: "C".into(), group_type: "C".into(),
dr: 3, dr: 3,
frequency: 868300000, frequency: 868300000,
class_b_ping_slot_period: 32, class_b_ping_slot_nb_k: 0,
..Default::default() ..Default::default()
}) })
.await .await

View File

@ -47,7 +47,7 @@ function MulticastGroupForm(props: IProps) {
mg.setFrequency(v.frequency); mg.setFrequency(v.frequency);
mg.setRegion(v.region); mg.setRegion(v.region);
mg.setGroupType(v.groupType); mg.setGroupType(v.groupType);
mg.setClassBPingSlotPeriod(v.classBPingSlotPeriod); mg.setClassBPingSlotNbK(v.classBPingSlotNbK);
mg.setClassCSchedulingType(v.classCSchedulingType); mg.setClassCSchedulingType(v.classCSchedulingType);
props.onFinish(mg); props.onFinish(mg);
@ -146,16 +146,16 @@ function MulticastGroupForm(props: IProps) {
</Form.Item> </Form.Item>
</Col> </Col>
<Col span={8}> <Col span={8}>
<Form.Item label="Class-B ping-slot periodicity" name="classBPingSlotPeriod"> <Form.Item label="Class-B ping-slot periodicity" name="classBPingSlotNbK">
<Select disabled={!selectPingSlotPeriod || props.disabled}> <Select disabled={!selectPingSlotPeriod || props.disabled}>
<Select.Option value={32 * 1}>Every second</Select.Option> <Select.Option value={0}>Every second</Select.Option>
<Select.Option value={32 * 2}>Every 2 seconds</Select.Option> <Select.Option value={1}>Every 2 seconds</Select.Option>
<Select.Option value={32 * 4}>Every 4 seconds</Select.Option> <Select.Option value={2}>Every 4 seconds</Select.Option>
<Select.Option value={32 * 8}>Every 8 seconds</Select.Option> <Select.Option value={3}>Every 8 seconds</Select.Option>
<Select.Option value={32 * 16}>Every 16 seconds</Select.Option> <Select.Option value={4}>Every 16 seconds</Select.Option>
<Select.Option value={32 * 32}>Every 32 seconds</Select.Option> <Select.Option value={5}>Every 32 seconds</Select.Option>
<Select.Option value={32 * 64}>Every 64 seconds</Select.Option> <Select.Option value={6}>Every 64 seconds</Select.Option>
<Select.Option value={32 * 128}>Every 128 seconds</Select.Option> <Select.Option value={7}>Every 128 seconds</Select.Option>
</Select> </Select>
</Form.Item> </Form.Item>
</Col> </Col>