matc/clusters/codec/
mode_base.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 mode_tags: Option<Vec<ModeTag>>,
18}
19
20#[derive(Debug, serde::Serialize)]
21pub struct ModeTag {
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_supported_modes(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<ModeOption>> {
43 let mut res = Vec::new();
44 if let tlv::TlvItemValue::List(v) = inp {
45 for item in v {
46 res.push(ModeOption {
47 label: item.get_string_owned(&[0]),
48 mode: item.get_int(&[1]).map(|v| v as u8),
49 mode_tags: {
50 if let Some(tlv::TlvItemValue::List(l)) = item.get(&[2]) {
51 let mut items = Vec::new();
52 for list_item in l {
53 items.push(ModeTag {
54 mfg_code: list_item.get_int(&[0]).map(|v| v as u16),
55 value: list_item.get_int(&[1]).map(|v| v as u8),
56 });
57 }
58 Some(items)
59 } else {
60 None
61 }
62 },
63 });
64 }
65 }
66 Ok(res)
67}
68
69pub fn decode_current_mode(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
71 if let tlv::TlvItemValue::Int(v) = inp {
72 Ok(*v as u8)
73 } else {
74 Err(anyhow::anyhow!("Expected Integer"))
75 }
76}
77
78pub fn decode_start_up_mode(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
80 if let tlv::TlvItemValue::Int(v) = inp {
81 Ok(Some(*v as u8))
82 } else {
83 Ok(None)
84 }
85}
86
87pub fn decode_on_mode(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
89 if let tlv::TlvItemValue::Int(v) = inp {
90 Ok(Some(*v as u8))
91 } else {
92 Ok(None)
93 }
94}
95
96
97pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
109 if cluster_id != 0x0000 {
111 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0000, got {}\"}}", cluster_id);
112 }
113
114 match attribute_id {
115 0x0000 => {
116 match decode_supported_modes(tlv_value) {
117 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
118 Err(e) => format!("{{\"error\": \"{}\"}}", e),
119 }
120 }
121 0x0001 => {
122 match decode_current_mode(tlv_value) {
123 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
124 Err(e) => format!("{{\"error\": \"{}\"}}", e),
125 }
126 }
127 0x0002 => {
128 match decode_start_up_mode(tlv_value) {
129 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
130 Err(e) => format!("{{\"error\": \"{}\"}}", e),
131 }
132 }
133 0x0003 => {
134 match decode_on_mode(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 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
140 }
141}
142
143pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
148 vec![
149 (0x0000, "SupportedModes"),
150 (0x0001, "CurrentMode"),
151 (0x0002, "StartUpMode"),
152 (0x0003, "OnMode"),
153 ]
154}
155