matc/clusters/codec/
mode_select.rs1use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11#[derive(Debug, serde::Serialize)]
14pub struct ModeOption {
15 pub label: Option<String>,
16 pub mode: Option<u8>,
17 pub semantic_tags: Option<Vec<SemanticTag>>,
18}
19
20#[derive(Debug, serde::Serialize)]
21pub struct SemanticTag {
22 pub mfg_code: Option<u16>,
23 pub value: Option<u8>,
24}
25
26pub fn encode_change_to_mode(new_mode: u8) -> anyhow::Result<Vec<u8>> {
30 let tlv = tlv::TlvItemEnc {
31 tag: 0,
32 value: tlv::TlvItemValueEnc::StructInvisible(vec![
33 (0, tlv::TlvItemValueEnc::UInt8(new_mode)).into(),
34 ]),
35 };
36 Ok(tlv.encode()?)
37}
38
39pub fn decode_description(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
43 if let tlv::TlvItemValue::String(v) = inp {
44 Ok(v.clone())
45 } else {
46 Err(anyhow::anyhow!("Expected String"))
47 }
48}
49
50pub fn decode_standard_namespace(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
52 if let tlv::TlvItemValue::Int(v) = inp {
53 Ok(Some(*v as u8))
54 } else {
55 Ok(None)
56 }
57}
58
59pub fn decode_supported_modes(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<ModeOption>> {
61 let mut res = Vec::new();
62 if let tlv::TlvItemValue::List(v) = inp {
63 for item in v {
64 res.push(ModeOption {
65 label: item.get_string_owned(&[0]),
66 mode: item.get_int(&[1]).map(|v| v as u8),
67 semantic_tags: {
68 if let Some(tlv::TlvItemValue::List(l)) = item.get(&[2]) {
69 let mut items = Vec::new();
70 for list_item in l {
71 items.push(SemanticTag {
72 mfg_code: list_item.get_int(&[0]).map(|v| v as u16),
73 value: list_item.get_int(&[1]).map(|v| v as u8),
74 });
75 }
76 Some(items)
77 } else {
78 None
79 }
80 },
81 });
82 }
83 }
84 Ok(res)
85}
86
87pub fn decode_current_mode(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
89 if let tlv::TlvItemValue::Int(v) = inp {
90 Ok(*v as u8)
91 } else {
92 Err(anyhow::anyhow!("Expected Integer"))
93 }
94}
95
96pub fn decode_start_up_mode(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
98 if let tlv::TlvItemValue::Int(v) = inp {
99 Ok(Some(*v as u8))
100 } else {
101 Ok(None)
102 }
103}
104
105pub fn decode_on_mode(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
107 if let tlv::TlvItemValue::Int(v) = inp {
108 Ok(Some(*v as u8))
109 } else {
110 Ok(None)
111 }
112}
113
114
115pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
127 if cluster_id != 0x0050 {
129 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0050, got {}\"}}", cluster_id);
130 }
131
132 match attribute_id {
133 0x0000 => {
134 match decode_description(tlv_value) {
135 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
136 Err(e) => format!("{{\"error\": \"{}\"}}", e),
137 }
138 }
139 0x0001 => {
140 match decode_standard_namespace(tlv_value) {
141 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
142 Err(e) => format!("{{\"error\": \"{}\"}}", e),
143 }
144 }
145 0x0002 => {
146 match decode_supported_modes(tlv_value) {
147 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
148 Err(e) => format!("{{\"error\": \"{}\"}}", e),
149 }
150 }
151 0x0003 => {
152 match decode_current_mode(tlv_value) {
153 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
154 Err(e) => format!("{{\"error\": \"{}\"}}", e),
155 }
156 }
157 0x0004 => {
158 match decode_start_up_mode(tlv_value) {
159 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
160 Err(e) => format!("{{\"error\": \"{}\"}}", e),
161 }
162 }
163 0x0005 => {
164 match decode_on_mode(tlv_value) {
165 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
166 Err(e) => format!("{{\"error\": \"{}\"}}", e),
167 }
168 }
169 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
170 }
171}
172
173pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
178 vec![
179 (0x0000, "Description"),
180 (0x0001, "StandardNamespace"),
181 (0x0002, "SupportedModes"),
182 (0x0003, "CurrentMode"),
183 (0x0004, "StartUpMode"),
184 (0x0005, "OnMode"),
185 ]
186}
187