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
6#![allow(clippy::too_many_arguments)]
7
8use crate::tlv;
9use anyhow;
10use serde_json;
11
12
13// Enum definitions
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
16#[repr(u8)]
17pub enum ConnectionStatus {
18    /// Node is connected
19    Connected = 0,
20    /// Node is not connected
21    Notconnected = 1,
22}
23
24impl ConnectionStatus {
25    /// Convert from u8 value
26    pub fn from_u8(value: u8) -> Option<Self> {
27        match value {
28            0 => Some(ConnectionStatus::Connected),
29            1 => Some(ConnectionStatus::Notconnected),
30            _ => None,
31        }
32    }
33
34    /// Convert to u8 value
35    pub fn to_u8(self) -> u8 {
36        self as u8
37    }
38}
39
40impl From<ConnectionStatus> for u8 {
41    fn from(val: ConnectionStatus) -> Self {
42        val as u8
43    }
44}
45
46#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
47#[repr(u8)]
48pub enum NetworkFault {
49    /// Indicates an unspecified fault.
50    Unspecified = 0,
51    /// Indicates the Thread link is down.
52    Linkdown = 1,
53    /// Indicates there has been Thread hardware failure.
54    Hardwarefailure = 2,
55    /// Indicates the Thread network is jammed.
56    Networkjammed = 3,
57}
58
59impl NetworkFault {
60    /// Convert from u8 value
61    pub fn from_u8(value: u8) -> Option<Self> {
62        match value {
63            0 => Some(NetworkFault::Unspecified),
64            1 => Some(NetworkFault::Linkdown),
65            2 => Some(NetworkFault::Hardwarefailure),
66            3 => Some(NetworkFault::Networkjammed),
67            _ => None,
68        }
69    }
70
71    /// Convert to u8 value
72    pub fn to_u8(self) -> u8 {
73        self as u8
74    }
75}
76
77impl From<NetworkFault> for u8 {
78    fn from(val: NetworkFault) -> Self {
79        val as u8
80    }
81}
82
83#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
84#[repr(u8)]
85pub enum RoutingRole {
86    /// Unspecified routing role.
87    Unspecified = 0,
88    /// The Node does not currently have a role as a result of the Thread interface not currently being configured or operational.
89    Unassigned = 1,
90    /// The Node acts as a Sleepy End Device with RX-off-when-idle sleepy radio behavior.
91    Sleepyenddevice = 2,
92    /// The Node acts as an End Device without RX-off-when-idle sleepy radio behavior.
93    Enddevice = 3,
94    /// The Node acts as an Router Eligible End Device.
95    Reed = 4,
96    /// The Node acts as a Router Device.
97    Router = 5,
98    /// The Node acts as a Leader Device.
99    Leader = 6,
100}
101
102impl RoutingRole {
103    /// Convert from u8 value
104    pub fn from_u8(value: u8) -> Option<Self> {
105        match value {
106            0 => Some(RoutingRole::Unspecified),
107            1 => Some(RoutingRole::Unassigned),
108            2 => Some(RoutingRole::Sleepyenddevice),
109            3 => Some(RoutingRole::Enddevice),
110            4 => Some(RoutingRole::Reed),
111            5 => Some(RoutingRole::Router),
112            6 => Some(RoutingRole::Leader),
113            _ => None,
114        }
115    }
116
117    /// Convert to u8 value
118    pub fn to_u8(self) -> u8 {
119        self as u8
120    }
121}
122
123impl From<RoutingRole> for u8 {
124    fn from(val: RoutingRole) -> Self {
125        val as u8
126    }
127}
128
129// Struct definitions
130
131#[derive(Debug, serde::Serialize)]
132pub struct NeighborTable {
133    pub ext_address: Option<u64>,
134    pub age: Option<u32>,
135    pub rloc16: Option<u16>,
136    pub link_frame_counter: Option<u32>,
137    pub mle_frame_counter: Option<u32>,
138    pub lqi: Option<u8>,
139    pub average_rssi: Option<i8>,
140    pub last_rssi: Option<i8>,
141    pub frame_error_rate: Option<u8>,
142    pub message_error_rate: Option<u8>,
143    pub rx_on_when_idle: Option<bool>,
144    pub full_thread_device: Option<bool>,
145    pub full_network_data: Option<bool>,
146    pub is_child: Option<bool>,
147}
148
149#[derive(Debug, serde::Serialize)]
150pub struct OperationalDatasetComponents {
151    pub active_timestamp_present: Option<bool>,
152    pub pending_timestamp_present: Option<bool>,
153    pub master_key_present: Option<bool>,
154    pub network_name_present: Option<bool>,
155    pub extended_pan_id_present: Option<bool>,
156    pub mesh_local_prefix_present: Option<bool>,
157    pub delay_present: Option<bool>,
158    pub pan_id_present: Option<bool>,
159    pub channel_present: Option<bool>,
160    pub pskc_present: Option<bool>,
161    pub security_policy_present: Option<bool>,
162    pub channel_mask_present: Option<bool>,
163}
164
165#[derive(Debug, serde::Serialize)]
166pub struct RouteTable {
167    pub ext_address: Option<u64>,
168    pub rloc16: Option<u16>,
169    pub router_id: Option<u8>,
170    pub next_hop: Option<u8>,
171    pub path_cost: Option<u8>,
172    pub lqi_in: Option<u8>,
173    pub lqi_out: Option<u8>,
174    pub age: Option<u8>,
175    pub allocated: Option<bool>,
176    pub link_established: Option<bool>,
177}
178
179#[derive(Debug, serde::Serialize)]
180pub struct SecurityPolicy {
181    pub rotation_time: Option<u16>,
182    pub flags: Option<u16>,
183}
184
185// Command encoders
186
187// Attribute decoders
188
189/// Decode Channel attribute (0x0000)
190pub fn decode_channel(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u16>> {
191    if let tlv::TlvItemValue::Int(v) = inp {
192        Ok(Some(*v as u16))
193    } else {
194        Ok(None)
195    }
196}
197
198/// Decode RoutingRole attribute (0x0001)
199pub fn decode_routing_role(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<RoutingRole>> {
200    if let tlv::TlvItemValue::Int(v) = inp {
201        Ok(RoutingRole::from_u8(*v as u8))
202    } else {
203        Ok(None)
204    }
205}
206
207/// Decode NetworkName attribute (0x0002)
208pub fn decode_network_name(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<String>> {
209    if let tlv::TlvItemValue::String(v) = inp {
210        Ok(Some(v.clone()))
211    } else {
212        Ok(None)
213    }
214}
215
216/// Decode PanId attribute (0x0003)
217pub fn decode_pan_id(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u16>> {
218    if let tlv::TlvItemValue::Int(v) = inp {
219        Ok(Some(*v as u16))
220    } else {
221        Ok(None)
222    }
223}
224
225/// Decode ExtendedPanId attribute (0x0004)
226pub fn decode_extended_pan_id(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u64>> {
227    if let tlv::TlvItemValue::Int(v) = inp {
228        Ok(Some(*v))
229    } else {
230        Ok(None)
231    }
232}
233
234/// Decode MeshLocalPrefix attribute (0x0005)
235pub fn decode_mesh_local_prefix(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
236    if let tlv::TlvItemValue::Int(v) = inp {
237        Ok(Some(*v as u8))
238    } else {
239        Ok(None)
240    }
241}
242
243/// Decode OverrunCount attribute (0x0006)
244pub fn decode_overrun_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u64> {
245    if let tlv::TlvItemValue::Int(v) = inp {
246        Ok(*v)
247    } else {
248        Err(anyhow::anyhow!("Expected UInt64"))
249    }
250}
251
252/// Decode NeighborTable attribute (0x0007)
253pub fn decode_neighbor_table(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<NeighborTable>> {
254    let mut res = Vec::new();
255    if let tlv::TlvItemValue::List(v) = inp {
256        for item in v {
257            res.push(NeighborTable {
258                ext_address: item.get_int(&[0]),
259                age: item.get_int(&[1]).map(|v| v as u32),
260                rloc16: item.get_int(&[2]).map(|v| v as u16),
261                link_frame_counter: item.get_int(&[3]).map(|v| v as u32),
262                mle_frame_counter: item.get_int(&[4]).map(|v| v as u32),
263                lqi: item.get_int(&[5]).map(|v| v as u8),
264                average_rssi: item.get_int(&[6]).map(|v| v as i8),
265                last_rssi: item.get_int(&[7]).map(|v| v as i8),
266                frame_error_rate: item.get_int(&[8]).map(|v| v as u8),
267                message_error_rate: item.get_int(&[9]).map(|v| v as u8),
268                rx_on_when_idle: item.get_bool(&[10]),
269                full_thread_device: item.get_bool(&[11]),
270                full_network_data: item.get_bool(&[12]),
271                is_child: item.get_bool(&[13]),
272            });
273        }
274    }
275    Ok(res)
276}
277
278/// Decode RouteTable attribute (0x0008)
279pub fn decode_route_table(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<RouteTable>> {
280    let mut res = Vec::new();
281    if let tlv::TlvItemValue::List(v) = inp {
282        for item in v {
283            res.push(RouteTable {
284                ext_address: item.get_int(&[0]),
285                rloc16: item.get_int(&[1]).map(|v| v as u16),
286                router_id: item.get_int(&[2]).map(|v| v as u8),
287                next_hop: item.get_int(&[3]).map(|v| v as u8),
288                path_cost: item.get_int(&[4]).map(|v| v as u8),
289                lqi_in: item.get_int(&[5]).map(|v| v as u8),
290                lqi_out: item.get_int(&[6]).map(|v| v as u8),
291                age: item.get_int(&[7]).map(|v| v as u8),
292                allocated: item.get_bool(&[8]),
293                link_established: item.get_bool(&[9]),
294            });
295        }
296    }
297    Ok(res)
298}
299
300/// Decode PartitionId attribute (0x0009)
301pub fn decode_partition_id(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u32>> {
302    if let tlv::TlvItemValue::Int(v) = inp {
303        Ok(Some(*v as u32))
304    } else {
305        Ok(None)
306    }
307}
308
309/// Decode Weighting attribute (0x000A)
310pub fn decode_weighting(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u16>> {
311    if let tlv::TlvItemValue::Int(v) = inp {
312        Ok(Some(*v as u16))
313    } else {
314        Ok(None)
315    }
316}
317
318/// Decode DataVersion attribute (0x000B)
319pub fn decode_data_version(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u16>> {
320    if let tlv::TlvItemValue::Int(v) = inp {
321        Ok(Some(*v as u16))
322    } else {
323        Ok(None)
324    }
325}
326
327/// Decode StableDataVersion attribute (0x000C)
328pub fn decode_stable_data_version(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u16>> {
329    if let tlv::TlvItemValue::Int(v) = inp {
330        Ok(Some(*v as u16))
331    } else {
332        Ok(None)
333    }
334}
335
336/// Decode LeaderRouterId attribute (0x000D)
337pub fn decode_leader_router_id(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
338    if let tlv::TlvItemValue::Int(v) = inp {
339        Ok(Some(*v as u8))
340    } else {
341        Ok(None)
342    }
343}
344
345/// Decode DetachedRoleCount attribute (0x000E)
346pub fn decode_detached_role_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
347    if let tlv::TlvItemValue::Int(v) = inp {
348        Ok(*v as u16)
349    } else {
350        Err(anyhow::anyhow!("Expected UInt16"))
351    }
352}
353
354/// Decode ChildRoleCount attribute (0x000F)
355pub fn decode_child_role_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
356    if let tlv::TlvItemValue::Int(v) = inp {
357        Ok(*v as u16)
358    } else {
359        Err(anyhow::anyhow!("Expected UInt16"))
360    }
361}
362
363/// Decode RouterRoleCount attribute (0x0010)
364pub fn decode_router_role_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
365    if let tlv::TlvItemValue::Int(v) = inp {
366        Ok(*v as u16)
367    } else {
368        Err(anyhow::anyhow!("Expected UInt16"))
369    }
370}
371
372/// Decode LeaderRoleCount attribute (0x0011)
373pub fn decode_leader_role_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
374    if let tlv::TlvItemValue::Int(v) = inp {
375        Ok(*v as u16)
376    } else {
377        Err(anyhow::anyhow!("Expected UInt16"))
378    }
379}
380
381/// Decode AttachAttemptCount attribute (0x0012)
382pub fn decode_attach_attempt_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
383    if let tlv::TlvItemValue::Int(v) = inp {
384        Ok(*v as u16)
385    } else {
386        Err(anyhow::anyhow!("Expected UInt16"))
387    }
388}
389
390/// Decode PartitionIdChangeCount attribute (0x0013)
391pub fn decode_partition_id_change_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
392    if let tlv::TlvItemValue::Int(v) = inp {
393        Ok(*v as u16)
394    } else {
395        Err(anyhow::anyhow!("Expected UInt16"))
396    }
397}
398
399/// Decode BetterPartitionAttachAttemptCount attribute (0x0014)
400pub fn decode_better_partition_attach_attempt_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
401    if let tlv::TlvItemValue::Int(v) = inp {
402        Ok(*v as u16)
403    } else {
404        Err(anyhow::anyhow!("Expected UInt16"))
405    }
406}
407
408/// Decode ParentChangeCount attribute (0x0015)
409pub fn decode_parent_change_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
410    if let tlv::TlvItemValue::Int(v) = inp {
411        Ok(*v as u16)
412    } else {
413        Err(anyhow::anyhow!("Expected UInt16"))
414    }
415}
416
417/// Decode TxTotalCount attribute (0x0016)
418pub fn decode_tx_total_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
419    if let tlv::TlvItemValue::Int(v) = inp {
420        Ok(*v as u32)
421    } else {
422        Err(anyhow::anyhow!("Expected UInt32"))
423    }
424}
425
426/// Decode TxUnicastCount attribute (0x0017)
427pub fn decode_tx_unicast_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
428    if let tlv::TlvItemValue::Int(v) = inp {
429        Ok(*v as u32)
430    } else {
431        Err(anyhow::anyhow!("Expected UInt32"))
432    }
433}
434
435/// Decode TxBroadcastCount attribute (0x0018)
436pub fn decode_tx_broadcast_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
437    if let tlv::TlvItemValue::Int(v) = inp {
438        Ok(*v as u32)
439    } else {
440        Err(anyhow::anyhow!("Expected UInt32"))
441    }
442}
443
444/// Decode TxAckRequestedCount attribute (0x0019)
445pub fn decode_tx_ack_requested_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
446    if let tlv::TlvItemValue::Int(v) = inp {
447        Ok(*v as u32)
448    } else {
449        Err(anyhow::anyhow!("Expected UInt32"))
450    }
451}
452
453/// Decode TxAckedCount attribute (0x001A)
454pub fn decode_tx_acked_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
455    if let tlv::TlvItemValue::Int(v) = inp {
456        Ok(*v as u32)
457    } else {
458        Err(anyhow::anyhow!("Expected UInt32"))
459    }
460}
461
462/// Decode TxNoAckRequestedCount attribute (0x001B)
463pub fn decode_tx_no_ack_requested_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
464    if let tlv::TlvItemValue::Int(v) = inp {
465        Ok(*v as u32)
466    } else {
467        Err(anyhow::anyhow!("Expected UInt32"))
468    }
469}
470
471/// Decode TxDataCount attribute (0x001C)
472pub fn decode_tx_data_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
473    if let tlv::TlvItemValue::Int(v) = inp {
474        Ok(*v as u32)
475    } else {
476        Err(anyhow::anyhow!("Expected UInt32"))
477    }
478}
479
480/// Decode TxDataPollCount attribute (0x001D)
481pub fn decode_tx_data_poll_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
482    if let tlv::TlvItemValue::Int(v) = inp {
483        Ok(*v as u32)
484    } else {
485        Err(anyhow::anyhow!("Expected UInt32"))
486    }
487}
488
489/// Decode TxBeaconCount attribute (0x001E)
490pub fn decode_tx_beacon_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
491    if let tlv::TlvItemValue::Int(v) = inp {
492        Ok(*v as u32)
493    } else {
494        Err(anyhow::anyhow!("Expected UInt32"))
495    }
496}
497
498/// Decode TxBeaconRequestCount attribute (0x001F)
499pub fn decode_tx_beacon_request_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
500    if let tlv::TlvItemValue::Int(v) = inp {
501        Ok(*v as u32)
502    } else {
503        Err(anyhow::anyhow!("Expected UInt32"))
504    }
505}
506
507/// Decode TxOtherCount attribute (0x0020)
508pub fn decode_tx_other_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
509    if let tlv::TlvItemValue::Int(v) = inp {
510        Ok(*v as u32)
511    } else {
512        Err(anyhow::anyhow!("Expected UInt32"))
513    }
514}
515
516/// Decode TxRetryCount attribute (0x0021)
517pub fn decode_tx_retry_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
518    if let tlv::TlvItemValue::Int(v) = inp {
519        Ok(*v as u32)
520    } else {
521        Err(anyhow::anyhow!("Expected UInt32"))
522    }
523}
524
525/// Decode TxDirectMaxRetryExpiryCount attribute (0x0022)
526pub fn decode_tx_direct_max_retry_expiry_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
527    if let tlv::TlvItemValue::Int(v) = inp {
528        Ok(*v as u32)
529    } else {
530        Err(anyhow::anyhow!("Expected UInt32"))
531    }
532}
533
534/// Decode TxIndirectMaxRetryExpiryCount attribute (0x0023)
535pub fn decode_tx_indirect_max_retry_expiry_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
536    if let tlv::TlvItemValue::Int(v) = inp {
537        Ok(*v as u32)
538    } else {
539        Err(anyhow::anyhow!("Expected UInt32"))
540    }
541}
542
543/// Decode TxErrCcaCount attribute (0x0024)
544pub fn decode_tx_err_cca_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
545    if let tlv::TlvItemValue::Int(v) = inp {
546        Ok(*v as u32)
547    } else {
548        Err(anyhow::anyhow!("Expected UInt32"))
549    }
550}
551
552/// Decode TxErrAbortCount attribute (0x0025)
553pub fn decode_tx_err_abort_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
554    if let tlv::TlvItemValue::Int(v) = inp {
555        Ok(*v as u32)
556    } else {
557        Err(anyhow::anyhow!("Expected UInt32"))
558    }
559}
560
561/// Decode TxErrBusyChannelCount attribute (0x0026)
562pub fn decode_tx_err_busy_channel_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
563    if let tlv::TlvItemValue::Int(v) = inp {
564        Ok(*v as u32)
565    } else {
566        Err(anyhow::anyhow!("Expected UInt32"))
567    }
568}
569
570/// Decode RxTotalCount attribute (0x0027)
571pub fn decode_rx_total_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
572    if let tlv::TlvItemValue::Int(v) = inp {
573        Ok(*v as u32)
574    } else {
575        Err(anyhow::anyhow!("Expected UInt32"))
576    }
577}
578
579/// Decode RxUnicastCount attribute (0x0028)
580pub fn decode_rx_unicast_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
581    if let tlv::TlvItemValue::Int(v) = inp {
582        Ok(*v as u32)
583    } else {
584        Err(anyhow::anyhow!("Expected UInt32"))
585    }
586}
587
588/// Decode RxBroadcastCount attribute (0x0029)
589pub fn decode_rx_broadcast_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
590    if let tlv::TlvItemValue::Int(v) = inp {
591        Ok(*v as u32)
592    } else {
593        Err(anyhow::anyhow!("Expected UInt32"))
594    }
595}
596
597/// Decode RxDataCount attribute (0x002A)
598pub fn decode_rx_data_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
599    if let tlv::TlvItemValue::Int(v) = inp {
600        Ok(*v as u32)
601    } else {
602        Err(anyhow::anyhow!("Expected UInt32"))
603    }
604}
605
606/// Decode RxDataPollCount attribute (0x002B)
607pub fn decode_rx_data_poll_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
608    if let tlv::TlvItemValue::Int(v) = inp {
609        Ok(*v as u32)
610    } else {
611        Err(anyhow::anyhow!("Expected UInt32"))
612    }
613}
614
615/// Decode RxBeaconCount attribute (0x002C)
616pub fn decode_rx_beacon_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
617    if let tlv::TlvItemValue::Int(v) = inp {
618        Ok(*v as u32)
619    } else {
620        Err(anyhow::anyhow!("Expected UInt32"))
621    }
622}
623
624/// Decode RxBeaconRequestCount attribute (0x002D)
625pub fn decode_rx_beacon_request_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
626    if let tlv::TlvItemValue::Int(v) = inp {
627        Ok(*v as u32)
628    } else {
629        Err(anyhow::anyhow!("Expected UInt32"))
630    }
631}
632
633/// Decode RxOtherCount attribute (0x002E)
634pub fn decode_rx_other_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
635    if let tlv::TlvItemValue::Int(v) = inp {
636        Ok(*v as u32)
637    } else {
638        Err(anyhow::anyhow!("Expected UInt32"))
639    }
640}
641
642/// Decode RxAddressFilteredCount attribute (0x002F)
643pub fn decode_rx_address_filtered_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
644    if let tlv::TlvItemValue::Int(v) = inp {
645        Ok(*v as u32)
646    } else {
647        Err(anyhow::anyhow!("Expected UInt32"))
648    }
649}
650
651/// Decode RxDestAddrFilteredCount attribute (0x0030)
652pub fn decode_rx_dest_addr_filtered_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
653    if let tlv::TlvItemValue::Int(v) = inp {
654        Ok(*v as u32)
655    } else {
656        Err(anyhow::anyhow!("Expected UInt32"))
657    }
658}
659
660/// Decode RxDuplicatedCount attribute (0x0031)
661pub fn decode_rx_duplicated_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
662    if let tlv::TlvItemValue::Int(v) = inp {
663        Ok(*v as u32)
664    } else {
665        Err(anyhow::anyhow!("Expected UInt32"))
666    }
667}
668
669/// Decode RxErrNoFrameCount attribute (0x0032)
670pub fn decode_rx_err_no_frame_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
671    if let tlv::TlvItemValue::Int(v) = inp {
672        Ok(*v as u32)
673    } else {
674        Err(anyhow::anyhow!("Expected UInt32"))
675    }
676}
677
678/// Decode RxErrUnknownNeighborCount attribute (0x0033)
679pub fn decode_rx_err_unknown_neighbor_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
680    if let tlv::TlvItemValue::Int(v) = inp {
681        Ok(*v as u32)
682    } else {
683        Err(anyhow::anyhow!("Expected UInt32"))
684    }
685}
686
687/// Decode RxErrInvalidSrcAddrCount attribute (0x0034)
688pub fn decode_rx_err_invalid_src_addr_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
689    if let tlv::TlvItemValue::Int(v) = inp {
690        Ok(*v as u32)
691    } else {
692        Err(anyhow::anyhow!("Expected UInt32"))
693    }
694}
695
696/// Decode RxErrSecCount attribute (0x0035)
697pub fn decode_rx_err_sec_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
698    if let tlv::TlvItemValue::Int(v) = inp {
699        Ok(*v as u32)
700    } else {
701        Err(anyhow::anyhow!("Expected UInt32"))
702    }
703}
704
705/// Decode RxErrFcsCount attribute (0x0036)
706pub fn decode_rx_err_fcs_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
707    if let tlv::TlvItemValue::Int(v) = inp {
708        Ok(*v as u32)
709    } else {
710        Err(anyhow::anyhow!("Expected UInt32"))
711    }
712}
713
714/// Decode RxErrOtherCount attribute (0x0037)
715pub fn decode_rx_err_other_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
716    if let tlv::TlvItemValue::Int(v) = inp {
717        Ok(*v as u32)
718    } else {
719        Err(anyhow::anyhow!("Expected UInt32"))
720    }
721}
722
723/// Decode ActiveTimestamp attribute (0x0038)
724pub fn decode_active_timestamp(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u64>> {
725    if let tlv::TlvItemValue::Int(v) = inp {
726        Ok(Some(*v))
727    } else {
728        Ok(None)
729    }
730}
731
732/// Decode PendingTimestamp attribute (0x0039)
733pub fn decode_pending_timestamp(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u64>> {
734    if let tlv::TlvItemValue::Int(v) = inp {
735        Ok(Some(*v))
736    } else {
737        Ok(None)
738    }
739}
740
741/// Decode Delay attribute (0x003A)
742pub fn decode_delay(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u32>> {
743    if let tlv::TlvItemValue::Int(v) = inp {
744        Ok(Some(*v as u32))
745    } else {
746        Ok(None)
747    }
748}
749
750/// Decode SecurityPolicy attribute (0x003B)
751pub fn decode_security_policy(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<SecurityPolicy>> {
752    if let tlv::TlvItemValue::List(_fields) = inp {
753        // Struct with fields
754        let item = tlv::TlvItem { tag: 0, value: inp.clone() };
755        Ok(Some(SecurityPolicy {
756                rotation_time: item.get_int(&[0]).map(|v| v as u16),
757                flags: item.get_int(&[1]).map(|v| v as u16),
758        }))
759    //} else if let tlv::TlvItemValue::Null = inp {
760    //    // Null value for nullable struct
761    //    Ok(None)
762    } else {
763    Ok(None)
764    //    Err(anyhow::anyhow!("Expected struct fields or null"))
765    }
766}
767
768/// Decode ChannelPage0Mask attribute (0x003C)
769pub fn decode_channel_page0_mask(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<Vec<u8>>> {
770    if let tlv::TlvItemValue::OctetString(v) = inp {
771        Ok(Some(v.clone()))
772    } else {
773        Ok(None)
774    }
775}
776
777/// Decode OperationalDatasetComponents attribute (0x003D)
778pub fn decode_operational_dataset_components(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<OperationalDatasetComponents>> {
779    if let tlv::TlvItemValue::List(_fields) = inp {
780        // Struct with fields
781        let item = tlv::TlvItem { tag: 0, value: inp.clone() };
782        Ok(Some(OperationalDatasetComponents {
783                active_timestamp_present: item.get_bool(&[0]),
784                pending_timestamp_present: item.get_bool(&[1]),
785                master_key_present: item.get_bool(&[2]),
786                network_name_present: item.get_bool(&[3]),
787                extended_pan_id_present: item.get_bool(&[4]),
788                mesh_local_prefix_present: item.get_bool(&[5]),
789                delay_present: item.get_bool(&[6]),
790                pan_id_present: item.get_bool(&[7]),
791                channel_present: item.get_bool(&[8]),
792                pskc_present: item.get_bool(&[9]),
793                security_policy_present: item.get_bool(&[10]),
794                channel_mask_present: item.get_bool(&[11]),
795        }))
796    //} else if let tlv::TlvItemValue::Null = inp {
797    //    // Null value for nullable struct
798    //    Ok(None)
799    } else {
800    Ok(None)
801    //    Err(anyhow::anyhow!("Expected struct fields or null"))
802    }
803}
804
805/// Decode ActiveNetworkFaultsList attribute (0x003E)
806pub fn decode_active_network_faults_list(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<NetworkFault>> {
807    let mut res = Vec::new();
808    if let tlv::TlvItemValue::List(v) = inp {
809        for item in v {
810            if let tlv::TlvItemValue::Int(i) = &item.value {
811                if let Some(enum_val) = NetworkFault::from_u8(*i as u8) {
812                    res.push(enum_val);
813                }
814            }
815        }
816    }
817    Ok(res)
818}
819
820/// Decode ExtAddress attribute (0x003F)
821pub fn decode_ext_address(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u64>> {
822    if let tlv::TlvItemValue::Int(v) = inp {
823        Ok(Some(*v))
824    } else {
825        Ok(None)
826    }
827}
828
829/// Decode Rloc16 attribute (0x0040)
830pub fn decode_rloc16(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u16>> {
831    if let tlv::TlvItemValue::Int(v) = inp {
832        Ok(Some(*v as u16))
833    } else {
834        Ok(None)
835    }
836}
837
838
839// JSON dispatcher function
840
841/// Decode attribute value and return as JSON string
842///
843/// # Parameters
844/// * `cluster_id` - The cluster identifier
845/// * `attribute_id` - The attribute identifier
846/// * `tlv_value` - The TLV value to decode
847///
848/// # Returns
849/// JSON string representation of the decoded value or error
850pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
851    // Verify this is the correct cluster
852    if cluster_id != 0x0035 {
853        return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0035, got {}\"}}", cluster_id);
854    }
855
856    match attribute_id {
857        0x0000 => {
858            match decode_channel(tlv_value) {
859                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
860                Err(e) => format!("{{\"error\": \"{}\"}}", e),
861            }
862        }
863        0x0001 => {
864            match decode_routing_role(tlv_value) {
865                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
866                Err(e) => format!("{{\"error\": \"{}\"}}", e),
867            }
868        }
869        0x0002 => {
870            match decode_network_name(tlv_value) {
871                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
872                Err(e) => format!("{{\"error\": \"{}\"}}", e),
873            }
874        }
875        0x0003 => {
876            match decode_pan_id(tlv_value) {
877                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
878                Err(e) => format!("{{\"error\": \"{}\"}}", e),
879            }
880        }
881        0x0004 => {
882            match decode_extended_pan_id(tlv_value) {
883                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
884                Err(e) => format!("{{\"error\": \"{}\"}}", e),
885            }
886        }
887        0x0005 => {
888            match decode_mesh_local_prefix(tlv_value) {
889                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
890                Err(e) => format!("{{\"error\": \"{}\"}}", e),
891            }
892        }
893        0x0006 => {
894            match decode_overrun_count(tlv_value) {
895                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
896                Err(e) => format!("{{\"error\": \"{}\"}}", e),
897            }
898        }
899        0x0007 => {
900            match decode_neighbor_table(tlv_value) {
901                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
902                Err(e) => format!("{{\"error\": \"{}\"}}", e),
903            }
904        }
905        0x0008 => {
906            match decode_route_table(tlv_value) {
907                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
908                Err(e) => format!("{{\"error\": \"{}\"}}", e),
909            }
910        }
911        0x0009 => {
912            match decode_partition_id(tlv_value) {
913                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
914                Err(e) => format!("{{\"error\": \"{}\"}}", e),
915            }
916        }
917        0x000A => {
918            match decode_weighting(tlv_value) {
919                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
920                Err(e) => format!("{{\"error\": \"{}\"}}", e),
921            }
922        }
923        0x000B => {
924            match decode_data_version(tlv_value) {
925                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
926                Err(e) => format!("{{\"error\": \"{}\"}}", e),
927            }
928        }
929        0x000C => {
930            match decode_stable_data_version(tlv_value) {
931                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
932                Err(e) => format!("{{\"error\": \"{}\"}}", e),
933            }
934        }
935        0x000D => {
936            match decode_leader_router_id(tlv_value) {
937                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
938                Err(e) => format!("{{\"error\": \"{}\"}}", e),
939            }
940        }
941        0x000E => {
942            match decode_detached_role_count(tlv_value) {
943                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
944                Err(e) => format!("{{\"error\": \"{}\"}}", e),
945            }
946        }
947        0x000F => {
948            match decode_child_role_count(tlv_value) {
949                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
950                Err(e) => format!("{{\"error\": \"{}\"}}", e),
951            }
952        }
953        0x0010 => {
954            match decode_router_role_count(tlv_value) {
955                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
956                Err(e) => format!("{{\"error\": \"{}\"}}", e),
957            }
958        }
959        0x0011 => {
960            match decode_leader_role_count(tlv_value) {
961                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
962                Err(e) => format!("{{\"error\": \"{}\"}}", e),
963            }
964        }
965        0x0012 => {
966            match decode_attach_attempt_count(tlv_value) {
967                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
968                Err(e) => format!("{{\"error\": \"{}\"}}", e),
969            }
970        }
971        0x0013 => {
972            match decode_partition_id_change_count(tlv_value) {
973                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
974                Err(e) => format!("{{\"error\": \"{}\"}}", e),
975            }
976        }
977        0x0014 => {
978            match decode_better_partition_attach_attempt_count(tlv_value) {
979                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
980                Err(e) => format!("{{\"error\": \"{}\"}}", e),
981            }
982        }
983        0x0015 => {
984            match decode_parent_change_count(tlv_value) {
985                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
986                Err(e) => format!("{{\"error\": \"{}\"}}", e),
987            }
988        }
989        0x0016 => {
990            match decode_tx_total_count(tlv_value) {
991                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
992                Err(e) => format!("{{\"error\": \"{}\"}}", e),
993            }
994        }
995        0x0017 => {
996            match decode_tx_unicast_count(tlv_value) {
997                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
998                Err(e) => format!("{{\"error\": \"{}\"}}", e),
999            }
1000        }
1001        0x0018 => {
1002            match decode_tx_broadcast_count(tlv_value) {
1003                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1004                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1005            }
1006        }
1007        0x0019 => {
1008            match decode_tx_ack_requested_count(tlv_value) {
1009                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1010                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1011            }
1012        }
1013        0x001A => {
1014            match decode_tx_acked_count(tlv_value) {
1015                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1016                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1017            }
1018        }
1019        0x001B => {
1020            match decode_tx_no_ack_requested_count(tlv_value) {
1021                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1022                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1023            }
1024        }
1025        0x001C => {
1026            match decode_tx_data_count(tlv_value) {
1027                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1028                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1029            }
1030        }
1031        0x001D => {
1032            match decode_tx_data_poll_count(tlv_value) {
1033                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1034                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1035            }
1036        }
1037        0x001E => {
1038            match decode_tx_beacon_count(tlv_value) {
1039                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1040                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1041            }
1042        }
1043        0x001F => {
1044            match decode_tx_beacon_request_count(tlv_value) {
1045                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1046                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1047            }
1048        }
1049        0x0020 => {
1050            match decode_tx_other_count(tlv_value) {
1051                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1052                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1053            }
1054        }
1055        0x0021 => {
1056            match decode_tx_retry_count(tlv_value) {
1057                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1058                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1059            }
1060        }
1061        0x0022 => {
1062            match decode_tx_direct_max_retry_expiry_count(tlv_value) {
1063                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1064                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1065            }
1066        }
1067        0x0023 => {
1068            match decode_tx_indirect_max_retry_expiry_count(tlv_value) {
1069                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1070                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1071            }
1072        }
1073        0x0024 => {
1074            match decode_tx_err_cca_count(tlv_value) {
1075                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1076                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1077            }
1078        }
1079        0x0025 => {
1080            match decode_tx_err_abort_count(tlv_value) {
1081                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1082                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1083            }
1084        }
1085        0x0026 => {
1086            match decode_tx_err_busy_channel_count(tlv_value) {
1087                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1088                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1089            }
1090        }
1091        0x0027 => {
1092            match decode_rx_total_count(tlv_value) {
1093                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1094                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1095            }
1096        }
1097        0x0028 => {
1098            match decode_rx_unicast_count(tlv_value) {
1099                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1100                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1101            }
1102        }
1103        0x0029 => {
1104            match decode_rx_broadcast_count(tlv_value) {
1105                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1106                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1107            }
1108        }
1109        0x002A => {
1110            match decode_rx_data_count(tlv_value) {
1111                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1112                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1113            }
1114        }
1115        0x002B => {
1116            match decode_rx_data_poll_count(tlv_value) {
1117                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1118                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1119            }
1120        }
1121        0x002C => {
1122            match decode_rx_beacon_count(tlv_value) {
1123                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1124                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1125            }
1126        }
1127        0x002D => {
1128            match decode_rx_beacon_request_count(tlv_value) {
1129                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1130                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1131            }
1132        }
1133        0x002E => {
1134            match decode_rx_other_count(tlv_value) {
1135                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1136                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1137            }
1138        }
1139        0x002F => {
1140            match decode_rx_address_filtered_count(tlv_value) {
1141                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1142                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1143            }
1144        }
1145        0x0030 => {
1146            match decode_rx_dest_addr_filtered_count(tlv_value) {
1147                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1148                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1149            }
1150        }
1151        0x0031 => {
1152            match decode_rx_duplicated_count(tlv_value) {
1153                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1154                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1155            }
1156        }
1157        0x0032 => {
1158            match decode_rx_err_no_frame_count(tlv_value) {
1159                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1160                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1161            }
1162        }
1163        0x0033 => {
1164            match decode_rx_err_unknown_neighbor_count(tlv_value) {
1165                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1166                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1167            }
1168        }
1169        0x0034 => {
1170            match decode_rx_err_invalid_src_addr_count(tlv_value) {
1171                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1172                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1173            }
1174        }
1175        0x0035 => {
1176            match decode_rx_err_sec_count(tlv_value) {
1177                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1178                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1179            }
1180        }
1181        0x0036 => {
1182            match decode_rx_err_fcs_count(tlv_value) {
1183                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1184                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1185            }
1186        }
1187        0x0037 => {
1188            match decode_rx_err_other_count(tlv_value) {
1189                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1190                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1191            }
1192        }
1193        0x0038 => {
1194            match decode_active_timestamp(tlv_value) {
1195                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1196                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1197            }
1198        }
1199        0x0039 => {
1200            match decode_pending_timestamp(tlv_value) {
1201                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1202                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1203            }
1204        }
1205        0x003A => {
1206            match decode_delay(tlv_value) {
1207                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1208                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1209            }
1210        }
1211        0x003B => {
1212            match decode_security_policy(tlv_value) {
1213                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1214                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1215            }
1216        }
1217        0x003C => {
1218            match decode_channel_page0_mask(tlv_value) {
1219                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1220                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1221            }
1222        }
1223        0x003D => {
1224            match decode_operational_dataset_components(tlv_value) {
1225                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1226                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1227            }
1228        }
1229        0x003E => {
1230            match decode_active_network_faults_list(tlv_value) {
1231                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1232                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1233            }
1234        }
1235        0x003F => {
1236            match decode_ext_address(tlv_value) {
1237                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1238                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1239            }
1240        }
1241        0x0040 => {
1242            match decode_rloc16(tlv_value) {
1243                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1244                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1245            }
1246        }
1247        _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
1248    }
1249}
1250
1251/// Get list of all attributes supported by this cluster
1252///
1253/// # Returns
1254/// Vector of tuples containing (attribute_id, attribute_name)
1255pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
1256    vec![
1257        (0x0000, "Channel"),
1258        (0x0001, "RoutingRole"),
1259        (0x0002, "NetworkName"),
1260        (0x0003, "PanId"),
1261        (0x0004, "ExtendedPanId"),
1262        (0x0005, "MeshLocalPrefix"),
1263        (0x0006, "OverrunCount"),
1264        (0x0007, "NeighborTable"),
1265        (0x0008, "RouteTable"),
1266        (0x0009, "PartitionId"),
1267        (0x000A, "Weighting"),
1268        (0x000B, "DataVersion"),
1269        (0x000C, "StableDataVersion"),
1270        (0x000D, "LeaderRouterId"),
1271        (0x000E, "DetachedRoleCount"),
1272        (0x000F, "ChildRoleCount"),
1273        (0x0010, "RouterRoleCount"),
1274        (0x0011, "LeaderRoleCount"),
1275        (0x0012, "AttachAttemptCount"),
1276        (0x0013, "PartitionIdChangeCount"),
1277        (0x0014, "BetterPartitionAttachAttemptCount"),
1278        (0x0015, "ParentChangeCount"),
1279        (0x0016, "TxTotalCount"),
1280        (0x0017, "TxUnicastCount"),
1281        (0x0018, "TxBroadcastCount"),
1282        (0x0019, "TxAckRequestedCount"),
1283        (0x001A, "TxAckedCount"),
1284        (0x001B, "TxNoAckRequestedCount"),
1285        (0x001C, "TxDataCount"),
1286        (0x001D, "TxDataPollCount"),
1287        (0x001E, "TxBeaconCount"),
1288        (0x001F, "TxBeaconRequestCount"),
1289        (0x0020, "TxOtherCount"),
1290        (0x0021, "TxRetryCount"),
1291        (0x0022, "TxDirectMaxRetryExpiryCount"),
1292        (0x0023, "TxIndirectMaxRetryExpiryCount"),
1293        (0x0024, "TxErrCcaCount"),
1294        (0x0025, "TxErrAbortCount"),
1295        (0x0026, "TxErrBusyChannelCount"),
1296        (0x0027, "RxTotalCount"),
1297        (0x0028, "RxUnicastCount"),
1298        (0x0029, "RxBroadcastCount"),
1299        (0x002A, "RxDataCount"),
1300        (0x002B, "RxDataPollCount"),
1301        (0x002C, "RxBeaconCount"),
1302        (0x002D, "RxBeaconRequestCount"),
1303        (0x002E, "RxOtherCount"),
1304        (0x002F, "RxAddressFilteredCount"),
1305        (0x0030, "RxDestAddrFilteredCount"),
1306        (0x0031, "RxDuplicatedCount"),
1307        (0x0032, "RxErrNoFrameCount"),
1308        (0x0033, "RxErrUnknownNeighborCount"),
1309        (0x0034, "RxErrInvalidSrcAddrCount"),
1310        (0x0035, "RxErrSecCount"),
1311        (0x0036, "RxErrFcsCount"),
1312        (0x0037, "RxErrOtherCount"),
1313        (0x0038, "ActiveTimestamp"),
1314        (0x0039, "PendingTimestamp"),
1315        (0x003A, "Delay"),
1316        (0x003B, "SecurityPolicy"),
1317        (0x003C, "ChannelPage0Mask"),
1318        (0x003D, "OperationalDatasetComponents"),
1319        (0x003E, "ActiveNetworkFaultsList"),
1320        (0x003F, "ExtAddress"),
1321        (0x0040, "Rloc16"),
1322    ]
1323}
1324
1325// Command listing
1326
1327pub fn get_command_list() -> Vec<(u32, &'static str)> {
1328    vec![
1329        (0x00, "ResetCounts"),
1330    ]
1331}
1332
1333pub fn get_command_name(cmd_id: u32) -> Option<&'static str> {
1334    match cmd_id {
1335        0x00 => Some("ResetCounts"),
1336        _ => None,
1337    }
1338}
1339
1340pub fn get_command_schema(cmd_id: u32) -> Option<Vec<crate::clusters::codec::CommandField>> {
1341    match cmd_id {
1342        0x00 => Some(vec![]),
1343        _ => None,
1344    }
1345}
1346
1347pub fn encode_command_json(cmd_id: u32, _args: &serde_json::Value) -> anyhow::Result<Vec<u8>> {
1348    match cmd_id {
1349        0x00 => Ok(vec![]),
1350        _ => Err(anyhow::anyhow!("unknown command ID: 0x{:02X}", cmd_id)),
1351    }
1352}
1353
1354// Typed facade (invokes + reads)
1355
1356/// Invoke `ResetCounts` command on cluster `Thread Network Diagnostics`.
1357pub async fn reset_counts(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<()> {
1358    conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_CMD_ID_RESETCOUNTS, &[]).await?;
1359    Ok(())
1360}
1361
1362/// Read `Channel` attribute from cluster `Thread Network Diagnostics`.
1363pub async fn read_channel(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u16>> {
1364    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_CHANNEL).await?;
1365    decode_channel(&tlv)
1366}
1367
1368/// Read `RoutingRole` attribute from cluster `Thread Network Diagnostics`.
1369pub async fn read_routing_role(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<RoutingRole>> {
1370    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_ROUTINGROLE).await?;
1371    decode_routing_role(&tlv)
1372}
1373
1374/// Read `NetworkName` attribute from cluster `Thread Network Diagnostics`.
1375pub async fn read_network_name(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<String>> {
1376    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_NETWORKNAME).await?;
1377    decode_network_name(&tlv)
1378}
1379
1380/// Read `PanId` attribute from cluster `Thread Network Diagnostics`.
1381pub async fn read_pan_id(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u16>> {
1382    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_PANID).await?;
1383    decode_pan_id(&tlv)
1384}
1385
1386/// Read `ExtendedPanId` attribute from cluster `Thread Network Diagnostics`.
1387pub async fn read_extended_pan_id(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u64>> {
1388    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_EXTENDEDPANID).await?;
1389    decode_extended_pan_id(&tlv)
1390}
1391
1392/// Read `MeshLocalPrefix` attribute from cluster `Thread Network Diagnostics`.
1393pub async fn read_mesh_local_prefix(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
1394    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_MESHLOCALPREFIX).await?;
1395    decode_mesh_local_prefix(&tlv)
1396}
1397
1398/// Read `OverrunCount` attribute from cluster `Thread Network Diagnostics`.
1399pub async fn read_overrun_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u64> {
1400    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_OVERRUNCOUNT).await?;
1401    decode_overrun_count(&tlv)
1402}
1403
1404/// Read `NeighborTable` attribute from cluster `Thread Network Diagnostics`.
1405pub async fn read_neighbor_table(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Vec<NeighborTable>> {
1406    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_NEIGHBORTABLE).await?;
1407    decode_neighbor_table(&tlv)
1408}
1409
1410/// Read `RouteTable` attribute from cluster `Thread Network Diagnostics`.
1411pub async fn read_route_table(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Vec<RouteTable>> {
1412    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_ROUTETABLE).await?;
1413    decode_route_table(&tlv)
1414}
1415
1416/// Read `PartitionId` attribute from cluster `Thread Network Diagnostics`.
1417pub async fn read_partition_id(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u32>> {
1418    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_PARTITIONID).await?;
1419    decode_partition_id(&tlv)
1420}
1421
1422/// Read `Weighting` attribute from cluster `Thread Network Diagnostics`.
1423pub async fn read_weighting(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u16>> {
1424    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_WEIGHTING).await?;
1425    decode_weighting(&tlv)
1426}
1427
1428/// Read `DataVersion` attribute from cluster `Thread Network Diagnostics`.
1429pub async fn read_data_version(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u16>> {
1430    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_DATAVERSION).await?;
1431    decode_data_version(&tlv)
1432}
1433
1434/// Read `StableDataVersion` attribute from cluster `Thread Network Diagnostics`.
1435pub async fn read_stable_data_version(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u16>> {
1436    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_STABLEDATAVERSION).await?;
1437    decode_stable_data_version(&tlv)
1438}
1439
1440/// Read `LeaderRouterId` attribute from cluster `Thread Network Diagnostics`.
1441pub async fn read_leader_router_id(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
1442    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_LEADERROUTERID).await?;
1443    decode_leader_router_id(&tlv)
1444}
1445
1446/// Read `DetachedRoleCount` attribute from cluster `Thread Network Diagnostics`.
1447pub async fn read_detached_role_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
1448    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_DETACHEDROLECOUNT).await?;
1449    decode_detached_role_count(&tlv)
1450}
1451
1452/// Read `ChildRoleCount` attribute from cluster `Thread Network Diagnostics`.
1453pub async fn read_child_role_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
1454    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_CHILDROLECOUNT).await?;
1455    decode_child_role_count(&tlv)
1456}
1457
1458/// Read `RouterRoleCount` attribute from cluster `Thread Network Diagnostics`.
1459pub async fn read_router_role_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
1460    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_ROUTERROLECOUNT).await?;
1461    decode_router_role_count(&tlv)
1462}
1463
1464/// Read `LeaderRoleCount` attribute from cluster `Thread Network Diagnostics`.
1465pub async fn read_leader_role_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
1466    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_LEADERROLECOUNT).await?;
1467    decode_leader_role_count(&tlv)
1468}
1469
1470/// Read `AttachAttemptCount` attribute from cluster `Thread Network Diagnostics`.
1471pub async fn read_attach_attempt_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
1472    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_ATTACHATTEMPTCOUNT).await?;
1473    decode_attach_attempt_count(&tlv)
1474}
1475
1476/// Read `PartitionIdChangeCount` attribute from cluster `Thread Network Diagnostics`.
1477pub async fn read_partition_id_change_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
1478    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_PARTITIONIDCHANGECOUNT).await?;
1479    decode_partition_id_change_count(&tlv)
1480}
1481
1482/// Read `BetterPartitionAttachAttemptCount` attribute from cluster `Thread Network Diagnostics`.
1483pub async fn read_better_partition_attach_attempt_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
1484    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_BETTERPARTITIONATTACHATTEMPTCOUNT).await?;
1485    decode_better_partition_attach_attempt_count(&tlv)
1486}
1487
1488/// Read `ParentChangeCount` attribute from cluster `Thread Network Diagnostics`.
1489pub async fn read_parent_change_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
1490    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_PARENTCHANGECOUNT).await?;
1491    decode_parent_change_count(&tlv)
1492}
1493
1494/// Read `TxTotalCount` attribute from cluster `Thread Network Diagnostics`.
1495pub async fn read_tx_total_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1496    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_TXTOTALCOUNT).await?;
1497    decode_tx_total_count(&tlv)
1498}
1499
1500/// Read `TxUnicastCount` attribute from cluster `Thread Network Diagnostics`.
1501pub async fn read_tx_unicast_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1502    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_TXUNICASTCOUNT).await?;
1503    decode_tx_unicast_count(&tlv)
1504}
1505
1506/// Read `TxBroadcastCount` attribute from cluster `Thread Network Diagnostics`.
1507pub async fn read_tx_broadcast_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1508    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_TXBROADCASTCOUNT).await?;
1509    decode_tx_broadcast_count(&tlv)
1510}
1511
1512/// Read `TxAckRequestedCount` attribute from cluster `Thread Network Diagnostics`.
1513pub async fn read_tx_ack_requested_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1514    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_TXACKREQUESTEDCOUNT).await?;
1515    decode_tx_ack_requested_count(&tlv)
1516}
1517
1518/// Read `TxAckedCount` attribute from cluster `Thread Network Diagnostics`.
1519pub async fn read_tx_acked_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1520    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_TXACKEDCOUNT).await?;
1521    decode_tx_acked_count(&tlv)
1522}
1523
1524/// Read `TxNoAckRequestedCount` attribute from cluster `Thread Network Diagnostics`.
1525pub async fn read_tx_no_ack_requested_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1526    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_TXNOACKREQUESTEDCOUNT).await?;
1527    decode_tx_no_ack_requested_count(&tlv)
1528}
1529
1530/// Read `TxDataCount` attribute from cluster `Thread Network Diagnostics`.
1531pub async fn read_tx_data_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1532    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_TXDATACOUNT).await?;
1533    decode_tx_data_count(&tlv)
1534}
1535
1536/// Read `TxDataPollCount` attribute from cluster `Thread Network Diagnostics`.
1537pub async fn read_tx_data_poll_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1538    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_TXDATAPOLLCOUNT).await?;
1539    decode_tx_data_poll_count(&tlv)
1540}
1541
1542/// Read `TxBeaconCount` attribute from cluster `Thread Network Diagnostics`.
1543pub async fn read_tx_beacon_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1544    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_TXBEACONCOUNT).await?;
1545    decode_tx_beacon_count(&tlv)
1546}
1547
1548/// Read `TxBeaconRequestCount` attribute from cluster `Thread Network Diagnostics`.
1549pub async fn read_tx_beacon_request_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1550    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_TXBEACONREQUESTCOUNT).await?;
1551    decode_tx_beacon_request_count(&tlv)
1552}
1553
1554/// Read `TxOtherCount` attribute from cluster `Thread Network Diagnostics`.
1555pub async fn read_tx_other_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1556    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_TXOTHERCOUNT).await?;
1557    decode_tx_other_count(&tlv)
1558}
1559
1560/// Read `TxRetryCount` attribute from cluster `Thread Network Diagnostics`.
1561pub async fn read_tx_retry_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1562    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_TXRETRYCOUNT).await?;
1563    decode_tx_retry_count(&tlv)
1564}
1565
1566/// Read `TxDirectMaxRetryExpiryCount` attribute from cluster `Thread Network Diagnostics`.
1567pub async fn read_tx_direct_max_retry_expiry_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1568    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_TXDIRECTMAXRETRYEXPIRYCOUNT).await?;
1569    decode_tx_direct_max_retry_expiry_count(&tlv)
1570}
1571
1572/// Read `TxIndirectMaxRetryExpiryCount` attribute from cluster `Thread Network Diagnostics`.
1573pub async fn read_tx_indirect_max_retry_expiry_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1574    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_TXINDIRECTMAXRETRYEXPIRYCOUNT).await?;
1575    decode_tx_indirect_max_retry_expiry_count(&tlv)
1576}
1577
1578/// Read `TxErrCcaCount` attribute from cluster `Thread Network Diagnostics`.
1579pub async fn read_tx_err_cca_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1580    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_TXERRCCACOUNT).await?;
1581    decode_tx_err_cca_count(&tlv)
1582}
1583
1584/// Read `TxErrAbortCount` attribute from cluster `Thread Network Diagnostics`.
1585pub async fn read_tx_err_abort_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1586    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_TXERRABORTCOUNT).await?;
1587    decode_tx_err_abort_count(&tlv)
1588}
1589
1590/// Read `TxErrBusyChannelCount` attribute from cluster `Thread Network Diagnostics`.
1591pub async fn read_tx_err_busy_channel_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1592    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_TXERRBUSYCHANNELCOUNT).await?;
1593    decode_tx_err_busy_channel_count(&tlv)
1594}
1595
1596/// Read `RxTotalCount` attribute from cluster `Thread Network Diagnostics`.
1597pub async fn read_rx_total_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1598    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_RXTOTALCOUNT).await?;
1599    decode_rx_total_count(&tlv)
1600}
1601
1602/// Read `RxUnicastCount` attribute from cluster `Thread Network Diagnostics`.
1603pub async fn read_rx_unicast_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1604    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_RXUNICASTCOUNT).await?;
1605    decode_rx_unicast_count(&tlv)
1606}
1607
1608/// Read `RxBroadcastCount` attribute from cluster `Thread Network Diagnostics`.
1609pub async fn read_rx_broadcast_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1610    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_RXBROADCASTCOUNT).await?;
1611    decode_rx_broadcast_count(&tlv)
1612}
1613
1614/// Read `RxDataCount` attribute from cluster `Thread Network Diagnostics`.
1615pub async fn read_rx_data_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1616    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_RXDATACOUNT).await?;
1617    decode_rx_data_count(&tlv)
1618}
1619
1620/// Read `RxDataPollCount` attribute from cluster `Thread Network Diagnostics`.
1621pub async fn read_rx_data_poll_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1622    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_RXDATAPOLLCOUNT).await?;
1623    decode_rx_data_poll_count(&tlv)
1624}
1625
1626/// Read `RxBeaconCount` attribute from cluster `Thread Network Diagnostics`.
1627pub async fn read_rx_beacon_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1628    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_RXBEACONCOUNT).await?;
1629    decode_rx_beacon_count(&tlv)
1630}
1631
1632/// Read `RxBeaconRequestCount` attribute from cluster `Thread Network Diagnostics`.
1633pub async fn read_rx_beacon_request_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1634    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_RXBEACONREQUESTCOUNT).await?;
1635    decode_rx_beacon_request_count(&tlv)
1636}
1637
1638/// Read `RxOtherCount` attribute from cluster `Thread Network Diagnostics`.
1639pub async fn read_rx_other_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1640    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_RXOTHERCOUNT).await?;
1641    decode_rx_other_count(&tlv)
1642}
1643
1644/// Read `RxAddressFilteredCount` attribute from cluster `Thread Network Diagnostics`.
1645pub async fn read_rx_address_filtered_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1646    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_RXADDRESSFILTEREDCOUNT).await?;
1647    decode_rx_address_filtered_count(&tlv)
1648}
1649
1650/// Read `RxDestAddrFilteredCount` attribute from cluster `Thread Network Diagnostics`.
1651pub async fn read_rx_dest_addr_filtered_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1652    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_RXDESTADDRFILTEREDCOUNT).await?;
1653    decode_rx_dest_addr_filtered_count(&tlv)
1654}
1655
1656/// Read `RxDuplicatedCount` attribute from cluster `Thread Network Diagnostics`.
1657pub async fn read_rx_duplicated_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1658    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_RXDUPLICATEDCOUNT).await?;
1659    decode_rx_duplicated_count(&tlv)
1660}
1661
1662/// Read `RxErrNoFrameCount` attribute from cluster `Thread Network Diagnostics`.
1663pub async fn read_rx_err_no_frame_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1664    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_RXERRNOFRAMECOUNT).await?;
1665    decode_rx_err_no_frame_count(&tlv)
1666}
1667
1668/// Read `RxErrUnknownNeighborCount` attribute from cluster `Thread Network Diagnostics`.
1669pub async fn read_rx_err_unknown_neighbor_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1670    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_RXERRUNKNOWNNEIGHBORCOUNT).await?;
1671    decode_rx_err_unknown_neighbor_count(&tlv)
1672}
1673
1674/// Read `RxErrInvalidSrcAddrCount` attribute from cluster `Thread Network Diagnostics`.
1675pub async fn read_rx_err_invalid_src_addr_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1676    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_RXERRINVALIDSRCADDRCOUNT).await?;
1677    decode_rx_err_invalid_src_addr_count(&tlv)
1678}
1679
1680/// Read `RxErrSecCount` attribute from cluster `Thread Network Diagnostics`.
1681pub async fn read_rx_err_sec_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1682    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_RXERRSECCOUNT).await?;
1683    decode_rx_err_sec_count(&tlv)
1684}
1685
1686/// Read `RxErrFcsCount` attribute from cluster `Thread Network Diagnostics`.
1687pub async fn read_rx_err_fcs_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1688    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_RXERRFCSCOUNT).await?;
1689    decode_rx_err_fcs_count(&tlv)
1690}
1691
1692/// Read `RxErrOtherCount` attribute from cluster `Thread Network Diagnostics`.
1693pub async fn read_rx_err_other_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
1694    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_RXERROTHERCOUNT).await?;
1695    decode_rx_err_other_count(&tlv)
1696}
1697
1698/// Read `ActiveTimestamp` attribute from cluster `Thread Network Diagnostics`.
1699pub async fn read_active_timestamp(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u64>> {
1700    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_ACTIVETIMESTAMP).await?;
1701    decode_active_timestamp(&tlv)
1702}
1703
1704/// Read `PendingTimestamp` attribute from cluster `Thread Network Diagnostics`.
1705pub async fn read_pending_timestamp(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u64>> {
1706    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_PENDINGTIMESTAMP).await?;
1707    decode_pending_timestamp(&tlv)
1708}
1709
1710/// Read `Delay` attribute from cluster `Thread Network Diagnostics`.
1711pub async fn read_delay(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u32>> {
1712    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_DELAY).await?;
1713    decode_delay(&tlv)
1714}
1715
1716/// Read `SecurityPolicy` attribute from cluster `Thread Network Diagnostics`.
1717pub async fn read_security_policy(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<SecurityPolicy>> {
1718    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_SECURITYPOLICY).await?;
1719    decode_security_policy(&tlv)
1720}
1721
1722/// Read `ChannelPage0Mask` attribute from cluster `Thread Network Diagnostics`.
1723pub async fn read_channel_page0_mask(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<Vec<u8>>> {
1724    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_CHANNELPAGE0MASK).await?;
1725    decode_channel_page0_mask(&tlv)
1726}
1727
1728/// Read `OperationalDatasetComponents` attribute from cluster `Thread Network Diagnostics`.
1729pub async fn read_operational_dataset_components(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<OperationalDatasetComponents>> {
1730    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_OPERATIONALDATASETCOMPONENTS).await?;
1731    decode_operational_dataset_components(&tlv)
1732}
1733
1734/// Read `ActiveNetworkFaultsList` attribute from cluster `Thread Network Diagnostics`.
1735pub async fn read_active_network_faults_list(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Vec<NetworkFault>> {
1736    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_ACTIVENETWORKFAULTSLIST).await?;
1737    decode_active_network_faults_list(&tlv)
1738}
1739
1740/// Read `ExtAddress` attribute from cluster `Thread Network Diagnostics`.
1741pub async fn read_ext_address(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u64>> {
1742    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_EXTADDRESS).await?;
1743    decode_ext_address(&tlv)
1744}
1745
1746/// Read `Rloc16` attribute from cluster `Thread Network Diagnostics`.
1747pub async fn read_rloc16(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u16>> {
1748    let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_THREAD_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_THREAD_NETWORK_DIAGNOSTICS_ATTR_ID_RLOC16).await?;
1749    decode_rloc16(&tlv)
1750}
1751
1752#[derive(Debug, serde::Serialize)]
1753pub struct ConnectionStatusEvent {
1754    pub connection_status: Option<ConnectionStatus>,
1755}
1756
1757#[derive(Debug, serde::Serialize)]
1758pub struct NetworkFaultChangeEvent {
1759    pub current: Option<Vec<NetworkFault>>,
1760    pub previous: Option<Vec<NetworkFault>>,
1761}
1762
1763// Event decoders
1764
1765/// Decode ConnectionStatus event (0x00, priority: info)
1766pub fn decode_connection_status_event(inp: &tlv::TlvItemValue) -> anyhow::Result<ConnectionStatusEvent> {
1767    if let tlv::TlvItemValue::List(_fields) = inp {
1768        let item = tlv::TlvItem { tag: 0, value: inp.clone() };
1769        Ok(ConnectionStatusEvent {
1770                                connection_status: item.get_int(&[0]).and_then(|v| ConnectionStatus::from_u8(v as u8)),
1771        })
1772    } else {
1773        Err(anyhow::anyhow!("Expected struct fields"))
1774    }
1775}
1776
1777/// Decode NetworkFaultChange event (0x01, priority: info)
1778pub fn decode_network_fault_change_event(inp: &tlv::TlvItemValue) -> anyhow::Result<NetworkFaultChangeEvent> {
1779    if let tlv::TlvItemValue::List(_fields) = inp {
1780        let item = tlv::TlvItem { tag: 0, value: inp.clone() };
1781        Ok(NetworkFaultChangeEvent {
1782                                current: {
1783                    if let Some(tlv::TlvItemValue::List(l)) = item.get(&[0]) {
1784                        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();
1785                        Some(items)
1786                    } else {
1787                        None
1788                    }
1789                },
1790                                previous: {
1791                    if let Some(tlv::TlvItemValue::List(l)) = item.get(&[1]) {
1792                        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();
1793                        Some(items)
1794                    } else {
1795                        None
1796                    }
1797                },
1798        })
1799    } else {
1800        Err(anyhow::anyhow!("Expected struct fields"))
1801    }
1802}
1803