matc/clusters/codec/
admin_commissioning_cluster.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 CommissioningWindowStatus {
16 Windownotopen = 0,
18 Enhancedwindowopen = 1,
20 Basicwindowopen = 2,
22}
23
24impl CommissioningWindowStatus {
25 pub fn from_u8(value: u8) -> Option<Self> {
27 match value {
28 0 => Some(CommissioningWindowStatus::Windownotopen),
29 1 => Some(CommissioningWindowStatus::Enhancedwindowopen),
30 2 => Some(CommissioningWindowStatus::Basicwindowopen),
31 _ => None,
32 }
33 }
34
35 pub fn to_u8(self) -> u8 {
37 self as u8
38 }
39}
40
41impl From<CommissioningWindowStatus> for u8 {
42 fn from(val: CommissioningWindowStatus) -> Self {
43 val as u8
44 }
45}
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
48#[repr(u8)]
49pub enum StatusCode {
50 Busy = 2,
52 Pakeparametererror = 3,
54 Windownotopen = 4,
56}
57
58impl StatusCode {
59 pub fn from_u8(value: u8) -> Option<Self> {
61 match value {
62 2 => Some(StatusCode::Busy),
63 3 => Some(StatusCode::Pakeparametererror),
64 4 => Some(StatusCode::Windownotopen),
65 _ => None,
66 }
67 }
68
69 pub fn to_u8(self) -> u8 {
71 self as u8
72 }
73}
74
75impl From<StatusCode> for u8 {
76 fn from(val: StatusCode) -> Self {
77 val as u8
78 }
79}
80
81pub fn encode_open_commissioning_window(commissioning_timeout: u16, pake_passcode_verifier: Vec<u8>, discriminator: u16, iterations: u32, salt: Vec<u8>) -> anyhow::Result<Vec<u8>> {
85 let tlv = tlv::TlvItemEnc {
86 tag: 0,
87 value: tlv::TlvItemValueEnc::StructInvisible(vec![
88 (0, tlv::TlvItemValueEnc::UInt16(commissioning_timeout)).into(),
89 (1, tlv::TlvItemValueEnc::OctetString(pake_passcode_verifier)).into(),
90 (2, tlv::TlvItemValueEnc::UInt16(discriminator)).into(),
91 (3, tlv::TlvItemValueEnc::UInt32(iterations)).into(),
92 (4, tlv::TlvItemValueEnc::OctetString(salt)).into(),
93 ]),
94 };
95 Ok(tlv.encode()?)
96}
97
98pub fn encode_open_basic_commissioning_window(commissioning_timeout: u16) -> anyhow::Result<Vec<u8>> {
100 let tlv = tlv::TlvItemEnc {
101 tag: 0,
102 value: tlv::TlvItemValueEnc::StructInvisible(vec![
103 (0, tlv::TlvItemValueEnc::UInt16(commissioning_timeout)).into(),
104 ]),
105 };
106 Ok(tlv.encode()?)
107}
108
109pub fn decode_window_status(inp: &tlv::TlvItemValue) -> anyhow::Result<CommissioningWindowStatus> {
113 if let tlv::TlvItemValue::Int(v) = inp {
114 CommissioningWindowStatus::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
115 } else {
116 Err(anyhow::anyhow!("Expected Integer"))
117 }
118}
119
120pub fn decode_admin_fabric_index(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
122 if let tlv::TlvItemValue::Int(v) = inp {
123 Ok(Some(*v as u8))
124 } else {
125 Ok(None)
126 }
127}
128
129pub fn decode_admin_vendor_id(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u16>> {
131 if let tlv::TlvItemValue::Int(v) = inp {
132 Ok(Some(*v as u16))
133 } else {
134 Ok(None)
135 }
136}
137
138
139pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
151 if cluster_id != 0x003C {
153 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x003C, got {}\"}}", cluster_id);
154 }
155
156 match attribute_id {
157 0x0000 => {
158 match decode_window_status(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 0x0001 => {
164 match decode_admin_fabric_index(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 0x0002 => {
170 match decode_admin_vendor_id(tlv_value) {
171 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
172 Err(e) => format!("{{\"error\": \"{}\"}}", e),
173 }
174 }
175 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
176 }
177}
178
179pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
184 vec![
185 (0x0000, "WindowStatus"),
186 (0x0001, "AdminFabricIndex"),
187 (0x0002, "AdminVendorId"),
188 ]
189}
190