1use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11#[derive(Debug, serde::Serialize)]
14pub struct MonitoringRegistration {
15 pub check_in_node_id: Option<u64>,
16 pub monitored_subject: Option<u64>,
17 pub key: Option<u8>,
18 pub client_type: Option<u8>,
19}
20
21pub fn encode_register_client(check_in_node_id: u64, monitored_subject: u64, key: Vec<u8>, verification_key: Vec<u8>, client_type: u8) -> anyhow::Result<Vec<u8>> {
25 let tlv = tlv::TlvItemEnc {
26 tag: 0,
27 value: tlv::TlvItemValueEnc::StructInvisible(vec![
28 (0, tlv::TlvItemValueEnc::UInt64(check_in_node_id)).into(),
29 (1, tlv::TlvItemValueEnc::UInt64(monitored_subject)).into(),
30 (2, tlv::TlvItemValueEnc::OctetString(key)).into(),
31 (3, tlv::TlvItemValueEnc::OctetString(verification_key)).into(),
32 (4, tlv::TlvItemValueEnc::UInt8(client_type)).into(),
33 ]),
34 };
35 Ok(tlv.encode()?)
36}
37
38pub fn encode_unregister_client(check_in_node_id: u64, verification_key: Vec<u8>) -> anyhow::Result<Vec<u8>> {
40 let tlv = tlv::TlvItemEnc {
41 tag: 0,
42 value: tlv::TlvItemValueEnc::StructInvisible(vec![
43 (0, tlv::TlvItemValueEnc::UInt64(check_in_node_id)).into(),
44 (1, tlv::TlvItemValueEnc::OctetString(verification_key)).into(),
45 ]),
46 };
47 Ok(tlv.encode()?)
48}
49
50pub fn encode_stay_active_request(stay_active_duration: u32) -> anyhow::Result<Vec<u8>> {
52 let tlv = tlv::TlvItemEnc {
53 tag: 0,
54 value: tlv::TlvItemValueEnc::StructInvisible(vec![
55 (0, tlv::TlvItemValueEnc::UInt32(stay_active_duration)).into(),
56 ]),
57 };
58 Ok(tlv.encode()?)
59}
60
61pub fn decode_idle_mode_duration(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
65 if let tlv::TlvItemValue::Int(v) = inp {
66 Ok(*v as u32)
67 } else {
68 Err(anyhow::anyhow!("Expected Integer"))
69 }
70}
71
72pub fn decode_active_mode_duration(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
74 if let tlv::TlvItemValue::Int(v) = inp {
75 Ok(*v as u32)
76 } else {
77 Err(anyhow::anyhow!("Expected Integer"))
78 }
79}
80
81pub fn decode_active_mode_threshold(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
83 if let tlv::TlvItemValue::Int(v) = inp {
84 Ok(*v as u16)
85 } else {
86 Err(anyhow::anyhow!("Expected Integer"))
87 }
88}
89
90pub fn decode_registered_clients(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<MonitoringRegistration>> {
92 let mut res = Vec::new();
93 if let tlv::TlvItemValue::List(v) = inp {
94 for item in v {
95 res.push(MonitoringRegistration {
96 check_in_node_id: item.get_int(&[1]),
97 monitored_subject: item.get_int(&[2]),
98 key: item.get_int(&[3]).map(|v| v as u8),
99 client_type: item.get_int(&[4]).map(|v| v as u8),
100 });
101 }
102 }
103 Ok(res)
104}
105
106pub fn decode_icd_counter(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
108 if let tlv::TlvItemValue::Int(v) = inp {
109 Ok(*v as u32)
110 } else {
111 Err(anyhow::anyhow!("Expected Integer"))
112 }
113}
114
115pub fn decode_clients_supported_per_fabric(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
117 if let tlv::TlvItemValue::Int(v) = inp {
118 Ok(*v as u16)
119 } else {
120 Err(anyhow::anyhow!("Expected Integer"))
121 }
122}
123
124pub fn decode_user_active_mode_trigger_hint(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
126 if let tlv::TlvItemValue::Int(v) = inp {
127 Ok(*v as u8)
128 } else {
129 Err(anyhow::anyhow!("Expected Integer"))
130 }
131}
132
133pub fn decode_user_active_mode_trigger_instruction(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
135 if let tlv::TlvItemValue::String(v) = inp {
136 Ok(v.clone())
137 } else {
138 Err(anyhow::anyhow!("Expected String"))
139 }
140}
141
142pub fn decode_operating_mode(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
144 if let tlv::TlvItemValue::Int(v) = inp {
145 Ok(*v as u8)
146 } else {
147 Err(anyhow::anyhow!("Expected Integer"))
148 }
149}
150
151pub fn decode_maximum_check_in_backoff(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
153 if let tlv::TlvItemValue::Int(v) = inp {
154 Ok(*v as u32)
155 } else {
156 Err(anyhow::anyhow!("Expected Integer"))
157 }
158}
159
160
161pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
173 if cluster_id != 0x0046 {
175 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0046, got {}\"}}", cluster_id);
176 }
177
178 match attribute_id {
179 0x0000 => {
180 match decode_idle_mode_duration(tlv_value) {
181 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
182 Err(e) => format!("{{\"error\": \"{}\"}}", e),
183 }
184 }
185 0x0001 => {
186 match decode_active_mode_duration(tlv_value) {
187 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
188 Err(e) => format!("{{\"error\": \"{}\"}}", e),
189 }
190 }
191 0x0002 => {
192 match decode_active_mode_threshold(tlv_value) {
193 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
194 Err(e) => format!("{{\"error\": \"{}\"}}", e),
195 }
196 }
197 0x0003 => {
198 match decode_registered_clients(tlv_value) {
199 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
200 Err(e) => format!("{{\"error\": \"{}\"}}", e),
201 }
202 }
203 0x0004 => {
204 match decode_icd_counter(tlv_value) {
205 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
206 Err(e) => format!("{{\"error\": \"{}\"}}", e),
207 }
208 }
209 0x0005 => {
210 match decode_clients_supported_per_fabric(tlv_value) {
211 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
212 Err(e) => format!("{{\"error\": \"{}\"}}", e),
213 }
214 }
215 0x0006 => {
216 match decode_user_active_mode_trigger_hint(tlv_value) {
217 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
218 Err(e) => format!("{{\"error\": \"{}\"}}", e),
219 }
220 }
221 0x0007 => {
222 match decode_user_active_mode_trigger_instruction(tlv_value) {
223 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
224 Err(e) => format!("{{\"error\": \"{}\"}}", e),
225 }
226 }
227 0x0008 => {
228 match decode_operating_mode(tlv_value) {
229 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
230 Err(e) => format!("{{\"error\": \"{}\"}}", e),
231 }
232 }
233 0x0009 => {
234 match decode_maximum_check_in_backoff(tlv_value) {
235 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
236 Err(e) => format!("{{\"error\": \"{}\"}}", e),
237 }
238 }
239 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
240 }
241}
242
243pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
248 vec![
249 (0x0000, "IdleModeDuration"),
250 (0x0001, "ActiveModeDuration"),
251 (0x0002, "ActiveModeThreshold"),
252 (0x0003, "RegisteredClients"),
253 (0x0004, "ICDCounter"),
254 (0x0005, "ClientsSupportedPerFabric"),
255 (0x0006, "UserActiveModeTriggerHint"),
256 (0x0007, "UserActiveModeTriggerInstruction"),
257 (0x0008, "OperatingMode"),
258 (0x0009, "MaximumCheckInBackoff"),
259 ]
260}
261