matc/clusters/codec/
commodity_metering.rs1#![allow(clippy::too_many_arguments)]
7
8use crate::tlv;
9use anyhow;
10use serde_json;
11
12
13#[derive(Debug, serde::Serialize)]
16pub struct MeteredQuantity {
17 pub tariff_component_i_ds: Option<Vec<u32>>,
18 pub quantity: Option<i64>,
19}
20
21pub fn decode_metered_quantity(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<MeteredQuantity>> {
25 let mut res = Vec::new();
26 if let tlv::TlvItemValue::List(v) = inp {
27 for item in v {
28 res.push(MeteredQuantity {
29 tariff_component_i_ds: {
30 if let Some(tlv::TlvItemValue::List(l)) = item.get(&[0]) {
31 let items: Vec<u32> = l.iter().filter_map(|e| { if let tlv::TlvItemValue::Int(v) = &e.value { Some(*v as u32) } else { None } }).collect();
32 Some(items)
33 } else {
34 None
35 }
36 },
37 quantity: item.get_int(&[1]).map(|v| v as i64),
38 });
39 }
40 }
41 Ok(res)
42}
43
44pub fn decode_metered_quantity_timestamp(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u64>> {
46 if let tlv::TlvItemValue::Int(v) = inp {
47 Ok(Some(*v))
48 } else {
49 Ok(None)
50 }
51}
52
53pub fn decode_tariff_unit(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
55 if let tlv::TlvItemValue::Int(v) = inp {
56 Ok(Some(*v as u8))
57 } else {
58 Ok(None)
59 }
60}
61
62pub fn decode_maximum_metered_quantities(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u16>> {
64 if let tlv::TlvItemValue::Int(v) = inp {
65 Ok(Some(*v as u16))
66 } else {
67 Ok(None)
68 }
69}
70
71
72pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
84 if cluster_id != 0x0B07 {
86 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0B07, got {}\"}}", cluster_id);
87 }
88
89 match attribute_id {
90 0x0000 => {
91 match decode_metered_quantity(tlv_value) {
92 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
93 Err(e) => format!("{{\"error\": \"{}\"}}", e),
94 }
95 }
96 0x0001 => {
97 match decode_metered_quantity_timestamp(tlv_value) {
98 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
99 Err(e) => format!("{{\"error\": \"{}\"}}", e),
100 }
101 }
102 0x0002 => {
103 match decode_tariff_unit(tlv_value) {
104 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
105 Err(e) => format!("{{\"error\": \"{}\"}}", e),
106 }
107 }
108 0x0003 => {
109 match decode_maximum_metered_quantities(tlv_value) {
110 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
111 Err(e) => format!("{{\"error\": \"{}\"}}", e),
112 }
113 }
114 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
115 }
116}
117
118pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
123 vec![
124 (0x0000, "MeteredQuantity"),
125 (0x0001, "MeteredQuantityTimestamp"),
126 (0x0002, "TariffUnit"),
127 (0x0003, "MaximumMeteredQuantities"),
128 ]
129}
130
131pub async fn read_metered_quantity(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Vec<MeteredQuantity>> {
135 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COMMODITY_METERING, crate::clusters::defs::CLUSTER_COMMODITY_METERING_ATTR_ID_METEREDQUANTITY).await?;
136 decode_metered_quantity(&tlv)
137}
138
139pub async fn read_metered_quantity_timestamp(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u64>> {
141 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COMMODITY_METERING, crate::clusters::defs::CLUSTER_COMMODITY_METERING_ATTR_ID_METEREDQUANTITYTIMESTAMP).await?;
142 decode_metered_quantity_timestamp(&tlv)
143}
144
145pub async fn read_tariff_unit(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
147 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COMMODITY_METERING, crate::clusters::defs::CLUSTER_COMMODITY_METERING_ATTR_ID_TARIFFUNIT).await?;
148 decode_tariff_unit(&tlv)
149}
150
151pub async fn read_maximum_metered_quantities(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u16>> {
153 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_COMMODITY_METERING, crate::clusters::defs::CLUSTER_COMMODITY_METERING_ATTR_ID_MAXIMUMMETEREDQUANTITIES).await?;
154 decode_maximum_metered_quantities(&tlv)
155}
156