matc/clusters/codec/
fan_control.rs1use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11pub fn encode_step(direction: u8, wrap: bool, lowest_off: bool) -> anyhow::Result<Vec<u8>> {
15 let tlv = tlv::TlvItemEnc {
16 tag: 0,
17 value: tlv::TlvItemValueEnc::StructInvisible(vec![
18 (0, tlv::TlvItemValueEnc::UInt8(direction)).into(),
19 (1, tlv::TlvItemValueEnc::Bool(wrap)).into(),
20 (2, tlv::TlvItemValueEnc::Bool(lowest_off)).into(),
21 ]),
22 };
23 Ok(tlv.encode()?)
24}
25
26pub fn decode_fan_mode(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
30 if let tlv::TlvItemValue::Int(v) = inp {
31 Ok(*v as u8)
32 } else {
33 Err(anyhow::anyhow!("Expected Integer"))
34 }
35}
36
37pub fn decode_fan_mode_sequence(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
39 if let tlv::TlvItemValue::Int(v) = inp {
40 Ok(*v as u8)
41 } else {
42 Err(anyhow::anyhow!("Expected Integer"))
43 }
44}
45
46pub fn decode_percent_setting(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
48 if let tlv::TlvItemValue::Int(v) = inp {
49 Ok(Some(*v as u8))
50 } else {
51 Ok(None)
52 }
53}
54
55pub fn decode_percent_current(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
57 if let tlv::TlvItemValue::Int(v) = inp {
58 Ok(*v as u8)
59 } else {
60 Err(anyhow::anyhow!("Expected Integer"))
61 }
62}
63
64pub fn decode_speed_max(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
66 if let tlv::TlvItemValue::Int(v) = inp {
67 Ok(*v as u8)
68 } else {
69 Err(anyhow::anyhow!("Expected Integer"))
70 }
71}
72
73pub fn decode_speed_setting(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
75 if let tlv::TlvItemValue::Int(v) = inp {
76 Ok(Some(*v as u8))
77 } else {
78 Ok(None)
79 }
80}
81
82pub fn decode_speed_current(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
84 if let tlv::TlvItemValue::Int(v) = inp {
85 Ok(*v as u8)
86 } else {
87 Err(anyhow::anyhow!("Expected Integer"))
88 }
89}
90
91pub fn decode_rock_support(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
100pub fn decode_rock_setting(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
102 if let tlv::TlvItemValue::Int(v) = inp {
103 Ok(*v as u8)
104 } else {
105 Err(anyhow::anyhow!("Expected Integer"))
106 }
107}
108
109pub fn decode_wind_support(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
111 if let tlv::TlvItemValue::Int(v) = inp {
112 Ok(*v as u8)
113 } else {
114 Err(anyhow::anyhow!("Expected Integer"))
115 }
116}
117
118pub fn decode_wind_setting(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
127pub fn decode_airflow_direction(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
129 if let tlv::TlvItemValue::Int(v) = inp {
130 Ok(*v as u8)
131 } else {
132 Err(anyhow::anyhow!("Expected Integer"))
133 }
134}
135
136
137pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
149 if cluster_id != 0x0202 {
151 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0202, got {}\"}}", cluster_id);
152 }
153
154 match attribute_id {
155 0x0000 => {
156 match decode_fan_mode(tlv_value) {
157 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
158 Err(e) => format!("{{\"error\": \"{}\"}}", e),
159 }
160 }
161 0x0001 => {
162 match decode_fan_mode_sequence(tlv_value) {
163 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
164 Err(e) => format!("{{\"error\": \"{}\"}}", e),
165 }
166 }
167 0x0002 => {
168 match decode_percent_setting(tlv_value) {
169 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
170 Err(e) => format!("{{\"error\": \"{}\"}}", e),
171 }
172 }
173 0x0003 => {
174 match decode_percent_current(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 0x0004 => {
180 match decode_speed_max(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 0x0005 => {
186 match decode_speed_setting(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 0x0006 => {
192 match decode_speed_current(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 0x0007 => {
198 match decode_rock_support(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 0x0008 => {
204 match decode_rock_setting(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 0x0009 => {
210 match decode_wind_support(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 0x000A => {
216 match decode_wind_setting(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 0x000B => {
222 match decode_airflow_direction(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 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
228 }
229}
230
231pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
236 vec![
237 (0x0000, "FanMode"),
238 (0x0001, "FanModeSequence"),
239 (0x0002, "PercentSetting"),
240 (0x0003, "PercentCurrent"),
241 (0x0004, "SpeedMax"),
242 (0x0005, "SpeedSetting"),
243 (0x0006, "SpeedCurrent"),
244 (0x0007, "RockSupport"),
245 (0x0008, "RockSetting"),
246 (0x0009, "WindSupport"),
247 (0x000A, "WindSetting"),
248 (0x000B, "AirflowDirection"),
249 ]
250}
251