matc/clusters/codec/
occupancy_sensing.rs

1//! Generated Matter TLV encoders and decoders for Occupancy Sensing Cluster
2//! Cluster ID: 0x0406
3//! 
4//! This file is automatically generated from OccupancySensing.xml
5
6use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11// Struct definitions
12
13#[derive(Debug, serde::Serialize)]
14pub struct HoldTimeLimits {
15    pub hold_time_min: Option<u16>,
16    pub hold_time_max: Option<u16>,
17    pub hold_time_default: Option<u16>,
18}
19
20// Attribute decoders
21
22/// Decode Occupancy attribute (0x0000)
23pub fn decode_occupancy(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
24    if let tlv::TlvItemValue::Int(v) = inp {
25        Ok(*v as u8)
26    } else {
27        Err(anyhow::anyhow!("Expected Integer"))
28    }
29}
30
31/// Decode OccupancySensorType attribute (0x0001)
32pub fn decode_occupancy_sensor_type(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
33    if let tlv::TlvItemValue::Int(v) = inp {
34        Ok(*v as u8)
35    } else {
36        Err(anyhow::anyhow!("Expected Integer"))
37    }
38}
39
40/// Decode OccupancySensorTypeBitmap attribute (0x0002)
41pub fn decode_occupancy_sensor_type_bitmap(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
42    if let tlv::TlvItemValue::Int(v) = inp {
43        Ok(*v as u8)
44    } else {
45        Err(anyhow::anyhow!("Expected Integer"))
46    }
47}
48
49/// Decode HoldTime attribute (0x0003)
50pub fn decode_hold_time(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
51    if let tlv::TlvItemValue::Int(v) = inp {
52        Ok(*v as u16)
53    } else {
54        Err(anyhow::anyhow!("Expected Integer"))
55    }
56}
57
58/// Decode HoldTimeLimits attribute (0x0004)
59pub fn decode_hold_time_limits(inp: &tlv::TlvItemValue) -> anyhow::Result<HoldTimeLimits> {
60    if let tlv::TlvItemValue::List(_fields) = inp {
61        // Struct with fields
62        let item = tlv::TlvItem { tag: 0, value: inp.clone() };
63        Ok(HoldTimeLimits {
64                hold_time_min: item.get_int(&[0]).map(|v| v as u16),
65                hold_time_max: item.get_int(&[1]).map(|v| v as u16),
66                hold_time_default: item.get_int(&[2]).map(|v| v as u16),
67        })
68    } else {
69        Err(anyhow::anyhow!("Expected struct fields"))
70    }
71}
72
73/// Decode PIROccupiedToUnoccupiedDelay attribute (0x0010)
74pub fn decode_pir_occupied_to_unoccupied_delay(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
75    if let tlv::TlvItemValue::Int(v) = inp {
76        Ok(*v as u16)
77    } else {
78        Err(anyhow::anyhow!("Expected Integer"))
79    }
80}
81
82/// Decode PIRUnoccupiedToOccupiedDelay attribute (0x0011)
83pub fn decode_pir_unoccupied_to_occupied_delay(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
84    if let tlv::TlvItemValue::Int(v) = inp {
85        Ok(*v as u16)
86    } else {
87        Err(anyhow::anyhow!("Expected Integer"))
88    }
89}
90
91/// Decode PIRUnoccupiedToOccupiedThreshold attribute (0x0012)
92pub fn decode_pir_unoccupied_to_occupied_threshold(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
93    if let tlv::TlvItemValue::Int(v) = inp {
94        Ok(*v as u8)
95    } else {
96        Err(anyhow::anyhow!("Expected Integer"))
97    }
98}
99
100/// Decode UltrasonicOccupiedToUnoccupiedDelay attribute (0x0020)
101pub fn decode_ultrasonic_occupied_to_unoccupied_delay(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
102    if let tlv::TlvItemValue::Int(v) = inp {
103        Ok(*v as u16)
104    } else {
105        Err(anyhow::anyhow!("Expected Integer"))
106    }
107}
108
109/// Decode UltrasonicUnoccupiedToOccupiedDelay attribute (0x0021)
110pub fn decode_ultrasonic_unoccupied_to_occupied_delay(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
111    if let tlv::TlvItemValue::Int(v) = inp {
112        Ok(*v as u16)
113    } else {
114        Err(anyhow::anyhow!("Expected Integer"))
115    }
116}
117
118/// Decode UltrasonicUnoccupiedToOccupiedThreshold attribute (0x0022)
119pub fn decode_ultrasonic_unoccupied_to_occupied_threshold(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
120    if let tlv::TlvItemValue::Int(v) = inp {
121        Ok(*v as u8)
122    } else {
123        Err(anyhow::anyhow!("Expected Integer"))
124    }
125}
126
127/// Decode PhysicalContactOccupiedToUnoccupiedDelay attribute (0x0030)
128pub fn decode_physical_contact_occupied_to_unoccupied_delay(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
129    if let tlv::TlvItemValue::Int(v) = inp {
130        Ok(*v as u16)
131    } else {
132        Err(anyhow::anyhow!("Expected Integer"))
133    }
134}
135
136/// Decode PhysicalContactUnoccupiedToOccupiedDelay attribute (0x0031)
137pub fn decode_physical_contact_unoccupied_to_occupied_delay(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
138    if let tlv::TlvItemValue::Int(v) = inp {
139        Ok(*v as u16)
140    } else {
141        Err(anyhow::anyhow!("Expected Integer"))
142    }
143}
144
145/// Decode PhysicalContactUnoccupiedToOccupiedThreshold attribute (0x0032)
146pub fn decode_physical_contact_unoccupied_to_occupied_threshold(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
147    if let tlv::TlvItemValue::Int(v) = inp {
148        Ok(*v as u8)
149    } else {
150        Err(anyhow::anyhow!("Expected Integer"))
151    }
152}
153
154
155// JSON dispatcher function
156
157/// Decode attribute value and return as JSON string
158/// 
159/// # Parameters
160/// * `cluster_id` - The cluster identifier
161/// * `attribute_id` - The attribute identifier
162/// * `tlv_value` - The TLV value to decode
163/// 
164/// # Returns
165/// JSON string representation of the decoded value or error
166pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
167    // Verify this is the correct cluster
168    if cluster_id != 0x0406 {
169        return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0406, got {}\"}}", cluster_id);
170    }
171    
172    match attribute_id {
173        0x0000 => {
174            match decode_occupancy(tlv_value) {
175                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
176                Err(e) => format!("{{\"error\": \"{}\"}}", e),
177            }
178        }
179        0x0001 => {
180            match decode_occupancy_sensor_type(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        0x0002 => {
186            match decode_occupancy_sensor_type_bitmap(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        0x0003 => {
192            match decode_hold_time(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        0x0004 => {
198            match decode_hold_time_limits(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        0x0010 => {
204            match decode_pir_occupied_to_unoccupied_delay(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        0x0011 => {
210            match decode_pir_unoccupied_to_occupied_delay(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        0x0012 => {
216            match decode_pir_unoccupied_to_occupied_threshold(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        0x0020 => {
222            match decode_ultrasonic_occupied_to_unoccupied_delay(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        0x0021 => {
228            match decode_ultrasonic_unoccupied_to_occupied_delay(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        0x0022 => {
234            match decode_ultrasonic_unoccupied_to_occupied_threshold(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        0x0030 => {
240            match decode_physical_contact_occupied_to_unoccupied_delay(tlv_value) {
241                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
242                Err(e) => format!("{{\"error\": \"{}\"}}", e),
243            }
244        }
245        0x0031 => {
246            match decode_physical_contact_unoccupied_to_occupied_delay(tlv_value) {
247                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
248                Err(e) => format!("{{\"error\": \"{}\"}}", e),
249            }
250        }
251        0x0032 => {
252            match decode_physical_contact_unoccupied_to_occupied_threshold(tlv_value) {
253                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
254                Err(e) => format!("{{\"error\": \"{}\"}}", e),
255            }
256        }
257        _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
258    }
259}
260
261/// Get list of all attributes supported by this cluster
262/// 
263/// # Returns
264/// Vector of tuples containing (attribute_id, attribute_name)
265pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
266    vec![
267        (0x0000, "Occupancy"),
268        (0x0001, "OccupancySensorType"),
269        (0x0002, "OccupancySensorTypeBitmap"),
270        (0x0003, "HoldTime"),
271        (0x0004, "HoldTimeLimits"),
272        (0x0010, "PIROccupiedToUnoccupiedDelay"),
273        (0x0011, "PIRUnoccupiedToOccupiedDelay"),
274        (0x0012, "PIRUnoccupiedToOccupiedThreshold"),
275        (0x0020, "UltrasonicOccupiedToUnoccupiedDelay"),
276        (0x0021, "UltrasonicUnoccupiedToOccupiedDelay"),
277        (0x0022, "UltrasonicUnoccupiedToOccupiedThreshold"),
278        (0x0030, "PhysicalContactOccupiedToUnoccupiedDelay"),
279        (0x0031, "PhysicalContactUnoccupiedToOccupiedDelay"),
280        (0x0032, "PhysicalContactUnoccupiedToOccupiedThreshold"),
281    ]
282}
283