matc/clusters/codec/
power_source_cluster.rs

1//! Matter TLV encoders and decoders for Power Source Cluster
2//! Cluster ID: 0x002F
3//!
4//! This file is automatically generated from PowerSourceCluster.xml
5
6use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11// Enum definitions
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
14#[repr(u8)]
15pub enum BatApprovedChemistry {
16    /// Cell chemistry is unspecified or unknown
17    Unspecified = 0,
18    /// Cell chemistry is alkaline
19    Alkaline = 1,
20    /// Cell chemistry is lithium carbon fluoride
21    Lithiumcarbonfluoride = 2,
22    /// Cell chemistry is lithium chromium oxide
23    Lithiumchromiumoxide = 3,
24    /// Cell chemistry is lithium copper oxide
25    Lithiumcopperoxide = 4,
26    /// Cell chemistry is lithium iron disulfide
27    Lithiumirondisulfide = 5,
28    /// Cell chemistry is lithium manganese dioxide
29    Lithiummanganesedioxide = 6,
30    /// Cell chemistry is lithium thionyl chloride
31    Lithiumthionylchloride = 7,
32    /// Cell chemistry is magnesium
33    Magnesium = 8,
34    /// Cell chemistry is mercury oxide
35    Mercuryoxide = 9,
36    /// Cell chemistry is nickel oxyhydride
37    Nickeloxyhydride = 10,
38    /// Cell chemistry is silver oxide
39    Silveroxide = 11,
40    /// Cell chemistry is zinc air
41    Zincair = 12,
42    /// Cell chemistry is zinc carbon
43    Zinccarbon = 13,
44    /// Cell chemistry is zinc chloride
45    Zincchloride = 14,
46    /// Cell chemistry is zinc manganese dioxide
47    Zincmanganesedioxide = 15,
48    /// Cell chemistry is lead acid
49    Leadacid = 16,
50    /// Cell chemistry is lithium cobalt oxide
51    Lithiumcobaltoxide = 17,
52    /// Cell chemistry is lithium ion
53    Lithiumion = 18,
54    /// Cell chemistry is lithium ion polymer
55    Lithiumionpolymer = 19,
56    /// Cell chemistry is lithium iron phosphate
57    Lithiumironphosphate = 20,
58    /// Cell chemistry is lithium sulfur
59    Lithiumsulfur = 21,
60    /// Cell chemistry is lithium titanate
61    Lithiumtitanate = 22,
62    /// Cell chemistry is nickel cadmium
63    Nickelcadmium = 23,
64    /// Cell chemistry is nickel hydrogen
65    Nickelhydrogen = 24,
66    /// Cell chemistry is nickel iron
67    Nickeliron = 25,
68    /// Cell chemistry is nickel metal hydride
69    Nickelmetalhydride = 26,
70    /// Cell chemistry is nickel zinc
71    Nickelzinc = 27,
72    /// Cell chemistry is silver zinc
73    Silverzinc = 28,
74    /// Cell chemistry is sodium ion
75    Sodiumion = 29,
76    /// Cell chemistry is sodium sulfur
77    Sodiumsulfur = 30,
78    /// Cell chemistry is zinc bromide
79    Zincbromide = 31,
80    /// Cell chemistry is zinc cerium
81    Zinccerium = 32,
82}
83
84impl BatApprovedChemistry {
85    /// Convert from u8 value
86    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    /// Convert to u8 value
126    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    /// The Node detects an unspecified fault on this battery source.
141    Unspecified = 0,
142    /// The Node detects the ambient temperature is above the nominal range for this battery source.
143    Ambienttoohot = 1,
144    /// The Node detects the ambient temperature is below the nominal range for this battery source.
145    Ambienttoocold = 2,
146    /// The Node detects the temperature of this battery source is above the nominal range.
147    Batterytoohot = 3,
148    /// The Node detects the temperature of this battery source is below the nominal range.
149    Batterytoocold = 4,
150    /// The Node detects this battery source is not present.
151    Batteryabsent = 5,
152    /// The Node detects this battery source is over voltage.
153    Batteryovervoltage = 6,
154    /// The Node detects this battery source is under voltage.
155    Batteryundervoltage = 7,
156    /// The Node detects the charger for this battery source is over voltage.
157    Chargerovervoltage = 8,
158    /// The Node detects the charger for this battery source is under voltage.
159    Chargerundervoltage = 9,
160    /// The Node detects a charging safety timeout for this battery source.
161    Safetytimeout = 10,
162}
163
164impl BatChargeFault {
165    /// Convert from u8 value
166    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    /// Convert to u8 value
184    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    /// Charge level is nominal
199    Ok = 0,
200    /// Charge level is low, intervention may soon be required.
201    Warning = 1,
202    /// Charge level is critical, immediate intervention is required
203    Critical = 2,
204}
205
206impl BatChargeLevel {
207    /// Convert from u8 value
208    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    /// Convert to u8 value
218    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    /// Unable to determine the charging state
233    Unknown = 0,
234    /// The battery is charging
235    Ischarging = 1,
236    /// The battery is at full charge
237    Isatfullcharge = 2,
238    /// The battery is not charging
239    Isnotcharging = 3,
240}
241
242impl BatChargeState {
243    /// Convert from u8 value
244    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    /// Convert to u8 value
255    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    /// Common type is unknown or unspecified
270    Unspecified = 0,
271    /// Common type is as specified
272    Aaa = 1,
273    /// Common type is as specified
274    Aa = 2,
275    /// Common type is as specified
276    C = 3,
277    /// Common type is as specified
278    D = 4,
279    /// Common type is as specified
280    _4v5 = 5,
281    /// Common type is as specified
282    _6v0 = 6,
283    /// Common type is as specified
284    _9v0 = 7,
285    /// Common type is as specified
286    _12aa = 8,
287    /// Common type is as specified
288    Aaaa = 9,
289    /// Common type is as specified
290    A = 10,
291    /// Common type is as specified
292    B = 11,
293    /// Common type is as specified
294    F = 12,
295    /// Common type is as specified
296    N = 13,
297    /// Common type is as specified
298    No6 = 14,
299    /// Common type is as specified
300    Subc = 15,
301    /// Common type is as specified
302    A23 = 16,
303    /// Common type is as specified
304    A27 = 17,
305    /// Common type is as specified
306    Ba5800 = 18,
307    /// Common type is as specified
308    Duplex = 19,
309    /// Common type is as specified
310    _4sr44 = 20,
311    /// Common type is as specified
312    _523 = 21,
313    /// Common type is as specified
314    _531 = 22,
315    /// Common type is as specified
316    _15v0 = 23,
317    /// Common type is as specified
318    _22v5 = 24,
319    /// Common type is as specified
320    _30v0 = 25,
321    /// Common type is as specified
322    _45v0 = 26,
323    /// Common type is as specified
324    _67v5 = 27,
325    /// Common type is as specified
326    J = 28,
327    /// Common type is as specified
328    Cr123a = 29,
329    /// Common type is as specified
330    Cr2 = 30,
331    /// Common type is as specified
332    _2cr5 = 31,
333    /// Common type is as specified
334    CrP2 = 32,
335    /// Common type is as specified
336    CrV3 = 33,
337    /// Common type is as specified
338    Sr41 = 34,
339    /// Common type is as specified
340    Sr43 = 35,
341    /// Common type is as specified
342    Sr44 = 36,
343    /// Common type is as specified
344    Sr45 = 37,
345    /// Common type is as specified
346    Sr48 = 38,
347    /// Common type is as specified
348    Sr54 = 39,
349    /// Common type is as specified
350    Sr55 = 40,
351    /// Common type is as specified
352    Sr57 = 41,
353    /// Common type is as specified
354    Sr58 = 42,
355    /// Common type is as specified
356    Sr59 = 43,
357    /// Common type is as specified
358    Sr60 = 44,
359    /// Common type is as specified
360    Sr63 = 45,
361    /// Common type is as specified
362    Sr64 = 46,
363    /// Common type is as specified
364    Sr65 = 47,
365    /// Common type is as specified
366    Sr66 = 48,
367    /// Common type is as specified
368    Sr67 = 49,
369    /// Common type is as specified
370    Sr68 = 50,
371    /// Common type is as specified
372    Sr69 = 51,
373    /// Common type is as specified
374    Sr516 = 52,
375    /// Common type is as specified
376    Sr731 = 53,
377    /// Common type is as specified
378    Sr712 = 54,
379    /// Common type is as specified
380    Lr932 = 55,
381    /// Common type is as specified
382    A5 = 56,
383    /// Common type is as specified
384    A10 = 57,
385    /// Common type is as specified
386    A13 = 58,
387    /// Common type is as specified
388    A312 = 59,
389    /// Common type is as specified
390    A675 = 60,
391    /// Common type is as specified
392    Ac41e = 61,
393    /// Common type is as specified
394    _10180 = 62,
395    /// Common type is as specified
396    _10280 = 63,
397    /// Common type is as specified
398    _10440 = 64,
399    /// Common type is as specified
400    _14250 = 65,
401    /// Common type is as specified
402    _14430 = 66,
403    /// Common type is as specified
404    _14500 = 67,
405    /// Common type is as specified
406    _14650 = 68,
407    /// Common type is as specified
408    _15270 = 69,
409    /// Common type is as specified
410    _16340 = 70,
411    /// Common type is as specified
412    Rcr123a = 71,
413    /// Common type is as specified
414    _17500 = 72,
415    /// Common type is as specified
416    _17670 = 73,
417    /// Common type is as specified
418    _18350 = 74,
419    /// Common type is as specified
420    _18500 = 75,
421    /// Common type is as specified
422    _18650 = 76,
423    /// Common type is as specified
424    _19670 = 77,
425    /// Common type is as specified
426    _25500 = 78,
427    /// Common type is as specified
428    _26650 = 79,
429    /// Common type is as specified
430    _32600 = 80,
431}
432
433impl BatCommonDesignation {
434    /// Convert from u8 value
435    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    /// Convert to u8 value
523    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    /// The Node detects an unspecified fault on this battery power source.
538    Unspecified = 0,
539    /// The Node detects the temperature of this battery power source is above ideal operating conditions.
540    Overtemp = 1,
541    /// The Node detects the temperature of this battery power source is below ideal operating conditions.
542    Undertemp = 2,
543}
544
545impl BatFault {
546    /// Convert from u8 value
547    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    /// Convert to u8 value
557    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    /// The replaceability is unspecified or unknown.
572    Unspecified = 0,
573    /// The battery is not replaceable.
574    Notreplaceable = 1,
575    /// The battery is replaceable by the user or customer.
576    Userreplaceable = 2,
577    /// The battery is replaceable by an authorized factory technician.
578    Factoryreplaceable = 3,
579}
580
581impl BatReplaceability {
582    /// Convert from u8 value
583    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    /// Convert to u8 value
594    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    /// Indicate the source status is not specified
609    Unspecified = 0,
610    /// Indicate the source is available and currently supplying power
611    Active = 1,
612    /// Indicate the source is available, but is not currently supplying power
613    Standby = 2,
614    /// Indicate the source is not currently available to supply power
615    Unavailable = 3,
616}
617
618impl PowerSourceStatus {
619    /// Convert from u8 value
620    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    /// Convert to u8 value
631    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    /// Indicates AC current
646    Ac = 0,
647    /// Indicates DC current
648    Dc = 1,
649}
650
651impl WiredCurrentType {
652    /// Convert from u8 value
653    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    /// Convert to u8 value
662    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    /// The Node detects an unspecified fault on this wired power source.
677    Unspecified = 0,
678    /// The Node detects the supplied voltage is above maximum supported value for this wired power source.
679    Overvoltage = 1,
680    /// The Node detects the supplied voltage is below maximum supported value for this wired power source.
681    Undervoltage = 2,
682}
683
684impl WiredFault {
685    /// Convert from u8 value
686    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    /// Convert to u8 value
696    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
707// Attribute decoders
708
709/// Decode Status attribute (0x0000)
710pub 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
718/// Decode Order attribute (0x0001)
719pub 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
727/// Decode Description attribute (0x0002)
728pub 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
736/// Decode WiredAssessedInputVoltage attribute (0x0003)
737pub 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
745/// Decode WiredAssessedInputFrequency attribute (0x0004)
746pub 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
754/// Decode WiredCurrentType attribute (0x0005)
755pub 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
763/// Decode WiredAssessedCurrent attribute (0x0006)
764pub 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
772/// Decode WiredNominalVoltage attribute (0x0007)
773pub 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
781/// Decode WiredMaximumCurrent attribute (0x0008)
782pub 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
790/// Decode WiredPresent attribute (0x0009)
791pub 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
799/// Decode ActiveWiredFaults attribute (0x000A)
800pub 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
814/// Decode BatVoltage attribute (0x000B)
815pub 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
823/// Decode BatPercentRemaining attribute (0x000C)
824pub 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
832/// Decode BatTimeRemaining attribute (0x000D)
833pub 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
841/// Decode BatChargeLevel attribute (0x000E)
842pub 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
850/// Decode BatReplacementNeeded attribute (0x000F)
851pub 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
859/// Decode BatReplaceability attribute (0x0010)
860pub 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
868/// Decode BatPresent attribute (0x0011)
869pub 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
877/// Decode ActiveBatFaults attribute (0x0012)
878pub 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
892/// Decode BatReplacementDescription attribute (0x0013)
893pub 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
901/// Decode BatCommonDesignation attribute (0x0014)
902pub 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
910/// Decode BatANSIDesignation attribute (0x0015)
911pub 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
919/// Decode BatIECDesignation attribute (0x0016)
920pub 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
928/// Decode BatApprovedChemistry attribute (0x0017)
929pub 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
937/// Decode BatCapacity attribute (0x0018)
938pub 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
946/// Decode BatQuantity attribute (0x0019)
947pub 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
955/// Decode BatChargeState attribute (0x001A)
956pub 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
964/// Decode BatTimeToFullCharge attribute (0x001B)
965pub 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
973/// Decode BatFunctionalWhileCharging attribute (0x001C)
974pub 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
982/// Decode BatChargingCurrent attribute (0x001D)
983pub 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
991/// Decode ActiveBatChargeFaults attribute (0x001E)
992pub 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
1006/// Decode EndpointList attribute (0x001F)
1007pub 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
1020// JSON dispatcher function
1021
1022/// Decode attribute value and return as JSON string
1023///
1024/// # Parameters
1025/// * `cluster_id` - The cluster identifier
1026/// * `attribute_id` - The attribute identifier
1027/// * `tlv_value` - The TLV value to decode
1028///
1029/// # Returns
1030/// JSON string representation of the decoded value or error
1031pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
1032    // Verify this is the correct cluster
1033    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
1234/// Get list of all attributes supported by this cluster
1235///
1236/// # Returns
1237/// Vector of tuples containing (attribute_id, attribute_name)
1238pub 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
1293// Event decoders
1294
1295/// Decode WiredFaultChange event (0x00, priority: info)
1296pub 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
1322/// Decode BatFaultChange event (0x01, priority: info)
1323pub 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
1349/// Decode BatChargeFaultChange event (0x02, priority: info)
1350pub 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