1use core::fmt::Debug;
21
22use rs_matter_macros::{FromTLV, ToTLV};
23
24use crate::dm::{ArrayAttributeRead, Dataver, InvokeContext, ReadContext};
25use crate::error::{Error, ErrorCode};
26use crate::tlv::{
27 Nullable, NullableBuilder, Octets, OctetsBuilder, TLVBuilderParent, ToTLVArrayBuilder,
28 ToTLVBuilder, Utf8StrBuilder,
29};
30use crate::with;
31
32pub use crate::dm::clusters::decl::thread_network_diagnostics::*;
33
34use super::wifi_diag::WirelessDiag;
35
36#[derive(Debug, Clone, Eq, PartialEq, Hash, FromTLV, ToTLV)]
38#[cfg_attr(feature = "defmt", derive(defmt::Format))]
39pub struct NeighborTable {
40 pub ext_address: u64,
41 pub age: u32,
42 pub rloc16: u16,
43 pub link_frame_counter: u32,
44 pub mle_frame_counter: u32,
45 pub lqi: u8,
46 pub average_rssi: Option<i8>,
47 pub last_rssi: Option<i8>,
48 pub frame_error_rate: u8,
49 pub message_error_rate: u8,
50 pub rx_on_when_idle: bool,
51 pub full_thread_device: bool,
52 pub full_network_data: bool,
53 pub is_child: bool,
54}
55
56#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Default)]
63#[cfg_attr(feature = "defmt", derive(defmt::Format))]
64pub struct MacCounters {
65 pub tx_total_count: u32,
66 pub tx_unicast_count: u32,
67 pub tx_broadcast_count: u32,
68 pub tx_ack_requested_count: u32,
69 pub tx_acked_count: u32,
70 pub tx_no_ack_requested_count: u32,
71 pub tx_data_count: u32,
72 pub tx_data_poll_count: u32,
73 pub tx_beacon_count: u32,
74 pub tx_beacon_request_count: u32,
75 pub tx_other_count: u32,
76 pub tx_retry_count: u32,
77 pub tx_direct_max_retry_expiry_count: Option<u32>,
78 pub tx_indirect_max_retry_expiry_count: Option<u32>,
79 pub tx_err_cca_count: u32,
80 pub tx_err_abort_count: u32,
81 pub tx_err_busy_channel_count: u32,
82 pub rx_total_count: u32,
83 pub rx_unicast_count: u32,
84 pub rx_broadcast_count: u32,
85 pub rx_data_count: u32,
86 pub rx_data_poll_count: u32,
87 pub rx_beacon_count: u32,
88 pub rx_beacon_request_count: u32,
89 pub rx_other_count: u32,
90 pub rx_address_filtered_count: u32,
91 pub rx_dest_addr_filtered_count: u32,
92 pub rx_duplicated_count: u32,
93 pub rx_err_no_frame_count: u32,
94 pub rx_err_unknown_neighbor_count: u32,
95 pub rx_err_invalid_src_addr_count: u32,
96 pub rx_err_sec_count: u32,
97 pub rx_err_fcs_count: u32,
98 pub rx_err_other_count: u32,
99}
100
101impl NeighborTable {
102 fn read_into<P: TLVBuilderParent>(
104 &self,
105 builder: NeighborTableStructBuilder<P>,
106 ) -> Result<P, Error> {
107 builder
108 .ext_address(self.ext_address)?
109 .age(self.age)?
110 .rloc_16(self.rloc16)?
111 .link_frame_counter(self.link_frame_counter)?
112 .mle_frame_counter(self.mle_frame_counter)?
113 .lqi(self.lqi)?
114 .average_rssi(Nullable::new(self.average_rssi))?
115 .last_rssi(Nullable::new(self.last_rssi))?
116 .frame_error_rate(self.frame_error_rate)?
117 .message_error_rate(self.message_error_rate)?
118 .rx_on_when_idle(self.rx_on_when_idle)?
119 .full_thread_device(self.full_thread_device)?
120 .full_network_data(self.full_network_data)?
121 .is_child(self.is_child)?
122 .end()
123 }
124}
125
126#[derive(Debug, Clone, Eq, PartialEq, Hash, FromTLV, ToTLV)]
128#[cfg_attr(feature = "defmt", derive(defmt::Format))]
129pub struct RouteTable {
130 pub ext_address: u64,
131 pub rloc16: u16,
132 pub router_id: u8,
133 pub next_hop: u8,
134 pub path_cost: u8,
135 pub lqi_in: u8,
136 pub lqi_out: u8,
137 pub age: u8,
138 pub allocated: bool,
139 pub link_established: bool,
140}
141
142impl RouteTable {
143 fn read_into<P: TLVBuilderParent>(
145 &self,
146 builder: RouteTableStructBuilder<P>,
147 ) -> Result<P, Error> {
148 builder
149 .ext_address(self.ext_address)?
150 .rloc_16(self.rloc16)?
151 .router_id(self.router_id)?
152 .next_hop(self.next_hop)?
153 .path_cost(self.path_cost)?
154 .lqi_in(self.lqi_in)?
155 .lqi_out(self.lqi_out)?
156 .age(self.age)?
157 .allocated(self.allocated)?
158 .link_established(self.link_established)?
159 .end()
160 }
161}
162
163#[derive(Debug, Clone, Eq, PartialEq, Hash, FromTLV, ToTLV)]
165#[cfg_attr(feature = "defmt", derive(defmt::Format))]
166pub struct SecurityPolicy {
167 pub rotation_time: u16,
168 pub flags: u16,
169}
170
171#[derive(Debug, Clone, Eq, PartialEq, Hash, FromTLV, ToTLV)]
173#[cfg_attr(feature = "defmt", derive(defmt::Format))]
174pub struct OperationalDatasetComponents {
175 pub active_timestamp_present: bool,
176 pub pending_timestamp_present: bool,
177 pub master_key_present: bool,
178 pub network_name_present: bool,
179 pub extended_pan_id_present: bool,
180 pub mesh_local_prefix_present: bool,
181 pub delay_present: bool,
182 pub pan_id_present: bool,
183 pub channel_present: bool,
184 pub pskc_present: bool,
185 pub security_policy_present: bool,
186 pub channel_mask_present: bool,
187}
188
189impl OperationalDatasetComponents {
190 fn read_into<P: TLVBuilderParent>(
192 &self,
193 builder: OperationalDatasetComponentsBuilder<P>,
194 ) -> Result<P, Error> {
195 builder
196 .active_timestamp_present(self.active_timestamp_present)?
197 .pending_timestamp_present(self.pending_timestamp_present)?
198 .master_key_present(self.master_key_present)?
199 .network_name_present(self.network_name_present)?
200 .extended_pan_id_present(self.extended_pan_id_present)?
201 .mesh_local_prefix_present(self.mesh_local_prefix_present)?
202 .delay_present(self.delay_present)?
203 .pan_id_present(self.pan_id_present)?
204 .channel_present(self.channel_present)?
205 .pskc_present(self.pskc_present)?
206 .security_policy_present(self.security_policy_present)?
207 .channel_mask_present(self.channel_mask_present)?
208 .end()
209 }
210}
211
212pub trait ThreadDiag: WirelessDiag {
217 fn channel(&self) -> Result<Option<u16>, Error> {
218 Ok(None)
219 }
220
221 fn routing_role(&self) -> Result<Option<RoutingRoleEnum>, Error> {
222 Ok(None)
223 }
224
225 fn network_name(
226 &self,
227 f: &mut dyn FnMut(Option<&str>) -> Result<(), Error>,
228 ) -> Result<(), Error> {
229 f(None)
230 }
231
232 fn pan_id(&self) -> Result<Option<u16>, Error> {
233 Ok(None)
234 }
235
236 fn extended_pan_id(&self) -> Result<Option<u64>, Error> {
237 Ok(None)
238 }
239
240 #[allow(clippy::type_complexity)]
241 fn mesh_local_prefix(
242 &self,
243 f: &mut dyn FnMut(Option<&[u8]>) -> Result<(), Error>,
244 ) -> Result<(), Error> {
245 f(None)
246 }
247
248 fn neighbor_table(
249 &self,
250 _f: &mut dyn FnMut(&NeighborTable) -> Result<(), Error>,
251 ) -> Result<(), Error> {
252 Ok(())
253 }
254
255 fn route_table(
256 &self,
257 _f: &mut dyn FnMut(&RouteTable) -> Result<(), Error>,
258 ) -> Result<(), Error> {
259 Ok(())
260 }
261
262 fn partition_id(&self) -> Result<Option<u32>, Error> {
263 Ok(None)
264 }
265
266 fn weighting(&self) -> Result<Option<u16>, Error> {
267 Ok(None)
268 }
269
270 fn data_version(&self) -> Result<Option<u16>, Error> {
271 Ok(None)
272 }
273
274 fn stable_data_version(&self) -> Result<Option<u16>, Error> {
275 Ok(None)
276 }
277
278 fn leader_router_id(&self) -> Result<Option<u8>, Error> {
279 Ok(None)
280 }
281
282 fn ext_address(&self) -> Result<Option<u64>, Error> {
283 Ok(None)
284 }
285
286 fn rloc_16(&self) -> Result<Option<u16>, Error> {
287 Ok(None)
288 }
289
290 fn security_policy(&self) -> Result<Option<SecurityPolicy>, Error> {
291 Ok(None)
292 }
293
294 #[allow(clippy::type_complexity)]
295 fn channel_page0_mask(
296 &self,
297 f: &mut dyn FnMut(Option<&[u8]>) -> Result<(), Error>,
298 ) -> Result<(), Error> {
299 f(None)
300 }
301
302 #[allow(clippy::type_complexity)]
303 fn operational_dataset_components(
304 &self,
305 f: &mut dyn FnMut(Option<&OperationalDatasetComponents>) -> Result<(), Error>,
306 ) -> Result<(), Error> {
307 f(None)
308 }
309
310 #[allow(clippy::type_complexity)]
311 fn active_network_faults_list(
312 &self,
313 _f: &mut dyn FnMut(NetworkFaultEnum) -> Result<(), Error>,
314 ) -> Result<(), Error> {
315 Ok(())
316 }
317
318 #[allow(clippy::type_complexity)]
326 fn mac_counters(
327 &self,
328 f: &mut dyn FnMut(Option<&MacCounters>) -> Result<(), Error>,
329 ) -> Result<(), Error> {
330 f(None)
331 }
332}
333
334impl<T> ThreadDiag for &T
335where
336 T: ThreadDiag,
337{
338 fn mac_counters(
339 &self,
340 f: &mut dyn FnMut(Option<&MacCounters>) -> Result<(), Error>,
341 ) -> Result<(), Error> {
342 (*self).mac_counters(f)
343 }
344
345 fn channel(&self) -> Result<Option<u16>, Error> {
346 (*self).channel()
347 }
348
349 fn routing_role(&self) -> Result<Option<RoutingRoleEnum>, Error> {
350 (*self).routing_role()
351 }
352
353 fn network_name(
354 &self,
355 f: &mut dyn FnMut(Option<&str>) -> Result<(), Error>,
356 ) -> Result<(), Error> {
357 (*self).network_name(f)
358 }
359
360 fn pan_id(&self) -> Result<Option<u16>, Error> {
361 (*self).pan_id()
362 }
363
364 fn extended_pan_id(&self) -> Result<Option<u64>, Error> {
365 (*self).extended_pan_id()
366 }
367
368 fn mesh_local_prefix(
369 &self,
370 f: &mut dyn FnMut(Option<&[u8]>) -> Result<(), Error>,
371 ) -> Result<(), Error> {
372 (*self).mesh_local_prefix(f)
373 }
374
375 fn neighbor_table(
376 &self,
377 f: &mut dyn FnMut(&NeighborTable) -> Result<(), Error>,
378 ) -> Result<(), Error> {
379 (*self).neighbor_table(f)
380 }
381
382 fn route_table(
383 &self,
384 f: &mut dyn FnMut(&RouteTable) -> Result<(), Error>,
385 ) -> Result<(), Error> {
386 (*self).route_table(f)
387 }
388
389 fn partition_id(&self) -> Result<Option<u32>, Error> {
390 (*self).partition_id()
391 }
392
393 fn weighting(&self) -> Result<Option<u16>, Error> {
394 (*self).weighting()
395 }
396
397 fn data_version(&self) -> Result<Option<u16>, Error> {
398 (*self).data_version()
399 }
400
401 fn stable_data_version(&self) -> Result<Option<u16>, Error> {
402 (*self).stable_data_version()
403 }
404
405 fn leader_router_id(&self) -> Result<Option<u8>, Error> {
406 (*self).leader_router_id()
407 }
408
409 fn ext_address(&self) -> Result<Option<u64>, Error> {
410 (*self).ext_address()
411 }
412
413 fn rloc_16(&self) -> Result<Option<u16>, Error> {
414 (*self).rloc_16()
415 }
416
417 fn security_policy(&self) -> Result<Option<SecurityPolicy>, Error> {
418 (*self).security_policy()
419 }
420
421 fn channel_page0_mask(
422 &self,
423 f: &mut dyn FnMut(Option<&[u8]>) -> Result<(), Error>,
424 ) -> Result<(), Error> {
425 (*self).channel_page0_mask(f)
426 }
427
428 fn operational_dataset_components(
429 &self,
430 f: &mut dyn FnMut(Option<&OperationalDatasetComponents>) -> Result<(), Error>,
431 ) -> Result<(), Error> {
432 (*self).operational_dataset_components(f)
433 }
434
435 fn active_network_faults_list(
436 &self,
437 f: &mut dyn FnMut(NetworkFaultEnum) -> Result<(), Error>,
438 ) -> Result<(), Error> {
439 (*self).active_network_faults_list(f)
440 }
441}
442
443impl ThreadDiag for () {}
444
445#[derive(Clone)]
447pub struct ThreadDiagHandler<'a> {
448 dataver: Dataver,
449 diag: &'a dyn ThreadDiag,
450}
451
452impl<'a> ThreadDiagHandler<'a> {
453 pub const fn new(dataver: Dataver, diag: &'a dyn ThreadDiag) -> Self {
455 Self { dataver, diag }
456 }
457
458 fn counter(&self, pick: impl FnOnce(&MacCounters) -> Option<u32>) -> Result<u32, Error> {
462 let mut pick = Some(pick);
463 let mut value = None;
464
465 self.diag.mac_counters(&mut |counters| {
466 if let (Some(counters), Some(pick)) = (counters, pick.take()) {
467 value = pick(counters);
468 }
469
470 Ok(())
471 })?;
472
473 value.ok_or_else(|| ErrorCode::AttributeNotFound.into())
474 }
475
476 pub const fn adapt(self) -> HandlerAdaptor<Self> {
478 HandlerAdaptor(self)
479 }
480}
481
482impl ClusterHandler for ThreadDiagHandler<'_> {
483 const CLUSTER: crate::dm::Cluster<'static> =
484 FULL_CLUSTER.with_attrs(with!(required)).with_cmds(with!());
485
486 fn dataver(&self) -> u32 {
487 self.dataver.get()
488 }
489
490 fn dataver_changed(&self) {
491 self.dataver.changed();
492 }
493
494 fn channel(&self, _ctx: impl ReadContext) -> Result<Nullable<u16>, Error> {
495 Ok(Nullable::new(self.diag.channel()?))
496 }
497
498 fn routing_role(&self, _ctx: impl ReadContext) -> Result<Nullable<RoutingRoleEnum>, Error> {
499 Ok(Nullable::new(self.diag.routing_role()?))
500 }
501
502 fn network_name<P: TLVBuilderParent>(
503 &self,
504 _ctx: impl ReadContext,
505 builder: NullableBuilder<P, Utf8StrBuilder<P>>,
506 ) -> Result<P, Error> {
507 let mut builder = Some(builder);
508 let mut parent = None;
509
510 self.diag.network_name(&mut |name| {
511 if let Some(name) = name {
512 parent = Some(unwrap!(builder.take()).non_null()?.set(name)?);
513 } else {
514 parent = Some(unwrap!(builder.take()).null()?);
515 }
516
517 Ok(())
518 })?;
519
520 Ok(unwrap!(parent))
521 }
522
523 fn pan_id(&self, _ctx: impl ReadContext) -> Result<Nullable<u16>, Error> {
524 Ok(Nullable::new(self.diag.pan_id()?))
525 }
526
527 fn extended_pan_id(&self, _ctx: impl ReadContext) -> Result<Nullable<u64>, Error> {
528 Ok(Nullable::new(self.diag.extended_pan_id()?))
529 }
530
531 fn mesh_local_prefix<P: TLVBuilderParent>(
532 &self,
533 _ctx: impl ReadContext,
534 builder: NullableBuilder<P, OctetsBuilder<P>>,
535 ) -> Result<P, Error> {
536 let mut builder = Some(builder);
537 let mut parent = None;
538
539 self.diag.mesh_local_prefix(&mut |prefix| {
540 if let Some(prefix) = prefix {
541 parent = Some(
542 unwrap!(builder.take())
543 .non_null()?
544 .set(Octets::new(prefix))?,
545 );
546 } else {
547 parent = Some(unwrap!(builder.take()).null()?);
548 }
549
550 Ok(())
551 })?;
552
553 Ok(unwrap!(parent))
554 }
555
556 fn neighbor_table<P: TLVBuilderParent>(
557 &self,
558 _ctx: impl ReadContext,
559 builder: ArrayAttributeRead<
560 NeighborTableStructArrayBuilder<P>,
561 NeighborTableStructBuilder<P>,
562 >,
563 ) -> Result<P, Error> {
564 match builder {
565 ArrayAttributeRead::ReadAll(builder) => {
566 let mut builder = Some(builder);
567
568 self.diag.neighbor_table(&mut |item| {
569 builder = Some(item.read_into(unwrap!(builder.take()).push()?)?);
570
571 Ok(())
572 })?;
573
574 unwrap!(builder).end()
575 }
576 ArrayAttributeRead::ReadOne(index, builder) => {
577 let mut builder = Some(builder);
578 let mut parent = None;
579 let mut current = 0;
580
581 self.diag.neighbor_table(&mut |item| {
582 if index == current {
583 parent = Some(item.read_into(unwrap!(builder.take()))?);
584 }
585
586 current += 1;
587
588 Ok(())
589 })?;
590
591 if let Some(parent) = parent {
592 Ok(parent)
593 } else {
594 Err(ErrorCode::InvalidAction.into())
595 }
596 }
597 ArrayAttributeRead::ReadNone(builder) => builder.end(),
598 }
599 }
600
601 fn route_table<P: TLVBuilderParent>(
602 &self,
603 _ctx: impl ReadContext,
604 builder: ArrayAttributeRead<RouteTableStructArrayBuilder<P>, RouteTableStructBuilder<P>>,
605 ) -> Result<P, Error> {
606 match builder {
607 ArrayAttributeRead::ReadAll(builder) => {
608 let mut builder = Some(builder);
609
610 self.diag.route_table(&mut |item| {
611 builder = Some(item.read_into(unwrap!(builder.take()).push()?)?);
612
613 Ok(())
614 })?;
615
616 unwrap!(builder).end()
617 }
618 ArrayAttributeRead::ReadOne(index, builder) => {
619 let mut builder = Some(builder);
620 let mut parent = None;
621 let mut current = 0;
622
623 self.diag.route_table(&mut |item| {
624 if index == current {
625 parent = Some(item.read_into(unwrap!(builder.take()))?);
626 }
627
628 current += 1;
629
630 Ok(())
631 })?;
632
633 if let Some(parent) = parent {
634 Ok(parent)
635 } else {
636 Err(ErrorCode::InvalidAction.into())
637 }
638 }
639 ArrayAttributeRead::ReadNone(builder) => builder.end(),
640 }
641 }
642
643 fn partition_id(&self, _ctx: impl ReadContext) -> Result<Nullable<u32>, Error> {
644 Ok(Nullable::new(self.diag.partition_id()?))
645 }
646
647 fn weighting(&self, _ctx: impl ReadContext) -> Result<Nullable<u16>, Error> {
648 Ok(Nullable::new(self.diag.weighting()?))
649 }
650
651 fn data_version(&self, _ctx: impl ReadContext) -> Result<Nullable<u16>, Error> {
652 Ok(Nullable::new(self.diag.data_version()?))
653 }
654
655 fn stable_data_version(&self, _ctx: impl ReadContext) -> Result<Nullable<u16>, Error> {
656 Ok(Nullable::new(self.diag.stable_data_version()?))
657 }
658
659 fn leader_router_id(&self, _ctx: impl ReadContext) -> Result<Nullable<u8>, Error> {
660 Ok(Nullable::new(self.diag.leader_router_id()?))
661 }
662
663 fn security_policy<P: TLVBuilderParent>(
664 &self,
665 _ctx: impl ReadContext,
666 builder: NullableBuilder<P, SecurityPolicyBuilder<P>>,
667 ) -> Result<P, Error> {
668 let security_policy = self.diag.security_policy()?;
669 if let Some(security_policy) = security_policy {
670 builder
671 .non_null()?
672 .rotation_time(security_policy.rotation_time)?
673 .flags(security_policy.flags)?
674 .end()
675 } else {
676 builder.null()
677 }
678 }
679
680 fn channel_page_0_mask<P: TLVBuilderParent>(
681 &self,
682 _ctx: impl ReadContext,
683 builder: NullableBuilder<P, OctetsBuilder<P>>,
684 ) -> Result<P, Error> {
685 let mut builder = Some(builder);
686 let mut parent = None;
687
688 self.diag.channel_page0_mask(&mut |mask| {
689 if let Some(mask) = mask {
690 parent = Some(unwrap!(builder.take()).non_null()?.set(Octets::new(mask))?);
691 } else {
692 parent = Some(unwrap!(builder.take()).null()?);
693 }
694
695 Ok(())
696 })?;
697
698 Ok(unwrap!(parent.take()))
699 }
700
701 fn operational_dataset_components<P: TLVBuilderParent>(
702 &self,
703 _ctx: impl ReadContext,
704 builder: NullableBuilder<P, OperationalDatasetComponentsBuilder<P>>,
705 ) -> Result<P, Error> {
706 let mut builder = Some(builder);
707 let mut parent = None;
708
709 self.diag.operational_dataset_components(&mut |dsc| {
710 if let Some(dsc) = dsc {
711 parent = Some(dsc.read_into(unwrap!(builder.take()).non_null()?)?);
712 } else {
713 parent = Some(unwrap!(builder.take()).null()?);
714 }
715
716 Ok(())
717 })?;
718
719 Ok(unwrap!(parent))
720 }
721
722 fn active_network_faults_list<P: TLVBuilderParent>(
723 &self,
724 _ctx: impl ReadContext,
725 builder: ArrayAttributeRead<
726 ToTLVArrayBuilder<P, NetworkFaultEnum>,
727 ToTLVBuilder<P, NetworkFaultEnum>,
728 >,
729 ) -> Result<P, Error> {
730 match builder {
731 ArrayAttributeRead::ReadAll(builder) => {
732 let mut builder = Some(builder);
733
734 self.diag.active_network_faults_list(&mut |fault| {
735 builder = Some(unwrap!(builder.take()).push(&fault)?);
736
737 Ok(())
738 })?;
739
740 unwrap!(builder.take()).end()
741 }
742 ArrayAttributeRead::ReadOne(index, builder) => {
743 let mut builder = Some(builder);
744 let mut parent = None;
745 let mut current = 0;
746
747 self.diag.active_network_faults_list(&mut |fault| {
748 if index == current {
749 parent = Some(unwrap!(builder.take()).set(&fault)?);
750 }
751
752 current += 1;
753
754 Ok(())
755 })?;
756
757 if let Some(parent) = parent {
758 Ok(parent)
759 } else {
760 Err(ErrorCode::InvalidAction.into())
761 }
762 }
763 ArrayAttributeRead::ReadNone(builder) => builder.end(),
764 }
765 }
766 fn ext_address(&self, _ctx: impl ReadContext) -> Result<Nullable<u64>, Error> {
767 Ok(Nullable::new(self.diag.ext_address()?))
768 }
769
770 fn rloc_16(&self, _ctx: impl ReadContext) -> Result<Nullable<u16>, Error> {
771 Ok(Nullable::new(self.diag.rloc_16()?))
772 }
773
774 fn tx_total_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
778 self.counter(|counters| Some(counters.tx_total_count))
779 }
780
781 fn tx_unicast_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
782 self.counter(|counters| Some(counters.tx_unicast_count))
783 }
784
785 fn tx_broadcast_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
786 self.counter(|counters| Some(counters.tx_broadcast_count))
787 }
788
789 fn tx_ack_requested_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
790 self.counter(|counters| Some(counters.tx_ack_requested_count))
791 }
792
793 fn tx_acked_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
794 self.counter(|counters| Some(counters.tx_acked_count))
795 }
796
797 fn tx_no_ack_requested_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
798 self.counter(|counters| Some(counters.tx_no_ack_requested_count))
799 }
800
801 fn tx_data_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
802 self.counter(|counters| Some(counters.tx_data_count))
803 }
804
805 fn tx_data_poll_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
806 self.counter(|counters| Some(counters.tx_data_poll_count))
807 }
808
809 fn tx_beacon_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
810 self.counter(|counters| Some(counters.tx_beacon_count))
811 }
812
813 fn tx_beacon_request_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
814 self.counter(|counters| Some(counters.tx_beacon_request_count))
815 }
816
817 fn tx_other_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
818 self.counter(|counters| Some(counters.tx_other_count))
819 }
820
821 fn tx_retry_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
822 self.counter(|counters| Some(counters.tx_retry_count))
823 }
824
825 fn tx_err_cca_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
826 self.counter(|counters| Some(counters.tx_err_cca_count))
827 }
828
829 fn tx_err_abort_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
830 self.counter(|counters| Some(counters.tx_err_abort_count))
831 }
832
833 fn tx_err_busy_channel_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
834 self.counter(|counters| Some(counters.tx_err_busy_channel_count))
835 }
836
837 fn rx_total_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
838 self.counter(|counters| Some(counters.rx_total_count))
839 }
840
841 fn rx_unicast_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
842 self.counter(|counters| Some(counters.rx_unicast_count))
843 }
844
845 fn rx_broadcast_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
846 self.counter(|counters| Some(counters.rx_broadcast_count))
847 }
848
849 fn rx_data_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
850 self.counter(|counters| Some(counters.rx_data_count))
851 }
852
853 fn rx_data_poll_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
854 self.counter(|counters| Some(counters.rx_data_poll_count))
855 }
856
857 fn rx_beacon_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
858 self.counter(|counters| Some(counters.rx_beacon_count))
859 }
860
861 fn rx_beacon_request_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
862 self.counter(|counters| Some(counters.rx_beacon_request_count))
863 }
864
865 fn rx_other_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
866 self.counter(|counters| Some(counters.rx_other_count))
867 }
868
869 fn rx_address_filtered_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
870 self.counter(|counters| Some(counters.rx_address_filtered_count))
871 }
872
873 fn rx_dest_addr_filtered_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
874 self.counter(|counters| Some(counters.rx_dest_addr_filtered_count))
875 }
876
877 fn rx_duplicated_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
878 self.counter(|counters| Some(counters.rx_duplicated_count))
879 }
880
881 fn rx_err_no_frame_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
882 self.counter(|counters| Some(counters.rx_err_no_frame_count))
883 }
884
885 fn rx_err_unknown_neighbor_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
886 self.counter(|counters| Some(counters.rx_err_unknown_neighbor_count))
887 }
888
889 fn rx_err_invalid_src_addr_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
890 self.counter(|counters| Some(counters.rx_err_invalid_src_addr_count))
891 }
892
893 fn rx_err_sec_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
894 self.counter(|counters| Some(counters.rx_err_sec_count))
895 }
896
897 fn rx_err_fcs_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
898 self.counter(|counters| Some(counters.rx_err_fcs_count))
899 }
900
901 fn rx_err_other_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
902 self.counter(|counters| Some(counters.rx_err_other_count))
903 }
904
905 fn tx_direct_max_retry_expiry_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
906 self.counter(|counters| counters.tx_direct_max_retry_expiry_count)
907 }
908
909 fn tx_indirect_max_retry_expiry_count(&self, _ctx: impl ReadContext) -> Result<u32, Error> {
910 self.counter(|counters| counters.tx_indirect_max_retry_expiry_count)
911 }
912
913 fn handle_reset_counts(&self, _ctx: impl InvokeContext) -> Result<(), Error> {
914 Err(ErrorCode::CommandNotFound.into())
915 }
916}
917
918impl Debug for ThreadDiagHandler<'_> {
919 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
920 f.debug_struct("ThreadDiagHandler")
921 .field("dataver", &self.dataver)
922 .finish()
923 }
924}
925
926#[cfg(feature = "defmt")]
927impl defmt::Format for ThreadDiagHandler<'_> {
928 fn format(&self, f: defmt::Formatter) {
929 defmt::write!(f, "ThreadDiagHandler {{ dataver: {} }}", self.dataver.get());
930 }
931}