1use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11pub fn decode_status(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
15 if let tlv::TlvItemValue::Int(v) = inp {
16 Ok(*v as u8)
17 } else {
18 Err(anyhow::anyhow!("Expected Integer"))
19 }
20}
21
22pub fn decode_order(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
24 if let tlv::TlvItemValue::Int(v) = inp {
25 Ok(*v as u8)
26 } else {
27 Err(anyhow::anyhow!("Expected Integer"))
28 }
29}
30
31pub fn decode_description(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
33 if let tlv::TlvItemValue::String(v) = inp {
34 Ok(v.clone())
35 } else {
36 Err(anyhow::anyhow!("Expected String"))
37 }
38}
39
40pub fn decode_wired_assessed_input_voltage(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u32>> {
42 if let tlv::TlvItemValue::Int(v) = inp {
43 Ok(Some(*v as u32))
44 } else {
45 Ok(None)
46 }
47}
48
49pub fn decode_wired_assessed_input_frequency(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u16>> {
51 if let tlv::TlvItemValue::Int(v) = inp {
52 Ok(Some(*v as u16))
53 } else {
54 Ok(None)
55 }
56}
57
58pub fn decode_wired_current_type(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
60 if let tlv::TlvItemValue::Int(v) = inp {
61 Ok(*v as u8)
62 } else {
63 Err(anyhow::anyhow!("Expected Integer"))
64 }
65}
66
67pub fn decode_wired_assessed_current(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u32>> {
69 if let tlv::TlvItemValue::Int(v) = inp {
70 Ok(Some(*v as u32))
71 } else {
72 Ok(None)
73 }
74}
75
76pub fn decode_wired_nominal_voltage(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
78 if let tlv::TlvItemValue::Int(v) = inp {
79 Ok(*v as u32)
80 } else {
81 Err(anyhow::anyhow!("Expected Integer"))
82 }
83}
84
85pub fn decode_wired_maximum_current(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
87 if let tlv::TlvItemValue::Int(v) = inp {
88 Ok(*v as u32)
89 } else {
90 Err(anyhow::anyhow!("Expected Integer"))
91 }
92}
93
94pub fn decode_wired_present(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
96 if let tlv::TlvItemValue::Bool(v) = inp {
97 Ok(*v)
98 } else {
99 Err(anyhow::anyhow!("Expected Bool"))
100 }
101}
102
103pub fn decode_active_wired_faults(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<u8>> {
105 let mut res = Vec::new();
106 if let tlv::TlvItemValue::List(v) = inp {
107 for item in v {
108 if let tlv::TlvItemValue::Int(i) = &item.value {
109 res.push(*i as u8);
110 }
111 }
112 }
113 Ok(res)
114}
115
116pub fn decode_bat_voltage(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u32>> {
118 if let tlv::TlvItemValue::Int(v) = inp {
119 Ok(Some(*v as u32))
120 } else {
121 Ok(None)
122 }
123}
124
125pub fn decode_bat_percent_remaining(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
127 if let tlv::TlvItemValue::Int(v) = inp {
128 Ok(Some(*v as u8))
129 } else {
130 Ok(None)
131 }
132}
133
134pub fn decode_bat_time_remaining(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u32>> {
136 if let tlv::TlvItemValue::Int(v) = inp {
137 Ok(Some(*v as u32))
138 } else {
139 Ok(None)
140 }
141}
142
143pub fn decode_bat_charge_level(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
145 if let tlv::TlvItemValue::Int(v) = inp {
146 Ok(*v as u8)
147 } else {
148 Err(anyhow::anyhow!("Expected Integer"))
149 }
150}
151
152pub fn decode_bat_replacement_needed(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
154 if let tlv::TlvItemValue::Bool(v) = inp {
155 Ok(*v)
156 } else {
157 Err(anyhow::anyhow!("Expected Bool"))
158 }
159}
160
161pub fn decode_bat_replaceability(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
163 if let tlv::TlvItemValue::Int(v) = inp {
164 Ok(*v as u8)
165 } else {
166 Err(anyhow::anyhow!("Expected Integer"))
167 }
168}
169
170pub fn decode_bat_present(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
172 if let tlv::TlvItemValue::Bool(v) = inp {
173 Ok(*v)
174 } else {
175 Err(anyhow::anyhow!("Expected Bool"))
176 }
177}
178
179pub fn decode_active_bat_faults(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<u8>> {
181 let mut res = Vec::new();
182 if let tlv::TlvItemValue::List(v) = inp {
183 for item in v {
184 if let tlv::TlvItemValue::Int(i) = &item.value {
185 res.push(*i as u8);
186 }
187 }
188 }
189 Ok(res)
190}
191
192pub fn decode_bat_replacement_description(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
194 if let tlv::TlvItemValue::String(v) = inp {
195 Ok(v.clone())
196 } else {
197 Err(anyhow::anyhow!("Expected String"))
198 }
199}
200
201pub fn decode_bat_common_designation(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
203 if let tlv::TlvItemValue::Int(v) = inp {
204 Ok(*v as u8)
205 } else {
206 Err(anyhow::anyhow!("Expected Integer"))
207 }
208}
209
210pub fn decode_bat_ansi_designation(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
212 if let tlv::TlvItemValue::String(v) = inp {
213 Ok(v.clone())
214 } else {
215 Err(anyhow::anyhow!("Expected String"))
216 }
217}
218
219pub fn decode_bat_iec_designation(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
221 if let tlv::TlvItemValue::String(v) = inp {
222 Ok(v.clone())
223 } else {
224 Err(anyhow::anyhow!("Expected String"))
225 }
226}
227
228pub fn decode_bat_approved_chemistry(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
230 if let tlv::TlvItemValue::Int(v) = inp {
231 Ok(*v as u8)
232 } else {
233 Err(anyhow::anyhow!("Expected Integer"))
234 }
235}
236
237pub fn decode_bat_capacity(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
239 if let tlv::TlvItemValue::Int(v) = inp {
240 Ok(*v as u32)
241 } else {
242 Err(anyhow::anyhow!("Expected Integer"))
243 }
244}
245
246pub fn decode_bat_quantity(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
248 if let tlv::TlvItemValue::Int(v) = inp {
249 Ok(*v as u8)
250 } else {
251 Err(anyhow::anyhow!("Expected Integer"))
252 }
253}
254
255pub fn decode_bat_charge_state(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
257 if let tlv::TlvItemValue::Int(v) = inp {
258 Ok(*v as u8)
259 } else {
260 Err(anyhow::anyhow!("Expected Integer"))
261 }
262}
263
264pub fn decode_bat_time_to_full_charge(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u32>> {
266 if let tlv::TlvItemValue::Int(v) = inp {
267 Ok(Some(*v as u32))
268 } else {
269 Ok(None)
270 }
271}
272
273pub fn decode_bat_functional_while_charging(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
275 if let tlv::TlvItemValue::Bool(v) = inp {
276 Ok(*v)
277 } else {
278 Err(anyhow::anyhow!("Expected Bool"))
279 }
280}
281
282pub fn decode_bat_charging_current(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u32>> {
284 if let tlv::TlvItemValue::Int(v) = inp {
285 Ok(Some(*v as u32))
286 } else {
287 Ok(None)
288 }
289}
290
291pub fn decode_active_bat_charge_faults(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<u8>> {
293 let mut res = Vec::new();
294 if let tlv::TlvItemValue::List(v) = inp {
295 for item in v {
296 if let tlv::TlvItemValue::Int(i) = &item.value {
297 res.push(*i as u8);
298 }
299 }
300 }
301 Ok(res)
302}
303
304pub fn decode_endpoint_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<u16>> {
306 let mut res = Vec::new();
307 if let tlv::TlvItemValue::List(v) = inp {
308 for item in v {
309 if let tlv::TlvItemValue::Int(i) = &item.value {
310 res.push(*i as u16);
311 }
312 }
313 }
314 Ok(res)
315}
316
317
318pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
330 if cluster_id != 0x002F {
332 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x002F, got {}\"}}", cluster_id);
333 }
334
335 match attribute_id {
336 0x0000 => {
337 match decode_status(tlv_value) {
338 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
339 Err(e) => format!("{{\"error\": \"{}\"}}", e),
340 }
341 }
342 0x0001 => {
343 match decode_order(tlv_value) {
344 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
345 Err(e) => format!("{{\"error\": \"{}\"}}", e),
346 }
347 }
348 0x0002 => {
349 match decode_description(tlv_value) {
350 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
351 Err(e) => format!("{{\"error\": \"{}\"}}", e),
352 }
353 }
354 0x0003 => {
355 match decode_wired_assessed_input_voltage(tlv_value) {
356 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
357 Err(e) => format!("{{\"error\": \"{}\"}}", e),
358 }
359 }
360 0x0004 => {
361 match decode_wired_assessed_input_frequency(tlv_value) {
362 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
363 Err(e) => format!("{{\"error\": \"{}\"}}", e),
364 }
365 }
366 0x0005 => {
367 match decode_wired_current_type(tlv_value) {
368 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
369 Err(e) => format!("{{\"error\": \"{}\"}}", e),
370 }
371 }
372 0x0006 => {
373 match decode_wired_assessed_current(tlv_value) {
374 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
375 Err(e) => format!("{{\"error\": \"{}\"}}", e),
376 }
377 }
378 0x0007 => {
379 match decode_wired_nominal_voltage(tlv_value) {
380 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
381 Err(e) => format!("{{\"error\": \"{}\"}}", e),
382 }
383 }
384 0x0008 => {
385 match decode_wired_maximum_current(tlv_value) {
386 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
387 Err(e) => format!("{{\"error\": \"{}\"}}", e),
388 }
389 }
390 0x0009 => {
391 match decode_wired_present(tlv_value) {
392 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
393 Err(e) => format!("{{\"error\": \"{}\"}}", e),
394 }
395 }
396 0x000A => {
397 match decode_active_wired_faults(tlv_value) {
398 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
399 Err(e) => format!("{{\"error\": \"{}\"}}", e),
400 }
401 }
402 0x000B => {
403 match decode_bat_voltage(tlv_value) {
404 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
405 Err(e) => format!("{{\"error\": \"{}\"}}", e),
406 }
407 }
408 0x000C => {
409 match decode_bat_percent_remaining(tlv_value) {
410 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
411 Err(e) => format!("{{\"error\": \"{}\"}}", e),
412 }
413 }
414 0x000D => {
415 match decode_bat_time_remaining(tlv_value) {
416 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
417 Err(e) => format!("{{\"error\": \"{}\"}}", e),
418 }
419 }
420 0x000E => {
421 match decode_bat_charge_level(tlv_value) {
422 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
423 Err(e) => format!("{{\"error\": \"{}\"}}", e),
424 }
425 }
426 0x000F => {
427 match decode_bat_replacement_needed(tlv_value) {
428 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
429 Err(e) => format!("{{\"error\": \"{}\"}}", e),
430 }
431 }
432 0x0010 => {
433 match decode_bat_replaceability(tlv_value) {
434 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
435 Err(e) => format!("{{\"error\": \"{}\"}}", e),
436 }
437 }
438 0x0011 => {
439 match decode_bat_present(tlv_value) {
440 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
441 Err(e) => format!("{{\"error\": \"{}\"}}", e),
442 }
443 }
444 0x0012 => {
445 match decode_active_bat_faults(tlv_value) {
446 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
447 Err(e) => format!("{{\"error\": \"{}\"}}", e),
448 }
449 }
450 0x0013 => {
451 match decode_bat_replacement_description(tlv_value) {
452 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
453 Err(e) => format!("{{\"error\": \"{}\"}}", e),
454 }
455 }
456 0x0014 => {
457 match decode_bat_common_designation(tlv_value) {
458 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
459 Err(e) => format!("{{\"error\": \"{}\"}}", e),
460 }
461 }
462 0x0015 => {
463 match decode_bat_ansi_designation(tlv_value) {
464 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
465 Err(e) => format!("{{\"error\": \"{}\"}}", e),
466 }
467 }
468 0x0016 => {
469 match decode_bat_iec_designation(tlv_value) {
470 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
471 Err(e) => format!("{{\"error\": \"{}\"}}", e),
472 }
473 }
474 0x0017 => {
475 match decode_bat_approved_chemistry(tlv_value) {
476 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
477 Err(e) => format!("{{\"error\": \"{}\"}}", e),
478 }
479 }
480 0x0018 => {
481 match decode_bat_capacity(tlv_value) {
482 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
483 Err(e) => format!("{{\"error\": \"{}\"}}", e),
484 }
485 }
486 0x0019 => {
487 match decode_bat_quantity(tlv_value) {
488 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
489 Err(e) => format!("{{\"error\": \"{}\"}}", e),
490 }
491 }
492 0x001A => {
493 match decode_bat_charge_state(tlv_value) {
494 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
495 Err(e) => format!("{{\"error\": \"{}\"}}", e),
496 }
497 }
498 0x001B => {
499 match decode_bat_time_to_full_charge(tlv_value) {
500 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
501 Err(e) => format!("{{\"error\": \"{}\"}}", e),
502 }
503 }
504 0x001C => {
505 match decode_bat_functional_while_charging(tlv_value) {
506 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
507 Err(e) => format!("{{\"error\": \"{}\"}}", e),
508 }
509 }
510 0x001D => {
511 match decode_bat_charging_current(tlv_value) {
512 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
513 Err(e) => format!("{{\"error\": \"{}\"}}", e),
514 }
515 }
516 0x001E => {
517 match decode_active_bat_charge_faults(tlv_value) {
518 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
519 Err(e) => format!("{{\"error\": \"{}\"}}", e),
520 }
521 }
522 0x001F => {
523 match decode_endpoint_list(tlv_value) {
524 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
525 Err(e) => format!("{{\"error\": \"{}\"}}", e),
526 }
527 }
528 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
529 }
530}
531
532pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
537 vec![
538 (0x0000, "Status"),
539 (0x0001, "Order"),
540 (0x0002, "Description"),
541 (0x0003, "WiredAssessedInputVoltage"),
542 (0x0004, "WiredAssessedInputFrequency"),
543 (0x0005, "WiredCurrentType"),
544 (0x0006, "WiredAssessedCurrent"),
545 (0x0007, "WiredNominalVoltage"),
546 (0x0008, "WiredMaximumCurrent"),
547 (0x0009, "WiredPresent"),
548 (0x000A, "ActiveWiredFaults"),
549 (0x000B, "BatVoltage"),
550 (0x000C, "BatPercentRemaining"),
551 (0x000D, "BatTimeRemaining"),
552 (0x000E, "BatChargeLevel"),
553 (0x000F, "BatReplacementNeeded"),
554 (0x0010, "BatReplaceability"),
555 (0x0011, "BatPresent"),
556 (0x0012, "ActiveBatFaults"),
557 (0x0013, "BatReplacementDescription"),
558 (0x0014, "BatCommonDesignation"),
559 (0x0015, "BatANSIDesignation"),
560 (0x0016, "BatIECDesignation"),
561 (0x0017, "BatApprovedChemistry"),
562 (0x0018, "BatCapacity"),
563 (0x0019, "BatQuantity"),
564 (0x001A, "BatChargeState"),
565 (0x001B, "BatTimeToFullCharge"),
566 (0x001C, "BatFunctionalWhileCharging"),
567 (0x001D, "BatChargingCurrent"),
568 (0x001E, "ActiveBatChargeFaults"),
569 (0x001F, "EndpointList"),
570 ]
571}
572