1#![allow(dead_code)]
2use crate::lib::fmt;
3use crate::lib::ops::{Deref, DerefMut};
4use crate::lib::vec::Vec;
5use num_derive::FromPrimitive;
6use serde::{Deserialize, Serialize};
7use serde_repr::{Deserialize_repr, Serialize_repr};
8
9pub use crate::object::EchonetObject;
10use crate::{de, ser, Error};
11
12#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
23pub struct ElPacket {
24 ehd1: u8,
26 ehd2: u8,
27 transaction_id: u16,
29 pub seoj: EchonetObject,
31 pub deoj: EchonetObject,
33 pub esv: ServiceCode,
35 pub props: Properties,
38}
39
40impl ElPacket {
41 pub fn serialize(&self) -> Result<Vec<u8>, Error> {
43 ser::serialize(&self)
44 }
45
46 pub fn from_bytes(bytes: &[u8]) -> Result<(usize, ElPacket), Error> {
48 de::deserialize(bytes)
49 }
50
51 #[allow(clippy::suspicious_operation_groupings)]
53 pub fn is_response_for(&self, req: &ElPacket) -> bool {
54 self.transaction_id == req.transaction_id && self.seoj == req.deoj
55 }
56
57 pub fn create_response(&self, esv: ServiceCode, props: Properties) -> ElPacket {
65 ElPacketBuilder::new()
66 .transaction_id(self.transaction_id)
67 .seoj(self.deoj)
68 .deoj(self.seoj)
69 .esv(esv)
70 .props(props)
71 .build()
72 }
73}
74
75impl fmt::Display for ElPacket {
76 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
77 writeln!(f, "EHD: {:02X}{:02X}", self.ehd1, self.ehd2)?;
78 writeln!(f, "TID: {}", self.transaction_id)?;
79 writeln!(f, "SEOJ: {}", self.seoj)?;
80 writeln!(f, "DEOJ: {}", self.deoj)?;
81 writeln!(f, "{}", self.esv)?;
82 write!(f, "{}", self.props)
83 }
84}
85
86#[derive(Debug, PartialEq, Eq, Clone, Copy, FromPrimitive, Serialize_repr, Deserialize_repr)]
89#[repr(u8)]
90pub enum ServiceCode {
91 SetISNA = 0x50,
93 SetCSNA = 0x51,
95 GetSNA = 0x52,
97 InfSNA = 0x53,
99 SetGetSNA = 0x5E,
101 SetI = 0x60,
103 SetC = 0x61,
105 Get = 0x62,
107 InfReq = 0x63,
109 SetGet = 0x6E,
111 SetRes = 0x71,
113 GetRes = 0x72,
115 Inf = 0x73,
117 InfC = 0x74,
119 InfCRes = 0x7A,
121 SetGetRes = 0x7E,
123}
124
125impl fmt::Display for ServiceCode {
126 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
127 write!(f, "ESV: {:02X} ", *self as u8)?;
128 let esv = match self {
129 ServiceCode::SetISNA => "SetISNA",
130 ServiceCode::SetCSNA => "SetCSNA",
131 ServiceCode::GetSNA => "GetSNA",
132 ServiceCode::InfSNA => "InfSNA",
133 ServiceCode::SetGetSNA => "SetGetSNA",
134 ServiceCode::SetI => "SetI",
135 ServiceCode::SetC => "SetC",
136 ServiceCode::Get => "Get",
137 ServiceCode::InfReq => "InfReq",
138 ServiceCode::SetGet => "SetGet",
139 ServiceCode::SetRes => "SetRes",
140 ServiceCode::GetRes => "GetRes",
141 ServiceCode::Inf => "Inf",
142 ServiceCode::InfC => "InfC",
143 ServiceCode::InfCRes => "InfCRes",
144 ServiceCode::SetGetRes => "SetGetRes",
145 };
146 write!(f, "({esv})")
147 }
148}
149
150#[derive(PartialEq, Eq, Default, Serialize, Deserialize)]
152pub struct Properties(Vec<Property>);
153impl Properties {
154 pub fn num(&self) -> usize {
155 self.0.len()
156 }
157
158 pub fn get(&self, index: usize) -> Option<&Property> {
159 if index < self.num() {
160 Some(&self.0[index])
161 } else {
162 None
163 }
164 }
165
166 pub fn iter(&self) -> core::slice::Iter<Property> {
167 self.0.iter()
168 }
169}
170
171impl core::iter::IntoIterator for Properties {
172 type Item = Property;
173 type IntoIter = crate::lib::vec::IntoIter<Property>;
174 fn into_iter(self) -> Self::IntoIter {
175 self.0.into_iter()
176 }
177}
178
179impl Deref for Properties {
180 type Target = Vec<Property>;
181
182 fn deref(&self) -> &Self::Target {
183 &self.0
184 }
185}
186
187impl DerefMut for Properties {
188 fn deref_mut(&mut self) -> &mut Self::Target {
189 &mut self.0
190 }
191}
192
193impl From<Vec<Property>> for Properties {
195 fn from(props: Vec<Property>) -> Self {
196 Self(props)
197 }
198}
199
200impl fmt::Debug for Properties {
201 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
202 writeln!(f, "OPC: {}", self.0.len())?;
203 for prop in self.0.iter() {
204 write!(f, "{prop:?}")?;
205 }
206 Ok(())
207 }
208}
209
210impl fmt::Display for Properties {
211 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
212 for prop in self.0.iter() {
213 writeln!(f, "{prop}")?;
214 }
215 Ok(())
216 }
217}
218
219impl Clone for Properties {
220 fn clone(&self) -> Self {
221 Self(self.0.to_vec())
222 }
223}
224
225#[derive(Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
227pub struct Property {
228 pub epc: u8,
229 pub edt: Edt,
230}
231
232impl fmt::Display for Property {
233 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
234 write!(f, "{:02X}: ", self.epc)?;
235 write!(f, "{}", self.edt)?;
236 Ok(())
237 }
238}
239
240impl fmt::Debug for Property {
241 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
242 writeln!(f, "EPC: {:02X}", self.epc)?;
243 writeln!(f, "{:?}", self.edt)?;
244 Ok(())
245 }
246}
247
248#[derive(PartialEq, Eq, Default, Serialize, Deserialize)]
253pub struct Edt(Vec<u8>);
254
255impl Edt {
256 pub fn new(value: Vec<u8>) -> Edt {
257 Edt(value)
258 }
259}
260
261impl Deref for Edt {
262 type Target = [u8];
263 fn deref(&self) -> &Self::Target {
264 &self.0
265 }
266}
267
268impl Clone for Edt {
269 fn clone(&self) -> Self {
270 Self(self.0.to_vec())
271 }
272}
273
274impl fmt::Display for Edt {
275 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
276 for byte in self.0.iter() {
277 write!(f, "{byte:02X} ")?;
278 }
279 Ok(())
280 }
281}
282
283impl fmt::Debug for Edt {
284 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
285 writeln!(f, "PDC: {}", self.0.len())?;
286 write!(f, "EDT: ")?;
287 for byte in self.0.iter() {
288 write!(f, "{byte:02X} ")?;
289 }
290 Ok(())
291 }
292}
293
294#[derive(Debug)]
311pub struct ElPacketBuilder {
312 transaction_id: u16,
313 seoj: EchonetObject,
314 deoj: EchonetObject,
315 esv: Option<ServiceCode>,
316 props: Properties,
317}
318
319impl Default for ElPacketBuilder {
320 fn default() -> Self {
321 Self::new()
322 }
323}
324
325impl ElPacketBuilder {
326 pub fn new() -> Self {
327 Self {
328 transaction_id: 0,
329 seoj: Default::default(),
330 deoj: Default::default(),
331 esv: None,
332 props: Default::default(),
333 }
334 }
335
336 pub fn transaction_id(mut self, tid: u16) -> Self {
337 self.transaction_id = tid;
338 self
339 }
340
341 pub fn seoj<T>(mut self, seoj: T) -> Self
342 where
343 T: Into<EchonetObject>,
344 {
345 self.seoj = seoj.into();
346 self
347 }
348
349 pub fn deoj<T>(mut self, deoj: T) -> Self
350 where
351 T: Into<EchonetObject>,
352 {
353 self.deoj = deoj.into();
354 self
355 }
356
357 pub fn esv(mut self, esv: ServiceCode) -> Self {
358 self.esv = Some(esv);
359 self
360 }
361
362 pub fn props(mut self, props: Properties) -> Self {
363 self.props = props;
364 self
365 }
366
367 pub fn build(self) -> ElPacket {
368 ElPacket {
369 ehd1: 0x10,
370 ehd2: 0x81,
371 transaction_id: self.transaction_id,
372 seoj: self.seoj,
373 deoj: self.deoj,
374 esv: self.esv.unwrap(), props: self.props,
376 }
377 }
378}
379
380#[macro_export]
389macro_rules! prop {
390 ( $epc:expr, [ $( $edt:expr ),* ] ) => {
391 {
392 let mut bytes: Vec<u8> = Vec::new();
393 $(
394 bytes.push($edt);
395 )*
396 Property{ epc: $epc, edt: Edt::new(bytes) }
397 }
398 };
399}
400
401#[macro_export(local_inner_macros)]
410macro_rules! props {
411 ( $( [ $epc:expr, [ $( $edt:expr ),* ] ] ),* ) => {
412 {
413 let mut props: Vec<Property> = Vec::new();
414 $(
415 props.push( $crate::prop!($epc, [ $( $edt ),* ] ) );
416 )*
417 Properties::from(props)
418 }
419 };
420}
421
422#[macro_export]
431macro_rules! bulk_read {
432 ( $( $epc:expr ),* ) => {
433 {
434 let mut props: Vec<Property> = Vec::new();
435 $(
436 props.push( $crate::prop!($epc, [] ) );
437 )*
438 Properties::from(props)
439 }
440 };
441}
442
443#[cfg(test)]
444mod test {
445 use super::*;
446 use crate::de;
447
448 #[test]
449 fn serialize() {
450 let props = props!([0x80, [0x02]]);
451 let result = ElPacketBuilder::new()
452 .transaction_id(1)
453 .esv(ServiceCode::Get)
454 .seoj([0xefu8, 0xffu8, 0x01u8])
455 .deoj([0x03u8, 0x08u8, 0x01u8])
456 .props(props)
457 .build()
458 .serialize()
459 .unwrap();
460 assert_eq!(
461 vec![0x10, 0x81, 0, 1, 0xef, 0xff, 0x01, 0x03, 0x08, 0x01, 0x62, 1, 0x80, 0x01, 0x02],
462 result
463 );
464 }
465
466 #[test]
467 fn deserialize() {
468 let input: Vec<u8> = vec![
469 0x10, 0x81, 0, 1, 0xef, 0xff, 0x01, 0x03, 0x08, 0x01, 0x62, 1, 0x80, 0x01, 0x02,
470 ];
471 let (consumed, decoded): (usize, ElPacket) = ElPacket::from_bytes(&input).unwrap();
472
473 let prop = Property {
474 epc: 0x80,
475 edt: Edt(vec![0x02]),
476 };
477 let expect = ElPacketBuilder::new()
478 .transaction_id(1)
479 .esv(ServiceCode::Get)
480 .seoj([0xef, 0xff, 0x01])
481 .deoj([0x03, 0x08, 0x01])
482 .props(Properties(vec![prop]))
483 .build();
484
485 assert_eq!(15, consumed);
486 assert_eq!(expect, decoded);
487 }
488
489 #[test]
490 fn deserialize_tid() {
491 let input = [0u8, 1u8];
492 let (_, decoded): (usize, u16) = de::deserialize(&input).unwrap();
493
494 assert_eq!(1, decoded);
495 }
496
497 #[test]
498 fn deserialize_esv() {
499 let input = [0x62u8];
500 let (_, decoded): (usize, ServiceCode) = de::deserialize(&input).unwrap();
501
502 assert_eq!(ServiceCode::Get, decoded);
503 }
504
505 #[test]
506 fn deserialize_eoj() {
507 let input = [0xefu8, 0xffu8, 0x01u8];
508 let (_, decoded): (usize, EchonetObject) = de::deserialize(&input).unwrap();
509
510 assert_eq!(EchonetObject::from([0xefu8, 0xffu8, 0x01u8]), decoded);
511 }
512
513 #[test]
514 fn deserialize_edt() {
515 let input: [u8; 2] = [0x01, 0x01];
516 let (_, decoded): (usize, Edt) = de::deserialize(&input).unwrap();
517
518 let expect = Edt(vec![0x01u8]);
519 assert_eq!(expect, decoded);
520 }
521
522 #[test]
523 fn deserialize_empty_edt() {
524 let input: [u8; 1] = [0u8];
525 let (_, decoded): (usize, Edt) = de::deserialize(&input).unwrap();
526
527 let expect = Edt(vec![]);
528 assert_eq!(expect, decoded);
529 }
530
531 #[test]
532 fn deserialize_props() {
533 let input: Vec<u8> = vec![1, 0x80, 0x01, 0x02];
534 let (_, decoded): (usize, Properties) = de::deserialize(&input).unwrap();
535
536 let expect = Properties(vec![Property {
537 epc: 0x80,
538 edt: Edt(vec![0x02]),
539 }]);
540 assert_eq!(expect, decoded);
541 }
542
543 #[test]
544 fn iter_properties() {
545 let props = props!([0x80, [0x02]]);
546 let expect = prop!(0x80, [0x02]);
547 assert_eq!(1usize, props.num());
548 for prop in props.iter() {
549 assert_eq!(expect, *prop);
550 }
551 }
552}