matc/clusters/codec/
door_lock.rs

1//! Generated Matter TLV encoders and decoders for Door Lock Cluster
2//! Cluster ID: 0x0101
3//! 
4//! This file is automatically generated from DoorLock.xml
5
6use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11// Struct definitions
12
13#[derive(Debug, serde::Serialize)]
14pub struct Credential {
15    pub credential_type: Option<u8>,
16    pub credential_index: Option<u16>,
17}
18
19// Command encoders
20
21/// Encode LockDoor command (0x00)
22pub fn encode_lock_door(pin_code: Vec<u8>) -> anyhow::Result<Vec<u8>> {
23    let tlv = tlv::TlvItemEnc {
24        tag: 0,
25        value: tlv::TlvItemValueEnc::StructInvisible(vec![
26        (0, tlv::TlvItemValueEnc::OctetString(pin_code)).into(),
27        ]),
28    };
29    Ok(tlv.encode()?)
30}
31
32/// Encode UnlockDoor command (0x01)
33pub fn encode_unlock_door(pin_code: Vec<u8>) -> anyhow::Result<Vec<u8>> {
34    let tlv = tlv::TlvItemEnc {
35        tag: 0,
36        value: tlv::TlvItemValueEnc::StructInvisible(vec![
37        (0, tlv::TlvItemValueEnc::OctetString(pin_code)).into(),
38        ]),
39    };
40    Ok(tlv.encode()?)
41}
42
43/// Encode UnlockWithTimeout command (0x03)
44pub fn encode_unlock_with_timeout(timeout: u16, pin_code: Vec<u8>) -> anyhow::Result<Vec<u8>> {
45    let tlv = tlv::TlvItemEnc {
46        tag: 0,
47        value: tlv::TlvItemValueEnc::StructInvisible(vec![
48        (0, tlv::TlvItemValueEnc::UInt16(timeout)).into(),
49        (1, tlv::TlvItemValueEnc::OctetString(pin_code)).into(),
50        ]),
51    };
52    Ok(tlv.encode()?)
53}
54
55/// Encode SetPINCode command (0x05)
56pub fn encode_set_pin_code(user_id: u16, user_status: Option<u8>, user_type: Option<u8>, pin: Vec<u8>) -> anyhow::Result<Vec<u8>> {
57    let tlv = tlv::TlvItemEnc {
58        tag: 0,
59        value: tlv::TlvItemValueEnc::StructInvisible(vec![
60        (0, tlv::TlvItemValueEnc::UInt16(user_id)).into(),
61        (1, tlv::TlvItemValueEnc::UInt8(user_status.unwrap_or(0))).into(),
62        (2, tlv::TlvItemValueEnc::UInt8(user_type.unwrap_or(0))).into(),
63        (3, tlv::TlvItemValueEnc::OctetString(pin)).into(),
64        ]),
65    };
66    Ok(tlv.encode()?)
67}
68
69/// Encode GetPINCode command (0x06)
70pub fn encode_get_pin_code(user_id: u16) -> anyhow::Result<Vec<u8>> {
71    let tlv = tlv::TlvItemEnc {
72        tag: 0,
73        value: tlv::TlvItemValueEnc::StructInvisible(vec![
74        (0, tlv::TlvItemValueEnc::UInt16(user_id)).into(),
75        ]),
76    };
77    Ok(tlv.encode()?)
78}
79
80/// Encode ClearPINCode command (0x07)
81pub fn encode_clear_pin_code(pin_slot_index: u16) -> anyhow::Result<Vec<u8>> {
82    let tlv = tlv::TlvItemEnc {
83        tag: 0,
84        value: tlv::TlvItemValueEnc::StructInvisible(vec![
85        (0, tlv::TlvItemValueEnc::UInt16(pin_slot_index)).into(),
86        ]),
87    };
88    Ok(tlv.encode()?)
89}
90
91/// Encode SetUserStatus command (0x09)
92pub fn encode_set_user_status(user_id: u16, user_status: u8) -> anyhow::Result<Vec<u8>> {
93    let tlv = tlv::TlvItemEnc {
94        tag: 0,
95        value: tlv::TlvItemValueEnc::StructInvisible(vec![
96        (0, tlv::TlvItemValueEnc::UInt16(user_id)).into(),
97        (1, tlv::TlvItemValueEnc::UInt8(user_status)).into(),
98        ]),
99    };
100    Ok(tlv.encode()?)
101}
102
103/// Encode GetUserStatus command (0x0A)
104pub fn encode_get_user_status(user_id: u16) -> anyhow::Result<Vec<u8>> {
105    let tlv = tlv::TlvItemEnc {
106        tag: 0,
107        value: tlv::TlvItemValueEnc::StructInvisible(vec![
108        (0, tlv::TlvItemValueEnc::UInt16(user_id)).into(),
109        ]),
110    };
111    Ok(tlv.encode()?)
112}
113
114/// Encode SetWeekDaySchedule command (0x0B)
115pub fn encode_set_week_day_schedule(week_day_index: u8, user_index: u16, days_mask: u8, start_hour: u8, start_minute: u8, end_hour: u8, end_minute: u8) -> anyhow::Result<Vec<u8>> {
116    let tlv = tlv::TlvItemEnc {
117        tag: 0,
118        value: tlv::TlvItemValueEnc::StructInvisible(vec![
119        (0, tlv::TlvItemValueEnc::UInt8(week_day_index)).into(),
120        (1, tlv::TlvItemValueEnc::UInt16(user_index)).into(),
121        (2, tlv::TlvItemValueEnc::UInt8(days_mask)).into(),
122        (3, tlv::TlvItemValueEnc::UInt8(start_hour)).into(),
123        (4, tlv::TlvItemValueEnc::UInt8(start_minute)).into(),
124        (5, tlv::TlvItemValueEnc::UInt8(end_hour)).into(),
125        (6, tlv::TlvItemValueEnc::UInt8(end_minute)).into(),
126        ]),
127    };
128    Ok(tlv.encode()?)
129}
130
131/// Encode GetWeekDaySchedule command (0x0C)
132pub fn encode_get_week_day_schedule(week_day_index: u8, user_index: u16) -> anyhow::Result<Vec<u8>> {
133    let tlv = tlv::TlvItemEnc {
134        tag: 0,
135        value: tlv::TlvItemValueEnc::StructInvisible(vec![
136        (0, tlv::TlvItemValueEnc::UInt8(week_day_index)).into(),
137        (1, tlv::TlvItemValueEnc::UInt16(user_index)).into(),
138        ]),
139    };
140    Ok(tlv.encode()?)
141}
142
143/// Encode ClearWeekDaySchedule command (0x0D)
144pub fn encode_clear_week_day_schedule(week_day_index: u8, user_index: u16) -> anyhow::Result<Vec<u8>> {
145    let tlv = tlv::TlvItemEnc {
146        tag: 0,
147        value: tlv::TlvItemValueEnc::StructInvisible(vec![
148        (0, tlv::TlvItemValueEnc::UInt8(week_day_index)).into(),
149        (1, tlv::TlvItemValueEnc::UInt16(user_index)).into(),
150        ]),
151    };
152    Ok(tlv.encode()?)
153}
154
155/// Encode SetYearDaySchedule command (0x0E)
156pub fn encode_set_year_day_schedule(year_day_index: u8, user_index: u16, local_start_time: u64, local_end_time: u64) -> anyhow::Result<Vec<u8>> {
157    let tlv = tlv::TlvItemEnc {
158        tag: 0,
159        value: tlv::TlvItemValueEnc::StructInvisible(vec![
160        (0, tlv::TlvItemValueEnc::UInt8(year_day_index)).into(),
161        (1, tlv::TlvItemValueEnc::UInt16(user_index)).into(),
162        (2, tlv::TlvItemValueEnc::UInt64(local_start_time)).into(),
163        (3, tlv::TlvItemValueEnc::UInt64(local_end_time)).into(),
164        ]),
165    };
166    Ok(tlv.encode()?)
167}
168
169/// Encode GetYearDaySchedule command (0x0F)
170pub fn encode_get_year_day_schedule(year_day_index: u8, user_index: u16) -> anyhow::Result<Vec<u8>> {
171    let tlv = tlv::TlvItemEnc {
172        tag: 0,
173        value: tlv::TlvItemValueEnc::StructInvisible(vec![
174        (0, tlv::TlvItemValueEnc::UInt8(year_day_index)).into(),
175        (1, tlv::TlvItemValueEnc::UInt16(user_index)).into(),
176        ]),
177    };
178    Ok(tlv.encode()?)
179}
180
181/// Encode ClearYearDaySchedule command (0x10)
182pub fn encode_clear_year_day_schedule(year_day_index: u8, user_index: u16) -> anyhow::Result<Vec<u8>> {
183    let tlv = tlv::TlvItemEnc {
184        tag: 0,
185        value: tlv::TlvItemValueEnc::StructInvisible(vec![
186        (0, tlv::TlvItemValueEnc::UInt8(year_day_index)).into(),
187        (1, tlv::TlvItemValueEnc::UInt16(user_index)).into(),
188        ]),
189    };
190    Ok(tlv.encode()?)
191}
192
193/// Encode SetHolidaySchedule command (0x11)
194pub fn encode_set_holiday_schedule(holiday_index: u8, local_start_time: u64, local_end_time: u64, operating_mode: u8) -> anyhow::Result<Vec<u8>> {
195    let tlv = tlv::TlvItemEnc {
196        tag: 0,
197        value: tlv::TlvItemValueEnc::StructInvisible(vec![
198        (0, tlv::TlvItemValueEnc::UInt8(holiday_index)).into(),
199        (1, tlv::TlvItemValueEnc::UInt64(local_start_time)).into(),
200        (2, tlv::TlvItemValueEnc::UInt64(local_end_time)).into(),
201        (3, tlv::TlvItemValueEnc::UInt8(operating_mode)).into(),
202        ]),
203    };
204    Ok(tlv.encode()?)
205}
206
207/// Encode GetHolidaySchedule command (0x12)
208pub fn encode_get_holiday_schedule(holiday_index: u8) -> anyhow::Result<Vec<u8>> {
209    let tlv = tlv::TlvItemEnc {
210        tag: 0,
211        value: tlv::TlvItemValueEnc::StructInvisible(vec![
212        (0, tlv::TlvItemValueEnc::UInt8(holiday_index)).into(),
213        ]),
214    };
215    Ok(tlv.encode()?)
216}
217
218/// Encode ClearHolidaySchedule command (0x13)
219pub fn encode_clear_holiday_schedule(holiday_index: u8) -> anyhow::Result<Vec<u8>> {
220    let tlv = tlv::TlvItemEnc {
221        tag: 0,
222        value: tlv::TlvItemValueEnc::StructInvisible(vec![
223        (0, tlv::TlvItemValueEnc::UInt8(holiday_index)).into(),
224        ]),
225    };
226    Ok(tlv.encode()?)
227}
228
229/// Encode SetUserType command (0x14)
230pub fn encode_set_user_type(user_id: u16, user_type: u8) -> anyhow::Result<Vec<u8>> {
231    let tlv = tlv::TlvItemEnc {
232        tag: 0,
233        value: tlv::TlvItemValueEnc::StructInvisible(vec![
234        (0, tlv::TlvItemValueEnc::UInt16(user_id)).into(),
235        (1, tlv::TlvItemValueEnc::UInt8(user_type)).into(),
236        ]),
237    };
238    Ok(tlv.encode()?)
239}
240
241/// Encode GetUserType command (0x15)
242pub fn encode_get_user_type(user_id: u16) -> anyhow::Result<Vec<u8>> {
243    let tlv = tlv::TlvItemEnc {
244        tag: 0,
245        value: tlv::TlvItemValueEnc::StructInvisible(vec![
246        (0, tlv::TlvItemValueEnc::UInt16(user_id)).into(),
247        ]),
248    };
249    Ok(tlv.encode()?)
250}
251
252/// Encode SetRFIDCode command (0x16)
253pub fn encode_set_rfid_code(user_id: u16, user_status: Option<u8>, user_type: Option<u8>, rfid_code: Vec<u8>) -> anyhow::Result<Vec<u8>> {
254    let tlv = tlv::TlvItemEnc {
255        tag: 0,
256        value: tlv::TlvItemValueEnc::StructInvisible(vec![
257        (0, tlv::TlvItemValueEnc::UInt16(user_id)).into(),
258        (1, tlv::TlvItemValueEnc::UInt8(user_status.unwrap_or(0))).into(),
259        (2, tlv::TlvItemValueEnc::UInt8(user_type.unwrap_or(0))).into(),
260        (3, tlv::TlvItemValueEnc::OctetString(rfid_code)).into(),
261        ]),
262    };
263    Ok(tlv.encode()?)
264}
265
266/// Encode GetRFIDCode command (0x17)
267pub fn encode_get_rfid_code(user_id: u16) -> anyhow::Result<Vec<u8>> {
268    let tlv = tlv::TlvItemEnc {
269        tag: 0,
270        value: tlv::TlvItemValueEnc::StructInvisible(vec![
271        (0, tlv::TlvItemValueEnc::UInt16(user_id)).into(),
272        ]),
273    };
274    Ok(tlv.encode()?)
275}
276
277/// Encode ClearRFIDCode command (0x18)
278pub fn encode_clear_rfid_code(rfid_slot_index: u16) -> anyhow::Result<Vec<u8>> {
279    let tlv = tlv::TlvItemEnc {
280        tag: 0,
281        value: tlv::TlvItemValueEnc::StructInvisible(vec![
282        (0, tlv::TlvItemValueEnc::UInt16(rfid_slot_index)).into(),
283        ]),
284    };
285    Ok(tlv.encode()?)
286}
287
288/// Encode SetUser command (0x1A)
289pub fn encode_set_user(operation_type: u8, user_index: u16, user_name: Option<String>, user_unique_id: Option<u32>, user_status: Option<u8>, user_type: Option<u8>, credential_rule: Option<u8>) -> anyhow::Result<Vec<u8>> {
290    let tlv = tlv::TlvItemEnc {
291        tag: 0,
292        value: tlv::TlvItemValueEnc::StructInvisible(vec![
293        (0, tlv::TlvItemValueEnc::UInt8(operation_type)).into(),
294        (1, tlv::TlvItemValueEnc::UInt16(user_index)).into(),
295        (2, tlv::TlvItemValueEnc::String(user_name.unwrap_or("".to_string()))).into(),
296        (3, tlv::TlvItemValueEnc::UInt32(user_unique_id.unwrap_or(0))).into(),
297        (4, tlv::TlvItemValueEnc::UInt8(user_status.unwrap_or(0))).into(),
298        (5, tlv::TlvItemValueEnc::UInt8(user_type.unwrap_or(0))).into(),
299        (6, tlv::TlvItemValueEnc::UInt8(credential_rule.unwrap_or(0))).into(),
300        ]),
301    };
302    Ok(tlv.encode()?)
303}
304
305/// Encode GetUser command (0x1B)
306pub fn encode_get_user(user_index: u16) -> anyhow::Result<Vec<u8>> {
307    let tlv = tlv::TlvItemEnc {
308        tag: 0,
309        value: tlv::TlvItemValueEnc::StructInvisible(vec![
310        (0, tlv::TlvItemValueEnc::UInt16(user_index)).into(),
311        ]),
312    };
313    Ok(tlv.encode()?)
314}
315
316/// Encode ClearUser command (0x1D)
317pub fn encode_clear_user(user_index: u16) -> anyhow::Result<Vec<u8>> {
318    let tlv = tlv::TlvItemEnc {
319        tag: 0,
320        value: tlv::TlvItemValueEnc::StructInvisible(vec![
321        (0, tlv::TlvItemValueEnc::UInt16(user_index)).into(),
322        ]),
323    };
324    Ok(tlv.encode()?)
325}
326
327/// Encode SetCredential command (0x22)
328pub fn encode_set_credential(operation_type: u8, credential: u8, credential_data: Vec<u8>, user_index: Option<u16>, user_status: Option<u8>, user_type: Option<u8>) -> anyhow::Result<Vec<u8>> {
329    let tlv = tlv::TlvItemEnc {
330        tag: 0,
331        value: tlv::TlvItemValueEnc::StructInvisible(vec![
332        (0, tlv::TlvItemValueEnc::UInt8(operation_type)).into(),
333        (1, tlv::TlvItemValueEnc::UInt8(credential)).into(),
334        (2, tlv::TlvItemValueEnc::OctetString(credential_data)).into(),
335        (3, tlv::TlvItemValueEnc::UInt16(user_index.unwrap_or(0))).into(),
336        (4, tlv::TlvItemValueEnc::UInt8(user_status.unwrap_or(0))).into(),
337        (5, tlv::TlvItemValueEnc::UInt8(user_type.unwrap_or(0))).into(),
338        ]),
339    };
340    Ok(tlv.encode()?)
341}
342
343/// Encode GetCredentialStatus command (0x24)
344pub fn encode_get_credential_status(credential: u8) -> anyhow::Result<Vec<u8>> {
345    let tlv = tlv::TlvItemEnc {
346        tag: 0,
347        value: tlv::TlvItemValueEnc::StructInvisible(vec![
348        (0, tlv::TlvItemValueEnc::UInt8(credential)).into(),
349        ]),
350    };
351    Ok(tlv.encode()?)
352}
353
354/// Encode ClearCredential command (0x26)
355pub fn encode_clear_credential(credential: Option<u8>) -> anyhow::Result<Vec<u8>> {
356    let tlv = tlv::TlvItemEnc {
357        tag: 0,
358        value: tlv::TlvItemValueEnc::StructInvisible(vec![
359        (0, tlv::TlvItemValueEnc::UInt8(credential.unwrap_or(0))).into(),
360        ]),
361    };
362    Ok(tlv.encode()?)
363}
364
365/// Encode UnboltDoor command (0x27)
366pub fn encode_unbolt_door(pin_code: Vec<u8>) -> anyhow::Result<Vec<u8>> {
367    let tlv = tlv::TlvItemEnc {
368        tag: 0,
369        value: tlv::TlvItemValueEnc::StructInvisible(vec![
370        (0, tlv::TlvItemValueEnc::OctetString(pin_code)).into(),
371        ]),
372    };
373    Ok(tlv.encode()?)
374}
375
376/// Encode SetAliroReaderConfig command (0x28)
377pub fn encode_set_aliro_reader_config(signing_key: Vec<u8>, verification_key: Vec<u8>, group_identifier: Vec<u8>, group_resolving_key: Vec<u8>) -> anyhow::Result<Vec<u8>> {
378    let tlv = tlv::TlvItemEnc {
379        tag: 0,
380        value: tlv::TlvItemValueEnc::StructInvisible(vec![
381        (0, tlv::TlvItemValueEnc::OctetString(signing_key)).into(),
382        (1, tlv::TlvItemValueEnc::OctetString(verification_key)).into(),
383        (2, tlv::TlvItemValueEnc::OctetString(group_identifier)).into(),
384        (3, tlv::TlvItemValueEnc::OctetString(group_resolving_key)).into(),
385        ]),
386    };
387    Ok(tlv.encode()?)
388}
389
390// Attribute decoders
391
392/// Decode LockState attribute (0x0000)
393pub fn decode_lock_state(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
394    if let tlv::TlvItemValue::Int(v) = inp {
395        Ok(Some(*v as u8))
396    } else {
397        Ok(None)
398    }
399}
400
401/// Decode LockType attribute (0x0001)
402pub fn decode_lock_type(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
403    if let tlv::TlvItemValue::Int(v) = inp {
404        Ok(*v as u8)
405    } else {
406        Err(anyhow::anyhow!("Expected Integer"))
407    }
408}
409
410/// Decode ActuatorEnabled attribute (0x0002)
411pub fn decode_actuator_enabled(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
412    if let tlv::TlvItemValue::Bool(v) = inp {
413        Ok(*v)
414    } else {
415        Err(anyhow::anyhow!("Expected Bool"))
416    }
417}
418
419/// Decode DoorState attribute (0x0003)
420pub fn decode_door_state(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
421    if let tlv::TlvItemValue::Int(v) = inp {
422        Ok(Some(*v as u8))
423    } else {
424        Ok(None)
425    }
426}
427
428/// Decode DoorOpenEvents attribute (0x0004)
429pub fn decode_door_open_events(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
430    if let tlv::TlvItemValue::Int(v) = inp {
431        Ok(*v as u32)
432    } else {
433        Err(anyhow::anyhow!("Expected Integer"))
434    }
435}
436
437/// Decode DoorClosedEvents attribute (0x0005)
438pub fn decode_door_closed_events(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
439    if let tlv::TlvItemValue::Int(v) = inp {
440        Ok(*v as u32)
441    } else {
442        Err(anyhow::anyhow!("Expected Integer"))
443    }
444}
445
446/// Decode OpenPeriod attribute (0x0006)
447pub fn decode_open_period(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
448    if let tlv::TlvItemValue::Int(v) = inp {
449        Ok(*v as u16)
450    } else {
451        Err(anyhow::anyhow!("Expected Integer"))
452    }
453}
454
455/// Decode NumberOfTotalUsersSupported attribute (0x0011)
456pub fn decode_number_of_total_users_supported(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
457    if let tlv::TlvItemValue::Int(v) = inp {
458        Ok(*v as u16)
459    } else {
460        Err(anyhow::anyhow!("Expected Integer"))
461    }
462}
463
464/// Decode NumberOfPINUsersSupported attribute (0x0012)
465pub fn decode_number_of_pin_users_supported(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
466    if let tlv::TlvItemValue::Int(v) = inp {
467        Ok(*v as u16)
468    } else {
469        Err(anyhow::anyhow!("Expected Integer"))
470    }
471}
472
473/// Decode NumberOfRFIDUsersSupported attribute (0x0013)
474pub fn decode_number_of_rfid_users_supported(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
475    if let tlv::TlvItemValue::Int(v) = inp {
476        Ok(*v as u16)
477    } else {
478        Err(anyhow::anyhow!("Expected Integer"))
479    }
480}
481
482/// Decode NumberOfWeekDaySchedulesSupportedPerUser attribute (0x0014)
483pub fn decode_number_of_week_day_schedules_supported_per_user(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
484    if let tlv::TlvItemValue::Int(v) = inp {
485        Ok(*v as u8)
486    } else {
487        Err(anyhow::anyhow!("Expected Integer"))
488    }
489}
490
491/// Decode NumberOfYearDaySchedulesSupportedPerUser attribute (0x0015)
492pub fn decode_number_of_year_day_schedules_supported_per_user(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
493    if let tlv::TlvItemValue::Int(v) = inp {
494        Ok(*v as u8)
495    } else {
496        Err(anyhow::anyhow!("Expected Integer"))
497    }
498}
499
500/// Decode NumberOfHolidaySchedulesSupported attribute (0x0016)
501pub fn decode_number_of_holiday_schedules_supported(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
502    if let tlv::TlvItemValue::Int(v) = inp {
503        Ok(*v as u8)
504    } else {
505        Err(anyhow::anyhow!("Expected Integer"))
506    }
507}
508
509/// Decode MaxPINCodeLength attribute (0x0017)
510pub fn decode_max_pin_code_length(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
511    if let tlv::TlvItemValue::Int(v) = inp {
512        Ok(*v as u8)
513    } else {
514        Err(anyhow::anyhow!("Expected Integer"))
515    }
516}
517
518/// Decode MinPINCodeLength attribute (0x0018)
519pub fn decode_min_pin_code_length(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
520    if let tlv::TlvItemValue::Int(v) = inp {
521        Ok(*v as u8)
522    } else {
523        Err(anyhow::anyhow!("Expected Integer"))
524    }
525}
526
527/// Decode MaxRFIDCodeLength attribute (0x0019)
528pub fn decode_max_rfid_code_length(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
529    if let tlv::TlvItemValue::Int(v) = inp {
530        Ok(*v as u8)
531    } else {
532        Err(anyhow::anyhow!("Expected Integer"))
533    }
534}
535
536/// Decode MinRFIDCodeLength attribute (0x001A)
537pub fn decode_min_rfid_code_length(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
538    if let tlv::TlvItemValue::Int(v) = inp {
539        Ok(*v as u8)
540    } else {
541        Err(anyhow::anyhow!("Expected Integer"))
542    }
543}
544
545/// Decode CredentialRulesSupport attribute (0x001B)
546pub fn decode_credential_rules_support(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
547    if let tlv::TlvItemValue::Int(v) = inp {
548        Ok(*v as u8)
549    } else {
550        Err(anyhow::anyhow!("Expected Integer"))
551    }
552}
553
554/// Decode NumberOfCredentialsSupportedPerUser attribute (0x001C)
555pub fn decode_number_of_credentials_supported_per_user(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
556    if let tlv::TlvItemValue::Int(v) = inp {
557        Ok(*v as u8)
558    } else {
559        Err(anyhow::anyhow!("Expected Integer"))
560    }
561}
562
563/// Decode Language attribute (0x0021)
564pub fn decode_language(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
565    if let tlv::TlvItemValue::String(v) = inp {
566        Ok(v.clone())
567    } else {
568        Err(anyhow::anyhow!("Expected String"))
569    }
570}
571
572/// Decode LEDSettings attribute (0x0022)
573pub fn decode_led_settings(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
574    if let tlv::TlvItemValue::Int(v) = inp {
575        Ok(*v as u8)
576    } else {
577        Err(anyhow::anyhow!("Expected Integer"))
578    }
579}
580
581/// Decode AutoRelockTime attribute (0x0023)
582pub fn decode_auto_relock_time(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
583    if let tlv::TlvItemValue::Int(v) = inp {
584        Ok(*v as u32)
585    } else {
586        Err(anyhow::anyhow!("Expected Integer"))
587    }
588}
589
590/// Decode SoundVolume attribute (0x0024)
591pub fn decode_sound_volume(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
592    if let tlv::TlvItemValue::Int(v) = inp {
593        Ok(*v as u8)
594    } else {
595        Err(anyhow::anyhow!("Expected Integer"))
596    }
597}
598
599/// Decode OperatingMode attribute (0x0025)
600pub fn decode_operating_mode(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
601    if let tlv::TlvItemValue::Int(v) = inp {
602        Ok(*v as u8)
603    } else {
604        Err(anyhow::anyhow!("Expected Integer"))
605    }
606}
607
608/// Decode SupportedOperatingModes attribute (0x0026)
609pub fn decode_supported_operating_modes(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
610    if let tlv::TlvItemValue::Int(v) = inp {
611        Ok(*v as u8)
612    } else {
613        Err(anyhow::anyhow!("Expected Integer"))
614    }
615}
616
617/// Decode DefaultConfigurationRegister attribute (0x0027)
618pub fn decode_default_configuration_register(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
619    if let tlv::TlvItemValue::Int(v) = inp {
620        Ok(*v as u8)
621    } else {
622        Err(anyhow::anyhow!("Expected Integer"))
623    }
624}
625
626/// Decode EnableLocalProgramming attribute (0x0028)
627pub fn decode_enable_local_programming(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
628    if let tlv::TlvItemValue::Bool(v) = inp {
629        Ok(*v)
630    } else {
631        Err(anyhow::anyhow!("Expected Bool"))
632    }
633}
634
635/// Decode EnableOneTouchLocking attribute (0x0029)
636pub fn decode_enable_one_touch_locking(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
637    if let tlv::TlvItemValue::Bool(v) = inp {
638        Ok(*v)
639    } else {
640        Err(anyhow::anyhow!("Expected Bool"))
641    }
642}
643
644/// Decode EnableInsideStatusLED attribute (0x002A)
645pub fn decode_enable_inside_status_led(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
646    if let tlv::TlvItemValue::Bool(v) = inp {
647        Ok(*v)
648    } else {
649        Err(anyhow::anyhow!("Expected Bool"))
650    }
651}
652
653/// Decode EnablePrivacyModeButton attribute (0x002B)
654pub fn decode_enable_privacy_mode_button(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
655    if let tlv::TlvItemValue::Bool(v) = inp {
656        Ok(*v)
657    } else {
658        Err(anyhow::anyhow!("Expected Bool"))
659    }
660}
661
662/// Decode LocalProgrammingFeatures attribute (0x002C)
663pub fn decode_local_programming_features(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
664    if let tlv::TlvItemValue::Int(v) = inp {
665        Ok(*v as u8)
666    } else {
667        Err(anyhow::anyhow!("Expected Integer"))
668    }
669}
670
671/// Decode WrongCodeEntryLimit attribute (0x0030)
672pub fn decode_wrong_code_entry_limit(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
673    if let tlv::TlvItemValue::Int(v) = inp {
674        Ok(*v as u8)
675    } else {
676        Err(anyhow::anyhow!("Expected Integer"))
677    }
678}
679
680/// Decode UserCodeTemporaryDisableTime attribute (0x0031)
681pub fn decode_user_code_temporary_disable_time(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
682    if let tlv::TlvItemValue::Int(v) = inp {
683        Ok(*v as u8)
684    } else {
685        Err(anyhow::anyhow!("Expected Integer"))
686    }
687}
688
689/// Decode SendPINOverTheAir attribute (0x0032)
690pub fn decode_send_pin_over_the_air(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
691    if let tlv::TlvItemValue::Bool(v) = inp {
692        Ok(*v)
693    } else {
694        Err(anyhow::anyhow!("Expected Bool"))
695    }
696}
697
698/// Decode RequirePINforRemoteOperation attribute (0x0033)
699pub fn decode_require_pinfor_remote_operation(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
700    if let tlv::TlvItemValue::Bool(v) = inp {
701        Ok(*v)
702    } else {
703        Err(anyhow::anyhow!("Expected Bool"))
704    }
705}
706
707/// Decode SecurityLevel attribute (0x0034)
708pub fn decode_security_level(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
709    if let tlv::TlvItemValue::Int(v) = inp {
710        Ok(*v as u8)
711    } else {
712        Err(anyhow::anyhow!("Expected Integer"))
713    }
714}
715
716/// Decode ExpiringUserTimeout attribute (0x0035)
717pub fn decode_expiring_user_timeout(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
718    if let tlv::TlvItemValue::Int(v) = inp {
719        Ok(*v as u16)
720    } else {
721        Err(anyhow::anyhow!("Expected Integer"))
722    }
723}
724
725/// Decode AliroReaderVerificationKey attribute (0x0080)
726pub fn decode_aliro_reader_verification_key(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<Vec<u8>>> {
727    if let tlv::TlvItemValue::OctetString(v) = inp {
728        Ok(Some(v.clone()))
729    } else {
730        Ok(None)
731    }
732}
733
734/// Decode AliroReaderGroupIdentifier attribute (0x0081)
735pub fn decode_aliro_reader_group_identifier(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<Vec<u8>>> {
736    if let tlv::TlvItemValue::OctetString(v) = inp {
737        Ok(Some(v.clone()))
738    } else {
739        Ok(None)
740    }
741}
742
743/// Decode AliroReaderGroupSubIdentifier attribute (0x0082)
744pub fn decode_aliro_reader_group_sub_identifier(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<u8>> {
745    if let tlv::TlvItemValue::OctetString(v) = inp {
746        Ok(v.clone())
747    } else {
748        Err(anyhow::anyhow!("Expected OctetString"))
749    }
750}
751
752/// Decode AliroExpeditedTransactionSupportedProtocolVersions attribute (0x0083)
753pub fn decode_aliro_expedited_transaction_supported_protocol_versions(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<Vec<u8>>> {
754    let mut res = Vec::new();
755    if let tlv::TlvItemValue::List(v) = inp {
756        for item in v {
757            if let tlv::TlvItemValue::OctetString(o) = &item.value {
758                res.push(o.clone());
759            }
760        }
761    }
762    Ok(res)
763}
764
765/// Decode AliroGroupResolvingKey attribute (0x0084)
766pub fn decode_aliro_group_resolving_key(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<Vec<u8>>> {
767    if let tlv::TlvItemValue::OctetString(v) = inp {
768        Ok(Some(v.clone()))
769    } else {
770        Ok(None)
771    }
772}
773
774/// Decode AliroSupportedBLEUWBProtocolVersions attribute (0x0085)
775pub fn decode_aliro_supported_bleuwb_protocol_versions(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<Vec<u8>>> {
776    let mut res = Vec::new();
777    if let tlv::TlvItemValue::List(v) = inp {
778        for item in v {
779            if let tlv::TlvItemValue::OctetString(o) = &item.value {
780                res.push(o.clone());
781            }
782        }
783    }
784    Ok(res)
785}
786
787/// Decode AliroBLEAdvertisingVersion attribute (0x0086)
788pub fn decode_aliro_ble_advertising_version(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
789    if let tlv::TlvItemValue::Int(v) = inp {
790        Ok(*v as u8)
791    } else {
792        Err(anyhow::anyhow!("Expected Integer"))
793    }
794}
795
796/// Decode NumberOfAliroCredentialIssuerKeysSupported attribute (0x0087)
797pub fn decode_number_of_aliro_credential_issuer_keys_supported(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
798    if let tlv::TlvItemValue::Int(v) = inp {
799        Ok(*v as u16)
800    } else {
801        Err(anyhow::anyhow!("Expected Integer"))
802    }
803}
804
805/// Decode NumberOfAliroEndpointKeysSupported attribute (0x0088)
806pub fn decode_number_of_aliro_endpoint_keys_supported(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
807    if let tlv::TlvItemValue::Int(v) = inp {
808        Ok(*v as u16)
809    } else {
810        Err(anyhow::anyhow!("Expected Integer"))
811    }
812}
813
814
815// JSON dispatcher function
816
817/// Decode attribute value and return as JSON string
818/// 
819/// # Parameters
820/// * `cluster_id` - The cluster identifier
821/// * `attribute_id` - The attribute identifier
822/// * `tlv_value` - The TLV value to decode
823/// 
824/// # Returns
825/// JSON string representation of the decoded value or error
826pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
827    // Verify this is the correct cluster
828    if cluster_id != 0x0101 {
829        return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0101, got {}\"}}", cluster_id);
830    }
831    
832    match attribute_id {
833        0x0000 => {
834            match decode_lock_state(tlv_value) {
835                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
836                Err(e) => format!("{{\"error\": \"{}\"}}", e),
837            }
838        }
839        0x0001 => {
840            match decode_lock_type(tlv_value) {
841                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
842                Err(e) => format!("{{\"error\": \"{}\"}}", e),
843            }
844        }
845        0x0002 => {
846            match decode_actuator_enabled(tlv_value) {
847                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
848                Err(e) => format!("{{\"error\": \"{}\"}}", e),
849            }
850        }
851        0x0003 => {
852            match decode_door_state(tlv_value) {
853                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
854                Err(e) => format!("{{\"error\": \"{}\"}}", e),
855            }
856        }
857        0x0004 => {
858            match decode_door_open_events(tlv_value) {
859                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
860                Err(e) => format!("{{\"error\": \"{}\"}}", e),
861            }
862        }
863        0x0005 => {
864            match decode_door_closed_events(tlv_value) {
865                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
866                Err(e) => format!("{{\"error\": \"{}\"}}", e),
867            }
868        }
869        0x0006 => {
870            match decode_open_period(tlv_value) {
871                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
872                Err(e) => format!("{{\"error\": \"{}\"}}", e),
873            }
874        }
875        0x0011 => {
876            match decode_number_of_total_users_supported(tlv_value) {
877                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
878                Err(e) => format!("{{\"error\": \"{}\"}}", e),
879            }
880        }
881        0x0012 => {
882            match decode_number_of_pin_users_supported(tlv_value) {
883                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
884                Err(e) => format!("{{\"error\": \"{}\"}}", e),
885            }
886        }
887        0x0013 => {
888            match decode_number_of_rfid_users_supported(tlv_value) {
889                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
890                Err(e) => format!("{{\"error\": \"{}\"}}", e),
891            }
892        }
893        0x0014 => {
894            match decode_number_of_week_day_schedules_supported_per_user(tlv_value) {
895                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
896                Err(e) => format!("{{\"error\": \"{}\"}}", e),
897            }
898        }
899        0x0015 => {
900            match decode_number_of_year_day_schedules_supported_per_user(tlv_value) {
901                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
902                Err(e) => format!("{{\"error\": \"{}\"}}", e),
903            }
904        }
905        0x0016 => {
906            match decode_number_of_holiday_schedules_supported(tlv_value) {
907                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
908                Err(e) => format!("{{\"error\": \"{}\"}}", e),
909            }
910        }
911        0x0017 => {
912            match decode_max_pin_code_length(tlv_value) {
913                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
914                Err(e) => format!("{{\"error\": \"{}\"}}", e),
915            }
916        }
917        0x0018 => {
918            match decode_min_pin_code_length(tlv_value) {
919                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
920                Err(e) => format!("{{\"error\": \"{}\"}}", e),
921            }
922        }
923        0x0019 => {
924            match decode_max_rfid_code_length(tlv_value) {
925                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
926                Err(e) => format!("{{\"error\": \"{}\"}}", e),
927            }
928        }
929        0x001A => {
930            match decode_min_rfid_code_length(tlv_value) {
931                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
932                Err(e) => format!("{{\"error\": \"{}\"}}", e),
933            }
934        }
935        0x001B => {
936            match decode_credential_rules_support(tlv_value) {
937                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
938                Err(e) => format!("{{\"error\": \"{}\"}}", e),
939            }
940        }
941        0x001C => {
942            match decode_number_of_credentials_supported_per_user(tlv_value) {
943                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
944                Err(e) => format!("{{\"error\": \"{}\"}}", e),
945            }
946        }
947        0x0021 => {
948            match decode_language(tlv_value) {
949                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
950                Err(e) => format!("{{\"error\": \"{}\"}}", e),
951            }
952        }
953        0x0022 => {
954            match decode_led_settings(tlv_value) {
955                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
956                Err(e) => format!("{{\"error\": \"{}\"}}", e),
957            }
958        }
959        0x0023 => {
960            match decode_auto_relock_time(tlv_value) {
961                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
962                Err(e) => format!("{{\"error\": \"{}\"}}", e),
963            }
964        }
965        0x0024 => {
966            match decode_sound_volume(tlv_value) {
967                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
968                Err(e) => format!("{{\"error\": \"{}\"}}", e),
969            }
970        }
971        0x0025 => {
972            match decode_operating_mode(tlv_value) {
973                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
974                Err(e) => format!("{{\"error\": \"{}\"}}", e),
975            }
976        }
977        0x0026 => {
978            match decode_supported_operating_modes(tlv_value) {
979                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
980                Err(e) => format!("{{\"error\": \"{}\"}}", e),
981            }
982        }
983        0x0027 => {
984            match decode_default_configuration_register(tlv_value) {
985                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
986                Err(e) => format!("{{\"error\": \"{}\"}}", e),
987            }
988        }
989        0x0028 => {
990            match decode_enable_local_programming(tlv_value) {
991                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
992                Err(e) => format!("{{\"error\": \"{}\"}}", e),
993            }
994        }
995        0x0029 => {
996            match decode_enable_one_touch_locking(tlv_value) {
997                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
998                Err(e) => format!("{{\"error\": \"{}\"}}", e),
999            }
1000        }
1001        0x002A => {
1002            match decode_enable_inside_status_led(tlv_value) {
1003                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1004                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1005            }
1006        }
1007        0x002B => {
1008            match decode_enable_privacy_mode_button(tlv_value) {
1009                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1010                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1011            }
1012        }
1013        0x002C => {
1014            match decode_local_programming_features(tlv_value) {
1015                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1016                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1017            }
1018        }
1019        0x0030 => {
1020            match decode_wrong_code_entry_limit(tlv_value) {
1021                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1022                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1023            }
1024        }
1025        0x0031 => {
1026            match decode_user_code_temporary_disable_time(tlv_value) {
1027                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1028                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1029            }
1030        }
1031        0x0032 => {
1032            match decode_send_pin_over_the_air(tlv_value) {
1033                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1034                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1035            }
1036        }
1037        0x0033 => {
1038            match decode_require_pinfor_remote_operation(tlv_value) {
1039                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1040                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1041            }
1042        }
1043        0x0034 => {
1044            match decode_security_level(tlv_value) {
1045                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1046                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1047            }
1048        }
1049        0x0035 => {
1050            match decode_expiring_user_timeout(tlv_value) {
1051                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1052                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1053            }
1054        }
1055        0x0080 => {
1056            match decode_aliro_reader_verification_key(tlv_value) {
1057                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1058                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1059            }
1060        }
1061        0x0081 => {
1062            match decode_aliro_reader_group_identifier(tlv_value) {
1063                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1064                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1065            }
1066        }
1067        0x0082 => {
1068            match decode_aliro_reader_group_sub_identifier(tlv_value) {
1069                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1070                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1071            }
1072        }
1073        0x0083 => {
1074            match decode_aliro_expedited_transaction_supported_protocol_versions(tlv_value) {
1075                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1076                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1077            }
1078        }
1079        0x0084 => {
1080            match decode_aliro_group_resolving_key(tlv_value) {
1081                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1082                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1083            }
1084        }
1085        0x0085 => {
1086            match decode_aliro_supported_bleuwb_protocol_versions(tlv_value) {
1087                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1088                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1089            }
1090        }
1091        0x0086 => {
1092            match decode_aliro_ble_advertising_version(tlv_value) {
1093                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1094                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1095            }
1096        }
1097        0x0087 => {
1098            match decode_number_of_aliro_credential_issuer_keys_supported(tlv_value) {
1099                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1100                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1101            }
1102        }
1103        0x0088 => {
1104            match decode_number_of_aliro_endpoint_keys_supported(tlv_value) {
1105                Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1106                Err(e) => format!("{{\"error\": \"{}\"}}", e),
1107            }
1108        }
1109        _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
1110    }
1111}
1112
1113/// Get list of all attributes supported by this cluster
1114/// 
1115/// # Returns
1116/// Vector of tuples containing (attribute_id, attribute_name)
1117pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
1118    vec![
1119        (0x0000, "LockState"),
1120        (0x0001, "LockType"),
1121        (0x0002, "ActuatorEnabled"),
1122        (0x0003, "DoorState"),
1123        (0x0004, "DoorOpenEvents"),
1124        (0x0005, "DoorClosedEvents"),
1125        (0x0006, "OpenPeriod"),
1126        (0x0011, "NumberOfTotalUsersSupported"),
1127        (0x0012, "NumberOfPINUsersSupported"),
1128        (0x0013, "NumberOfRFIDUsersSupported"),
1129        (0x0014, "NumberOfWeekDaySchedulesSupportedPerUser"),
1130        (0x0015, "NumberOfYearDaySchedulesSupportedPerUser"),
1131        (0x0016, "NumberOfHolidaySchedulesSupported"),
1132        (0x0017, "MaxPINCodeLength"),
1133        (0x0018, "MinPINCodeLength"),
1134        (0x0019, "MaxRFIDCodeLength"),
1135        (0x001A, "MinRFIDCodeLength"),
1136        (0x001B, "CredentialRulesSupport"),
1137        (0x001C, "NumberOfCredentialsSupportedPerUser"),
1138        (0x0021, "Language"),
1139        (0x0022, "LEDSettings"),
1140        (0x0023, "AutoRelockTime"),
1141        (0x0024, "SoundVolume"),
1142        (0x0025, "OperatingMode"),
1143        (0x0026, "SupportedOperatingModes"),
1144        (0x0027, "DefaultConfigurationRegister"),
1145        (0x0028, "EnableLocalProgramming"),
1146        (0x0029, "EnableOneTouchLocking"),
1147        (0x002A, "EnableInsideStatusLED"),
1148        (0x002B, "EnablePrivacyModeButton"),
1149        (0x002C, "LocalProgrammingFeatures"),
1150        (0x0030, "WrongCodeEntryLimit"),
1151        (0x0031, "UserCodeTemporaryDisableTime"),
1152        (0x0032, "SendPINOverTheAir"),
1153        (0x0033, "RequirePINforRemoteOperation"),
1154        (0x0034, "SecurityLevel"),
1155        (0x0035, "ExpiringUserTimeout"),
1156        (0x0080, "AliroReaderVerificationKey"),
1157        (0x0081, "AliroReaderGroupIdentifier"),
1158        (0x0082, "AliroReaderGroupSubIdentifier"),
1159        (0x0083, "AliroExpeditedTransactionSupportedProtocolVersions"),
1160        (0x0084, "AliroGroupResolvingKey"),
1161        (0x0085, "AliroSupportedBLEUWBProtocolVersions"),
1162        (0x0086, "AliroBLEAdvertisingVersion"),
1163        (0x0087, "NumberOfAliroCredentialIssuerKeysSupported"),
1164        (0x0088, "NumberOfAliroEndpointKeysSupported"),
1165    ]
1166}
1167