open_dis_rust/
radio_communications.rs

1//     open-dis-rust - Rust implementation of the IEEE 1278.1-2012 Distributed Interactive
2//                     Simulation (DIS) application protocol
3//     Copyright (C) 2025 Cameron Howell
4//
5//     Licensed under the BSD 2-Clause License
6
7//! The Radio Communications protocol family
8
9use crate::{
10    common::{
11        GenericHeader, SerializedLength,
12        data_types::{
13            EntityCoordinateVector, WorldCoordinate, antenna_pattern::AntennaPattern,
14            entity_id::EntityId,
15            intercom_communications_parameters::IntercomCommunicationsParameters,
16            modulation_parameters::ModulationParameters, modulation_type::ModulationType,
17            radio_entity_type::RadioEntityType,
18            variable_transmitter_parameters::VariableTransmitterParameters,
19        },
20        enums::{
21            IntercomControlCommand, IntercomControlControlType, IntercomControlTransmitLineState,
22            PduType, ProtocolFamily, ReceiverReceiverState, SignalTDLType,
23            TransmitterAntennaPatternType, TransmitterCryptoSystem, TransmitterInputSource,
24            TransmitterTransmitState,
25        },
26        pdu::Pdu,
27        pdu_header::PduHeader,
28    },
29    define_pdu,
30};
31
32define_pdu! {
33    #[derive(Debug)]
34    /// Implemented according to IEEE 1278.1-2012 §7.7.2
35    pub struct TransmitterPdu {
36        header: PduHeader,
37        pdu_type: PduType::Transmitter,
38        protocol_family: ProtocolFamily::RadioCommunications,
39        fields: {
40            pub entity_id: EntityId,
41            pub radio_id: u16,
42            pub radio_entity_type: RadioEntityType,
43            pub transmit_state: TransmitterTransmitState,
44            pub input_source: TransmitterInputSource,
45            pub number_of_variable_transmitter_parameters_records: u16,
46            pub antenna_location: WorldCoordinate,
47            pub relative_antenna_location: EntityCoordinateVector,
48            pub antenna_pattern_type: TransmitterAntennaPatternType,
49            pub antenna_pattern_length: u16,
50            pub frequency: u64,
51            pub transmit_frequency_bandwidth: f32,
52            pub power: f32,
53            pub modulation_type: ModulationType,
54            pub crypto_system: TransmitterCryptoSystem,
55            pub crypto_key_id: u16,
56            pub modulation_parameter_length: u8,
57            padding: u8,
58            padding2: u16,
59            #[len = modulation_parameter_length]
60            pub modulation_parameters: Option<ModulationParameters>,
61            pub antenna_pattern: Option<AntennaPattern>,
62            pub variable_transmitter_parameters: Vec<VariableTransmitterParameters>,
63        }
64    }
65}
66
67define_pdu! {
68    #[derive(Debug)]
69    /// Implemented according to IEEE 1278.1-2012 §7.7.3
70    pub struct SignalPdu {
71        header: PduHeader,
72        pdu_type: PduType::Signal,
73        protocol_family: ProtocolFamily::RadioCommunications,
74        fields: {
75            pub entity_id: EntityId,
76            pub radio_id: u16,
77            pub encoding_scheme: u16,
78            pub tdl_type: SignalTDLType,
79            pub sample_rate: u32,
80            pub data_length: u16,
81            pub samples: u16,
82            pub data: Vec<u8>,
83        }
84    }
85}
86
87define_pdu! {
88    #[derive(Debug)]
89    /// Implemented according to IEEE 1278.1-2012 §7.7.4
90    pub struct ReceiverPdu {
91        header: PduHeader,
92        pdu_type: PduType::Receiver,
93        protocol_family: ProtocolFamily::RadioCommunications,
94        fields: {
95            pub entity_id: EntityId,
96            pub radio_id: u16,
97            pub receiver_state: ReceiverReceiverState,
98            padding: u16,
99            pub received_power: f32,
100            pub transmitter_radio_reference_id: EntityId,
101            pub transmitter_radio_id: u16,
102        }
103    }
104}
105
106define_pdu! {
107    #[derive(Debug)]
108    /// Implemented according to IEEE 1278.1-2012 §7.7.5
109    pub struct IntercomSignalPdu {
110        header: PduHeader,
111        pdu_type: PduType::IntercomSignal,
112        protocol_family: ProtocolFamily::RadioCommunications,
113        fields: {
114            pub intercom_reference_id: EntityId,
115            pub intercom_number: u16,
116            pub encoding_scheme: u16,
117            pub tdl_type: SignalTDLType,
118            pub sample_rate: u32,
119            pub data_length: u16,
120            pub samples: u16,
121            pub data: Vec<u8>,
122        }
123    }
124}
125
126define_pdu! {
127    #[derive(Debug)]
128    /// Implemented according to IEEE 1278.1-2012 §7.7.6
129    pub struct IntercomControlPdu {
130        header: PduHeader,
131        pdu_type: PduType::IntercomControl,
132        protocol_family: ProtocolFamily::RadioCommunications,
133        fields: {
134            pub control_type: IntercomControlControlType,
135            pub communications_channel_type: u8,
136            pub source_intercom_reference_id: EntityId,
137            pub source_intercom_number: u16,
138            pub source_line_id: u8,
139            pub transmit_priority: u8,
140            pub transmit_line_state: IntercomControlTransmitLineState,
141            pub command: IntercomControlCommand,
142            pub master_intercom_reference_id: EntityId,
143            pub master_intercom_number: u16,
144            pub master_channel_id: u16,
145            pub intercom_parameters_length: u32,
146            pub intercom_parameters: Vec<IntercomCommunicationsParameters>,
147        }
148    }
149}
150
151#[cfg(test)]
152mod tests {
153    use super::*;
154    use crate::common::{constants::BITS_PER_BYTE, pdu::Pdu};
155    use bytes::BytesMut;
156
157    mod transmitter_pdu_tests {
158        use super::*;
159
160        #[test]
161        fn cast_to_any() {
162            let pdu = TransmitterPdu::new();
163            let any_pdu = pdu.as_any();
164
165            assert!(any_pdu.is::<TransmitterPdu>());
166        }
167
168        #[test]
169        fn serialize_then_deserialize() {
170            let mut pdu = TransmitterPdu::new();
171            let mut serialize_buf = BytesMut::new();
172            let _ = pdu.serialize(&mut serialize_buf);
173
174            let mut deserialize_buf = serialize_buf.freeze();
175            let new_pdu = TransmitterPdu::deserialize(&mut deserialize_buf).unwrap_or_default();
176            assert_eq!(new_pdu.header, pdu.header);
177        }
178
179        #[test]
180        fn check_default_pdu_length() {
181            const DEFAULT_LENGTH: u16 = 832 / BITS_PER_BYTE;
182            let pdu = TransmitterPdu::new();
183            assert_eq!(pdu.header().length, DEFAULT_LENGTH);
184        }
185    }
186
187    mod signal_pdu_tests {
188        use super::*;
189
190        #[test]
191        fn cast_to_any() {
192            let pdu = SignalPdu::new();
193            let any_pdu = pdu.as_any();
194
195            assert!(any_pdu.is::<SignalPdu>());
196        }
197
198        #[test]
199        fn serialize_then_deserialize() {
200            let mut pdu = SignalPdu::new();
201            let mut serialize_buf = BytesMut::new();
202            let _ = pdu.serialize(&mut serialize_buf);
203
204            let mut deserialize_buf = serialize_buf.freeze();
205            let new_pdu = SignalPdu::deserialize(&mut deserialize_buf).unwrap_or_default();
206            assert_eq!(new_pdu.header, pdu.header);
207        }
208
209        #[test]
210        fn check_default_pdu_length() {
211            const DEFAULT_LENGTH: u16 = 256 / BITS_PER_BYTE;
212            let pdu = SignalPdu::new();
213            assert_eq!(pdu.header().length, DEFAULT_LENGTH);
214        }
215    }
216
217    mod receiver_pdu_tests {
218        use super::*;
219
220        #[test]
221        fn cast_to_any() {
222            let pdu = ReceiverPdu::new();
223            let any_pdu = pdu.as_any();
224
225            assert!(any_pdu.is::<ReceiverPdu>());
226        }
227
228        #[test]
229        fn serialize_then_deserialize() {
230            let mut pdu = ReceiverPdu::new();
231            let mut serialize_buf = BytesMut::new();
232            let _ = pdu.serialize(&mut serialize_buf);
233
234            let mut deserialize_buf = serialize_buf.freeze();
235            let new_pdu = ReceiverPdu::deserialize(&mut deserialize_buf).unwrap_or_default();
236            assert_eq!(new_pdu.header, pdu.header);
237        }
238
239        #[test]
240        fn check_default_pdu_length() {
241            const DEFAULT_LENGTH: u16 = 288 / BITS_PER_BYTE;
242            let pdu = ReceiverPdu::new();
243            assert_eq!(pdu.header().length, DEFAULT_LENGTH);
244        }
245    }
246
247    mod intercom_signal_pdu_tests {
248        use super::*;
249
250        #[test]
251        fn cast_to_any() {
252            let pdu = IntercomSignalPdu::new();
253            let any_pdu = pdu.as_any();
254
255            assert!(any_pdu.is::<IntercomSignalPdu>());
256        }
257
258        #[test]
259        fn serialize_then_deserialize() {
260            let mut pdu = IntercomSignalPdu::new();
261            let mut serialize_buf = BytesMut::new();
262            let _ = pdu.serialize(&mut serialize_buf);
263
264            let mut deserialize_buf = serialize_buf.freeze();
265            let new_pdu = IntercomSignalPdu::deserialize(&mut deserialize_buf).unwrap_or_default();
266            assert_eq!(new_pdu.header, pdu.header);
267        }
268
269        #[test]
270        fn check_default_pdu_length() {
271            const DEFAULT_LENGTH: u16 = 256 / BITS_PER_BYTE;
272            let pdu = IntercomSignalPdu::new();
273            assert_eq!(pdu.header().length, DEFAULT_LENGTH);
274        }
275    }
276
277    mod intercom_control_pdu_tests {
278        use super::*;
279
280        #[test]
281        fn cast_to_any() {
282            let pdu = IntercomControlPdu::new();
283            let any_pdu = pdu.as_any();
284
285            assert!(any_pdu.is::<IntercomControlPdu>());
286        }
287
288        #[test]
289        fn serialize_then_deserialize() {
290            let mut pdu = IntercomControlPdu::new();
291            let mut serialize_buf = BytesMut::new();
292            let _ = pdu.serialize(&mut serialize_buf);
293
294            let mut deserialize_buf = serialize_buf.freeze();
295            let new_pdu = IntercomControlPdu::deserialize(&mut deserialize_buf).unwrap_or_default();
296            assert_eq!(new_pdu.header, pdu.header);
297        }
298
299        #[test]
300        fn check_default_pdu_length() {
301            const DEFAULT_LENGTH: u16 = 320 / BITS_PER_BYTE;
302            let pdu = IntercomControlPdu::new();
303            assert_eq!(pdu.header().length, DEFAULT_LENGTH);
304        }
305    }
306}