matc/clusters/codec/
window_covering.rs

1//! Generated Matter TLV encoders and decoders for Window Covering Cluster
2//! Cluster ID: 0x0102
3//! 
4//! This file is automatically generated from WindowCovering.xml
5
6use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11// Command encoders
12
13/// Encode GoToLiftValue command (0x04)
14pub fn encode_go_to_lift_value(lift_value: u16) -> anyhow::Result<Vec<u8>> {
15    let tlv = tlv::TlvItemEnc {
16        tag: 0,
17        value: tlv::TlvItemValueEnc::StructInvisible(vec![
18        (0, tlv::TlvItemValueEnc::UInt16(lift_value)).into(),
19        ]),
20    };
21    Ok(tlv.encode()?)
22}
23
24/// Encode GoToLiftPercentage command (0x05)
25pub fn encode_go_to_lift_percentage(lift_percent100ths_value: u8) -> anyhow::Result<Vec<u8>> {
26    let tlv = tlv::TlvItemEnc {
27        tag: 0,
28        value: tlv::TlvItemValueEnc::StructInvisible(vec![
29        (0, tlv::TlvItemValueEnc::UInt8(lift_percent100ths_value)).into(),
30        ]),
31    };
32    Ok(tlv.encode()?)
33}
34
35/// Encode GoToTiltValue command (0x07)
36pub fn encode_go_to_tilt_value(tilt_value: u16) -> anyhow::Result<Vec<u8>> {
37    let tlv = tlv::TlvItemEnc {
38        tag: 0,
39        value: tlv::TlvItemValueEnc::StructInvisible(vec![
40        (0, tlv::TlvItemValueEnc::UInt16(tilt_value)).into(),
41        ]),
42    };
43    Ok(tlv.encode()?)
44}
45
46/// Encode GoToTiltPercentage command (0x08)
47pub fn encode_go_to_tilt_percentage(tilt_percent100ths_value: u8) -> anyhow::Result<Vec<u8>> {
48    let tlv = tlv::TlvItemEnc {
49        tag: 0,
50        value: tlv::TlvItemValueEnc::StructInvisible(vec![
51        (0, tlv::TlvItemValueEnc::UInt8(tilt_percent100ths_value)).into(),
52        ]),
53    };
54    Ok(tlv.encode()?)
55}
56
57// Attribute decoders
58
59/// Decode Type attribute (0x0000)
60pub fn decode_type_(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
61    if let tlv::TlvItemValue::Int(v) = inp {
62        Ok(*v as u8)
63    } else {
64        Err(anyhow::anyhow!("Expected Integer"))
65    }
66}
67
68/// Decode PhysicalClosedLimitLift attribute (0x0001)
69pub fn decode_physical_closed_limit_lift(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
70    if let tlv::TlvItemValue::Int(v) = inp {
71        Ok(*v as u16)
72    } else {
73        Err(anyhow::anyhow!("Expected Integer"))
74    }
75}
76
77/// Decode PhysicalClosedLimitTilt attribute (0x0002)
78pub fn decode_physical_closed_limit_tilt(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
79    if let tlv::TlvItemValue::Int(v) = inp {
80        Ok(*v as u16)
81    } else {
82        Err(anyhow::anyhow!("Expected Integer"))
83    }
84}
85
86/// Decode CurrentPositionLift attribute (0x0003)
87pub fn decode_current_position_lift(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u16>> {
88    if let tlv::TlvItemValue::Int(v) = inp {
89        Ok(Some(*v as u16))
90    } else {
91        Ok(None)
92    }
93}
94
95/// Decode CurrentPositionTilt attribute (0x0004)
96pub fn decode_current_position_tilt(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u16>> {
97    if let tlv::TlvItemValue::Int(v) = inp {
98        Ok(Some(*v as u16))
99    } else {
100        Ok(None)
101    }
102}
103
104/// Decode NumberOfActuationsLift attribute (0x0005)
105pub fn decode_number_of_actuations_lift(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
106    if let tlv::TlvItemValue::Int(v) = inp {
107        Ok(*v as u16)
108    } else {
109        Err(anyhow::anyhow!("Expected Integer"))
110    }
111}
112
113/// Decode NumberOfActuationsTilt attribute (0x0006)
114pub fn decode_number_of_actuations_tilt(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
115    if let tlv::TlvItemValue::Int(v) = inp {
116        Ok(*v as u16)
117    } else {
118        Err(anyhow::anyhow!("Expected Integer"))
119    }
120}
121
122/// Decode ConfigStatus attribute (0x0007)
123pub fn decode_config_status(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
124    if let tlv::TlvItemValue::Int(v) = inp {
125        Ok(*v as u8)
126    } else {
127        Err(anyhow::anyhow!("Expected Integer"))
128    }
129}
130
131/// Decode CurrentPositionLiftPercentage attribute (0x0008)
132pub fn decode_current_position_lift_percentage(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
133    if let tlv::TlvItemValue::Int(v) = inp {
134        Ok(Some(*v as u8))
135    } else {
136        Ok(None)
137    }
138}
139
140/// Decode CurrentPositionTiltPercentage attribute (0x0009)
141pub fn decode_current_position_tilt_percentage(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
142    if let tlv::TlvItemValue::Int(v) = inp {
143        Ok(Some(*v as u8))
144    } else {
145        Ok(None)
146    }
147}
148
149/// Decode OperationalStatus attribute (0x000A)
150pub fn decode_operational_status(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
151    if let tlv::TlvItemValue::Int(v) = inp {
152        Ok(*v as u8)
153    } else {
154        Err(anyhow::anyhow!("Expected Integer"))
155    }
156}
157
158/// Decode TargetPositionLiftPercent100ths attribute (0x000B)
159pub fn decode_target_position_lift_percent100ths(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
160    if let tlv::TlvItemValue::Int(v) = inp {
161        Ok(Some(*v as u8))
162    } else {
163        Ok(None)
164    }
165}
166
167/// Decode TargetPositionTiltPercent100ths attribute (0x000C)
168pub fn decode_target_position_tilt_percent100ths(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
169    if let tlv::TlvItemValue::Int(v) = inp {
170        Ok(Some(*v as u8))
171    } else {
172        Ok(None)
173    }
174}
175
176/// Decode EndProductType attribute (0x000D)
177pub fn decode_end_product_type(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
178    if let tlv::TlvItemValue::Int(v) = inp {
179        Ok(*v as u8)
180    } else {
181        Err(anyhow::anyhow!("Expected Integer"))
182    }
183}
184
185/// Decode CurrentPositionLiftPercent100ths attribute (0x000E)
186pub fn decode_current_position_lift_percent100ths(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
187    if let tlv::TlvItemValue::Int(v) = inp {
188        Ok(Some(*v as u8))
189    } else {
190        Ok(None)
191    }
192}
193
194/// Decode CurrentPositionTiltPercent100ths attribute (0x000F)
195pub fn decode_current_position_tilt_percent100ths(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
196    if let tlv::TlvItemValue::Int(v) = inp {
197        Ok(Some(*v as u8))
198    } else {
199        Ok(None)
200    }
201}
202
203/// Decode InstalledOpenLimitLift attribute (0x0010)
204pub fn decode_installed_open_limit_lift(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
205    if let tlv::TlvItemValue::Int(v) = inp {
206        Ok(*v as u16)
207    } else {
208        Err(anyhow::anyhow!("Expected Integer"))
209    }
210}
211
212/// Decode InstalledClosedLimitLift attribute (0x0011)
213pub fn decode_installed_closed_limit_lift(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
214    if let tlv::TlvItemValue::Int(v) = inp {
215        Ok(*v as u16)
216    } else {
217        Err(anyhow::anyhow!("Expected Integer"))
218    }
219}
220
221/// Decode InstalledOpenLimitTilt attribute (0x0012)
222pub fn decode_installed_open_limit_tilt(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
223    if let tlv::TlvItemValue::Int(v) = inp {
224        Ok(*v as u16)
225    } else {
226        Err(anyhow::anyhow!("Expected Integer"))
227    }
228}
229
230/// Decode InstalledClosedLimitTilt attribute (0x0013)
231pub fn decode_installed_closed_limit_tilt(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
232    if let tlv::TlvItemValue::Int(v) = inp {
233        Ok(*v as u16)
234    } else {
235        Err(anyhow::anyhow!("Expected Integer"))
236    }
237}
238
239/// Decode VelocityLift attribute (0x0014)
240pub fn decode_velocity_lift(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
241    if let tlv::TlvItemValue::Int(v) = inp {
242        Ok(*v as u8)
243    } else {
244        Err(anyhow::anyhow!("Expected Integer"))
245    }
246}
247
248/// Decode AccelerationTimeLift attribute (0x0015)
249pub fn decode_acceleration_time_lift(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
250    if let tlv::TlvItemValue::Int(v) = inp {
251        Ok(*v as u8)
252    } else {
253        Err(anyhow::anyhow!("Expected Integer"))
254    }
255}
256
257/// Decode DecelerationTimeLift attribute (0x0016)
258pub fn decode_deceleration_time_lift(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
259    if let tlv::TlvItemValue::Int(v) = inp {
260        Ok(*v as u8)
261    } else {
262        Err(anyhow::anyhow!("Expected Integer"))
263    }
264}
265
266/// Decode Mode attribute (0x0017)
267pub fn decode_mode(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
268    if let tlv::TlvItemValue::Int(v) = inp {
269        Ok(*v as u8)
270    } else {
271        Err(anyhow::anyhow!("Expected Integer"))
272    }
273}
274
275/// Decode IntermediateSetpointsLift attribute (0x0018)
276pub fn decode_intermediate_setpoints_lift(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
277    if let tlv::TlvItemValue::Int(v) = inp {
278        Ok(*v as u8)
279    } else {
280        Err(anyhow::anyhow!("Expected Integer"))
281    }
282}
283
284/// Decode IntermediateSetpointsTilt attribute (0x0019)
285pub fn decode_intermediate_setpoints_tilt(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
286    if let tlv::TlvItemValue::Int(v) = inp {
287        Ok(*v as u8)
288    } else {
289        Err(anyhow::anyhow!("Expected Integer"))
290    }
291}
292
293/// Decode SafetyStatus attribute (0x001A)
294pub fn decode_safety_status(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
295    if let tlv::TlvItemValue::Int(v) = inp {
296        Ok(*v as u8)
297    } else {
298        Err(anyhow::anyhow!("Expected Integer"))
299    }
300}
301
302
303// JSON dispatcher function
304
305/// Decode attribute value and return as JSON string
306/// 
307/// # Parameters
308/// * `cluster_id` - The cluster identifier
309/// * `attribute_id` - The attribute identifier
310/// * `tlv_value` - The TLV value to decode
311/// 
312/// # Returns
313/// JSON string representation of the decoded value or error
314pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
315    // Verify this is the correct cluster
316    if cluster_id != 0x0102 {
317        return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0102, got {}\"}}", cluster_id);
318    }
319    
320    match attribute_id {
321        0x0000 => {
322            match decode_type_(tlv_value) {
323                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
324                Err(e) => format!("{{\"error\": \"{}\"}}", e),
325            }
326        }
327        0x0001 => {
328            match decode_physical_closed_limit_lift(tlv_value) {
329                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
330                Err(e) => format!("{{\"error\": \"{}\"}}", e),
331            }
332        }
333        0x0002 => {
334            match decode_physical_closed_limit_tilt(tlv_value) {
335                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
336                Err(e) => format!("{{\"error\": \"{}\"}}", e),
337            }
338        }
339        0x0003 => {
340            match decode_current_position_lift(tlv_value) {
341                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
342                Err(e) => format!("{{\"error\": \"{}\"}}", e),
343            }
344        }
345        0x0004 => {
346            match decode_current_position_tilt(tlv_value) {
347                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
348                Err(e) => format!("{{\"error\": \"{}\"}}", e),
349            }
350        }
351        0x0005 => {
352            match decode_number_of_actuations_lift(tlv_value) {
353                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
354                Err(e) => format!("{{\"error\": \"{}\"}}", e),
355            }
356        }
357        0x0006 => {
358            match decode_number_of_actuations_tilt(tlv_value) {
359                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
360                Err(e) => format!("{{\"error\": \"{}\"}}", e),
361            }
362        }
363        0x0007 => {
364            match decode_config_status(tlv_value) {
365                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
366                Err(e) => format!("{{\"error\": \"{}\"}}", e),
367            }
368        }
369        0x0008 => {
370            match decode_current_position_lift_percentage(tlv_value) {
371                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
372                Err(e) => format!("{{\"error\": \"{}\"}}", e),
373            }
374        }
375        0x0009 => {
376            match decode_current_position_tilt_percentage(tlv_value) {
377                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
378                Err(e) => format!("{{\"error\": \"{}\"}}", e),
379            }
380        }
381        0x000A => {
382            match decode_operational_status(tlv_value) {
383                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
384                Err(e) => format!("{{\"error\": \"{}\"}}", e),
385            }
386        }
387        0x000B => {
388            match decode_target_position_lift_percent100ths(tlv_value) {
389                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
390                Err(e) => format!("{{\"error\": \"{}\"}}", e),
391            }
392        }
393        0x000C => {
394            match decode_target_position_tilt_percent100ths(tlv_value) {
395                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
396                Err(e) => format!("{{\"error\": \"{}\"}}", e),
397            }
398        }
399        0x000D => {
400            match decode_end_product_type(tlv_value) {
401                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
402                Err(e) => format!("{{\"error\": \"{}\"}}", e),
403            }
404        }
405        0x000E => {
406            match decode_current_position_lift_percent100ths(tlv_value) {
407                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
408                Err(e) => format!("{{\"error\": \"{}\"}}", e),
409            }
410        }
411        0x000F => {
412            match decode_current_position_tilt_percent100ths(tlv_value) {
413                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
414                Err(e) => format!("{{\"error\": \"{}\"}}", e),
415            }
416        }
417        0x0010 => {
418            match decode_installed_open_limit_lift(tlv_value) {
419                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
420                Err(e) => format!("{{\"error\": \"{}\"}}", e),
421            }
422        }
423        0x0011 => {
424            match decode_installed_closed_limit_lift(tlv_value) {
425                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
426                Err(e) => format!("{{\"error\": \"{}\"}}", e),
427            }
428        }
429        0x0012 => {
430            match decode_installed_open_limit_tilt(tlv_value) {
431                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
432                Err(e) => format!("{{\"error\": \"{}\"}}", e),
433            }
434        }
435        0x0013 => {
436            match decode_installed_closed_limit_tilt(tlv_value) {
437                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
438                Err(e) => format!("{{\"error\": \"{}\"}}", e),
439            }
440        }
441        0x0014 => {
442            match decode_velocity_lift(tlv_value) {
443                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
444                Err(e) => format!("{{\"error\": \"{}\"}}", e),
445            }
446        }
447        0x0015 => {
448            match decode_acceleration_time_lift(tlv_value) {
449                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
450                Err(e) => format!("{{\"error\": \"{}\"}}", e),
451            }
452        }
453        0x0016 => {
454            match decode_deceleration_time_lift(tlv_value) {
455                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
456                Err(e) => format!("{{\"error\": \"{}\"}}", e),
457            }
458        }
459        0x0017 => {
460            match decode_mode(tlv_value) {
461                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
462                Err(e) => format!("{{\"error\": \"{}\"}}", e),
463            }
464        }
465        0x0018 => {
466            match decode_intermediate_setpoints_lift(tlv_value) {
467                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
468                Err(e) => format!("{{\"error\": \"{}\"}}", e),
469            }
470        }
471        0x0019 => {
472            match decode_intermediate_setpoints_tilt(tlv_value) {
473                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
474                Err(e) => format!("{{\"error\": \"{}\"}}", e),
475            }
476        }
477        0x001A => {
478            match decode_safety_status(tlv_value) {
479                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
480                Err(e) => format!("{{\"error\": \"{}\"}}", e),
481            }
482        }
483        _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
484    }
485}
486
487/// Get list of all attributes supported by this cluster
488/// 
489/// # Returns
490/// Vector of tuples containing (attribute_id, attribute_name)
491pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
492    vec![
493        (0x0000, "Type"),
494        (0x0001, "PhysicalClosedLimitLift"),
495        (0x0002, "PhysicalClosedLimitTilt"),
496        (0x0003, "CurrentPositionLift"),
497        (0x0004, "CurrentPositionTilt"),
498        (0x0005, "NumberOfActuationsLift"),
499        (0x0006, "NumberOfActuationsTilt"),
500        (0x0007, "ConfigStatus"),
501        (0x0008, "CurrentPositionLiftPercentage"),
502        (0x0009, "CurrentPositionTiltPercentage"),
503        (0x000A, "OperationalStatus"),
504        (0x000B, "TargetPositionLiftPercent100ths"),
505        (0x000C, "TargetPositionTiltPercent100ths"),
506        (0x000D, "EndProductType"),
507        (0x000E, "CurrentPositionLiftPercent100ths"),
508        (0x000F, "CurrentPositionTiltPercent100ths"),
509        (0x0010, "InstalledOpenLimitLift"),
510        (0x0011, "InstalledClosedLimitLift"),
511        (0x0012, "InstalledOpenLimitTilt"),
512        (0x0013, "InstalledClosedLimitTilt"),
513        (0x0014, "VelocityLift"),
514        (0x0015, "AccelerationTimeLift"),
515        (0x0016, "DecelerationTimeLift"),
516        (0x0017, "Mode"),
517        (0x0018, "IntermediateSetpointsLift"),
518        (0x0019, "IntermediateSetpointsTilt"),
519        (0x001A, "SafetyStatus"),
520    ]
521}
522