1use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11use crate::clusters::helpers::{serialize_opt_bytes_as_hex};
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
17#[repr(u8)]
18pub enum GroupKeyMulticastPolicy {
19 Pergroupid = 0,
21 Allnodes = 1,
23}
24
25impl GroupKeyMulticastPolicy {
26 pub fn from_u8(value: u8) -> Option<Self> {
28 match value {
29 0 => Some(GroupKeyMulticastPolicy::Pergroupid),
30 1 => Some(GroupKeyMulticastPolicy::Allnodes),
31 _ => None,
32 }
33 }
34
35 pub fn to_u8(self) -> u8 {
37 self as u8
38 }
39}
40
41impl From<GroupKeyMulticastPolicy> for u8 {
42 fn from(val: GroupKeyMulticastPolicy) -> Self {
43 val as u8
44 }
45}
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
48#[repr(u8)]
49pub enum GroupKeySecurityPolicy {
50 Trustfirst = 0,
52 Cacheandsync = 1,
54}
55
56impl GroupKeySecurityPolicy {
57 pub fn from_u8(value: u8) -> Option<Self> {
59 match value {
60 0 => Some(GroupKeySecurityPolicy::Trustfirst),
61 1 => Some(GroupKeySecurityPolicy::Cacheandsync),
62 _ => None,
63 }
64 }
65
66 pub fn to_u8(self) -> u8 {
68 self as u8
69 }
70}
71
72impl From<GroupKeySecurityPolicy> for u8 {
73 fn from(val: GroupKeySecurityPolicy) -> Self {
74 val as u8
75 }
76}
77
78#[derive(Debug, serde::Serialize)]
81pub struct GroupInfoMap {
82 pub group_id: Option<u8>,
83 pub endpoints: Option<Vec<u16>>,
84 pub group_name: Option<String>,
85}
86
87#[derive(Debug, serde::Serialize)]
88pub struct GroupKeyMap {
89 pub group_id: Option<u8>,
90 pub group_key_set_id: Option<u16>,
91}
92
93#[derive(Debug, serde::Serialize)]
94pub struct GroupKeySet {
95 pub group_key_set_id: Option<u16>,
96 pub group_key_security_policy: Option<GroupKeySecurityPolicy>,
97 #[serde(serialize_with = "serialize_opt_bytes_as_hex")]
98 pub epoch_key0: Option<Vec<u8>>,
99 pub epoch_start_time0: Option<u64>,
100 #[serde(serialize_with = "serialize_opt_bytes_as_hex")]
101 pub epoch_key1: Option<Vec<u8>>,
102 pub epoch_start_time1: Option<u64>,
103 #[serde(serialize_with = "serialize_opt_bytes_as_hex")]
104 pub epoch_key2: Option<Vec<u8>>,
105 pub epoch_start_time2: Option<u64>,
106 pub group_key_multicast_policy: Option<GroupKeyMulticastPolicy>,
107}
108
109pub fn encode_key_set_write(group_key_set: GroupKeySet) -> anyhow::Result<Vec<u8>> {
113 let mut group_key_set_fields = Vec::new();
115 if let Some(x) = group_key_set.group_key_set_id { group_key_set_fields.push((0, tlv::TlvItemValueEnc::UInt16(x)).into()); }
116 if let Some(x) = group_key_set.group_key_security_policy { group_key_set_fields.push((1, tlv::TlvItemValueEnc::UInt8(x.to_u8())).into()); }
117 if let Some(x) = group_key_set.epoch_key0 { group_key_set_fields.push((2, tlv::TlvItemValueEnc::OctetString(x.clone())).into()); }
118 if let Some(x) = group_key_set.epoch_start_time0 { group_key_set_fields.push((3, tlv::TlvItemValueEnc::UInt64(x)).into()); }
119 if let Some(x) = group_key_set.epoch_key1 { group_key_set_fields.push((4, tlv::TlvItemValueEnc::OctetString(x.clone())).into()); }
120 if let Some(x) = group_key_set.epoch_start_time1 { group_key_set_fields.push((5, tlv::TlvItemValueEnc::UInt64(x)).into()); }
121 if let Some(x) = group_key_set.epoch_key2 { group_key_set_fields.push((6, tlv::TlvItemValueEnc::OctetString(x.clone())).into()); }
122 if let Some(x) = group_key_set.epoch_start_time2 { group_key_set_fields.push((7, tlv::TlvItemValueEnc::UInt64(x)).into()); }
123 if let Some(x) = group_key_set.group_key_multicast_policy { group_key_set_fields.push((8, tlv::TlvItemValueEnc::UInt8(x.to_u8())).into()); }
124 let tlv = tlv::TlvItemEnc {
125 tag: 0,
126 value: tlv::TlvItemValueEnc::StructInvisible(vec![
127 (0, tlv::TlvItemValueEnc::StructInvisible(group_key_set_fields)).into(),
128 ]),
129 };
130 Ok(tlv.encode()?)
131}
132
133pub fn encode_key_set_read(group_key_set_id: u16) -> anyhow::Result<Vec<u8>> {
135 let tlv = tlv::TlvItemEnc {
136 tag: 0,
137 value: tlv::TlvItemValueEnc::StructInvisible(vec![
138 (0, tlv::TlvItemValueEnc::UInt16(group_key_set_id)).into(),
139 ]),
140 };
141 Ok(tlv.encode()?)
142}
143
144pub fn encode_key_set_remove(group_key_set_id: u16) -> anyhow::Result<Vec<u8>> {
146 let tlv = tlv::TlvItemEnc {
147 tag: 0,
148 value: tlv::TlvItemValueEnc::StructInvisible(vec![
149 (0, tlv::TlvItemValueEnc::UInt16(group_key_set_id)).into(),
150 ]),
151 };
152 Ok(tlv.encode()?)
153}
154
155pub fn encode_key_set_read_all_indices(do_not_use: u8) -> anyhow::Result<Vec<u8>> {
157 let tlv = tlv::TlvItemEnc {
158 tag: 0,
159 value: tlv::TlvItemValueEnc::StructInvisible(vec![
160 (0, tlv::TlvItemValueEnc::UInt8(do_not_use)).into(),
161 ]),
162 };
163 Ok(tlv.encode()?)
164}
165
166pub fn decode_group_key_map(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<GroupKeyMap>> {
170 let mut res = Vec::new();
171 if let tlv::TlvItemValue::List(v) = inp {
172 for item in v {
173 res.push(GroupKeyMap {
174 group_id: item.get_int(&[1]).map(|v| v as u8),
175 group_key_set_id: item.get_int(&[2]).map(|v| v as u16),
176 });
177 }
178 }
179 Ok(res)
180}
181
182pub fn decode_group_table(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<GroupInfoMap>> {
184 let mut res = Vec::new();
185 if let tlv::TlvItemValue::List(v) = inp {
186 for item in v {
187 res.push(GroupInfoMap {
188 group_id: item.get_int(&[1]).map(|v| v as u8),
189 endpoints: {
190 if let Some(tlv::TlvItemValue::List(l)) = item.get(&[2]) {
191 let items: Vec<u16> = l.iter().filter_map(|e| { if let tlv::TlvItemValue::Int(v) = &e.value { Some(*v as u16) } else { None } }).collect();
192 Some(items)
193 } else {
194 None
195 }
196 },
197 group_name: item.get_string_owned(&[3]),
198 });
199 }
200 }
201 Ok(res)
202}
203
204pub fn decode_max_groups_per_fabric(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
206 if let tlv::TlvItemValue::Int(v) = inp {
207 Ok(*v as u16)
208 } else {
209 Err(anyhow::anyhow!("Expected UInt16"))
210 }
211}
212
213pub fn decode_max_group_keys_per_fabric(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
215 if let tlv::TlvItemValue::Int(v) = inp {
216 Ok(*v as u16)
217 } else {
218 Err(anyhow::anyhow!("Expected UInt16"))
219 }
220}
221
222
223pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
235 if cluster_id != 0x003F {
237 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x003F, got {}\"}}", cluster_id);
238 }
239
240 match attribute_id {
241 0x0000 => {
242 match decode_group_key_map(tlv_value) {
243 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
244 Err(e) => format!("{{\"error\": \"{}\"}}", e),
245 }
246 }
247 0x0001 => {
248 match decode_group_table(tlv_value) {
249 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
250 Err(e) => format!("{{\"error\": \"{}\"}}", e),
251 }
252 }
253 0x0002 => {
254 match decode_max_groups_per_fabric(tlv_value) {
255 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
256 Err(e) => format!("{{\"error\": \"{}\"}}", e),
257 }
258 }
259 0x0003 => {
260 match decode_max_group_keys_per_fabric(tlv_value) {
261 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
262 Err(e) => format!("{{\"error\": \"{}\"}}", e),
263 }
264 }
265 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
266 }
267}
268
269pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
274 vec![
275 (0x0000, "GroupKeyMap"),
276 (0x0001, "GroupTable"),
277 (0x0002, "MaxGroupsPerFabric"),
278 (0x0003, "MaxGroupKeysPerFabric"),
279 ]
280}
281
282#[derive(Debug, serde::Serialize)]
283pub struct KeySetReadResponse {
284 pub group_key_set: Option<GroupKeySet>,
285}
286
287#[derive(Debug, serde::Serialize)]
288pub struct KeySetReadAllIndicesResponse {
289 pub group_key_set_i_ds: Option<Vec<u16>>,
290}
291
292pub fn decode_key_set_read_response(inp: &tlv::TlvItemValue) -> anyhow::Result<KeySetReadResponse> {
296 if let tlv::TlvItemValue::List(_fields) = inp {
297 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
298 Ok(KeySetReadResponse {
299 group_key_set: {
300 if let Some(nested_tlv) = item.get(&[0]) {
301 if let tlv::TlvItemValue::List(_) = nested_tlv {
302 let nested_item = tlv::TlvItem { tag: 0, value: nested_tlv.clone() };
303 Some(GroupKeySet {
304 group_key_set_id: nested_item.get_int(&[0]).map(|v| v as u16),
305 group_key_security_policy: nested_item.get_int(&[1]).and_then(|v| GroupKeySecurityPolicy::from_u8(v as u8)),
306 epoch_key0: nested_item.get_octet_string_owned(&[2]),
307 epoch_start_time0: nested_item.get_int(&[3]),
308 epoch_key1: nested_item.get_octet_string_owned(&[4]),
309 epoch_start_time1: nested_item.get_int(&[5]),
310 epoch_key2: nested_item.get_octet_string_owned(&[6]),
311 epoch_start_time2: nested_item.get_int(&[7]),
312 group_key_multicast_policy: nested_item.get_int(&[8]).and_then(|v| GroupKeyMulticastPolicy::from_u8(v as u8)),
313 })
314 } else {
315 None
316 }
317 } else {
318 None
319 }
320 },
321 })
322 } else {
323 Err(anyhow::anyhow!("Expected struct fields"))
324 }
325}
326
327pub fn decode_key_set_read_all_indices_response(inp: &tlv::TlvItemValue) -> anyhow::Result<KeySetReadAllIndicesResponse> {
329 if let tlv::TlvItemValue::List(_fields) = inp {
330 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
331 Ok(KeySetReadAllIndicesResponse {
332 group_key_set_i_ds: {
333 if let Some(tlv::TlvItemValue::List(l)) = item.get(&[0]) {
334 let items: Vec<u16> = l.iter().filter_map(|e| { if let tlv::TlvItemValue::Int(v) = &e.value { Some(*v as u16) } else { None } }).collect();
335 Some(items)
336 } else {
337 None
338 }
339 },
340 })
341 } else {
342 Err(anyhow::anyhow!("Expected struct fields"))
343 }
344}
345