1use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11#[derive(Debug, serde::Serialize)]
14pub struct CapabilityMinima {
15 pub case_sessions_per_fabric: Option<u16>,
16 pub subscriptions_per_fabric: Option<u16>,
17}
18
19#[derive(Debug, serde::Serialize)]
20pub struct ProductAppearance {
21 pub finish: Option<u8>,
22 pub primary_color: Option<u8>,
23}
24
25pub fn decode_data_model_revision(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
29 if let tlv::TlvItemValue::Int(v) = inp {
30 Ok(*v as u16)
31 } else {
32 Err(anyhow::anyhow!("Expected Integer"))
33 }
34}
35
36pub fn decode_vendor_name(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
38 if let tlv::TlvItemValue::String(v) = inp {
39 Ok(v.clone())
40 } else {
41 Err(anyhow::anyhow!("Expected String"))
42 }
43}
44
45pub fn decode_vendor_id(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
47 if let tlv::TlvItemValue::Int(v) = inp {
48 Ok(*v as u16)
49 } else {
50 Err(anyhow::anyhow!("Expected Integer"))
51 }
52}
53
54pub fn decode_product_name(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
56 if let tlv::TlvItemValue::String(v) = inp {
57 Ok(v.clone())
58 } else {
59 Err(anyhow::anyhow!("Expected String"))
60 }
61}
62
63pub fn decode_product_id(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
65 if let tlv::TlvItemValue::Int(v) = inp {
66 Ok(*v as u16)
67 } else {
68 Err(anyhow::anyhow!("Expected Integer"))
69 }
70}
71
72pub fn decode_node_label(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
74 if let tlv::TlvItemValue::String(v) = inp {
75 Ok(v.clone())
76 } else {
77 Err(anyhow::anyhow!("Expected String"))
78 }
79}
80
81pub fn decode_location(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
83 if let tlv::TlvItemValue::String(v) = inp {
84 Ok(v.clone())
85 } else {
86 Err(anyhow::anyhow!("Expected String"))
87 }
88}
89
90pub fn decode_hardware_version(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
92 if let tlv::TlvItemValue::Int(v) = inp {
93 Ok(*v as u16)
94 } else {
95 Err(anyhow::anyhow!("Expected Integer"))
96 }
97}
98
99pub fn decode_hardware_version_string(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
101 if let tlv::TlvItemValue::String(v) = inp {
102 Ok(v.clone())
103 } else {
104 Err(anyhow::anyhow!("Expected String"))
105 }
106}
107
108pub fn decode_software_version(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
110 if let tlv::TlvItemValue::Int(v) = inp {
111 Ok(*v as u32)
112 } else {
113 Err(anyhow::anyhow!("Expected Integer"))
114 }
115}
116
117pub fn decode_software_version_string(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
119 if let tlv::TlvItemValue::String(v) = inp {
120 Ok(v.clone())
121 } else {
122 Err(anyhow::anyhow!("Expected String"))
123 }
124}
125
126pub fn decode_manufacturing_date(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
128 if let tlv::TlvItemValue::String(v) = inp {
129 Ok(v.clone())
130 } else {
131 Err(anyhow::anyhow!("Expected String"))
132 }
133}
134
135pub fn decode_part_number(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
137 if let tlv::TlvItemValue::String(v) = inp {
138 Ok(v.clone())
139 } else {
140 Err(anyhow::anyhow!("Expected String"))
141 }
142}
143
144pub fn decode_product_url(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
146 if let tlv::TlvItemValue::String(v) = inp {
147 Ok(v.clone())
148 } else {
149 Err(anyhow::anyhow!("Expected String"))
150 }
151}
152
153pub fn decode_product_label(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
155 if let tlv::TlvItemValue::String(v) = inp {
156 Ok(v.clone())
157 } else {
158 Err(anyhow::anyhow!("Expected String"))
159 }
160}
161
162pub fn decode_serial_number(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
164 if let tlv::TlvItemValue::String(v) = inp {
165 Ok(v.clone())
166 } else {
167 Err(anyhow::anyhow!("Expected String"))
168 }
169}
170
171pub fn decode_local_config_disabled(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
173 if let tlv::TlvItemValue::Bool(v) = inp {
174 Ok(*v)
175 } else {
176 Err(anyhow::anyhow!("Expected Bool"))
177 }
178}
179
180pub fn decode_reachable(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
182 if let tlv::TlvItemValue::Bool(v) = inp {
183 Ok(*v)
184 } else {
185 Err(anyhow::anyhow!("Expected Bool"))
186 }
187}
188
189pub fn decode_unique_id(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
191 if let tlv::TlvItemValue::String(v) = inp {
192 Ok(v.clone())
193 } else {
194 Err(anyhow::anyhow!("Expected String"))
195 }
196}
197
198pub fn decode_capability_minima(inp: &tlv::TlvItemValue) -> anyhow::Result<CapabilityMinima> {
200 if let tlv::TlvItemValue::List(_fields) = inp {
201 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
203 Ok(CapabilityMinima {
204 case_sessions_per_fabric: item.get_int(&[0]).map(|v| v as u16),
205 subscriptions_per_fabric: item.get_int(&[1]).map(|v| v as u16),
206 })
207 } else {
208 Err(anyhow::anyhow!("Expected struct fields"))
209 }
210}
211
212pub fn decode_product_appearance(inp: &tlv::TlvItemValue) -> anyhow::Result<ProductAppearance> {
214 if let tlv::TlvItemValue::List(_fields) = inp {
215 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
217 Ok(ProductAppearance {
218 finish: item.get_int(&[0]).map(|v| v as u8),
219 primary_color: item.get_int(&[1]).map(|v| v as u8),
220 })
221 } else {
222 Err(anyhow::anyhow!("Expected struct fields"))
223 }
224}
225
226pub fn decode_specification_version(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
228 if let tlv::TlvItemValue::Int(v) = inp {
229 Ok(*v as u32)
230 } else {
231 Err(anyhow::anyhow!("Expected Integer"))
232 }
233}
234
235pub fn decode_max_paths_per_invoke(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
237 if let tlv::TlvItemValue::Int(v) = inp {
238 Ok(*v as u16)
239 } else {
240 Err(anyhow::anyhow!("Expected Integer"))
241 }
242}
243
244pub fn decode_configuration_version(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
246 if let tlv::TlvItemValue::Int(v) = inp {
247 Ok(*v as u32)
248 } else {
249 Err(anyhow::anyhow!("Expected Integer"))
250 }
251}
252
253
254pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
266 if cluster_id != 0x0028 {
268 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0028, got {}\"}}", cluster_id);
269 }
270
271 match attribute_id {
272 0x0000 => {
273 match decode_data_model_revision(tlv_value) {
274 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
275 Err(e) => format!("{{\"error\": \"{}\"}}", e),
276 }
277 }
278 0x0001 => {
279 match decode_vendor_name(tlv_value) {
280 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
281 Err(e) => format!("{{\"error\": \"{}\"}}", e),
282 }
283 }
284 0x0002 => {
285 match decode_vendor_id(tlv_value) {
286 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
287 Err(e) => format!("{{\"error\": \"{}\"}}", e),
288 }
289 }
290 0x0003 => {
291 match decode_product_name(tlv_value) {
292 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
293 Err(e) => format!("{{\"error\": \"{}\"}}", e),
294 }
295 }
296 0x0004 => {
297 match decode_product_id(tlv_value) {
298 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
299 Err(e) => format!("{{\"error\": \"{}\"}}", e),
300 }
301 }
302 0x0005 => {
303 match decode_node_label(tlv_value) {
304 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
305 Err(e) => format!("{{\"error\": \"{}\"}}", e),
306 }
307 }
308 0x0006 => {
309 match decode_location(tlv_value) {
310 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
311 Err(e) => format!("{{\"error\": \"{}\"}}", e),
312 }
313 }
314 0x0007 => {
315 match decode_hardware_version(tlv_value) {
316 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
317 Err(e) => format!("{{\"error\": \"{}\"}}", e),
318 }
319 }
320 0x0008 => {
321 match decode_hardware_version_string(tlv_value) {
322 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
323 Err(e) => format!("{{\"error\": \"{}\"}}", e),
324 }
325 }
326 0x0009 => {
327 match decode_software_version(tlv_value) {
328 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
329 Err(e) => format!("{{\"error\": \"{}\"}}", e),
330 }
331 }
332 0x000A => {
333 match decode_software_version_string(tlv_value) {
334 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
335 Err(e) => format!("{{\"error\": \"{}\"}}", e),
336 }
337 }
338 0x000B => {
339 match decode_manufacturing_date(tlv_value) {
340 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
341 Err(e) => format!("{{\"error\": \"{}\"}}", e),
342 }
343 }
344 0x000C => {
345 match decode_part_number(tlv_value) {
346 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
347 Err(e) => format!("{{\"error\": \"{}\"}}", e),
348 }
349 }
350 0x000D => {
351 match decode_product_url(tlv_value) {
352 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
353 Err(e) => format!("{{\"error\": \"{}\"}}", e),
354 }
355 }
356 0x000E => {
357 match decode_product_label(tlv_value) {
358 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
359 Err(e) => format!("{{\"error\": \"{}\"}}", e),
360 }
361 }
362 0x000F => {
363 match decode_serial_number(tlv_value) {
364 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
365 Err(e) => format!("{{\"error\": \"{}\"}}", e),
366 }
367 }
368 0x0010 => {
369 match decode_local_config_disabled(tlv_value) {
370 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
371 Err(e) => format!("{{\"error\": \"{}\"}}", e),
372 }
373 }
374 0x0011 => {
375 match decode_reachable(tlv_value) {
376 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
377 Err(e) => format!("{{\"error\": \"{}\"}}", e),
378 }
379 }
380 0x0012 => {
381 match decode_unique_id(tlv_value) {
382 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
383 Err(e) => format!("{{\"error\": \"{}\"}}", e),
384 }
385 }
386 0x0013 => {
387 match decode_capability_minima(tlv_value) {
388 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
389 Err(e) => format!("{{\"error\": \"{}\"}}", e),
390 }
391 }
392 0x0014 => {
393 match decode_product_appearance(tlv_value) {
394 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
395 Err(e) => format!("{{\"error\": \"{}\"}}", e),
396 }
397 }
398 0x0015 => {
399 match decode_specification_version(tlv_value) {
400 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
401 Err(e) => format!("{{\"error\": \"{}\"}}", e),
402 }
403 }
404 0x0016 => {
405 match decode_max_paths_per_invoke(tlv_value) {
406 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
407 Err(e) => format!("{{\"error\": \"{}\"}}", e),
408 }
409 }
410 0x0018 => {
411 match decode_configuration_version(tlv_value) {
412 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
413 Err(e) => format!("{{\"error\": \"{}\"}}", e),
414 }
415 }
416 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
417 }
418}
419
420pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
425 vec![
426 (0x0000, "DataModelRevision"),
427 (0x0001, "VendorName"),
428 (0x0002, "VendorID"),
429 (0x0003, "ProductName"),
430 (0x0004, "ProductID"),
431 (0x0005, "NodeLabel"),
432 (0x0006, "Location"),
433 (0x0007, "HardwareVersion"),
434 (0x0008, "HardwareVersionString"),
435 (0x0009, "SoftwareVersion"),
436 (0x000A, "SoftwareVersionString"),
437 (0x000B, "ManufacturingDate"),
438 (0x000C, "PartNumber"),
439 (0x000D, "ProductURL"),
440 (0x000E, "ProductLabel"),
441 (0x000F, "SerialNumber"),
442 (0x0010, "LocalConfigDisabled"),
443 (0x0011, "Reachable"),
444 (0x0012, "UniqueID"),
445 (0x0013, "CapabilityMinima"),
446 (0x0014, "ProductAppearance"),
447 (0x0015, "SpecificationVersion"),
448 (0x0016, "MaxPathsPerInvoke"),
449 (0x0018, "ConfigurationVersion"),
450 ]
451}
452