matc/clusters/codec/
identify.rs1use 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 EffectIdentifier {
16 Blink = 0,
18 Breathe = 1,
20 Okay = 2,
22 Channelchange = 11,
24 Finisheffect = 254,
26 Stopeffect = 255,
28}
29
30impl EffectIdentifier {
31 pub fn from_u8(value: u8) -> Option<Self> {
33 match value {
34 0 => Some(EffectIdentifier::Blink),
35 1 => Some(EffectIdentifier::Breathe),
36 2 => Some(EffectIdentifier::Okay),
37 11 => Some(EffectIdentifier::Channelchange),
38 254 => Some(EffectIdentifier::Finisheffect),
39 255 => Some(EffectIdentifier::Stopeffect),
40 _ => None,
41 }
42 }
43
44 pub fn to_u8(self) -> u8 {
46 self as u8
47 }
48}
49
50impl From<EffectIdentifier> for u8 {
51 fn from(val: EffectIdentifier) -> Self {
52 val as u8
53 }
54}
55
56#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
57#[repr(u8)]
58pub enum EffectVariant {
59 Default = 0,
61}
62
63impl EffectVariant {
64 pub fn from_u8(value: u8) -> Option<Self> {
66 match value {
67 0 => Some(EffectVariant::Default),
68 _ => None,
69 }
70 }
71
72 pub fn to_u8(self) -> u8 {
74 self as u8
75 }
76}
77
78impl From<EffectVariant> for u8 {
79 fn from(val: EffectVariant) -> Self {
80 val as u8
81 }
82}
83
84#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
85#[repr(u8)]
86pub enum IdentifyType {
87 None = 0,
89 Lightoutput = 1,
91 Visibleindicator = 2,
93 Audiblebeep = 3,
94 Display = 4,
96 Actuator = 5,
98}
99
100impl IdentifyType {
101 pub fn from_u8(value: u8) -> Option<Self> {
103 match value {
104 0 => Some(IdentifyType::None),
105 1 => Some(IdentifyType::Lightoutput),
106 2 => Some(IdentifyType::Visibleindicator),
107 3 => Some(IdentifyType::Audiblebeep),
108 4 => Some(IdentifyType::Display),
109 5 => Some(IdentifyType::Actuator),
110 _ => None,
111 }
112 }
113
114 pub fn to_u8(self) -> u8 {
116 self as u8
117 }
118}
119
120impl From<IdentifyType> for u8 {
121 fn from(val: IdentifyType) -> Self {
122 val as u8
123 }
124}
125
126pub fn encode_identify(identify_time: u16) -> anyhow::Result<Vec<u8>> {
130 let tlv = tlv::TlvItemEnc {
131 tag: 0,
132 value: tlv::TlvItemValueEnc::StructInvisible(vec![
133 (0, tlv::TlvItemValueEnc::UInt16(identify_time)).into(),
134 ]),
135 };
136 Ok(tlv.encode()?)
137}
138
139pub fn encode_trigger_effect(effect_identifier: EffectIdentifier, effect_variant: EffectVariant) -> anyhow::Result<Vec<u8>> {
141 let tlv = tlv::TlvItemEnc {
142 tag: 0,
143 value: tlv::TlvItemValueEnc::StructInvisible(vec![
144 (0, tlv::TlvItemValueEnc::UInt8(effect_identifier.to_u8())).into(),
145 (1, tlv::TlvItemValueEnc::UInt8(effect_variant.to_u8())).into(),
146 ]),
147 };
148 Ok(tlv.encode()?)
149}
150
151pub fn decode_identify_time(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
155 if let tlv::TlvItemValue::Int(v) = inp {
156 Ok(*v as u16)
157 } else {
158 Err(anyhow::anyhow!("Expected UInt16"))
159 }
160}
161
162pub fn decode_identify_type(inp: &tlv::TlvItemValue) -> anyhow::Result<IdentifyType> {
164 if let tlv::TlvItemValue::Int(v) = inp {
165 IdentifyType::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
166 } else {
167 Err(anyhow::anyhow!("Expected Integer"))
168 }
169}
170
171
172pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
184 if cluster_id != 0x0003 {
186 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0003, got {}\"}}", cluster_id);
187 }
188
189 match attribute_id {
190 0x0000 => {
191 match decode_identify_time(tlv_value) {
192 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
193 Err(e) => format!("{{\"error\": \"{}\"}}", e),
194 }
195 }
196 0x0001 => {
197 match decode_identify_type(tlv_value) {
198 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
199 Err(e) => format!("{{\"error\": \"{}\"}}", e),
200 }
201 }
202 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
203 }
204}
205
206pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
211 vec![
212 (0x0000, "IdentifyTime"),
213 (0x0001, "IdentifyType"),
214 ]
215}
216