1use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
14#[repr(u8)]
15pub enum BatApprovedChemistry {
16 Unspecified = 0,
18 Alkaline = 1,
20 Lithiumcarbonfluoride = 2,
22 Lithiumchromiumoxide = 3,
24 Lithiumcopperoxide = 4,
26 Lithiumirondisulfide = 5,
28 Lithiummanganesedioxide = 6,
30 Lithiumthionylchloride = 7,
32 Magnesium = 8,
34 Mercuryoxide = 9,
36 Nickeloxyhydride = 10,
38 Silveroxide = 11,
40 Zincair = 12,
42 Zinccarbon = 13,
44 Zincchloride = 14,
46 Zincmanganesedioxide = 15,
48 Leadacid = 16,
50 Lithiumcobaltoxide = 17,
52 Lithiumion = 18,
54 Lithiumionpolymer = 19,
56 Lithiumironphosphate = 20,
58 Lithiumsulfur = 21,
60 Lithiumtitanate = 22,
62 Nickelcadmium = 23,
64 Nickelhydrogen = 24,
66 Nickeliron = 25,
68 Nickelmetalhydride = 26,
70 Nickelzinc = 27,
72 Silverzinc = 28,
74 Sodiumion = 29,
76 Sodiumsulfur = 30,
78 Zincbromide = 31,
80 Zinccerium = 32,
82}
83
84impl BatApprovedChemistry {
85 pub fn from_u8(value: u8) -> Option<Self> {
87 match value {
88 0 => Some(BatApprovedChemistry::Unspecified),
89 1 => Some(BatApprovedChemistry::Alkaline),
90 2 => Some(BatApprovedChemistry::Lithiumcarbonfluoride),
91 3 => Some(BatApprovedChemistry::Lithiumchromiumoxide),
92 4 => Some(BatApprovedChemistry::Lithiumcopperoxide),
93 5 => Some(BatApprovedChemistry::Lithiumirondisulfide),
94 6 => Some(BatApprovedChemistry::Lithiummanganesedioxide),
95 7 => Some(BatApprovedChemistry::Lithiumthionylchloride),
96 8 => Some(BatApprovedChemistry::Magnesium),
97 9 => Some(BatApprovedChemistry::Mercuryoxide),
98 10 => Some(BatApprovedChemistry::Nickeloxyhydride),
99 11 => Some(BatApprovedChemistry::Silveroxide),
100 12 => Some(BatApprovedChemistry::Zincair),
101 13 => Some(BatApprovedChemistry::Zinccarbon),
102 14 => Some(BatApprovedChemistry::Zincchloride),
103 15 => Some(BatApprovedChemistry::Zincmanganesedioxide),
104 16 => Some(BatApprovedChemistry::Leadacid),
105 17 => Some(BatApprovedChemistry::Lithiumcobaltoxide),
106 18 => Some(BatApprovedChemistry::Lithiumion),
107 19 => Some(BatApprovedChemistry::Lithiumionpolymer),
108 20 => Some(BatApprovedChemistry::Lithiumironphosphate),
109 21 => Some(BatApprovedChemistry::Lithiumsulfur),
110 22 => Some(BatApprovedChemistry::Lithiumtitanate),
111 23 => Some(BatApprovedChemistry::Nickelcadmium),
112 24 => Some(BatApprovedChemistry::Nickelhydrogen),
113 25 => Some(BatApprovedChemistry::Nickeliron),
114 26 => Some(BatApprovedChemistry::Nickelmetalhydride),
115 27 => Some(BatApprovedChemistry::Nickelzinc),
116 28 => Some(BatApprovedChemistry::Silverzinc),
117 29 => Some(BatApprovedChemistry::Sodiumion),
118 30 => Some(BatApprovedChemistry::Sodiumsulfur),
119 31 => Some(BatApprovedChemistry::Zincbromide),
120 32 => Some(BatApprovedChemistry::Zinccerium),
121 _ => None,
122 }
123 }
124
125 pub fn to_u8(self) -> u8 {
127 self as u8
128 }
129}
130
131impl From<BatApprovedChemistry> for u8 {
132 fn from(val: BatApprovedChemistry) -> Self {
133 val as u8
134 }
135}
136
137#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
138#[repr(u8)]
139pub enum BatChargeFault {
140 Unspecified = 0,
142 Ambienttoohot = 1,
144 Ambienttoocold = 2,
146 Batterytoohot = 3,
148 Batterytoocold = 4,
150 Batteryabsent = 5,
152 Batteryovervoltage = 6,
154 Batteryundervoltage = 7,
156 Chargerovervoltage = 8,
158 Chargerundervoltage = 9,
160 Safetytimeout = 10,
162}
163
164impl BatChargeFault {
165 pub fn from_u8(value: u8) -> Option<Self> {
167 match value {
168 0 => Some(BatChargeFault::Unspecified),
169 1 => Some(BatChargeFault::Ambienttoohot),
170 2 => Some(BatChargeFault::Ambienttoocold),
171 3 => Some(BatChargeFault::Batterytoohot),
172 4 => Some(BatChargeFault::Batterytoocold),
173 5 => Some(BatChargeFault::Batteryabsent),
174 6 => Some(BatChargeFault::Batteryovervoltage),
175 7 => Some(BatChargeFault::Batteryundervoltage),
176 8 => Some(BatChargeFault::Chargerovervoltage),
177 9 => Some(BatChargeFault::Chargerundervoltage),
178 10 => Some(BatChargeFault::Safetytimeout),
179 _ => None,
180 }
181 }
182
183 pub fn to_u8(self) -> u8 {
185 self as u8
186 }
187}
188
189impl From<BatChargeFault> for u8 {
190 fn from(val: BatChargeFault) -> Self {
191 val as u8
192 }
193}
194
195#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
196#[repr(u8)]
197pub enum BatChargeLevel {
198 Ok = 0,
200 Warning = 1,
202 Critical = 2,
204}
205
206impl BatChargeLevel {
207 pub fn from_u8(value: u8) -> Option<Self> {
209 match value {
210 0 => Some(BatChargeLevel::Ok),
211 1 => Some(BatChargeLevel::Warning),
212 2 => Some(BatChargeLevel::Critical),
213 _ => None,
214 }
215 }
216
217 pub fn to_u8(self) -> u8 {
219 self as u8
220 }
221}
222
223impl From<BatChargeLevel> for u8 {
224 fn from(val: BatChargeLevel) -> Self {
225 val as u8
226 }
227}
228
229#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
230#[repr(u8)]
231pub enum BatChargeState {
232 Unknown = 0,
234 Ischarging = 1,
236 Isatfullcharge = 2,
238 Isnotcharging = 3,
240}
241
242impl BatChargeState {
243 pub fn from_u8(value: u8) -> Option<Self> {
245 match value {
246 0 => Some(BatChargeState::Unknown),
247 1 => Some(BatChargeState::Ischarging),
248 2 => Some(BatChargeState::Isatfullcharge),
249 3 => Some(BatChargeState::Isnotcharging),
250 _ => None,
251 }
252 }
253
254 pub fn to_u8(self) -> u8 {
256 self as u8
257 }
258}
259
260impl From<BatChargeState> for u8 {
261 fn from(val: BatChargeState) -> Self {
262 val as u8
263 }
264}
265
266#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
267#[repr(u8)]
268pub enum BatCommonDesignation {
269 Unspecified = 0,
271 Aaa = 1,
273 Aa = 2,
275 C = 3,
277 D = 4,
279 _4v5 = 5,
281 _6v0 = 6,
283 _9v0 = 7,
285 _12aa = 8,
287 Aaaa = 9,
289 A = 10,
291 B = 11,
293 F = 12,
295 N = 13,
297 No6 = 14,
299 Subc = 15,
301 A23 = 16,
303 A27 = 17,
305 Ba5800 = 18,
307 Duplex = 19,
309 _4sr44 = 20,
311 _523 = 21,
313 _531 = 22,
315 _15v0 = 23,
317 _22v5 = 24,
319 _30v0 = 25,
321 _45v0 = 26,
323 _67v5 = 27,
325 J = 28,
327 Cr123a = 29,
329 Cr2 = 30,
331 _2cr5 = 31,
333 CrP2 = 32,
335 CrV3 = 33,
337 Sr41 = 34,
339 Sr43 = 35,
341 Sr44 = 36,
343 Sr45 = 37,
345 Sr48 = 38,
347 Sr54 = 39,
349 Sr55 = 40,
351 Sr57 = 41,
353 Sr58 = 42,
355 Sr59 = 43,
357 Sr60 = 44,
359 Sr63 = 45,
361 Sr64 = 46,
363 Sr65 = 47,
365 Sr66 = 48,
367 Sr67 = 49,
369 Sr68 = 50,
371 Sr69 = 51,
373 Sr516 = 52,
375 Sr731 = 53,
377 Sr712 = 54,
379 Lr932 = 55,
381 A5 = 56,
383 A10 = 57,
385 A13 = 58,
387 A312 = 59,
389 A675 = 60,
391 Ac41e = 61,
393 _10180 = 62,
395 _10280 = 63,
397 _10440 = 64,
399 _14250 = 65,
401 _14430 = 66,
403 _14500 = 67,
405 _14650 = 68,
407 _15270 = 69,
409 _16340 = 70,
411 Rcr123a = 71,
413 _17500 = 72,
415 _17670 = 73,
417 _18350 = 74,
419 _18500 = 75,
421 _18650 = 76,
423 _19670 = 77,
425 _25500 = 78,
427 _26650 = 79,
429 _32600 = 80,
431}
432
433impl BatCommonDesignation {
434 pub fn from_u8(value: u8) -> Option<Self> {
436 match value {
437 0 => Some(BatCommonDesignation::Unspecified),
438 1 => Some(BatCommonDesignation::Aaa),
439 2 => Some(BatCommonDesignation::Aa),
440 3 => Some(BatCommonDesignation::C),
441 4 => Some(BatCommonDesignation::D),
442 5 => Some(BatCommonDesignation::_4v5),
443 6 => Some(BatCommonDesignation::_6v0),
444 7 => Some(BatCommonDesignation::_9v0),
445 8 => Some(BatCommonDesignation::_12aa),
446 9 => Some(BatCommonDesignation::Aaaa),
447 10 => Some(BatCommonDesignation::A),
448 11 => Some(BatCommonDesignation::B),
449 12 => Some(BatCommonDesignation::F),
450 13 => Some(BatCommonDesignation::N),
451 14 => Some(BatCommonDesignation::No6),
452 15 => Some(BatCommonDesignation::Subc),
453 16 => Some(BatCommonDesignation::A23),
454 17 => Some(BatCommonDesignation::A27),
455 18 => Some(BatCommonDesignation::Ba5800),
456 19 => Some(BatCommonDesignation::Duplex),
457 20 => Some(BatCommonDesignation::_4sr44),
458 21 => Some(BatCommonDesignation::_523),
459 22 => Some(BatCommonDesignation::_531),
460 23 => Some(BatCommonDesignation::_15v0),
461 24 => Some(BatCommonDesignation::_22v5),
462 25 => Some(BatCommonDesignation::_30v0),
463 26 => Some(BatCommonDesignation::_45v0),
464 27 => Some(BatCommonDesignation::_67v5),
465 28 => Some(BatCommonDesignation::J),
466 29 => Some(BatCommonDesignation::Cr123a),
467 30 => Some(BatCommonDesignation::Cr2),
468 31 => Some(BatCommonDesignation::_2cr5),
469 32 => Some(BatCommonDesignation::CrP2),
470 33 => Some(BatCommonDesignation::CrV3),
471 34 => Some(BatCommonDesignation::Sr41),
472 35 => Some(BatCommonDesignation::Sr43),
473 36 => Some(BatCommonDesignation::Sr44),
474 37 => Some(BatCommonDesignation::Sr45),
475 38 => Some(BatCommonDesignation::Sr48),
476 39 => Some(BatCommonDesignation::Sr54),
477 40 => Some(BatCommonDesignation::Sr55),
478 41 => Some(BatCommonDesignation::Sr57),
479 42 => Some(BatCommonDesignation::Sr58),
480 43 => Some(BatCommonDesignation::Sr59),
481 44 => Some(BatCommonDesignation::Sr60),
482 45 => Some(BatCommonDesignation::Sr63),
483 46 => Some(BatCommonDesignation::Sr64),
484 47 => Some(BatCommonDesignation::Sr65),
485 48 => Some(BatCommonDesignation::Sr66),
486 49 => Some(BatCommonDesignation::Sr67),
487 50 => Some(BatCommonDesignation::Sr68),
488 51 => Some(BatCommonDesignation::Sr69),
489 52 => Some(BatCommonDesignation::Sr516),
490 53 => Some(BatCommonDesignation::Sr731),
491 54 => Some(BatCommonDesignation::Sr712),
492 55 => Some(BatCommonDesignation::Lr932),
493 56 => Some(BatCommonDesignation::A5),
494 57 => Some(BatCommonDesignation::A10),
495 58 => Some(BatCommonDesignation::A13),
496 59 => Some(BatCommonDesignation::A312),
497 60 => Some(BatCommonDesignation::A675),
498 61 => Some(BatCommonDesignation::Ac41e),
499 62 => Some(BatCommonDesignation::_10180),
500 63 => Some(BatCommonDesignation::_10280),
501 64 => Some(BatCommonDesignation::_10440),
502 65 => Some(BatCommonDesignation::_14250),
503 66 => Some(BatCommonDesignation::_14430),
504 67 => Some(BatCommonDesignation::_14500),
505 68 => Some(BatCommonDesignation::_14650),
506 69 => Some(BatCommonDesignation::_15270),
507 70 => Some(BatCommonDesignation::_16340),
508 71 => Some(BatCommonDesignation::Rcr123a),
509 72 => Some(BatCommonDesignation::_17500),
510 73 => Some(BatCommonDesignation::_17670),
511 74 => Some(BatCommonDesignation::_18350),
512 75 => Some(BatCommonDesignation::_18500),
513 76 => Some(BatCommonDesignation::_18650),
514 77 => Some(BatCommonDesignation::_19670),
515 78 => Some(BatCommonDesignation::_25500),
516 79 => Some(BatCommonDesignation::_26650),
517 80 => Some(BatCommonDesignation::_32600),
518 _ => None,
519 }
520 }
521
522 pub fn to_u8(self) -> u8 {
524 self as u8
525 }
526}
527
528impl From<BatCommonDesignation> for u8 {
529 fn from(val: BatCommonDesignation) -> Self {
530 val as u8
531 }
532}
533
534#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
535#[repr(u8)]
536pub enum BatFault {
537 Unspecified = 0,
539 Overtemp = 1,
541 Undertemp = 2,
543}
544
545impl BatFault {
546 pub fn from_u8(value: u8) -> Option<Self> {
548 match value {
549 0 => Some(BatFault::Unspecified),
550 1 => Some(BatFault::Overtemp),
551 2 => Some(BatFault::Undertemp),
552 _ => None,
553 }
554 }
555
556 pub fn to_u8(self) -> u8 {
558 self as u8
559 }
560}
561
562impl From<BatFault> for u8 {
563 fn from(val: BatFault) -> Self {
564 val as u8
565 }
566}
567
568#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
569#[repr(u8)]
570pub enum BatReplaceability {
571 Unspecified = 0,
573 Notreplaceable = 1,
575 Userreplaceable = 2,
577 Factoryreplaceable = 3,
579}
580
581impl BatReplaceability {
582 pub fn from_u8(value: u8) -> Option<Self> {
584 match value {
585 0 => Some(BatReplaceability::Unspecified),
586 1 => Some(BatReplaceability::Notreplaceable),
587 2 => Some(BatReplaceability::Userreplaceable),
588 3 => Some(BatReplaceability::Factoryreplaceable),
589 _ => None,
590 }
591 }
592
593 pub fn to_u8(self) -> u8 {
595 self as u8
596 }
597}
598
599impl From<BatReplaceability> for u8 {
600 fn from(val: BatReplaceability) -> Self {
601 val as u8
602 }
603}
604
605#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
606#[repr(u8)]
607pub enum PowerSourceStatus {
608 Unspecified = 0,
610 Active = 1,
612 Standby = 2,
614 Unavailable = 3,
616}
617
618impl PowerSourceStatus {
619 pub fn from_u8(value: u8) -> Option<Self> {
621 match value {
622 0 => Some(PowerSourceStatus::Unspecified),
623 1 => Some(PowerSourceStatus::Active),
624 2 => Some(PowerSourceStatus::Standby),
625 3 => Some(PowerSourceStatus::Unavailable),
626 _ => None,
627 }
628 }
629
630 pub fn to_u8(self) -> u8 {
632 self as u8
633 }
634}
635
636impl From<PowerSourceStatus> for u8 {
637 fn from(val: PowerSourceStatus) -> Self {
638 val as u8
639 }
640}
641
642#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
643#[repr(u8)]
644pub enum WiredCurrentType {
645 Ac = 0,
647 Dc = 1,
649}
650
651impl WiredCurrentType {
652 pub fn from_u8(value: u8) -> Option<Self> {
654 match value {
655 0 => Some(WiredCurrentType::Ac),
656 1 => Some(WiredCurrentType::Dc),
657 _ => None,
658 }
659 }
660
661 pub fn to_u8(self) -> u8 {
663 self as u8
664 }
665}
666
667impl From<WiredCurrentType> for u8 {
668 fn from(val: WiredCurrentType) -> Self {
669 val as u8
670 }
671}
672
673#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
674#[repr(u8)]
675pub enum WiredFault {
676 Unspecified = 0,
678 Overvoltage = 1,
680 Undervoltage = 2,
682}
683
684impl WiredFault {
685 pub fn from_u8(value: u8) -> Option<Self> {
687 match value {
688 0 => Some(WiredFault::Unspecified),
689 1 => Some(WiredFault::Overvoltage),
690 2 => Some(WiredFault::Undervoltage),
691 _ => None,
692 }
693 }
694
695 pub fn to_u8(self) -> u8 {
697 self as u8
698 }
699}
700
701impl From<WiredFault> for u8 {
702 fn from(val: WiredFault) -> Self {
703 val as u8
704 }
705}
706
707pub fn decode_status(inp: &tlv::TlvItemValue) -> anyhow::Result<PowerSourceStatus> {
711 if let tlv::TlvItemValue::Int(v) = inp {
712 PowerSourceStatus::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
713 } else {
714 Err(anyhow::anyhow!("Expected Integer"))
715 }
716}
717
718pub fn decode_order(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
720 if let tlv::TlvItemValue::Int(v) = inp {
721 Ok(*v as u8)
722 } else {
723 Err(anyhow::anyhow!("Expected UInt8"))
724 }
725}
726
727pub fn decode_description(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
729 if let tlv::TlvItemValue::String(v) = inp {
730 Ok(v.clone())
731 } else {
732 Err(anyhow::anyhow!("Expected String"))
733 }
734}
735
736pub fn decode_wired_assessed_input_voltage(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u32>> {
738 if let tlv::TlvItemValue::Int(v) = inp {
739 Ok(Some(*v as u32))
740 } else {
741 Ok(None)
742 }
743}
744
745pub fn decode_wired_assessed_input_frequency(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u16>> {
747 if let tlv::TlvItemValue::Int(v) = inp {
748 Ok(Some(*v as u16))
749 } else {
750 Ok(None)
751 }
752}
753
754pub fn decode_wired_current_type(inp: &tlv::TlvItemValue) -> anyhow::Result<WiredCurrentType> {
756 if let tlv::TlvItemValue::Int(v) = inp {
757 WiredCurrentType::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
758 } else {
759 Err(anyhow::anyhow!("Expected Integer"))
760 }
761}
762
763pub fn decode_wired_assessed_current(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u32>> {
765 if let tlv::TlvItemValue::Int(v) = inp {
766 Ok(Some(*v as u32))
767 } else {
768 Ok(None)
769 }
770}
771
772pub fn decode_wired_nominal_voltage(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
774 if let tlv::TlvItemValue::Int(v) = inp {
775 Ok(*v as u32)
776 } else {
777 Err(anyhow::anyhow!("Expected UInt32"))
778 }
779}
780
781pub fn decode_wired_maximum_current(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
783 if let tlv::TlvItemValue::Int(v) = inp {
784 Ok(*v as u32)
785 } else {
786 Err(anyhow::anyhow!("Expected UInt32"))
787 }
788}
789
790pub fn decode_wired_present(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
792 if let tlv::TlvItemValue::Bool(v) = inp {
793 Ok(*v)
794 } else {
795 Err(anyhow::anyhow!("Expected Bool"))
796 }
797}
798
799pub fn decode_active_wired_faults(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<WiredFault>> {
801 let mut res = Vec::new();
802 if let tlv::TlvItemValue::List(v) = inp {
803 for item in v {
804 if let tlv::TlvItemValue::Int(i) = &item.value {
805 if let Some(enum_val) = WiredFault::from_u8(*i as u8) {
806 res.push(enum_val);
807 }
808 }
809 }
810 }
811 Ok(res)
812}
813
814pub fn decode_bat_voltage(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u32>> {
816 if let tlv::TlvItemValue::Int(v) = inp {
817 Ok(Some(*v as u32))
818 } else {
819 Ok(None)
820 }
821}
822
823pub fn decode_bat_percent_remaining(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
825 if let tlv::TlvItemValue::Int(v) = inp {
826 Ok(Some(*v as u8))
827 } else {
828 Ok(None)
829 }
830}
831
832pub fn decode_bat_time_remaining(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u32>> {
834 if let tlv::TlvItemValue::Int(v) = inp {
835 Ok(Some(*v as u32))
836 } else {
837 Ok(None)
838 }
839}
840
841pub fn decode_bat_charge_level(inp: &tlv::TlvItemValue) -> anyhow::Result<BatChargeLevel> {
843 if let tlv::TlvItemValue::Int(v) = inp {
844 BatChargeLevel::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
845 } else {
846 Err(anyhow::anyhow!("Expected Integer"))
847 }
848}
849
850pub fn decode_bat_replacement_needed(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
852 if let tlv::TlvItemValue::Bool(v) = inp {
853 Ok(*v)
854 } else {
855 Err(anyhow::anyhow!("Expected Bool"))
856 }
857}
858
859pub fn decode_bat_replaceability(inp: &tlv::TlvItemValue) -> anyhow::Result<BatReplaceability> {
861 if let tlv::TlvItemValue::Int(v) = inp {
862 BatReplaceability::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
863 } else {
864 Err(anyhow::anyhow!("Expected Integer"))
865 }
866}
867
868pub fn decode_bat_present(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
870 if let tlv::TlvItemValue::Bool(v) = inp {
871 Ok(*v)
872 } else {
873 Err(anyhow::anyhow!("Expected Bool"))
874 }
875}
876
877pub fn decode_active_bat_faults(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<BatFault>> {
879 let mut res = Vec::new();
880 if let tlv::TlvItemValue::List(v) = inp {
881 for item in v {
882 if let tlv::TlvItemValue::Int(i) = &item.value {
883 if let Some(enum_val) = BatFault::from_u8(*i as u8) {
884 res.push(enum_val);
885 }
886 }
887 }
888 }
889 Ok(res)
890}
891
892pub fn decode_bat_replacement_description(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
894 if let tlv::TlvItemValue::String(v) = inp {
895 Ok(v.clone())
896 } else {
897 Err(anyhow::anyhow!("Expected String"))
898 }
899}
900
901pub fn decode_bat_common_designation(inp: &tlv::TlvItemValue) -> anyhow::Result<BatCommonDesignation> {
903 if let tlv::TlvItemValue::Int(v) = inp {
904 BatCommonDesignation::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
905 } else {
906 Err(anyhow::anyhow!("Expected Integer"))
907 }
908}
909
910pub fn decode_bat_ansi_designation(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
912 if let tlv::TlvItemValue::String(v) = inp {
913 Ok(v.clone())
914 } else {
915 Err(anyhow::anyhow!("Expected String"))
916 }
917}
918
919pub fn decode_bat_iec_designation(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
921 if let tlv::TlvItemValue::String(v) = inp {
922 Ok(v.clone())
923 } else {
924 Err(anyhow::anyhow!("Expected String"))
925 }
926}
927
928pub fn decode_bat_approved_chemistry(inp: &tlv::TlvItemValue) -> anyhow::Result<BatApprovedChemistry> {
930 if let tlv::TlvItemValue::Int(v) = inp {
931 BatApprovedChemistry::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
932 } else {
933 Err(anyhow::anyhow!("Expected Integer"))
934 }
935}
936
937pub fn decode_bat_capacity(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
939 if let tlv::TlvItemValue::Int(v) = inp {
940 Ok(*v as u32)
941 } else {
942 Err(anyhow::anyhow!("Expected UInt32"))
943 }
944}
945
946pub fn decode_bat_quantity(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
948 if let tlv::TlvItemValue::Int(v) = inp {
949 Ok(*v as u8)
950 } else {
951 Err(anyhow::anyhow!("Expected UInt8"))
952 }
953}
954
955pub fn decode_bat_charge_state(inp: &tlv::TlvItemValue) -> anyhow::Result<BatChargeState> {
957 if let tlv::TlvItemValue::Int(v) = inp {
958 BatChargeState::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
959 } else {
960 Err(anyhow::anyhow!("Expected Integer"))
961 }
962}
963
964pub fn decode_bat_time_to_full_charge(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u32>> {
966 if let tlv::TlvItemValue::Int(v) = inp {
967 Ok(Some(*v as u32))
968 } else {
969 Ok(None)
970 }
971}
972
973pub fn decode_bat_functional_while_charging(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
975 if let tlv::TlvItemValue::Bool(v) = inp {
976 Ok(*v)
977 } else {
978 Err(anyhow::anyhow!("Expected Bool"))
979 }
980}
981
982pub fn decode_bat_charging_current(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u32>> {
984 if let tlv::TlvItemValue::Int(v) = inp {
985 Ok(Some(*v as u32))
986 } else {
987 Ok(None)
988 }
989}
990
991pub fn decode_active_bat_charge_faults(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<BatChargeFault>> {
993 let mut res = Vec::new();
994 if let tlv::TlvItemValue::List(v) = inp {
995 for item in v {
996 if let tlv::TlvItemValue::Int(i) = &item.value {
997 if let Some(enum_val) = BatChargeFault::from_u8(*i as u8) {
998 res.push(enum_val);
999 }
1000 }
1001 }
1002 }
1003 Ok(res)
1004}
1005
1006pub fn decode_endpoint_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<u16>> {
1008 let mut res = Vec::new();
1009 if let tlv::TlvItemValue::List(v) = inp {
1010 for item in v {
1011 if let tlv::TlvItemValue::Int(i) = &item.value {
1012 res.push(*i as u16);
1013 }
1014 }
1015 }
1016 Ok(res)
1017}
1018
1019
1020pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
1032 if cluster_id != 0x002F {
1034 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x002F, got {}\"}}", cluster_id);
1035 }
1036
1037 match attribute_id {
1038 0x0000 => {
1039 match decode_status(tlv_value) {
1040 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1041 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1042 }
1043 }
1044 0x0001 => {
1045 match decode_order(tlv_value) {
1046 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1047 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1048 }
1049 }
1050 0x0002 => {
1051 match decode_description(tlv_value) {
1052 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1053 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1054 }
1055 }
1056 0x0003 => {
1057 match decode_wired_assessed_input_voltage(tlv_value) {
1058 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1059 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1060 }
1061 }
1062 0x0004 => {
1063 match decode_wired_assessed_input_frequency(tlv_value) {
1064 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1065 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1066 }
1067 }
1068 0x0005 => {
1069 match decode_wired_current_type(tlv_value) {
1070 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1071 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1072 }
1073 }
1074 0x0006 => {
1075 match decode_wired_assessed_current(tlv_value) {
1076 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1077 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1078 }
1079 }
1080 0x0007 => {
1081 match decode_wired_nominal_voltage(tlv_value) {
1082 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1083 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1084 }
1085 }
1086 0x0008 => {
1087 match decode_wired_maximum_current(tlv_value) {
1088 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1089 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1090 }
1091 }
1092 0x0009 => {
1093 match decode_wired_present(tlv_value) {
1094 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1095 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1096 }
1097 }
1098 0x000A => {
1099 match decode_active_wired_faults(tlv_value) {
1100 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1101 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1102 }
1103 }
1104 0x000B => {
1105 match decode_bat_voltage(tlv_value) {
1106 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1107 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1108 }
1109 }
1110 0x000C => {
1111 match decode_bat_percent_remaining(tlv_value) {
1112 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1113 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1114 }
1115 }
1116 0x000D => {
1117 match decode_bat_time_remaining(tlv_value) {
1118 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1119 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1120 }
1121 }
1122 0x000E => {
1123 match decode_bat_charge_level(tlv_value) {
1124 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1125 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1126 }
1127 }
1128 0x000F => {
1129 match decode_bat_replacement_needed(tlv_value) {
1130 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1131 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1132 }
1133 }
1134 0x0010 => {
1135 match decode_bat_replaceability(tlv_value) {
1136 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1137 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1138 }
1139 }
1140 0x0011 => {
1141 match decode_bat_present(tlv_value) {
1142 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1143 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1144 }
1145 }
1146 0x0012 => {
1147 match decode_active_bat_faults(tlv_value) {
1148 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1149 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1150 }
1151 }
1152 0x0013 => {
1153 match decode_bat_replacement_description(tlv_value) {
1154 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1155 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1156 }
1157 }
1158 0x0014 => {
1159 match decode_bat_common_designation(tlv_value) {
1160 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1161 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1162 }
1163 }
1164 0x0015 => {
1165 match decode_bat_ansi_designation(tlv_value) {
1166 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1167 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1168 }
1169 }
1170 0x0016 => {
1171 match decode_bat_iec_designation(tlv_value) {
1172 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1173 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1174 }
1175 }
1176 0x0017 => {
1177 match decode_bat_approved_chemistry(tlv_value) {
1178 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1179 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1180 }
1181 }
1182 0x0018 => {
1183 match decode_bat_capacity(tlv_value) {
1184 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1185 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1186 }
1187 }
1188 0x0019 => {
1189 match decode_bat_quantity(tlv_value) {
1190 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1191 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1192 }
1193 }
1194 0x001A => {
1195 match decode_bat_charge_state(tlv_value) {
1196 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1197 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1198 }
1199 }
1200 0x001B => {
1201 match decode_bat_time_to_full_charge(tlv_value) {
1202 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1203 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1204 }
1205 }
1206 0x001C => {
1207 match decode_bat_functional_while_charging(tlv_value) {
1208 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1209 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1210 }
1211 }
1212 0x001D => {
1213 match decode_bat_charging_current(tlv_value) {
1214 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1215 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1216 }
1217 }
1218 0x001E => {
1219 match decode_active_bat_charge_faults(tlv_value) {
1220 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1221 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1222 }
1223 }
1224 0x001F => {
1225 match decode_endpoint_list(tlv_value) {
1226 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1227 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1228 }
1229 }
1230 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
1231 }
1232}
1233
1234pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
1239 vec![
1240 (0x0000, "Status"),
1241 (0x0001, "Order"),
1242 (0x0002, "Description"),
1243 (0x0003, "WiredAssessedInputVoltage"),
1244 (0x0004, "WiredAssessedInputFrequency"),
1245 (0x0005, "WiredCurrentType"),
1246 (0x0006, "WiredAssessedCurrent"),
1247 (0x0007, "WiredNominalVoltage"),
1248 (0x0008, "WiredMaximumCurrent"),
1249 (0x0009, "WiredPresent"),
1250 (0x000A, "ActiveWiredFaults"),
1251 (0x000B, "BatVoltage"),
1252 (0x000C, "BatPercentRemaining"),
1253 (0x000D, "BatTimeRemaining"),
1254 (0x000E, "BatChargeLevel"),
1255 (0x000F, "BatReplacementNeeded"),
1256 (0x0010, "BatReplaceability"),
1257 (0x0011, "BatPresent"),
1258 (0x0012, "ActiveBatFaults"),
1259 (0x0013, "BatReplacementDescription"),
1260 (0x0014, "BatCommonDesignation"),
1261 (0x0015, "BatANSIDesignation"),
1262 (0x0016, "BatIECDesignation"),
1263 (0x0017, "BatApprovedChemistry"),
1264 (0x0018, "BatCapacity"),
1265 (0x0019, "BatQuantity"),
1266 (0x001A, "BatChargeState"),
1267 (0x001B, "BatTimeToFullCharge"),
1268 (0x001C, "BatFunctionalWhileCharging"),
1269 (0x001D, "BatChargingCurrent"),
1270 (0x001E, "ActiveBatChargeFaults"),
1271 (0x001F, "EndpointList"),
1272 ]
1273}
1274
1275#[derive(Debug, serde::Serialize)]
1276pub struct WiredFaultChangeEvent {
1277 pub current: Option<Vec<WiredFault>>,
1278 pub previous: Option<Vec<WiredFault>>,
1279}
1280
1281#[derive(Debug, serde::Serialize)]
1282pub struct BatFaultChangeEvent {
1283 pub current: Option<Vec<BatFault>>,
1284 pub previous: Option<Vec<BatFault>>,
1285}
1286
1287#[derive(Debug, serde::Serialize)]
1288pub struct BatChargeFaultChangeEvent {
1289 pub current: Option<Vec<BatChargeFault>>,
1290 pub previous: Option<Vec<BatChargeFault>>,
1291}
1292
1293pub fn decode_wired_fault_change_event(inp: &tlv::TlvItemValue) -> anyhow::Result<WiredFaultChangeEvent> {
1297 if let tlv::TlvItemValue::List(_fields) = inp {
1298 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
1299 Ok(WiredFaultChangeEvent {
1300 current: {
1301 if let Some(tlv::TlvItemValue::List(l)) = item.get(&[0]) {
1302 let items: Vec<WiredFault> = l.iter().filter_map(|e| { if let tlv::TlvItemValue::Int(v) = &e.value { WiredFault::from_u8(*v as u8) } else { None } }).collect();
1303 Some(items)
1304 } else {
1305 None
1306 }
1307 },
1308 previous: {
1309 if let Some(tlv::TlvItemValue::List(l)) = item.get(&[1]) {
1310 let items: Vec<WiredFault> = l.iter().filter_map(|e| { if let tlv::TlvItemValue::Int(v) = &e.value { WiredFault::from_u8(*v as u8) } else { None } }).collect();
1311 Some(items)
1312 } else {
1313 None
1314 }
1315 },
1316 })
1317 } else {
1318 Err(anyhow::anyhow!("Expected struct fields"))
1319 }
1320}
1321
1322pub fn decode_bat_fault_change_event(inp: &tlv::TlvItemValue) -> anyhow::Result<BatFaultChangeEvent> {
1324 if let tlv::TlvItemValue::List(_fields) = inp {
1325 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
1326 Ok(BatFaultChangeEvent {
1327 current: {
1328 if let Some(tlv::TlvItemValue::List(l)) = item.get(&[0]) {
1329 let items: Vec<BatFault> = l.iter().filter_map(|e| { if let tlv::TlvItemValue::Int(v) = &e.value { BatFault::from_u8(*v as u8) } else { None } }).collect();
1330 Some(items)
1331 } else {
1332 None
1333 }
1334 },
1335 previous: {
1336 if let Some(tlv::TlvItemValue::List(l)) = item.get(&[1]) {
1337 let items: Vec<BatFault> = l.iter().filter_map(|e| { if let tlv::TlvItemValue::Int(v) = &e.value { BatFault::from_u8(*v as u8) } else { None } }).collect();
1338 Some(items)
1339 } else {
1340 None
1341 }
1342 },
1343 })
1344 } else {
1345 Err(anyhow::anyhow!("Expected struct fields"))
1346 }
1347}
1348
1349pub fn decode_bat_charge_fault_change_event(inp: &tlv::TlvItemValue) -> anyhow::Result<BatChargeFaultChangeEvent> {
1351 if let tlv::TlvItemValue::List(_fields) = inp {
1352 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
1353 Ok(BatChargeFaultChangeEvent {
1354 current: {
1355 if let Some(tlv::TlvItemValue::List(l)) = item.get(&[0]) {
1356 let items: Vec<BatChargeFault> = l.iter().filter_map(|e| { if let tlv::TlvItemValue::Int(v) = &e.value { BatChargeFault::from_u8(*v as u8) } else { None } }).collect();
1357 Some(items)
1358 } else {
1359 None
1360 }
1361 },
1362 previous: {
1363 if let Some(tlv::TlvItemValue::List(l)) = item.get(&[1]) {
1364 let items: Vec<BatChargeFault> = l.iter().filter_map(|e| { if let tlv::TlvItemValue::Int(v) = &e.value { BatChargeFault::from_u8(*v as u8) } else { None } }).collect();
1365 Some(items)
1366 } else {
1367 None
1368 }
1369 },
1370 })
1371 } else {
1372 Err(anyhow::anyhow!("Expected struct fields"))
1373 }
1374}
1375