matc/clusters/codec/
meter_identification.rs1#![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 MeterType {
18 Utility = 0,
20 Private = 1,
22 Generic = 2,
24}
25
26impl MeterType {
27 pub fn from_u8(value: u8) -> Option<Self> {
29 match value {
30 0 => Some(MeterType::Utility),
31 1 => Some(MeterType::Private),
32 2 => Some(MeterType::Generic),
33 _ => None,
34 }
35 }
36
37 pub fn to_u8(self) -> u8 {
39 self as u8
40 }
41}
42
43impl From<MeterType> for u8 {
44 fn from(val: MeterType) -> Self {
45 val as u8
46 }
47}
48
49pub fn decode_meter_type(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<MeterType>> {
53 if let tlv::TlvItemValue::Int(v) = inp {
54 Ok(MeterType::from_u8(*v as u8))
55 } else {
56 Ok(None)
57 }
58}
59
60pub fn decode_point_of_delivery(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<String>> {
62 if let tlv::TlvItemValue::String(v) = inp {
63 Ok(Some(v.clone()))
64 } else {
65 Ok(None)
66 }
67}
68
69pub fn decode_meter_serial_number(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<String>> {
71 if let tlv::TlvItemValue::String(v) = inp {
72 Ok(Some(v.clone()))
73 } else {
74 Ok(None)
75 }
76}
77
78pub fn decode_protocol_version(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<String>> {
80 if let tlv::TlvItemValue::String(v) = inp {
81 Ok(Some(v.clone()))
82 } else {
83 Ok(None)
84 }
85}
86
87pub fn decode_power_threshold(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
89 if let tlv::TlvItemValue::Int(v) = inp {
90 Ok(Some(*v as u8))
91 } else {
92 Ok(None)
93 }
94}
95
96
97pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
109 if cluster_id != 0x0B06 {
111 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0B06, got {}\"}}", cluster_id);
112 }
113
114 match attribute_id {
115 0x0000 => {
116 match decode_meter_type(tlv_value) {
117 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
118 Err(e) => format!("{{\"error\": \"{}\"}}", e),
119 }
120 }
121 0x0001 => {
122 match decode_point_of_delivery(tlv_value) {
123 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
124 Err(e) => format!("{{\"error\": \"{}\"}}", e),
125 }
126 }
127 0x0002 => {
128 match decode_meter_serial_number(tlv_value) {
129 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
130 Err(e) => format!("{{\"error\": \"{}\"}}", e),
131 }
132 }
133 0x0003 => {
134 match decode_protocol_version(tlv_value) {
135 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
136 Err(e) => format!("{{\"error\": \"{}\"}}", e),
137 }
138 }
139 0x0004 => {
140 match decode_power_threshold(tlv_value) {
141 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
142 Err(e) => format!("{{\"error\": \"{}\"}}", e),
143 }
144 }
145 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
146 }
147}
148
149pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
154 vec![
155 (0x0000, "MeterType"),
156 (0x0001, "PointOfDelivery"),
157 (0x0002, "MeterSerialNumber"),
158 (0x0003, "ProtocolVersion"),
159 (0x0004, "PowerThreshold"),
160 ]
161}
162
163pub async fn read_meter_type(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<MeterType>> {
167 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_METER_IDENTIFICATION, crate::clusters::defs::CLUSTER_METER_IDENTIFICATION_ATTR_ID_METERTYPE).await?;
168 decode_meter_type(&tlv)
169}
170
171pub async fn read_point_of_delivery(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<String>> {
173 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_METER_IDENTIFICATION, crate::clusters::defs::CLUSTER_METER_IDENTIFICATION_ATTR_ID_POINTOFDELIVERY).await?;
174 decode_point_of_delivery(&tlv)
175}
176
177pub async fn read_meter_serial_number(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<String>> {
179 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_METER_IDENTIFICATION, crate::clusters::defs::CLUSTER_METER_IDENTIFICATION_ATTR_ID_METERSERIALNUMBER).await?;
180 decode_meter_serial_number(&tlv)
181}
182
183pub async fn read_protocol_version(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<String>> {
185 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_METER_IDENTIFICATION, crate::clusters::defs::CLUSTER_METER_IDENTIFICATION_ATTR_ID_PROTOCOLVERSION).await?;
186 decode_protocol_version(&tlv)
187}
188
189pub async fn read_power_threshold(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
191 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_METER_IDENTIFICATION, crate::clusters::defs::CLUSTER_METER_IDENTIFICATION_ATTR_ID_POWERTHRESHOLD).await?;
192 decode_power_threshold(&tlv)
193}
194