Skip to content

Commit 9ced9b4

Browse files
author
Ulf Lilleengen
authored
Merge pull request #23 from badrbouslikhin/main
feat: support publish retransmit
2 parents d93b61e + 3ebefb7 commit 9ced9b4

File tree

5 files changed

+132
-14
lines changed

5 files changed

+132
-14
lines changed

btmesh-device/src/lib.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ pub use btmesh_common::{
1818
ProductIdentifier, VersionIdentifier,
1919
};
2020
use btmesh_common::{IvIndex, ParseError, Ttl};
21-
use btmesh_models::foundation::configuration::model_publication::{PublishPeriod, Resolution};
21+
use btmesh_models::foundation::configuration::model_publication::{
22+
PublishPeriod, PublishRetransmit, Resolution,
23+
};
2224
use btmesh_models::foundation::configuration::{AppKeyIndex, NetKeyIndex};
2325
pub use btmesh_models::Model;
2426
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
@@ -56,6 +58,7 @@ pub enum InboundBody {
5658
pub enum Control {
5759
Shutdown,
5860
PublicationCadence(PublicationCadence),
61+
PublicationRetransmission(PublicationRetransmission),
5962
}
6063

6164
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -82,6 +85,33 @@ impl From<PublishPeriod> for PublicationCadence {
8285
}
8386
}
8487

88+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
89+
#[derive(Copy, Clone, Eq, PartialEq)]
90+
pub struct Retransmission {
91+
pub count: u8,
92+
pub interval: Duration,
93+
}
94+
95+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
96+
#[derive(Copy, Clone, Eq, PartialEq)]
97+
pub enum PublicationRetransmission {
98+
None,
99+
RetransmitCountInterval(Retransmission),
100+
}
101+
102+
impl From<PublishRetransmit> for PublicationRetransmission {
103+
fn from(val: PublishRetransmit) -> Self {
104+
if val.count() == 0 {
105+
PublicationRetransmission::None
106+
} else {
107+
PublicationRetransmission::RetransmitCountInterval(Retransmission {
108+
count: val.count(),
109+
interval: Duration::from_millis((val.interval_steps() as u64 + 1) * 50),
110+
})
111+
}
112+
}
113+
}
114+
85115
pub struct InboundMessage {
86116
pub opcode: Opcode,
87117
pub parameters: Vec<u8, 380>,
@@ -383,12 +413,14 @@ impl From<ApplicationKeyHandle> for AppKeyIndex {
383413

384414
pub struct CompositionExtra {
385415
pub publication_cadence: PublicationCadence,
416+
pub publication_retransmission: PublicationRetransmission,
386417
}
387418

388419
impl Default for CompositionExtra {
389420
fn default() -> Self {
390421
Self {
391422
publication_cadence: PublicationCadence::None,
423+
publication_retransmission: PublicationRetransmission::None,
392424
}
393425
}
394426
}

btmesh-driver/src/dispatch.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use btmesh_common::{ModelIdentifier, Seq};
55
use btmesh_device::access_counted::AccessCounted;
66
use btmesh_device::{
77
Control, InboundBody, InboundChannelSender, InboundMessage, InboundPayload, PublicationCadence,
8+
PublicationRetransmission,
89
};
910
use btmesh_models::foundation::configuration::ConfigurationServer;
1011
use btmesh_models::Model;
@@ -142,7 +143,7 @@ impl Dispatcher {
142143
Ok(())
143144
}
144145

145-
pub async fn dispatch_publish(
146+
pub async fn dispatch_publish_cadence(
146147
&self,
147148
element_index: u8,
148149
model_identifier: ModelIdentifier,
@@ -166,6 +167,31 @@ impl Dispatcher {
166167
PAYLOAD.wait().await;
167168
}
168169
}
170+
171+
pub async fn dispatch_publish_retransmission(
172+
&self,
173+
element_index: u8,
174+
model_identifier: ModelIdentifier,
175+
retransmission: PublicationRetransmission,
176+
) {
177+
unsafe {
178+
PAYLOAD.set(InboundPayload {
179+
element_index: element_index as usize,
180+
model_identifier: Some(model_identifier),
181+
body: InboundBody::Control(Control::PublicationRetransmission(retransmission)),
182+
});
183+
}
184+
185+
if element_index == 0 && model_identifier == ConfigurationServer::IDENTIFIER {
186+
self.foundation_sender.send(unsafe { PAYLOAD.get() }).await;
187+
}
188+
189+
self.device_sender.send(unsafe { PAYLOAD.get() }).await;
190+
191+
unsafe {
192+
PAYLOAD.wait().await;
193+
}
194+
}
169195
}
170196

171197
static mut PAYLOAD: AccessCounted<InboundPayload> = AccessCounted::new();

btmesh-driver/src/lib.rs

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ use btmesh_common::address::{Address, UnicastAddress};
1313
use btmesh_common::{Composition, Seq, Ttl, Uuid};
1414
use btmesh_device::{
1515
BluetoothMeshDevice, CompletionToken, CompositionExtra, InboundChannel, InboundChannelReceiver,
16-
KeyHandle, OutboundChannel, OutboundExtra, OutboundPayload, PublicationCadence, SendExtra,
16+
KeyHandle, OutboundChannel, OutboundExtra, OutboundPayload, PublicationCadence,
17+
PublicationRetransmission, SendExtra,
1718
};
1819
use btmesh_models::foundation::configuration::model_publication::PublishAddress;
1920
use btmesh_models::foundation::configuration::CONFIGURATION_SERVER;
@@ -523,29 +524,55 @@ impl<'s, N: NetworkInterfaces, R: RngCore + CryptoRng, B: BackingStore> InnerDri
523524
{
524525
let pub_cadence =
525526
PublicationCadence::from(publication.details.publish_period);
527+
let pub_retransmit =
528+
PublicationRetransmission::from(publication.details.publish_retransmit);
526529

527530
if model_descriptor.extra.publication_cadence != pub_cadence {
528531
self.dispatcher
529532
.borrow()
530-
.dispatch_publish(
533+
.dispatch_publish_cadence(
531534
element_index as u8,
532535
model_descriptor.model_identifier,
533536
pub_cadence,
534537
)
535538
.await;
536539
model_descriptor.extra.publication_cadence = pub_cadence;
537540
}
541+
if model_descriptor.extra.publication_retransmission != pub_retransmit {
542+
self.dispatcher
543+
.borrow()
544+
.dispatch_publish_retransmission(
545+
element_index as u8,
546+
model_descriptor.model_identifier,
547+
pub_retransmit,
548+
)
549+
.await;
550+
model_descriptor.extra.publication_retransmission = pub_retransmit;
551+
}
538552
} else if model_descriptor.extra.publication_cadence != PublicationCadence::None
539553
{
540554
self.dispatcher
541555
.borrow()
542-
.dispatch_publish(
556+
.dispatch_publish_cadence(
543557
element_index as u8,
544558
model_descriptor.model_identifier,
545559
PublicationCadence::None,
546560
)
547561
.await;
548562
model_descriptor.extra.publication_cadence = PublicationCadence::None;
563+
} else if model_descriptor.extra.publication_retransmission
564+
!= PublicationRetransmission::None
565+
{
566+
self.dispatcher
567+
.borrow()
568+
.dispatch_publish_retransmission(
569+
element_index as u8,
570+
model_descriptor.model_identifier,
571+
PublicationRetransmission::None,
572+
)
573+
.await;
574+
model_descriptor.extra.publication_retransmission =
575+
PublicationRetransmission::None;
549576
}
550577
}
551578
}
@@ -556,14 +583,28 @@ impl<'s, N: NetworkInterfaces, R: RngCore + CryptoRng, B: BackingStore> InnerDri
556583
if model_descriptor.extra.publication_cadence != PublicationCadence::None {
557584
self.dispatcher
558585
.borrow()
559-
.dispatch_publish(
586+
.dispatch_publish_cadence(
560587
element_index as u8,
561588
model_descriptor.model_identifier,
562589
PublicationCadence::None,
563590
)
564591
.await;
565592
model_descriptor.extra.publication_cadence = PublicationCadence::None;
566593
}
594+
if model_descriptor.extra.publication_retransmission
595+
!= PublicationRetransmission::None
596+
{
597+
self.dispatcher
598+
.borrow()
599+
.dispatch_publish_retransmission(
600+
element_index as u8,
601+
model_descriptor.model_identifier,
602+
PublicationRetransmission::None,
603+
)
604+
.await;
605+
model_descriptor.extra.publication_retransmission =
606+
PublicationRetransmission::None;
607+
}
567608
}
568609
}
569610
}

btmesh-driver/src/storage/provisioned/publications.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::DriverError;
22
use btmesh_common::{Composition, ModelIdentifier};
3+
use btmesh_device::{PublicationCadence, PublicationRetransmission};
34
use btmesh_models::foundation::configuration::model_publication::{
45
PublicationDetails, PublishAddress,
56
};
@@ -30,11 +31,12 @@ impl<const N: usize> Publications<N> {
3031
if let Some(publication) = self.get(index as u8, model_descriptor.model_identifier)
3132
{
3233
info!(
33-
" {} --> {} {}/{}",
34+
" {} --> {} {} / {} {}",
3435
model_descriptor.model_identifier,
3536
publication.details.publish_address,
3637
publication.details.publish_ttl,
37-
publication.details.publish_period
38+
PublicationCadence::from(publication.details.publish_period),
39+
PublicationRetransmission::from(publication.details.publish_retransmit)
3840
);
3941
}
4042
}

btmesh-models/src/foundation/configuration/model_publication.rs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ impl PublishRetransmit {
432432
/// Creates new publish retransmit using count and steps.
433433
pub fn new(count: u8, interval_steps: u8) -> Self {
434434
Self {
435-
retransmit: (count << 5) | (interval_steps & 0b00011111),
435+
retransmit: (interval_steps << 3) | (count & 0b00000111),
436436
}
437437
}
438438
/// Creates new publish period from u8.
@@ -442,12 +442,12 @@ impl PublishRetransmit {
442442

443443
/// Returns publish retransmit count.
444444
pub fn count(&self) -> u8 {
445-
self.retransmit >> 5
445+
self.retransmit & 0b00000111
446446
}
447447

448448
/// Returns publish retransmit steps.
449449
pub fn interval_steps(&self) -> u8 {
450-
self.retransmit & 0b00011111
450+
self.retransmit >> 3
451451
}
452452
}
453453

@@ -522,10 +522,27 @@ mod tests {
522522

523523
#[test]
524524
fn test_retransmit() {
525-
let rxt = PublishRetransmit::from(0xa0);
526-
assert_eq!(rxt.count(), 5);
525+
let rxt = PublishRetransmit::new(0, 0);
526+
assert_eq!(rxt.count(), 0);
527527
assert_eq!(rxt.interval_steps(), 0);
528+
assert_eq!(u8::from(rxt), 0b00000000);
528529

529-
assert_eq!(u8::from(rxt), 0b10100000);
530+
let rxt2 = PublishRetransmit::new(5, 1);
531+
assert_eq!(rxt2.count(), 5);
532+
assert_eq!(rxt2.interval_steps(), 1);
533+
assert_eq!(u8::from(rxt2), 0b00001101);
534+
535+
let rxt3 = PublishRetransmit::new(7, 31);
536+
assert_eq!(rxt3.count(), 7);
537+
assert_eq!(rxt3.interval_steps(), 31);
538+
assert_eq!(u8::from(rxt3), 0b11111111);
539+
540+
let rxt4 = PublishRetransmit::from(0b00000001);
541+
assert_eq!(rxt4.count(), 1);
542+
assert_eq!(rxt4.interval_steps(), 0);
543+
544+
let rxt5 = PublishRetransmit::from(0b00001001);
545+
assert_eq!(rxt5.count(), 1);
546+
assert_eq!(rxt5.interval_steps(), 1);
530547
}
531548
}

0 commit comments

Comments
 (0)