1#![allow(clippy::too_many_arguments)]
7
8use crate::tlv;
9use anyhow;
10use serde_json;
11
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
16#[repr(u8)]
17pub enum PHYRate {
18 Rate10m = 0,
20 Rate100m = 1,
22 Rate1g = 2,
24 Rate25g = 3,
26 Rate5g = 4,
28 Rate10g = 5,
30 Rate40g = 6,
32 Rate100g = 7,
34 Rate200g = 8,
36 Rate400g = 9,
38}
39
40impl PHYRate {
41 pub fn from_u8(value: u8) -> Option<Self> {
43 match value {
44 0 => Some(PHYRate::Rate10m),
45 1 => Some(PHYRate::Rate100m),
46 2 => Some(PHYRate::Rate1g),
47 3 => Some(PHYRate::Rate25g),
48 4 => Some(PHYRate::Rate5g),
49 5 => Some(PHYRate::Rate10g),
50 6 => Some(PHYRate::Rate40g),
51 7 => Some(PHYRate::Rate100g),
52 8 => Some(PHYRate::Rate200g),
53 9 => Some(PHYRate::Rate400g),
54 _ => None,
55 }
56 }
57
58 pub fn to_u8(self) -> u8 {
60 self as u8
61 }
62}
63
64impl From<PHYRate> for u8 {
65 fn from(val: PHYRate) -> Self {
66 val as u8
67 }
68}
69
70pub fn decode_phy_rate(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<PHYRate>> {
76 if let tlv::TlvItemValue::Int(v) = inp {
77 Ok(PHYRate::from_u8(*v as u8))
78 } else {
79 Ok(None)
80 }
81}
82
83pub fn decode_full_duplex(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<bool>> {
85 if let tlv::TlvItemValue::Bool(v) = inp {
86 Ok(Some(*v))
87 } else {
88 Ok(None)
89 }
90}
91
92pub fn decode_packet_rx_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u64> {
94 if let tlv::TlvItemValue::Int(v) = inp {
95 Ok(*v)
96 } else {
97 Err(anyhow::anyhow!("Expected UInt64"))
98 }
99}
100
101pub fn decode_packet_tx_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u64> {
103 if let tlv::TlvItemValue::Int(v) = inp {
104 Ok(*v)
105 } else {
106 Err(anyhow::anyhow!("Expected UInt64"))
107 }
108}
109
110pub fn decode_tx_err_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u64> {
112 if let tlv::TlvItemValue::Int(v) = inp {
113 Ok(*v)
114 } else {
115 Err(anyhow::anyhow!("Expected UInt64"))
116 }
117}
118
119pub fn decode_collision_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u64> {
121 if let tlv::TlvItemValue::Int(v) = inp {
122 Ok(*v)
123 } else {
124 Err(anyhow::anyhow!("Expected UInt64"))
125 }
126}
127
128pub fn decode_overrun_count(inp: &tlv::TlvItemValue) -> anyhow::Result<u64> {
130 if let tlv::TlvItemValue::Int(v) = inp {
131 Ok(*v)
132 } else {
133 Err(anyhow::anyhow!("Expected UInt64"))
134 }
135}
136
137pub fn decode_carrier_detect(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<bool>> {
139 if let tlv::TlvItemValue::Bool(v) = inp {
140 Ok(Some(*v))
141 } else {
142 Ok(None)
143 }
144}
145
146pub fn decode_time_since_reset(inp: &tlv::TlvItemValue) -> anyhow::Result<u64> {
148 if let tlv::TlvItemValue::Int(v) = inp {
149 Ok(*v)
150 } else {
151 Err(anyhow::anyhow!("Expected UInt64"))
152 }
153}
154
155
156pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
168 if cluster_id != 0x0037 {
170 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0037, got {}\"}}", cluster_id);
171 }
172
173 match attribute_id {
174 0x0000 => {
175 match decode_phy_rate(tlv_value) {
176 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
177 Err(e) => format!("{{\"error\": \"{}\"}}", e),
178 }
179 }
180 0x0001 => {
181 match decode_full_duplex(tlv_value) {
182 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
183 Err(e) => format!("{{\"error\": \"{}\"}}", e),
184 }
185 }
186 0x0002 => {
187 match decode_packet_rx_count(tlv_value) {
188 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
189 Err(e) => format!("{{\"error\": \"{}\"}}", e),
190 }
191 }
192 0x0003 => {
193 match decode_packet_tx_count(tlv_value) {
194 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
195 Err(e) => format!("{{\"error\": \"{}\"}}", e),
196 }
197 }
198 0x0004 => {
199 match decode_tx_err_count(tlv_value) {
200 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
201 Err(e) => format!("{{\"error\": \"{}\"}}", e),
202 }
203 }
204 0x0005 => {
205 match decode_collision_count(tlv_value) {
206 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
207 Err(e) => format!("{{\"error\": \"{}\"}}", e),
208 }
209 }
210 0x0006 => {
211 match decode_overrun_count(tlv_value) {
212 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
213 Err(e) => format!("{{\"error\": \"{}\"}}", e),
214 }
215 }
216 0x0007 => {
217 match decode_carrier_detect(tlv_value) {
218 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
219 Err(e) => format!("{{\"error\": \"{}\"}}", e),
220 }
221 }
222 0x0008 => {
223 match decode_time_since_reset(tlv_value) {
224 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
225 Err(e) => format!("{{\"error\": \"{}\"}}", e),
226 }
227 }
228 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
229 }
230}
231
232pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
237 vec![
238 (0x0000, "PHYRate"),
239 (0x0001, "FullDuplex"),
240 (0x0002, "PacketRxCount"),
241 (0x0003, "PacketTxCount"),
242 (0x0004, "TxErrCount"),
243 (0x0005, "CollisionCount"),
244 (0x0006, "OverrunCount"),
245 (0x0007, "CarrierDetect"),
246 (0x0008, "TimeSinceReset"),
247 ]
248}
249
250pub fn get_command_list() -> Vec<(u32, &'static str)> {
253 vec![
254 (0x00, "ResetCounts"),
255 ]
256}
257
258pub fn get_command_name(cmd_id: u32) -> Option<&'static str> {
259 match cmd_id {
260 0x00 => Some("ResetCounts"),
261 _ => None,
262 }
263}
264
265pub fn get_command_schema(cmd_id: u32) -> Option<Vec<crate::clusters::codec::CommandField>> {
266 match cmd_id {
267 0x00 => Some(vec![]),
268 _ => None,
269 }
270}
271
272pub fn encode_command_json(cmd_id: u32, _args: &serde_json::Value) -> anyhow::Result<Vec<u8>> {
273 match cmd_id {
274 0x00 => Ok(vec![]),
275 _ => Err(anyhow::anyhow!("unknown command ID: 0x{:02X}", cmd_id)),
276 }
277}
278
279pub async fn reset_counts(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<()> {
283 conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_ETHERNET_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_ETHERNET_NETWORK_DIAGNOSTICS_CMD_ID_RESETCOUNTS, &[]).await?;
284 Ok(())
285}
286
287pub async fn read_phy_rate(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<PHYRate>> {
289 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ETHERNET_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_ETHERNET_NETWORK_DIAGNOSTICS_ATTR_ID_PHYRATE).await?;
290 decode_phy_rate(&tlv)
291}
292
293pub async fn read_full_duplex(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<bool>> {
295 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ETHERNET_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_ETHERNET_NETWORK_DIAGNOSTICS_ATTR_ID_FULLDUPLEX).await?;
296 decode_full_duplex(&tlv)
297}
298
299pub async fn read_packet_rx_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u64> {
301 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ETHERNET_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_ETHERNET_NETWORK_DIAGNOSTICS_ATTR_ID_PACKETRXCOUNT).await?;
302 decode_packet_rx_count(&tlv)
303}
304
305pub async fn read_packet_tx_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u64> {
307 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ETHERNET_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_ETHERNET_NETWORK_DIAGNOSTICS_ATTR_ID_PACKETTXCOUNT).await?;
308 decode_packet_tx_count(&tlv)
309}
310
311pub async fn read_tx_err_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u64> {
313 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ETHERNET_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_ETHERNET_NETWORK_DIAGNOSTICS_ATTR_ID_TXERRCOUNT).await?;
314 decode_tx_err_count(&tlv)
315}
316
317pub async fn read_collision_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u64> {
319 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ETHERNET_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_ETHERNET_NETWORK_DIAGNOSTICS_ATTR_ID_COLLISIONCOUNT).await?;
320 decode_collision_count(&tlv)
321}
322
323pub async fn read_overrun_count(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u64> {
325 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ETHERNET_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_ETHERNET_NETWORK_DIAGNOSTICS_ATTR_ID_OVERRUNCOUNT).await?;
326 decode_overrun_count(&tlv)
327}
328
329pub async fn read_carrier_detect(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<bool>> {
331 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ETHERNET_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_ETHERNET_NETWORK_DIAGNOSTICS_ATTR_ID_CARRIERDETECT).await?;
332 decode_carrier_detect(&tlv)
333}
334
335pub async fn read_time_since_reset(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u64> {
337 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ETHERNET_NETWORK_DIAGNOSTICS, crate::clusters::defs::CLUSTER_ETHERNET_NETWORK_DIAGNOSTICS_ATTR_ID_TIMESINCERESET).await?;
338 decode_time_since_reset(&tlv)
339}
340