1use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11use crate::clusters::helpers::{serialize_opt_bytes_as_hex};
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
17#[repr(u8)]
18pub enum AlarmCode {
19 Lockjammed = 0,
21 Lockfactoryreset = 1,
23 Lockradiopowercycled = 3,
25 Wrongcodeentrylimit = 4,
27 Frontesceutcheonremoved = 5,
29 Doorforcedopen = 6,
31 Doorajar = 7,
33 Forceduser = 8,
35}
36
37impl AlarmCode {
38 pub fn from_u8(value: u8) -> Option<Self> {
40 match value {
41 0 => Some(AlarmCode::Lockjammed),
42 1 => Some(AlarmCode::Lockfactoryreset),
43 3 => Some(AlarmCode::Lockradiopowercycled),
44 4 => Some(AlarmCode::Wrongcodeentrylimit),
45 5 => Some(AlarmCode::Frontesceutcheonremoved),
46 6 => Some(AlarmCode::Doorforcedopen),
47 7 => Some(AlarmCode::Doorajar),
48 8 => Some(AlarmCode::Forceduser),
49 _ => None,
50 }
51 }
52
53 pub fn to_u8(self) -> u8 {
55 self as u8
56 }
57}
58
59impl From<AlarmCode> for u8 {
60 fn from(val: AlarmCode) -> Self {
61 val as u8
62 }
63}
64
65#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
66#[repr(u8)]
67pub enum CredentialRule {
68 Single = 0,
70 Dual = 1,
72 Tri = 2,
74}
75
76impl CredentialRule {
77 pub fn from_u8(value: u8) -> Option<Self> {
79 match value {
80 0 => Some(CredentialRule::Single),
81 1 => Some(CredentialRule::Dual),
82 2 => Some(CredentialRule::Tri),
83 _ => None,
84 }
85 }
86
87 pub fn to_u8(self) -> u8 {
89 self as u8
90 }
91}
92
93impl From<CredentialRule> for u8 {
94 fn from(val: CredentialRule) -> Self {
95 val as u8
96 }
97}
98
99#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
100#[repr(u8)]
101pub enum CredentialType {
102 Programmingpin = 0,
104 Pin = 1,
106 Rfid = 2,
108 Fingerprint = 3,
110 Fingervein = 4,
112 Face = 5,
114 Alirocredentialissuerkey = 6,
116 Aliroevictableendpointkey = 7,
118 Alirononevictableendpointkey = 8,
120}
121
122impl CredentialType {
123 pub fn from_u8(value: u8) -> Option<Self> {
125 match value {
126 0 => Some(CredentialType::Programmingpin),
127 1 => Some(CredentialType::Pin),
128 2 => Some(CredentialType::Rfid),
129 3 => Some(CredentialType::Fingerprint),
130 4 => Some(CredentialType::Fingervein),
131 5 => Some(CredentialType::Face),
132 6 => Some(CredentialType::Alirocredentialissuerkey),
133 7 => Some(CredentialType::Aliroevictableendpointkey),
134 8 => Some(CredentialType::Alirononevictableendpointkey),
135 _ => None,
136 }
137 }
138
139 pub fn to_u8(self) -> u8 {
141 self as u8
142 }
143}
144
145impl From<CredentialType> for u8 {
146 fn from(val: CredentialType) -> Self {
147 val as u8
148 }
149}
150
151#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
152#[repr(u8)]
153pub enum DataOperationType {
154 Add = 0,
156 Clear = 1,
158 Modify = 2,
160}
161
162impl DataOperationType {
163 pub fn from_u8(value: u8) -> Option<Self> {
165 match value {
166 0 => Some(DataOperationType::Add),
167 1 => Some(DataOperationType::Clear),
168 2 => Some(DataOperationType::Modify),
169 _ => None,
170 }
171 }
172
173 pub fn to_u8(self) -> u8 {
175 self as u8
176 }
177}
178
179impl From<DataOperationType> for u8 {
180 fn from(val: DataOperationType) -> Self {
181 val as u8
182 }
183}
184
185#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
186#[repr(u8)]
187pub enum DoorState {
188 Dooropen = 0,
190 Doorclosed = 1,
192 Doorjammed = 2,
194 Doorforcedopen = 3,
196 Doorunspecifiederror = 4,
198 Doorajar = 5,
200}
201
202impl DoorState {
203 pub fn from_u8(value: u8) -> Option<Self> {
205 match value {
206 0 => Some(DoorState::Dooropen),
207 1 => Some(DoorState::Doorclosed),
208 2 => Some(DoorState::Doorjammed),
209 3 => Some(DoorState::Doorforcedopen),
210 4 => Some(DoorState::Doorunspecifiederror),
211 5 => Some(DoorState::Doorajar),
212 _ => None,
213 }
214 }
215
216 pub fn to_u8(self) -> u8 {
218 self as u8
219 }
220}
221
222impl From<DoorState> for u8 {
223 fn from(val: DoorState) -> Self {
224 val as u8
225 }
226}
227
228#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
229#[repr(u8)]
230pub enum EventType {
231 Operation = 0,
233 Programming = 1,
235 Alarm = 2,
237}
238
239impl EventType {
240 pub fn from_u8(value: u8) -> Option<Self> {
242 match value {
243 0 => Some(EventType::Operation),
244 1 => Some(EventType::Programming),
245 2 => Some(EventType::Alarm),
246 _ => None,
247 }
248 }
249
250 pub fn to_u8(self) -> u8 {
252 self as u8
253 }
254}
255
256impl From<EventType> for u8 {
257 fn from(val: EventType) -> Self {
258 val as u8
259 }
260}
261
262#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
263#[repr(u8)]
264pub enum LEDSetting {
265 Noledsignal = 0,
267 Noledsignalaccessallowed = 1,
269 Ledsignalall = 2,
271}
272
273impl LEDSetting {
274 pub fn from_u8(value: u8) -> Option<Self> {
276 match value {
277 0 => Some(LEDSetting::Noledsignal),
278 1 => Some(LEDSetting::Noledsignalaccessallowed),
279 2 => Some(LEDSetting::Ledsignalall),
280 _ => None,
281 }
282 }
283
284 pub fn to_u8(self) -> u8 {
286 self as u8
287 }
288}
289
290impl From<LEDSetting> for u8 {
291 fn from(val: LEDSetting) -> Self {
292 val as u8
293 }
294}
295
296#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
297#[repr(u8)]
298pub enum LockDataType {
299 Unspecified = 0,
301 Programmingcode = 1,
303 Userindex = 2,
305 Weekdayschedule = 3,
307 Yeardayschedule = 4,
309 Holidayschedule = 5,
311 Pin = 6,
313 Rfid = 7,
315 Fingerprint = 8,
317 Fingervein = 9,
319 Face = 10,
321 Alirocredentialissuerkey = 11,
323 Aliroevictableendpointkey = 12,
325 Alirononevictableendpointkey = 13,
327}
328
329impl LockDataType {
330 pub fn from_u8(value: u8) -> Option<Self> {
332 match value {
333 0 => Some(LockDataType::Unspecified),
334 1 => Some(LockDataType::Programmingcode),
335 2 => Some(LockDataType::Userindex),
336 3 => Some(LockDataType::Weekdayschedule),
337 4 => Some(LockDataType::Yeardayschedule),
338 5 => Some(LockDataType::Holidayschedule),
339 6 => Some(LockDataType::Pin),
340 7 => Some(LockDataType::Rfid),
341 8 => Some(LockDataType::Fingerprint),
342 9 => Some(LockDataType::Fingervein),
343 10 => Some(LockDataType::Face),
344 11 => Some(LockDataType::Alirocredentialissuerkey),
345 12 => Some(LockDataType::Aliroevictableendpointkey),
346 13 => Some(LockDataType::Alirononevictableendpointkey),
347 _ => None,
348 }
349 }
350
351 pub fn to_u8(self) -> u8 {
353 self as u8
354 }
355}
356
357impl From<LockDataType> for u8 {
358 fn from(val: LockDataType) -> Self {
359 val as u8
360 }
361}
362
363#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
364#[repr(u8)]
365pub enum LockOperationType {
366 Lock = 0,
368 Unlock = 1,
370 Nonaccessuserevent = 2,
372 Forceduserevent = 3,
374 Unlatch = 4,
376}
377
378impl LockOperationType {
379 pub fn from_u8(value: u8) -> Option<Self> {
381 match value {
382 0 => Some(LockOperationType::Lock),
383 1 => Some(LockOperationType::Unlock),
384 2 => Some(LockOperationType::Nonaccessuserevent),
385 3 => Some(LockOperationType::Forceduserevent),
386 4 => Some(LockOperationType::Unlatch),
387 _ => None,
388 }
389 }
390
391 pub fn to_u8(self) -> u8 {
393 self as u8
394 }
395}
396
397impl From<LockOperationType> for u8 {
398 fn from(val: LockOperationType) -> Self {
399 val as u8
400 }
401}
402
403#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
404#[repr(u8)]
405pub enum LockState {
406 Notfullylocked = 0,
408 Locked = 1,
410 Unlocked = 2,
412 Unlatched = 3,
414}
415
416impl LockState {
417 pub fn from_u8(value: u8) -> Option<Self> {
419 match value {
420 0 => Some(LockState::Notfullylocked),
421 1 => Some(LockState::Locked),
422 2 => Some(LockState::Unlocked),
423 3 => Some(LockState::Unlatched),
424 _ => None,
425 }
426 }
427
428 pub fn to_u8(self) -> u8 {
430 self as u8
431 }
432}
433
434impl From<LockState> for u8 {
435 fn from(val: LockState) -> Self {
436 val as u8
437 }
438}
439
440#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
441#[repr(u8)]
442pub enum LockType {
443 Deadbolt = 0,
445 Magnetic = 1,
447 Other = 2,
449 Mortise = 3,
451 Rim = 4,
453 Latchbolt = 5,
455 Cylindricallock = 6,
457 Tubularlock = 7,
459 Interconnectedlock = 8,
461 Deadlatch = 9,
463 Doorfurniture = 10,
465 Eurocylinder = 11,
467}
468
469impl LockType {
470 pub fn from_u8(value: u8) -> Option<Self> {
472 match value {
473 0 => Some(LockType::Deadbolt),
474 1 => Some(LockType::Magnetic),
475 2 => Some(LockType::Other),
476 3 => Some(LockType::Mortise),
477 4 => Some(LockType::Rim),
478 5 => Some(LockType::Latchbolt),
479 6 => Some(LockType::Cylindricallock),
480 7 => Some(LockType::Tubularlock),
481 8 => Some(LockType::Interconnectedlock),
482 9 => Some(LockType::Deadlatch),
483 10 => Some(LockType::Doorfurniture),
484 11 => Some(LockType::Eurocylinder),
485 _ => None,
486 }
487 }
488
489 pub fn to_u8(self) -> u8 {
491 self as u8
492 }
493}
494
495impl From<LockType> for u8 {
496 fn from(val: LockType) -> Self {
497 val as u8
498 }
499}
500
501#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
502#[repr(u8)]
503pub enum OperatingMode {
504 Normal = 0,
505 Vacation = 1,
506 Privacy = 2,
507 Noremotelockunlock = 3,
508 Passage = 4,
509}
510
511impl OperatingMode {
512 pub fn from_u8(value: u8) -> Option<Self> {
514 match value {
515 0 => Some(OperatingMode::Normal),
516 1 => Some(OperatingMode::Vacation),
517 2 => Some(OperatingMode::Privacy),
518 3 => Some(OperatingMode::Noremotelockunlock),
519 4 => Some(OperatingMode::Passage),
520 _ => None,
521 }
522 }
523
524 pub fn to_u8(self) -> u8 {
526 self as u8
527 }
528}
529
530impl From<OperatingMode> for u8 {
531 fn from(val: OperatingMode) -> Self {
532 val as u8
533 }
534}
535
536#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
537#[repr(u8)]
538pub enum OperationError {
539 Unspecified = 0,
541 Invalidcredential = 1,
543 Disableduserdenied = 2,
545 Restricted = 3,
547 Insufficientbattery = 4,
549}
550
551impl OperationError {
552 pub fn from_u8(value: u8) -> Option<Self> {
554 match value {
555 0 => Some(OperationError::Unspecified),
556 1 => Some(OperationError::Invalidcredential),
557 2 => Some(OperationError::Disableduserdenied),
558 3 => Some(OperationError::Restricted),
559 4 => Some(OperationError::Insufficientbattery),
560 _ => None,
561 }
562 }
563
564 pub fn to_u8(self) -> u8 {
566 self as u8
567 }
568}
569
570impl From<OperationError> for u8 {
571 fn from(val: OperationError) -> Self {
572 val as u8
573 }
574}
575
576#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
577#[repr(u8)]
578pub enum OperationSource {
579 Unspecified = 0,
581 Manual = 1,
583 Proprietaryremote = 2,
585 Keypad = 3,
587 Auto = 4,
589 Button = 5,
591 Schedule = 6,
593 Remote = 7,
595 Rfid = 8,
597 Biometric = 9,
599 Aliro = 10,
601}
602
603impl OperationSource {
604 pub fn from_u8(value: u8) -> Option<Self> {
606 match value {
607 0 => Some(OperationSource::Unspecified),
608 1 => Some(OperationSource::Manual),
609 2 => Some(OperationSource::Proprietaryremote),
610 3 => Some(OperationSource::Keypad),
611 4 => Some(OperationSource::Auto),
612 5 => Some(OperationSource::Button),
613 6 => Some(OperationSource::Schedule),
614 7 => Some(OperationSource::Remote),
615 8 => Some(OperationSource::Rfid),
616 9 => Some(OperationSource::Biometric),
617 10 => Some(OperationSource::Aliro),
618 _ => None,
619 }
620 }
621
622 pub fn to_u8(self) -> u8 {
624 self as u8
625 }
626}
627
628impl From<OperationSource> for u8 {
629 fn from(val: OperationSource) -> Self {
630 val as u8
631 }
632}
633
634#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
635#[repr(u8)]
636pub enum SoundVolume {
637 Silent = 0,
639 Low = 1,
641 High = 2,
643 Medium = 3,
645}
646
647impl SoundVolume {
648 pub fn from_u8(value: u8) -> Option<Self> {
650 match value {
651 0 => Some(SoundVolume::Silent),
652 1 => Some(SoundVolume::Low),
653 2 => Some(SoundVolume::High),
654 3 => Some(SoundVolume::Medium),
655 _ => None,
656 }
657 }
658
659 pub fn to_u8(self) -> u8 {
661 self as u8
662 }
663}
664
665impl From<SoundVolume> for u8 {
666 fn from(val: SoundVolume) -> Self {
667 val as u8
668 }
669}
670
671#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
672#[repr(u8)]
673pub enum StatusCode {
674 Duplicate = 2,
676 Occupied = 3,
678}
679
680impl StatusCode {
681 pub fn from_u8(value: u8) -> Option<Self> {
683 match value {
684 2 => Some(StatusCode::Duplicate),
685 3 => Some(StatusCode::Occupied),
686 _ => None,
687 }
688 }
689
690 pub fn to_u8(self) -> u8 {
692 self as u8
693 }
694}
695
696impl From<StatusCode> for u8 {
697 fn from(val: StatusCode) -> Self {
698 val as u8
699 }
700}
701
702#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
703#[repr(u8)]
704pub enum UserStatus {
705 Available = 0,
707 Occupiedenabled = 1,
709 Occupieddisabled = 3,
711}
712
713impl UserStatus {
714 pub fn from_u8(value: u8) -> Option<Self> {
716 match value {
717 0 => Some(UserStatus::Available),
718 1 => Some(UserStatus::Occupiedenabled),
719 3 => Some(UserStatus::Occupieddisabled),
720 _ => None,
721 }
722 }
723
724 pub fn to_u8(self) -> u8 {
726 self as u8
727 }
728}
729
730impl From<UserStatus> for u8 {
731 fn from(val: UserStatus) -> Self {
732 val as u8
733 }
734}
735
736#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
737#[repr(u8)]
738pub enum UserType {
739 Unrestricteduser = 0,
741 Yeardayscheduleuser = 1,
743 Weekdayscheduleuser = 2,
745 Programminguser = 3,
747 Nonaccessuser = 4,
749 Forceduser = 5,
751 Disposableuser = 6,
753 Expiringuser = 7,
755 Schedulerestricteduser = 8,
757 Remoteonlyuser = 9,
759}
760
761impl UserType {
762 pub fn from_u8(value: u8) -> Option<Self> {
764 match value {
765 0 => Some(UserType::Unrestricteduser),
766 1 => Some(UserType::Yeardayscheduleuser),
767 2 => Some(UserType::Weekdayscheduleuser),
768 3 => Some(UserType::Programminguser),
769 4 => Some(UserType::Nonaccessuser),
770 5 => Some(UserType::Forceduser),
771 6 => Some(UserType::Disposableuser),
772 7 => Some(UserType::Expiringuser),
773 8 => Some(UserType::Schedulerestricteduser),
774 9 => Some(UserType::Remoteonlyuser),
775 _ => None,
776 }
777 }
778
779 pub fn to_u8(self) -> u8 {
781 self as u8
782 }
783}
784
785impl From<UserType> for u8 {
786 fn from(val: UserType) -> Self {
787 val as u8
788 }
789}
790
791pub type AlarmMask = u8;
795
796pub mod alarmmask {
798 pub const LOCK_JAMMED: u8 = 0x01;
800 pub const LOCK_FACTORY_RESET: u8 = 0x02;
802 pub const LOCK_RADIO_POWER_CYCLED: u8 = 0x08;
804 pub const WRONG_CODE_ENTRY_LIMIT: u8 = 0x10;
806 pub const FRONT_ESCUTCHEON_REMOVED: u8 = 0x20;
808 pub const DOOR_FORCED_OPEN: u8 = 0x40;
810}
811
812pub type ConfigurationRegister = u8;
814
815pub mod configurationregister {
817 pub const LOCAL_PROGRAMMING: u8 = 0x01;
819 pub const KEYPAD_INTERFACE: u8 = 0x02;
821 pub const REMOTE_INTERFACE: u8 = 0x04;
823 pub const SOUND_VOLUME: u8 = 0x20;
825 pub const AUTO_RELOCK_TIME: u8 = 0x40;
827 pub const LEDSETTINGS: u8 = 0x80;
829}
830
831pub type CredentialRules = u8;
833
834pub mod credentialrules {
836 pub const SINGLE: u8 = 0x01;
838 pub const DUAL: u8 = 0x02;
840 pub const TRI: u8 = 0x04;
842}
843
844pub type DaysMask = u8;
846
847pub mod daysmask {
849 pub const SUNDAY: u8 = 0x01;
851 pub const MONDAY: u8 = 0x02;
853 pub const TUESDAY: u8 = 0x04;
855 pub const WEDNESDAY: u8 = 0x08;
857 pub const THURSDAY: u8 = 0x10;
859 pub const FRIDAY: u8 = 0x20;
861 pub const SATURDAY: u8 = 0x40;
863}
864
865pub type LocalProgrammingFeatures = u8;
867
868pub mod localprogrammingfeatures {
870 pub const ADD_USERS_CREDENTIALS_SCHEDULES: u8 = 0x01;
872 pub const MODIFY_USERS_CREDENTIALS_SCHEDULES: u8 = 0x02;
874 pub const CLEAR_USERS_CREDENTIALS_SCHEDULES: u8 = 0x04;
876 pub const ADJUST_SETTINGS: u8 = 0x08;
878}
879
880pub type OperatingModes = u8;
882
883pub mod operatingmodes {
885 pub const NORMAL: u8 = 0x01;
887 pub const VACATION: u8 = 0x02;
889 pub const PRIVACY: u8 = 0x04;
891 pub const NO_REMOTE_LOCK_UNLOCK: u8 = 0x08;
893 pub const PASSAGE: u8 = 0x10;
895}
896
897#[derive(Debug, serde::Serialize)]
900pub struct Credential {
901 pub credential_type: Option<CredentialType>,
902 pub credential_index: Option<u16>,
903}
904
905pub fn encode_lock_door(pin_code: Vec<u8>) -> anyhow::Result<Vec<u8>> {
909 let tlv = tlv::TlvItemEnc {
910 tag: 0,
911 value: tlv::TlvItemValueEnc::StructInvisible(vec![
912 (0, tlv::TlvItemValueEnc::OctetString(pin_code)).into(),
913 ]),
914 };
915 Ok(tlv.encode()?)
916}
917
918pub fn encode_unlock_door(pin_code: Vec<u8>) -> anyhow::Result<Vec<u8>> {
920 let tlv = tlv::TlvItemEnc {
921 tag: 0,
922 value: tlv::TlvItemValueEnc::StructInvisible(vec![
923 (0, tlv::TlvItemValueEnc::OctetString(pin_code)).into(),
924 ]),
925 };
926 Ok(tlv.encode()?)
927}
928
929pub fn encode_unlock_with_timeout(timeout: u16, pin_code: Vec<u8>) -> anyhow::Result<Vec<u8>> {
931 let tlv = tlv::TlvItemEnc {
932 tag: 0,
933 value: tlv::TlvItemValueEnc::StructInvisible(vec![
934 (0, tlv::TlvItemValueEnc::UInt16(timeout)).into(),
935 (1, tlv::TlvItemValueEnc::OctetString(pin_code)).into(),
936 ]),
937 };
938 Ok(tlv.encode()?)
939}
940
941pub 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>> {
943 let tlv = tlv::TlvItemEnc {
944 tag: 0,
945 value: tlv::TlvItemValueEnc::StructInvisible(vec![
946 (0, tlv::TlvItemValueEnc::UInt8(week_day_index)).into(),
947 (1, tlv::TlvItemValueEnc::UInt16(user_index)).into(),
948 (2, tlv::TlvItemValueEnc::UInt8(days_mask)).into(),
949 (3, tlv::TlvItemValueEnc::UInt8(start_hour)).into(),
950 (4, tlv::TlvItemValueEnc::UInt8(start_minute)).into(),
951 (5, tlv::TlvItemValueEnc::UInt8(end_hour)).into(),
952 (6, tlv::TlvItemValueEnc::UInt8(end_minute)).into(),
953 ]),
954 };
955 Ok(tlv.encode()?)
956}
957
958pub fn encode_get_week_day_schedule(week_day_index: u8, user_index: u16) -> anyhow::Result<Vec<u8>> {
960 let tlv = tlv::TlvItemEnc {
961 tag: 0,
962 value: tlv::TlvItemValueEnc::StructInvisible(vec![
963 (0, tlv::TlvItemValueEnc::UInt8(week_day_index)).into(),
964 (1, tlv::TlvItemValueEnc::UInt16(user_index)).into(),
965 ]),
966 };
967 Ok(tlv.encode()?)
968}
969
970pub fn encode_clear_week_day_schedule(week_day_index: u8, user_index: u16) -> anyhow::Result<Vec<u8>> {
972 let tlv = tlv::TlvItemEnc {
973 tag: 0,
974 value: tlv::TlvItemValueEnc::StructInvisible(vec![
975 (0, tlv::TlvItemValueEnc::UInt8(week_day_index)).into(),
976 (1, tlv::TlvItemValueEnc::UInt16(user_index)).into(),
977 ]),
978 };
979 Ok(tlv.encode()?)
980}
981
982pub 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>> {
984 let tlv = tlv::TlvItemEnc {
985 tag: 0,
986 value: tlv::TlvItemValueEnc::StructInvisible(vec![
987 (0, tlv::TlvItemValueEnc::UInt8(year_day_index)).into(),
988 (1, tlv::TlvItemValueEnc::UInt16(user_index)).into(),
989 (2, tlv::TlvItemValueEnc::UInt64(local_start_time)).into(),
990 (3, tlv::TlvItemValueEnc::UInt64(local_end_time)).into(),
991 ]),
992 };
993 Ok(tlv.encode()?)
994}
995
996pub fn encode_get_year_day_schedule(year_day_index: u8, user_index: u16) -> anyhow::Result<Vec<u8>> {
998 let tlv = tlv::TlvItemEnc {
999 tag: 0,
1000 value: tlv::TlvItemValueEnc::StructInvisible(vec![
1001 (0, tlv::TlvItemValueEnc::UInt8(year_day_index)).into(),
1002 (1, tlv::TlvItemValueEnc::UInt16(user_index)).into(),
1003 ]),
1004 };
1005 Ok(tlv.encode()?)
1006}
1007
1008pub fn encode_clear_year_day_schedule(year_day_index: u8, user_index: u16) -> anyhow::Result<Vec<u8>> {
1010 let tlv = tlv::TlvItemEnc {
1011 tag: 0,
1012 value: tlv::TlvItemValueEnc::StructInvisible(vec![
1013 (0, tlv::TlvItemValueEnc::UInt8(year_day_index)).into(),
1014 (1, tlv::TlvItemValueEnc::UInt16(user_index)).into(),
1015 ]),
1016 };
1017 Ok(tlv.encode()?)
1018}
1019
1020pub fn encode_set_holiday_schedule(holiday_index: u8, local_start_time: u64, local_end_time: u64, operating_mode: OperatingMode) -> anyhow::Result<Vec<u8>> {
1022 let tlv = tlv::TlvItemEnc {
1023 tag: 0,
1024 value: tlv::TlvItemValueEnc::StructInvisible(vec![
1025 (0, tlv::TlvItemValueEnc::UInt8(holiday_index)).into(),
1026 (1, tlv::TlvItemValueEnc::UInt64(local_start_time)).into(),
1027 (2, tlv::TlvItemValueEnc::UInt64(local_end_time)).into(),
1028 (3, tlv::TlvItemValueEnc::UInt8(operating_mode.to_u8())).into(),
1029 ]),
1030 };
1031 Ok(tlv.encode()?)
1032}
1033
1034pub fn encode_get_holiday_schedule(holiday_index: u8) -> anyhow::Result<Vec<u8>> {
1036 let tlv = tlv::TlvItemEnc {
1037 tag: 0,
1038 value: tlv::TlvItemValueEnc::StructInvisible(vec![
1039 (0, tlv::TlvItemValueEnc::UInt8(holiday_index)).into(),
1040 ]),
1041 };
1042 Ok(tlv.encode()?)
1043}
1044
1045pub fn encode_clear_holiday_schedule(holiday_index: u8) -> anyhow::Result<Vec<u8>> {
1047 let tlv = tlv::TlvItemEnc {
1048 tag: 0,
1049 value: tlv::TlvItemValueEnc::StructInvisible(vec![
1050 (0, tlv::TlvItemValueEnc::UInt8(holiday_index)).into(),
1051 ]),
1052 };
1053 Ok(tlv.encode()?)
1054}
1055
1056pub 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>> {
1058 let tlv = tlv::TlvItemEnc {
1059 tag: 0,
1060 value: tlv::TlvItemValueEnc::StructInvisible(vec![
1061 (0, tlv::TlvItemValueEnc::UInt8(operation_type.to_u8())).into(),
1062 (1, tlv::TlvItemValueEnc::UInt16(user_index)).into(),
1063 (2, tlv::TlvItemValueEnc::String(user_name.unwrap_or("".to_string()))).into(),
1064 (3, tlv::TlvItemValueEnc::UInt32(user_unique_id.unwrap_or(0))).into(),
1065 (4, tlv::TlvItemValueEnc::UInt8(user_status.map(|e| e.to_u8()).unwrap_or(0))).into(),
1066 (5, tlv::TlvItemValueEnc::UInt8(user_type.map(|e| e.to_u8()).unwrap_or(0))).into(),
1067 (6, tlv::TlvItemValueEnc::UInt8(credential_rule.map(|e| e.to_u8()).unwrap_or(0))).into(),
1068 ]),
1069 };
1070 Ok(tlv.encode()?)
1071}
1072
1073pub fn encode_get_user(user_index: u16) -> anyhow::Result<Vec<u8>> {
1075 let tlv = tlv::TlvItemEnc {
1076 tag: 0,
1077 value: tlv::TlvItemValueEnc::StructInvisible(vec![
1078 (0, tlv::TlvItemValueEnc::UInt16(user_index)).into(),
1079 ]),
1080 };
1081 Ok(tlv.encode()?)
1082}
1083
1084pub fn encode_clear_user(user_index: u16) -> anyhow::Result<Vec<u8>> {
1086 let tlv = tlv::TlvItemEnc {
1087 tag: 0,
1088 value: tlv::TlvItemValueEnc::StructInvisible(vec![
1089 (0, tlv::TlvItemValueEnc::UInt16(user_index)).into(),
1090 ]),
1091 };
1092 Ok(tlv.encode()?)
1093}
1094
1095pub 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>> {
1097 let mut credential_fields = Vec::new();
1099 if let Some(x) = credential.credential_type { credential_fields.push((0, tlv::TlvItemValueEnc::UInt8(x.to_u8())).into()); }
1100 if let Some(x) = credential.credential_index { credential_fields.push((1, tlv::TlvItemValueEnc::UInt16(x)).into()); }
1101 let tlv = tlv::TlvItemEnc {
1102 tag: 0,
1103 value: tlv::TlvItemValueEnc::StructInvisible(vec![
1104 (0, tlv::TlvItemValueEnc::UInt8(operation_type.to_u8())).into(),
1105 (1, tlv::TlvItemValueEnc::StructInvisible(credential_fields)).into(),
1106 (2, tlv::TlvItemValueEnc::OctetString(credential_data)).into(),
1107 (3, tlv::TlvItemValueEnc::UInt16(user_index.unwrap_or(0))).into(),
1108 (4, tlv::TlvItemValueEnc::UInt8(user_status.map(|e| e.to_u8()).unwrap_or(0))).into(),
1109 (5, tlv::TlvItemValueEnc::UInt8(user_type.map(|e| e.to_u8()).unwrap_or(0))).into(),
1110 ]),
1111 };
1112 Ok(tlv.encode()?)
1113}
1114
1115pub fn encode_get_credential_status(credential: Credential) -> anyhow::Result<Vec<u8>> {
1117 let mut credential_fields = Vec::new();
1119 if let Some(x) = credential.credential_type { credential_fields.push((0, tlv::TlvItemValueEnc::UInt8(x.to_u8())).into()); }
1120 if let Some(x) = credential.credential_index { credential_fields.push((1, tlv::TlvItemValueEnc::UInt16(x)).into()); }
1121 let tlv = tlv::TlvItemEnc {
1122 tag: 0,
1123 value: tlv::TlvItemValueEnc::StructInvisible(vec![
1124 (0, tlv::TlvItemValueEnc::StructInvisible(credential_fields)).into(),
1125 ]),
1126 };
1127 Ok(tlv.encode()?)
1128}
1129
1130pub fn encode_clear_credential(credential: Option<Credential>) -> anyhow::Result<Vec<u8>> {
1132 let credential_enc = if let Some(s) = credential {
1134 let mut fields = Vec::new();
1135 if let Some(x) = s.credential_type { fields.push((0, tlv::TlvItemValueEnc::UInt8(x.to_u8())).into()); }
1136 if let Some(x) = s.credential_index { fields.push((1, tlv::TlvItemValueEnc::UInt16(x)).into()); }
1137 tlv::TlvItemValueEnc::StructInvisible(fields)
1138 } else {
1139 tlv::TlvItemValueEnc::StructInvisible(Vec::new())
1140 };
1141 let tlv = tlv::TlvItemEnc {
1142 tag: 0,
1143 value: tlv::TlvItemValueEnc::StructInvisible(vec![
1144 (0, credential_enc).into(),
1145 ]),
1146 };
1147 Ok(tlv.encode()?)
1148}
1149
1150pub fn encode_unbolt_door(pin_code: Vec<u8>) -> anyhow::Result<Vec<u8>> {
1152 let tlv = tlv::TlvItemEnc {
1153 tag: 0,
1154 value: tlv::TlvItemValueEnc::StructInvisible(vec![
1155 (0, tlv::TlvItemValueEnc::OctetString(pin_code)).into(),
1156 ]),
1157 };
1158 Ok(tlv.encode()?)
1159}
1160
1161pub 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>> {
1163 let tlv = tlv::TlvItemEnc {
1164 tag: 0,
1165 value: tlv::TlvItemValueEnc::StructInvisible(vec![
1166 (0, tlv::TlvItemValueEnc::OctetString(signing_key)).into(),
1167 (1, tlv::TlvItemValueEnc::OctetString(verification_key)).into(),
1168 (2, tlv::TlvItemValueEnc::OctetString(group_identifier)).into(),
1169 (3, tlv::TlvItemValueEnc::OctetString(group_resolving_key)).into(),
1170 ]),
1171 };
1172 Ok(tlv.encode()?)
1173}
1174
1175pub fn decode_lock_state(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<LockState>> {
1179 if let tlv::TlvItemValue::Int(v) = inp {
1180 Ok(LockState::from_u8(*v as u8))
1181 } else {
1182 Ok(None)
1183 }
1184}
1185
1186pub fn decode_lock_type(inp: &tlv::TlvItemValue) -> anyhow::Result<LockType> {
1188 if let tlv::TlvItemValue::Int(v) = inp {
1189 LockType::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
1190 } else {
1191 Err(anyhow::anyhow!("Expected Integer"))
1192 }
1193}
1194
1195pub fn decode_actuator_enabled(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
1197 if let tlv::TlvItemValue::Bool(v) = inp {
1198 Ok(*v)
1199 } else {
1200 Err(anyhow::anyhow!("Expected Bool"))
1201 }
1202}
1203
1204pub fn decode_door_state(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<DoorState>> {
1206 if let tlv::TlvItemValue::Int(v) = inp {
1207 Ok(DoorState::from_u8(*v as u8))
1208 } else {
1209 Ok(None)
1210 }
1211}
1212
1213pub fn decode_door_open_events(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
1215 if let tlv::TlvItemValue::Int(v) = inp {
1216 Ok(*v as u32)
1217 } else {
1218 Err(anyhow::anyhow!("Expected UInt32"))
1219 }
1220}
1221
1222pub fn decode_door_closed_events(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
1224 if let tlv::TlvItemValue::Int(v) = inp {
1225 Ok(*v as u32)
1226 } else {
1227 Err(anyhow::anyhow!("Expected UInt32"))
1228 }
1229}
1230
1231pub fn decode_open_period(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
1233 if let tlv::TlvItemValue::Int(v) = inp {
1234 Ok(*v as u16)
1235 } else {
1236 Err(anyhow::anyhow!("Expected UInt16"))
1237 }
1238}
1239
1240pub fn decode_number_of_total_users_supported(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
1242 if let tlv::TlvItemValue::Int(v) = inp {
1243 Ok(*v as u16)
1244 } else {
1245 Err(anyhow::anyhow!("Expected UInt16"))
1246 }
1247}
1248
1249pub fn decode_number_of_pin_users_supported(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
1251 if let tlv::TlvItemValue::Int(v) = inp {
1252 Ok(*v as u16)
1253 } else {
1254 Err(anyhow::anyhow!("Expected UInt16"))
1255 }
1256}
1257
1258pub fn decode_number_of_rfid_users_supported(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
1260 if let tlv::TlvItemValue::Int(v) = inp {
1261 Ok(*v as u16)
1262 } else {
1263 Err(anyhow::anyhow!("Expected UInt16"))
1264 }
1265}
1266
1267pub fn decode_number_of_week_day_schedules_supported_per_user(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
1269 if let tlv::TlvItemValue::Int(v) = inp {
1270 Ok(*v as u8)
1271 } else {
1272 Err(anyhow::anyhow!("Expected UInt8"))
1273 }
1274}
1275
1276pub fn decode_number_of_year_day_schedules_supported_per_user(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
1278 if let tlv::TlvItemValue::Int(v) = inp {
1279 Ok(*v as u8)
1280 } else {
1281 Err(anyhow::anyhow!("Expected UInt8"))
1282 }
1283}
1284
1285pub fn decode_number_of_holiday_schedules_supported(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
1287 if let tlv::TlvItemValue::Int(v) = inp {
1288 Ok(*v as u8)
1289 } else {
1290 Err(anyhow::anyhow!("Expected UInt8"))
1291 }
1292}
1293
1294pub fn decode_max_pin_code_length(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
1296 if let tlv::TlvItemValue::Int(v) = inp {
1297 Ok(*v as u8)
1298 } else {
1299 Err(anyhow::anyhow!("Expected UInt8"))
1300 }
1301}
1302
1303pub fn decode_min_pin_code_length(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
1305 if let tlv::TlvItemValue::Int(v) = inp {
1306 Ok(*v as u8)
1307 } else {
1308 Err(anyhow::anyhow!("Expected UInt8"))
1309 }
1310}
1311
1312pub fn decode_max_rfid_code_length(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
1314 if let tlv::TlvItemValue::Int(v) = inp {
1315 Ok(*v as u8)
1316 } else {
1317 Err(anyhow::anyhow!("Expected UInt8"))
1318 }
1319}
1320
1321pub fn decode_min_rfid_code_length(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
1323 if let tlv::TlvItemValue::Int(v) = inp {
1324 Ok(*v as u8)
1325 } else {
1326 Err(anyhow::anyhow!("Expected UInt8"))
1327 }
1328}
1329
1330pub fn decode_credential_rules_support(inp: &tlv::TlvItemValue) -> anyhow::Result<CredentialRules> {
1332 if let tlv::TlvItemValue::Int(v) = inp {
1333 Ok(*v as u8)
1334 } else {
1335 Err(anyhow::anyhow!("Expected Integer"))
1336 }
1337}
1338
1339pub fn decode_number_of_credentials_supported_per_user(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
1341 if let tlv::TlvItemValue::Int(v) = inp {
1342 Ok(*v as u8)
1343 } else {
1344 Err(anyhow::anyhow!("Expected UInt8"))
1345 }
1346}
1347
1348pub fn decode_language(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
1350 if let tlv::TlvItemValue::String(v) = inp {
1351 Ok(v.clone())
1352 } else {
1353 Err(anyhow::anyhow!("Expected String"))
1354 }
1355}
1356
1357pub fn decode_led_settings(inp: &tlv::TlvItemValue) -> anyhow::Result<LEDSetting> {
1359 if let tlv::TlvItemValue::Int(v) = inp {
1360 LEDSetting::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
1361 } else {
1362 Err(anyhow::anyhow!("Expected Integer"))
1363 }
1364}
1365
1366pub fn decode_auto_relock_time(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
1368 if let tlv::TlvItemValue::Int(v) = inp {
1369 Ok(*v as u32)
1370 } else {
1371 Err(anyhow::anyhow!("Expected UInt32"))
1372 }
1373}
1374
1375pub fn decode_sound_volume(inp: &tlv::TlvItemValue) -> anyhow::Result<SoundVolume> {
1377 if let tlv::TlvItemValue::Int(v) = inp {
1378 SoundVolume::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
1379 } else {
1380 Err(anyhow::anyhow!("Expected Integer"))
1381 }
1382}
1383
1384pub fn decode_operating_mode(inp: &tlv::TlvItemValue) -> anyhow::Result<OperatingMode> {
1386 if let tlv::TlvItemValue::Int(v) = inp {
1387 OperatingMode::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
1388 } else {
1389 Err(anyhow::anyhow!("Expected Integer"))
1390 }
1391}
1392
1393pub fn decode_supported_operating_modes(inp: &tlv::TlvItemValue) -> anyhow::Result<OperatingModes> {
1395 if let tlv::TlvItemValue::Int(v) = inp {
1396 Ok(*v as u8)
1397 } else {
1398 Err(anyhow::anyhow!("Expected Integer"))
1399 }
1400}
1401
1402pub fn decode_default_configuration_register(inp: &tlv::TlvItemValue) -> anyhow::Result<ConfigurationRegister> {
1404 if let tlv::TlvItemValue::Int(v) = inp {
1405 Ok(*v as u8)
1406 } else {
1407 Err(anyhow::anyhow!("Expected Integer"))
1408 }
1409}
1410
1411pub fn decode_enable_local_programming(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
1413 if let tlv::TlvItemValue::Bool(v) = inp {
1414 Ok(*v)
1415 } else {
1416 Err(anyhow::anyhow!("Expected Bool"))
1417 }
1418}
1419
1420pub fn decode_enable_one_touch_locking(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
1422 if let tlv::TlvItemValue::Bool(v) = inp {
1423 Ok(*v)
1424 } else {
1425 Err(anyhow::anyhow!("Expected Bool"))
1426 }
1427}
1428
1429pub fn decode_enable_inside_status_led(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
1431 if let tlv::TlvItemValue::Bool(v) = inp {
1432 Ok(*v)
1433 } else {
1434 Err(anyhow::anyhow!("Expected Bool"))
1435 }
1436}
1437
1438pub fn decode_enable_privacy_mode_button(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
1440 if let tlv::TlvItemValue::Bool(v) = inp {
1441 Ok(*v)
1442 } else {
1443 Err(anyhow::anyhow!("Expected Bool"))
1444 }
1445}
1446
1447pub fn decode_local_programming_features(inp: &tlv::TlvItemValue) -> anyhow::Result<LocalProgrammingFeatures> {
1449 if let tlv::TlvItemValue::Int(v) = inp {
1450 Ok(*v as u8)
1451 } else {
1452 Err(anyhow::anyhow!("Expected Integer"))
1453 }
1454}
1455
1456pub fn decode_wrong_code_entry_limit(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
1458 if let tlv::TlvItemValue::Int(v) = inp {
1459 Ok(*v as u8)
1460 } else {
1461 Err(anyhow::anyhow!("Expected UInt8"))
1462 }
1463}
1464
1465pub fn decode_user_code_temporary_disable_time(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
1467 if let tlv::TlvItemValue::Int(v) = inp {
1468 Ok(*v as u8)
1469 } else {
1470 Err(anyhow::anyhow!("Expected UInt8"))
1471 }
1472}
1473
1474pub fn decode_send_pin_over_the_air(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
1476 if let tlv::TlvItemValue::Bool(v) = inp {
1477 Ok(*v)
1478 } else {
1479 Err(anyhow::anyhow!("Expected Bool"))
1480 }
1481}
1482
1483pub fn decode_require_pinfor_remote_operation(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
1485 if let tlv::TlvItemValue::Bool(v) = inp {
1486 Ok(*v)
1487 } else {
1488 Err(anyhow::anyhow!("Expected Bool"))
1489 }
1490}
1491
1492pub fn decode_security_level(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
1494 if let tlv::TlvItemValue::Int(v) = inp {
1495 Ok(*v as u8)
1496 } else {
1497 Err(anyhow::anyhow!("Expected UInt8"))
1498 }
1499}
1500
1501pub fn decode_expiring_user_timeout(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
1503 if let tlv::TlvItemValue::Int(v) = inp {
1504 Ok(*v as u16)
1505 } else {
1506 Err(anyhow::anyhow!("Expected UInt16"))
1507 }
1508}
1509
1510pub fn decode_aliro_reader_verification_key(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<Vec<u8>>> {
1512 if let tlv::TlvItemValue::OctetString(v) = inp {
1513 Ok(Some(v.clone()))
1514 } else {
1515 Ok(None)
1516 }
1517}
1518
1519pub fn decode_aliro_reader_group_identifier(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<Vec<u8>>> {
1521 if let tlv::TlvItemValue::OctetString(v) = inp {
1522 Ok(Some(v.clone()))
1523 } else {
1524 Ok(None)
1525 }
1526}
1527
1528pub fn decode_aliro_reader_group_sub_identifier(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<u8>> {
1530 if let tlv::TlvItemValue::OctetString(v) = inp {
1531 Ok(v.clone())
1532 } else {
1533 Err(anyhow::anyhow!("Expected OctetString"))
1534 }
1535}
1536
1537pub fn decode_aliro_expedited_transaction_supported_protocol_versions(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<Vec<u8>>> {
1539 let mut res = Vec::new();
1540 if let tlv::TlvItemValue::List(v) = inp {
1541 for item in v {
1542 if let tlv::TlvItemValue::OctetString(o) = &item.value {
1543 res.push(o.clone());
1544 }
1545 }
1546 }
1547 Ok(res)
1548}
1549
1550pub fn decode_aliro_group_resolving_key(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<Vec<u8>>> {
1552 if let tlv::TlvItemValue::OctetString(v) = inp {
1553 Ok(Some(v.clone()))
1554 } else {
1555 Ok(None)
1556 }
1557}
1558
1559pub fn decode_aliro_supported_bleuwb_protocol_versions(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<Vec<u8>>> {
1561 let mut res = Vec::new();
1562 if let tlv::TlvItemValue::List(v) = inp {
1563 for item in v {
1564 if let tlv::TlvItemValue::OctetString(o) = &item.value {
1565 res.push(o.clone());
1566 }
1567 }
1568 }
1569 Ok(res)
1570}
1571
1572pub fn decode_aliro_ble_advertising_version(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
1574 if let tlv::TlvItemValue::Int(v) = inp {
1575 Ok(*v as u8)
1576 } else {
1577 Err(anyhow::anyhow!("Expected UInt8"))
1578 }
1579}
1580
1581pub fn decode_number_of_aliro_credential_issuer_keys_supported(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
1583 if let tlv::TlvItemValue::Int(v) = inp {
1584 Ok(*v as u16)
1585 } else {
1586 Err(anyhow::anyhow!("Expected UInt16"))
1587 }
1588}
1589
1590pub fn decode_number_of_aliro_endpoint_keys_supported(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
1592 if let tlv::TlvItemValue::Int(v) = inp {
1593 Ok(*v as u16)
1594 } else {
1595 Err(anyhow::anyhow!("Expected UInt16"))
1596 }
1597}
1598
1599
1600pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
1612 if cluster_id != 0x0101 {
1614 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0101, got {}\"}}", cluster_id);
1615 }
1616
1617 match attribute_id {
1618 0x0000 => {
1619 match decode_lock_state(tlv_value) {
1620 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1621 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1622 }
1623 }
1624 0x0001 => {
1625 match decode_lock_type(tlv_value) {
1626 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1627 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1628 }
1629 }
1630 0x0002 => {
1631 match decode_actuator_enabled(tlv_value) {
1632 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1633 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1634 }
1635 }
1636 0x0003 => {
1637 match decode_door_state(tlv_value) {
1638 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1639 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1640 }
1641 }
1642 0x0004 => {
1643 match decode_door_open_events(tlv_value) {
1644 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1645 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1646 }
1647 }
1648 0x0005 => {
1649 match decode_door_closed_events(tlv_value) {
1650 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1651 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1652 }
1653 }
1654 0x0006 => {
1655 match decode_open_period(tlv_value) {
1656 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1657 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1658 }
1659 }
1660 0x0011 => {
1661 match decode_number_of_total_users_supported(tlv_value) {
1662 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1663 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1664 }
1665 }
1666 0x0012 => {
1667 match decode_number_of_pin_users_supported(tlv_value) {
1668 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1669 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1670 }
1671 }
1672 0x0013 => {
1673 match decode_number_of_rfid_users_supported(tlv_value) {
1674 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1675 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1676 }
1677 }
1678 0x0014 => {
1679 match decode_number_of_week_day_schedules_supported_per_user(tlv_value) {
1680 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1681 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1682 }
1683 }
1684 0x0015 => {
1685 match decode_number_of_year_day_schedules_supported_per_user(tlv_value) {
1686 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1687 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1688 }
1689 }
1690 0x0016 => {
1691 match decode_number_of_holiday_schedules_supported(tlv_value) {
1692 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1693 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1694 }
1695 }
1696 0x0017 => {
1697 match decode_max_pin_code_length(tlv_value) {
1698 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1699 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1700 }
1701 }
1702 0x0018 => {
1703 match decode_min_pin_code_length(tlv_value) {
1704 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1705 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1706 }
1707 }
1708 0x0019 => {
1709 match decode_max_rfid_code_length(tlv_value) {
1710 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1711 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1712 }
1713 }
1714 0x001A => {
1715 match decode_min_rfid_code_length(tlv_value) {
1716 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1717 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1718 }
1719 }
1720 0x001B => {
1721 match decode_credential_rules_support(tlv_value) {
1722 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1723 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1724 }
1725 }
1726 0x001C => {
1727 match decode_number_of_credentials_supported_per_user(tlv_value) {
1728 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1729 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1730 }
1731 }
1732 0x0021 => {
1733 match decode_language(tlv_value) {
1734 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1735 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1736 }
1737 }
1738 0x0022 => {
1739 match decode_led_settings(tlv_value) {
1740 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1741 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1742 }
1743 }
1744 0x0023 => {
1745 match decode_auto_relock_time(tlv_value) {
1746 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1747 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1748 }
1749 }
1750 0x0024 => {
1751 match decode_sound_volume(tlv_value) {
1752 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1753 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1754 }
1755 }
1756 0x0025 => {
1757 match decode_operating_mode(tlv_value) {
1758 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1759 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1760 }
1761 }
1762 0x0026 => {
1763 match decode_supported_operating_modes(tlv_value) {
1764 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1765 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1766 }
1767 }
1768 0x0027 => {
1769 match decode_default_configuration_register(tlv_value) {
1770 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1771 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1772 }
1773 }
1774 0x0028 => {
1775 match decode_enable_local_programming(tlv_value) {
1776 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1777 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1778 }
1779 }
1780 0x0029 => {
1781 match decode_enable_one_touch_locking(tlv_value) {
1782 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1783 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1784 }
1785 }
1786 0x002A => {
1787 match decode_enable_inside_status_led(tlv_value) {
1788 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1789 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1790 }
1791 }
1792 0x002B => {
1793 match decode_enable_privacy_mode_button(tlv_value) {
1794 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1795 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1796 }
1797 }
1798 0x002C => {
1799 match decode_local_programming_features(tlv_value) {
1800 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1801 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1802 }
1803 }
1804 0x0030 => {
1805 match decode_wrong_code_entry_limit(tlv_value) {
1806 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1807 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1808 }
1809 }
1810 0x0031 => {
1811 match decode_user_code_temporary_disable_time(tlv_value) {
1812 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1813 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1814 }
1815 }
1816 0x0032 => {
1817 match decode_send_pin_over_the_air(tlv_value) {
1818 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1819 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1820 }
1821 }
1822 0x0033 => {
1823 match decode_require_pinfor_remote_operation(tlv_value) {
1824 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1825 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1826 }
1827 }
1828 0x0034 => {
1829 match decode_security_level(tlv_value) {
1830 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1831 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1832 }
1833 }
1834 0x0035 => {
1835 match decode_expiring_user_timeout(tlv_value) {
1836 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1837 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1838 }
1839 }
1840 0x0080 => {
1841 match decode_aliro_reader_verification_key(tlv_value) {
1842 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1843 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1844 }
1845 }
1846 0x0081 => {
1847 match decode_aliro_reader_group_identifier(tlv_value) {
1848 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1849 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1850 }
1851 }
1852 0x0082 => {
1853 match decode_aliro_reader_group_sub_identifier(tlv_value) {
1854 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1855 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1856 }
1857 }
1858 0x0083 => {
1859 match decode_aliro_expedited_transaction_supported_protocol_versions(tlv_value) {
1860 Ok(value) => {
1861 let hex_array: Vec<String> = value.iter()
1863 .map(|bytes| bytes.iter()
1864 .map(|byte| format!("{:02x}", byte))
1865 .collect::<String>())
1866 .collect();
1867 serde_json::to_string(&hex_array).unwrap_or_else(|_| "null".to_string())
1868 },
1869 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1870 }
1871 }
1872 0x0084 => {
1873 match decode_aliro_group_resolving_key(tlv_value) {
1874 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1875 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1876 }
1877 }
1878 0x0085 => {
1879 match decode_aliro_supported_bleuwb_protocol_versions(tlv_value) {
1880 Ok(value) => {
1881 let hex_array: Vec<String> = value.iter()
1883 .map(|bytes| bytes.iter()
1884 .map(|byte| format!("{:02x}", byte))
1885 .collect::<String>())
1886 .collect();
1887 serde_json::to_string(&hex_array).unwrap_or_else(|_| "null".to_string())
1888 },
1889 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1890 }
1891 }
1892 0x0086 => {
1893 match decode_aliro_ble_advertising_version(tlv_value) {
1894 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1895 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1896 }
1897 }
1898 0x0087 => {
1899 match decode_number_of_aliro_credential_issuer_keys_supported(tlv_value) {
1900 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1901 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1902 }
1903 }
1904 0x0088 => {
1905 match decode_number_of_aliro_endpoint_keys_supported(tlv_value) {
1906 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
1907 Err(e) => format!("{{\"error\": \"{}\"}}", e),
1908 }
1909 }
1910 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
1911 }
1912}
1913
1914pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
1919 vec![
1920 (0x0000, "LockState"),
1921 (0x0001, "LockType"),
1922 (0x0002, "ActuatorEnabled"),
1923 (0x0003, "DoorState"),
1924 (0x0004, "DoorOpenEvents"),
1925 (0x0005, "DoorClosedEvents"),
1926 (0x0006, "OpenPeriod"),
1927 (0x0011, "NumberOfTotalUsersSupported"),
1928 (0x0012, "NumberOfPINUsersSupported"),
1929 (0x0013, "NumberOfRFIDUsersSupported"),
1930 (0x0014, "NumberOfWeekDaySchedulesSupportedPerUser"),
1931 (0x0015, "NumberOfYearDaySchedulesSupportedPerUser"),
1932 (0x0016, "NumberOfHolidaySchedulesSupported"),
1933 (0x0017, "MaxPINCodeLength"),
1934 (0x0018, "MinPINCodeLength"),
1935 (0x0019, "MaxRFIDCodeLength"),
1936 (0x001A, "MinRFIDCodeLength"),
1937 (0x001B, "CredentialRulesSupport"),
1938 (0x001C, "NumberOfCredentialsSupportedPerUser"),
1939 (0x0021, "Language"),
1940 (0x0022, "LEDSettings"),
1941 (0x0023, "AutoRelockTime"),
1942 (0x0024, "SoundVolume"),
1943 (0x0025, "OperatingMode"),
1944 (0x0026, "SupportedOperatingModes"),
1945 (0x0027, "DefaultConfigurationRegister"),
1946 (0x0028, "EnableLocalProgramming"),
1947 (0x0029, "EnableOneTouchLocking"),
1948 (0x002A, "EnableInsideStatusLED"),
1949 (0x002B, "EnablePrivacyModeButton"),
1950 (0x002C, "LocalProgrammingFeatures"),
1951 (0x0030, "WrongCodeEntryLimit"),
1952 (0x0031, "UserCodeTemporaryDisableTime"),
1953 (0x0032, "SendPINOverTheAir"),
1954 (0x0033, "RequirePINforRemoteOperation"),
1955 (0x0034, "SecurityLevel"),
1956 (0x0035, "ExpiringUserTimeout"),
1957 (0x0080, "AliroReaderVerificationKey"),
1958 (0x0081, "AliroReaderGroupIdentifier"),
1959 (0x0082, "AliroReaderGroupSubIdentifier"),
1960 (0x0083, "AliroExpeditedTransactionSupportedProtocolVersions"),
1961 (0x0084, "AliroGroupResolvingKey"),
1962 (0x0085, "AliroSupportedBLEUWBProtocolVersions"),
1963 (0x0086, "AliroBLEAdvertisingVersion"),
1964 (0x0087, "NumberOfAliroCredentialIssuerKeysSupported"),
1965 (0x0088, "NumberOfAliroEndpointKeysSupported"),
1966 ]
1967}
1968
1969#[derive(Debug, serde::Serialize)]
1970pub struct GetWeekDayScheduleResponse {
1971 pub week_day_index: Option<u8>,
1972 pub user_index: Option<u16>,
1973 pub status: Option<u8>,
1974 pub days_mask: Option<DaysMask>,
1975 pub start_hour: Option<u8>,
1976 pub start_minute: Option<u8>,
1977 pub end_hour: Option<u8>,
1978 pub end_minute: Option<u8>,
1979}
1980
1981#[derive(Debug, serde::Serialize)]
1982pub struct GetYearDayScheduleResponse {
1983 pub year_day_index: Option<u8>,
1984 pub user_index: Option<u16>,
1985 pub status: Option<u8>,
1986 pub local_start_time: Option<u64>,
1987 pub local_end_time: Option<u64>,
1988}
1989
1990#[derive(Debug, serde::Serialize)]
1991pub struct GetHolidayScheduleResponse {
1992 pub holiday_index: Option<u8>,
1993 pub status: Option<u8>,
1994 pub local_start_time: Option<u64>,
1995 pub local_end_time: Option<u64>,
1996 pub operating_mode: Option<OperatingMode>,
1997}
1998
1999#[derive(Debug, serde::Serialize)]
2000pub struct GetUserResponse {
2001 pub user_index: Option<u16>,
2002 pub user_name: Option<String>,
2003 pub user_unique_id: Option<u32>,
2004 pub user_status: Option<UserStatus>,
2005 pub user_type: Option<UserType>,
2006 pub credential_rule: Option<CredentialRule>,
2007 pub credentials: Option<Vec<Credential>>,
2008 pub creator_fabric_index: Option<u8>,
2009 pub last_modified_fabric_index: Option<u8>,
2010 pub next_user_index: Option<u16>,
2011}
2012
2013#[derive(Debug, serde::Serialize)]
2014pub struct SetCredentialResponse {
2015 pub status: Option<u8>,
2016 pub user_index: Option<u16>,
2017 pub next_credential_index: Option<u16>,
2018}
2019
2020#[derive(Debug, serde::Serialize)]
2021pub struct GetCredentialStatusResponse {
2022 pub credential_exists: Option<bool>,
2023 pub user_index: Option<u16>,
2024 pub creator_fabric_index: Option<u8>,
2025 pub last_modified_fabric_index: Option<u8>,
2026 pub next_credential_index: Option<u16>,
2027 #[serde(serialize_with = "serialize_opt_bytes_as_hex")]
2028 pub credential_data: Option<Vec<u8>>,
2029}
2030
2031pub fn decode_get_week_day_schedule_response(inp: &tlv::TlvItemValue) -> anyhow::Result<GetWeekDayScheduleResponse> {
2035 if let tlv::TlvItemValue::List(_fields) = inp {
2036 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
2037 Ok(GetWeekDayScheduleResponse {
2038 week_day_index: item.get_int(&[0]).map(|v| v as u8),
2039 user_index: item.get_int(&[1]).map(|v| v as u16),
2040 status: item.get_int(&[2]).map(|v| v as u8),
2041 days_mask: item.get_int(&[3]).map(|v| v as u8),
2042 start_hour: item.get_int(&[4]).map(|v| v as u8),
2043 start_minute: item.get_int(&[5]).map(|v| v as u8),
2044 end_hour: item.get_int(&[6]).map(|v| v as u8),
2045 end_minute: item.get_int(&[7]).map(|v| v as u8),
2046 })
2047 } else {
2048 Err(anyhow::anyhow!("Expected struct fields"))
2049 }
2050}
2051
2052pub fn decode_get_year_day_schedule_response(inp: &tlv::TlvItemValue) -> anyhow::Result<GetYearDayScheduleResponse> {
2054 if let tlv::TlvItemValue::List(_fields) = inp {
2055 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
2056 Ok(GetYearDayScheduleResponse {
2057 year_day_index: item.get_int(&[0]).map(|v| v as u8),
2058 user_index: item.get_int(&[1]).map(|v| v as u16),
2059 status: item.get_int(&[2]).map(|v| v as u8),
2060 local_start_time: item.get_int(&[3]),
2061 local_end_time: item.get_int(&[4]),
2062 })
2063 } else {
2064 Err(anyhow::anyhow!("Expected struct fields"))
2065 }
2066}
2067
2068pub fn decode_get_holiday_schedule_response(inp: &tlv::TlvItemValue) -> anyhow::Result<GetHolidayScheduleResponse> {
2070 if let tlv::TlvItemValue::List(_fields) = inp {
2071 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
2072 Ok(GetHolidayScheduleResponse {
2073 holiday_index: item.get_int(&[0]).map(|v| v as u8),
2074 status: item.get_int(&[1]).map(|v| v as u8),
2075 local_start_time: item.get_int(&[2]),
2076 local_end_time: item.get_int(&[3]),
2077 operating_mode: item.get_int(&[4]).and_then(|v| OperatingMode::from_u8(v as u8)),
2078 })
2079 } else {
2080 Err(anyhow::anyhow!("Expected struct fields"))
2081 }
2082}
2083
2084pub fn decode_get_user_response(inp: &tlv::TlvItemValue) -> anyhow::Result<GetUserResponse> {
2086 if let tlv::TlvItemValue::List(_fields) = inp {
2087 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
2088 Ok(GetUserResponse {
2089 user_index: item.get_int(&[0]).map(|v| v as u16),
2090 user_name: item.get_string_owned(&[1]),
2091 user_unique_id: item.get_int(&[2]).map(|v| v as u32),
2092 user_status: item.get_int(&[3]).and_then(|v| UserStatus::from_u8(v as u8)),
2093 user_type: item.get_int(&[4]).and_then(|v| UserType::from_u8(v as u8)),
2094 credential_rule: item.get_int(&[5]).and_then(|v| CredentialRule::from_u8(v as u8)),
2095 credentials: {
2096 if let Some(tlv::TlvItemValue::List(l)) = item.get(&[6]) {
2097 let mut items = Vec::new();
2098 for list_item in l {
2099 items.push(Credential {
2100 credential_type: list_item.get_int(&[0]).and_then(|v| CredentialType::from_u8(v as u8)),
2101 credential_index: list_item.get_int(&[1]).map(|v| v as u16),
2102 });
2103 }
2104 Some(items)
2105 } else {
2106 None
2107 }
2108 },
2109 creator_fabric_index: item.get_int(&[7]).map(|v| v as u8),
2110 last_modified_fabric_index: item.get_int(&[8]).map(|v| v as u8),
2111 next_user_index: item.get_int(&[9]).map(|v| v as u16),
2112 })
2113 } else {
2114 Err(anyhow::anyhow!("Expected struct fields"))
2115 }
2116}
2117
2118pub fn decode_set_credential_response(inp: &tlv::TlvItemValue) -> anyhow::Result<SetCredentialResponse> {
2120 if let tlv::TlvItemValue::List(_fields) = inp {
2121 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
2122 Ok(SetCredentialResponse {
2123 status: item.get_int(&[0]).map(|v| v as u8),
2124 user_index: item.get_int(&[1]).map(|v| v as u16),
2125 next_credential_index: item.get_int(&[2]).map(|v| v as u16),
2126 })
2127 } else {
2128 Err(anyhow::anyhow!("Expected struct fields"))
2129 }
2130}
2131
2132pub fn decode_get_credential_status_response(inp: &tlv::TlvItemValue) -> anyhow::Result<GetCredentialStatusResponse> {
2134 if let tlv::TlvItemValue::List(_fields) = inp {
2135 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
2136 Ok(GetCredentialStatusResponse {
2137 credential_exists: item.get_bool(&[0]),
2138 user_index: item.get_int(&[1]).map(|v| v as u16),
2139 creator_fabric_index: item.get_int(&[2]).map(|v| v as u8),
2140 last_modified_fabric_index: item.get_int(&[3]).map(|v| v as u8),
2141 next_credential_index: item.get_int(&[4]).map(|v| v as u16),
2142 credential_data: item.get_octet_string_owned(&[5]),
2143 })
2144 } else {
2145 Err(anyhow::anyhow!("Expected struct fields"))
2146 }
2147}
2148
2149#[derive(Debug, serde::Serialize)]
2150pub struct DoorLockAlarmEvent {
2151 pub alarm_code: Option<AlarmCode>,
2152}
2153
2154#[derive(Debug, serde::Serialize)]
2155pub struct DoorStateChangeEvent {
2156 pub door_state: Option<DoorState>,
2157}
2158
2159#[derive(Debug, serde::Serialize)]
2160pub struct LockOperationEvent {
2161 pub lock_operation_type: Option<LockOperationType>,
2162 pub operation_source: Option<OperationSource>,
2163 pub user_index: Option<u16>,
2164 pub fabric_index: Option<u8>,
2165 pub source_node: Option<u64>,
2166 pub credentials: Option<Vec<Credential>>,
2167}
2168
2169#[derive(Debug, serde::Serialize)]
2170pub struct LockOperationErrorEvent {
2171 pub lock_operation_type: Option<LockOperationType>,
2172 pub operation_source: Option<OperationSource>,
2173 pub operation_error: Option<OperationError>,
2174 pub user_index: Option<u16>,
2175 pub fabric_index: Option<u8>,
2176 pub source_node: Option<u64>,
2177 pub credentials: Option<Vec<Credential>>,
2178}
2179
2180#[derive(Debug, serde::Serialize)]
2181pub struct LockUserChangeEvent {
2182 pub lock_data_type: Option<LockDataType>,
2183 pub data_operation_type: Option<DataOperationType>,
2184 pub operation_source: Option<OperationSource>,
2185 pub user_index: Option<u16>,
2186 pub fabric_index: Option<u8>,
2187 pub source_node: Option<u64>,
2188 pub data_index: Option<u16>,
2189}
2190
2191pub fn decode_door_lock_alarm_event(inp: &tlv::TlvItemValue) -> anyhow::Result<DoorLockAlarmEvent> {
2195 if let tlv::TlvItemValue::List(_fields) = inp {
2196 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
2197 Ok(DoorLockAlarmEvent {
2198 alarm_code: item.get_int(&[0]).and_then(|v| AlarmCode::from_u8(v as u8)),
2199 })
2200 } else {
2201 Err(anyhow::anyhow!("Expected struct fields"))
2202 }
2203}
2204
2205pub fn decode_door_state_change_event(inp: &tlv::TlvItemValue) -> anyhow::Result<DoorStateChangeEvent> {
2207 if let tlv::TlvItemValue::List(_fields) = inp {
2208 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
2209 Ok(DoorStateChangeEvent {
2210 door_state: item.get_int(&[0]).and_then(|v| DoorState::from_u8(v as u8)),
2211 })
2212 } else {
2213 Err(anyhow::anyhow!("Expected struct fields"))
2214 }
2215}
2216
2217pub fn decode_lock_operation_event(inp: &tlv::TlvItemValue) -> anyhow::Result<LockOperationEvent> {
2219 if let tlv::TlvItemValue::List(_fields) = inp {
2220 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
2221 Ok(LockOperationEvent {
2222 lock_operation_type: item.get_int(&[0]).and_then(|v| LockOperationType::from_u8(v as u8)),
2223 operation_source: item.get_int(&[1]).and_then(|v| OperationSource::from_u8(v as u8)),
2224 user_index: item.get_int(&[2]).map(|v| v as u16),
2225 fabric_index: item.get_int(&[3]).map(|v| v as u8),
2226 source_node: item.get_int(&[4]),
2227 credentials: {
2228 if let Some(tlv::TlvItemValue::List(l)) = item.get(&[5]) {
2229 let mut items = Vec::new();
2230 for list_item in l {
2231 items.push(Credential {
2232 credential_type: list_item.get_int(&[0]).and_then(|v| CredentialType::from_u8(v as u8)),
2233 credential_index: list_item.get_int(&[1]).map(|v| v as u16),
2234 });
2235 }
2236 Some(items)
2237 } else {
2238 None
2239 }
2240 },
2241 })
2242 } else {
2243 Err(anyhow::anyhow!("Expected struct fields"))
2244 }
2245}
2246
2247pub fn decode_lock_operation_error_event(inp: &tlv::TlvItemValue) -> anyhow::Result<LockOperationErrorEvent> {
2249 if let tlv::TlvItemValue::List(_fields) = inp {
2250 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
2251 Ok(LockOperationErrorEvent {
2252 lock_operation_type: item.get_int(&[0]).and_then(|v| LockOperationType::from_u8(v as u8)),
2253 operation_source: item.get_int(&[1]).and_then(|v| OperationSource::from_u8(v as u8)),
2254 operation_error: item.get_int(&[2]).and_then(|v| OperationError::from_u8(v as u8)),
2255 user_index: item.get_int(&[3]).map(|v| v as u16),
2256 fabric_index: item.get_int(&[4]).map(|v| v as u8),
2257 source_node: item.get_int(&[5]),
2258 credentials: {
2259 if let Some(tlv::TlvItemValue::List(l)) = item.get(&[6]) {
2260 let mut items = Vec::new();
2261 for list_item in l {
2262 items.push(Credential {
2263 credential_type: list_item.get_int(&[0]).and_then(|v| CredentialType::from_u8(v as u8)),
2264 credential_index: list_item.get_int(&[1]).map(|v| v as u16),
2265 });
2266 }
2267 Some(items)
2268 } else {
2269 None
2270 }
2271 },
2272 })
2273 } else {
2274 Err(anyhow::anyhow!("Expected struct fields"))
2275 }
2276}
2277
2278pub fn decode_lock_user_change_event(inp: &tlv::TlvItemValue) -> anyhow::Result<LockUserChangeEvent> {
2280 if let tlv::TlvItemValue::List(_fields) = inp {
2281 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
2282 Ok(LockUserChangeEvent {
2283 lock_data_type: item.get_int(&[0]).and_then(|v| LockDataType::from_u8(v as u8)),
2284 data_operation_type: item.get_int(&[1]).and_then(|v| DataOperationType::from_u8(v as u8)),
2285 operation_source: item.get_int(&[2]).and_then(|v| OperationSource::from_u8(v as u8)),
2286 user_index: item.get_int(&[3]).map(|v| v as u16),
2287 fabric_index: item.get_int(&[4]).map(|v| v as u8),
2288 source_node: item.get_int(&[5]),
2289 data_index: item.get_int(&[6]).map(|v| v as u16),
2290 })
2291 } else {
2292 Err(anyhow::anyhow!("Expected struct fields"))
2293 }
2294}
2295