matc/clusters/codec/
diagnostics_ethernet.rs1use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
14#[repr(u8)]
15pub enum PHYRate {
16 Rate10m = 0,
18 Rate100m = 1,
20 Rate1g = 2,
22 Rate25g = 3,
24 Rate5g = 4,
26 Rate10g = 5,
28 Rate40g = 6,
30 Rate100g = 7,
32 Rate200g = 8,
34 Rate400g = 9,
36}
37
38impl PHYRate {
39 pub fn from_u8(value: u8) -> Option<Self> {
41 match value {
42 0 => Some(PHYRate::Rate10m),
43 1 => Some(PHYRate::Rate100m),
44 2 => Some(PHYRate::Rate1g),
45 3 => Some(PHYRate::Rate25g),
46 4 => Some(PHYRate::Rate5g),
47 5 => Some(PHYRate::Rate10g),
48 6 => Some(PHYRate::Rate40g),
49 7 => Some(PHYRate::Rate100g),
50 8 => Some(PHYRate::Rate200g),
51 9 => Some(PHYRate::Rate400g),
52 _ => None,
53 }
54 }
55
56 pub fn to_u8(self) -> u8 {
58 self as u8
59 }
60}
61
62impl From<PHYRate> for u8 {
63 fn from(val: PHYRate) -> Self {
64 val as u8
65 }
66}
67
68pub fn decode_phy_rate(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<PHYRate>> {
74 if let tlv::TlvItemValue::Int(v) = inp {
75 Ok(PHYRate::from_u8(*v as u8))
76 } else {
77 Ok(None)
78 }
79}
80
81pub fn decode_full_duplex(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<bool>> {
83 if let tlv::TlvItemValue::Bool(v) = inp {
84 Ok(Some(*v))
85 } else {
86 Ok(None)
87 }
88}
89
90pub fn decode_packet_rx_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u64> {
92 if let tlv::TlvItemValue::Int(v) = inp {
93 Ok(*v)
94 } else {
95 Err(anyhow::anyhow!("Expected UInt64"))
96 }
97}
98
99pub fn decode_packet_tx_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u64> {
101 if let tlv::TlvItemValue::Int(v) = inp {
102 Ok(*v)
103 } else {
104 Err(anyhow::anyhow!("Expected UInt64"))
105 }
106}
107
108pub fn decode_tx_err_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u64> {
110 if let tlv::TlvItemValue::Int(v) = inp {
111 Ok(*v)
112 } else {
113 Err(anyhow::anyhow!("Expected UInt64"))
114 }
115}
116
117pub fn decode_collision_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u64> {
119 if let tlv::TlvItemValue::Int(v) = inp {
120 Ok(*v)
121 } else {
122 Err(anyhow::anyhow!("Expected UInt64"))
123 }
124}
125
126pub fn decode_overrun_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u64> {
128 if let tlv::TlvItemValue::Int(v) = inp {
129 Ok(*v)
130 } else {
131 Err(anyhow::anyhow!("Expected UInt64"))
132 }
133}
134
135pub fn decode_carrier_detect(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<bool>> {
137 if let tlv::TlvItemValue::Bool(v) = inp {
138 Ok(Some(*v))
139 } else {
140 Ok(None)
141 }
142}
143
144pub fn decode_time_since_reset(inp: &tlv::TlvItemValue) -> anyhow::Result<u64> {
146 if let tlv::TlvItemValue::Int(v) = inp {
147 Ok(*v)
148 } else {
149 Err(anyhow::anyhow!("Expected UInt64"))
150 }
151}
152
153
154pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
166 if cluster_id != 0x0037 {
168 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0037, got {}\"}}", cluster_id);
169 }
170
171 match attribute_id {
172 0x0000 => {
173 match decode_phy_rate(tlv_value) {
174 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
175 Err(e) => format!("{{\"error\": \"{}\"}}", e),
176 }
177 }
178 0x0001 => {
179 match decode_full_duplex(tlv_value) {
180 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
181 Err(e) => format!("{{\"error\": \"{}\"}}", e),
182 }
183 }
184 0x0002 => {
185 match decode_packet_rx_count(tlv_value) {
186 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
187 Err(e) => format!("{{\"error\": \"{}\"}}", e),
188 }
189 }
190 0x0003 => {
191 match decode_packet_tx_count(tlv_value) {
192 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
193 Err(e) => format!("{{\"error\": \"{}\"}}", e),
194 }
195 }
196 0x0004 => {
197 match decode_tx_err_count(tlv_value) {
198 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
199 Err(e) => format!("{{\"error\": \"{}\"}}", e),
200 }
201 }
202 0x0005 => {
203 match decode_collision_count(tlv_value) {
204 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
205 Err(e) => format!("{{\"error\": \"{}\"}}", e),
206 }
207 }
208 0x0006 => {
209 match decode_overrun_count(tlv_value) {
210 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
211 Err(e) => format!("{{\"error\": \"{}\"}}", e),
212 }
213 }
214 0x0007 => {
215 match decode_carrier_detect(tlv_value) {
216 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
217 Err(e) => format!("{{\"error\": \"{}\"}}", e),
218 }
219 }
220 0x0008 => {
221 match decode_time_since_reset(tlv_value) {
222 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
223 Err(e) => format!("{{\"error\": \"{}\"}}", e),
224 }
225 }
226 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
227 }
228}
229
230pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
235 vec![
236 (0x0000, "PHYRate"),
237 (0x0001, "FullDuplex"),
238 (0x0002, "PacketRxCount"),
239 (0x0003, "PacketTxCount"),
240 (0x0004, "TxErrCount"),
241 (0x0005, "CollisionCount"),
242 (0x0006, "OverrunCount"),
243 (0x0007, "CarrierDetect"),
244 (0x0008, "TimeSinceReset"),
245 ]
246}
247