dmx_rdm/
unique_identifier.rs

1use crate::consts::BROADCAST_UID;
2use crate::rdm_types::DeserializationError;
3
4/// The unique id that is used as a source id in the packages.
5///
6/// There shouldn't be multiple devices with same unique id.
7/// The manufacturer uids are assigned by the esta.
8/// [more information](https://tsp.esta.org/tsp/working_groups/CP/mfctrIDs.php)
9#[derive(Debug, Copy, Clone, Eq, PartialEq)]
10pub struct UniqueIdentifier {
11    manufacturer_uid: u16,
12    device_uid: u32,
13}
14
15impl core::fmt::Display for UniqueIdentifier {
16    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
17        write!(f, "{:04X}:{:08X}", self.manufacturer_uid, self.device_uid)
18    }
19}
20
21#[cfg(feature = "defmt")]
22impl defmt::Format for UniqueIdentifier {
23    fn format(&self, fmt: defmt::Formatter) {
24        defmt::write!(fmt, "{:04X}:{:08X}", self.manufacturer_uid, self.device_uid);
25    }
26}
27
28impl UniqueIdentifier {
29    pub const fn new(manufacturer_uid: u16, device_uid: u32) -> Result<Self, DeserializationError> {
30        if device_uid == u32::MAX || manufacturer_uid == u16::MAX {
31            return Err(DeserializationError);
32        }
33
34        Ok(UniqueIdentifier {
35            manufacturer_uid,
36            device_uid,
37        })
38    }
39
40    pub fn manufacturer_uid(&self) -> u16 {
41        self.manufacturer_uid
42    }
43
44    pub fn device_uid(&self) -> u32 {
45        self.device_uid
46    }
47
48    pub fn set_manufacturer_uid(
49        &mut self,
50        manufacturer_uid: u16,
51    ) -> Result<(), DeserializationError> {
52        if manufacturer_uid == u16::MAX {
53            return Err(DeserializationError);
54        }
55
56        self.manufacturer_uid = manufacturer_uid;
57        Ok(())
58    }
59
60    pub fn set_device_uid(&mut self, device_uid: u32) -> Result<(), DeserializationError> {
61        if device_uid == u32::MAX {
62            return Err(DeserializationError);
63        }
64
65        self.device_uid = device_uid;
66        Ok(())
67    }
68
69    pub fn to_bytes(&self) -> [u8; 6] {
70        let mut buffer = [0u8; 6];
71
72        buffer[..2].copy_from_slice(&self.manufacturer_uid.to_be_bytes());
73        buffer[2..].copy_from_slice(&self.device_uid.to_be_bytes());
74
75        buffer
76    }
77}
78
79impl TryFrom<u64> for UniqueIdentifier {
80    type Error = DeserializationError;
81
82    fn try_from(value: u64) -> Result<Self, Self::Error> {
83        let manufacturer_uid = (value >> u32::BITS) as u16;
84        let device_uid = (value & u32::MAX as u64) as u32;
85
86        if device_uid == u32::MAX {
87            return Err(DeserializationError);
88        }
89
90        Ok(Self {
91            manufacturer_uid,
92            device_uid,
93        })
94    }
95}
96
97impl From<UniqueIdentifier> for u64 {
98    fn from(value: UniqueIdentifier) -> Self {
99        ((value.manufacturer_uid as u64) << u32::BITS) | value.device_uid as u64
100    }
101}
102
103#[derive(Debug, Copy, Clone, Eq, PartialEq)]
104#[cfg_attr(feature = "defmt", derive(defmt::Format))]
105pub enum PackageAddress {
106    /// Broadcast to all devices.
107    Broadcast,
108    /// Broadcast to all devices from a specific manufacturer identified by the manufacturer id
109    /// in the u16.
110    ManufacturerBroadcast(u16),
111    /// Send package to a specific device.
112    Device(UniqueIdentifier),
113}
114
115impl PackageAddress {
116    pub fn from_bytes(buffer: &[u8; 6]) -> Self {
117        let manufacturer_uid = u16::from_be_bytes(buffer[0..2].try_into().unwrap());
118        let device_uid = u32::from_be_bytes(buffer[2..].try_into().unwrap());
119
120        if device_uid == u32::MAX {
121            if manufacturer_uid == u16::MAX {
122                Self::Broadcast
123            } else {
124                Self::ManufacturerBroadcast(manufacturer_uid)
125            }
126        } else {
127            Self::Device(UniqueIdentifier {
128                manufacturer_uid,
129                device_uid,
130            })
131        }
132    }
133
134    pub fn to_bytes(&self) -> [u8; 6] {
135        match self {
136            Self::Broadcast => [0xFFu8; 6],
137            Self::ManufacturerBroadcast(manufacturer_uid) => {
138                let mut buffer = [0xFFu8; 6];
139                buffer[..2].copy_from_slice(&manufacturer_uid.to_be_bytes());
140
141                buffer
142            },
143            Self::Device(uid) => uid.to_bytes(),
144        }
145    }
146
147    pub fn is_broadcast(&self) -> bool {
148        match self {
149            PackageAddress::Broadcast => true,
150            PackageAddress::ManufacturerBroadcast(_) => true,
151            PackageAddress::Device(_) => false,
152        }
153    }
154}
155
156impl TryFrom<u64> for PackageAddress {
157    type Error = DeserializationError;
158
159    fn try_from(value: u64) -> Result<Self, Self::Error> {
160        if value >> 6 > 0 {
161            return Err(DeserializationError);
162        }
163
164        let manufacturer_uid = (value >> u32::BITS) as u16;
165        let device_uid = (value & u32::MAX as u64) as u32;
166
167        if device_uid == u32::MAX {
168            if manufacturer_uid == u16::MAX {
169                return Ok(Self::Broadcast);
170            }
171
172            return Ok(Self::ManufacturerBroadcast(manufacturer_uid));
173        }
174
175        Ok(Self::Device(UniqueIdentifier {
176            manufacturer_uid: 0,
177            device_uid: 0,
178        }))
179    }
180}
181
182impl From<PackageAddress> for u64 {
183    fn from(value: PackageAddress) -> Self {
184        match value {
185            PackageAddress::Broadcast => BROADCAST_UID,
186            PackageAddress::ManufacturerBroadcast(manufacturer_uid) => {
187                ((manufacturer_uid as u64) << u32::BITS) | u32::MAX as u64
188            },
189            PackageAddress::Device(uid) => uid.into(),
190        }
191    }
192}