1#![allow(
5 clippy::all,
6 clippy::pedantic,
7 dead_code,
8 unreachable_pub,
9 unused_imports
10)]
11
12use crate::datatypes::SemanticTagStruct;
13use crate::error::ClusterError;
14use crate::types::Nullable;
15use matter_codec::{ContainerKind, Element, Tag, TlvReader, TlvWriter, Value};
16
17pub const CLUSTER_ID: u32 = 0x0006;
19pub const CLUSTER_REVISION: u16 = 6;
21
22pub mod command_id {
24 pub const OFF: u32 = 0x00;
26 pub const ON: u32 = 0x01;
28 pub const TOGGLE: u32 = 0x02;
30 pub const OFF_WITH_EFFECT: u32 = 0x40;
32 pub const ON_WITH_RECALL_GLOBAL_SCENE: u32 = 0x41;
34 pub const ON_WITH_TIMED_OFF: u32 = 0x42;
36}
37
38pub mod attribute_id {
40 pub const ON_OFF: u32 = 0x0000;
42 pub const GLOBAL_SCENE_CONTROL: u32 = 0x4000;
44 pub const ON_TIME: u32 = 0x4001;
46 pub const OFF_WAIT_TIME: u32 = 0x4002;
48 pub const START_UP_ON_OFF: u32 = 0x4003;
50}
51
52bitflags::bitflags! {
53 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
55 pub struct Feature: u32 {
56 const LT = 1 << 0;
58 const DF = 1 << 1;
60 const OFFONLY = 1 << 2;
62 }
63}
64
65#[derive(Copy, Clone, Debug, PartialEq, Eq)]
67pub enum DelayedAllOffEffectVariantEnum {
68 DelayedOffFastFade,
70 NoFade,
72 DelayedOffSlowFade,
74 Unknown(u8),
76}
77
78impl DelayedAllOffEffectVariantEnum {
79 #[must_use]
81 pub fn from_raw(v: u8) -> Self {
82 match v {
83 0 => Self::DelayedOffFastFade,
84 1 => Self::NoFade,
85 2 => Self::DelayedOffSlowFade,
86 other => Self::Unknown(other),
87 }
88 }
89 #[must_use]
91 pub fn to_raw(self) -> u8 {
92 match self {
93 Self::DelayedOffFastFade => 0,
94 Self::NoFade => 1,
95 Self::DelayedOffSlowFade => 2,
96 Self::Unknown(v) => v,
97 }
98 }
99}
100
101#[derive(Copy, Clone, Debug, PartialEq, Eq)]
103pub enum DyingLightEffectVariantEnum {
104 DyingLightFadeOff,
106 Unknown(u8),
108}
109
110impl DyingLightEffectVariantEnum {
111 #[must_use]
113 pub fn from_raw(v: u8) -> Self {
114 match v {
115 0 => Self::DyingLightFadeOff,
116 other => Self::Unknown(other),
117 }
118 }
119 #[must_use]
121 pub fn to_raw(self) -> u8 {
122 match self {
123 Self::DyingLightFadeOff => 0,
124 Self::Unknown(v) => v,
125 }
126 }
127}
128
129#[derive(Copy, Clone, Debug, PartialEq, Eq)]
131pub enum EffectIdentifierEnum {
132 DelayedAllOff,
134 DyingLight,
136 Unknown(u8),
138}
139
140impl EffectIdentifierEnum {
141 #[must_use]
143 pub fn from_raw(v: u8) -> Self {
144 match v {
145 0 => Self::DelayedAllOff,
146 1 => Self::DyingLight,
147 other => Self::Unknown(other),
148 }
149 }
150 #[must_use]
152 pub fn to_raw(self) -> u8 {
153 match self {
154 Self::DelayedAllOff => 0,
155 Self::DyingLight => 1,
156 Self::Unknown(v) => v,
157 }
158 }
159}
160
161bitflags::bitflags! {
162 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
164 pub struct OnOffControlBitmap: u8 {
165 const ACCEPT_ONLY_WHEN_ON = 1 << 0;
167 }
168}
169
170#[derive(Copy, Clone, Debug, PartialEq, Eq)]
172pub enum StartUpOnOffEnum {
173 Off,
175 On,
177 Toggle,
179 Unknown(u8),
181}
182
183impl StartUpOnOffEnum {
184 #[must_use]
186 pub fn from_raw(v: u8) -> Self {
187 match v {
188 0 => Self::Off,
189 1 => Self::On,
190 2 => Self::Toggle,
191 other => Self::Unknown(other),
192 }
193 }
194 #[must_use]
196 pub fn to_raw(self) -> u8 {
197 match self {
198 Self::Off => 0,
199 Self::On => 1,
200 Self::Toggle => 2,
201 Self::Unknown(v) => v,
202 }
203 }
204}
205
206pub fn decode_on_off(tlv: &[u8]) -> Result<bool, ClusterError> {
211 let mut r = TlvReader::new(tlv);
212 match r.next()? {
213 Some(Element::Scalar {
214 value: Value::Bool(v),
215 ..
216 }) => Ok(v),
217 _ => Err(ClusterError::UnexpectedType { context: "OnOff" }),
218 }
219}
220
221pub fn decode_global_scene_control(tlv: &[u8]) -> Result<bool, ClusterError> {
226 let mut r = TlvReader::new(tlv);
227 match r.next()? {
228 Some(Element::Scalar {
229 value: Value::Bool(v),
230 ..
231 }) => Ok(v),
232 _ => Err(ClusterError::UnexpectedType {
233 context: "GlobalSceneControl",
234 }),
235 }
236}
237
238pub fn decode_on_time(tlv: &[u8]) -> Result<u16, ClusterError> {
243 let mut r = TlvReader::new(tlv);
244 match r.next()? {
245 Some(Element::Scalar {
246 value: Value::Uint(v),
247 ..
248 }) => Ok(u16::try_from(v).map_err(|_| ClusterError::InvalidLength("OnTime"))?),
249 _ => Err(ClusterError::UnexpectedType { context: "OnTime" }),
250 }
251}
252
253#[must_use]
255#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_on_time(value: u16) -> Vec<u8> {
257 let mut buf = Vec::new();
258 let mut w = TlvWriter::new(&mut buf);
259 w.put_uint(Tag::Anonymous, u64::from(value))
260 .expect("infallible: vec writer");
261 buf
262}
263
264pub fn decode_off_wait_time(tlv: &[u8]) -> Result<u16, ClusterError> {
269 let mut r = TlvReader::new(tlv);
270 match r.next()? {
271 Some(Element::Scalar {
272 value: Value::Uint(v),
273 ..
274 }) => Ok(u16::try_from(v).map_err(|_| ClusterError::InvalidLength("OffWaitTime"))?),
275 _ => Err(ClusterError::UnexpectedType {
276 context: "OffWaitTime",
277 }),
278 }
279}
280
281#[must_use]
283#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_off_wait_time(value: u16) -> Vec<u8> {
285 let mut buf = Vec::new();
286 let mut w = TlvWriter::new(&mut buf);
287 w.put_uint(Tag::Anonymous, u64::from(value))
288 .expect("infallible: vec writer");
289 buf
290}
291
292pub fn decode_start_up_on_off(tlv: &[u8]) -> Result<Nullable<StartUpOnOffEnum>, ClusterError> {
297 let mut r = TlvReader::new(tlv);
298 match r.next()? {
299 Some(Element::Scalar {
300 value: Value::Null, ..
301 }) => Ok(Nullable::Null),
302 Some(Element::Scalar {
303 value: Value::Uint(v),
304 ..
305 }) => Ok(Nullable::Value(StartUpOnOffEnum::from_raw(
306 u8::try_from(v).map_err(|_| ClusterError::InvalidLength("StartUpOnOff"))?,
307 ))),
308 _ => Err(ClusterError::UnexpectedType {
309 context: "StartUpOnOff",
310 }),
311 }
312}
313
314#[must_use]
316#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_start_up_on_off(value: Nullable<StartUpOnOffEnum>) -> Vec<u8> {
318 let mut buf = Vec::new();
319 let mut w = TlvWriter::new(&mut buf);
320 match value {
321 Nullable::Null => w.put_null(Tag::Anonymous).expect("infallible: vec writer"),
322 Nullable::Value(value) => {
323 w.put_uint(Tag::Anonymous, u64::from(value.to_raw()))
324 .expect("infallible: vec writer");
325 }
326 }
327 buf
328}
329
330#[must_use]
332#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_off() -> Vec<u8> {
334 let mut buf = Vec::new();
335 let mut w = TlvWriter::new(&mut buf);
336 w.start_structure(Tag::Anonymous)
337 .expect("infallible: vec writer");
338 w.end_container().expect("infallible: vec writer");
339 buf
340}
341
342#[must_use]
344#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_on() -> Vec<u8> {
346 let mut buf = Vec::new();
347 let mut w = TlvWriter::new(&mut buf);
348 w.start_structure(Tag::Anonymous)
349 .expect("infallible: vec writer");
350 w.end_container().expect("infallible: vec writer");
351 buf
352}
353
354#[must_use]
356#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_toggle() -> Vec<u8> {
358 let mut buf = Vec::new();
359 let mut w = TlvWriter::new(&mut buf);
360 w.start_structure(Tag::Anonymous)
361 .expect("infallible: vec writer");
362 w.end_container().expect("infallible: vec writer");
363 buf
364}
365
366#[must_use]
368#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_off_with_effect(
370 effect_identifier: EffectIdentifierEnum,
371 effect_variant: u8,
372) -> Vec<u8> {
373 let mut buf = Vec::new();
374 let mut w = TlvWriter::new(&mut buf);
375 w.start_structure(Tag::Anonymous)
376 .expect("infallible: vec writer");
377 w.put_uint(Tag::Context(0), u64::from(effect_identifier.to_raw()))
378 .expect("infallible: vec writer");
379 w.put_uint(Tag::Context(1), u64::from(effect_variant))
380 .expect("infallible: vec writer");
381 w.end_container().expect("infallible: vec writer");
382 buf
383}
384
385#[must_use]
387#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_on_with_recall_global_scene() -> Vec<u8> {
389 let mut buf = Vec::new();
390 let mut w = TlvWriter::new(&mut buf);
391 w.start_structure(Tag::Anonymous)
392 .expect("infallible: vec writer");
393 w.end_container().expect("infallible: vec writer");
394 buf
395}
396
397#[must_use]
399#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_on_with_timed_off(
401 on_off_control: OnOffControlBitmap,
402 on_time: u16,
403 off_wait_time: u16,
404) -> Vec<u8> {
405 let mut buf = Vec::new();
406 let mut w = TlvWriter::new(&mut buf);
407 w.start_structure(Tag::Anonymous)
408 .expect("infallible: vec writer");
409 w.put_uint(Tag::Context(0), u64::from(on_off_control.bits()))
410 .expect("infallible: vec writer");
411 w.put_uint(Tag::Context(1), u64::from(on_time))
412 .expect("infallible: vec writer");
413 w.put_uint(Tag::Context(2), u64::from(off_wait_time))
414 .expect("infallible: vec writer");
415 w.end_container().expect("infallible: vec writer");
416 buf
417}