1use crate::{
2 common::{
3 error::{Error, Unimplemented},
4 helper::decode_unsigned,
5 io::{Reader, Writer},
6 spec::{ErrorClass, ErrorCode},
7 tag::{ApplicationTagNumber, Tag, TagNumber},
8 },
9 network_protocol::{data_link::DataLink, network_pdu::NetworkMessage},
10};
11
12use super::{
13 application_pdu::{ApduType, ApplicationPdu, MaxAdpu, MaxSegments, PduFlags},
14 services::{
15 change_of_value::SubscribeCov,
16 read_property::{ReadProperty, ReadPropertyAck},
17 read_property_multiple::{ReadPropertyMultiple, ReadPropertyMultipleAck},
18 read_range::{ReadRange, ReadRangeAck},
19 write_property::WriteProperty,
20 },
21};
22
23#[derive(Debug, Clone)]
24#[cfg_attr(feature = "defmt", derive(defmt::Format))]
25pub struct ConfirmedRequest<'a> {
26 pub max_segments: MaxSegments, pub max_adpu: MaxAdpu, pub invoke_id: u8, pub sequence_num: u8, pub proposed_window_size: u8, pub service: ConfirmedRequestService<'a>,
32}
33
34impl<'a> ConfirmedRequest<'a> {
35 pub fn new(invoke_id: u8, service: ConfirmedRequestService<'a>) -> Self {
36 Self {
37 max_segments: MaxSegments::_65,
38 max_adpu: MaxAdpu::_1476,
39 invoke_id,
40 sequence_num: 0,
41 proposed_window_size: 0,
42 service,
43 }
44 }
45
46 pub fn encode(&self, writer: &mut Writer) {
47 let max_segments_flag = match self.max_segments {
48 MaxSegments::_0 => 0,
49 _ => PduFlags::SegmentedResponseAccepted as u8,
50 };
51
52 let control = ((ApduType::ConfirmedServiceRequest as u8) << 4) | max_segments_flag;
53 writer.push(control);
54 writer.push(self.max_segments.clone() as u8 | self.max_adpu.clone() as u8);
55 writer.push(self.invoke_id);
56
57 match &self.service {
60 ConfirmedRequestService::ReadProperty(service) => {
61 writer.push(ConfirmedServiceChoice::ReadProperty as u8);
62 service.encode(writer)
63 }
64 ConfirmedRequestService::ReadPropertyMultiple(service) => {
65 writer.push(ConfirmedServiceChoice::ReadPropMultiple as u8);
66 service.encode(writer)
67 }
68 ConfirmedRequestService::SubscribeCov(service) => {
69 writer.push(ConfirmedServiceChoice::SubscribeCov as u8);
70 service.encode(writer)
71 }
72 ConfirmedRequestService::WriteProperty(service) => {
73 writer.push(ConfirmedServiceChoice::WriteProperty as u8);
74 service.encode(writer)
75 }
76 ConfirmedRequestService::ReadRange(service) => {
77 writer.push(ConfirmedServiceChoice::ReadRange as u8);
78 service.encode(writer)
79 }
80 };
81 }
82
83 pub fn decode(reader: &mut Reader, buf: &'a [u8]) -> Result<Self, Error> {
85 let byte0 = reader.read_byte(buf)?;
86 let max_segments: MaxSegments = (byte0 & 0xF0).into();
87 let max_adpu: MaxAdpu = (byte0 & 0x0F).into();
88 let invoke_id = reader.read_byte(buf)?;
89
90 let choice: ConfirmedServiceChoice = reader.read_byte(buf)?.try_into().map_err(|e| {
91 Error::InvalidVariant(("ConfirmedRequest decode ConfirmedServiceChoice", e as u32))
92 })?;
93
94 let service = match choice {
95 ConfirmedServiceChoice::ReadProperty => {
96 let service = ReadProperty::decode(reader, buf)?;
97 ConfirmedRequestService::ReadProperty(service)
98 }
99 ConfirmedServiceChoice::ReadPropMultiple => {
100 let service = ReadPropertyMultiple::decode(reader, buf);
101 ConfirmedRequestService::ReadPropertyMultiple(service)
102 }
103 ConfirmedServiceChoice::ReadRange => {
104 let service = ReadRange::decode(reader, buf)?;
105 ConfirmedRequestService::ReadRange(service)
106 }
107 ConfirmedServiceChoice::WriteProperty => {
108 let service = WriteProperty::decode(reader, buf)?;
109 ConfirmedRequestService::WriteProperty(service)
110 }
111 _ => todo!("Choice not supported: {:?}", choice),
112 };
113
114 Ok(Self {
115 max_segments,
116 max_adpu,
117 sequence_num: 0,
118 proposed_window_size: 0,
119 invoke_id,
120 service,
121 })
122 }
123}
124
125#[derive(Debug, Clone)]
126#[cfg_attr(feature = "defmt", derive(defmt::Format))]
127#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
128#[repr(u8)]
129pub enum ConfirmedServiceChoice {
130 AcknowledgeAlarm = 0,
132 AuditNotification = 32,
133 CovNotification = 1,
134 CovNotificationMultiple = 31,
135 EventNotification = 2,
136 GetAlarmSummary = 3,
137 GetEnrollmentSummary = 4,
138 GetEventInformation = 29,
139 LifeSafetyOperation = 27,
140 SubscribeCov = 5,
141 SubscribeCovProperty = 28,
142 SubscribeCovPropertyMultiple = 30,
143
144 AtomicReadFile = 6,
146 AtomicWriteFile = 7,
147
148 AddListElement = 8,
150 RemoveListElement = 9,
151 CreateObject = 10,
152 DeleteObject = 11,
153 ReadProperty = 12,
154 ReadPropConditional = 13,
155 ReadPropMultiple = 14,
156 ReadRange = 26,
157 WriteProperty = 15,
158 WritePropMultiple = 16,
159 AuditLogQuery = 33,
160
161 DeviceCommunicationControl = 17,
163 PrivateTransfer = 18,
164 TextMessage = 19,
165 ReinitializeDevice = 20,
166
167 VtOpen = 21,
169 VtClose = 22,
170 VtData = 23,
171
172 Authenticate = 24,
174 RequestKey = 25,
175
176 MaxBacnetConfirmedService = 34,
190}
191
192impl TryFrom<u8> for ConfirmedServiceChoice {
193 type Error = u8;
194
195 fn try_from(value: u8) -> Result<Self, u8> {
196 match value {
197 0 => Ok(Self::AcknowledgeAlarm),
198 1 => Ok(Self::CovNotification),
199 2 => Ok(Self::EventNotification),
200 3 => Ok(Self::GetAlarmSummary),
201 4 => Ok(Self::GetEnrollmentSummary),
202 5 => Ok(Self::SubscribeCov),
203 6 => Ok(Self::AtomicReadFile),
204 7 => Ok(Self::AtomicWriteFile),
205 8 => Ok(Self::AddListElement),
206 9 => Ok(Self::RemoveListElement),
207 10 => Ok(Self::CreateObject),
208 11 => Ok(Self::DeleteObject),
209 12 => Ok(Self::ReadProperty),
210 13 => Ok(Self::ReadPropConditional),
211 14 => Ok(Self::ReadPropMultiple),
212 15 => Ok(Self::WriteProperty),
213 16 => Ok(Self::WritePropMultiple),
214 17 => Ok(Self::DeviceCommunicationControl),
215 18 => Ok(Self::PrivateTransfer),
216 19 => Ok(Self::TextMessage),
217 20 => Ok(Self::ReinitializeDevice),
218 21 => Ok(Self::VtOpen),
219 22 => Ok(Self::VtClose),
220 23 => Ok(Self::VtData),
221 24 => Ok(Self::Authenticate),
222 25 => Ok(Self::RequestKey),
223 26 => Ok(Self::ReadRange),
224 27 => Ok(Self::LifeSafetyOperation),
225 28 => Ok(Self::SubscribeCovProperty),
226 29 => Ok(Self::GetEventInformation),
227 30 => Ok(Self::SubscribeCovPropertyMultiple),
228 31 => Ok(Self::CovNotificationMultiple),
229 32 => Ok(Self::AuditNotification),
230 33 => Ok(Self::AuditLogQuery),
231 34 => Ok(Self::MaxBacnetConfirmedService),
232 x => Err(x),
233 }
234 }
235}
236
237#[derive(Debug, Clone)]
238#[cfg_attr(feature = "defmt", derive(defmt::Format))]
239pub struct SimpleAck {
240 pub invoke_id: u8,
241 pub service_choice: ConfirmedServiceChoice,
242}
243
244impl SimpleAck {
245 pub fn encode(&self, writer: &mut Writer) {
246 let control = (ApduType::SimpleAck as u8) << 4;
247 writer.push(control);
248 writer.push(self.invoke_id);
249 writer.push(self.service_choice.clone() as u8);
250 }
251
252 pub fn decode(reader: &mut Reader, buf: &[u8]) -> Result<Self, Error> {
253 let invoke_id = reader.read_byte(buf)?;
254 let service_choice: ConfirmedServiceChoice =
255 reader.read_byte(buf)?.try_into().map_err(|e| {
256 Error::InvalidVariant(("SimpleAck decode ConfirmedServiceChoice", e as u32))
257 })?;
258
259 Ok(Self {
260 invoke_id,
261 service_choice,
262 })
263 }
264}
265
266#[derive(Debug, Clone)]
267#[cfg_attr(feature = "defmt", derive(defmt::Format))]
268pub struct BacnetError {
269 pub invoke_id: u8,
270 pub service_choice: ConfirmedServiceChoice,
271 pub error_class: ErrorClass,
272 pub error_code: ErrorCode,
273}
274
275impl BacnetError {
276 pub fn decode(reader: &mut Reader, buf: &[u8]) -> Result<Self, Error> {
277 let invoke_id = reader.read_byte(buf)?;
278 let service_choice: ConfirmedServiceChoice =
279 reader.read_byte(buf)?.try_into().map_err(|e| {
280 Error::InvalidVariant(("BacnetError decode ConfirmedServiceChoice", e as u32))
281 })?;
282
283 let tag = Tag::decode_expected(
284 reader,
285 buf,
286 TagNumber::Application(ApplicationTagNumber::Enumerated),
287 "BacnetError error class",
288 )?;
289 let value = decode_unsigned(tag.value, reader, buf)? as u32;
290 let error_class =
291 ErrorClass::try_from(value).map_err(|e| Error::InvalidVariant(("ErrorClass", e)))?;
292
293 let tag = Tag::decode_expected(
294 reader,
295 buf,
296 TagNumber::Application(ApplicationTagNumber::Enumerated),
297 "BacnetError error code",
298 )?;
299 let value = decode_unsigned(tag.value, reader, buf)? as u32;
300 let error_code =
301 ErrorCode::try_from(value).map_err(|e| Error::InvalidVariant(("ErrorCode", e)))?;
302
303 Ok(Self {
304 invoke_id,
305 service_choice,
306 error_class,
307 error_code,
308 })
309 }
310}
311
312#[derive(Debug, Clone)]
313#[cfg_attr(feature = "defmt", derive(defmt::Format))]
314pub struct ComplexAck<'a> {
315 pub invoke_id: u8,
316 pub service: ComplexAckService<'a>,
317}
318
319impl<'a> TryFrom<DataLink<'a>> for ComplexAck<'a> {
320 type Error = Error;
321
322 fn try_from(value: DataLink<'a>) -> Result<Self, Self::Error> {
323 match value.npdu {
324 Some(x) => match x.network_message {
325 NetworkMessage::Apdu(ApplicationPdu::ComplexAck(ack)) => Ok(ack),
326 _ => Err(Error::ConvertDataLink(
327 "npdu message is not an apdu complex ack",
328 )),
329 },
330 _ => Err(Error::ConvertDataLink("no npdu defined in message")),
331 }
332 }
333}
334
335impl<'a> ComplexAck<'a> {
336 pub fn encode(&self, writer: &mut Writer) {
337 let control = (ApduType::ComplexAck as u8) << 4;
338 writer.push(control);
339 writer.push(self.invoke_id);
340
341 match &self.service {
342 ComplexAckService::ReadProperty(service) => service.encode(writer),
343 ComplexAckService::ReadPropertyMultiple(service) => service.encode(writer),
344 ComplexAckService::ReadRange(service) => service.encode(writer),
345 }
346 }
347
348 pub fn decode(reader: &mut Reader, buf: &'a [u8]) -> Result<Self, Error> {
349 let invoke_id = reader.read_byte(buf)?;
350 let choice: ConfirmedServiceChoice = reader.read_byte(buf)?.try_into().map_err(|e| {
351 Error::InvalidVariant(("ComplexAck decode ConfirmedServiceChoice", e as u32))
352 })?;
353
354 let service = match choice {
355 ConfirmedServiceChoice::ReadProperty => {
356 let apdu = ReadPropertyAck::decode(reader, buf)?;
357 ComplexAckService::ReadProperty(apdu)
358 }
359 ConfirmedServiceChoice::ReadPropMultiple => {
360 let buf = &buf[reader.index..reader.end];
361 ComplexAckService::ReadPropertyMultiple(ReadPropertyMultipleAck::new_from_buf(buf))
362 }
363 ConfirmedServiceChoice::ReadRange => {
364 let apdu = ReadRangeAck::decode(reader, buf)?;
365 ComplexAckService::ReadRange(apdu)
366 }
367 s => {
368 return Err(Error::Unimplemented(Unimplemented::ConfirmedServiceChoice(
369 s,
370 )))
371 }
372 };
373
374 Ok(Self { invoke_id, service })
375 }
376}
377
378#[derive(Debug, Clone)]
379#[cfg_attr(feature = "defmt", derive(defmt::Format))]
380pub enum ComplexAckService<'a> {
381 ReadProperty(ReadPropertyAck<'a>),
382 ReadPropertyMultiple(ReadPropertyMultipleAck<'a>),
383 ReadRange(ReadRangeAck<'a>),
384 }
386
387#[derive(Debug, Clone)]
388#[cfg_attr(feature = "defmt", derive(defmt::Format))]
389pub enum ConfirmedRequestService<'a> {
390 ReadProperty(ReadProperty),
391 ReadPropertyMultiple(ReadPropertyMultiple<'a>),
392 SubscribeCov(SubscribeCov),
393 WriteProperty(WriteProperty<'a>),
394 ReadRange(ReadRange),
395 }