1use 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 StatusCode {
16 Failureduetofault = 2,
18}
19
20impl StatusCode {
21 pub fn from_u8(value: u8) -> Option<Self> {
23 match value {
24 2 => Some(StatusCode::Failureduetofault),
25 _ => None,
26 }
27 }
28
29 pub fn to_u8(self) -> u8 {
31 self as u8
32 }
33}
34
35impl From<StatusCode> for u8 {
36 fn from(val: StatusCode) -> Self {
37 val as u8
38 }
39}
40
41#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
42#[repr(u8)]
43pub enum ValveState {
44 Closed = 0,
46 Open = 1,
48 Transitioning = 2,
50}
51
52impl ValveState {
53 pub fn from_u8(value: u8) -> Option<Self> {
55 match value {
56 0 => Some(ValveState::Closed),
57 1 => Some(ValveState::Open),
58 2 => Some(ValveState::Transitioning),
59 _ => None,
60 }
61 }
62
63 pub fn to_u8(self) -> u8 {
65 self as u8
66 }
67}
68
69impl From<ValveState> for u8 {
70 fn from(val: ValveState) -> Self {
71 val as u8
72 }
73}
74
75pub type ValveFault = u8;
79
80pub mod valvefault {
82 pub const GENERAL_FAULT: u8 = 0x01;
84 pub const BLOCKED: u8 = 0x02;
86 pub const LEAKING: u8 = 0x04;
88 pub const NOT_CONNECTED: u8 = 0x08;
90 pub const SHORT_CIRCUIT: u8 = 0x10;
92 pub const CURRENT_EXCEEDED: u8 = 0x20;
94}
95
96pub fn encode_open(open_duration: Option<u32>, target_level: u8) -> anyhow::Result<Vec<u8>> {
100 let tlv = tlv::TlvItemEnc {
101 tag: 0,
102 value: tlv::TlvItemValueEnc::StructInvisible(vec![
103 (0, tlv::TlvItemValueEnc::UInt32(open_duration.unwrap_or(0))).into(),
104 (1, tlv::TlvItemValueEnc::UInt8(target_level)).into(),
105 ]),
106 };
107 Ok(tlv.encode()?)
108}
109
110pub fn decode_open_duration(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u32>> {
114 if let tlv::TlvItemValue::Int(v) = inp {
115 Ok(Some(*v as u32))
116 } else {
117 Ok(None)
118 }
119}
120
121pub fn decode_default_open_duration(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u32>> {
123 if let tlv::TlvItemValue::Int(v) = inp {
124 Ok(Some(*v as u32))
125 } else {
126 Ok(None)
127 }
128}
129
130pub fn decode_auto_close_time(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u64>> {
132 if let tlv::TlvItemValue::Int(v) = inp {
133 Ok(Some(*v))
134 } else {
135 Ok(None)
136 }
137}
138
139pub fn decode_remaining_duration(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u32>> {
141 if let tlv::TlvItemValue::Int(v) = inp {
142 Ok(Some(*v as u32))
143 } else {
144 Ok(None)
145 }
146}
147
148pub fn decode_current_state(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<ValveState>> {
150 if let tlv::TlvItemValue::Int(v) = inp {
151 Ok(ValveState::from_u8(*v as u8))
152 } else {
153 Ok(None)
154 }
155}
156
157pub fn decode_target_state(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<ValveState>> {
159 if let tlv::TlvItemValue::Int(v) = inp {
160 Ok(ValveState::from_u8(*v as u8))
161 } else {
162 Ok(None)
163 }
164}
165
166pub fn decode_current_level(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
168 if let tlv::TlvItemValue::Int(v) = inp {
169 Ok(Some(*v as u8))
170 } else {
171 Ok(None)
172 }
173}
174
175pub fn decode_target_level(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
177 if let tlv::TlvItemValue::Int(v) = inp {
178 Ok(Some(*v as u8))
179 } else {
180 Ok(None)
181 }
182}
183
184pub fn decode_default_open_level(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
186 if let tlv::TlvItemValue::Int(v) = inp {
187 Ok(*v as u8)
188 } else {
189 Err(anyhow::anyhow!("Expected UInt8"))
190 }
191}
192
193pub fn decode_valve_fault(inp: &tlv::TlvItemValue) -> anyhow::Result<ValveFault> {
195 if let tlv::TlvItemValue::Int(v) = inp {
196 Ok(*v as u8)
197 } else {
198 Err(anyhow::anyhow!("Expected Integer"))
199 }
200}
201
202pub fn decode_level_step(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
204 if let tlv::TlvItemValue::Int(v) = inp {
205 Ok(*v as u8)
206 } else {
207 Err(anyhow::anyhow!("Expected UInt8"))
208 }
209}
210
211
212pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
224 if cluster_id != 0x0081 {
226 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0081, got {}\"}}", cluster_id);
227 }
228
229 match attribute_id {
230 0x0000 => {
231 match decode_open_duration(tlv_value) {
232 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
233 Err(e) => format!("{{\"error\": \"{}\"}}", e),
234 }
235 }
236 0x0001 => {
237 match decode_default_open_duration(tlv_value) {
238 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
239 Err(e) => format!("{{\"error\": \"{}\"}}", e),
240 }
241 }
242 0x0002 => {
243 match decode_auto_close_time(tlv_value) {
244 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
245 Err(e) => format!("{{\"error\": \"{}\"}}", e),
246 }
247 }
248 0x0003 => {
249 match decode_remaining_duration(tlv_value) {
250 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
251 Err(e) => format!("{{\"error\": \"{}\"}}", e),
252 }
253 }
254 0x0004 => {
255 match decode_current_state(tlv_value) {
256 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
257 Err(e) => format!("{{\"error\": \"{}\"}}", e),
258 }
259 }
260 0x0005 => {
261 match decode_target_state(tlv_value) {
262 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
263 Err(e) => format!("{{\"error\": \"{}\"}}", e),
264 }
265 }
266 0x0006 => {
267 match decode_current_level(tlv_value) {
268 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
269 Err(e) => format!("{{\"error\": \"{}\"}}", e),
270 }
271 }
272 0x0007 => {
273 match decode_target_level(tlv_value) {
274 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
275 Err(e) => format!("{{\"error\": \"{}\"}}", e),
276 }
277 }
278 0x0008 => {
279 match decode_default_open_level(tlv_value) {
280 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
281 Err(e) => format!("{{\"error\": \"{}\"}}", e),
282 }
283 }
284 0x0009 => {
285 match decode_valve_fault(tlv_value) {
286 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
287 Err(e) => format!("{{\"error\": \"{}\"}}", e),
288 }
289 }
290 0x000A => {
291 match decode_level_step(tlv_value) {
292 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
293 Err(e) => format!("{{\"error\": \"{}\"}}", e),
294 }
295 }
296 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
297 }
298}
299
300pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
305 vec![
306 (0x0000, "OpenDuration"),
307 (0x0001, "DefaultOpenDuration"),
308 (0x0002, "AutoCloseTime"),
309 (0x0003, "RemainingDuration"),
310 (0x0004, "CurrentState"),
311 (0x0005, "TargetState"),
312 (0x0006, "CurrentLevel"),
313 (0x0007, "TargetLevel"),
314 (0x0008, "DefaultOpenLevel"),
315 (0x0009, "ValveFault"),
316 (0x000A, "LevelStep"),
317 ]
318}
319
320#[derive(Debug, serde::Serialize)]
321pub struct ValveStateChangedEvent {
322 pub valve_state: Option<ValveState>,
323 pub valve_level: Option<u8>,
324}
325
326#[derive(Debug, serde::Serialize)]
327pub struct ValveFaultEvent {
328 pub valve_fault: Option<ValveFault>,
329}
330
331pub fn decode_valve_state_changed_event(inp: &tlv::TlvItemValue) -> anyhow::Result<ValveStateChangedEvent> {
335 if let tlv::TlvItemValue::List(_fields) = inp {
336 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
337 Ok(ValveStateChangedEvent {
338 valve_state: item.get_int(&[0]).and_then(|v| ValveState::from_u8(v as u8)),
339 valve_level: item.get_int(&[1]).map(|v| v as u8),
340 })
341 } else {
342 Err(anyhow::anyhow!("Expected struct fields"))
343 }
344}
345
346pub fn decode_valve_fault_event(inp: &tlv::TlvItemValue) -> anyhow::Result<ValveFaultEvent> {
348 if let tlv::TlvItemValue::List(_fields) = inp {
349 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
350 Ok(ValveFaultEvent {
351 valve_fault: item.get_int(&[0]).map(|v| v as u8),
352 })
353 } else {
354 Err(anyhow::anyhow!("Expected struct fields"))
355 }
356}
357