matc/clusters/codec/
diagnostics_thread.rs

1//! Matter TLV encoders and decoders for Thread Network Diagnostics Cluster
2//! Cluster ID: 0x0035
3//!
4//! This file is automatically generated from DiagnosticsThread.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 ConnectionStatus {
16    /// Node is connected
17    Connected = 0,
18    /// Node is not connected
19    Notconnected = 1,
20}
21
22impl ConnectionStatus {
23    /// Convert from u8 value
24    pub fn from_u8(value: u8) -> Option<Self> {
25        match value {
26            0 => Some(ConnectionStatus::Connected),
27            1 => Some(ConnectionStatus::Notconnected),
28            _ => None,
29        }
30    }
31
32    /// Convert to u8 value
33    pub fn to_u8(self) -> u8 {
34        self as u8
35    }
36}
37
38impl From<ConnectionStatus> for u8 {
39    fn from(val: ConnectionStatus) -> Self {
40        val as u8
41    }
42}
43
44#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
45#[repr(u8)]
46pub enum NetworkFault {
47    /// Indicates an unspecified fault.
48    Unspecified = 0,
49    /// Indicates the Thread link is down.
50    Linkdown = 1,
51    /// Indicates there has been Thread hardware failure.
52    Hardwarefailure = 2,
53    /// Indicates the Thread network is jammed.
54    Networkjammed = 3,
55}
56
57impl NetworkFault {
58    /// Convert from u8 value
59    pub fn from_u8(value: u8) -> Option<Self> {
60        match value {
61            0 => Some(NetworkFault::Unspecified),
62            1 => Some(NetworkFault::Linkdown),
63            2 => Some(NetworkFault::Hardwarefailure),
64            3 => Some(NetworkFault::Networkjammed),
65            _ => None,
66        }
67    }
68
69    /// Convert to u8 value
70    pub fn to_u8(self) -> u8 {
71        self as u8
72    }
73}
74
75impl From<NetworkFault> for u8 {
76    fn from(val: NetworkFault) -> Self {
77        val as u8
78    }
79}
80
81#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
82#[repr(u8)]
83pub enum RoutingRole {
84    /// Unspecified routing role.
85    Unspecified = 0,
86    /// The Node does not currently have a role as a result of the Thread interface not currently being configured or operational.
87    Unassigned = 1,
88    /// The Node acts as a Sleepy End Device with RX-off-when-idle sleepy radio behavior.
89    Sleepyenddevice = 2,
90    /// The Node acts as an End Device without RX-off-when-idle sleepy radio behavior.
91    Enddevice = 3,
92    /// The Node acts as an Router Eligible End Device.
93    Reed = 4,
94    /// The Node acts as a Router Device.
95    Router = 5,
96    /// The Node acts as a Leader Device.
97    Leader = 6,
98}
99
100impl RoutingRole {
101    /// Convert from u8 value
102    pub fn from_u8(value: u8) -> Option<Self> {
103        match value {
104            0 => Some(RoutingRole::Unspecified),
105            1 => Some(RoutingRole::Unassigned),
106            2 => Some(RoutingRole::Sleepyenddevice),
107            3 => Some(RoutingRole::Enddevice),
108            4 => Some(RoutingRole::Reed),
109            5 => Some(RoutingRole::Router),
110            6 => Some(RoutingRole::Leader),
111            _ => None,
112        }
113    }
114
115    /// Convert to u8 value
116    pub fn to_u8(self) -> u8 {
117        self as u8
118    }
119}
120
121impl From<RoutingRole> for u8 {
122    fn from(val: RoutingRole) -> Self {
123        val as u8
124    }
125}
126
127// Struct definitions
128
129#[derive(Debug, serde::Serialize)]
130pub struct NeighborTable {
131    pub ext_address: Option<u64>,
132    pub age: Option<u32>,
133    pub rloc16: Option<u16>,
134    pub link_frame_counter: Option<u32>,
135    pub mle_frame_counter: Option<u32>,
136    pub lqi: Option<u8>,
137    pub average_rssi: Option<i8>,
138    pub last_rssi: Option<i8>,
139    pub frame_error_rate: Option<u8>,
140    pub message_error_rate: Option<u8>,
141    pub rx_on_when_idle: Option<bool>,
142    pub full_thread_device: Option<bool>,
143    pub full_network_data: Option<bool>,
144    pub is_child: Option<bool>,
145}
146
147#[derive(Debug, serde::Serialize)]
148pub struct OperationalDatasetComponents {
149    pub active_timestamp_present: Option<bool>,
150    pub pending_timestamp_present: Option<bool>,
151    pub master_key_present: Option<bool>,
152    pub network_name_present: Option<bool>,
153    pub extended_pan_id_present: Option<bool>,
154    pub mesh_local_prefix_present: Option<bool>,
155    pub delay_present: Option<bool>,
156    pub pan_id_present: Option<bool>,
157    pub channel_present: Option<bool>,
158    pub pskc_present: Option<bool>,
159    pub security_policy_present: Option<bool>,
160    pub channel_mask_present: Option<bool>,
161}
162
163#[derive(Debug, serde::Serialize)]
164pub struct RouteTable {
165    pub ext_address: Option<u64>,
166    pub rloc16: Option<u16>,
167    pub router_id: Option<u8>,
168    pub next_hop: Option<u8>,
169    pub path_cost: Option<u8>,
170    pub lqi_in: Option<u8>,
171    pub lqi_out: Option<u8>,
172    pub age: Option<u8>,
173    pub allocated: Option<bool>,
174    pub link_established: Option<bool>,
175}
176
177#[derive(Debug, serde::Serialize)]
178pub struct SecurityPolicy {
179    pub rotation_time: Option<u16>,
180    pub flags: Option<u16>,
181}
182
183// Command encoders
184
185// Attribute decoders
186
187/// Decode Channel attribute (0x0000)
188pub fn decode_channel(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u16>> {
189    if let tlv::TlvItemValue::Int(v) = inp {
190        Ok(Some(*v as u16))
191    } else {
192        Ok(None)
193    }
194}
195
196/// Decode RoutingRole attribute (0x0001)
197pub fn decode_routing_role(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<RoutingRole>> {
198    if let tlv::TlvItemValue::Int(v) = inp {
199        Ok(RoutingRole::from_u8(*v as u8))
200    } else {
201        Ok(None)
202    }
203}
204
205/// Decode NetworkName attribute (0x0002)
206pub fn decode_network_name(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<String>> {
207    if let tlv::TlvItemValue::String(v) = inp {
208        Ok(Some(v.clone()))
209    } else {
210        Ok(None)
211    }
212}
213
214/// Decode PanId attribute (0x0003)
215pub fn decode_pan_id(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u16>> {
216    if let tlv::TlvItemValue::Int(v) = inp {
217        Ok(Some(*v as u16))
218    } else {
219        Ok(None)
220    }
221}
222
223/// Decode ExtendedPanId attribute (0x0004)
224pub fn decode_extended_pan_id(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u64>> {
225    if let tlv::TlvItemValue::Int(v) = inp {
226        Ok(Some(*v))
227    } else {
228        Ok(None)
229    }
230}
231
232/// Decode MeshLocalPrefix attribute (0x0005)
233pub fn decode_mesh_local_prefix(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
234    if let tlv::TlvItemValue::Int(v) = inp {
235        Ok(Some(*v as u8))
236    } else {
237        Ok(None)
238    }
239}
240
241/// Decode OverrunCount attribute (0x0006)
242pub fn decode_overrun_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u64> {
243    if let tlv::TlvItemValue::Int(v) = inp {
244        Ok(*v)
245    } else {
246        Err(anyhow::anyhow!("Expected UInt64"))
247    }
248}
249
250/// Decode NeighborTable attribute (0x0007)
251pub fn decode_neighbor_table(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<NeighborTable>> {
252    let mut res = Vec::new();
253    if let tlv::TlvItemValue::List(v) = inp {
254        for item in v {
255            res.push(NeighborTable {
256                ext_address: item.get_int(&[0]),
257                age: item.get_int(&[1]).map(|v| v as u32),
258                rloc16: item.get_int(&[2]).map(|v| v as u16),
259                link_frame_counter: item.get_int(&[3]).map(|v| v as u32),
260                mle_frame_counter: item.get_int(&[4]).map(|v| v as u32),
261                lqi: item.get_int(&[5]).map(|v| v as u8),
262                average_rssi: item.get_int(&[6]).map(|v| v as i8),
263                last_rssi: item.get_int(&[7]).map(|v| v as i8),
264                frame_error_rate: item.get_int(&[8]).map(|v| v as u8),
265                message_error_rate: item.get_int(&[9]).map(|v| v as u8),
266                rx_on_when_idle: item.get_bool(&[10]),
267                full_thread_device: item.get_bool(&[11]),
268                full_network_data: item.get_bool(&[12]),
269                is_child: item.get_bool(&[13]),
270            });
271        }
272    }
273    Ok(res)
274}
275
276/// Decode RouteTable attribute (0x0008)
277pub fn decode_route_table(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<RouteTable>> {
278    let mut res = Vec::new();
279    if let tlv::TlvItemValue::List(v) = inp {
280        for item in v {
281            res.push(RouteTable {
282                ext_address: item.get_int(&[0]),
283                rloc16: item.get_int(&[1]).map(|v| v as u16),
284                router_id: item.get_int(&[2]).map(|v| v as u8),
285                next_hop: item.get_int(&[3]).map(|v| v as u8),
286                path_cost: item.get_int(&[4]).map(|v| v as u8),
287                lqi_in: item.get_int(&[5]).map(|v| v as u8),
288                lqi_out: item.get_int(&[6]).map(|v| v as u8),
289                age: item.get_int(&[7]).map(|v| v as u8),
290                allocated: item.get_bool(&[8]),
291                link_established: item.get_bool(&[9]),
292            });
293        }
294    }
295    Ok(res)
296}
297
298/// Decode PartitionId attribute (0x0009)
299pub fn decode_partition_id(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u32>> {
300    if let tlv::TlvItemValue::Int(v) = inp {
301        Ok(Some(*v as u32))
302    } else {
303        Ok(None)
304    }
305}
306
307/// Decode Weighting attribute (0x000A)
308pub fn decode_weighting(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u16>> {
309    if let tlv::TlvItemValue::Int(v) = inp {
310        Ok(Some(*v as u16))
311    } else {
312        Ok(None)
313    }
314}
315
316/// Decode DataVersion attribute (0x000B)
317pub fn decode_data_version(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u16>> {
318    if let tlv::TlvItemValue::Int(v) = inp {
319        Ok(Some(*v as u16))
320    } else {
321        Ok(None)
322    }
323}
324
325/// Decode StableDataVersion attribute (0x000C)
326pub fn decode_stable_data_version(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u16>> {
327    if let tlv::TlvItemValue::Int(v) = inp {
328        Ok(Some(*v as u16))
329    } else {
330        Ok(None)
331    }
332}
333
334/// Decode LeaderRouterId attribute (0x000D)
335pub fn decode_leader_router_id(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
336    if let tlv::TlvItemValue::Int(v) = inp {
337        Ok(Some(*v as u8))
338    } else {
339        Ok(None)
340    }
341}
342
343/// Decode DetachedRoleCount attribute (0x000E)
344pub fn decode_detached_role_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
345    if let tlv::TlvItemValue::Int(v) = inp {
346        Ok(*v as u16)
347    } else {
348        Err(anyhow::anyhow!("Expected UInt16"))
349    }
350}
351
352/// Decode ChildRoleCount attribute (0x000F)
353pub fn decode_child_role_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
354    if let tlv::TlvItemValue::Int(v) = inp {
355        Ok(*v as u16)
356    } else {
357        Err(anyhow::anyhow!("Expected UInt16"))
358    }
359}
360
361/// Decode RouterRoleCount attribute (0x0010)
362pub fn decode_router_role_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
363    if let tlv::TlvItemValue::Int(v) = inp {
364        Ok(*v as u16)
365    } else {
366        Err(anyhow::anyhow!("Expected UInt16"))
367    }
368}
369
370/// Decode LeaderRoleCount attribute (0x0011)
371pub fn decode_leader_role_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
372    if let tlv::TlvItemValue::Int(v) = inp {
373        Ok(*v as u16)
374    } else {
375        Err(anyhow::anyhow!("Expected UInt16"))
376    }
377}
378
379/// Decode AttachAttemptCount attribute (0x0012)
380pub fn decode_attach_attempt_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
381    if let tlv::TlvItemValue::Int(v) = inp {
382        Ok(*v as u16)
383    } else {
384        Err(anyhow::anyhow!("Expected UInt16"))
385    }
386}
387
388/// Decode PartitionIdChangeCount attribute (0x0013)
389pub fn decode_partition_id_change_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
390    if let tlv::TlvItemValue::Int(v) = inp {
391        Ok(*v as u16)
392    } else {
393        Err(anyhow::anyhow!("Expected UInt16"))
394    }
395}
396
397/// Decode BetterPartitionAttachAttemptCount attribute (0x0014)
398pub fn decode_better_partition_attach_attempt_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
399    if let tlv::TlvItemValue::Int(v) = inp {
400        Ok(*v as u16)
401    } else {
402        Err(anyhow::anyhow!("Expected UInt16"))
403    }
404}
405
406/// Decode ParentChangeCount attribute (0x0015)
407pub fn decode_parent_change_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
408    if let tlv::TlvItemValue::Int(v) = inp {
409        Ok(*v as u16)
410    } else {
411        Err(anyhow::anyhow!("Expected UInt16"))
412    }
413}
414
415/// Decode TxTotalCount attribute (0x0016)
416pub fn decode_tx_total_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
417    if let tlv::TlvItemValue::Int(v) = inp {
418        Ok(*v as u32)
419    } else {
420        Err(anyhow::anyhow!("Expected UInt32"))
421    }
422}
423
424/// Decode TxUnicastCount attribute (0x0017)
425pub fn decode_tx_unicast_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
426    if let tlv::TlvItemValue::Int(v) = inp {
427        Ok(*v as u32)
428    } else {
429        Err(anyhow::anyhow!("Expected UInt32"))
430    }
431}
432
433/// Decode TxBroadcastCount attribute (0x0018)
434pub fn decode_tx_broadcast_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
435    if let tlv::TlvItemValue::Int(v) = inp {
436        Ok(*v as u32)
437    } else {
438        Err(anyhow::anyhow!("Expected UInt32"))
439    }
440}
441
442/// Decode TxAckRequestedCount attribute (0x0019)
443pub fn decode_tx_ack_requested_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
444    if let tlv::TlvItemValue::Int(v) = inp {
445        Ok(*v as u32)
446    } else {
447        Err(anyhow::anyhow!("Expected UInt32"))
448    }
449}
450
451/// Decode TxAckedCount attribute (0x001A)
452pub fn decode_tx_acked_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
453    if let tlv::TlvItemValue::Int(v) = inp {
454        Ok(*v as u32)
455    } else {
456        Err(anyhow::anyhow!("Expected UInt32"))
457    }
458}
459
460/// Decode TxNoAckRequestedCount attribute (0x001B)
461pub fn decode_tx_no_ack_requested_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
462    if let tlv::TlvItemValue::Int(v) = inp {
463        Ok(*v as u32)
464    } else {
465        Err(anyhow::anyhow!("Expected UInt32"))
466    }
467}
468
469/// Decode TxDataCount attribute (0x001C)
470pub fn decode_tx_data_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
471    if let tlv::TlvItemValue::Int(v) = inp {
472        Ok(*v as u32)
473    } else {
474        Err(anyhow::anyhow!("Expected UInt32"))
475    }
476}
477
478/// Decode TxDataPollCount attribute (0x001D)
479pub fn decode_tx_data_poll_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
480    if let tlv::TlvItemValue::Int(v) = inp {
481        Ok(*v as u32)
482    } else {
483        Err(anyhow::anyhow!("Expected UInt32"))
484    }
485}
486
487/// Decode TxBeaconCount attribute (0x001E)
488pub fn decode_tx_beacon_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
489    if let tlv::TlvItemValue::Int(v) = inp {
490        Ok(*v as u32)
491    } else {
492        Err(anyhow::anyhow!("Expected UInt32"))
493    }
494}
495
496/// Decode TxBeaconRequestCount attribute (0x001F)
497pub fn decode_tx_beacon_request_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
498    if let tlv::TlvItemValue::Int(v) = inp {
499        Ok(*v as u32)
500    } else {
501        Err(anyhow::anyhow!("Expected UInt32"))
502    }
503}
504
505/// Decode TxOtherCount attribute (0x0020)
506pub fn decode_tx_other_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
507    if let tlv::TlvItemValue::Int(v) = inp {
508        Ok(*v as u32)
509    } else {
510        Err(anyhow::anyhow!("Expected UInt32"))
511    }
512}
513
514/// Decode TxRetryCount attribute (0x0021)
515pub fn decode_tx_retry_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
516    if let tlv::TlvItemValue::Int(v) = inp {
517        Ok(*v as u32)
518    } else {
519        Err(anyhow::anyhow!("Expected UInt32"))
520    }
521}
522
523/// Decode TxDirectMaxRetryExpiryCount attribute (0x0022)
524pub fn decode_tx_direct_max_retry_expiry_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
525    if let tlv::TlvItemValue::Int(v) = inp {
526        Ok(*v as u32)
527    } else {
528        Err(anyhow::anyhow!("Expected UInt32"))
529    }
530}
531
532/// Decode TxIndirectMaxRetryExpiryCount attribute (0x0023)
533pub fn decode_tx_indirect_max_retry_expiry_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
534    if let tlv::TlvItemValue::Int(v) = inp {
535        Ok(*v as u32)
536    } else {
537        Err(anyhow::anyhow!("Expected UInt32"))
538    }
539}
540
541/// Decode TxErrCcaCount attribute (0x0024)
542pub fn decode_tx_err_cca_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
543    if let tlv::TlvItemValue::Int(v) = inp {
544        Ok(*v as u32)
545    } else {
546        Err(anyhow::anyhow!("Expected UInt32"))
547    }
548}
549
550/// Decode TxErrAbortCount attribute (0x0025)
551pub fn decode_tx_err_abort_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
552    if let tlv::TlvItemValue::Int(v) = inp {
553        Ok(*v as u32)
554    } else {
555        Err(anyhow::anyhow!("Expected UInt32"))
556    }
557}
558
559/// Decode TxErrBusyChannelCount attribute (0x0026)
560pub fn decode_tx_err_busy_channel_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
561    if let tlv::TlvItemValue::Int(v) = inp {
562        Ok(*v as u32)
563    } else {
564        Err(anyhow::anyhow!("Expected UInt32"))
565    }
566}
567
568/// Decode RxTotalCount attribute (0x0027)
569pub fn decode_rx_total_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
570    if let tlv::TlvItemValue::Int(v) = inp {
571        Ok(*v as u32)
572    } else {
573        Err(anyhow::anyhow!("Expected UInt32"))
574    }
575}
576
577/// Decode RxUnicastCount attribute (0x0028)
578pub fn decode_rx_unicast_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
579    if let tlv::TlvItemValue::Int(v) = inp {
580        Ok(*v as u32)
581    } else {
582        Err(anyhow::anyhow!("Expected UInt32"))
583    }
584}
585
586/// Decode RxBroadcastCount attribute (0x0029)
587pub fn decode_rx_broadcast_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
588    if let tlv::TlvItemValue::Int(v) = inp {
589        Ok(*v as u32)
590    } else {
591        Err(anyhow::anyhow!("Expected UInt32"))
592    }
593}
594
595/// Decode RxDataCount attribute (0x002A)
596pub fn decode_rx_data_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
597    if let tlv::TlvItemValue::Int(v) = inp {
598        Ok(*v as u32)
599    } else {
600        Err(anyhow::anyhow!("Expected UInt32"))
601    }
602}
603
604/// Decode RxDataPollCount attribute (0x002B)
605pub fn decode_rx_data_poll_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
606    if let tlv::TlvItemValue::Int(v) = inp {
607        Ok(*v as u32)
608    } else {
609        Err(anyhow::anyhow!("Expected UInt32"))
610    }
611}
612
613/// Decode RxBeaconCount attribute (0x002C)
614pub fn decode_rx_beacon_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
615    if let tlv::TlvItemValue::Int(v) = inp {
616        Ok(*v as u32)
617    } else {
618        Err(anyhow::anyhow!("Expected UInt32"))
619    }
620}
621
622/// Decode RxBeaconRequestCount attribute (0x002D)
623pub fn decode_rx_beacon_request_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
624    if let tlv::TlvItemValue::Int(v) = inp {
625        Ok(*v as u32)
626    } else {
627        Err(anyhow::anyhow!("Expected UInt32"))
628    }
629}
630
631/// Decode RxOtherCount attribute (0x002E)
632pub fn decode_rx_other_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
633    if let tlv::TlvItemValue::Int(v) = inp {
634        Ok(*v as u32)
635    } else {
636        Err(anyhow::anyhow!("Expected UInt32"))
637    }
638}
639
640/// Decode RxAddressFilteredCount attribute (0x002F)
641pub fn decode_rx_address_filtered_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
642    if let tlv::TlvItemValue::Int(v) = inp {
643        Ok(*v as u32)
644    } else {
645        Err(anyhow::anyhow!("Expected UInt32"))
646    }
647}
648
649/// Decode RxDestAddrFilteredCount attribute (0x0030)
650pub fn decode_rx_dest_addr_filtered_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
651    if let tlv::TlvItemValue::Int(v) = inp {
652        Ok(*v as u32)
653    } else {
654        Err(anyhow::anyhow!("Expected UInt32"))
655    }
656}
657
658/// Decode RxDuplicatedCount attribute (0x0031)
659pub fn decode_rx_duplicated_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
660    if let tlv::TlvItemValue::Int(v) = inp {
661        Ok(*v as u32)
662    } else {
663        Err(anyhow::anyhow!("Expected UInt32"))
664    }
665}
666
667/// Decode RxErrNoFrameCount attribute (0x0032)
668pub fn decode_rx_err_no_frame_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
669    if let tlv::TlvItemValue::Int(v) = inp {
670        Ok(*v as u32)
671    } else {
672        Err(anyhow::anyhow!("Expected UInt32"))
673    }
674}
675
676/// Decode RxErrUnknownNeighborCount attribute (0x0033)
677pub fn decode_rx_err_unknown_neighbor_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
678    if let tlv::TlvItemValue::Int(v) = inp {
679        Ok(*v as u32)
680    } else {
681        Err(anyhow::anyhow!("Expected UInt32"))
682    }
683}
684
685/// Decode RxErrInvalidSrcAddrCount attribute (0x0034)
686pub fn decode_rx_err_invalid_src_addr_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
687    if let tlv::TlvItemValue::Int(v) = inp {
688        Ok(*v as u32)
689    } else {
690        Err(anyhow::anyhow!("Expected UInt32"))
691    }
692}
693
694/// Decode RxErrSecCount attribute (0x0035)
695pub fn decode_rx_err_sec_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
696    if let tlv::TlvItemValue::Int(v) = inp {
697        Ok(*v as u32)
698    } else {
699        Err(anyhow::anyhow!("Expected UInt32"))
700    }
701}
702
703/// Decode RxErrFcsCount attribute (0x0036)
704pub fn decode_rx_err_fcs_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
705    if let tlv::TlvItemValue::Int(v) = inp {
706        Ok(*v as u32)
707    } else {
708        Err(anyhow::anyhow!("Expected UInt32"))
709    }
710}
711
712/// Decode RxErrOtherCount attribute (0x0037)
713pub fn decode_rx_err_other_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
714    if let tlv::TlvItemValue::Int(v) = inp {
715        Ok(*v as u32)
716    } else {
717        Err(anyhow::anyhow!("Expected UInt32"))
718    }
719}
720
721/// Decode ActiveTimestamp attribute (0x0038)
722pub fn decode_active_timestamp(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u64>> {
723    if let tlv::TlvItemValue::Int(v) = inp {
724        Ok(Some(*v))
725    } else {
726        Ok(None)
727    }
728}
729
730/// Decode PendingTimestamp attribute (0x0039)
731pub fn decode_pending_timestamp(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u64>> {
732    if let tlv::TlvItemValue::Int(v) = inp {
733        Ok(Some(*v))
734    } else {
735        Ok(None)
736    }
737}
738
739/// Decode Delay attribute (0x003A)
740pub fn decode_delay(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u32>> {
741    if let tlv::TlvItemValue::Int(v) = inp {
742        Ok(Some(*v as u32))
743    } else {
744        Ok(None)
745    }
746}
747
748/// Decode SecurityPolicy attribute (0x003B)
749pub fn decode_security_policy(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<SecurityPolicy>> {
750    if let tlv::TlvItemValue::List(_fields) = inp {
751        // Struct with fields
752        let item = tlv::TlvItem { tag: 0, value: inp.clone() };
753        Ok(Some(SecurityPolicy {
754                rotation_time: item.get_int(&[0]).map(|v| v as u16),
755                flags: item.get_int(&[1]).map(|v| v as u16),
756        }))
757    //} else if let tlv::TlvItemValue::Null = inp {
758    //    // Null value for nullable struct
759    //    Ok(None)
760    } else {
761    Ok(None)
762    //    Err(anyhow::anyhow!("Expected struct fields or null"))
763    }
764}
765
766/// Decode ChannelPage0Mask attribute (0x003C)
767pub fn decode_channel_page0_mask(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<Vec<u8>>> {
768    if let tlv::TlvItemValue::OctetString(v) = inp {
769        Ok(Some(v.clone()))
770    } else {
771        Ok(None)
772    }
773}
774
775/// Decode OperationalDatasetComponents attribute (0x003D)
776pub fn decode_operational_dataset_components(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<OperationalDatasetComponents>> {
777    if let tlv::TlvItemValue::List(_fields) = inp {
778        // Struct with fields
779        let item = tlv::TlvItem { tag: 0, value: inp.clone() };
780        Ok(Some(OperationalDatasetComponents {
781                active_timestamp_present: item.get_bool(&[0]),
782                pending_timestamp_present: item.get_bool(&[1]),
783                master_key_present: item.get_bool(&[2]),
784                network_name_present: item.get_bool(&[3]),
785                extended_pan_id_present: item.get_bool(&[4]),
786                mesh_local_prefix_present: item.get_bool(&[5]),
787                delay_present: item.get_bool(&[6]),
788                pan_id_present: item.get_bool(&[7]),
789                channel_present: item.get_bool(&[8]),
790                pskc_present: item.get_bool(&[9]),
791                security_policy_present: item.get_bool(&[10]),
792                channel_mask_present: item.get_bool(&[11]),
793        }))
794    //} else if let tlv::TlvItemValue::Null = inp {
795    //    // Null value for nullable struct
796    //    Ok(None)
797    } else {
798    Ok(None)
799    //    Err(anyhow::anyhow!("Expected struct fields or null"))
800    }
801}
802
803/// Decode ActiveNetworkFaultsList attribute (0x003E)
804pub fn decode_active_network_faults_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<NetworkFault>> {
805    let mut res = Vec::new();
806    if let tlv::TlvItemValue::List(v) = inp {
807        for item in v {
808            if let tlv::TlvItemValue::Int(i) = &item.value {
809                if let Some(enum_val) = NetworkFault::from_u8(*i as u8) {
810                    res.push(enum_val);
811                }
812            }
813        }
814    }
815    Ok(res)
816}
817
818/// Decode ExtAddress attribute (0x003F)
819pub fn decode_ext_address(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u64>> {
820    if let tlv::TlvItemValue::Int(v) = inp {
821        Ok(Some(*v))
822    } else {
823        Ok(None)
824    }
825}
826
827/// Decode Rloc16 attribute (0x0040)
828pub fn decode_rloc16(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u16>> {
829    if let tlv::TlvItemValue::Int(v) = inp {
830        Ok(Some(*v as u16))
831    } else {
832        Ok(None)
833    }
834}
835
836
837// JSON dispatcher function
838
839/// Decode attribute value and return as JSON string
840///
841/// # Parameters
842/// * `cluster_id` - The cluster identifier
843/// * `attribute_id` - The attribute identifier
844/// * `tlv_value` - The TLV value to decode
845///
846/// # Returns
847/// JSON string representation of the decoded value or error
848pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
849    // Verify this is the correct cluster
850    if cluster_id != 0x0035 {
851        return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0035, got {}\"}}", cluster_id);
852    }
853
854    match attribute_id {
855        0x0000 => {
856            match decode_channel(tlv_value) {
857                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
858                Err(e) => format!("{{\"error\": \"{}\"}}", e),
859            }
860        }
861        0x0001 => {
862            match decode_routing_role(tlv_value) {
863                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
864                Err(e) => format!("{{\"error\": \"{}\"}}", e),
865            }
866        }
867        0x0002 => {
868            match decode_network_name(tlv_value) {
869                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
870                Err(e) => format!("{{\"error\": \"{}\"}}", e),
871            }
872        }
873        0x0003 => {
874            match decode_pan_id(tlv_value) {
875                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
876                Err(e) => format!("{{\"error\": \"{}\"}}", e),
877            }
878        }
879        0x0004 => {
880            match decode_extended_pan_id(tlv_value) {
881                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
882                Err(e) => format!("{{\"error\": \"{}\"}}", e),
883            }
884        }
885        0x0005 => {
886            match decode_mesh_local_prefix(tlv_value) {
887                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
888                Err(e) => format!("{{\"error\": \"{}\"}}", e),
889            }
890        }
891        0x0006 => {
892            match decode_overrun_count(tlv_value) {
893                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
894                Err(e) => format!("{{\"error\": \"{}\"}}", e),
895            }
896        }
897        0x0007 => {
898            match decode_neighbor_table(tlv_value) {
899                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
900                Err(e) => format!("{{\"error\": \"{}\"}}", e),
901            }
902        }
903        0x0008 => {
904            match decode_route_table(tlv_value) {
905                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
906                Err(e) => format!("{{\"error\": \"{}\"}}", e),
907            }
908        }
909        0x0009 => {
910            match decode_partition_id(tlv_value) {
911                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
912                Err(e) => format!("{{\"error\": \"{}\"}}", e),
913            }
914        }
915        0x000A => {
916            match decode_weighting(tlv_value) {
917                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
918                Err(e) => format!("{{\"error\": \"{}\"}}", e),
919            }
920        }
921        0x000B => {
922            match decode_data_version(tlv_value) {
923                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
924                Err(e) => format!("{{\"error\": \"{}\"}}", e),
925            }
926        }
927        0x000C => {
928            match decode_stable_data_version(tlv_value) {
929                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
930                Err(e) => format!("{{\"error\": \"{}\"}}", e),
931            }
932        }
933        0x000D => {
934            match decode_leader_router_id(tlv_value) {
935                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
936                Err(e) => format!("{{\"error\": \"{}\"}}", e),
937            }
938        }
939        0x000E => {
940            match decode_detached_role_count(tlv_value) {
941                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
942                Err(e) => format!("{{\"error\": \"{}\"}}", e),
943            }
944        }
945        0x000F => {
946            match decode_child_role_count(tlv_value) {
947                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
948                Err(e) => format!("{{\"error\": \"{}\"}}", e),
949            }
950        }
951        0x0010 => {
952            match decode_router_role_count(tlv_value) {
953                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
954                Err(e) => format!("{{\"error\": \"{}\"}}", e),
955            }
956        }
957        0x0011 => {
958            match decode_leader_role_count(tlv_value) {
959                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
960                Err(e) => format!("{{\"error\": \"{}\"}}", e),
961            }
962        }
963        0x0012 => {
964            match decode_attach_attempt_count(tlv_value) {
965                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
966                Err(e) => format!("{{\"error\": \"{}\"}}", e),
967            }
968        }
969        0x0013 => {
970            match decode_partition_id_change_count(tlv_value) {
971                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
972                Err(e) => format!("{{\"error\": \"{}\"}}", e),
973            }
974        }
975        0x0014 => {
976            match decode_better_partition_attach_attempt_count(tlv_value) {
977                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
978                Err(e) => format!("{{\"error\": \"{}\"}}", e),
979            }
980        }
981        0x0015 => {
982            match decode_parent_change_count(tlv_value) {
983                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
984                Err(e) => format!("{{\"error\": \"{}\"}}", e),
985            }
986        }
987        0x0016 => {
988            match decode_tx_total_count(tlv_value) {
989                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
990                Err(e) => format!("{{\"error\": \"{}\"}}", e),
991            }
992        }
993        0x0017 => {
994            match decode_tx_unicast_count(tlv_value) {
995                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
996                Err(e) => format!("{{\"error\": \"{}\"}}", e),
997            }
998        }
999        0x0018 => {
1000            match decode_tx_broadcast_count(tlv_value) {
1001                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1002                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1003            }
1004        }
1005        0x0019 => {
1006            match decode_tx_ack_requested_count(tlv_value) {
1007                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1008                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1009            }
1010        }
1011        0x001A => {
1012            match decode_tx_acked_count(tlv_value) {
1013                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1014                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1015            }
1016        }
1017        0x001B => {
1018            match decode_tx_no_ack_requested_count(tlv_value) {
1019                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1020                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1021            }
1022        }
1023        0x001C => {
1024            match decode_tx_data_count(tlv_value) {
1025                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1026                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1027            }
1028        }
1029        0x001D => {
1030            match decode_tx_data_poll_count(tlv_value) {
1031                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1032                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1033            }
1034        }
1035        0x001E => {
1036            match decode_tx_beacon_count(tlv_value) {
1037                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1038                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1039            }
1040        }
1041        0x001F => {
1042            match decode_tx_beacon_request_count(tlv_value) {
1043                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1044                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1045            }
1046        }
1047        0x0020 => {
1048            match decode_tx_other_count(tlv_value) {
1049                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1050                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1051            }
1052        }
1053        0x0021 => {
1054            match decode_tx_retry_count(tlv_value) {
1055                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1056                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1057            }
1058        }
1059        0x0022 => {
1060            match decode_tx_direct_max_retry_expiry_count(tlv_value) {
1061                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1062                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1063            }
1064        }
1065        0x0023 => {
1066            match decode_tx_indirect_max_retry_expiry_count(tlv_value) {
1067                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1068                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1069            }
1070        }
1071        0x0024 => {
1072            match decode_tx_err_cca_count(tlv_value) {
1073                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1074                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1075            }
1076        }
1077        0x0025 => {
1078            match decode_tx_err_abort_count(tlv_value) {
1079                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1080                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1081            }
1082        }
1083        0x0026 => {
1084            match decode_tx_err_busy_channel_count(tlv_value) {
1085                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1086                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1087            }
1088        }
1089        0x0027 => {
1090            match decode_rx_total_count(tlv_value) {
1091                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1092                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1093            }
1094        }
1095        0x0028 => {
1096            match decode_rx_unicast_count(tlv_value) {
1097                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1098                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1099            }
1100        }
1101        0x0029 => {
1102            match decode_rx_broadcast_count(tlv_value) {
1103                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1104                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1105            }
1106        }
1107        0x002A => {
1108            match decode_rx_data_count(tlv_value) {
1109                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1110                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1111            }
1112        }
1113        0x002B => {
1114            match decode_rx_data_poll_count(tlv_value) {
1115                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1116                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1117            }
1118        }
1119        0x002C => {
1120            match decode_rx_beacon_count(tlv_value) {
1121                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1122                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1123            }
1124        }
1125        0x002D => {
1126            match decode_rx_beacon_request_count(tlv_value) {
1127                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1128                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1129            }
1130        }
1131        0x002E => {
1132            match decode_rx_other_count(tlv_value) {
1133                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1134                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1135            }
1136        }
1137        0x002F => {
1138            match decode_rx_address_filtered_count(tlv_value) {
1139                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1140                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1141            }
1142        }
1143        0x0030 => {
1144            match decode_rx_dest_addr_filtered_count(tlv_value) {
1145                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1146                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1147            }
1148        }
1149        0x0031 => {
1150            match decode_rx_duplicated_count(tlv_value) {
1151                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1152                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1153            }
1154        }
1155        0x0032 => {
1156            match decode_rx_err_no_frame_count(tlv_value) {
1157                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1158                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1159            }
1160        }
1161        0x0033 => {
1162            match decode_rx_err_unknown_neighbor_count(tlv_value) {
1163                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1164                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1165            }
1166        }
1167        0x0034 => {
1168            match decode_rx_err_invalid_src_addr_count(tlv_value) {
1169                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1170                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1171            }
1172        }
1173        0x0035 => {
1174            match decode_rx_err_sec_count(tlv_value) {
1175                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1176                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1177            }
1178        }
1179        0x0036 => {
1180            match decode_rx_err_fcs_count(tlv_value) {
1181                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1182                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1183            }
1184        }
1185        0x0037 => {
1186            match decode_rx_err_other_count(tlv_value) {
1187                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1188                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1189            }
1190        }
1191        0x0038 => {
1192            match decode_active_timestamp(tlv_value) {
1193                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1194                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1195            }
1196        }
1197        0x0039 => {
1198            match decode_pending_timestamp(tlv_value) {
1199                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1200                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1201            }
1202        }
1203        0x003A => {
1204            match decode_delay(tlv_value) {
1205                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1206                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1207            }
1208        }
1209        0x003B => {
1210            match decode_security_policy(tlv_value) {
1211                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1212                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1213            }
1214        }
1215        0x003C => {
1216            match decode_channel_page0_mask(tlv_value) {
1217                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1218                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1219            }
1220        }
1221        0x003D => {
1222            match decode_operational_dataset_components(tlv_value) {
1223                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1224                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1225            }
1226        }
1227        0x003E => {
1228            match decode_active_network_faults_list(tlv_value) {
1229                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1230                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1231            }
1232        }
1233        0x003F => {
1234            match decode_ext_address(tlv_value) {
1235                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1236                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1237            }
1238        }
1239        0x0040 => {
1240            match decode_rloc16(tlv_value) {
1241                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1242                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1243            }
1244        }
1245        _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
1246    }
1247}
1248
1249/// Get list of all attributes supported by this cluster
1250///
1251/// # Returns
1252/// Vector of tuples containing (attribute_id, attribute_name)
1253pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
1254    vec![
1255        (0x0000, "Channel"),
1256        (0x0001, "RoutingRole"),
1257        (0x0002, "NetworkName"),
1258        (0x0003, "PanId"),
1259        (0x0004, "ExtendedPanId"),
1260        (0x0005, "MeshLocalPrefix"),
1261        (0x0006, "OverrunCount"),
1262        (0x0007, "NeighborTable"),
1263        (0x0008, "RouteTable"),
1264        (0x0009, "PartitionId"),
1265        (0x000A, "Weighting"),
1266        (0x000B, "DataVersion"),
1267        (0x000C, "StableDataVersion"),
1268        (0x000D, "LeaderRouterId"),
1269        (0x000E, "DetachedRoleCount"),
1270        (0x000F, "ChildRoleCount"),
1271        (0x0010, "RouterRoleCount"),
1272        (0x0011, "LeaderRoleCount"),
1273        (0x0012, "AttachAttemptCount"),
1274        (0x0013, "PartitionIdChangeCount"),
1275        (0x0014, "BetterPartitionAttachAttemptCount"),
1276        (0x0015, "ParentChangeCount"),
1277        (0x0016, "TxTotalCount"),
1278        (0x0017, "TxUnicastCount"),
1279        (0x0018, "TxBroadcastCount"),
1280        (0x0019, "TxAckRequestedCount"),
1281        (0x001A, "TxAckedCount"),
1282        (0x001B, "TxNoAckRequestedCount"),
1283        (0x001C, "TxDataCount"),
1284        (0x001D, "TxDataPollCount"),
1285        (0x001E, "TxBeaconCount"),
1286        (0x001F, "TxBeaconRequestCount"),
1287        (0x0020, "TxOtherCount"),
1288        (0x0021, "TxRetryCount"),
1289        (0x0022, "TxDirectMaxRetryExpiryCount"),
1290        (0x0023, "TxIndirectMaxRetryExpiryCount"),
1291        (0x0024, "TxErrCcaCount"),
1292        (0x0025, "TxErrAbortCount"),
1293        (0x0026, "TxErrBusyChannelCount"),
1294        (0x0027, "RxTotalCount"),
1295        (0x0028, "RxUnicastCount"),
1296        (0x0029, "RxBroadcastCount"),
1297        (0x002A, "RxDataCount"),
1298        (0x002B, "RxDataPollCount"),
1299        (0x002C, "RxBeaconCount"),
1300        (0x002D, "RxBeaconRequestCount"),
1301        (0x002E, "RxOtherCount"),
1302        (0x002F, "RxAddressFilteredCount"),
1303        (0x0030, "RxDestAddrFilteredCount"),
1304        (0x0031, "RxDuplicatedCount"),
1305        (0x0032, "RxErrNoFrameCount"),
1306        (0x0033, "RxErrUnknownNeighborCount"),
1307        (0x0034, "RxErrInvalidSrcAddrCount"),
1308        (0x0035, "RxErrSecCount"),
1309        (0x0036, "RxErrFcsCount"),
1310        (0x0037, "RxErrOtherCount"),
1311        (0x0038, "ActiveTimestamp"),
1312        (0x0039, "PendingTimestamp"),
1313        (0x003A, "Delay"),
1314        (0x003B, "SecurityPolicy"),
1315        (0x003C, "ChannelPage0Mask"),
1316        (0x003D, "OperationalDatasetComponents"),
1317        (0x003E, "ActiveNetworkFaultsList"),
1318        (0x003F, "ExtAddress"),
1319        (0x0040, "Rloc16"),
1320    ]
1321}
1322
1323#[derive(Debug, serde::Serialize)]
1324pub struct ConnectionStatusEvent {
1325    pub connection_status: Option<ConnectionStatus>,
1326}
1327
1328#[derive(Debug, serde::Serialize)]
1329pub struct NetworkFaultChangeEvent {
1330    pub current: Option<Vec<NetworkFault>>,
1331    pub previous: Option<Vec<NetworkFault>>,
1332}
1333
1334// Event decoders
1335
1336/// Decode ConnectionStatus event (0x00, priority: info)
1337pub fn decode_connection_status_event(inp: &tlv::TlvItemValue) -> anyhow::Result<ConnectionStatusEvent> {
1338    if let tlv::TlvItemValue::List(_fields) = inp {
1339        let item = tlv::TlvItem { tag: 0, value: inp.clone() };
1340        Ok(ConnectionStatusEvent {
1341                                connection_status: item.get_int(&[0]).and_then(|v| ConnectionStatus::from_u8(v as u8)),
1342        })
1343    } else {
1344        Err(anyhow::anyhow!("Expected struct fields"))
1345    }
1346}
1347
1348/// Decode NetworkFaultChange event (0x01, priority: info)
1349pub fn decode_network_fault_change_event(inp: &tlv::TlvItemValue) -> anyhow::Result<NetworkFaultChangeEvent> {
1350    if let tlv::TlvItemValue::List(_fields) = inp {
1351        let item = tlv::TlvItem { tag: 0, value: inp.clone() };
1352        Ok(NetworkFaultChangeEvent {
1353                                current: {
1354                    if let Some(tlv::TlvItemValue::List(l)) = item.get(&[0]) {
1355                        let items: Vec<NetworkFault> = l.iter().filter_map(|e| { if let tlv::TlvItemValue::Int(v) = &e.value { NetworkFault::from_u8(*v as u8) } else { None } }).collect();
1356                        Some(items)
1357                    } else {
1358                        None
1359                    }
1360                },
1361                                previous: {
1362                    if let Some(tlv::TlvItemValue::List(l)) = item.get(&[1]) {
1363                        let items: Vec<NetworkFault> = l.iter().filter_map(|e| { if let tlv::TlvItemValue::Int(v) = &e.value { NetworkFault::from_u8(*v as u8) } else { None } }).collect();
1364                        Some(items)
1365                    } else {
1366                        None
1367                    }
1368                },
1369        })
1370    } else {
1371        Err(anyhow::anyhow!("Expected struct fields"))
1372    }
1373}
1374