dmx_rdm/
rdm_types.rs

1use crate::consts::{
2    RDM_DEVICE_INFO_SIZE, RDM_MAX_STATUS_PACKAGES_PER_REQUEST,
3    RDM_MAX_SUPPORTED_PARAMETERS_PER_REQUEST, RDM_STATUS_MESSAGE_SIZE,
4};
5use crate::layouts::{rdm_device_info_layout, rdm_status_message_layout};
6use crate::types::DataPack;
7use crate::unique_identifier::{PackageAddress, UniqueIdentifier};
8use modular_bitfield::bitfield;
9use modular_bitfield::prelude::B12;
10
11#[derive(Debug)]
12#[cfg_attr(feature = "defmt", derive(defmt::Format))]
13pub struct DeserializationError;
14
15impl core::fmt::Display for DeserializationError {
16    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
17        write!(f, "There was a deserialization error.")
18    }
19}
20
21#[cfg(feature = "std")]
22impl std::error::Error for DeserializationError {}
23
24#[derive(Debug, Clone)]
25#[cfg_attr(feature = "defmt", derive(defmt::Format))]
26pub enum DmxStartAddress {
27    /// The requested device has a dmx footprint of 0.
28    NoAddress,
29    /// The requested device does allocate dmx addresses.
30    Address(u16),
31}
32
33impl DmxStartAddress {
34    pub fn as_u16(&self) -> u16 {
35        match self {
36            DmxStartAddress::Address(address) => *address,
37            DmxStartAddress::NoAddress => 0xFFFF,
38        }
39    }
40
41    pub fn deserialize(data: &[u8]) -> Result<Self, DeserializationError> {
42        let start_address = u16::from_be_bytes(data.try_into().map_err(|_| DeserializationError)?);
43
44        start_address.try_into().map_err(|_| DeserializationError)
45    }
46
47    pub fn serialize(&self) -> DataPack {
48        DataPack::from_slice(&self.as_u16().to_be_bytes()).unwrap()
49    }
50}
51
52impl TryFrom<u16> for DmxStartAddress {
53    type Error = DeserializationError;
54
55    fn try_from(start_address: u16) -> Result<Self, Self::Error> {
56        if start_address == 0xFFFF {
57            return Ok(Self::NoAddress);
58        }
59
60        if !(1..=512).contains(&start_address) {
61            return Err(DeserializationError);
62        }
63
64        Ok(Self::Address(start_address))
65    }
66}
67
68/// Response to discovery mute/unmute requests.
69#[derive(Debug, Eq, PartialEq)]
70pub struct DiscoveryMuteResponse {
71    /// The responder is a proxy device.
72    pub managed_proxy: bool,
73    /// The responder supports sub devices.
74    pub sub_device: bool,
75    /// The responder is not operational before receiving a firmware update.
76    pub boot_loader: bool,
77    /// A proxy device has responded on behalf of another device.
78    pub proxy_device: bool,
79    /// Included if the responding device contains multiple responder ports.
80    /// It is the UUID to the primary port of the device.
81    pub binding_uid: Option<UniqueIdentifier>,
82}
83
84#[bitfield]
85struct DiscControlField {
86    /// The responder is a proxy device.
87    pub managed_proxy: bool,
88    /// The responder supports sub devices.
89    pub sub_device: bool,
90    /// The responder is not operational before receiving a firmware update.
91    pub boot_loader: bool,
92    /// A proxy device has responded on behalf of another device.
93    pub proxy_device: bool,
94    #[skip]
95    reserved: B12,
96}
97
98impl DiscoveryMuteResponse {
99    pub fn deserialize(data: &[u8]) -> Result<Self, DeserializationError> {
100        if data.len() < 2 {
101            return Err(DeserializationError);
102        }
103
104        let control_field = DiscControlField::from_bytes((&data[0..2]).try_into().unwrap());
105        let mut discovery_mute_response = Self {
106            managed_proxy: control_field.managed_proxy(),
107            sub_device: control_field.sub_device(),
108            boot_loader: control_field.boot_loader(),
109            proxy_device: control_field.proxy_device(),
110            binding_uid: None,
111        };
112
113        if data.len() == 8 {
114            let binding_uuid = match PackageAddress::from_bytes((&data[2..8]).try_into().unwrap()) {
115                PackageAddress::Device(uid) => uid,
116                _ => return Err(DeserializationError),
117            };
118
119            discovery_mute_response.binding_uid = Some(binding_uuid);
120        }
121
122        Ok(discovery_mute_response)
123    }
124
125    pub fn serialize(&self) -> DataPack {
126        let mut data_pack = DataPack::new();
127        let disc_control_field = DiscControlField::new()
128            .with_managed_proxy(self.managed_proxy)
129            .with_sub_device(self.sub_device)
130            .with_boot_loader(self.boot_loader)
131            .with_proxy_device(self.proxy_device);
132
133        data_pack
134            .extend_from_slice(&disc_control_field.into_bytes())
135            .unwrap();
136
137        match self.binding_uid {
138            None => {},
139            Some(uid) => data_pack.extend_from_slice(&uid.to_bytes()).unwrap(),
140        }
141
142        data_pack
143    }
144}
145
146#[derive(Debug, Copy, Clone, Eq, PartialEq)]
147#[cfg_attr(feature = "defmt", derive(defmt::Format))]
148#[repr(u8)]
149pub enum StatusType {
150    StatusNone = 0x00,
151    StatusGetLastMessage = 0x01,
152    StatusAdvisory = 0x02,
153    StatusWarning = 0x03,
154    StatusError = 0x04,
155    StatusAdvisoryCleared = 0x12,
156    StatusWarningCleared = 0x13,
157    StatusErrorCleared = 0x14,
158}
159
160impl StatusType {
161    pub fn deserialize(data: &[u8]) -> Result<Self, DeserializationError> {
162        if data.len() != 1 {
163            return Err(DeserializationError);
164        }
165
166        let status_type_requested: StatusType = match data[0].try_into() {
167            Ok(status_type) => status_type,
168            Err(_) => {
169                return Err(DeserializationError);
170            },
171        };
172
173        Ok(status_type_requested)
174    }
175}
176
177impl TryFrom<u8> for StatusType {
178    type Error = DeserializationError;
179
180    fn try_from(value: u8) -> Result<Self, Self::Error> {
181        Ok(match value {
182            0x00 => Self::StatusNone,
183            0x01 => Self::StatusGetLastMessage,
184            0x02 => Self::StatusAdvisory,
185            0x03 => Self::StatusWarning,
186            0x04 => Self::StatusError,
187            0x12 => Self::StatusAdvisoryCleared,
188            0x13 => Self::StatusWarningCleared,
189            0x14 => Self::StatusWarningCleared,
190            _ => return Err(DeserializationError),
191        })
192    }
193}
194
195#[derive(Debug, Copy, Clone)]
196#[cfg_attr(feature = "defmt", derive(defmt::Format))]
197pub struct StatusMessage {
198    pub sub_device_id: u16,
199    pub status_type: StatusType,
200    // we should add proper deserialization
201    pub status_message_id: u16,
202    pub data_value_1: u16,
203    pub data_value_2: u16,
204}
205
206impl StatusMessage {
207    pub fn deserialize(buffer: &[u8]) -> Result<Self, DeserializationError> {
208        let status_message_view = rdm_status_message_layout::View::new(buffer);
209
210        Ok(Self {
211            sub_device_id: status_message_view.sub_device_id().read(),
212            status_type: status_message_view.status_type().read().try_into()?,
213            status_message_id: status_message_view.status_message_id().read(),
214            data_value_1: status_message_view.data_value_1().read(),
215            data_value_2: status_message_view.data_value_2().read(),
216        })
217    }
218
219    pub fn serialize(&self) -> [u8; RDM_STATUS_MESSAGE_SIZE] {
220        let mut resp_buffer = [0u8; RDM_STATUS_MESSAGE_SIZE];
221        let mut status_message_view = rdm_status_message_layout::View::new(&mut resp_buffer);
222
223        status_message_view
224            .sub_device_id_mut()
225            .write(self.sub_device_id);
226        status_message_view
227            .status_type_mut()
228            .write(self.status_type as u8);
229        status_message_view
230            .status_message_id_mut()
231            .write(self.status_message_id);
232        status_message_view
233            .data_value_1_mut()
234            .write(self.data_value_1);
235        status_message_view
236            .data_value_2_mut()
237            .write(self.data_value_2);
238
239        resp_buffer
240    }
241}
242
243pub type StatusMessages = heapless::Vec<StatusMessage, RDM_MAX_STATUS_PACKAGES_PER_REQUEST>;
244pub type SupportedParameters = heapless::Vec<u16, RDM_MAX_SUPPORTED_PARAMETERS_PER_REQUEST>;
245
246#[derive(Debug, Clone)]
247#[cfg_attr(feature = "defmt", derive(defmt::Format))]
248pub struct DeviceInfo {
249    pub device_model_id: u16,
250    pub product_category: u16,
251    pub software_version: u32,
252    pub dmx_footprint: u16,
253    pub dmx_personality: u16,
254    pub dmx_start_address: DmxStartAddress,
255    pub sub_device_count: u16,
256    pub sensor_count: u8,
257}
258
259impl DeviceInfo {
260    pub fn deserialize(buffer: &[u8]) -> Result<Self, DeserializationError> {
261        if buffer.len() != rdm_device_info_layout::SIZE.unwrap() {
262            return Err(DeserializationError);
263        }
264
265        let device_info_view = rdm_device_info_layout::View::new(buffer);
266        Ok(DeviceInfo {
267            device_model_id: device_info_view.device_model_id().read(),
268            product_category: device_info_view.product_category().read(),
269            software_version: device_info_view.software_version_id().read(),
270            dmx_footprint: device_info_view.dmx_footprint().read(),
271            dmx_personality: device_info_view.dmx_personality().read(),
272            dmx_start_address: device_info_view.dmx_start_address().read().try_into()?,
273            sub_device_count: device_info_view.sub_device_count().read(),
274            sensor_count: device_info_view.sensor_count().read(),
275        })
276    }
277
278    pub fn serialize(&self) -> DataPack {
279        let mut resp_buffer = [0u8; RDM_DEVICE_INFO_SIZE];
280        let mut device_info_view = rdm_device_info_layout::View::new(&mut resp_buffer);
281
282        device_info_view.protocol_version_mut().write(0x01_00);
283        device_info_view
284            .device_model_id_mut()
285            .write(self.device_model_id);
286        device_info_view
287            .product_category_mut()
288            .write(self.product_category);
289        device_info_view
290            .software_version_id_mut()
291            .write(self.software_version);
292        device_info_view
293            .dmx_footprint_mut()
294            .write(self.dmx_footprint);
295        device_info_view
296            .dmx_personality_mut()
297            .write(self.dmx_personality);
298        device_info_view
299            .dmx_start_address_mut()
300            .write(self.dmx_start_address.as_u16());
301        device_info_view
302            .sub_device_count_mut()
303            .write(self.sub_device_count);
304        device_info_view.sensor_count_mut().write(self.sensor_count);
305
306        DataPack::from_slice(&resp_buffer).unwrap()
307    }
308}
309
310/// Returned by parameter packages where the response might not fit into one package.
311pub enum OverflowMessageResp<T> {
312    /// Has received the complete message.
313    Complete(T),
314    /// Has not received the complete message.
315    /// Request the same pid to get the next part until you receive [OverflowMessageResp::Complete].
316    Incomplete(T),
317}