1use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11#[derive(Debug, serde::Serialize)]
14pub struct NetworkInterface {
15 pub name: Option<String>,
16 pub is_operational: Option<bool>,
17 pub off_premise_services_reachable_i_pv4: Option<bool>,
18 pub off_premise_services_reachable_i_pv6: Option<bool>,
19 pub hardware_address: Option<u8>,
20 pub i_pv4_addresses: Option<Vec<u8>>,
21 pub i_pv6_addresses: Option<Vec<u8>>,
22 pub type_: Option<u8>,
23}
24
25pub fn encode_test_event_trigger(enable_key: Vec<u8>, event_trigger: u64) -> anyhow::Result<Vec<u8>> {
29 let tlv = tlv::TlvItemEnc {
30 tag: 0,
31 value: tlv::TlvItemValueEnc::StructInvisible(vec![
32 (0, tlv::TlvItemValueEnc::OctetString(enable_key)).into(),
33 (1, tlv::TlvItemValueEnc::UInt64(event_trigger)).into(),
34 ]),
35 };
36 Ok(tlv.encode()?)
37}
38
39pub fn encode_payload_test_request(enable_key: Vec<u8>, value: u8, count: u16) -> anyhow::Result<Vec<u8>> {
41 let tlv = tlv::TlvItemEnc {
42 tag: 0,
43 value: tlv::TlvItemValueEnc::StructInvisible(vec![
44 (0, tlv::TlvItemValueEnc::OctetString(enable_key)).into(),
45 (1, tlv::TlvItemValueEnc::UInt8(value)).into(),
46 (2, tlv::TlvItemValueEnc::UInt16(count)).into(),
47 ]),
48 };
49 Ok(tlv.encode()?)
50}
51
52pub fn decode_network_interfaces(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<NetworkInterface>> {
56 let mut res = Vec::new();
57 if let tlv::TlvItemValue::List(v) = inp {
58 for item in v {
59 res.push(NetworkInterface {
60 name: item.get_string_owned(&[0]),
61 is_operational: item.get_bool(&[1]),
62 off_premise_services_reachable_i_pv4: item.get_bool(&[2]),
63 off_premise_services_reachable_i_pv6: item.get_bool(&[3]),
64 hardware_address: item.get_int(&[4]).map(|v| v as u8),
65 i_pv4_addresses: {
66 if let Some(tlv::TlvItemValue::List(l)) = item.get(&[5]) {
67 let items: Vec<u8> = l.iter().filter_map(|e| { if let tlv::TlvItemValue::Int(v) = &e.value { Some(*v as u8) } else { None } }).collect();
68 Some(items)
69 } else {
70 None
71 }
72 },
73 i_pv6_addresses: {
74 if let Some(tlv::TlvItemValue::List(l)) = item.get(&[6]) {
75 let items: Vec<u8> = l.iter().filter_map(|e| { if let tlv::TlvItemValue::Int(v) = &e.value { Some(*v as u8) } else { None } }).collect();
76 Some(items)
77 } else {
78 None
79 }
80 },
81 type_: item.get_int(&[7]).map(|v| v as u8),
82 });
83 }
84 }
85 Ok(res)
86}
87
88pub fn decode_reboot_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
90 if let tlv::TlvItemValue::Int(v) = inp {
91 Ok(*v as u16)
92 } else {
93 Err(anyhow::anyhow!("Expected Integer"))
94 }
95}
96
97pub fn decode_up_time(inp: &tlv::TlvItemValue) -> anyhow::Result<u64> {
99 if let tlv::TlvItemValue::Int(v) = inp {
100 Ok(*v)
101 } else {
102 Err(anyhow::anyhow!("Expected Integer"))
103 }
104}
105
106pub fn decode_total_operational_hours(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
108 if let tlv::TlvItemValue::Int(v) = inp {
109 Ok(*v as u32)
110 } else {
111 Err(anyhow::anyhow!("Expected Integer"))
112 }
113}
114
115pub fn decode_boot_reason(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
117 if let tlv::TlvItemValue::Int(v) = inp {
118 Ok(*v as u8)
119 } else {
120 Err(anyhow::anyhow!("Expected Integer"))
121 }
122}
123
124pub fn decode_active_hardware_faults(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<u8>> {
126 let mut res = Vec::new();
127 if let tlv::TlvItemValue::List(v) = inp {
128 for item in v {
129 if let tlv::TlvItemValue::Int(i) = &item.value {
130 res.push(*i as u8);
131 }
132 }
133 }
134 Ok(res)
135}
136
137pub fn decode_active_radio_faults(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<u8>> {
139 let mut res = Vec::new();
140 if let tlv::TlvItemValue::List(v) = inp {
141 for item in v {
142 if let tlv::TlvItemValue::Int(i) = &item.value {
143 res.push(*i as u8);
144 }
145 }
146 }
147 Ok(res)
148}
149
150pub fn decode_active_network_faults(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<u8>> {
152 let mut res = Vec::new();
153 if let tlv::TlvItemValue::List(v) = inp {
154 for item in v {
155 if let tlv::TlvItemValue::Int(i) = &item.value {
156 res.push(*i as u8);
157 }
158 }
159 }
160 Ok(res)
161}
162
163pub fn decode_test_event_triggers_enabled(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
165 if let tlv::TlvItemValue::Bool(v) = inp {
166 Ok(*v)
167 } else {
168 Err(anyhow::anyhow!("Expected Bool"))
169 }
170}
171
172pub fn decode_do_not_use(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
174 if let tlv::TlvItemValue::Int(v) = inp {
175 Ok(*v as u8)
176 } else {
177 Err(anyhow::anyhow!("Expected Integer"))
178 }
179}
180
181
182pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
194 if cluster_id != 0x0033 {
196 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0033, got {}\"}}", cluster_id);
197 }
198
199 match attribute_id {
200 0x0000 => {
201 match decode_network_interfaces(tlv_value) {
202 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
203 Err(e) => format!("{{\"error\": \"{}\"}}", e),
204 }
205 }
206 0x0001 => {
207 match decode_reboot_count(tlv_value) {
208 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
209 Err(e) => format!("{{\"error\": \"{}\"}}", e),
210 }
211 }
212 0x0002 => {
213 match decode_up_time(tlv_value) {
214 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
215 Err(e) => format!("{{\"error\": \"{}\"}}", e),
216 }
217 }
218 0x0003 => {
219 match decode_total_operational_hours(tlv_value) {
220 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
221 Err(e) => format!("{{\"error\": \"{}\"}}", e),
222 }
223 }
224 0x0004 => {
225 match decode_boot_reason(tlv_value) {
226 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
227 Err(e) => format!("{{\"error\": \"{}\"}}", e),
228 }
229 }
230 0x0005 => {
231 match decode_active_hardware_faults(tlv_value) {
232 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
233 Err(e) => format!("{{\"error\": \"{}\"}}", e),
234 }
235 }
236 0x0006 => {
237 match decode_active_radio_faults(tlv_value) {
238 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
239 Err(e) => format!("{{\"error\": \"{}\"}}", e),
240 }
241 }
242 0x0007 => {
243 match decode_active_network_faults(tlv_value) {
244 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
245 Err(e) => format!("{{\"error\": \"{}\"}}", e),
246 }
247 }
248 0x0008 => {
249 match decode_test_event_triggers_enabled(tlv_value) {
250 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
251 Err(e) => format!("{{\"error\": \"{}\"}}", e),
252 }
253 }
254 0x0009 => {
255 match decode_do_not_use(tlv_value) {
256 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
257 Err(e) => format!("{{\"error\": \"{}\"}}", e),
258 }
259 }
260 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
261 }
262}
263
264pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
269 vec![
270 (0x0000, "NetworkInterfaces"),
271 (0x0001, "RebootCount"),
272 (0x0002, "UpTime"),
273 (0x0003, "TotalOperationalHours"),
274 (0x0004, "BootReason"),
275 (0x0005, "ActiveHardwareFaults"),
276 (0x0006, "ActiveRadioFaults"),
277 (0x0007, "ActiveNetworkFaults"),
278 (0x0008, "TestEventTriggersEnabled"),
279 (0x0009, "DoNotUse"),
280 ]
281}
282