1
1
import time
2
2
from datetime import datetime , timezone , timedelta
3
3
from seamapi .types import (
4
+ AbstractUnmanagedAccessCodes ,
5
+ UnmanagedAccessCode ,
4
6
WaitForAccessCodeFailedException ,
5
7
AbstractAccessCodes ,
6
8
AccessCode ,
@@ -30,12 +32,16 @@ class AccessCodes(AbstractAccessCodes):
30
32
31
33
Methods
32
34
-------
33
- list(device)
35
+ list(device, access_codes=None )
34
36
Gets a list of access codes for a device
35
37
get(access_code=None, device=None)
36
38
Gets a certain access code of a device
37
39
create(device, name=None, code=None, starts_at=None, ends_at=None, attempt_for_offline_device=None, wait_for_code=None, timeout=None, allow_external_modification=None, prefer_native_scheduling=None, use_backup_access_code_pool=None)
38
40
Creates an access code on a device
41
+ create_multiple(devices, name=None, code=None, starts_at=None, ends_at=None)
42
+ Creates multiple access codes across devices
43
+ update(access_code, device=None, name=None, code=None, starts_at=None, ends_at=None, type=None, allow_external_modification=None)
44
+ Updates an access code on a device
39
45
delete(access_code, device=None)
40
46
Deletes an access code on a device
41
47
pull_backup_access_code(access_code)
@@ -53,6 +59,7 @@ def __init__(self, seam: Seam):
53
59
"""
54
60
55
61
self .seam = seam
62
+ self .unmanaged = UnmanagedAccessCodes (seam )
56
63
57
64
@report_error
58
65
def list (
@@ -339,6 +346,7 @@ def update(
339
346
starts_at : Optional [str ] = None ,
340
347
ends_at : Optional [str ] = None ,
341
348
type : Optional [str ] = None ,
349
+ allow_external_modification : Optional [bool ] = None ,
342
350
) -> AccessCode :
343
351
"""Updates an access code on a device.
344
352
@@ -358,6 +366,8 @@ def update(
358
366
Time when access code ceases to be effective
359
367
type : str, optional
360
368
Access code type eg. ongoing or time_bound
369
+ allow_external_modification : bool, optional:
370
+ Allow external modifications of the access code e.g. through the lock provider's app. False by default.
361
371
362
372
Raises
363
373
------
@@ -383,6 +393,10 @@ def update(
383
393
update_payload ["ends_at" ] = ends_at
384
394
if type is not None :
385
395
update_payload ["type" ] = type
396
+ if allow_external_modification is not None :
397
+ update_payload [
398
+ "allow_external_modification"
399
+ ] = allow_external_modification
386
400
387
401
res = self .seam .make_request (
388
402
"POST" ,
@@ -470,3 +484,161 @@ def pull_backup_access_code(
470
484
)
471
485
472
486
return AccessCode .from_dict (res ["backup_access_code" ])
487
+
488
+
489
+ class UnmanagedAccessCodes (AbstractUnmanagedAccessCodes ):
490
+ """
491
+ A class used to retrieve unmanaged access code data
492
+ through interaction with Seam API
493
+
494
+ ...
495
+
496
+ Attributes
497
+ ----------
498
+ seam : Seam
499
+ Initial seam class
500
+
501
+ Methods
502
+ -------
503
+ get(device=None, access_code=None, code=None)
504
+ Gets an unmanaged access code
505
+ list(device)
506
+ Gets a list of unmanaged access codes
507
+ convert_to_managed(access_code, allow_external_modification=None)
508
+ Converts an unmanaged access code to a managed one
509
+ """
510
+
511
+ seam : Seam
512
+
513
+ def __init__ (self , seam : Seam ):
514
+ """
515
+ Parameters
516
+ ----------
517
+ seam : Seam
518
+ Initial seam class
519
+ """
520
+
521
+ self .seam = seam
522
+
523
+ @report_error
524
+ def get (
525
+ self ,
526
+ access_code : Optional [Union [AccessCodeId , AccessCode ]] = None ,
527
+ device : Optional [Union [DeviceId , Device ]] = None ,
528
+ code : Optional [str ] = None ,
529
+ ) -> UnmanagedAccessCode :
530
+ """Gets an unmanaged access code.
531
+
532
+ Parameters
533
+ ----------
534
+ access_code : Union[AccessCodeId, UnmanagedAccessCode], optional
535
+ Access Code ID or Access Code
536
+ device : Union[DeviceId, Device], optional
537
+ Device ID or Device
538
+ code : str, optional
539
+ Pin code of an access code
540
+
541
+ Raises
542
+ ------
543
+ Exception
544
+ If the API request wasn't successful.
545
+
546
+ Returns
547
+ ------
548
+ An unmanaged access code.
549
+ """
550
+
551
+ params = {}
552
+
553
+ if device :
554
+ params ["device_id" ] = to_device_id (device )
555
+ if access_code :
556
+ params ["access_code_id" ] = to_access_code_id (access_code )
557
+ if code :
558
+ params ["code" ] = code
559
+
560
+ res = self .seam .make_request (
561
+ "GET" ,
562
+ "/access_codes/unmanaged/get" ,
563
+ params = params ,
564
+ )
565
+ json_access_code = res ["access_code" ]
566
+
567
+ return UnmanagedAccessCode .from_dict (json_access_code )
568
+
569
+ @report_error
570
+ def list (
571
+ self ,
572
+ device : Union [DeviceId , Device ],
573
+ ) -> List [UnmanagedAccessCode ]:
574
+ """Gets a list of unmanaged access codes.
575
+
576
+ Parameters
577
+ ----------
578
+ device : Union[DeviceId, Device], optional
579
+ Device ID or Device
580
+
581
+ Raises
582
+ ------
583
+ Exception
584
+ If the API request wasn't successful.
585
+
586
+ Returns
587
+ ------
588
+ A list of unmanaged access codes.
589
+ """
590
+
591
+ res = self .seam .make_request (
592
+ "GET" ,
593
+ "/access_codes/unmanaged/list" ,
594
+ params = {"device_id" : to_device_id (device )},
595
+ )
596
+ access_codes = res ["access_codes" ]
597
+
598
+ return [UnmanagedAccessCode .from_dict (ac ) for ac in access_codes ]
599
+
600
+ @report_error
601
+ def convert_to_managed (
602
+ self ,
603
+ access_code : Union [AccessCodeId , UnmanagedAccessCode ],
604
+ allow_external_modification : Optional [bool ] = None ,
605
+ ) -> ActionAttempt :
606
+ """Converts an unmanaged access code to a managed one.
607
+
608
+ Parameters
609
+ ----------
610
+ access_code : AccessCodeId or UnmanagedAccessCode
611
+ Access Code ID or UnmanagedAccessCode
612
+ allow_external_modification : bool
613
+ Allow external modifications of the access code e.g. through the lock provider's app. False by default.
614
+
615
+ Raises
616
+ ------
617
+ Exception
618
+ If the API request wasn't successful.
619
+
620
+ Returns
621
+ ------
622
+ ActionAttempt
623
+ """
624
+
625
+ payload = {
626
+ "access_code_id" : to_access_code_id (access_code ),
627
+ }
628
+
629
+ if allow_external_modification is not None :
630
+ payload [
631
+ "allow_external_modification"
632
+ ] = allow_external_modification
633
+
634
+ res = self .seam .make_request (
635
+ "POST" ,
636
+ "/access_codes/unmanaged/convert_to_managed" ,
637
+ json = payload ,
638
+ )
639
+
640
+ action_attempt = self .seam .action_attempts .poll_until_ready (
641
+ res ["action_attempt" ]["action_attempt_id" ]
642
+ )
643
+
644
+ return action_attempt
0 commit comments