matc/clusters/codec/
resource_monitoring.rs1use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11#[derive(Debug, serde::Serialize)]
14pub struct ReplacementProduct {
15 pub product_identifier_type: Option<u8>,
16 pub product_identifier_value: Option<String>,
17}
18
19pub fn decode_condition(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
25 if let tlv::TlvItemValue::Int(v) = inp {
26 Ok(*v as u8)
27 } else {
28 Err(anyhow::anyhow!("Expected Integer"))
29 }
30}
31
32pub fn decode_degradation_direction(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
34 if let tlv::TlvItemValue::Int(v) = inp {
35 Ok(*v as u8)
36 } else {
37 Err(anyhow::anyhow!("Expected Integer"))
38 }
39}
40
41pub fn decode_change_indication(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
43 if let tlv::TlvItemValue::Int(v) = inp {
44 Ok(*v as u8)
45 } else {
46 Err(anyhow::anyhow!("Expected Integer"))
47 }
48}
49
50pub fn decode_in_place_indicator(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
52 if let tlv::TlvItemValue::Bool(v) = inp {
53 Ok(*v)
54 } else {
55 Err(anyhow::anyhow!("Expected Bool"))
56 }
57}
58
59pub fn decode_last_changed_time(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u64>> {
61 if let tlv::TlvItemValue::Int(v) = inp {
62 Ok(Some(*v))
63 } else {
64 Ok(None)
65 }
66}
67
68pub fn decode_replacement_product_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<ReplacementProduct>> {
70 let mut res = Vec::new();
71 if let tlv::TlvItemValue::List(v) = inp {
72 for item in v {
73 res.push(ReplacementProduct {
74 product_identifier_type: item.get_int(&[0]).map(|v| v as u8),
75 product_identifier_value: item.get_string_owned(&[1]),
76 });
77 }
78 }
79 Ok(res)
80}
81
82
83pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
95 if cluster_id != 0x0000 {
97 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0000, got {}\"}}", cluster_id);
98 }
99
100 match attribute_id {
101 0x0000 => {
102 match decode_condition(tlv_value) {
103 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
104 Err(e) => format!("{{\"error\": \"{}\"}}", e),
105 }
106 }
107 0x0001 => {
108 match decode_degradation_direction(tlv_value) {
109 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
110 Err(e) => format!("{{\"error\": \"{}\"}}", e),
111 }
112 }
113 0x0002 => {
114 match decode_change_indication(tlv_value) {
115 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
116 Err(e) => format!("{{\"error\": \"{}\"}}", e),
117 }
118 }
119 0x0003 => {
120 match decode_in_place_indicator(tlv_value) {
121 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
122 Err(e) => format!("{{\"error\": \"{}\"}}", e),
123 }
124 }
125 0x0004 => {
126 match decode_last_changed_time(tlv_value) {
127 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
128 Err(e) => format!("{{\"error\": \"{}\"}}", e),
129 }
130 }
131 0x0005 => {
132 match decode_replacement_product_list(tlv_value) {
133 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
134 Err(e) => format!("{{\"error\": \"{}\"}}", e),
135 }
136 }
137 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
138 }
139}
140
141pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
146 vec![
147 (0x0000, "Condition"),
148 (0x0001, "DegradationDirection"),
149 (0x0002, "ChangeIndication"),
150 (0x0003, "InPlaceIndicator"),
151 (0x0004, "LastChangedTime"),
152 (0x0005, "ReplacementProductList"),
153 ]
154}
155