1#![allow(clippy::too_many_arguments)]
7
8use crate::tlv;
9use anyhow;
10use serde_json;
11
12
13use crate::clusters::helpers::{serialize_opt_bytes_as_hex};
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
19#[repr(u8)]
20pub enum AlarmCode {
21 Lockjammed = 0,
23 Lockfactoryreset = 1,
25 Lockradiopowercycled = 3,
27 Wrongcodeentrylimit = 4,
29 Frontesceutcheonremoved = 5,
31 Doorforcedopen = 6,
33 Doorajar = 7,
35 Forceduser = 8,
37}
38
39impl AlarmCode {
40 pub fn from_u8(value: u8) -> Option<Self> {
42 match value {
43 0 => Some(AlarmCode::Lockjammed),
44 1 => Some(AlarmCode::Lockfactoryreset),
45 3 => Some(AlarmCode::Lockradiopowercycled),
46 4 => Some(AlarmCode::Wrongcodeentrylimit),
47 5 => Some(AlarmCode::Frontesceutcheonremoved),
48 6 => Some(AlarmCode::Doorforcedopen),
49 7 => Some(AlarmCode::Doorajar),
50 8 => Some(AlarmCode::Forceduser),
51 _ => None,
52 }
53 }
54
55 pub fn to_u8(self) -> u8 {
57 self as u8
58 }
59}
60
61impl From<AlarmCode> for u8 {
62 fn from(val: AlarmCode) -> Self {
63 val as u8
64 }
65}
66
67#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
68#[repr(u8)]
69pub enum CredentialRule {
70 Single = 0,
72 Dual = 1,
74 Tri = 2,
76}
77
78impl CredentialRule {
79 pub fn from_u8(value: u8) -> Option<Self> {
81 match value {
82 0 => Some(CredentialRule::Single),
83 1 => Some(CredentialRule::Dual),
84 2 => Some(CredentialRule::Tri),
85 _ => None,
86 }
87 }
88
89 pub fn to_u8(self) -> u8 {
91 self as u8
92 }
93}
94
95impl From<CredentialRule> for u8 {
96 fn from(val: CredentialRule) -> Self {
97 val as u8
98 }
99}
100
101#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
102#[repr(u8)]
103pub enum CredentialType {
104 Programmingpin = 0,
106 Pin = 1,
108 Rfid = 2,
110 Fingerprint = 3,
112 Fingervein = 4,
114 Face = 5,
116 Alirocredentialissuerkey = 6,
118 Aliroevictableendpointkey = 7,
120 Alirononevictableendpointkey = 8,
122}
123
124impl CredentialType {
125 pub fn from_u8(value: u8) -> Option<Self> {
127 match value {
128 0 => Some(CredentialType::Programmingpin),
129 1 => Some(CredentialType::Pin),
130 2 => Some(CredentialType::Rfid),
131 3 => Some(CredentialType::Fingerprint),
132 4 => Some(CredentialType::Fingervein),
133 5 => Some(CredentialType::Face),
134 6 => Some(CredentialType::Alirocredentialissuerkey),
135 7 => Some(CredentialType::Aliroevictableendpointkey),
136 8 => Some(CredentialType::Alirononevictableendpointkey),
137 _ => None,
138 }
139 }
140
141 pub fn to_u8(self) -> u8 {
143 self as u8
144 }
145}
146
147impl From<CredentialType> for u8 {
148 fn from(val: CredentialType) -> Self {
149 val as u8
150 }
151}
152
153#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
154#[repr(u8)]
155pub enum DataOperationType {
156 Add = 0,
158 Clear = 1,
160 Modify = 2,
162}
163
164impl DataOperationType {
165 pub fn from_u8(value: u8) -> Option<Self> {
167 match value {
168 0 => Some(DataOperationType::Add),
169 1 => Some(DataOperationType::Clear),
170 2 => Some(DataOperationType::Modify),
171 _ => None,
172 }
173 }
174
175 pub fn to_u8(self) -> u8 {
177 self as u8
178 }
179}
180
181impl From<DataOperationType> for u8 {
182 fn from(val: DataOperationType) -> Self {
183 val as u8
184 }
185}
186
187#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
188#[repr(u8)]
189pub enum DoorState {
190 Dooropen = 0,
192 Doorclosed = 1,
194 Doorjammed = 2,
196 Doorforcedopen = 3,
198 Doorunspecifiederror = 4,
200 Doorajar = 5,
202}
203
204impl DoorState {
205 pub fn from_u8(value: u8) -> Option<Self> {
207 match value {
208 0 => Some(DoorState::Dooropen),
209 1 => Some(DoorState::Doorclosed),
210 2 => Some(DoorState::Doorjammed),
211 3 => Some(DoorState::Doorforcedopen),
212 4 => Some(DoorState::Doorunspecifiederror),
213 5 => Some(DoorState::Doorajar),
214 _ => None,
215 }
216 }
217
218 pub fn to_u8(self) -> u8 {
220 self as u8
221 }
222}
223
224impl From<DoorState> for u8 {
225 fn from(val: DoorState) -> Self {
226 val as u8
227 }
228}
229
230#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
231#[repr(u8)]
232pub enum EventType {
233 Operation = 0,
235 Programming = 1,
237 Alarm = 2,
239}
240
241impl EventType {
242 pub fn from_u8(value: u8) -> Option<Self> {
244 match value {
245 0 => Some(EventType::Operation),
246 1 => Some(EventType::Programming),
247 2 => Some(EventType::Alarm),
248 _ => None,
249 }
250 }
251
252 pub fn to_u8(self) -> u8 {
254 self as u8
255 }
256}
257
258impl From<EventType> for u8 {
259 fn from(val: EventType) -> Self {
260 val as u8
261 }
262}
263
264#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
265#[repr(u8)]
266pub enum LEDSetting {
267 Noledsignal = 0,
269 Noledsignalaccessallowed = 1,
271 Ledsignalall = 2,
273}
274
275impl LEDSetting {
276 pub fn from_u8(value: u8) -> Option<Self> {
278 match value {
279 0 => Some(LEDSetting::Noledsignal),
280 1 => Some(LEDSetting::Noledsignalaccessallowed),
281 2 => Some(LEDSetting::Ledsignalall),
282 _ => None,
283 }
284 }
285
286 pub fn to_u8(self) -> u8 {
288 self as u8
289 }
290}
291
292impl From<LEDSetting> for u8 {
293 fn from(val: LEDSetting) -> Self {
294 val as u8
295 }
296}
297
298#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
299#[repr(u8)]
300pub enum LockDataType {
301 Unspecified = 0,
303 Programmingcode = 1,
305 Userindex = 2,
307 Weekdayschedule = 3,
309 Yeardayschedule = 4,
311 Holidayschedule = 5,
313 Pin = 6,
315 Rfid = 7,
317 Fingerprint = 8,
319 Fingervein = 9,
321 Face = 10,
323 Alirocredentialissuerkey = 11,
325 Aliroevictableendpointkey = 12,
327 Alirononevictableendpointkey = 13,
329}
330
331impl LockDataType {
332 pub fn from_u8(value: u8) -> Option<Self> {
334 match value {
335 0 => Some(LockDataType::Unspecified),
336 1 => Some(LockDataType::Programmingcode),
337 2 => Some(LockDataType::Userindex),
338 3 => Some(LockDataType::Weekdayschedule),
339 4 => Some(LockDataType::Yeardayschedule),
340 5 => Some(LockDataType::Holidayschedule),
341 6 => Some(LockDataType::Pin),
342 7 => Some(LockDataType::Rfid),
343 8 => Some(LockDataType::Fingerprint),
344 9 => Some(LockDataType::Fingervein),
345 10 => Some(LockDataType::Face),
346 11 => Some(LockDataType::Alirocredentialissuerkey),
347 12 => Some(LockDataType::Aliroevictableendpointkey),
348 13 => Some(LockDataType::Alirononevictableendpointkey),
349 _ => None,
350 }
351 }
352
353 pub fn to_u8(self) -> u8 {
355 self as u8
356 }
357}
358
359impl From<LockDataType> for u8 {
360 fn from(val: LockDataType) -> Self {
361 val as u8
362 }
363}
364
365#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
366#[repr(u8)]
367pub enum LockOperationType {
368 Lock = 0,
370 Unlock = 1,
372 Nonaccessuserevent = 2,
374 Forceduserevent = 3,
376 Unlatch = 4,
378}
379
380impl LockOperationType {
381 pub fn from_u8(value: u8) -> Option<Self> {
383 match value {
384 0 => Some(LockOperationType::Lock),
385 1 => Some(LockOperationType::Unlock),
386 2 => Some(LockOperationType::Nonaccessuserevent),
387 3 => Some(LockOperationType::Forceduserevent),
388 4 => Some(LockOperationType::Unlatch),
389 _ => None,
390 }
391 }
392
393 pub fn to_u8(self) -> u8 {
395 self as u8
396 }
397}
398
399impl From<LockOperationType> for u8 {
400 fn from(val: LockOperationType) -> Self {
401 val as u8
402 }
403}
404
405#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
406#[repr(u8)]
407pub enum LockState {
408 Notfullylocked = 0,
410 Locked = 1,
412 Unlocked = 2,
414 Unlatched = 3,
416}
417
418impl LockState {
419 pub fn from_u8(value: u8) -> Option<Self> {
421 match value {
422 0 => Some(LockState::Notfullylocked),
423 1 => Some(LockState::Locked),
424 2 => Some(LockState::Unlocked),
425 3 => Some(LockState::Unlatched),
426 _ => None,
427 }
428 }
429
430 pub fn to_u8(self) -> u8 {
432 self as u8
433 }
434}
435
436impl From<LockState> for u8 {
437 fn from(val: LockState) -> Self {
438 val as u8
439 }
440}
441
442#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
443#[repr(u8)]
444pub enum LockType {
445 Deadbolt = 0,
447 Magnetic = 1,
449 Other = 2,
451 Mortise = 3,
453 Rim = 4,
455 Latchbolt = 5,
457 Cylindricallock = 6,
459 Tubularlock = 7,
461 Interconnectedlock = 8,
463 Deadlatch = 9,
465 Doorfurniture = 10,
467 Eurocylinder = 11,
469}
470
471impl LockType {
472 pub fn from_u8(value: u8) -> Option<Self> {
474 match value {
475 0 => Some(LockType::Deadbolt),
476 1 => Some(LockType::Magnetic),
477 2 => Some(LockType::Other),
478 3 => Some(LockType::Mortise),
479 4 => Some(LockType::Rim),
480 5 => Some(LockType::Latchbolt),
481 6 => Some(LockType::Cylindricallock),
482 7 => Some(LockType::Tubularlock),
483 8 => Some(LockType::Interconnectedlock),
484 9 => Some(LockType::Deadlatch),
485 10 => Some(LockType::Doorfurniture),
486 11 => Some(LockType::Eurocylinder),
487 _ => None,
488 }
489 }
490
491 pub fn to_u8(self) -> u8 {
493 self as u8
494 }
495}
496
497impl From<LockType> for u8 {
498 fn from(val: LockType) -> Self {
499 val as u8
500 }
501}
502
503#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
504#[repr(u8)]
505pub enum OperatingMode {
506 Normal = 0,
507 Vacation = 1,
508 Privacy = 2,
509 Noremotelockunlock = 3,
510 Passage = 4,
511}
512
513impl OperatingMode {
514 pub fn from_u8(value: u8) -> Option<Self> {
516 match value {
517 0 => Some(OperatingMode::Normal),
518 1 => Some(OperatingMode::Vacation),
519 2 => Some(OperatingMode::Privacy),
520 3 => Some(OperatingMode::Noremotelockunlock),
521 4 => Some(OperatingMode::Passage),
522 _ => None,
523 }
524 }
525
526 pub fn to_u8(self) -> u8 {
528 self as u8
529 }
530}
531
532impl From<OperatingMode> for u8 {
533 fn from(val: OperatingMode) -> Self {
534 val as u8
535 }
536}
537
538#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
539#[repr(u8)]
540pub enum OperationError {
541 Unspecified = 0,
543 Invalidcredential = 1,
545 Disableduserdenied = 2,
547 Restricted = 3,
549 Insufficientbattery = 4,
551}
552
553impl OperationError {
554 pub fn from_u8(value: u8) -> Option<Self> {
556 match value {
557 0 => Some(OperationError::Unspecified),
558 1 => Some(OperationError::Invalidcredential),
559 2 => Some(OperationError::Disableduserdenied),
560 3 => Some(OperationError::Restricted),
561 4 => Some(OperationError::Insufficientbattery),
562 _ => None,
563 }
564 }
565
566 pub fn to_u8(self) -> u8 {
568 self as u8
569 }
570}
571
572impl From<OperationError> for u8 {
573 fn from(val: OperationError) -> Self {
574 val as u8
575 }
576}
577
578#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
579#[repr(u8)]
580pub enum OperationSource {
581 Unspecified = 0,
583 Manual = 1,
585 Proprietaryremote = 2,
587 Keypad = 3,
589 Auto = 4,
591 Button = 5,
593 Schedule = 6,
595 Remote = 7,
597 Rfid = 8,
599 Biometric = 9,
601 Aliro = 10,
603}
604
605impl OperationSource {
606 pub fn from_u8(value: u8) -> Option<Self> {
608 match value {
609 0 => Some(OperationSource::Unspecified),
610 1 => Some(OperationSource::Manual),
611 2 => Some(OperationSource::Proprietaryremote),
612 3 => Some(OperationSource::Keypad),
613 4 => Some(OperationSource::Auto),
614 5 => Some(OperationSource::Button),
615 6 => Some(OperationSource::Schedule),
616 7 => Some(OperationSource::Remote),
617 8 => Some(OperationSource::Rfid),
618 9 => Some(OperationSource::Biometric),
619 10 => Some(OperationSource::Aliro),
620 _ => None,
621 }
622 }
623
624 pub fn to_u8(self) -> u8 {
626 self as u8
627 }
628}
629
630impl From<OperationSource> for u8 {
631 fn from(val: OperationSource) -> Self {
632 val as u8
633 }
634}
635
636#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
637#[repr(u8)]
638pub enum SoundVolume {
639 Silent = 0,
641 Low = 1,
643 High = 2,
645 Medium = 3,
647}
648
649impl SoundVolume {
650 pub fn from_u8(value: u8) -> Option<Self> {
652 match value {
653 0 => Some(SoundVolume::Silent),
654 1 => Some(SoundVolume::Low),
655 2 => Some(SoundVolume::High),
656 3 => Some(SoundVolume::Medium),
657 _ => None,
658 }
659 }
660
661 pub fn to_u8(self) -> u8 {
663 self as u8
664 }
665}
666
667impl From<SoundVolume> for u8 {
668 fn from(val: SoundVolume) -> Self {
669 val as u8
670 }
671}
672
673#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
674#[repr(u8)]
675pub enum StatusCode {
676 Duplicate = 2,
678 Occupied = 3,
680}
681
682impl StatusCode {
683 pub fn from_u8(value: u8) -> Option<Self> {
685 match value {
686 2 => Some(StatusCode::Duplicate),
687 3 => Some(StatusCode::Occupied),
688 _ => None,
689 }
690 }
691
692 pub fn to_u8(self) -> u8 {
694 self as u8
695 }
696}
697
698impl From<StatusCode> for u8 {
699 fn from(val: StatusCode) -> Self {
700 val as u8
701 }
702}
703
704#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
705#[repr(u8)]
706pub enum UserStatus {
707 Available = 0,
709 Occupiedenabled = 1,
711 Occupieddisabled = 3,
713}
714
715impl UserStatus {
716 pub fn from_u8(value: u8) -> Option<Self> {
718 match value {
719 0 => Some(UserStatus::Available),
720 1 => Some(UserStatus::Occupiedenabled),
721 3 => Some(UserStatus::Occupieddisabled),
722 _ => None,
723 }
724 }
725
726 pub fn to_u8(self) -> u8 {
728 self as u8
729 }
730}
731
732impl From<UserStatus> for u8 {
733 fn from(val: UserStatus) -> Self {
734 val as u8
735 }
736}
737
738#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
739#[repr(u8)]
740pub enum UserType {
741 Unrestricteduser = 0,
743 Yeardayscheduleuser = 1,
745 Weekdayscheduleuser = 2,
747 Programminguser = 3,
749 Nonaccessuser = 4,
751 Forceduser = 5,
753 Disposableuser = 6,
755 Expiringuser = 7,
757 Schedulerestricteduser = 8,
759 Remoteonlyuser = 9,
761}
762
763impl UserType {
764 pub fn from_u8(value: u8) -> Option<Self> {
766 match value {
767 0 => Some(UserType::Unrestricteduser),
768 1 => Some(UserType::Yeardayscheduleuser),
769 2 => Some(UserType::Weekdayscheduleuser),
770 3 => Some(UserType::Programminguser),
771 4 => Some(UserType::Nonaccessuser),
772 5 => Some(UserType::Forceduser),
773 6 => Some(UserType::Disposableuser),
774 7 => Some(UserType::Expiringuser),
775 8 => Some(UserType::Schedulerestricteduser),
776 9 => Some(UserType::Remoteonlyuser),
777 _ => None,
778 }
779 }
780
781 pub fn to_u8(self) -> u8 {
783 self as u8
784 }
785}
786
787impl From<UserType> for u8 {
788 fn from(val: UserType) -> Self {
789 val as u8
790 }
791}
792
793pub type AlarmMask = u8;
797
798pub mod alarmmask {
800 pub const LOCK_JAMMED: u8 = 0x01;
802 pub const LOCK_FACTORY_RESET: u8 = 0x02;
804 pub const LOCK_RADIO_POWER_CYCLED: u8 = 0x08;
806 pub const WRONG_CODE_ENTRY_LIMIT: u8 = 0x10;
808 pub const FRONT_ESCUTCHEON_REMOVED: u8 = 0x20;
810 pub const DOOR_FORCED_OPEN: u8 = 0x40;
812}
813
814pub type ConfigurationRegister = u8;
816
817pub mod configurationregister {
819 pub const LOCAL_PROGRAMMING: u8 = 0x01;
821 pub const KEYPAD_INTERFACE: u8 = 0x02;
823 pub const REMOTE_INTERFACE: u8 = 0x04;
825 pub const SOUND_VOLUME: u8 = 0x20;
827 pub const AUTO_RELOCK_TIME: u8 = 0x40;
829 pub const LEDSETTINGS: u8 = 0x80;
831}
832
833pub type CredentialRules = u8;
835
836pub mod credentialrules {
838 pub const SINGLE: u8 = 0x01;
840 pub const DUAL: u8 = 0x02;
842 pub const TRI: u8 = 0x04;
844}
845
846pub type DaysMask = u8;
848
849pub mod daysmask {
851 pub const SUNDAY: u8 = 0x01;
853 pub const MONDAY: u8 = 0x02;
855 pub const TUESDAY: u8 = 0x04;
857 pub const WEDNESDAY: u8 = 0x08;
859 pub const THURSDAY: u8 = 0x10;
861 pub const FRIDAY: u8 = 0x20;
863 pub const SATURDAY: u8 = 0x40;
865}
866
867pub type LocalProgrammingFeatures = u8;
869
870pub mod localprogrammingfeatures {
872 pub const ADD_USERS_CREDENTIALS_SCHEDULES: u8 = 0x01;
874 pub const MODIFY_USERS_CREDENTIALS_SCHEDULES: u8 = 0x02;
876 pub const CLEAR_USERS_CREDENTIALS_SCHEDULES: u8 = 0x04;
878 pub const ADJUST_SETTINGS: u8 = 0x08;
880}
881
882pub type OperatingModes = u8;
884
885pub mod operatingmodes {
887 pub const NORMAL: u8 = 0x01;
889 pub const VACATION: u8 = 0x02;
891 pub const PRIVACY: u8 = 0x04;
893 pub const NO_REMOTE_LOCK_UNLOCK: u8 = 0x08;
895 pub const PASSAGE: u8 = 0x10;
897}
898
899#[derive(Debug, serde::Serialize)]
902pub struct Credential {
903 pub credential_type: Option<CredentialType>,
904 pub credential_index: Option<u16>,
905}
906
907pub fn encode_lock_door(pin_code: Vec<u8>) -> anyhow::Result<Vec<u8>> {
911 let tlv = tlv::TlvItemEnc {
912 tag: 0,
913 value: tlv::TlvItemValueEnc::StructInvisible(vec![
914 (0, tlv::TlvItemValueEnc::OctetString(pin_code)).into(),
915 ]),
916 };
917 Ok(tlv.encode()?)
918}
919
920pub fn encode_unlock_door(pin_code: Vec<u8>) -> anyhow::Result<Vec<u8>> {
922 let tlv = tlv::TlvItemEnc {
923 tag: 0,
924 value: tlv::TlvItemValueEnc::StructInvisible(vec![
925 (0, tlv::TlvItemValueEnc::OctetString(pin_code)).into(),
926 ]),
927 };
928 Ok(tlv.encode()?)
929}
930
931pub fn encode_unlock_with_timeout(timeout: u16, pin_code: Vec<u8>) -> anyhow::Result<Vec<u8>> {
933 let tlv = tlv::TlvItemEnc {
934 tag: 0,
935 value: tlv::TlvItemValueEnc::StructInvisible(vec![
936 (0, tlv::TlvItemValueEnc::UInt16(timeout)).into(),
937 (1, tlv::TlvItemValueEnc::OctetString(pin_code)).into(),
938 ]),
939 };
940 Ok(tlv.encode()?)
941}
942
943pub fn encode_set_week_day_schedule(week_day_index: u8, user_index: u16, days_mask: DaysMask, start_hour: u8, start_minute: u8, end_hour: u8, end_minute: u8) -> anyhow::Result<Vec<u8>> {
945 let tlv = tlv::TlvItemEnc {
946 tag: 0,
947 value: tlv::TlvItemValueEnc::StructInvisible(vec![
948 (0, tlv::TlvItemValueEnc::UInt8(week_day_index)).into(),
949 (1, tlv::TlvItemValueEnc::UInt16(user_index)).into(),
950 (2, tlv::TlvItemValueEnc::UInt8(days_mask)).into(),
951 (3, tlv::TlvItemValueEnc::UInt8(start_hour)).into(),
952 (4, tlv::TlvItemValueEnc::UInt8(start_minute)).into(),
953 (5, tlv::TlvItemValueEnc::UInt8(end_hour)).into(),
954 (6, tlv::TlvItemValueEnc::UInt8(end_minute)).into(),
955 ]),
956 };
957 Ok(tlv.encode()?)
958}
959
960pub fn encode_get_week_day_schedule(week_day_index: u8, user_index: u16) -> anyhow::Result<Vec<u8>> {
962 let tlv = tlv::TlvItemEnc {
963 tag: 0,
964 value: tlv::TlvItemValueEnc::StructInvisible(vec![
965 (0, tlv::TlvItemValueEnc::UInt8(week_day_index)).into(),
966 (1, tlv::TlvItemValueEnc::UInt16(user_index)).into(),
967 ]),
968 };
969 Ok(tlv.encode()?)
970}
971
972pub fn encode_clear_week_day_schedule(week_day_index: u8, user_index: u16) -> anyhow::Result<Vec<u8>> {
974 let tlv = tlv::TlvItemEnc {
975 tag: 0,
976 value: tlv::TlvItemValueEnc::StructInvisible(vec![
977 (0, tlv::TlvItemValueEnc::UInt8(week_day_index)).into(),
978 (1, tlv::TlvItemValueEnc::UInt16(user_index)).into(),
979 ]),
980 };
981 Ok(tlv.encode()?)
982}
983
984pub 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>> {
986 let tlv = tlv::TlvItemEnc {
987 tag: 0,
988 value: tlv::TlvItemValueEnc::StructInvisible(vec![
989 (0, tlv::TlvItemValueEnc::UInt8(year_day_index)).into(),
990 (1, tlv::TlvItemValueEnc::UInt16(user_index)).into(),
991 (2, tlv::TlvItemValueEnc::UInt64(local_start_time)).into(),
992 (3, tlv::TlvItemValueEnc::UInt64(local_end_time)).into(),
993 ]),
994 };
995 Ok(tlv.encode()?)
996}
997
998pub fn encode_get_year_day_schedule(year_day_index: u8, user_index: u16) -> anyhow::Result<Vec<u8>> {
1000 let tlv = tlv::TlvItemEnc {
1001 tag: 0,
1002 value: tlv::TlvItemValueEnc::StructInvisible(vec![
1003 (0, tlv::TlvItemValueEnc::UInt8(year_day_index)).into(),
1004 (1, tlv::TlvItemValueEnc::UInt16(user_index)).into(),
1005 ]),
1006 };
1007 Ok(tlv.encode()?)
1008}
1009
1010pub fn encode_clear_year_day_schedule(year_day_index: u8, user_index: u16) -> anyhow::Result<Vec<u8>> {
1012 let tlv = tlv::TlvItemEnc {
1013 tag: 0,
1014 value: tlv::TlvItemValueEnc::StructInvisible(vec![
1015 (0, tlv::TlvItemValueEnc::UInt8(year_day_index)).into(),
1016 (1, tlv::TlvItemValueEnc::UInt16(user_index)).into(),
1017 ]),
1018 };
1019 Ok(tlv.encode()?)
1020}
1021
1022pub fn encode_set_holiday_schedule(holiday_index: u8, local_start_time: u64, local_end_time: u64, operating_mode: OperatingMode) -> anyhow::Result<Vec<u8>> {
1024 let tlv = tlv::TlvItemEnc {
1025 tag: 0,
1026 value: tlv::TlvItemValueEnc::StructInvisible(vec![
1027 (0, tlv::TlvItemValueEnc::UInt8(holiday_index)).into(),
1028 (1, tlv::TlvItemValueEnc::UInt64(local_start_time)).into(),
1029 (2, tlv::TlvItemValueEnc::UInt64(local_end_time)).into(),
1030 (3, tlv::TlvItemValueEnc::UInt8(operating_mode.to_u8())).into(),
1031 ]),
1032 };
1033 Ok(tlv.encode()?)
1034}
1035
1036pub fn encode_get_holiday_schedule(holiday_index: u8) -> anyhow::Result<Vec<u8>> {
1038 let tlv = tlv::TlvItemEnc {
1039 tag: 0,
1040 value: tlv::TlvItemValueEnc::StructInvisible(vec![
1041 (0, tlv::TlvItemValueEnc::UInt8(holiday_index)).into(),
1042 ]),
1043 };
1044 Ok(tlv.encode()?)
1045}
1046
1047pub fn encode_clear_holiday_schedule(holiday_index: u8) -> anyhow::Result<Vec<u8>> {
1049 let tlv = tlv::TlvItemEnc {
1050 tag: 0,
1051 value: tlv::TlvItemValueEnc::StructInvisible(vec![
1052 (0, tlv::TlvItemValueEnc::UInt8(holiday_index)).into(),
1053 ]),
1054 };
1055 Ok(tlv.encode()?)
1056}
1057
1058pub fn encode_set_user(operation_type: DataOperationType, user_index: u16, user_name: Option<String>, user_unique_id: Option<u32>, user_status: Option<UserStatus>, user_type: Option<UserType>, credential_rule: Option<CredentialRule>) -> anyhow::Result<Vec<u8>> {
1060 let tlv = tlv::TlvItemEnc {
1061 tag: 0,
1062 value: tlv::TlvItemValueEnc::StructInvisible(vec![
1063 (0, tlv::TlvItemValueEnc::UInt8(operation_type.to_u8())).into(),
1064 (1, tlv::TlvItemValueEnc::UInt16(user_index)).into(),
1065 (2, tlv::TlvItemValueEnc::String(user_name.unwrap_or("".to_string()))).into(),
1066 (3, tlv::TlvItemValueEnc::UInt32(user_unique_id.unwrap_or(0))).into(),
1067 (4, tlv::TlvItemValueEnc::UInt8(user_status.map(|e| e.to_u8()).unwrap_or(0))).into(),
1068 (5, tlv::TlvItemValueEnc::UInt8(user_type.map(|e| e.to_u8()).unwrap_or(0))).into(),
1069 (6, tlv::TlvItemValueEnc::UInt8(credential_rule.map(|e| e.to_u8()).unwrap_or(0))).into(),
1070 ]),
1071 };
1072 Ok(tlv.encode()?)
1073}
1074
1075pub fn encode_get_user(user_index: u16) -> anyhow::Result<Vec<u8>> {
1077 let tlv = tlv::TlvItemEnc {
1078 tag: 0,
1079 value: tlv::TlvItemValueEnc::StructInvisible(vec![
1080 (0, tlv::TlvItemValueEnc::UInt16(user_index)).into(),
1081 ]),
1082 };
1083 Ok(tlv.encode()?)
1084}
1085
1086pub fn encode_clear_user(user_index: u16) -> anyhow::Result<Vec<u8>> {
1088 let tlv = tlv::TlvItemEnc {
1089 tag: 0,
1090 value: tlv::TlvItemValueEnc::StructInvisible(vec![
1091 (0, tlv::TlvItemValueEnc::UInt16(user_index)).into(),
1092 ]),
1093 };
1094 Ok(tlv.encode()?)
1095}
1096
1097pub fn encode_set_credential(operation_type: DataOperationType, credential: Credential, credential_data: Vec<u8>, user_index: Option<u16>, user_status: Option<UserStatus>, user_type: Option<UserType>) -> anyhow::Result<Vec<u8>> {
1099 let mut credential_fields = Vec::new();
1101 if let Some(x) = credential.credential_type { credential_fields.push((0, tlv::TlvItemValueEnc::UInt8(x.to_u8())).into()); }
1102 if let Some(x) = credential.credential_index { credential_fields.push((1, tlv::TlvItemValueEnc::UInt16(x)).into()); }
1103 let tlv = tlv::TlvItemEnc {
1104 tag: 0,
1105 value: tlv::TlvItemValueEnc::StructInvisible(vec![
1106 (0, tlv::TlvItemValueEnc::UInt8(operation_type.to_u8())).into(),
1107 (1, tlv::TlvItemValueEnc::StructInvisible(credential_fields)).into(),
1108 (2, tlv::TlvItemValueEnc::OctetString(credential_data)).into(),
1109 (3, tlv::TlvItemValueEnc::UInt16(user_index.unwrap_or(0))).into(),
1110 (4, tlv::TlvItemValueEnc::UInt8(user_status.map(|e| e.to_u8()).unwrap_or(0))).into(),
1111 (5, tlv::TlvItemValueEnc::UInt8(user_type.map(|e| e.to_u8()).unwrap_or(0))).into(),
1112 ]),
1113 };
1114 Ok(tlv.encode()?)
1115}
1116
1117pub fn encode_get_credential_status(credential: Credential) -> anyhow::Result<Vec<u8>> {
1119 let mut credential_fields = Vec::new();
1121 if let Some(x) = credential.credential_type { credential_fields.push((0, tlv::TlvItemValueEnc::UInt8(x.to_u8())).into()); }
1122 if let Some(x) = credential.credential_index { credential_fields.push((1, tlv::TlvItemValueEnc::UInt16(x)).into()); }
1123 let tlv = tlv::TlvItemEnc {
1124 tag: 0,
1125 value: tlv::TlvItemValueEnc::StructInvisible(vec![
1126 (0, tlv::TlvItemValueEnc::StructInvisible(credential_fields)).into(),
1127 ]),
1128 };
1129 Ok(tlv.encode()?)
1130}
1131
1132pub fn encode_clear_credential(credential: Option<Credential>) -> anyhow::Result<Vec<u8>> {
1134 let credential_enc = if let Some(s) = credential {
1136 let mut fields = Vec::new();
1137 if let Some(x) = s.credential_type { fields.push((0, tlv::TlvItemValueEnc::UInt8(x.to_u8())).into()); }
1138 if let Some(x) = s.credential_index { fields.push((1, tlv::TlvItemValueEnc::UInt16(x)).into()); }
1139 tlv::TlvItemValueEnc::StructInvisible(fields)
1140 } else {
1141 tlv::TlvItemValueEnc::StructInvisible(Vec::new())
1142 };
1143 let tlv = tlv::TlvItemEnc {
1144 tag: 0,
1145 value: tlv::TlvItemValueEnc::StructInvisible(vec![
1146 (0, credential_enc).into(),
1147 ]),
1148 };
1149 Ok(tlv.encode()?)
1150}
1151
1152pub fn encode_unbolt_door(pin_code: Vec<u8>) -> anyhow::Result<Vec<u8>> {
1154 let tlv = tlv::TlvItemEnc {
1155 tag: 0,
1156 value: tlv::TlvItemValueEnc::StructInvisible(vec![
1157 (0, tlv::TlvItemValueEnc::OctetString(pin_code)).into(),
1158 ]),
1159 };
1160 Ok(tlv.encode()?)
1161}
1162
1163pub 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>> {
1165 let tlv = tlv::TlvItemEnc {
1166 tag: 0,
1167 value: tlv::TlvItemValueEnc::StructInvisible(vec![
1168 (0, tlv::TlvItemValueEnc::OctetString(signing_key)).into(),
1169 (1, tlv::TlvItemValueEnc::OctetString(verification_key)).into(),
1170 (2, tlv::TlvItemValueEnc::OctetString(group_identifier)).into(),
1171 (3, tlv::TlvItemValueEnc::OctetString(group_resolving_key)).into(),
1172 ]),
1173 };
1174 Ok(tlv.encode()?)
1175}
1176
1177pub fn decode_lock_state(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<LockState>> {
1181 if let tlv::TlvItemValue::Int(v) = inp {
1182 Ok(LockState::from_u8(*v as u8))
1183 } else {
1184 Ok(None)
1185 }
1186}
1187
1188pub fn decode_lock_type(inp: &tlv::TlvItemValue) -> anyhow::Result<LockType> {
1190 if let tlv::TlvItemValue::Int(v) = inp {
1191 LockType::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
1192 } else {
1193 Err(anyhow::anyhow!("Expected Integer"))
1194 }
1195}
1196
1197pub fn decode_actuator_enabled(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
1199 if let tlv::TlvItemValue::Bool(v) = inp {
1200 Ok(*v)
1201 } else {
1202 Err(anyhow::anyhow!("Expected Bool"))
1203 }
1204}
1205
1206pub fn decode_door_state(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<DoorState>> {
1208 if let tlv::TlvItemValue::Int(v) = inp {
1209 Ok(DoorState::from_u8(*v as u8))
1210 } else {
1211 Ok(None)
1212 }
1213}
1214
1215pub fn decode_door_open_events(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
1217 if let tlv::TlvItemValue::Int(v) = inp {
1218 Ok(*v as u32)
1219 } else {
1220 Err(anyhow::anyhow!("Expected UInt32"))
1221 }
1222}
1223
1224pub fn decode_door_closed_events(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
1226 if let tlv::TlvItemValue::Int(v) = inp {
1227 Ok(*v as u32)
1228 } else {
1229 Err(anyhow::anyhow!("Expected UInt32"))
1230 }
1231}
1232
1233pub fn decode_open_period(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
1235 if let tlv::TlvItemValue::Int(v) = inp {
1236 Ok(*v as u16)
1237 } else {
1238 Err(anyhow::anyhow!("Expected UInt16"))
1239 }
1240}
1241
1242pub fn decode_number_of_total_users_supported(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
1244 if let tlv::TlvItemValue::Int(v) = inp {
1245 Ok(*v as u16)
1246 } else {
1247 Err(anyhow::anyhow!("Expected UInt16"))
1248 }
1249}
1250
1251pub fn decode_number_of_pin_users_supported(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
1253 if let tlv::TlvItemValue::Int(v) = inp {
1254 Ok(*v as u16)
1255 } else {
1256 Err(anyhow::anyhow!("Expected UInt16"))
1257 }
1258}
1259
1260pub fn decode_number_of_rfid_users_supported(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
1262 if let tlv::TlvItemValue::Int(v) = inp {
1263 Ok(*v as u16)
1264 } else {
1265 Err(anyhow::anyhow!("Expected UInt16"))
1266 }
1267}
1268
1269pub fn decode_number_of_week_day_schedules_supported_per_user(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
1271 if let tlv::TlvItemValue::Int(v) = inp {
1272 Ok(*v as u8)
1273 } else {
1274 Err(anyhow::anyhow!("Expected UInt8"))
1275 }
1276}
1277
1278pub fn decode_number_of_year_day_schedules_supported_per_user(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
1280 if let tlv::TlvItemValue::Int(v) = inp {
1281 Ok(*v as u8)
1282 } else {
1283 Err(anyhow::anyhow!("Expected UInt8"))
1284 }
1285}
1286
1287pub fn decode_number_of_holiday_schedules_supported(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
1289 if let tlv::TlvItemValue::Int(v) = inp {
1290 Ok(*v as u8)
1291 } else {
1292 Err(anyhow::anyhow!("Expected UInt8"))
1293 }
1294}
1295
1296pub fn decode_max_pin_code_length(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
1298 if let tlv::TlvItemValue::Int(v) = inp {
1299 Ok(*v as u8)
1300 } else {
1301 Err(anyhow::anyhow!("Expected UInt8"))
1302 }
1303}
1304
1305pub fn decode_min_pin_code_length(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
1307 if let tlv::TlvItemValue::Int(v) = inp {
1308 Ok(*v as u8)
1309 } else {
1310 Err(anyhow::anyhow!("Expected UInt8"))
1311 }
1312}
1313
1314pub fn decode_max_rfid_code_length(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
1316 if let tlv::TlvItemValue::Int(v) = inp {
1317 Ok(*v as u8)
1318 } else {
1319 Err(anyhow::anyhow!("Expected UInt8"))
1320 }
1321}
1322
1323pub fn decode_min_rfid_code_length(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
1325 if let tlv::TlvItemValue::Int(v) = inp {
1326 Ok(*v as u8)
1327 } else {
1328 Err(anyhow::anyhow!("Expected UInt8"))
1329 }
1330}
1331
1332pub fn decode_credential_rules_support(inp: &tlv::TlvItemValue) -> anyhow::Result<CredentialRules> {
1334 if let tlv::TlvItemValue::Int(v) = inp {
1335 Ok(*v as u8)
1336 } else {
1337 Err(anyhow::anyhow!("Expected Integer"))
1338 }
1339}
1340
1341pub fn decode_number_of_credentials_supported_per_user(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
1343 if let tlv::TlvItemValue::Int(v) = inp {
1344 Ok(*v as u8)
1345 } else {
1346 Err(anyhow::anyhow!("Expected UInt8"))
1347 }
1348}
1349
1350pub fn decode_language(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
1352 if let tlv::TlvItemValue::String(v) = inp {
1353 Ok(v.clone())
1354 } else {
1355 Err(anyhow::anyhow!("Expected String"))
1356 }
1357}
1358
1359pub fn decode_led_settings(inp: &tlv::TlvItemValue) -> anyhow::Result<LEDSetting> {
1361 if let tlv::TlvItemValue::Int(v) = inp {
1362 LEDSetting::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
1363 } else {
1364 Err(anyhow::anyhow!("Expected Integer"))
1365 }
1366}
1367
1368pub fn decode_auto_relock_time(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
1370 if let tlv::TlvItemValue::Int(v) = inp {
1371 Ok(*v as u32)
1372 } else {
1373 Err(anyhow::anyhow!("Expected UInt32"))
1374 }
1375}
1376
1377pub fn decode_sound_volume(inp: &tlv::TlvItemValue) -> anyhow::Result<SoundVolume> {
1379 if let tlv::TlvItemValue::Int(v) = inp {
1380 SoundVolume::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
1381 } else {
1382 Err(anyhow::anyhow!("Expected Integer"))
1383 }
1384}
1385
1386pub fn decode_operating_mode(inp: &tlv::TlvItemValue) -> anyhow::Result<OperatingMode> {
1388 if let tlv::TlvItemValue::Int(v) = inp {
1389 OperatingMode::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
1390 } else {
1391 Err(anyhow::anyhow!("Expected Integer"))
1392 }
1393}
1394
1395pub fn decode_supported_operating_modes(inp: &tlv::TlvItemValue) -> anyhow::Result<OperatingModes> {
1397 if let tlv::TlvItemValue::Int(v) = inp {
1398 Ok(*v as u8)
1399 } else {
1400 Err(anyhow::anyhow!("Expected Integer"))
1401 }
1402}
1403
1404pub fn decode_default_configuration_register(inp: &tlv::TlvItemValue) -> anyhow::Result<ConfigurationRegister> {
1406 if let tlv::TlvItemValue::Int(v) = inp {
1407 Ok(*v as u8)
1408 } else {
1409 Err(anyhow::anyhow!("Expected Integer"))
1410 }
1411}
1412
1413pub fn decode_enable_local_programming(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
1415 if let tlv::TlvItemValue::Bool(v) = inp {
1416 Ok(*v)
1417 } else {
1418 Err(anyhow::anyhow!("Expected Bool"))
1419 }
1420}
1421
1422pub fn decode_enable_one_touch_locking(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
1424 if let tlv::TlvItemValue::Bool(v) = inp {
1425 Ok(*v)
1426 } else {
1427 Err(anyhow::anyhow!("Expected Bool"))
1428 }
1429}
1430
1431pub fn decode_enable_inside_status_led(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
1433 if let tlv::TlvItemValue::Bool(v) = inp {
1434 Ok(*v)
1435 } else {
1436 Err(anyhow::anyhow!("Expected Bool"))
1437 }
1438}
1439
1440pub fn decode_enable_privacy_mode_button(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
1442 if let tlv::TlvItemValue::Bool(v) = inp {
1443 Ok(*v)
1444 } else {
1445 Err(anyhow::anyhow!("Expected Bool"))
1446 }
1447}
1448
1449pub fn decode_local_programming_features(inp: &tlv::TlvItemValue) -> anyhow::Result<LocalProgrammingFeatures> {
1451 if let tlv::TlvItemValue::Int(v) = inp {
1452 Ok(*v as u8)
1453 } else {
1454 Err(anyhow::anyhow!("Expected Integer"))
1455 }
1456}
1457
1458pub fn decode_wrong_code_entry_limit(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
1460 if let tlv::TlvItemValue::Int(v) = inp {
1461 Ok(*v as u8)
1462 } else {
1463 Err(anyhow::anyhow!("Expected UInt8"))
1464 }
1465}
1466
1467pub fn decode_user_code_temporary_disable_time(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
1469 if let tlv::TlvItemValue::Int(v) = inp {
1470 Ok(*v as u8)
1471 } else {
1472 Err(anyhow::anyhow!("Expected UInt8"))
1473 }
1474}
1475
1476pub fn decode_send_pin_over_the_air(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
1478 if let tlv::TlvItemValue::Bool(v) = inp {
1479 Ok(*v)
1480 } else {
1481 Err(anyhow::anyhow!("Expected Bool"))
1482 }
1483}
1484
1485pub fn decode_require_pinfor_remote_operation(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
1487 if let tlv::TlvItemValue::Bool(v) = inp {
1488 Ok(*v)
1489 } else {
1490 Err(anyhow::anyhow!("Expected Bool"))
1491 }
1492}
1493
1494pub fn decode_security_level(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
1496 if let tlv::TlvItemValue::Int(v) = inp {
1497 Ok(*v as u8)
1498 } else {
1499 Err(anyhow::anyhow!("Expected UInt8"))
1500 }
1501}
1502
1503pub fn decode_expiring_user_timeout(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
1505 if let tlv::TlvItemValue::Int(v) = inp {
1506 Ok(*v as u16)
1507 } else {
1508 Err(anyhow::anyhow!("Expected UInt16"))
1509 }
1510}
1511
1512pub fn decode_aliro_reader_verification_key(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<Vec<u8>>> {
1514 if let tlv::TlvItemValue::OctetString(v) = inp {
1515 Ok(Some(v.clone()))
1516 } else {
1517 Ok(None)
1518 }
1519}
1520
1521pub fn decode_aliro_reader_group_identifier(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<Vec<u8>>> {
1523 if let tlv::TlvItemValue::OctetString(v) = inp {
1524 Ok(Some(v.clone()))
1525 } else {
1526 Ok(None)
1527 }
1528}
1529
1530pub fn decode_aliro_reader_group_sub_identifier(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<u8>> {
1532 if let tlv::TlvItemValue::OctetString(v) = inp {
1533 Ok(v.clone())
1534 } else {
1535 Err(anyhow::anyhow!("Expected OctetString"))
1536 }
1537}
1538
1539pub fn decode_aliro_expedited_transaction_supported_protocol_versions(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<Vec<u8>>> {
1541 let mut res = Vec::new();
1542 if let tlv::TlvItemValue::List(v) = inp {
1543 for item in v {
1544 if let tlv::TlvItemValue::OctetString(o) = &item.value {
1545 res.push(o.clone());
1546 }
1547 }
1548 }
1549 Ok(res)
1550}
1551
1552pub fn decode_aliro_group_resolving_key(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<Vec<u8>>> {
1554 if let tlv::TlvItemValue::OctetString(v) = inp {
1555 Ok(Some(v.clone()))
1556 } else {
1557 Ok(None)
1558 }
1559}
1560
1561pub fn decode_aliro_supported_bleuwb_protocol_versions(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<Vec<u8>>> {
1563 let mut res = Vec::new();
1564 if let tlv::TlvItemValue::List(v) = inp {
1565 for item in v {
1566 if let tlv::TlvItemValue::OctetString(o) = &item.value {
1567 res.push(o.clone());
1568 }
1569 }
1570 }
1571 Ok(res)
1572}
1573
1574pub fn decode_aliro_ble_advertising_version(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
1576 if let tlv::TlvItemValue::Int(v) = inp {
1577 Ok(*v as u8)
1578 } else {
1579 Err(anyhow::anyhow!("Expected UInt8"))
1580 }
1581}
1582
1583pub fn decode_number_of_aliro_credential_issuer_keys_supported(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
1585 if let tlv::TlvItemValue::Int(v) = inp {
1586 Ok(*v as u16)
1587 } else {
1588 Err(anyhow::anyhow!("Expected UInt16"))
1589 }
1590}
1591
1592pub fn decode_number_of_aliro_endpoint_keys_supported(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
1594 if let tlv::TlvItemValue::Int(v) = inp {
1595 Ok(*v as u16)
1596 } else {
1597 Err(anyhow::anyhow!("Expected UInt16"))
1598 }
1599}
1600
1601
1602pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
1614 if cluster_id != 0x0101 {
1616 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0101, got {}\"}}", cluster_id);
1617 }
1618
1619 match attribute_id {
1620 0x0000 => {
1621 match decode_lock_state(tlv_value) {
1622 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1623 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1624 }
1625 }
1626 0x0001 => {
1627 match decode_lock_type(tlv_value) {
1628 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1629 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1630 }
1631 }
1632 0x0002 => {
1633 match decode_actuator_enabled(tlv_value) {
1634 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1635 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1636 }
1637 }
1638 0x0003 => {
1639 match decode_door_state(tlv_value) {
1640 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1641 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1642 }
1643 }
1644 0x0004 => {
1645 match decode_door_open_events(tlv_value) {
1646 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1647 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1648 }
1649 }
1650 0x0005 => {
1651 match decode_door_closed_events(tlv_value) {
1652 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1653 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1654 }
1655 }
1656 0x0006 => {
1657 match decode_open_period(tlv_value) {
1658 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1659 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1660 }
1661 }
1662 0x0011 => {
1663 match decode_number_of_total_users_supported(tlv_value) {
1664 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1665 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1666 }
1667 }
1668 0x0012 => {
1669 match decode_number_of_pin_users_supported(tlv_value) {
1670 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1671 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1672 }
1673 }
1674 0x0013 => {
1675 match decode_number_of_rfid_users_supported(tlv_value) {
1676 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1677 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1678 }
1679 }
1680 0x0014 => {
1681 match decode_number_of_week_day_schedules_supported_per_user(tlv_value) {
1682 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1683 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1684 }
1685 }
1686 0x0015 => {
1687 match decode_number_of_year_day_schedules_supported_per_user(tlv_value) {
1688 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1689 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1690 }
1691 }
1692 0x0016 => {
1693 match decode_number_of_holiday_schedules_supported(tlv_value) {
1694 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1695 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1696 }
1697 }
1698 0x0017 => {
1699 match decode_max_pin_code_length(tlv_value) {
1700 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1701 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1702 }
1703 }
1704 0x0018 => {
1705 match decode_min_pin_code_length(tlv_value) {
1706 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1707 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1708 }
1709 }
1710 0x0019 => {
1711 match decode_max_rfid_code_length(tlv_value) {
1712 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1713 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1714 }
1715 }
1716 0x001A => {
1717 match decode_min_rfid_code_length(tlv_value) {
1718 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1719 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1720 }
1721 }
1722 0x001B => {
1723 match decode_credential_rules_support(tlv_value) {
1724 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1725 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1726 }
1727 }
1728 0x001C => {
1729 match decode_number_of_credentials_supported_per_user(tlv_value) {
1730 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1731 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1732 }
1733 }
1734 0x0021 => {
1735 match decode_language(tlv_value) {
1736 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1737 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1738 }
1739 }
1740 0x0022 => {
1741 match decode_led_settings(tlv_value) {
1742 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1743 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1744 }
1745 }
1746 0x0023 => {
1747 match decode_auto_relock_time(tlv_value) {
1748 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1749 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1750 }
1751 }
1752 0x0024 => {
1753 match decode_sound_volume(tlv_value) {
1754 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1755 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1756 }
1757 }
1758 0x0025 => {
1759 match decode_operating_mode(tlv_value) {
1760 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1761 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1762 }
1763 }
1764 0x0026 => {
1765 match decode_supported_operating_modes(tlv_value) {
1766 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1767 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1768 }
1769 }
1770 0x0027 => {
1771 match decode_default_configuration_register(tlv_value) {
1772 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1773 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1774 }
1775 }
1776 0x0028 => {
1777 match decode_enable_local_programming(tlv_value) {
1778 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1779 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1780 }
1781 }
1782 0x0029 => {
1783 match decode_enable_one_touch_locking(tlv_value) {
1784 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1785 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1786 }
1787 }
1788 0x002A => {
1789 match decode_enable_inside_status_led(tlv_value) {
1790 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1791 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1792 }
1793 }
1794 0x002B => {
1795 match decode_enable_privacy_mode_button(tlv_value) {
1796 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1797 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1798 }
1799 }
1800 0x002C => {
1801 match decode_local_programming_features(tlv_value) {
1802 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1803 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1804 }
1805 }
1806 0x0030 => {
1807 match decode_wrong_code_entry_limit(tlv_value) {
1808 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1809 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1810 }
1811 }
1812 0x0031 => {
1813 match decode_user_code_temporary_disable_time(tlv_value) {
1814 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1815 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1816 }
1817 }
1818 0x0032 => {
1819 match decode_send_pin_over_the_air(tlv_value) {
1820 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1821 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1822 }
1823 }
1824 0x0033 => {
1825 match decode_require_pinfor_remote_operation(tlv_value) {
1826 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1827 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1828 }
1829 }
1830 0x0034 => {
1831 match decode_security_level(tlv_value) {
1832 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1833 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1834 }
1835 }
1836 0x0035 => {
1837 match decode_expiring_user_timeout(tlv_value) {
1838 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1839 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1840 }
1841 }
1842 0x0080 => {
1843 match decode_aliro_reader_verification_key(tlv_value) {
1844 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1845 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1846 }
1847 }
1848 0x0081 => {
1849 match decode_aliro_reader_group_identifier(tlv_value) {
1850 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1851 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1852 }
1853 }
1854 0x0082 => {
1855 match decode_aliro_reader_group_sub_identifier(tlv_value) {
1856 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1857 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1858 }
1859 }
1860 0x0083 => {
1861 match decode_aliro_expedited_transaction_supported_protocol_versions(tlv_value) {
1862 Ok(value) => {
1863 let hex_array: Vec<String> = value.iter()
1865 .map(|bytes| bytes.iter()
1866 .map(|byte| format!("{:02x}", byte))
1867 .collect::<String>())
1868 .collect();
1869 serde_json::to_string(&hex_array).unwrap_or_else(|_| "null".to_string())
1870 },
1871 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1872 }
1873 }
1874 0x0084 => {
1875 match decode_aliro_group_resolving_key(tlv_value) {
1876 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1877 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1878 }
1879 }
1880 0x0085 => {
1881 match decode_aliro_supported_bleuwb_protocol_versions(tlv_value) {
1882 Ok(value) => {
1883 let hex_array: Vec<String> = value.iter()
1885 .map(|bytes| bytes.iter()
1886 .map(|byte| format!("{:02x}", byte))
1887 .collect::<String>())
1888 .collect();
1889 serde_json::to_string(&hex_array).unwrap_or_else(|_| "null".to_string())
1890 },
1891 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1892 }
1893 }
1894 0x0086 => {
1895 match decode_aliro_ble_advertising_version(tlv_value) {
1896 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1897 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1898 }
1899 }
1900 0x0087 => {
1901 match decode_number_of_aliro_credential_issuer_keys_supported(tlv_value) {
1902 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1903 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1904 }
1905 }
1906 0x0088 => {
1907 match decode_number_of_aliro_endpoint_keys_supported(tlv_value) {
1908 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1909 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1910 }
1911 }
1912 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
1913 }
1914}
1915
1916pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
1921 vec![
1922 (0x0000, "LockState"),
1923 (0x0001, "LockType"),
1924 (0x0002, "ActuatorEnabled"),
1925 (0x0003, "DoorState"),
1926 (0x0004, "DoorOpenEvents"),
1927 (0x0005, "DoorClosedEvents"),
1928 (0x0006, "OpenPeriod"),
1929 (0x0011, "NumberOfTotalUsersSupported"),
1930 (0x0012, "NumberOfPINUsersSupported"),
1931 (0x0013, "NumberOfRFIDUsersSupported"),
1932 (0x0014, "NumberOfWeekDaySchedulesSupportedPerUser"),
1933 (0x0015, "NumberOfYearDaySchedulesSupportedPerUser"),
1934 (0x0016, "NumberOfHolidaySchedulesSupported"),
1935 (0x0017, "MaxPINCodeLength"),
1936 (0x0018, "MinPINCodeLength"),
1937 (0x0019, "MaxRFIDCodeLength"),
1938 (0x001A, "MinRFIDCodeLength"),
1939 (0x001B, "CredentialRulesSupport"),
1940 (0x001C, "NumberOfCredentialsSupportedPerUser"),
1941 (0x0021, "Language"),
1942 (0x0022, "LEDSettings"),
1943 (0x0023, "AutoRelockTime"),
1944 (0x0024, "SoundVolume"),
1945 (0x0025, "OperatingMode"),
1946 (0x0026, "SupportedOperatingModes"),
1947 (0x0027, "DefaultConfigurationRegister"),
1948 (0x0028, "EnableLocalProgramming"),
1949 (0x0029, "EnableOneTouchLocking"),
1950 (0x002A, "EnableInsideStatusLED"),
1951 (0x002B, "EnablePrivacyModeButton"),
1952 (0x002C, "LocalProgrammingFeatures"),
1953 (0x0030, "WrongCodeEntryLimit"),
1954 (0x0031, "UserCodeTemporaryDisableTime"),
1955 (0x0032, "SendPINOverTheAir"),
1956 (0x0033, "RequirePINforRemoteOperation"),
1957 (0x0034, "SecurityLevel"),
1958 (0x0035, "ExpiringUserTimeout"),
1959 (0x0080, "AliroReaderVerificationKey"),
1960 (0x0081, "AliroReaderGroupIdentifier"),
1961 (0x0082, "AliroReaderGroupSubIdentifier"),
1962 (0x0083, "AliroExpeditedTransactionSupportedProtocolVersions"),
1963 (0x0084, "AliroGroupResolvingKey"),
1964 (0x0085, "AliroSupportedBLEUWBProtocolVersions"),
1965 (0x0086, "AliroBLEAdvertisingVersion"),
1966 (0x0087, "NumberOfAliroCredentialIssuerKeysSupported"),
1967 (0x0088, "NumberOfAliroEndpointKeysSupported"),
1968 ]
1969}
1970
1971pub fn get_command_list() -> Vec<(u32, &'static str)> {
1974 vec![
1975 (0x00, "LockDoor"),
1976 (0x01, "UnlockDoor"),
1977 (0x02, "Toggle"),
1978 (0x03, "UnlockWithTimeout"),
1979 (0x0B, "SetWeekDaySchedule"),
1980 (0x0C, "GetWeekDaySchedule"),
1981 (0x0D, "ClearWeekDaySchedule"),
1982 (0x0E, "SetYearDaySchedule"),
1983 (0x0F, "GetYearDaySchedule"),
1984 (0x10, "ClearYearDaySchedule"),
1985 (0x11, "SetHolidaySchedule"),
1986 (0x12, "GetHolidaySchedule"),
1987 (0x13, "ClearHolidaySchedule"),
1988 (0x1A, "SetUser"),
1989 (0x1B, "GetUser"),
1990 (0x1D, "ClearUser"),
1991 (0x22, "SetCredential"),
1992 (0x24, "GetCredentialStatus"),
1993 (0x26, "ClearCredential"),
1994 (0x27, "UnboltDoor"),
1995 (0x28, "SetAliroReaderConfig"),
1996 (0x29, "ClearAliroReaderConfig"),
1997 ]
1998}
1999
2000pub fn get_command_name(cmd_id: u32) -> Option<&'static str> {
2001 match cmd_id {
2002 0x00 => Some("LockDoor"),
2003 0x01 => Some("UnlockDoor"),
2004 0x02 => Some("Toggle"),
2005 0x03 => Some("UnlockWithTimeout"),
2006 0x0B => Some("SetWeekDaySchedule"),
2007 0x0C => Some("GetWeekDaySchedule"),
2008 0x0D => Some("ClearWeekDaySchedule"),
2009 0x0E => Some("SetYearDaySchedule"),
2010 0x0F => Some("GetYearDaySchedule"),
2011 0x10 => Some("ClearYearDaySchedule"),
2012 0x11 => Some("SetHolidaySchedule"),
2013 0x12 => Some("GetHolidaySchedule"),
2014 0x13 => Some("ClearHolidaySchedule"),
2015 0x1A => Some("SetUser"),
2016 0x1B => Some("GetUser"),
2017 0x1D => Some("ClearUser"),
2018 0x22 => Some("SetCredential"),
2019 0x24 => Some("GetCredentialStatus"),
2020 0x26 => Some("ClearCredential"),
2021 0x27 => Some("UnboltDoor"),
2022 0x28 => Some("SetAliroReaderConfig"),
2023 0x29 => Some("ClearAliroReaderConfig"),
2024 _ => None,
2025 }
2026}
2027
2028pub fn get_command_schema(cmd_id: u32) -> Option<Vec<crate::clusters::codec::CommandField>> {
2029 match cmd_id {
2030 0x00 => Some(vec![
2031 crate::clusters::codec::CommandField { tag: 0, name: "pin_code", kind: crate::clusters::codec::FieldKind::OctetString, optional: true, nullable: false },
2032 ]),
2033 0x01 => Some(vec![
2034 crate::clusters::codec::CommandField { tag: 0, name: "pin_code", kind: crate::clusters::codec::FieldKind::OctetString, optional: true, nullable: false },
2035 ]),
2036 0x02 => Some(vec![]),
2037 0x03 => Some(vec![
2038 crate::clusters::codec::CommandField { tag: 0, name: "timeout", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
2039 crate::clusters::codec::CommandField { tag: 1, name: "pin_code", kind: crate::clusters::codec::FieldKind::OctetString, optional: true, nullable: false },
2040 ]),
2041 0x0B => Some(vec![
2042 crate::clusters::codec::CommandField { tag: 0, name: "week_day_index", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: false },
2043 crate::clusters::codec::CommandField { tag: 1, name: "user_index", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
2044 crate::clusters::codec::CommandField { tag: 2, name: "days_mask", kind: crate::clusters::codec::FieldKind::Bitmap { name: "DaysMask", bits: &[(1, "SUNDAY"), (2, "MONDAY"), (4, "TUESDAY"), (8, "WEDNESDAY"), (16, "THURSDAY"), (32, "FRIDAY"), (64, "SATURDAY")] }, optional: false, nullable: false },
2045 crate::clusters::codec::CommandField { tag: 3, name: "start_hour", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: false },
2046 crate::clusters::codec::CommandField { tag: 4, name: "start_minute", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: false },
2047 crate::clusters::codec::CommandField { tag: 5, name: "end_hour", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: false },
2048 crate::clusters::codec::CommandField { tag: 6, name: "end_minute", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: false },
2049 ]),
2050 0x0C => Some(vec![
2051 crate::clusters::codec::CommandField { tag: 0, name: "week_day_index", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: false },
2052 crate::clusters::codec::CommandField { tag: 1, name: "user_index", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
2053 ]),
2054 0x0D => Some(vec![
2055 crate::clusters::codec::CommandField { tag: 0, name: "week_day_index", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: false },
2056 crate::clusters::codec::CommandField { tag: 1, name: "user_index", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
2057 ]),
2058 0x0E => Some(vec![
2059 crate::clusters::codec::CommandField { tag: 0, name: "year_day_index", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: false },
2060 crate::clusters::codec::CommandField { tag: 1, name: "user_index", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
2061 crate::clusters::codec::CommandField { tag: 2, name: "local_start_time", kind: crate::clusters::codec::FieldKind::U64, optional: false, nullable: false },
2062 crate::clusters::codec::CommandField { tag: 3, name: "local_end_time", kind: crate::clusters::codec::FieldKind::U64, optional: false, nullable: false },
2063 ]),
2064 0x0F => Some(vec![
2065 crate::clusters::codec::CommandField { tag: 0, name: "year_day_index", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: false },
2066 crate::clusters::codec::CommandField { tag: 1, name: "user_index", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
2067 ]),
2068 0x10 => Some(vec![
2069 crate::clusters::codec::CommandField { tag: 0, name: "year_day_index", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: false },
2070 crate::clusters::codec::CommandField { tag: 1, name: "user_index", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
2071 ]),
2072 0x11 => Some(vec![
2073 crate::clusters::codec::CommandField { tag: 0, name: "holiday_index", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: false },
2074 crate::clusters::codec::CommandField { tag: 1, name: "local_start_time", kind: crate::clusters::codec::FieldKind::U64, optional: false, nullable: false },
2075 crate::clusters::codec::CommandField { tag: 2, name: "local_end_time", kind: crate::clusters::codec::FieldKind::U64, optional: false, nullable: false },
2076 crate::clusters::codec::CommandField { tag: 3, name: "operating_mode", kind: crate::clusters::codec::FieldKind::Enum { name: "OperatingMode", variants: &[(0, "Normal"), (1, "Vacation"), (2, "Privacy"), (3, "Noremotelockunlock"), (4, "Passage")] }, optional: false, nullable: false },
2077 ]),
2078 0x12 => Some(vec![
2079 crate::clusters::codec::CommandField { tag: 0, name: "holiday_index", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: false },
2080 ]),
2081 0x13 => Some(vec![
2082 crate::clusters::codec::CommandField { tag: 0, name: "holiday_index", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: false },
2083 ]),
2084 0x1A => Some(vec![
2085 crate::clusters::codec::CommandField { tag: 0, name: "operation_type", kind: crate::clusters::codec::FieldKind::Enum { name: "DataOperationType", variants: &[(0, "Add"), (1, "Clear"), (2, "Modify")] }, optional: false, nullable: false },
2086 crate::clusters::codec::CommandField { tag: 1, name: "user_index", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
2087 crate::clusters::codec::CommandField { tag: 2, name: "user_name", kind: crate::clusters::codec::FieldKind::String, optional: false, nullable: true },
2088 crate::clusters::codec::CommandField { tag: 3, name: "user_unique_id", kind: crate::clusters::codec::FieldKind::U32, optional: false, nullable: true },
2089 crate::clusters::codec::CommandField { tag: 4, name: "user_status", kind: crate::clusters::codec::FieldKind::Enum { name: "UserStatus", variants: &[(0, "Available"), (1, "Occupiedenabled"), (3, "Occupieddisabled")] }, optional: false, nullable: true },
2090 crate::clusters::codec::CommandField { tag: 5, name: "user_type", kind: crate::clusters::codec::FieldKind::Enum { name: "UserType", variants: &[(0, "Unrestricteduser"), (1, "Yeardayscheduleuser"), (2, "Weekdayscheduleuser"), (3, "Programminguser"), (4, "Nonaccessuser"), (5, "Forceduser"), (6, "Disposableuser"), (7, "Expiringuser"), (8, "Schedulerestricteduser"), (9, "Remoteonlyuser")] }, optional: false, nullable: true },
2091 crate::clusters::codec::CommandField { tag: 6, name: "credential_rule", kind: crate::clusters::codec::FieldKind::Enum { name: "CredentialRule", variants: &[(0, "Single"), (1, "Dual"), (2, "Tri")] }, optional: false, nullable: true },
2092 ]),
2093 0x1B => Some(vec![
2094 crate::clusters::codec::CommandField { tag: 0, name: "user_index", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
2095 ]),
2096 0x1D => Some(vec![
2097 crate::clusters::codec::CommandField { tag: 0, name: "user_index", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
2098 ]),
2099 0x22 => Some(vec![
2100 crate::clusters::codec::CommandField { tag: 0, name: "operation_type", kind: crate::clusters::codec::FieldKind::Enum { name: "DataOperationType", variants: &[(0, "Add"), (1, "Clear"), (2, "Modify")] }, optional: false, nullable: false },
2101 crate::clusters::codec::CommandField { tag: 1, name: "credential", kind: crate::clusters::codec::FieldKind::Struct { name: "CredentialStruct" }, optional: false, nullable: false },
2102 crate::clusters::codec::CommandField { tag: 2, name: "credential_data", kind: crate::clusters::codec::FieldKind::OctetString, optional: false, nullable: false },
2103 crate::clusters::codec::CommandField { tag: 3, name: "user_index", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: true },
2104 crate::clusters::codec::CommandField { tag: 4, name: "user_status", kind: crate::clusters::codec::FieldKind::Enum { name: "UserStatus", variants: &[(0, "Available"), (1, "Occupiedenabled"), (3, "Occupieddisabled")] }, optional: false, nullable: true },
2105 crate::clusters::codec::CommandField { tag: 5, name: "user_type", kind: crate::clusters::codec::FieldKind::Enum { name: "UserType", variants: &[(0, "Unrestricteduser"), (1, "Yeardayscheduleuser"), (2, "Weekdayscheduleuser"), (3, "Programminguser"), (4, "Nonaccessuser"), (5, "Forceduser"), (6, "Disposableuser"), (7, "Expiringuser"), (8, "Schedulerestricteduser"), (9, "Remoteonlyuser")] }, optional: false, nullable: true },
2106 ]),
2107 0x24 => Some(vec![
2108 crate::clusters::codec::CommandField { tag: 0, name: "credential", kind: crate::clusters::codec::FieldKind::Struct { name: "CredentialStruct" }, optional: false, nullable: false },
2109 ]),
2110 0x26 => Some(vec![
2111 crate::clusters::codec::CommandField { tag: 0, name: "credential", kind: crate::clusters::codec::FieldKind::Struct { name: "CredentialStruct" }, optional: false, nullable: true },
2112 ]),
2113 0x27 => Some(vec![
2114 crate::clusters::codec::CommandField { tag: 0, name: "pin_code", kind: crate::clusters::codec::FieldKind::OctetString, optional: true, nullable: false },
2115 ]),
2116 0x28 => Some(vec![
2117 crate::clusters::codec::CommandField { tag: 0, name: "signing_key", kind: crate::clusters::codec::FieldKind::OctetString, optional: false, nullable: false },
2118 crate::clusters::codec::CommandField { tag: 1, name: "verification_key", kind: crate::clusters::codec::FieldKind::OctetString, optional: false, nullable: false },
2119 crate::clusters::codec::CommandField { tag: 2, name: "group_identifier", kind: crate::clusters::codec::FieldKind::OctetString, optional: false, nullable: false },
2120 crate::clusters::codec::CommandField { tag: 3, name: "group_resolving_key", kind: crate::clusters::codec::FieldKind::OctetString, optional: false, nullable: false },
2121 ]),
2122 0x29 => Some(vec![]),
2123 _ => None,
2124 }
2125}
2126
2127pub fn encode_command_json(cmd_id: u32, args: &serde_json::Value) -> anyhow::Result<Vec<u8>> {
2128 match cmd_id {
2129 0x00 => {
2130 let pin_code = crate::clusters::codec::json_util::get_octstr(args, "pin_code")?;
2131 encode_lock_door(pin_code)
2132 }
2133 0x01 => {
2134 let pin_code = crate::clusters::codec::json_util::get_octstr(args, "pin_code")?;
2135 encode_unlock_door(pin_code)
2136 }
2137 0x02 => Ok(vec![]),
2138 0x03 => {
2139 let timeout = crate::clusters::codec::json_util::get_u16(args, "timeout")?;
2140 let pin_code = crate::clusters::codec::json_util::get_octstr(args, "pin_code")?;
2141 encode_unlock_with_timeout(timeout, pin_code)
2142 }
2143 0x0B => {
2144 let week_day_index = crate::clusters::codec::json_util::get_u8(args, "week_day_index")?;
2145 let user_index = crate::clusters::codec::json_util::get_u16(args, "user_index")?;
2146 let days_mask = crate::clusters::codec::json_util::get_u8(args, "days_mask")?;
2147 let start_hour = crate::clusters::codec::json_util::get_u8(args, "start_hour")?;
2148 let start_minute = crate::clusters::codec::json_util::get_u8(args, "start_minute")?;
2149 let end_hour = crate::clusters::codec::json_util::get_u8(args, "end_hour")?;
2150 let end_minute = crate::clusters::codec::json_util::get_u8(args, "end_minute")?;
2151 encode_set_week_day_schedule(week_day_index, user_index, days_mask, start_hour, start_minute, end_hour, end_minute)
2152 }
2153 0x0C => {
2154 let week_day_index = crate::clusters::codec::json_util::get_u8(args, "week_day_index")?;
2155 let user_index = crate::clusters::codec::json_util::get_u16(args, "user_index")?;
2156 encode_get_week_day_schedule(week_day_index, user_index)
2157 }
2158 0x0D => {
2159 let week_day_index = crate::clusters::codec::json_util::get_u8(args, "week_day_index")?;
2160 let user_index = crate::clusters::codec::json_util::get_u16(args, "user_index")?;
2161 encode_clear_week_day_schedule(week_day_index, user_index)
2162 }
2163 0x0E => {
2164 let year_day_index = crate::clusters::codec::json_util::get_u8(args, "year_day_index")?;
2165 let user_index = crate::clusters::codec::json_util::get_u16(args, "user_index")?;
2166 let local_start_time = crate::clusters::codec::json_util::get_u64(args, "local_start_time")?;
2167 let local_end_time = crate::clusters::codec::json_util::get_u64(args, "local_end_time")?;
2168 encode_set_year_day_schedule(year_day_index, user_index, local_start_time, local_end_time)
2169 }
2170 0x0F => {
2171 let year_day_index = crate::clusters::codec::json_util::get_u8(args, "year_day_index")?;
2172 let user_index = crate::clusters::codec::json_util::get_u16(args, "user_index")?;
2173 encode_get_year_day_schedule(year_day_index, user_index)
2174 }
2175 0x10 => {
2176 let year_day_index = crate::clusters::codec::json_util::get_u8(args, "year_day_index")?;
2177 let user_index = crate::clusters::codec::json_util::get_u16(args, "user_index")?;
2178 encode_clear_year_day_schedule(year_day_index, user_index)
2179 }
2180 0x11 => {
2181 let holiday_index = crate::clusters::codec::json_util::get_u8(args, "holiday_index")?;
2182 let local_start_time = crate::clusters::codec::json_util::get_u64(args, "local_start_time")?;
2183 let local_end_time = crate::clusters::codec::json_util::get_u64(args, "local_end_time")?;
2184 let operating_mode = {
2185 let n = crate::clusters::codec::json_util::get_u64(args, "operating_mode")?;
2186 OperatingMode::from_u8(n as u8).ok_or_else(|| anyhow::anyhow!("invalid OperatingMode: {}", n))?
2187 };
2188 encode_set_holiday_schedule(holiday_index, local_start_time, local_end_time, operating_mode)
2189 }
2190 0x12 => {
2191 let holiday_index = crate::clusters::codec::json_util::get_u8(args, "holiday_index")?;
2192 encode_get_holiday_schedule(holiday_index)
2193 }
2194 0x13 => {
2195 let holiday_index = crate::clusters::codec::json_util::get_u8(args, "holiday_index")?;
2196 encode_clear_holiday_schedule(holiday_index)
2197 }
2198 0x1A => {
2199 let operation_type = {
2200 let n = crate::clusters::codec::json_util::get_u64(args, "operation_type")?;
2201 DataOperationType::from_u8(n as u8).ok_or_else(|| anyhow::anyhow!("invalid DataOperationType: {}", n))?
2202 };
2203 let user_index = crate::clusters::codec::json_util::get_u16(args, "user_index")?;
2204 let user_name = crate::clusters::codec::json_util::get_opt_string(args, "user_name")?;
2205 let user_unique_id = crate::clusters::codec::json_util::get_opt_u32(args, "user_unique_id")?;
2206 let user_status = crate::clusters::codec::json_util::get_opt_u64(args, "user_status")?
2207 .and_then(|n| UserStatus::from_u8(n as u8));
2208 let user_type = crate::clusters::codec::json_util::get_opt_u64(args, "user_type")?
2209 .and_then(|n| UserType::from_u8(n as u8));
2210 let credential_rule = crate::clusters::codec::json_util::get_opt_u64(args, "credential_rule")?
2211 .and_then(|n| CredentialRule::from_u8(n as u8));
2212 encode_set_user(operation_type, user_index, user_name, user_unique_id, user_status, user_type, credential_rule)
2213 }
2214 0x1B => {
2215 let user_index = crate::clusters::codec::json_util::get_u16(args, "user_index")?;
2216 encode_get_user(user_index)
2217 }
2218 0x1D => {
2219 let user_index = crate::clusters::codec::json_util::get_u16(args, "user_index")?;
2220 encode_clear_user(user_index)
2221 }
2222 0x22 => Err(anyhow::anyhow!("command \"SetCredential\" has complex args: use raw mode")),
2223 0x24 => Err(anyhow::anyhow!("command \"GetCredentialStatus\" has complex args: use raw mode")),
2224 0x26 => Err(anyhow::anyhow!("command \"ClearCredential\" has complex args: use raw mode")),
2225 0x27 => {
2226 let pin_code = crate::clusters::codec::json_util::get_octstr(args, "pin_code")?;
2227 encode_unbolt_door(pin_code)
2228 }
2229 0x28 => {
2230 let signing_key = crate::clusters::codec::json_util::get_octstr(args, "signing_key")?;
2231 let verification_key = crate::clusters::codec::json_util::get_octstr(args, "verification_key")?;
2232 let group_identifier = crate::clusters::codec::json_util::get_octstr(args, "group_identifier")?;
2233 let group_resolving_key = crate::clusters::codec::json_util::get_octstr(args, "group_resolving_key")?;
2234 encode_set_aliro_reader_config(signing_key, verification_key, group_identifier, group_resolving_key)
2235 }
2236 0x29 => Ok(vec![]),
2237 _ => Err(anyhow::anyhow!("unknown command ID: 0x{:02X}", cmd_id)),
2238 }
2239}
2240
2241#[derive(Debug, serde::Serialize)]
2242pub struct GetWeekDayScheduleResponse {
2243 pub week_day_index: Option<u8>,
2244 pub user_index: Option<u16>,
2245 pub status: Option<u8>,
2246 pub days_mask: Option<DaysMask>,
2247 pub start_hour: Option<u8>,
2248 pub start_minute: Option<u8>,
2249 pub end_hour: Option<u8>,
2250 pub end_minute: Option<u8>,
2251}
2252
2253#[derive(Debug, serde::Serialize)]
2254pub struct GetYearDayScheduleResponse {
2255 pub year_day_index: Option<u8>,
2256 pub user_index: Option<u16>,
2257 pub status: Option<u8>,
2258 pub local_start_time: Option<u64>,
2259 pub local_end_time: Option<u64>,
2260}
2261
2262#[derive(Debug, serde::Serialize)]
2263pub struct GetHolidayScheduleResponse {
2264 pub holiday_index: Option<u8>,
2265 pub status: Option<u8>,
2266 pub local_start_time: Option<u64>,
2267 pub local_end_time: Option<u64>,
2268 pub operating_mode: Option<OperatingMode>,
2269}
2270
2271#[derive(Debug, serde::Serialize)]
2272pub struct GetUserResponse {
2273 pub user_index: Option<u16>,
2274 pub user_name: Option<String>,
2275 pub user_unique_id: Option<u32>,
2276 pub user_status: Option<UserStatus>,
2277 pub user_type: Option<UserType>,
2278 pub credential_rule: Option<CredentialRule>,
2279 pub credentials: Option<Vec<Credential>>,
2280 pub creator_fabric_index: Option<u8>,
2281 pub last_modified_fabric_index: Option<u8>,
2282 pub next_user_index: Option<u16>,
2283}
2284
2285#[derive(Debug, serde::Serialize)]
2286pub struct SetCredentialResponse {
2287 pub status: Option<u8>,
2288 pub user_index: Option<u16>,
2289 pub next_credential_index: Option<u16>,
2290}
2291
2292#[derive(Debug, serde::Serialize)]
2293pub struct GetCredentialStatusResponse {
2294 pub credential_exists: Option<bool>,
2295 pub user_index: Option<u16>,
2296 pub creator_fabric_index: Option<u8>,
2297 pub last_modified_fabric_index: Option<u8>,
2298 pub next_credential_index: Option<u16>,
2299 #[serde(serialize_with = "serialize_opt_bytes_as_hex")]
2300 pub credential_data: Option<Vec<u8>>,
2301}
2302
2303pub fn decode_get_week_day_schedule_response(inp: &tlv::TlvItemValue) -> anyhow::Result<GetWeekDayScheduleResponse> {
2307 if let tlv::TlvItemValue::List(_fields) = inp {
2308 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
2309 Ok(GetWeekDayScheduleResponse {
2310 week_day_index: item.get_int(&[0]).map(|v| v as u8),
2311 user_index: item.get_int(&[1]).map(|v| v as u16),
2312 status: item.get_int(&[2]).map(|v| v as u8),
2313 days_mask: item.get_int(&[3]).map(|v| v as u8),
2314 start_hour: item.get_int(&[4]).map(|v| v as u8),
2315 start_minute: item.get_int(&[5]).map(|v| v as u8),
2316 end_hour: item.get_int(&[6]).map(|v| v as u8),
2317 end_minute: item.get_int(&[7]).map(|v| v as u8),
2318 })
2319 } else {
2320 Err(anyhow::anyhow!("Expected struct fields"))
2321 }
2322}
2323
2324pub fn decode_get_year_day_schedule_response(inp: &tlv::TlvItemValue) -> anyhow::Result<GetYearDayScheduleResponse> {
2326 if let tlv::TlvItemValue::List(_fields) = inp {
2327 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
2328 Ok(GetYearDayScheduleResponse {
2329 year_day_index: item.get_int(&[0]).map(|v| v as u8),
2330 user_index: item.get_int(&[1]).map(|v| v as u16),
2331 status: item.get_int(&[2]).map(|v| v as u8),
2332 local_start_time: item.get_int(&[3]),
2333 local_end_time: item.get_int(&[4]),
2334 })
2335 } else {
2336 Err(anyhow::anyhow!("Expected struct fields"))
2337 }
2338}
2339
2340pub fn decode_get_holiday_schedule_response(inp: &tlv::TlvItemValue) -> anyhow::Result<GetHolidayScheduleResponse> {
2342 if let tlv::TlvItemValue::List(_fields) = inp {
2343 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
2344 Ok(GetHolidayScheduleResponse {
2345 holiday_index: item.get_int(&[0]).map(|v| v as u8),
2346 status: item.get_int(&[1]).map(|v| v as u8),
2347 local_start_time: item.get_int(&[2]),
2348 local_end_time: item.get_int(&[3]),
2349 operating_mode: item.get_int(&[4]).and_then(|v| OperatingMode::from_u8(v as u8)),
2350 })
2351 } else {
2352 Err(anyhow::anyhow!("Expected struct fields"))
2353 }
2354}
2355
2356pub fn decode_get_user_response(inp: &tlv::TlvItemValue) -> anyhow::Result<GetUserResponse> {
2358 if let tlv::TlvItemValue::List(_fields) = inp {
2359 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
2360 Ok(GetUserResponse {
2361 user_index: item.get_int(&[0]).map(|v| v as u16),
2362 user_name: item.get_string_owned(&[1]),
2363 user_unique_id: item.get_int(&[2]).map(|v| v as u32),
2364 user_status: item.get_int(&[3]).and_then(|v| UserStatus::from_u8(v as u8)),
2365 user_type: item.get_int(&[4]).and_then(|v| UserType::from_u8(v as u8)),
2366 credential_rule: item.get_int(&[5]).and_then(|v| CredentialRule::from_u8(v as u8)),
2367 credentials: {
2368 if let Some(tlv::TlvItemValue::List(l)) = item.get(&[6]) {
2369 let mut items = Vec::new();
2370 for list_item in l {
2371 items.push(Credential {
2372 credential_type: list_item.get_int(&[0]).and_then(|v| CredentialType::from_u8(v as u8)),
2373 credential_index: list_item.get_int(&[1]).map(|v| v as u16),
2374 });
2375 }
2376 Some(items)
2377 } else {
2378 None
2379 }
2380 },
2381 creator_fabric_index: item.get_int(&[7]).map(|v| v as u8),
2382 last_modified_fabric_index: item.get_int(&[8]).map(|v| v as u8),
2383 next_user_index: item.get_int(&[9]).map(|v| v as u16),
2384 })
2385 } else {
2386 Err(anyhow::anyhow!("Expected struct fields"))
2387 }
2388}
2389
2390pub fn decode_set_credential_response(inp: &tlv::TlvItemValue) -> anyhow::Result<SetCredentialResponse> {
2392 if let tlv::TlvItemValue::List(_fields) = inp {
2393 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
2394 Ok(SetCredentialResponse {
2395 status: item.get_int(&[0]).map(|v| v as u8),
2396 user_index: item.get_int(&[1]).map(|v| v as u16),
2397 next_credential_index: item.get_int(&[2]).map(|v| v as u16),
2398 })
2399 } else {
2400 Err(anyhow::anyhow!("Expected struct fields"))
2401 }
2402}
2403
2404pub fn decode_get_credential_status_response(inp: &tlv::TlvItemValue) -> anyhow::Result<GetCredentialStatusResponse> {
2406 if let tlv::TlvItemValue::List(_fields) = inp {
2407 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
2408 Ok(GetCredentialStatusResponse {
2409 credential_exists: item.get_bool(&[0]),
2410 user_index: item.get_int(&[1]).map(|v| v as u16),
2411 creator_fabric_index: item.get_int(&[2]).map(|v| v as u8),
2412 last_modified_fabric_index: item.get_int(&[3]).map(|v| v as u8),
2413 next_credential_index: item.get_int(&[4]).map(|v| v as u16),
2414 credential_data: item.get_octet_string_owned(&[5]),
2415 })
2416 } else {
2417 Err(anyhow::anyhow!("Expected struct fields"))
2418 }
2419}
2420
2421pub async fn lock_door(conn: &crate::controller::Connection, endpoint: u16, pin_code: Vec<u8>) -> anyhow::Result<()> {
2425 conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_CMD_ID_LOCKDOOR, &encode_lock_door(pin_code)?).await?;
2426 Ok(())
2427}
2428
2429pub async fn unlock_door(conn: &crate::controller::Connection, endpoint: u16, pin_code: Vec<u8>) -> anyhow::Result<()> {
2431 conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_CMD_ID_UNLOCKDOOR, &encode_unlock_door(pin_code)?).await?;
2432 Ok(())
2433}
2434
2435pub async fn toggle(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<()> {
2437 conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_CMD_ID_TOGGLE, &[]).await?;
2438 Ok(())
2439}
2440
2441pub async fn unlock_with_timeout(conn: &crate::controller::Connection, endpoint: u16, timeout: u16, pin_code: Vec<u8>) -> anyhow::Result<()> {
2443 conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_CMD_ID_UNLOCKWITHTIMEOUT, &encode_unlock_with_timeout(timeout, pin_code)?).await?;
2444 Ok(())
2445}
2446
2447pub async fn set_week_day_schedule(conn: &crate::controller::Connection, endpoint: u16, week_day_index: u8, user_index: u16, days_mask: DaysMask, start_hour: u8, start_minute: u8, end_hour: u8, end_minute: u8) -> anyhow::Result<()> {
2449 conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_CMD_ID_SETWEEKDAYSCHEDULE, &encode_set_week_day_schedule(week_day_index, user_index, days_mask, start_hour, start_minute, end_hour, end_minute)?).await?;
2450 Ok(())
2451}
2452
2453pub async fn get_week_day_schedule(conn: &crate::controller::Connection, endpoint: u16, week_day_index: u8, user_index: u16) -> anyhow::Result<GetWeekDayScheduleResponse> {
2455 let tlv = conn.invoke_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_CMD_ID_GETWEEKDAYSCHEDULE, &encode_get_week_day_schedule(week_day_index, user_index)?).await?;
2456 decode_get_week_day_schedule_response(&tlv)
2457}
2458
2459pub async fn clear_week_day_schedule(conn: &crate::controller::Connection, endpoint: u16, week_day_index: u8, user_index: u16) -> anyhow::Result<()> {
2461 conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_CMD_ID_CLEARWEEKDAYSCHEDULE, &encode_clear_week_day_schedule(week_day_index, user_index)?).await?;
2462 Ok(())
2463}
2464
2465pub async fn set_year_day_schedule(conn: &crate::controller::Connection, endpoint: u16, year_day_index: u8, user_index: u16, local_start_time: u64, local_end_time: u64) -> anyhow::Result<()> {
2467 conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_CMD_ID_SETYEARDAYSCHEDULE, &encode_set_year_day_schedule(year_day_index, user_index, local_start_time, local_end_time)?).await?;
2468 Ok(())
2469}
2470
2471pub async fn get_year_day_schedule(conn: &crate::controller::Connection, endpoint: u16, year_day_index: u8, user_index: u16) -> anyhow::Result<GetYearDayScheduleResponse> {
2473 let tlv = conn.invoke_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_CMD_ID_GETYEARDAYSCHEDULE, &encode_get_year_day_schedule(year_day_index, user_index)?).await?;
2474 decode_get_year_day_schedule_response(&tlv)
2475}
2476
2477pub async fn clear_year_day_schedule(conn: &crate::controller::Connection, endpoint: u16, year_day_index: u8, user_index: u16) -> anyhow::Result<()> {
2479 conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_CMD_ID_CLEARYEARDAYSCHEDULE, &encode_clear_year_day_schedule(year_day_index, user_index)?).await?;
2480 Ok(())
2481}
2482
2483pub async fn set_holiday_schedule(conn: &crate::controller::Connection, endpoint: u16, holiday_index: u8, local_start_time: u64, local_end_time: u64, operating_mode: OperatingMode) -> anyhow::Result<()> {
2485 conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_CMD_ID_SETHOLIDAYSCHEDULE, &encode_set_holiday_schedule(holiday_index, local_start_time, local_end_time, operating_mode)?).await?;
2486 Ok(())
2487}
2488
2489pub async fn get_holiday_schedule(conn: &crate::controller::Connection, endpoint: u16, holiday_index: u8) -> anyhow::Result<GetHolidayScheduleResponse> {
2491 let tlv = conn.invoke_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_CMD_ID_GETHOLIDAYSCHEDULE, &encode_get_holiday_schedule(holiday_index)?).await?;
2492 decode_get_holiday_schedule_response(&tlv)
2493}
2494
2495pub async fn clear_holiday_schedule(conn: &crate::controller::Connection, endpoint: u16, holiday_index: u8) -> anyhow::Result<()> {
2497 conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_CMD_ID_CLEARHOLIDAYSCHEDULE, &encode_clear_holiday_schedule(holiday_index)?).await?;
2498 Ok(())
2499}
2500
2501pub async fn set_user(conn: &crate::controller::Connection, endpoint: u16, operation_type: DataOperationType, user_index: u16, user_name: Option<String>, user_unique_id: Option<u32>, user_status: Option<UserStatus>, user_type: Option<UserType>, credential_rule: Option<CredentialRule>) -> anyhow::Result<()> {
2503 conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_CMD_ID_SETUSER, &encode_set_user(operation_type, user_index, user_name, user_unique_id, user_status, user_type, credential_rule)?).await?;
2504 Ok(())
2505}
2506
2507pub async fn get_user(conn: &crate::controller::Connection, endpoint: u16, user_index: u16) -> anyhow::Result<GetUserResponse> {
2509 let tlv = conn.invoke_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_CMD_ID_GETUSER, &encode_get_user(user_index)?).await?;
2510 decode_get_user_response(&tlv)
2511}
2512
2513pub async fn clear_user(conn: &crate::controller::Connection, endpoint: u16, user_index: u16) -> anyhow::Result<()> {
2515 conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_CMD_ID_CLEARUSER, &encode_clear_user(user_index)?).await?;
2516 Ok(())
2517}
2518
2519pub async fn set_credential(conn: &crate::controller::Connection, endpoint: u16, operation_type: DataOperationType, credential: Credential, credential_data: Vec<u8>, user_index: Option<u16>, user_status: Option<UserStatus>, user_type: Option<UserType>) -> anyhow::Result<SetCredentialResponse> {
2521 let tlv = conn.invoke_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_CMD_ID_SETCREDENTIAL, &encode_set_credential(operation_type, credential, credential_data, user_index, user_status, user_type)?).await?;
2522 decode_set_credential_response(&tlv)
2523}
2524
2525pub async fn get_credential_status(conn: &crate::controller::Connection, endpoint: u16, credential: Credential) -> anyhow::Result<GetCredentialStatusResponse> {
2527 let tlv = conn.invoke_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_CMD_ID_GETCREDENTIALSTATUS, &encode_get_credential_status(credential)?).await?;
2528 decode_get_credential_status_response(&tlv)
2529}
2530
2531pub async fn clear_credential(conn: &crate::controller::Connection, endpoint: u16, credential: Option<Credential>) -> anyhow::Result<()> {
2533 conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_CMD_ID_CLEARCREDENTIAL, &encode_clear_credential(credential)?).await?;
2534 Ok(())
2535}
2536
2537pub async fn unbolt_door(conn: &crate::controller::Connection, endpoint: u16, pin_code: Vec<u8>) -> anyhow::Result<()> {
2539 conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_CMD_ID_UNBOLTDOOR, &encode_unbolt_door(pin_code)?).await?;
2540 Ok(())
2541}
2542
2543pub async fn set_aliro_reader_config(conn: &crate::controller::Connection, endpoint: u16, signing_key: Vec<u8>, verification_key: Vec<u8>, group_identifier: Vec<u8>, group_resolving_key: Vec<u8>) -> anyhow::Result<()> {
2545 conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_CMD_ID_SETALIROREADERCONFIG, &encode_set_aliro_reader_config(signing_key, verification_key, group_identifier, group_resolving_key)?).await?;
2546 Ok(())
2547}
2548
2549pub async fn clear_aliro_reader_config(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<()> {
2551 conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_CMD_ID_CLEARALIROREADERCONFIG, &[]).await?;
2552 Ok(())
2553}
2554
2555pub async fn read_lock_state(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<LockState>> {
2557 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_LOCKSTATE).await?;
2558 decode_lock_state(&tlv)
2559}
2560
2561pub async fn read_lock_type(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<LockType> {
2563 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_LOCKTYPE).await?;
2564 decode_lock_type(&tlv)
2565}
2566
2567pub async fn read_actuator_enabled(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<bool> {
2569 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_ACTUATORENABLED).await?;
2570 decode_actuator_enabled(&tlv)
2571}
2572
2573pub async fn read_door_state(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<DoorState>> {
2575 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_DOORSTATE).await?;
2576 decode_door_state(&tlv)
2577}
2578
2579pub async fn read_door_open_events(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
2581 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_DOOROPENEVENTS).await?;
2582 decode_door_open_events(&tlv)
2583}
2584
2585pub async fn read_door_closed_events(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
2587 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_DOORCLOSEDEVENTS).await?;
2588 decode_door_closed_events(&tlv)
2589}
2590
2591pub async fn read_open_period(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2593 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_OPENPERIOD).await?;
2594 decode_open_period(&tlv)
2595}
2596
2597pub async fn read_number_of_total_users_supported(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2599 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_NUMBEROFTOTALUSERSSUPPORTED).await?;
2600 decode_number_of_total_users_supported(&tlv)
2601}
2602
2603pub async fn read_number_of_pin_users_supported(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2605 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_NUMBEROFPINUSERSSUPPORTED).await?;
2606 decode_number_of_pin_users_supported(&tlv)
2607}
2608
2609pub async fn read_number_of_rfid_users_supported(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2611 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_NUMBEROFRFIDUSERSSUPPORTED).await?;
2612 decode_number_of_rfid_users_supported(&tlv)
2613}
2614
2615pub async fn read_number_of_week_day_schedules_supported_per_user(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
2617 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_NUMBEROFWEEKDAYSCHEDULESSUPPORTEDPERUSER).await?;
2618 decode_number_of_week_day_schedules_supported_per_user(&tlv)
2619}
2620
2621pub async fn read_number_of_year_day_schedules_supported_per_user(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
2623 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_NUMBEROFYEARDAYSCHEDULESSUPPORTEDPERUSER).await?;
2624 decode_number_of_year_day_schedules_supported_per_user(&tlv)
2625}
2626
2627pub async fn read_number_of_holiday_schedules_supported(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
2629 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_NUMBEROFHOLIDAYSCHEDULESSUPPORTED).await?;
2630 decode_number_of_holiday_schedules_supported(&tlv)
2631}
2632
2633pub async fn read_max_pin_code_length(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
2635 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_MAXPINCODELENGTH).await?;
2636 decode_max_pin_code_length(&tlv)
2637}
2638
2639pub async fn read_min_pin_code_length(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
2641 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_MINPINCODELENGTH).await?;
2642 decode_min_pin_code_length(&tlv)
2643}
2644
2645pub async fn read_max_rfid_code_length(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
2647 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_MAXRFIDCODELENGTH).await?;
2648 decode_max_rfid_code_length(&tlv)
2649}
2650
2651pub async fn read_min_rfid_code_length(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
2653 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_MINRFIDCODELENGTH).await?;
2654 decode_min_rfid_code_length(&tlv)
2655}
2656
2657pub async fn read_credential_rules_support(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<CredentialRules> {
2659 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_CREDENTIALRULESSUPPORT).await?;
2660 decode_credential_rules_support(&tlv)
2661}
2662
2663pub async fn read_number_of_credentials_supported_per_user(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
2665 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_NUMBEROFCREDENTIALSSUPPORTEDPERUSER).await?;
2666 decode_number_of_credentials_supported_per_user(&tlv)
2667}
2668
2669pub async fn read_language(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<String> {
2671 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_LANGUAGE).await?;
2672 decode_language(&tlv)
2673}
2674
2675pub async fn read_led_settings(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<LEDSetting> {
2677 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_LEDSETTINGS).await?;
2678 decode_led_settings(&tlv)
2679}
2680
2681pub async fn read_auto_relock_time(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
2683 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_AUTORELOCKTIME).await?;
2684 decode_auto_relock_time(&tlv)
2685}
2686
2687pub async fn read_sound_volume(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<SoundVolume> {
2689 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_SOUNDVOLUME).await?;
2690 decode_sound_volume(&tlv)
2691}
2692
2693pub async fn read_operating_mode(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<OperatingMode> {
2695 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_OPERATINGMODE).await?;
2696 decode_operating_mode(&tlv)
2697}
2698
2699pub async fn read_supported_operating_modes(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<OperatingModes> {
2701 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_SUPPORTEDOPERATINGMODES).await?;
2702 decode_supported_operating_modes(&tlv)
2703}
2704
2705pub async fn read_default_configuration_register(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<ConfigurationRegister> {
2707 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_DEFAULTCONFIGURATIONREGISTER).await?;
2708 decode_default_configuration_register(&tlv)
2709}
2710
2711pub async fn read_enable_local_programming(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<bool> {
2713 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_ENABLELOCALPROGRAMMING).await?;
2714 decode_enable_local_programming(&tlv)
2715}
2716
2717pub async fn read_enable_one_touch_locking(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<bool> {
2719 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_ENABLEONETOUCHLOCKING).await?;
2720 decode_enable_one_touch_locking(&tlv)
2721}
2722
2723pub async fn read_enable_inside_status_led(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<bool> {
2725 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_ENABLEINSIDESTATUSLED).await?;
2726 decode_enable_inside_status_led(&tlv)
2727}
2728
2729pub async fn read_enable_privacy_mode_button(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<bool> {
2731 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_ENABLEPRIVACYMODEBUTTON).await?;
2732 decode_enable_privacy_mode_button(&tlv)
2733}
2734
2735pub async fn read_local_programming_features(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<LocalProgrammingFeatures> {
2737 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_LOCALPROGRAMMINGFEATURES).await?;
2738 decode_local_programming_features(&tlv)
2739}
2740
2741pub async fn read_wrong_code_entry_limit(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
2743 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_WRONGCODEENTRYLIMIT).await?;
2744 decode_wrong_code_entry_limit(&tlv)
2745}
2746
2747pub async fn read_user_code_temporary_disable_time(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
2749 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_USERCODETEMPORARYDISABLETIME).await?;
2750 decode_user_code_temporary_disable_time(&tlv)
2751}
2752
2753pub async fn read_send_pin_over_the_air(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<bool> {
2755 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_SENDPINOVERTHEAIR).await?;
2756 decode_send_pin_over_the_air(&tlv)
2757}
2758
2759pub async fn read_require_pinfor_remote_operation(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<bool> {
2761 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_REQUIREPINFORREMOTEOPERATION).await?;
2762 decode_require_pinfor_remote_operation(&tlv)
2763}
2764
2765pub async fn read_security_level(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
2767 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_SECURITYLEVEL).await?;
2768 decode_security_level(&tlv)
2769}
2770
2771pub async fn read_expiring_user_timeout(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2773 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_EXPIRINGUSERTIMEOUT).await?;
2774 decode_expiring_user_timeout(&tlv)
2775}
2776
2777pub async fn read_aliro_reader_verification_key(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<Vec<u8>>> {
2779 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_ALIROREADERVERIFICATIONKEY).await?;
2780 decode_aliro_reader_verification_key(&tlv)
2781}
2782
2783pub async fn read_aliro_reader_group_identifier(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<Vec<u8>>> {
2785 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_ALIROREADERGROUPIDENTIFIER).await?;
2786 decode_aliro_reader_group_identifier(&tlv)
2787}
2788
2789pub async fn read_aliro_reader_group_sub_identifier(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Vec<u8>> {
2791 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_ALIROREADERGROUPSUBIDENTIFIER).await?;
2792 decode_aliro_reader_group_sub_identifier(&tlv)
2793}
2794
2795pub async fn read_aliro_expedited_transaction_supported_protocol_versions(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Vec<Vec<u8>>> {
2797 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_ALIROEXPEDITEDTRANSACTIONSUPPORTEDPROTOCOLVERSIONS).await?;
2798 decode_aliro_expedited_transaction_supported_protocol_versions(&tlv)
2799}
2800
2801pub async fn read_aliro_group_resolving_key(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<Vec<u8>>> {
2803 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_ALIROGROUPRESOLVINGKEY).await?;
2804 decode_aliro_group_resolving_key(&tlv)
2805}
2806
2807pub async fn read_aliro_supported_bleuwb_protocol_versions(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Vec<Vec<u8>>> {
2809 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_ALIROSUPPORTEDBLEUWBPROTOCOLVERSIONS).await?;
2810 decode_aliro_supported_bleuwb_protocol_versions(&tlv)
2811}
2812
2813pub async fn read_aliro_ble_advertising_version(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
2815 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_ALIROBLEADVERTISINGVERSION).await?;
2816 decode_aliro_ble_advertising_version(&tlv)
2817}
2818
2819pub async fn read_number_of_aliro_credential_issuer_keys_supported(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2821 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_NUMBEROFALIROCREDENTIALISSUERKEYSSUPPORTED).await?;
2822 decode_number_of_aliro_credential_issuer_keys_supported(&tlv)
2823}
2824
2825pub async fn read_number_of_aliro_endpoint_keys_supported(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
2827 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_DOOR_LOCK, crate::clusters::defs::CLUSTER_DOOR_LOCK_ATTR_ID_NUMBEROFALIROENDPOINTKEYSSUPPORTED).await?;
2828 decode_number_of_aliro_endpoint_keys_supported(&tlv)
2829}
2830
2831#[derive(Debug, serde::Serialize)]
2832pub struct DoorLockAlarmEvent {
2833 pub alarm_code: Option<AlarmCode>,
2834}
2835
2836#[derive(Debug, serde::Serialize)]
2837pub struct DoorStateChangeEvent {
2838 pub door_state: Option<DoorState>,
2839}
2840
2841#[derive(Debug, serde::Serialize)]
2842pub struct LockOperationEvent {
2843 pub lock_operation_type: Option<LockOperationType>,
2844 pub operation_source: Option<OperationSource>,
2845 pub user_index: Option<u16>,
2846 pub fabric_index: Option<u8>,
2847 pub source_node: Option<u64>,
2848 pub credentials: Option<Vec<Credential>>,
2849}
2850
2851#[derive(Debug, serde::Serialize)]
2852pub struct LockOperationErrorEvent {
2853 pub lock_operation_type: Option<LockOperationType>,
2854 pub operation_source: Option<OperationSource>,
2855 pub operation_error: Option<OperationError>,
2856 pub user_index: Option<u16>,
2857 pub fabric_index: Option<u8>,
2858 pub source_node: Option<u64>,
2859 pub credentials: Option<Vec<Credential>>,
2860}
2861
2862#[derive(Debug, serde::Serialize)]
2863pub struct LockUserChangeEvent {
2864 pub lock_data_type: Option<LockDataType>,
2865 pub data_operation_type: Option<DataOperationType>,
2866 pub operation_source: Option<OperationSource>,
2867 pub user_index: Option<u16>,
2868 pub fabric_index: Option<u8>,
2869 pub source_node: Option<u64>,
2870 pub data_index: Option<u16>,
2871}
2872
2873pub fn decode_door_lock_alarm_event(inp: &tlv::TlvItemValue) -> anyhow::Result<DoorLockAlarmEvent> {
2877 if let tlv::TlvItemValue::List(_fields) = inp {
2878 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
2879 Ok(DoorLockAlarmEvent {
2880 alarm_code: item.get_int(&[0]).and_then(|v| AlarmCode::from_u8(v as u8)),
2881 })
2882 } else {
2883 Err(anyhow::anyhow!("Expected struct fields"))
2884 }
2885}
2886
2887pub fn decode_door_state_change_event(inp: &tlv::TlvItemValue) -> anyhow::Result<DoorStateChangeEvent> {
2889 if let tlv::TlvItemValue::List(_fields) = inp {
2890 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
2891 Ok(DoorStateChangeEvent {
2892 door_state: item.get_int(&[0]).and_then(|v| DoorState::from_u8(v as u8)),
2893 })
2894 } else {
2895 Err(anyhow::anyhow!("Expected struct fields"))
2896 }
2897}
2898
2899pub fn decode_lock_operation_event(inp: &tlv::TlvItemValue) -> anyhow::Result<LockOperationEvent> {
2901 if let tlv::TlvItemValue::List(_fields) = inp {
2902 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
2903 Ok(LockOperationEvent {
2904 lock_operation_type: item.get_int(&[0]).and_then(|v| LockOperationType::from_u8(v as u8)),
2905 operation_source: item.get_int(&[1]).and_then(|v| OperationSource::from_u8(v as u8)),
2906 user_index: item.get_int(&[2]).map(|v| v as u16),
2907 fabric_index: item.get_int(&[3]).map(|v| v as u8),
2908 source_node: item.get_int(&[4]),
2909 credentials: {
2910 if let Some(tlv::TlvItemValue::List(l)) = item.get(&[5]) {
2911 let mut items = Vec::new();
2912 for list_item in l {
2913 items.push(Credential {
2914 credential_type: list_item.get_int(&[0]).and_then(|v| CredentialType::from_u8(v as u8)),
2915 credential_index: list_item.get_int(&[1]).map(|v| v as u16),
2916 });
2917 }
2918 Some(items)
2919 } else {
2920 None
2921 }
2922 },
2923 })
2924 } else {
2925 Err(anyhow::anyhow!("Expected struct fields"))
2926 }
2927}
2928
2929pub fn decode_lock_operation_error_event(inp: &tlv::TlvItemValue) -> anyhow::Result<LockOperationErrorEvent> {
2931 if let tlv::TlvItemValue::List(_fields) = inp {
2932 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
2933 Ok(LockOperationErrorEvent {
2934 lock_operation_type: item.get_int(&[0]).and_then(|v| LockOperationType::from_u8(v as u8)),
2935 operation_source: item.get_int(&[1]).and_then(|v| OperationSource::from_u8(v as u8)),
2936 operation_error: item.get_int(&[2]).and_then(|v| OperationError::from_u8(v as u8)),
2937 user_index: item.get_int(&[3]).map(|v| v as u16),
2938 fabric_index: item.get_int(&[4]).map(|v| v as u8),
2939 source_node: item.get_int(&[5]),
2940 credentials: {
2941 if let Some(tlv::TlvItemValue::List(l)) = item.get(&[6]) {
2942 let mut items = Vec::new();
2943 for list_item in l {
2944 items.push(Credential {
2945 credential_type: list_item.get_int(&[0]).and_then(|v| CredentialType::from_u8(v as u8)),
2946 credential_index: list_item.get_int(&[1]).map(|v| v as u16),
2947 });
2948 }
2949 Some(items)
2950 } else {
2951 None
2952 }
2953 },
2954 })
2955 } else {
2956 Err(anyhow::anyhow!("Expected struct fields"))
2957 }
2958}
2959
2960pub fn decode_lock_user_change_event(inp: &tlv::TlvItemValue) -> anyhow::Result<LockUserChangeEvent> {
2962 if let tlv::TlvItemValue::List(_fields) = inp {
2963 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
2964 Ok(LockUserChangeEvent {
2965 lock_data_type: item.get_int(&[0]).and_then(|v| LockDataType::from_u8(v as u8)),
2966 data_operation_type: item.get_int(&[1]).and_then(|v| DataOperationType::from_u8(v as u8)),
2967 operation_source: item.get_int(&[2]).and_then(|v| OperationSource::from_u8(v as u8)),
2968 user_index: item.get_int(&[3]).map(|v| v as u16),
2969 fabric_index: item.get_int(&[4]).map(|v| v as u8),
2970 source_node: item.get_int(&[5]),
2971 data_index: item.get_int(&[6]).map(|v| v as u16),
2972 })
2973 } else {
2974 Err(anyhow::anyhow!("Expected struct fields"))
2975 }
2976}
2977