From c32e80277c3dbd255d06d9bb97caf79ef2aa2438 Mon Sep 17 00:00:00 2001 From: Seam Bot Date: Fri, 14 Feb 2025 17:58:22 +0000 Subject: [PATCH] ci: Generate code --- seam/routes/__init__.py | 28 + seam/routes/access_codes.py | 323 ++++ seam/routes/access_codes_simulate.py | 27 + seam/routes/access_codes_unmanaged.py | 113 ++ seam/routes/acs.py | 32 +- seam/routes/acs_access_groups.py | 81 + seam/routes/acs_access_groups_unmanaged.py | 35 - seam/routes/acs_credential_pools.py | 21 - ...acs_credential_provisioning_automations.py | 50 - seam/routes/acs_credentials.py | 149 +- seam/routes/acs_credentials_unmanaged.py | 41 - seam/routes/acs_encoders.py | 87 ++ seam/routes/acs_encoders_simulate.py | 93 ++ seam/routes/acs_entrances.py | 64 + seam/routes/acs_systems.py | 44 + seam/routes/acs_users.py | 198 +++ seam/routes/acs_users_unmanaged.py | 45 - seam/routes/action_attempts.py | 46 + seam/routes/bridges.py | 28 + seam/routes/client_sessions.py | 150 ++ seam/routes/connect_webviews.py | 86 + seam/routes/connected_accounts.py | 74 + seam/routes/devices.py | 110 +- seam/routes/devices_simulate.py | 39 + seam/routes/devices_unmanaged.py | 85 + seam/routes/events.py | 85 + seam/routes/locks.py | 131 ++ seam/routes/models.py | 1385 ++++++++++++++++- seam/routes/networks.py | 28 + seam/routes/noise_sensors.py | 73 + seam/routes/noise_sensors_noise_thresholds.py | 120 ++ seam/routes/noise_sensors_simulate.py | 21 + seam/routes/phones.py | 52 + seam/routes/phones_simulate.py | 34 + seam/routes/thermostats.py | 435 +++++- seam/routes/thermostats_schedules.py | 109 ++ seam/routes/thermostats_simulate.py | 58 + seam/routes/user_identities.py | 187 +++ .../user_identities_enrollment_automations.py | 82 + seam/routes/webhooks.py | 62 + seam/routes/workspaces.py | 82 + 41 files changed, 4723 insertions(+), 270 deletions(-) create mode 100644 seam/routes/access_codes.py create mode 100644 seam/routes/access_codes_simulate.py create mode 100644 seam/routes/access_codes_unmanaged.py create mode 100644 seam/routes/acs_access_groups.py delete mode 100644 seam/routes/acs_access_groups_unmanaged.py delete mode 100644 seam/routes/acs_credential_pools.py delete mode 100644 seam/routes/acs_credential_provisioning_automations.py delete mode 100644 seam/routes/acs_credentials_unmanaged.py create mode 100644 seam/routes/acs_encoders.py create mode 100644 seam/routes/acs_encoders_simulate.py create mode 100644 seam/routes/acs_entrances.py create mode 100644 seam/routes/acs_systems.py create mode 100644 seam/routes/acs_users.py delete mode 100644 seam/routes/acs_users_unmanaged.py create mode 100644 seam/routes/action_attempts.py create mode 100644 seam/routes/bridges.py create mode 100644 seam/routes/client_sessions.py create mode 100644 seam/routes/connect_webviews.py create mode 100644 seam/routes/connected_accounts.py create mode 100644 seam/routes/devices_simulate.py create mode 100644 seam/routes/devices_unmanaged.py create mode 100644 seam/routes/events.py create mode 100644 seam/routes/locks.py create mode 100644 seam/routes/networks.py create mode 100644 seam/routes/noise_sensors.py create mode 100644 seam/routes/noise_sensors_noise_thresholds.py create mode 100644 seam/routes/noise_sensors_simulate.py create mode 100644 seam/routes/phones.py create mode 100644 seam/routes/phones_simulate.py create mode 100644 seam/routes/thermostats_schedules.py create mode 100644 seam/routes/thermostats_simulate.py create mode 100644 seam/routes/user_identities.py create mode 100644 seam/routes/user_identities_enrollment_automations.py create mode 100644 seam/routes/webhooks.py create mode 100644 seam/routes/workspaces.py diff --git a/seam/routes/__init__.py b/seam/routes/__init__.py index c0655b1..9eb6fac 100644 --- a/seam/routes/__init__.py +++ b/seam/routes/__init__.py @@ -1,13 +1,41 @@ from typing import Any, Dict from ..client import SeamHttpClient from .models import AbstractRoutes +from .access_codes import AccessCodes from .acs import Acs +from .action_attempts import ActionAttempts +from .bridges import Bridges +from .client_sessions import ClientSessions +from .connect_webviews import ConnectWebviews +from .connected_accounts import ConnectedAccounts from .devices import Devices +from .events import Events +from .locks import Locks +from .networks import Networks +from .noise_sensors import NoiseSensors +from .phones import Phones from .thermostats import Thermostats +from .user_identities import UserIdentities +from .webhooks import Webhooks +from .workspaces import Workspaces class Routes(AbstractRoutes): def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.access_codes = AccessCodes(client=client, defaults=defaults) self.acs = Acs(client=client, defaults=defaults) + self.action_attempts = ActionAttempts(client=client, defaults=defaults) + self.bridges = Bridges(client=client, defaults=defaults) + self.client_sessions = ClientSessions(client=client, defaults=defaults) + self.connect_webviews = ConnectWebviews(client=client, defaults=defaults) + self.connected_accounts = ConnectedAccounts(client=client, defaults=defaults) self.devices = Devices(client=client, defaults=defaults) + self.events = Events(client=client, defaults=defaults) + self.locks = Locks(client=client, defaults=defaults) + self.networks = Networks(client=client, defaults=defaults) + self.noise_sensors = NoiseSensors(client=client, defaults=defaults) + self.phones = Phones(client=client, defaults=defaults) self.thermostats = Thermostats(client=client, defaults=defaults) + self.user_identities = UserIdentities(client=client, defaults=defaults) + self.webhooks = Webhooks(client=client, defaults=defaults) + self.workspaces = Workspaces(client=client, defaults=defaults) diff --git a/seam/routes/access_codes.py b/seam/routes/access_codes.py new file mode 100644 index 0000000..510e987 --- /dev/null +++ b/seam/routes/access_codes.py @@ -0,0 +1,323 @@ +from typing import Optional, Any, List, Dict, Union +from ..client import SeamHttpClient +from .models import AbstractAccessCodes, AccessCode +from .access_codes_simulate import AccessCodesSimulate +from .access_codes_unmanaged import AccessCodesUnmanaged + + +class AccessCodes(AbstractAccessCodes): + def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.client = client + self.defaults = defaults + self._simulate = AccessCodesSimulate(client=client, defaults=defaults) + self._unmanaged = AccessCodesUnmanaged(client=client, defaults=defaults) + + @property + def simulate(self) -> AccessCodesSimulate: + return self._simulate + + @property + def unmanaged(self) -> AccessCodesUnmanaged: + return self._unmanaged + + def create( + self, + *, + device_id: str, + allow_external_modification: Optional[bool] = None, + attempt_for_offline_device: Optional[bool] = None, + code: Optional[str] = None, + common_code_key: Optional[str] = None, + ends_at: Optional[str] = None, + is_external_modification_allowed: Optional[bool] = None, + is_offline_access_code: Optional[bool] = None, + is_one_time_use: Optional[bool] = None, + max_time_rounding: Optional[str] = None, + name: Optional[str] = None, + prefer_native_scheduling: Optional[bool] = None, + preferred_code_length: Optional[float] = None, + starts_at: Optional[str] = None, + sync: Optional[bool] = None, + use_backup_access_code_pool: Optional[bool] = None, + use_offline_access_code: Optional[bool] = None + ) -> AccessCode: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + if allow_external_modification is not None: + json_payload["allow_external_modification"] = allow_external_modification + if attempt_for_offline_device is not None: + json_payload["attempt_for_offline_device"] = attempt_for_offline_device + if code is not None: + json_payload["code"] = code + if common_code_key is not None: + json_payload["common_code_key"] = common_code_key + if ends_at is not None: + json_payload["ends_at"] = ends_at + if is_external_modification_allowed is not None: + json_payload["is_external_modification_allowed"] = ( + is_external_modification_allowed + ) + if is_offline_access_code is not None: + json_payload["is_offline_access_code"] = is_offline_access_code + if is_one_time_use is not None: + json_payload["is_one_time_use"] = is_one_time_use + if max_time_rounding is not None: + json_payload["max_time_rounding"] = max_time_rounding + if name is not None: + json_payload["name"] = name + if prefer_native_scheduling is not None: + json_payload["prefer_native_scheduling"] = prefer_native_scheduling + if preferred_code_length is not None: + json_payload["preferred_code_length"] = preferred_code_length + if starts_at is not None: + json_payload["starts_at"] = starts_at + if sync is not None: + json_payload["sync"] = sync + if use_backup_access_code_pool is not None: + json_payload["use_backup_access_code_pool"] = use_backup_access_code_pool + if use_offline_access_code is not None: + json_payload["use_offline_access_code"] = use_offline_access_code + + res = self.client.post("/access_codes/create", json=json_payload) + + return AccessCode.from_dict(res["access_code"]) + + def create_multiple( + self, + *, + device_ids: List[str], + allow_external_modification: Optional[bool] = None, + attempt_for_offline_device: Optional[bool] = None, + behavior_when_code_cannot_be_shared: Optional[str] = None, + code: Optional[str] = None, + ends_at: Optional[str] = None, + is_external_modification_allowed: Optional[bool] = None, + is_offline_access_code: Optional[bool] = None, + is_one_time_use: Optional[bool] = None, + max_time_rounding: Optional[str] = None, + name: Optional[str] = None, + prefer_native_scheduling: Optional[bool] = None, + preferred_code_length: Optional[float] = None, + starts_at: Optional[str] = None, + use_backup_access_code_pool: Optional[bool] = None, + use_offline_access_code: Optional[bool] = None + ) -> List[AccessCode]: + json_payload = {} + + if device_ids is not None: + json_payload["device_ids"] = device_ids + if allow_external_modification is not None: + json_payload["allow_external_modification"] = allow_external_modification + if attempt_for_offline_device is not None: + json_payload["attempt_for_offline_device"] = attempt_for_offline_device + if behavior_when_code_cannot_be_shared is not None: + json_payload["behavior_when_code_cannot_be_shared"] = ( + behavior_when_code_cannot_be_shared + ) + if code is not None: + json_payload["code"] = code + if ends_at is not None: + json_payload["ends_at"] = ends_at + if is_external_modification_allowed is not None: + json_payload["is_external_modification_allowed"] = ( + is_external_modification_allowed + ) + if is_offline_access_code is not None: + json_payload["is_offline_access_code"] = is_offline_access_code + if is_one_time_use is not None: + json_payload["is_one_time_use"] = is_one_time_use + if max_time_rounding is not None: + json_payload["max_time_rounding"] = max_time_rounding + if name is not None: + json_payload["name"] = name + if prefer_native_scheduling is not None: + json_payload["prefer_native_scheduling"] = prefer_native_scheduling + if preferred_code_length is not None: + json_payload["preferred_code_length"] = preferred_code_length + if starts_at is not None: + json_payload["starts_at"] = starts_at + if use_backup_access_code_pool is not None: + json_payload["use_backup_access_code_pool"] = use_backup_access_code_pool + if use_offline_access_code is not None: + json_payload["use_offline_access_code"] = use_offline_access_code + + res = self.client.post("/access_codes/create_multiple", json=json_payload) + + return [AccessCode.from_dict(item) for item in res["access_codes"]] + + def delete( + self, + *, + access_code_id: str, + device_id: Optional[str] = None, + sync: Optional[bool] = None + ) -> None: + json_payload = {} + + if access_code_id is not None: + json_payload["access_code_id"] = access_code_id + if device_id is not None: + json_payload["device_id"] = device_id + if sync is not None: + json_payload["sync"] = sync + + self.client.post("/access_codes/delete", json=json_payload) + + return None + + def generate_code(self, *, device_id: str) -> AccessCode: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + + res = self.client.post("/access_codes/generate_code", json=json_payload) + + return AccessCode.from_dict(res["generated_code"]) + + def get( + self, + *, + access_code_id: Optional[str] = None, + code: Optional[str] = None, + device_id: Optional[str] = None + ) -> AccessCode: + json_payload = {} + + if access_code_id is not None: + json_payload["access_code_id"] = access_code_id + if code is not None: + json_payload["code"] = code + if device_id is not None: + json_payload["device_id"] = device_id + + res = self.client.post("/access_codes/get", json=json_payload) + + return AccessCode.from_dict(res["access_code"]) + + def list( + self, + *, + access_code_ids: Optional[List[str]] = None, + device_id: Optional[str] = None, + user_identifier_key: Optional[str] = None + ) -> List[AccessCode]: + json_payload = {} + + if access_code_ids is not None: + json_payload["access_code_ids"] = access_code_ids + if device_id is not None: + json_payload["device_id"] = device_id + if user_identifier_key is not None: + json_payload["user_identifier_key"] = user_identifier_key + + res = self.client.post("/access_codes/list", json=json_payload) + + return [AccessCode.from_dict(item) for item in res["access_codes"]] + + def pull_backup_access_code(self, *, access_code_id: str) -> AccessCode: + json_payload = {} + + if access_code_id is not None: + json_payload["access_code_id"] = access_code_id + + res = self.client.post( + "/access_codes/pull_backup_access_code", json=json_payload + ) + + return AccessCode.from_dict(res["access_code"]) + + def update( + self, + *, + access_code_id: str, + allow_external_modification: Optional[bool] = None, + attempt_for_offline_device: Optional[bool] = None, + code: Optional[str] = None, + device_id: Optional[str] = None, + ends_at: Optional[str] = None, + is_external_modification_allowed: Optional[bool] = None, + is_managed: Optional[bool] = None, + is_offline_access_code: Optional[bool] = None, + is_one_time_use: Optional[bool] = None, + max_time_rounding: Optional[str] = None, + name: Optional[str] = None, + prefer_native_scheduling: Optional[bool] = None, + preferred_code_length: Optional[float] = None, + starts_at: Optional[str] = None, + sync: Optional[bool] = None, + type: Optional[str] = None, + use_backup_access_code_pool: Optional[bool] = None, + use_offline_access_code: Optional[bool] = None + ) -> None: + json_payload = {} + + if access_code_id is not None: + json_payload["access_code_id"] = access_code_id + if allow_external_modification is not None: + json_payload["allow_external_modification"] = allow_external_modification + if attempt_for_offline_device is not None: + json_payload["attempt_for_offline_device"] = attempt_for_offline_device + if code is not None: + json_payload["code"] = code + if device_id is not None: + json_payload["device_id"] = device_id + if ends_at is not None: + json_payload["ends_at"] = ends_at + if is_external_modification_allowed is not None: + json_payload["is_external_modification_allowed"] = ( + is_external_modification_allowed + ) + if is_managed is not None: + json_payload["is_managed"] = is_managed + if is_offline_access_code is not None: + json_payload["is_offline_access_code"] = is_offline_access_code + if is_one_time_use is not None: + json_payload["is_one_time_use"] = is_one_time_use + if max_time_rounding is not None: + json_payload["max_time_rounding"] = max_time_rounding + if name is not None: + json_payload["name"] = name + if prefer_native_scheduling is not None: + json_payload["prefer_native_scheduling"] = prefer_native_scheduling + if preferred_code_length is not None: + json_payload["preferred_code_length"] = preferred_code_length + if starts_at is not None: + json_payload["starts_at"] = starts_at + if sync is not None: + json_payload["sync"] = sync + if type is not None: + json_payload["type"] = type + if use_backup_access_code_pool is not None: + json_payload["use_backup_access_code_pool"] = use_backup_access_code_pool + if use_offline_access_code is not None: + json_payload["use_offline_access_code"] = use_offline_access_code + + self.client.post("/access_codes/update", json=json_payload) + + return None + + def update_multiple( + self, + *, + common_code_key: str, + ends_at: Optional[str] = None, + name: Optional[str] = None, + starts_at: Optional[str] = None + ) -> None: + json_payload = {} + + if common_code_key is not None: + json_payload["common_code_key"] = common_code_key + if ends_at is not None: + json_payload["ends_at"] = ends_at + if name is not None: + json_payload["name"] = name + if starts_at is not None: + json_payload["starts_at"] = starts_at + + self.client.post("/access_codes/update_multiple", json=json_payload) + + return None diff --git a/seam/routes/access_codes_simulate.py b/seam/routes/access_codes_simulate.py new file mode 100644 index 0000000..16bd8b1 --- /dev/null +++ b/seam/routes/access_codes_simulate.py @@ -0,0 +1,27 @@ +from typing import Optional, Any, List, Dict, Union +from ..client import SeamHttpClient +from .models import AbstractAccessCodesSimulate, UnmanagedAccessCode + + +class AccessCodesSimulate(AbstractAccessCodesSimulate): + def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.client = client + self.defaults = defaults + + def create_unmanaged_access_code( + self, *, code: str, device_id: str, name: str + ) -> UnmanagedAccessCode: + json_payload = {} + + if code is not None: + json_payload["code"] = code + if device_id is not None: + json_payload["device_id"] = device_id + if name is not None: + json_payload["name"] = name + + res = self.client.post( + "/access_codes/simulate/create_unmanaged_access_code", json=json_payload + ) + + return UnmanagedAccessCode.from_dict(res["access_code"]) diff --git a/seam/routes/access_codes_unmanaged.py b/seam/routes/access_codes_unmanaged.py new file mode 100644 index 0000000..8325ee5 --- /dev/null +++ b/seam/routes/access_codes_unmanaged.py @@ -0,0 +1,113 @@ +from typing import Optional, Any, List, Dict, Union +from ..client import SeamHttpClient +from .models import AbstractAccessCodesUnmanaged, UnmanagedAccessCode + + +class AccessCodesUnmanaged(AbstractAccessCodesUnmanaged): + def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.client = client + self.defaults = defaults + + def convert_to_managed( + self, + *, + access_code_id: str, + allow_external_modification: Optional[bool] = None, + force: Optional[bool] = None, + is_external_modification_allowed: Optional[bool] = None, + sync: Optional[bool] = None + ) -> None: + json_payload = {} + + if access_code_id is not None: + json_payload["access_code_id"] = access_code_id + if allow_external_modification is not None: + json_payload["allow_external_modification"] = allow_external_modification + if force is not None: + json_payload["force"] = force + if is_external_modification_allowed is not None: + json_payload["is_external_modification_allowed"] = ( + is_external_modification_allowed + ) + if sync is not None: + json_payload["sync"] = sync + + self.client.post( + "/access_codes/unmanaged/convert_to_managed", json=json_payload + ) + + return None + + def delete(self, *, access_code_id: str, sync: Optional[bool] = None) -> None: + json_payload = {} + + if access_code_id is not None: + json_payload["access_code_id"] = access_code_id + if sync is not None: + json_payload["sync"] = sync + + self.client.post("/access_codes/unmanaged/delete", json=json_payload) + + return None + + def get( + self, + *, + access_code_id: Optional[str] = None, + code: Optional[str] = None, + device_id: Optional[str] = None + ) -> UnmanagedAccessCode: + json_payload = {} + + if access_code_id is not None: + json_payload["access_code_id"] = access_code_id + if code is not None: + json_payload["code"] = code + if device_id is not None: + json_payload["device_id"] = device_id + + res = self.client.post("/access_codes/unmanaged/get", json=json_payload) + + return UnmanagedAccessCode.from_dict(res["access_code"]) + + def list( + self, *, device_id: str, user_identifier_key: Optional[str] = None + ) -> List[UnmanagedAccessCode]: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + if user_identifier_key is not None: + json_payload["user_identifier_key"] = user_identifier_key + + res = self.client.post("/access_codes/unmanaged/list", json=json_payload) + + return [UnmanagedAccessCode.from_dict(item) for item in res["access_codes"]] + + def update( + self, + *, + access_code_id: str, + is_managed: bool, + allow_external_modification: Optional[bool] = None, + force: Optional[bool] = None, + is_external_modification_allowed: Optional[bool] = None + ) -> None: + json_payload = {} + + if access_code_id is not None: + json_payload["access_code_id"] = access_code_id + if is_managed is not None: + json_payload["is_managed"] = is_managed + if allow_external_modification is not None: + json_payload["allow_external_modification"] = allow_external_modification + if force is not None: + json_payload["force"] = force + if is_external_modification_allowed is not None: + json_payload["is_external_modification_allowed"] = ( + is_external_modification_allowed + ) + + self.client.post("/access_codes/unmanaged/update", json=json_payload) + + return None diff --git a/seam/routes/acs.py b/seam/routes/acs.py index 4af4118..54343a1 100644 --- a/seam/routes/acs.py +++ b/seam/routes/acs.py @@ -2,11 +2,10 @@ from ..client import SeamHttpClient from .models import AbstractAcs from .acs_access_groups import AcsAccessGroups -from .acs_credential_pools import AcsCredentialPools -from .acs_credential_provisioning_automations import ( - AcsCredentialProvisioningAutomations, -) from .acs_credentials import AcsCredentials +from .acs_encoders import AcsEncoders +from .acs_entrances import AcsEntrances +from .acs_systems import AcsSystems from .acs_users import AcsUsers @@ -15,11 +14,10 @@ def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): self.client = client self.defaults = defaults self._access_groups = AcsAccessGroups(client=client, defaults=defaults) - self._credential_pools = AcsCredentialPools(client=client, defaults=defaults) - self._credential_provisioning_automations = ( - AcsCredentialProvisioningAutomations(client=client, defaults=defaults) - ) self._credentials = AcsCredentials(client=client, defaults=defaults) + self._encoders = AcsEncoders(client=client, defaults=defaults) + self._entrances = AcsEntrances(client=client, defaults=defaults) + self._systems = AcsSystems(client=client, defaults=defaults) self._users = AcsUsers(client=client, defaults=defaults) @property @@ -27,18 +25,20 @@ def access_groups(self) -> AcsAccessGroups: return self._access_groups @property - def credential_pools(self) -> AcsCredentialPools: - return self._credential_pools + def credentials(self) -> AcsCredentials: + return self._credentials @property - def credential_provisioning_automations( - self, - ) -> AcsCredentialProvisioningAutomations: - return self._credential_provisioning_automations + def encoders(self) -> AcsEncoders: + return self._encoders @property - def credentials(self) -> AcsCredentials: - return self._credentials + def entrances(self) -> AcsEntrances: + return self._entrances + + @property + def systems(self) -> AcsSystems: + return self._systems @property def users(self) -> AcsUsers: diff --git a/seam/routes/acs_access_groups.py b/seam/routes/acs_access_groups.py new file mode 100644 index 0000000..a60a3b7 --- /dev/null +++ b/seam/routes/acs_access_groups.py @@ -0,0 +1,81 @@ +from typing import Optional, Any, List, Dict, Union +from ..client import SeamHttpClient +from .models import AbstractAcsAccessGroups, AcsAccessGroup, AcsEntrance, AcsUser + + +class AcsAccessGroups(AbstractAcsAccessGroups): + def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.client = client + self.defaults = defaults + + def add_user(self, *, acs_access_group_id: str, acs_user_id: str) -> None: + json_payload = {} + + if acs_access_group_id is not None: + json_payload["acs_access_group_id"] = acs_access_group_id + if acs_user_id is not None: + json_payload["acs_user_id"] = acs_user_id + + self.client.post("/acs/access_groups/add_user", json=json_payload) + + return None + + def get(self, *, acs_access_group_id: str) -> AcsAccessGroup: + json_payload = {} + + if acs_access_group_id is not None: + json_payload["acs_access_group_id"] = acs_access_group_id + + res = self.client.post("/acs/access_groups/get", json=json_payload) + + return AcsAccessGroup.from_dict(res["acs_access_group"]) + + def list( + self, *, acs_system_id: Optional[str] = None, acs_user_id: Optional[str] = None + ) -> List[AcsAccessGroup]: + json_payload = {} + + if acs_system_id is not None: + json_payload["acs_system_id"] = acs_system_id + if acs_user_id is not None: + json_payload["acs_user_id"] = acs_user_id + + res = self.client.post("/acs/access_groups/list", json=json_payload) + + return [AcsAccessGroup.from_dict(item) for item in res["acs_access_groups"]] + + def list_accessible_entrances( + self, *, acs_access_group_id: str + ) -> List[AcsEntrance]: + json_payload = {} + + if acs_access_group_id is not None: + json_payload["acs_access_group_id"] = acs_access_group_id + + res = self.client.post( + "/acs/access_groups/list_accessible_entrances", json=json_payload + ) + + return [AcsEntrance.from_dict(item) for item in res["acs_entrances"]] + + def list_users(self, *, acs_access_group_id: str) -> List[AcsUser]: + json_payload = {} + + if acs_access_group_id is not None: + json_payload["acs_access_group_id"] = acs_access_group_id + + res = self.client.post("/acs/access_groups/list_users", json=json_payload) + + return [AcsUser.from_dict(item) for item in res["acs_users"]] + + def remove_user(self, *, acs_access_group_id: str, acs_user_id: str) -> None: + json_payload = {} + + if acs_access_group_id is not None: + json_payload["acs_access_group_id"] = acs_access_group_id + if acs_user_id is not None: + json_payload["acs_user_id"] = acs_user_id + + self.client.post("/acs/access_groups/remove_user", json=json_payload) + + return None diff --git a/seam/routes/acs_access_groups_unmanaged.py b/seam/routes/acs_access_groups_unmanaged.py deleted file mode 100644 index 010869e..0000000 --- a/seam/routes/acs_access_groups_unmanaged.py +++ /dev/null @@ -1,35 +0,0 @@ -from typing import Optional, Any, List, Dict, Union -from ..client import SeamHttpClient -from .models import AbstractAcsAccessGroupsUnmanaged, UnmanagedAcsAccessGroup - - -class AcsAccessGroupsUnmanaged(AbstractAcsAccessGroupsUnmanaged): - def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): - self.client = client - self.defaults = defaults - - def get(self, *, acs_access_group_id: str) -> UnmanagedAcsAccessGroup: - json_payload = {} - - if acs_access_group_id is not None: - json_payload["acs_access_group_id"] = acs_access_group_id - - res = self.client.post("/acs/access_groups/unmanaged/get", json=json_payload) - - return UnmanagedAcsAccessGroup.from_dict(res["acs_access_group"]) - - def list( - self, *, acs_system_id: Optional[str] = None, acs_user_id: Optional[str] = None - ) -> List[UnmanagedAcsAccessGroup]: - json_payload = {} - - if acs_system_id is not None: - json_payload["acs_system_id"] = acs_system_id - if acs_user_id is not None: - json_payload["acs_user_id"] = acs_user_id - - res = self.client.post("/acs/access_groups/unmanaged/list", json=json_payload) - - return [ - UnmanagedAcsAccessGroup.from_dict(item) for item in res["acs_access_groups"] - ] diff --git a/seam/routes/acs_credential_pools.py b/seam/routes/acs_credential_pools.py deleted file mode 100644 index 6247162..0000000 --- a/seam/routes/acs_credential_pools.py +++ /dev/null @@ -1,21 +0,0 @@ -from typing import Optional, Any, List, Dict, Union -from ..client import SeamHttpClient -from .models import AbstractAcsCredentialPools, AcsCredentialPool - - -class AcsCredentialPools(AbstractAcsCredentialPools): - def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): - self.client = client - self.defaults = defaults - - def list(self, *, acs_system_id: str) -> List[AcsCredentialPool]: - json_payload = {} - - if acs_system_id is not None: - json_payload["acs_system_id"] = acs_system_id - - res = self.client.post("/acs/credential_pools/list", json=json_payload) - - return [ - AcsCredentialPool.from_dict(item) for item in res["acs_credential_pools"] - ] diff --git a/seam/routes/acs_credential_provisioning_automations.py b/seam/routes/acs_credential_provisioning_automations.py deleted file mode 100644 index c30a567..0000000 --- a/seam/routes/acs_credential_provisioning_automations.py +++ /dev/null @@ -1,50 +0,0 @@ -from typing import Optional, Any, List, Dict, Union -from ..client import SeamHttpClient -from .models import ( - AbstractAcsCredentialProvisioningAutomations, - AcsCredentialProvisioningAutomation, -) - - -class AcsCredentialProvisioningAutomations( - AbstractAcsCredentialProvisioningAutomations -): - def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): - self.client = client - self.defaults = defaults - - def launch( - self, - *, - credential_manager_acs_system_id: str, - user_identity_id: str, - acs_credential_pool_id: Optional[str] = None, - create_credential_manager_user: Optional[bool] = None, - credential_manager_acs_user_id: Optional[str] = None - ) -> AcsCredentialProvisioningAutomation: - json_payload = {} - - if credential_manager_acs_system_id is not None: - json_payload["credential_manager_acs_system_id"] = ( - credential_manager_acs_system_id - ) - if user_identity_id is not None: - json_payload["user_identity_id"] = user_identity_id - if acs_credential_pool_id is not None: - json_payload["acs_credential_pool_id"] = acs_credential_pool_id - if create_credential_manager_user is not None: - json_payload["create_credential_manager_user"] = ( - create_credential_manager_user - ) - if credential_manager_acs_user_id is not None: - json_payload["credential_manager_acs_user_id"] = ( - credential_manager_acs_user_id - ) - - res = self.client.post( - "/acs/credential_provisioning_automations/launch", json=json_payload - ) - - return AcsCredentialProvisioningAutomation.from_dict( - res["acs_credential_provisioning_automation"] - ) diff --git a/seam/routes/acs_credentials.py b/seam/routes/acs_credentials.py index 75048a8..6168673 100644 --- a/seam/routes/acs_credentials.py +++ b/seam/routes/acs_credentials.py @@ -1,6 +1,6 @@ from typing import Optional, Any, List, Dict, Union from ..client import SeamHttpClient -from .models import AbstractAcsCredentials, AcsCredential +from .models import AbstractAcsCredentials, AcsCredential, AcsEntrance class AcsCredentials(AbstractAcsCredentials): @@ -8,30 +8,157 @@ def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): self.client = client self.defaults = defaults - def create_offline_code( + def assign(self, *, acs_credential_id: str, acs_user_id: str) -> None: + json_payload = {} + + if acs_credential_id is not None: + json_payload["acs_credential_id"] = acs_credential_id + if acs_user_id is not None: + json_payload["acs_user_id"] = acs_user_id + + self.client.post("/acs/credentials/assign", json=json_payload) + + return None + + def create( self, *, + access_method: str, acs_user_id: str, - allowed_acs_entrance_id: str, + allowed_acs_entrance_ids: Optional[List[str]] = None, + assa_abloy_vostio_metadata: Optional[Dict[str, Any]] = None, + code: Optional[str] = None, + credential_manager_acs_system_id: Optional[str] = None, ends_at: Optional[str] = None, - is_one_time_use: Optional[bool] = None, - starts_at: Optional[str] = None + is_multi_phone_sync_credential: Optional[bool] = None, + salto_space_metadata: Optional[Dict[str, Any]] = None, + starts_at: Optional[str] = None, + visionline_metadata: Optional[Dict[str, Any]] = None ) -> AcsCredential: json_payload = {} + if access_method is not None: + json_payload["access_method"] = access_method if acs_user_id is not None: json_payload["acs_user_id"] = acs_user_id - if allowed_acs_entrance_id is not None: - json_payload["allowed_acs_entrance_id"] = allowed_acs_entrance_id + if allowed_acs_entrance_ids is not None: + json_payload["allowed_acs_entrance_ids"] = allowed_acs_entrance_ids + if assa_abloy_vostio_metadata is not None: + json_payload["assa_abloy_vostio_metadata"] = assa_abloy_vostio_metadata + if code is not None: + json_payload["code"] = code + if credential_manager_acs_system_id is not None: + json_payload["credential_manager_acs_system_id"] = ( + credential_manager_acs_system_id + ) if ends_at is not None: json_payload["ends_at"] = ends_at - if is_one_time_use is not None: - json_payload["is_one_time_use"] = is_one_time_use + if is_multi_phone_sync_credential is not None: + json_payload["is_multi_phone_sync_credential"] = ( + is_multi_phone_sync_credential + ) + if salto_space_metadata is not None: + json_payload["salto_space_metadata"] = salto_space_metadata if starts_at is not None: json_payload["starts_at"] = starts_at + if visionline_metadata is not None: + json_payload["visionline_metadata"] = visionline_metadata + + res = self.client.post("/acs/credentials/create", json=json_payload) + + return AcsCredential.from_dict(res["acs_credential"]) + + def delete(self, *, acs_credential_id: str) -> None: + json_payload = {} + + if acs_credential_id is not None: + json_payload["acs_credential_id"] = acs_credential_id + + self.client.post("/acs/credentials/delete", json=json_payload) + + return None + + def get(self, *, acs_credential_id: str) -> AcsCredential: + json_payload = {} + + if acs_credential_id is not None: + json_payload["acs_credential_id"] = acs_credential_id + + res = self.client.post("/acs/credentials/get", json=json_payload) + + return AcsCredential.from_dict(res["acs_credential"]) + + def list( + self, + *, + acs_user_id: Optional[str] = None, + acs_system_id: Optional[str] = None, + user_identity_id: Optional[str] = None, + created_before: Optional[str] = None, + is_multi_phone_sync_credential: Optional[bool] = None, + limit: Optional[float] = None + ) -> List[AcsCredential]: + json_payload = {} + + if acs_user_id is not None: + json_payload["acs_user_id"] = acs_user_id + if acs_system_id is not None: + json_payload["acs_system_id"] = acs_system_id + if user_identity_id is not None: + json_payload["user_identity_id"] = user_identity_id + if created_before is not None: + json_payload["created_before"] = created_before + if is_multi_phone_sync_credential is not None: + json_payload["is_multi_phone_sync_credential"] = ( + is_multi_phone_sync_credential + ) + if limit is not None: + json_payload["limit"] = limit + + res = self.client.post("/acs/credentials/list", json=json_payload) + + return [AcsCredential.from_dict(item) for item in res["acs_credentials"]] + + def list_accessible_entrances(self, *, acs_credential_id: str) -> List[AcsEntrance]: + json_payload = {} + + if acs_credential_id is not None: + json_payload["acs_credential_id"] = acs_credential_id res = self.client.post( - "/acs/credentials/create_offline_code", json=json_payload + "/acs/credentials/list_accessible_entrances", json=json_payload ) - return AcsCredential.from_dict(res["acs_credential"]) + return [AcsEntrance.from_dict(item) for item in res["acs_entrances"]] + + def unassign(self, *, acs_credential_id: str, acs_user_id: str) -> None: + json_payload = {} + + if acs_credential_id is not None: + json_payload["acs_credential_id"] = acs_credential_id + if acs_user_id is not None: + json_payload["acs_user_id"] = acs_user_id + + self.client.post("/acs/credentials/unassign", json=json_payload) + + return None + + def update( + self, + *, + acs_credential_id: str, + code: Optional[str] = None, + ends_at: Optional[str] = None + ) -> None: + json_payload = {} + + if acs_credential_id is not None: + json_payload["acs_credential_id"] = acs_credential_id + if code is not None: + json_payload["code"] = code + if ends_at is not None: + json_payload["ends_at"] = ends_at + + self.client.post("/acs/credentials/update", json=json_payload) + + return None diff --git a/seam/routes/acs_credentials_unmanaged.py b/seam/routes/acs_credentials_unmanaged.py deleted file mode 100644 index c7d9d79..0000000 --- a/seam/routes/acs_credentials_unmanaged.py +++ /dev/null @@ -1,41 +0,0 @@ -from typing import Optional, Any, List, Dict, Union -from ..client import SeamHttpClient -from .models import AbstractAcsCredentialsUnmanaged, UnmanagedAcsCredential - - -class AcsCredentialsUnmanaged(AbstractAcsCredentialsUnmanaged): - def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): - self.client = client - self.defaults = defaults - - def get(self, *, acs_credential_id: str) -> UnmanagedAcsCredential: - json_payload = {} - - if acs_credential_id is not None: - json_payload["acs_credential_id"] = acs_credential_id - - res = self.client.post("/acs/credentials/unmanaged/get", json=json_payload) - - return UnmanagedAcsCredential.from_dict(res["acs_credential"]) - - def list( - self, - *, - acs_user_id: Optional[str] = None, - acs_system_id: Optional[str] = None, - user_identity_id: Optional[str] = None - ) -> List[UnmanagedAcsCredential]: - json_payload = {} - - if acs_user_id is not None: - json_payload["acs_user_id"] = acs_user_id - if acs_system_id is not None: - json_payload["acs_system_id"] = acs_system_id - if user_identity_id is not None: - json_payload["user_identity_id"] = user_identity_id - - res = self.client.post("/acs/credentials/unmanaged/list", json=json_payload) - - return [ - UnmanagedAcsCredential.from_dict(item) for item in res["acs_credentials"] - ] diff --git a/seam/routes/acs_encoders.py b/seam/routes/acs_encoders.py new file mode 100644 index 0000000..6d7a684 --- /dev/null +++ b/seam/routes/acs_encoders.py @@ -0,0 +1,87 @@ +from typing import Optional, Any, List, Dict, Union +from ..client import SeamHttpClient +from .models import AbstractAcsEncoders, ActionAttempt, AcsEncoder + +from ..modules.action_attempts import resolve_action_attempt + + +class AcsEncoders(AbstractAcsEncoders): + def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.client = client + self.defaults = defaults + + def encode_credential( + self, + *, + acs_credential_id: str, + acs_encoder_id: str, + wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = None + ) -> ActionAttempt: + json_payload = {} + + if acs_credential_id is not None: + json_payload["acs_credential_id"] = acs_credential_id + if acs_encoder_id is not None: + json_payload["acs_encoder_id"] = acs_encoder_id + + res = self.client.post("/acs/encoders/encode_credential", json=json_payload) + + wait_for_action_attempt = ( + self.defaults.get("wait_for_action_attempt") + if wait_for_action_attempt is None + else wait_for_action_attempt + ) + + return resolve_action_attempt( + client=self.client, + action_attempt=ActionAttempt.from_dict(res["action_attempt"]), + wait_for_action_attempt=wait_for_action_attempt, + ) + + def list( + self, + *, + acs_system_id: Optional[str] = None, + limit: Optional[float] = None, + acs_system_ids: Optional[List[str]] = None, + acs_encoder_ids: Optional[List[str]] = None + ) -> List[AcsEncoder]: + json_payload = {} + + if acs_system_id is not None: + json_payload["acs_system_id"] = acs_system_id + if limit is not None: + json_payload["limit"] = limit + if acs_system_ids is not None: + json_payload["acs_system_ids"] = acs_system_ids + if acs_encoder_ids is not None: + json_payload["acs_encoder_ids"] = acs_encoder_ids + + res = self.client.post("/acs/encoders/list", json=json_payload) + + return [AcsEncoder.from_dict(item) for item in res["acs_encoders"]] + + def scan_credential( + self, + *, + acs_encoder_id: str, + wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = None + ) -> ActionAttempt: + json_payload = {} + + if acs_encoder_id is not None: + json_payload["acs_encoder_id"] = acs_encoder_id + + res = self.client.post("/acs/encoders/scan_credential", json=json_payload) + + wait_for_action_attempt = ( + self.defaults.get("wait_for_action_attempt") + if wait_for_action_attempt is None + else wait_for_action_attempt + ) + + return resolve_action_attempt( + client=self.client, + action_attempt=ActionAttempt.from_dict(res["action_attempt"]), + wait_for_action_attempt=wait_for_action_attempt, + ) diff --git a/seam/routes/acs_encoders_simulate.py b/seam/routes/acs_encoders_simulate.py new file mode 100644 index 0000000..d63857c --- /dev/null +++ b/seam/routes/acs_encoders_simulate.py @@ -0,0 +1,93 @@ +from typing import Optional, Any, List, Dict, Union +from ..client import SeamHttpClient +from .models import AbstractAcsEncodersSimulate + + +class AcsEncodersSimulate(AbstractAcsEncodersSimulate): + def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.client = client + self.defaults = defaults + + def next_credential_encode_will_fail( + self, + *, + acs_encoder_id: str, + error_code: Optional[str] = None, + acs_credential_id: Optional[str] = None + ) -> None: + json_payload = {} + + if acs_encoder_id is not None: + json_payload["acs_encoder_id"] = acs_encoder_id + if error_code is not None: + json_payload["error_code"] = error_code + if acs_credential_id is not None: + json_payload["acs_credential_id"] = acs_credential_id + + self.client.post( + "/acs/encoders/simulate/next_credential_encode_will_fail", json=json_payload + ) + + return None + + def next_credential_encode_will_succeed( + self, *, acs_encoder_id: str, scenario: Optional[str] = None + ) -> None: + json_payload = {} + + if acs_encoder_id is not None: + json_payload["acs_encoder_id"] = acs_encoder_id + if scenario is not None: + json_payload["scenario"] = scenario + + self.client.post( + "/acs/encoders/simulate/next_credential_encode_will_succeed", + json=json_payload, + ) + + return None + + def next_credential_scan_will_fail( + self, + *, + acs_encoder_id: str, + error_code: Optional[str] = None, + acs_credential_id_on_seam: Optional[str] = None + ) -> None: + json_payload = {} + + if acs_encoder_id is not None: + json_payload["acs_encoder_id"] = acs_encoder_id + if error_code is not None: + json_payload["error_code"] = error_code + if acs_credential_id_on_seam is not None: + json_payload["acs_credential_id_on_seam"] = acs_credential_id_on_seam + + self.client.post( + "/acs/encoders/simulate/next_credential_scan_will_fail", json=json_payload + ) + + return None + + def next_credential_scan_will_succeed( + self, + *, + acs_encoder_id: str, + acs_credential_id_on_seam: Optional[str] = None, + scenario: Optional[str] = None + ) -> None: + json_payload = {} + + if acs_encoder_id is not None: + json_payload["acs_encoder_id"] = acs_encoder_id + if acs_credential_id_on_seam is not None: + json_payload["acs_credential_id_on_seam"] = acs_credential_id_on_seam + if scenario is not None: + json_payload["scenario"] = scenario + + self.client.post( + "/acs/encoders/simulate/next_credential_scan_will_succeed", + json=json_payload, + ) + + return None diff --git a/seam/routes/acs_entrances.py b/seam/routes/acs_entrances.py new file mode 100644 index 0000000..bbe4758 --- /dev/null +++ b/seam/routes/acs_entrances.py @@ -0,0 +1,64 @@ +from typing import Optional, Any, List, Dict, Union +from ..client import SeamHttpClient +from .models import AbstractAcsEntrances, AcsEntrance, AcsCredential + + +class AcsEntrances(AbstractAcsEntrances): + def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.client = client + self.defaults = defaults + + def get(self, *, acs_entrance_id: str) -> AcsEntrance: + json_payload = {} + + if acs_entrance_id is not None: + json_payload["acs_entrance_id"] = acs_entrance_id + + res = self.client.post("/acs/entrances/get", json=json_payload) + + return AcsEntrance.from_dict(res["acs_entrance"]) + + def grant_access(self, *, acs_entrance_id: str, acs_user_id: str) -> None: + json_payload = {} + + if acs_entrance_id is not None: + json_payload["acs_entrance_id"] = acs_entrance_id + if acs_user_id is not None: + json_payload["acs_user_id"] = acs_user_id + + self.client.post("/acs/entrances/grant_access", json=json_payload) + + return None + + def list( + self, + *, + acs_credential_id: Optional[str] = None, + acs_system_id: Optional[str] = None + ) -> List[AcsEntrance]: + json_payload = {} + + if acs_credential_id is not None: + json_payload["acs_credential_id"] = acs_credential_id + if acs_system_id is not None: + json_payload["acs_system_id"] = acs_system_id + + res = self.client.post("/acs/entrances/list", json=json_payload) + + return [AcsEntrance.from_dict(item) for item in res["acs_entrances"]] + + def list_credentials_with_access( + self, *, acs_entrance_id: str, include_if: Optional[List[str]] = None + ) -> List[AcsCredential]: + json_payload = {} + + if acs_entrance_id is not None: + json_payload["acs_entrance_id"] = acs_entrance_id + if include_if is not None: + json_payload["include_if"] = include_if + + res = self.client.post( + "/acs/entrances/list_credentials_with_access", json=json_payload + ) + + return [AcsCredential.from_dict(item) for item in res["acs_credentials"]] diff --git a/seam/routes/acs_systems.py b/seam/routes/acs_systems.py new file mode 100644 index 0000000..3d45051 --- /dev/null +++ b/seam/routes/acs_systems.py @@ -0,0 +1,44 @@ +from typing import Optional, Any, List, Dict, Union +from ..client import SeamHttpClient +from .models import AbstractAcsSystems, AcsSystem + + +class AcsSystems(AbstractAcsSystems): + def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.client = client + self.defaults = defaults + + def get(self, *, acs_system_id: str) -> AcsSystem: + json_payload = {} + + if acs_system_id is not None: + json_payload["acs_system_id"] = acs_system_id + + res = self.client.post("/acs/systems/get", json=json_payload) + + return AcsSystem.from_dict(res["acs_system"]) + + def list(self, *, connected_account_id: Optional[str] = None) -> List[AcsSystem]: + json_payload = {} + + if connected_account_id is not None: + json_payload["connected_account_id"] = connected_account_id + + res = self.client.post("/acs/systems/list", json=json_payload) + + return [AcsSystem.from_dict(item) for item in res["acs_systems"]] + + def list_compatible_credential_manager_acs_systems( + self, *, acs_system_id: str + ) -> List[AcsSystem]: + json_payload = {} + + if acs_system_id is not None: + json_payload["acs_system_id"] = acs_system_id + + res = self.client.post( + "/acs/systems/list_compatible_credential_manager_acs_systems", + json=json_payload, + ) + + return [AcsSystem.from_dict(item) for item in res["acs_systems"]] diff --git a/seam/routes/acs_users.py b/seam/routes/acs_users.py new file mode 100644 index 0000000..a995382 --- /dev/null +++ b/seam/routes/acs_users.py @@ -0,0 +1,198 @@ +from typing import Optional, Any, List, Dict, Union +from ..client import SeamHttpClient +from .models import AbstractAcsUsers, AcsUser, AcsEntrance + + +class AcsUsers(AbstractAcsUsers): + def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.client = client + self.defaults = defaults + + def add_to_access_group( + self, *, acs_access_group_id: str, acs_user_id: str + ) -> None: + json_payload = {} + + if acs_access_group_id is not None: + json_payload["acs_access_group_id"] = acs_access_group_id + if acs_user_id is not None: + json_payload["acs_user_id"] = acs_user_id + + self.client.post("/acs/users/add_to_access_group", json=json_payload) + + return None + + def create( + self, + *, + acs_system_id: str, + full_name: str, + access_schedule: Optional[Dict[str, Any]] = None, + acs_access_group_ids: Optional[List[str]] = None, + email: Optional[str] = None, + email_address: Optional[str] = None, + phone_number: Optional[str] = None, + user_identity_id: Optional[str] = None + ) -> AcsUser: + json_payload = {} + + if acs_system_id is not None: + json_payload["acs_system_id"] = acs_system_id + if full_name is not None: + json_payload["full_name"] = full_name + if access_schedule is not None: + json_payload["access_schedule"] = access_schedule + if acs_access_group_ids is not None: + json_payload["acs_access_group_ids"] = acs_access_group_ids + if email is not None: + json_payload["email"] = email + if email_address is not None: + json_payload["email_address"] = email_address + if phone_number is not None: + json_payload["phone_number"] = phone_number + if user_identity_id is not None: + json_payload["user_identity_id"] = user_identity_id + + res = self.client.post("/acs/users/create", json=json_payload) + + return AcsUser.from_dict(res["acs_user"]) + + def delete(self, *, acs_user_id: str) -> None: + json_payload = {} + + if acs_user_id is not None: + json_payload["acs_user_id"] = acs_user_id + + self.client.post("/acs/users/delete", json=json_payload) + + return None + + def get(self, *, acs_user_id: str) -> AcsUser: + json_payload = {} + + if acs_user_id is not None: + json_payload["acs_user_id"] = acs_user_id + + res = self.client.post("/acs/users/get", json=json_payload) + + return AcsUser.from_dict(res["acs_user"]) + + def list( + self, + *, + acs_system_id: Optional[str] = None, + created_before: Optional[str] = None, + limit: Optional[int] = None, + page_cursor: Optional[str] = None, + user_identity_email_address: Optional[str] = None, + user_identity_id: Optional[str] = None, + user_identity_phone_number: Optional[str] = None + ) -> List[AcsUser]: + json_payload = {} + + if acs_system_id is not None: + json_payload["acs_system_id"] = acs_system_id + if created_before is not None: + json_payload["created_before"] = created_before + if limit is not None: + json_payload["limit"] = limit + if page_cursor is not None: + json_payload["page_cursor"] = page_cursor + if user_identity_email_address is not None: + json_payload["user_identity_email_address"] = user_identity_email_address + if user_identity_id is not None: + json_payload["user_identity_id"] = user_identity_id + if user_identity_phone_number is not None: + json_payload["user_identity_phone_number"] = user_identity_phone_number + + res = self.client.post("/acs/users/list", json=json_payload) + + return [AcsUser.from_dict(item) for item in res["acs_users"]] + + def list_accessible_entrances(self, *, acs_user_id: str) -> List[AcsEntrance]: + json_payload = {} + + if acs_user_id is not None: + json_payload["acs_user_id"] = acs_user_id + + res = self.client.post( + "/acs/users/list_accessible_entrances", json=json_payload + ) + + return [AcsEntrance.from_dict(item) for item in res["acs_entrances"]] + + def remove_from_access_group( + self, *, acs_access_group_id: str, acs_user_id: str + ) -> None: + json_payload = {} + + if acs_access_group_id is not None: + json_payload["acs_access_group_id"] = acs_access_group_id + if acs_user_id is not None: + json_payload["acs_user_id"] = acs_user_id + + self.client.post("/acs/users/remove_from_access_group", json=json_payload) + + return None + + def revoke_access_to_all_entrances(self, *, acs_user_id: str) -> None: + json_payload = {} + + if acs_user_id is not None: + json_payload["acs_user_id"] = acs_user_id + + self.client.post("/acs/users/revoke_access_to_all_entrances", json=json_payload) + + return None + + def suspend(self, *, acs_user_id: str) -> None: + json_payload = {} + + if acs_user_id is not None: + json_payload["acs_user_id"] = acs_user_id + + self.client.post("/acs/users/suspend", json=json_payload) + + return None + + def unsuspend(self, *, acs_user_id: str) -> None: + json_payload = {} + + if acs_user_id is not None: + json_payload["acs_user_id"] = acs_user_id + + self.client.post("/acs/users/unsuspend", json=json_payload) + + return None + + def update( + self, + *, + acs_user_id: str, + access_schedule: Optional[Dict[str, Any]] = None, + email: Optional[str] = None, + email_address: Optional[str] = None, + full_name: Optional[str] = None, + hid_acs_system_id: Optional[str] = None, + phone_number: Optional[str] = None + ) -> None: + json_payload = {} + + if acs_user_id is not None: + json_payload["acs_user_id"] = acs_user_id + if access_schedule is not None: + json_payload["access_schedule"] = access_schedule + if email is not None: + json_payload["email"] = email + if email_address is not None: + json_payload["email_address"] = email_address + if full_name is not None: + json_payload["full_name"] = full_name + if hid_acs_system_id is not None: + json_payload["hid_acs_system_id"] = hid_acs_system_id + if phone_number is not None: + json_payload["phone_number"] = phone_number + + self.client.post("/acs/users/update", json=json_payload) + + return None diff --git a/seam/routes/acs_users_unmanaged.py b/seam/routes/acs_users_unmanaged.py deleted file mode 100644 index 6c98525..0000000 --- a/seam/routes/acs_users_unmanaged.py +++ /dev/null @@ -1,45 +0,0 @@ -from typing import Optional, Any, List, Dict, Union -from ..client import SeamHttpClient -from .models import AbstractAcsUsersUnmanaged, UnmanagedAcsUser - - -class AcsUsersUnmanaged(AbstractAcsUsersUnmanaged): - def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): - self.client = client - self.defaults = defaults - - def get(self, *, acs_user_id: str) -> UnmanagedAcsUser: - json_payload = {} - - if acs_user_id is not None: - json_payload["acs_user_id"] = acs_user_id - - res = self.client.post("/acs/users/unmanaged/get", json=json_payload) - - return UnmanagedAcsUser.from_dict(res["acs_user"]) - - def list( - self, - *, - acs_system_id: Optional[str] = None, - limit: Optional[float] = None, - user_identity_email_address: Optional[str] = None, - user_identity_id: Optional[str] = None, - user_identity_phone_number: Optional[str] = None - ) -> List[UnmanagedAcsUser]: - json_payload = {} - - if acs_system_id is not None: - json_payload["acs_system_id"] = acs_system_id - if limit is not None: - json_payload["limit"] = limit - if user_identity_email_address is not None: - json_payload["user_identity_email_address"] = user_identity_email_address - if user_identity_id is not None: - json_payload["user_identity_id"] = user_identity_id - if user_identity_phone_number is not None: - json_payload["user_identity_phone_number"] = user_identity_phone_number - - res = self.client.post("/acs/users/unmanaged/list", json=json_payload) - - return [UnmanagedAcsUser.from_dict(item) for item in res["acs_users"]] diff --git a/seam/routes/action_attempts.py b/seam/routes/action_attempts.py new file mode 100644 index 0000000..e6f36fd --- /dev/null +++ b/seam/routes/action_attempts.py @@ -0,0 +1,46 @@ +from typing import Optional, Any, List, Dict, Union +from ..client import SeamHttpClient +from .models import AbstractActionAttempts, ActionAttempt + +from ..modules.action_attempts import resolve_action_attempt + + +class ActionAttempts(AbstractActionAttempts): + def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.client = client + self.defaults = defaults + + def get( + self, + *, + action_attempt_id: str, + wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = None + ) -> ActionAttempt: + json_payload = {} + + if action_attempt_id is not None: + json_payload["action_attempt_id"] = action_attempt_id + + res = self.client.post("/action_attempts/get", json=json_payload) + + wait_for_action_attempt = ( + self.defaults.get("wait_for_action_attempt") + if wait_for_action_attempt is None + else wait_for_action_attempt + ) + + return resolve_action_attempt( + client=self.client, + action_attempt=ActionAttempt.from_dict(res["action_attempt"]), + wait_for_action_attempt=wait_for_action_attempt, + ) + + def list(self, *, action_attempt_ids: List[str]) -> List[ActionAttempt]: + json_payload = {} + + if action_attempt_ids is not None: + json_payload["action_attempt_ids"] = action_attempt_ids + + res = self.client.post("/action_attempts/list", json=json_payload) + + return [ActionAttempt.from_dict(item) for item in res["action_attempts"]] diff --git a/seam/routes/bridges.py b/seam/routes/bridges.py new file mode 100644 index 0000000..bdfd49b --- /dev/null +++ b/seam/routes/bridges.py @@ -0,0 +1,28 @@ +from typing import Optional, Any, List, Dict, Union +from ..client import SeamHttpClient +from .models import AbstractBridges + + +class Bridges(AbstractBridges): + def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.client = client + self.defaults = defaults + + def get(self, *, bridge_id: str) -> None: + json_payload = {} + + if bridge_id is not None: + json_payload["bridge_id"] = bridge_id + + self.client.post("/bridges/get", json=json_payload) + + return None + + def list( + self, + ) -> None: + json_payload = {} + + self.client.post("/bridges/list", json=json_payload) + + return None diff --git a/seam/routes/client_sessions.py b/seam/routes/client_sessions.py new file mode 100644 index 0000000..f05d3df --- /dev/null +++ b/seam/routes/client_sessions.py @@ -0,0 +1,150 @@ +from typing import Optional, Any, List, Dict, Union +from ..client import SeamHttpClient +from .models import AbstractClientSessions, ClientSession + + +class ClientSessions(AbstractClientSessions): + def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.client = client + self.defaults = defaults + + def create( + self, + *, + connect_webview_ids: Optional[List[str]] = None, + connected_account_ids: Optional[List[str]] = None, + expires_at: Optional[str] = None, + user_identifier_key: Optional[str] = None, + user_identity_ids: Optional[List[str]] = None + ) -> ClientSession: + json_payload = {} + + if connect_webview_ids is not None: + json_payload["connect_webview_ids"] = connect_webview_ids + if connected_account_ids is not None: + json_payload["connected_account_ids"] = connected_account_ids + if expires_at is not None: + json_payload["expires_at"] = expires_at + if user_identifier_key is not None: + json_payload["user_identifier_key"] = user_identifier_key + if user_identity_ids is not None: + json_payload["user_identity_ids"] = user_identity_ids + + res = self.client.post("/client_sessions/create", json=json_payload) + + return ClientSession.from_dict(res["client_session"]) + + def delete(self, *, client_session_id: str) -> None: + json_payload = {} + + if client_session_id is not None: + json_payload["client_session_id"] = client_session_id + + self.client.post("/client_sessions/delete", json=json_payload) + + return None + + def get( + self, + *, + client_session_id: Optional[str] = None, + user_identifier_key: Optional[str] = None + ) -> ClientSession: + json_payload = {} + + if client_session_id is not None: + json_payload["client_session_id"] = client_session_id + if user_identifier_key is not None: + json_payload["user_identifier_key"] = user_identifier_key + + res = self.client.post("/client_sessions/get", json=json_payload) + + return ClientSession.from_dict(res["client_session"]) + + def get_or_create( + self, + *, + connect_webview_ids: Optional[List[str]] = None, + connected_account_ids: Optional[List[str]] = None, + expires_at: Optional[str] = None, + user_identifier_key: Optional[str] = None, + user_identity_ids: Optional[List[str]] = None + ) -> ClientSession: + json_payload = {} + + if connect_webview_ids is not None: + json_payload["connect_webview_ids"] = connect_webview_ids + if connected_account_ids is not None: + json_payload["connected_account_ids"] = connected_account_ids + if expires_at is not None: + json_payload["expires_at"] = expires_at + if user_identifier_key is not None: + json_payload["user_identifier_key"] = user_identifier_key + if user_identity_ids is not None: + json_payload["user_identity_ids"] = user_identity_ids + + res = self.client.post("/client_sessions/get_or_create", json=json_payload) + + return ClientSession.from_dict(res["client_session"]) + + def grant_access( + self, + *, + client_session_id: Optional[str] = None, + connect_webview_ids: Optional[List[str]] = None, + connected_account_ids: Optional[List[str]] = None, + user_identifier_key: Optional[str] = None, + user_identity_ids: Optional[List[str]] = None + ) -> None: + json_payload = {} + + if client_session_id is not None: + json_payload["client_session_id"] = client_session_id + if connect_webview_ids is not None: + json_payload["connect_webview_ids"] = connect_webview_ids + if connected_account_ids is not None: + json_payload["connected_account_ids"] = connected_account_ids + if user_identifier_key is not None: + json_payload["user_identifier_key"] = user_identifier_key + if user_identity_ids is not None: + json_payload["user_identity_ids"] = user_identity_ids + + self.client.post("/client_sessions/grant_access", json=json_payload) + + return None + + def list( + self, + *, + client_session_id: Optional[str] = None, + connect_webview_id: Optional[str] = None, + user_identifier_key: Optional[str] = None, + user_identity_id: Optional[str] = None, + without_user_identifier_key: Optional[bool] = None + ) -> List[ClientSession]: + json_payload = {} + + if client_session_id is not None: + json_payload["client_session_id"] = client_session_id + if connect_webview_id is not None: + json_payload["connect_webview_id"] = connect_webview_id + if user_identifier_key is not None: + json_payload["user_identifier_key"] = user_identifier_key + if user_identity_id is not None: + json_payload["user_identity_id"] = user_identity_id + if without_user_identifier_key is not None: + json_payload["without_user_identifier_key"] = without_user_identifier_key + + res = self.client.post("/client_sessions/list", json=json_payload) + + return [ClientSession.from_dict(item) for item in res["client_sessions"]] + + def revoke(self, *, client_session_id: str) -> None: + json_payload = {} + + if client_session_id is not None: + json_payload["client_session_id"] = client_session_id + + self.client.post("/client_sessions/revoke", json=json_payload) + + return None diff --git a/seam/routes/connect_webviews.py b/seam/routes/connect_webviews.py new file mode 100644 index 0000000..47c5bd7 --- /dev/null +++ b/seam/routes/connect_webviews.py @@ -0,0 +1,86 @@ +from typing import Optional, Any, List, Dict, Union +from ..client import SeamHttpClient +from .models import AbstractConnectWebviews, ConnectWebview + + +class ConnectWebviews(AbstractConnectWebviews): + def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.client = client + self.defaults = defaults + + def create( + self, + *, + accepted_providers: Optional[List[str]] = None, + automatically_manage_new_devices: Optional[bool] = None, + custom_metadata: Optional[Dict[str, Any]] = None, + custom_redirect_failure_url: Optional[str] = None, + custom_redirect_url: Optional[str] = None, + device_selection_mode: Optional[str] = None, + provider_category: Optional[str] = None, + wait_for_device_creation: Optional[bool] = None + ) -> ConnectWebview: + json_payload = {} + + if accepted_providers is not None: + json_payload["accepted_providers"] = accepted_providers + if automatically_manage_new_devices is not None: + json_payload["automatically_manage_new_devices"] = ( + automatically_manage_new_devices + ) + if custom_metadata is not None: + json_payload["custom_metadata"] = custom_metadata + if custom_redirect_failure_url is not None: + json_payload["custom_redirect_failure_url"] = custom_redirect_failure_url + if custom_redirect_url is not None: + json_payload["custom_redirect_url"] = custom_redirect_url + if device_selection_mode is not None: + json_payload["device_selection_mode"] = device_selection_mode + if provider_category is not None: + json_payload["provider_category"] = provider_category + if wait_for_device_creation is not None: + json_payload["wait_for_device_creation"] = wait_for_device_creation + + res = self.client.post("/connect_webviews/create", json=json_payload) + + return ConnectWebview.from_dict(res["connect_webview"]) + + def delete(self, *, connect_webview_id: str) -> None: + json_payload = {} + + if connect_webview_id is not None: + json_payload["connect_webview_id"] = connect_webview_id + + self.client.post("/connect_webviews/delete", json=json_payload) + + return None + + def get(self, *, connect_webview_id: str) -> ConnectWebview: + json_payload = {} + + if connect_webview_id is not None: + json_payload["connect_webview_id"] = connect_webview_id + + res = self.client.post("/connect_webviews/get", json=json_payload) + + return ConnectWebview.from_dict(res["connect_webview"]) + + def list( + self, + *, + custom_metadata_has: Optional[Dict[str, Any]] = None, + limit: Optional[float] = None, + user_identifier_key: Optional[str] = None + ) -> List[ConnectWebview]: + json_payload = {} + + if custom_metadata_has is not None: + json_payload["custom_metadata_has"] = custom_metadata_has + if limit is not None: + json_payload["limit"] = limit + if user_identifier_key is not None: + json_payload["user_identifier_key"] = user_identifier_key + + res = self.client.post("/connect_webviews/list", json=json_payload) + + return [ConnectWebview.from_dict(item) for item in res["connect_webviews"]] diff --git a/seam/routes/connected_accounts.py b/seam/routes/connected_accounts.py new file mode 100644 index 0000000..7f2ea63 --- /dev/null +++ b/seam/routes/connected_accounts.py @@ -0,0 +1,74 @@ +from typing import Optional, Any, List, Dict, Union +from ..client import SeamHttpClient +from .models import AbstractConnectedAccounts, ConnectedAccount + + +class ConnectedAccounts(AbstractConnectedAccounts): + def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.client = client + self.defaults = defaults + + def delete(self, *, connected_account_id: str, sync: Optional[bool] = None) -> None: + json_payload = {} + + if connected_account_id is not None: + json_payload["connected_account_id"] = connected_account_id + if sync is not None: + json_payload["sync"] = sync + + self.client.post("/connected_accounts/delete", json=json_payload) + + return None + + def get( + self, *, connected_account_id: Optional[str] = None, email: Optional[str] = None + ) -> ConnectedAccount: + json_payload = {} + + if connected_account_id is not None: + json_payload["connected_account_id"] = connected_account_id + if email is not None: + json_payload["email"] = email + + res = self.client.post("/connected_accounts/get", json=json_payload) + + return ConnectedAccount.from_dict(res["connected_account"]) + + def list( + self, + *, + custom_metadata_has: Optional[Dict[str, Any]] = None, + user_identifier_key: Optional[str] = None + ) -> List[ConnectedAccount]: + json_payload = {} + + if custom_metadata_has is not None: + json_payload["custom_metadata_has"] = custom_metadata_has + if user_identifier_key is not None: + json_payload["user_identifier_key"] = user_identifier_key + + res = self.client.post("/connected_accounts/list", json=json_payload) + + return [ConnectedAccount.from_dict(item) for item in res["connected_accounts"]] + + def update( + self, + *, + connected_account_id: str, + automatically_manage_new_devices: Optional[bool] = None, + custom_metadata: Optional[Dict[str, Any]] = None + ) -> None: + json_payload = {} + + if connected_account_id is not None: + json_payload["connected_account_id"] = connected_account_id + if automatically_manage_new_devices is not None: + json_payload["automatically_manage_new_devices"] = ( + automatically_manage_new_devices + ) + if custom_metadata is not None: + json_payload["custom_metadata"] = custom_metadata + + self.client.post("/connected_accounts/update", json=json_payload) + + return None diff --git a/seam/routes/devices.py b/seam/routes/devices.py index 154cead..92f48c7 100644 --- a/seam/routes/devices.py +++ b/seam/routes/devices.py @@ -1,19 +1,123 @@ from typing import Optional, Any, List, Dict, Union from ..client import SeamHttpClient -from .models import AbstractDevices +from .models import AbstractDevices, Device, DeviceProvider +from .devices_simulate import DevicesSimulate +from .devices_unmanaged import DevicesUnmanaged class Devices(AbstractDevices): def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): self.client = client self.defaults = defaults + self._simulate = DevicesSimulate(client=client, defaults=defaults) + self._unmanaged = DevicesUnmanaged(client=client, defaults=defaults) - def delete(self, *, device_id: str) -> None: + @property + def simulate(self) -> DevicesSimulate: + return self._simulate + + @property + def unmanaged(self) -> DevicesUnmanaged: + return self._unmanaged + + def get( + self, *, device_id: Optional[str] = None, name: Optional[str] = None + ) -> Device: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + if name is not None: + json_payload["name"] = name + + res = self.client.post("/devices/get", json=json_payload) + + return Device.from_dict(res["device"]) + + def list( + self, + *, + connect_webview_id: Optional[str] = None, + connected_account_id: Optional[str] = None, + connected_account_ids: Optional[List[str]] = None, + created_before: Optional[str] = None, + custom_metadata_has: Optional[Dict[str, Any]] = None, + device_ids: Optional[List[str]] = None, + device_type: Optional[str] = None, + device_types: Optional[List[str]] = None, + exclude_if: Optional[List[str]] = None, + include_if: Optional[List[str]] = None, + limit: Optional[float] = None, + manufacturer: Optional[str] = None, + user_identifier_key: Optional[str] = None + ) -> List[Device]: + json_payload = {} + + if connect_webview_id is not None: + json_payload["connect_webview_id"] = connect_webview_id + if connected_account_id is not None: + json_payload["connected_account_id"] = connected_account_id + if connected_account_ids is not None: + json_payload["connected_account_ids"] = connected_account_ids + if created_before is not None: + json_payload["created_before"] = created_before + if custom_metadata_has is not None: + json_payload["custom_metadata_has"] = custom_metadata_has + if device_ids is not None: + json_payload["device_ids"] = device_ids + if device_type is not None: + json_payload["device_type"] = device_type + if device_types is not None: + json_payload["device_types"] = device_types + if exclude_if is not None: + json_payload["exclude_if"] = exclude_if + if include_if is not None: + json_payload["include_if"] = include_if + if limit is not None: + json_payload["limit"] = limit + if manufacturer is not None: + json_payload["manufacturer"] = manufacturer + if user_identifier_key is not None: + json_payload["user_identifier_key"] = user_identifier_key + + res = self.client.post("/devices/list", json=json_payload) + + return [Device.from_dict(item) for item in res["devices"]] + + def list_device_providers( + self, *, provider_category: Optional[str] = None + ) -> List[DeviceProvider]: + json_payload = {} + + if provider_category is not None: + json_payload["provider_category"] = provider_category + + res = self.client.post("/devices/list_device_providers", json=json_payload) + + return [DeviceProvider.from_dict(item) for item in res["device_providers"]] + + def update( + self, + *, + device_id: str, + custom_metadata: Optional[Dict[str, Any]] = None, + is_managed: Optional[bool] = None, + name: Optional[str] = None, + properties: Optional[Dict[str, Any]] = None + ) -> None: json_payload = {} if device_id is not None: json_payload["device_id"] = device_id + if custom_metadata is not None: + json_payload["custom_metadata"] = custom_metadata + if is_managed is not None: + json_payload["is_managed"] = is_managed + if name is not None: + json_payload["name"] = name + if properties is not None: + json_payload["properties"] = properties - self.client.post("/devices/delete", json=json_payload) + self.client.post("/devices/update", json=json_payload) return None diff --git a/seam/routes/devices_simulate.py b/seam/routes/devices_simulate.py new file mode 100644 index 0000000..52ddc26 --- /dev/null +++ b/seam/routes/devices_simulate.py @@ -0,0 +1,39 @@ +from typing import Optional, Any, List, Dict, Union +from ..client import SeamHttpClient +from .models import AbstractDevicesSimulate + + +class DevicesSimulate(AbstractDevicesSimulate): + def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.client = client + self.defaults = defaults + + def connect(self, *, device_id: str) -> None: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + + self.client.post("/devices/simulate/connect", json=json_payload) + + return None + + def disconnect(self, *, device_id: str) -> None: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + + self.client.post("/devices/simulate/disconnect", json=json_payload) + + return None + + def remove(self, *, device_id: str) -> None: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + + self.client.post("/devices/simulate/remove", json=json_payload) + + return None diff --git a/seam/routes/devices_unmanaged.py b/seam/routes/devices_unmanaged.py new file mode 100644 index 0000000..141ce6f --- /dev/null +++ b/seam/routes/devices_unmanaged.py @@ -0,0 +1,85 @@ +from typing import Optional, Any, List, Dict, Union +from ..client import SeamHttpClient +from .models import AbstractDevicesUnmanaged, UnmanagedDevice + + +class DevicesUnmanaged(AbstractDevicesUnmanaged): + def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.client = client + self.defaults = defaults + + def get( + self, *, device_id: Optional[str] = None, name: Optional[str] = None + ) -> UnmanagedDevice: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + if name is not None: + json_payload["name"] = name + + res = self.client.post("/devices/unmanaged/get", json=json_payload) + + return UnmanagedDevice.from_dict(res["device"]) + + def list( + self, + *, + connect_webview_id: Optional[str] = None, + connected_account_id: Optional[str] = None, + connected_account_ids: Optional[List[str]] = None, + created_before: Optional[str] = None, + custom_metadata_has: Optional[Dict[str, Any]] = None, + device_ids: Optional[List[str]] = None, + device_type: Optional[str] = None, + device_types: Optional[List[str]] = None, + exclude_if: Optional[List[str]] = None, + include_if: Optional[List[str]] = None, + limit: Optional[float] = None, + manufacturer: Optional[str] = None, + user_identifier_key: Optional[str] = None + ) -> List[UnmanagedDevice]: + json_payload = {} + + if connect_webview_id is not None: + json_payload["connect_webview_id"] = connect_webview_id + if connected_account_id is not None: + json_payload["connected_account_id"] = connected_account_id + if connected_account_ids is not None: + json_payload["connected_account_ids"] = connected_account_ids + if created_before is not None: + json_payload["created_before"] = created_before + if custom_metadata_has is not None: + json_payload["custom_metadata_has"] = custom_metadata_has + if device_ids is not None: + json_payload["device_ids"] = device_ids + if device_type is not None: + json_payload["device_type"] = device_type + if device_types is not None: + json_payload["device_types"] = device_types + if exclude_if is not None: + json_payload["exclude_if"] = exclude_if + if include_if is not None: + json_payload["include_if"] = include_if + if limit is not None: + json_payload["limit"] = limit + if manufacturer is not None: + json_payload["manufacturer"] = manufacturer + if user_identifier_key is not None: + json_payload["user_identifier_key"] = user_identifier_key + + res = self.client.post("/devices/unmanaged/list", json=json_payload) + + return [UnmanagedDevice.from_dict(item) for item in res["devices"]] + + def update(self, *, device_id: str, is_managed: bool) -> None: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + if is_managed is not None: + json_payload["is_managed"] = is_managed + + self.client.post("/devices/unmanaged/update", json=json_payload) + + return None diff --git a/seam/routes/events.py b/seam/routes/events.py new file mode 100644 index 0000000..f769a54 --- /dev/null +++ b/seam/routes/events.py @@ -0,0 +1,85 @@ +from typing import Optional, Any, List, Dict, Union +from ..client import SeamHttpClient +from .models import AbstractEvents, SeamEvent + + +class Events(AbstractEvents): + def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.client = client + self.defaults = defaults + + def get( + self, + *, + device_id: Optional[str] = None, + event_id: Optional[str] = None, + event_type: Optional[str] = None + ) -> SeamEvent: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + if event_id is not None: + json_payload["event_id"] = event_id + if event_type is not None: + json_payload["event_type"] = event_type + + res = self.client.post("/events/get", json=json_payload) + + return SeamEvent.from_dict(res["event"]) + + def list( + self, + *, + access_code_id: Optional[str] = None, + access_code_ids: Optional[List[str]] = None, + acs_system_id: Optional[str] = None, + acs_system_ids: Optional[List[str]] = None, + between: Optional[List[str]] = None, + connect_webview_id: Optional[str] = None, + connected_account_id: Optional[str] = None, + device_id: Optional[str] = None, + device_ids: Optional[List[str]] = None, + event_ids: Optional[List[str]] = None, + event_type: Optional[str] = None, + event_types: Optional[List[str]] = None, + limit: Optional[float] = None, + since: Optional[str] = None, + unstable_offset: Optional[float] = None + ) -> List[SeamEvent]: + json_payload = {} + + if access_code_id is not None: + json_payload["access_code_id"] = access_code_id + if access_code_ids is not None: + json_payload["access_code_ids"] = access_code_ids + if acs_system_id is not None: + json_payload["acs_system_id"] = acs_system_id + if acs_system_ids is not None: + json_payload["acs_system_ids"] = acs_system_ids + if between is not None: + json_payload["between"] = between + if connect_webview_id is not None: + json_payload["connect_webview_id"] = connect_webview_id + if connected_account_id is not None: + json_payload["connected_account_id"] = connected_account_id + if device_id is not None: + json_payload["device_id"] = device_id + if device_ids is not None: + json_payload["device_ids"] = device_ids + if event_ids is not None: + json_payload["event_ids"] = event_ids + if event_type is not None: + json_payload["event_type"] = event_type + if event_types is not None: + json_payload["event_types"] = event_types + if limit is not None: + json_payload["limit"] = limit + if since is not None: + json_payload["since"] = since + if unstable_offset is not None: + json_payload["unstable_offset"] = unstable_offset + + res = self.client.post("/events/list", json=json_payload) + + return [SeamEvent.from_dict(item) for item in res["events"]] diff --git a/seam/routes/locks.py b/seam/routes/locks.py new file mode 100644 index 0000000..5924f98 --- /dev/null +++ b/seam/routes/locks.py @@ -0,0 +1,131 @@ +from typing import Optional, Any, List, Dict, Union +from ..client import SeamHttpClient +from .models import AbstractLocks, Device, ActionAttempt + +from ..modules.action_attempts import resolve_action_attempt + + +class Locks(AbstractLocks): + def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.client = client + self.defaults = defaults + + def get( + self, *, device_id: Optional[str] = None, name: Optional[str] = None + ) -> Device: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + if name is not None: + json_payload["name"] = name + + res = self.client.post("/locks/get", json=json_payload) + + return Device.from_dict(res["device"]) + + def list( + self, + *, + connect_webview_id: Optional[str] = None, + connected_account_id: Optional[str] = None, + connected_account_ids: Optional[List[str]] = None, + created_before: Optional[str] = None, + custom_metadata_has: Optional[Dict[str, Any]] = None, + device_ids: Optional[List[str]] = None, + device_type: Optional[str] = None, + device_types: Optional[List[str]] = None, + exclude_if: Optional[List[str]] = None, + include_if: Optional[List[str]] = None, + limit: Optional[float] = None, + manufacturer: Optional[str] = None, + user_identifier_key: Optional[str] = None + ) -> List[Device]: + json_payload = {} + + if connect_webview_id is not None: + json_payload["connect_webview_id"] = connect_webview_id + if connected_account_id is not None: + json_payload["connected_account_id"] = connected_account_id + if connected_account_ids is not None: + json_payload["connected_account_ids"] = connected_account_ids + if created_before is not None: + json_payload["created_before"] = created_before + if custom_metadata_has is not None: + json_payload["custom_metadata_has"] = custom_metadata_has + if device_ids is not None: + json_payload["device_ids"] = device_ids + if device_type is not None: + json_payload["device_type"] = device_type + if device_types is not None: + json_payload["device_types"] = device_types + if exclude_if is not None: + json_payload["exclude_if"] = exclude_if + if include_if is not None: + json_payload["include_if"] = include_if + if limit is not None: + json_payload["limit"] = limit + if manufacturer is not None: + json_payload["manufacturer"] = manufacturer + if user_identifier_key is not None: + json_payload["user_identifier_key"] = user_identifier_key + + res = self.client.post("/locks/list", json=json_payload) + + return [Device.from_dict(item) for item in res["devices"]] + + def lock_door( + self, + *, + device_id: str, + sync: Optional[bool] = None, + wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = None + ) -> ActionAttempt: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + if sync is not None: + json_payload["sync"] = sync + + res = self.client.post("/locks/lock_door", json=json_payload) + + wait_for_action_attempt = ( + self.defaults.get("wait_for_action_attempt") + if wait_for_action_attempt is None + else wait_for_action_attempt + ) + + return resolve_action_attempt( + client=self.client, + action_attempt=ActionAttempt.from_dict(res["action_attempt"]), + wait_for_action_attempt=wait_for_action_attempt, + ) + + def unlock_door( + self, + *, + device_id: str, + sync: Optional[bool] = None, + wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = None + ) -> ActionAttempt: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + if sync is not None: + json_payload["sync"] = sync + + res = self.client.post("/locks/unlock_door", json=json_payload) + + wait_for_action_attempt = ( + self.defaults.get("wait_for_action_attempt") + if wait_for_action_attempt is None + else wait_for_action_attempt + ) + + return resolve_action_attempt( + client=self.client, + action_attempt=ActionAttempt.from_dict(res["action_attempt"]), + wait_for_action_attempt=wait_for_action_attempt, + ) diff --git a/seam/routes/models.py b/seam/routes/models.py index 259df31..9973219 100644 --- a/seam/routes/models.py +++ b/seam/routes/models.py @@ -1158,105 +1158,1389 @@ def from_dict(d: Dict[str, Any]): ) -class AbstractAcsAccessGroupsUnmanaged(abc.ABC): +class AbstractAccessCodesSimulate(abc.ABC): @abc.abstractmethod - def get(self, *, acs_access_group_id: str) -> UnmanagedAcsAccessGroup: + def create_unmanaged_access_code( + self, *, code: str, device_id: str, name: str + ) -> UnmanagedAccessCode: + raise NotImplementedError() + + +class AbstractAccessCodesUnmanaged(abc.ABC): + + @abc.abstractmethod + def convert_to_managed( + self, + *, + access_code_id: str, + allow_external_modification: Optional[bool] = None, + force: Optional[bool] = None, + is_external_modification_allowed: Optional[bool] = None, + sync: Optional[bool] = None + ) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def delete(self, *, access_code_id: str, sync: Optional[bool] = None) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def get( + self, + *, + access_code_id: Optional[str] = None, + code: Optional[str] = None, + device_id: Optional[str] = None + ) -> UnmanagedAccessCode: + raise NotImplementedError() + + @abc.abstractmethod + def list( + self, *, device_id: str, user_identifier_key: Optional[str] = None + ) -> List[UnmanagedAccessCode]: + raise NotImplementedError() + + @abc.abstractmethod + def update( + self, + *, + access_code_id: str, + is_managed: bool, + allow_external_modification: Optional[bool] = None, + force: Optional[bool] = None, + is_external_modification_allowed: Optional[bool] = None + ) -> None: + raise NotImplementedError() + + +class AbstractAcsAccessGroups(abc.ABC): + + @abc.abstractmethod + def add_user(self, *, acs_access_group_id: str, acs_user_id: str) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def get(self, *, acs_access_group_id: str) -> AcsAccessGroup: + raise NotImplementedError() + + @abc.abstractmethod + def list( + self, *, acs_system_id: Optional[str] = None, acs_user_id: Optional[str] = None + ) -> List[AcsAccessGroup]: + raise NotImplementedError() + + @abc.abstractmethod + def list_accessible_entrances( + self, *, acs_access_group_id: str + ) -> List[AcsEntrance]: + raise NotImplementedError() + + @abc.abstractmethod + def list_users(self, *, acs_access_group_id: str) -> List[AcsUser]: + raise NotImplementedError() + + @abc.abstractmethod + def remove_user(self, *, acs_access_group_id: str, acs_user_id: str) -> None: + raise NotImplementedError() + + +class AbstractAcsCredentials(abc.ABC): + + @abc.abstractmethod + def assign(self, *, acs_credential_id: str, acs_user_id: str) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def create( + self, + *, + access_method: str, + acs_user_id: str, + allowed_acs_entrance_ids: Optional[List[str]] = None, + assa_abloy_vostio_metadata: Optional[Dict[str, Any]] = None, + code: Optional[str] = None, + credential_manager_acs_system_id: Optional[str] = None, + ends_at: Optional[str] = None, + is_multi_phone_sync_credential: Optional[bool] = None, + salto_space_metadata: Optional[Dict[str, Any]] = None, + starts_at: Optional[str] = None, + visionline_metadata: Optional[Dict[str, Any]] = None + ) -> AcsCredential: + raise NotImplementedError() + + @abc.abstractmethod + def delete(self, *, acs_credential_id: str) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def get(self, *, acs_credential_id: str) -> AcsCredential: + raise NotImplementedError() + + @abc.abstractmethod + def list( + self, + *, + acs_user_id: Optional[str] = None, + acs_system_id: Optional[str] = None, + user_identity_id: Optional[str] = None, + created_before: Optional[str] = None, + is_multi_phone_sync_credential: Optional[bool] = None, + limit: Optional[float] = None + ) -> List[AcsCredential]: + raise NotImplementedError() + + @abc.abstractmethod + def list_accessible_entrances(self, *, acs_credential_id: str) -> List[AcsEntrance]: + raise NotImplementedError() + + @abc.abstractmethod + def unassign(self, *, acs_credential_id: str, acs_user_id: str) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def update( + self, + *, + acs_credential_id: str, + code: Optional[str] = None, + ends_at: Optional[str] = None + ) -> None: + raise NotImplementedError() + + +class AbstractAcsEncoders(abc.ABC): + + @abc.abstractmethod + def encode_credential( + self, + *, + acs_credential_id: str, + acs_encoder_id: str, + wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = None + ) -> ActionAttempt: + raise NotImplementedError() + + @abc.abstractmethod + def list( + self, + *, + acs_system_id: Optional[str] = None, + limit: Optional[float] = None, + acs_system_ids: Optional[List[str]] = None, + acs_encoder_ids: Optional[List[str]] = None + ) -> List[AcsEncoder]: + raise NotImplementedError() + + @abc.abstractmethod + def scan_credential( + self, + *, + acs_encoder_id: str, + wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = None + ) -> ActionAttempt: + raise NotImplementedError() + + +class AbstractAcsEncodersSimulate(abc.ABC): + + @abc.abstractmethod + def next_credential_encode_will_fail( + self, + *, + acs_encoder_id: str, + error_code: Optional[str] = None, + acs_credential_id: Optional[str] = None + ) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def next_credential_encode_will_succeed( + self, *, acs_encoder_id: str, scenario: Optional[str] = None + ) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def next_credential_scan_will_fail( + self, + *, + acs_encoder_id: str, + error_code: Optional[str] = None, + acs_credential_id_on_seam: Optional[str] = None + ) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def next_credential_scan_will_succeed( + self, + *, + acs_encoder_id: str, + acs_credential_id_on_seam: Optional[str] = None, + scenario: Optional[str] = None + ) -> None: + raise NotImplementedError() + + +class AbstractAcsEntrances(abc.ABC): + + @abc.abstractmethod + def get(self, *, acs_entrance_id: str) -> AcsEntrance: + raise NotImplementedError() + + @abc.abstractmethod + def grant_access(self, *, acs_entrance_id: str, acs_user_id: str) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def list( + self, + *, + acs_credential_id: Optional[str] = None, + acs_system_id: Optional[str] = None + ) -> List[AcsEntrance]: + raise NotImplementedError() + + @abc.abstractmethod + def list_credentials_with_access( + self, *, acs_entrance_id: str, include_if: Optional[List[str]] = None + ) -> List[AcsCredential]: + raise NotImplementedError() + + +class AbstractAcsSystems(abc.ABC): + + @abc.abstractmethod + def get(self, *, acs_system_id: str) -> AcsSystem: + raise NotImplementedError() + + @abc.abstractmethod + def list(self, *, connected_account_id: Optional[str] = None) -> List[AcsSystem]: + raise NotImplementedError() + + @abc.abstractmethod + def list_compatible_credential_manager_acs_systems( + self, *, acs_system_id: str + ) -> List[AcsSystem]: + raise NotImplementedError() + + +class AbstractAcsUsers(abc.ABC): + + @abc.abstractmethod + def add_to_access_group( + self, *, acs_access_group_id: str, acs_user_id: str + ) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def create( + self, + *, + acs_system_id: str, + full_name: str, + access_schedule: Optional[Dict[str, Any]] = None, + acs_access_group_ids: Optional[List[str]] = None, + email: Optional[str] = None, + email_address: Optional[str] = None, + phone_number: Optional[str] = None, + user_identity_id: Optional[str] = None + ) -> AcsUser: + raise NotImplementedError() + + @abc.abstractmethod + def delete(self, *, acs_user_id: str) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def get(self, *, acs_user_id: str) -> AcsUser: + raise NotImplementedError() + + @abc.abstractmethod + def list( + self, + *, + acs_system_id: Optional[str] = None, + created_before: Optional[str] = None, + limit: Optional[int] = None, + page_cursor: Optional[str] = None, + user_identity_email_address: Optional[str] = None, + user_identity_id: Optional[str] = None, + user_identity_phone_number: Optional[str] = None + ) -> List[AcsUser]: + raise NotImplementedError() + + @abc.abstractmethod + def list_accessible_entrances(self, *, acs_user_id: str) -> List[AcsEntrance]: + raise NotImplementedError() + + @abc.abstractmethod + def remove_from_access_group( + self, *, acs_access_group_id: str, acs_user_id: str + ) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def revoke_access_to_all_entrances(self, *, acs_user_id: str) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def suspend(self, *, acs_user_id: str) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def unsuspend(self, *, acs_user_id: str) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def update( + self, + *, + acs_user_id: str, + access_schedule: Optional[Dict[str, Any]] = None, + email: Optional[str] = None, + email_address: Optional[str] = None, + full_name: Optional[str] = None, + hid_acs_system_id: Optional[str] = None, + phone_number: Optional[str] = None + ) -> None: + raise NotImplementedError() + + +class AbstractActionAttempts(abc.ABC): + + @abc.abstractmethod + def get( + self, + *, + action_attempt_id: str, + wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = None + ) -> ActionAttempt: + raise NotImplementedError() + + @abc.abstractmethod + def list(self, *, action_attempt_ids: List[str]) -> List[ActionAttempt]: + raise NotImplementedError() + + +class AbstractBridges(abc.ABC): + + @abc.abstractmethod + def get(self, *, bridge_id: str) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def list( + self, + ) -> None: + raise NotImplementedError() + + +class AbstractClientSessions(abc.ABC): + + @abc.abstractmethod + def create( + self, + *, + connect_webview_ids: Optional[List[str]] = None, + connected_account_ids: Optional[List[str]] = None, + expires_at: Optional[str] = None, + user_identifier_key: Optional[str] = None, + user_identity_ids: Optional[List[str]] = None + ) -> ClientSession: + raise NotImplementedError() + + @abc.abstractmethod + def delete(self, *, client_session_id: str) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def get( + self, + *, + client_session_id: Optional[str] = None, + user_identifier_key: Optional[str] = None + ) -> ClientSession: + raise NotImplementedError() + + @abc.abstractmethod + def get_or_create( + self, + *, + connect_webview_ids: Optional[List[str]] = None, + connected_account_ids: Optional[List[str]] = None, + expires_at: Optional[str] = None, + user_identifier_key: Optional[str] = None, + user_identity_ids: Optional[List[str]] = None + ) -> ClientSession: + raise NotImplementedError() + + @abc.abstractmethod + def grant_access( + self, + *, + client_session_id: Optional[str] = None, + connect_webview_ids: Optional[List[str]] = None, + connected_account_ids: Optional[List[str]] = None, + user_identifier_key: Optional[str] = None, + user_identity_ids: Optional[List[str]] = None + ) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def list( + self, + *, + client_session_id: Optional[str] = None, + connect_webview_id: Optional[str] = None, + user_identifier_key: Optional[str] = None, + user_identity_id: Optional[str] = None, + without_user_identifier_key: Optional[bool] = None + ) -> List[ClientSession]: + raise NotImplementedError() + + @abc.abstractmethod + def revoke(self, *, client_session_id: str) -> None: + raise NotImplementedError() + + +class AbstractConnectWebviews(abc.ABC): + + @abc.abstractmethod + def create( + self, + *, + accepted_providers: Optional[List[str]] = None, + automatically_manage_new_devices: Optional[bool] = None, + custom_metadata: Optional[Dict[str, Any]] = None, + custom_redirect_failure_url: Optional[str] = None, + custom_redirect_url: Optional[str] = None, + device_selection_mode: Optional[str] = None, + provider_category: Optional[str] = None, + wait_for_device_creation: Optional[bool] = None + ) -> ConnectWebview: + raise NotImplementedError() + + @abc.abstractmethod + def delete(self, *, connect_webview_id: str) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def get(self, *, connect_webview_id: str) -> ConnectWebview: + raise NotImplementedError() + + @abc.abstractmethod + def list( + self, + *, + custom_metadata_has: Optional[Dict[str, Any]] = None, + limit: Optional[float] = None, + user_identifier_key: Optional[str] = None + ) -> List[ConnectWebview]: + raise NotImplementedError() + + +class AbstractConnectedAccounts(abc.ABC): + + @abc.abstractmethod + def delete(self, *, connected_account_id: str, sync: Optional[bool] = None) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def get( + self, *, connected_account_id: Optional[str] = None, email: Optional[str] = None + ) -> ConnectedAccount: + raise NotImplementedError() + + @abc.abstractmethod + def list( + self, + *, + custom_metadata_has: Optional[Dict[str, Any]] = None, + user_identifier_key: Optional[str] = None + ) -> List[ConnectedAccount]: + raise NotImplementedError() + + @abc.abstractmethod + def update( + self, + *, + connected_account_id: str, + automatically_manage_new_devices: Optional[bool] = None, + custom_metadata: Optional[Dict[str, Any]] = None + ) -> None: + raise NotImplementedError() + + +class AbstractDevicesSimulate(abc.ABC): + + @abc.abstractmethod + def connect(self, *, device_id: str) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def disconnect(self, *, device_id: str) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def remove(self, *, device_id: str) -> None: + raise NotImplementedError() + + +class AbstractDevicesUnmanaged(abc.ABC): + + @abc.abstractmethod + def get( + self, *, device_id: Optional[str] = None, name: Optional[str] = None + ) -> UnmanagedDevice: + raise NotImplementedError() + + @abc.abstractmethod + def list( + self, + *, + connect_webview_id: Optional[str] = None, + connected_account_id: Optional[str] = None, + connected_account_ids: Optional[List[str]] = None, + created_before: Optional[str] = None, + custom_metadata_has: Optional[Dict[str, Any]] = None, + device_ids: Optional[List[str]] = None, + device_type: Optional[str] = None, + device_types: Optional[List[str]] = None, + exclude_if: Optional[List[str]] = None, + include_if: Optional[List[str]] = None, + limit: Optional[float] = None, + manufacturer: Optional[str] = None, + user_identifier_key: Optional[str] = None + ) -> List[UnmanagedDevice]: + raise NotImplementedError() + + @abc.abstractmethod + def update(self, *, device_id: str, is_managed: bool) -> None: + raise NotImplementedError() + + +class AbstractEvents(abc.ABC): + + @abc.abstractmethod + def get( + self, + *, + device_id: Optional[str] = None, + event_id: Optional[str] = None, + event_type: Optional[str] = None + ) -> SeamEvent: + raise NotImplementedError() + + @abc.abstractmethod + def list( + self, + *, + access_code_id: Optional[str] = None, + access_code_ids: Optional[List[str]] = None, + acs_system_id: Optional[str] = None, + acs_system_ids: Optional[List[str]] = None, + between: Optional[List[str]] = None, + connect_webview_id: Optional[str] = None, + connected_account_id: Optional[str] = None, + device_id: Optional[str] = None, + device_ids: Optional[List[str]] = None, + event_ids: Optional[List[str]] = None, + event_type: Optional[str] = None, + event_types: Optional[List[str]] = None, + limit: Optional[float] = None, + since: Optional[str] = None, + unstable_offset: Optional[float] = None + ) -> List[SeamEvent]: + raise NotImplementedError() + + +class AbstractLocks(abc.ABC): + + @abc.abstractmethod + def get( + self, *, device_id: Optional[str] = None, name: Optional[str] = None + ) -> Device: + raise NotImplementedError() + + @abc.abstractmethod + def list( + self, + *, + connect_webview_id: Optional[str] = None, + connected_account_id: Optional[str] = None, + connected_account_ids: Optional[List[str]] = None, + created_before: Optional[str] = None, + custom_metadata_has: Optional[Dict[str, Any]] = None, + device_ids: Optional[List[str]] = None, + device_type: Optional[str] = None, + device_types: Optional[List[str]] = None, + exclude_if: Optional[List[str]] = None, + include_if: Optional[List[str]] = None, + limit: Optional[float] = None, + manufacturer: Optional[str] = None, + user_identifier_key: Optional[str] = None + ) -> List[Device]: + raise NotImplementedError() + + @abc.abstractmethod + def lock_door( + self, + *, + device_id: str, + sync: Optional[bool] = None, + wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = None + ) -> ActionAttempt: + raise NotImplementedError() + + @abc.abstractmethod + def unlock_door( + self, + *, + device_id: str, + sync: Optional[bool] = None, + wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = None + ) -> ActionAttempt: + raise NotImplementedError() + + +class AbstractNetworks(abc.ABC): + + @abc.abstractmethod + def get(self, *, network_id: str) -> Network: + raise NotImplementedError() + + @abc.abstractmethod + def list( + self, + ) -> List[Network]: + raise NotImplementedError() + + +class AbstractNoiseSensorsNoiseThresholds(abc.ABC): + + @abc.abstractmethod + def create( + self, + *, + device_id: str, + ends_daily_at: str, + starts_daily_at: str, + name: Optional[str] = None, + noise_threshold_decibels: Optional[float] = None, + noise_threshold_nrs: Optional[float] = None, + sync: Optional[bool] = None + ) -> NoiseThreshold: + raise NotImplementedError() + + @abc.abstractmethod + def delete( + self, *, device_id: str, noise_threshold_id: str, sync: Optional[bool] = None + ) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def get(self, *, noise_threshold_id: str) -> NoiseThreshold: + raise NotImplementedError() + + @abc.abstractmethod + def list( + self, *, device_id: str, is_programmed: Optional[bool] = None + ) -> List[NoiseThreshold]: + raise NotImplementedError() + + @abc.abstractmethod + def update( + self, + *, + device_id: str, + noise_threshold_id: str, + ends_daily_at: Optional[str] = None, + name: Optional[str] = None, + noise_threshold_decibels: Optional[float] = None, + noise_threshold_nrs: Optional[float] = None, + starts_daily_at: Optional[str] = None, + sync: Optional[bool] = None + ) -> None: + raise NotImplementedError() + + +class AbstractNoiseSensorsSimulate(abc.ABC): + + @abc.abstractmethod + def trigger_noise_threshold(self, *, device_id: str) -> None: + raise NotImplementedError() + + +class AbstractPhonesSimulate(abc.ABC): + + @abc.abstractmethod + def create_sandbox_phone( + self, + *, + user_identity_id: str, + assa_abloy_metadata: Optional[Dict[str, Any]] = None, + custom_sdk_installation_id: Optional[str] = None, + phone_metadata: Optional[Dict[str, Any]] = None + ) -> Phone: + raise NotImplementedError() + + +class AbstractThermostatsSchedules(abc.ABC): + + @abc.abstractmethod + def create( + self, + *, + climate_preset_key: str, + device_id: str, + ends_at: str, + starts_at: str, + is_override_allowed: Optional[bool] = None, + max_override_period_minutes: Optional[int] = None, + name: Optional[str] = None + ) -> ThermostatSchedule: + raise NotImplementedError() + + @abc.abstractmethod + def delete(self, *, thermostat_schedule_id: str) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def get(self, *, thermostat_schedule_id: str) -> ThermostatSchedule: + raise NotImplementedError() + + @abc.abstractmethod + def list( + self, *, device_id: str, user_identifier_key: Optional[str] = None + ) -> List[ThermostatSchedule]: + raise NotImplementedError() + + @abc.abstractmethod + def update( + self, + *, + thermostat_schedule_id: str, + climate_preset_key: Optional[str] = None, + ends_at: Optional[str] = None, + is_override_allowed: Optional[bool] = None, + max_override_period_minutes: Optional[int] = None, + name: Optional[str] = None, + starts_at: Optional[str] = None + ) -> None: + raise NotImplementedError() + + +class AbstractThermostatsSimulate(abc.ABC): + + @abc.abstractmethod + def hvac_mode_adjusted( + self, + *, + device_id: str, + hvac_mode: str, + cooling_set_point_celsius: Optional[float] = None, + cooling_set_point_fahrenheit: Optional[float] = None, + heating_set_point_celsius: Optional[float] = None, + heating_set_point_fahrenheit: Optional[float] = None + ) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def temperature_reached( + self, + *, + device_id: str, + temperature_celsius: Optional[float] = None, + temperature_fahrenheit: Optional[float] = None + ) -> None: + raise NotImplementedError() + + +class AbstractUserIdentitiesEnrollmentAutomations(abc.ABC): + + @abc.abstractmethod + def delete(self, *, enrollment_automation_id: str) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def get(self, *, enrollment_automation_id: str) -> EnrollmentAutomation: + raise NotImplementedError() + + @abc.abstractmethod + def launch( + self, + *, + credential_manager_acs_system_id: str, + user_identity_id: str, + acs_credential_pool_id: Optional[str] = None, + create_credential_manager_user: Optional[bool] = None, + credential_manager_acs_user_id: Optional[str] = None + ) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def list(self, *, user_identity_id: str) -> List[EnrollmentAutomation]: + raise NotImplementedError() + + +class AbstractWebhooks(abc.ABC): + + @abc.abstractmethod + def create(self, *, url: str, event_types: Optional[List[str]] = None) -> Webhook: + raise NotImplementedError() + + @abc.abstractmethod + def delete(self, *, webhook_id: str) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def get(self, *, webhook_id: str) -> Webhook: raise NotImplementedError() @abc.abstractmethod def list( - self, *, acs_system_id: Optional[str] = None, acs_user_id: Optional[str] = None - ) -> List[UnmanagedAcsAccessGroup]: + self, + ) -> List[Webhook]: + raise NotImplementedError() + + @abc.abstractmethod + def update(self, *, event_types: List[str], webhook_id: str) -> None: + raise NotImplementedError() + + +class AbstractWorkspaces(abc.ABC): + + @abc.abstractmethod + def create( + self, + *, + name: str, + company_name: Optional[str] = None, + connect_partner_name: Optional[str] = None, + is_sandbox: Optional[bool] = None, + webview_logo_shape: Optional[str] = None, + webview_primary_button_color: Optional[str] = None, + webview_primary_button_text_color: Optional[str] = None + ) -> Workspace: raise NotImplementedError() + @abc.abstractmethod + def get( + self, + ) -> Workspace: + raise NotImplementedError() -class AbstractAcsCredentialPools(abc.ABC): + @abc.abstractmethod + def list( + self, + ) -> List[Workspace]: + raise NotImplementedError() @abc.abstractmethod - def list(self, *, acs_system_id: str) -> List[AcsCredentialPool]: + def reset_sandbox( + self, wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = None + ) -> ActionAttempt: raise NotImplementedError() -class AbstractAcsCredentialProvisioningAutomations(abc.ABC): +class AbstractPhones(abc.ABC): + @property @abc.abstractmethod - def launch( + def simulate(self) -> AbstractPhonesSimulate: + raise NotImplementedError() + + @abc.abstractmethod + def deactivate(self, *, device_id: str) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def get(self, *, device_id: str) -> Phone: + raise NotImplementedError() + + @abc.abstractmethod + def list( + self, + *, + acs_credential_id: Optional[str] = None, + owner_user_identity_id: Optional[str] = None + ) -> List[Phone]: + raise NotImplementedError() + + +class AbstractUserIdentities(abc.ABC): + + @property + @abc.abstractmethod + def enrollment_automations(self) -> AbstractUserIdentitiesEnrollmentAutomations: + raise NotImplementedError() + + @abc.abstractmethod + def add_acs_user(self, *, acs_user_id: str, user_identity_id: str) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def create( + self, + *, + email_address: Optional[str] = None, + full_name: Optional[str] = None, + phone_number: Optional[str] = None, + user_identity_key: Optional[str] = None + ) -> UserIdentity: + raise NotImplementedError() + + @abc.abstractmethod + def delete(self, *, user_identity_id: str) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def get( + self, + *, + user_identity_id: Optional[str] = None, + user_identity_key: Optional[str] = None + ) -> UserIdentity: + raise NotImplementedError() + + @abc.abstractmethod + def grant_access_to_device(self, *, device_id: str, user_identity_id: str) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def list( + self, *, credential_manager_acs_system_id: Optional[str] = None + ) -> List[UserIdentity]: + raise NotImplementedError() + + @abc.abstractmethod + def list_accessible_devices(self, *, user_identity_id: str) -> List[Device]: + raise NotImplementedError() + + @abc.abstractmethod + def list_acs_systems(self, *, user_identity_id: str) -> List[AcsSystem]: + raise NotImplementedError() + + @abc.abstractmethod + def list_acs_users(self, *, user_identity_id: str) -> List[AcsUser]: + raise NotImplementedError() + + @abc.abstractmethod + def remove_acs_user(self, *, acs_user_id: str, user_identity_id: str) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def revoke_access_to_device(self, *, device_id: str, user_identity_id: str) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def update( self, *, - credential_manager_acs_system_id: str, user_identity_id: str, - acs_credential_pool_id: Optional[str] = None, - create_credential_manager_user: Optional[bool] = None, - credential_manager_acs_user_id: Optional[str] = None - ) -> AcsCredentialProvisioningAutomation: + email_address: Optional[str] = None, + full_name: Optional[str] = None, + phone_number: Optional[str] = None, + user_identity_key: Optional[str] = None + ) -> None: raise NotImplementedError() -class AbstractAcsCredentials(abc.ABC): +class AbstractAccessCodes(abc.ABC): + + @property + @abc.abstractmethod + def simulate(self) -> AbstractAccessCodesSimulate: + raise NotImplementedError() + + @property + @abc.abstractmethod + def unmanaged(self) -> AbstractAccessCodesUnmanaged: + raise NotImplementedError() @abc.abstractmethod - def create_offline_code( + def create( self, *, - acs_user_id: str, - allowed_acs_entrance_id: str, + device_id: str, + allow_external_modification: Optional[bool] = None, + attempt_for_offline_device: Optional[bool] = None, + code: Optional[str] = None, + common_code_key: Optional[str] = None, ends_at: Optional[str] = None, + is_external_modification_allowed: Optional[bool] = None, + is_offline_access_code: Optional[bool] = None, is_one_time_use: Optional[bool] = None, - starts_at: Optional[str] = None - ) -> AcsCredential: + max_time_rounding: Optional[str] = None, + name: Optional[str] = None, + prefer_native_scheduling: Optional[bool] = None, + preferred_code_length: Optional[float] = None, + starts_at: Optional[str] = None, + sync: Optional[bool] = None, + use_backup_access_code_pool: Optional[bool] = None, + use_offline_access_code: Optional[bool] = None + ) -> AccessCode: + raise NotImplementedError() + + @abc.abstractmethod + def create_multiple( + self, + *, + device_ids: List[str], + allow_external_modification: Optional[bool] = None, + attempt_for_offline_device: Optional[bool] = None, + behavior_when_code_cannot_be_shared: Optional[str] = None, + code: Optional[str] = None, + ends_at: Optional[str] = None, + is_external_modification_allowed: Optional[bool] = None, + is_offline_access_code: Optional[bool] = None, + is_one_time_use: Optional[bool] = None, + max_time_rounding: Optional[str] = None, + name: Optional[str] = None, + prefer_native_scheduling: Optional[bool] = None, + preferred_code_length: Optional[float] = None, + starts_at: Optional[str] = None, + use_backup_access_code_pool: Optional[bool] = None, + use_offline_access_code: Optional[bool] = None + ) -> List[AccessCode]: raise NotImplementedError() + @abc.abstractmethod + def delete( + self, + *, + access_code_id: str, + device_id: Optional[str] = None, + sync: Optional[bool] = None + ) -> None: + raise NotImplementedError() -class AbstractAcsCredentialsUnmanaged(abc.ABC): + @abc.abstractmethod + def generate_code(self, *, device_id: str) -> AccessCode: + raise NotImplementedError() @abc.abstractmethod - def get(self, *, acs_credential_id: str) -> UnmanagedAcsCredential: + def get( + self, + *, + access_code_id: Optional[str] = None, + code: Optional[str] = None, + device_id: Optional[str] = None + ) -> AccessCode: raise NotImplementedError() @abc.abstractmethod def list( self, *, - acs_user_id: Optional[str] = None, - acs_system_id: Optional[str] = None, - user_identity_id: Optional[str] = None - ) -> List[UnmanagedAcsCredential]: + access_code_ids: Optional[List[str]] = None, + device_id: Optional[str] = None, + user_identifier_key: Optional[str] = None + ) -> List[AccessCode]: + raise NotImplementedError() + + @abc.abstractmethod + def pull_backup_access_code(self, *, access_code_id: str) -> AccessCode: + raise NotImplementedError() + + @abc.abstractmethod + def update( + self, + *, + access_code_id: str, + allow_external_modification: Optional[bool] = None, + attempt_for_offline_device: Optional[bool] = None, + code: Optional[str] = None, + device_id: Optional[str] = None, + ends_at: Optional[str] = None, + is_external_modification_allowed: Optional[bool] = None, + is_managed: Optional[bool] = None, + is_offline_access_code: Optional[bool] = None, + is_one_time_use: Optional[bool] = None, + max_time_rounding: Optional[str] = None, + name: Optional[str] = None, + prefer_native_scheduling: Optional[bool] = None, + preferred_code_length: Optional[float] = None, + starts_at: Optional[str] = None, + sync: Optional[bool] = None, + type: Optional[str] = None, + use_backup_access_code_pool: Optional[bool] = None, + use_offline_access_code: Optional[bool] = None + ) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def update_multiple( + self, + *, + common_code_key: str, + ends_at: Optional[str] = None, + name: Optional[str] = None, + starts_at: Optional[str] = None + ) -> None: raise NotImplementedError() -class AbstractAcsUsersUnmanaged(abc.ABC): +class AbstractDevices(abc.ABC): + + @property + @abc.abstractmethod + def simulate(self) -> AbstractDevicesSimulate: + raise NotImplementedError() + + @property + @abc.abstractmethod + def unmanaged(self) -> AbstractDevicesUnmanaged: + raise NotImplementedError() @abc.abstractmethod - def get(self, *, acs_user_id: str) -> UnmanagedAcsUser: + def get( + self, *, device_id: Optional[str] = None, name: Optional[str] = None + ) -> Device: raise NotImplementedError() @abc.abstractmethod def list( self, *, - acs_system_id: Optional[str] = None, + connect_webview_id: Optional[str] = None, + connected_account_id: Optional[str] = None, + connected_account_ids: Optional[List[str]] = None, + created_before: Optional[str] = None, + custom_metadata_has: Optional[Dict[str, Any]] = None, + device_ids: Optional[List[str]] = None, + device_type: Optional[str] = None, + device_types: Optional[List[str]] = None, + exclude_if: Optional[List[str]] = None, + include_if: Optional[List[str]] = None, limit: Optional[float] = None, - user_identity_email_address: Optional[str] = None, - user_identity_id: Optional[str] = None, - user_identity_phone_number: Optional[str] = None - ) -> List[UnmanagedAcsUser]: + manufacturer: Optional[str] = None, + user_identifier_key: Optional[str] = None + ) -> List[Device]: raise NotImplementedError() + @abc.abstractmethod + def list_device_providers( + self, *, provider_category: Optional[str] = None + ) -> List[DeviceProvider]: + raise NotImplementedError() -class AbstractDevices(abc.ABC): + @abc.abstractmethod + def update( + self, + *, + device_id: str, + custom_metadata: Optional[Dict[str, Any]] = None, + is_managed: Optional[bool] = None, + name: Optional[str] = None, + properties: Optional[Dict[str, Any]] = None + ) -> None: + raise NotImplementedError() + + +class AbstractNoiseSensors(abc.ABC): + + @property + @abc.abstractmethod + def noise_thresholds(self) -> AbstractNoiseSensorsNoiseThresholds: + raise NotImplementedError() + + @property + @abc.abstractmethod + def simulate(self) -> AbstractNoiseSensorsSimulate: + raise NotImplementedError() @abc.abstractmethod - def delete(self, *, device_id: str) -> None: + def list( + self, + *, + connect_webview_id: Optional[str] = None, + connected_account_id: Optional[str] = None, + connected_account_ids: Optional[List[str]] = None, + created_before: Optional[str] = None, + custom_metadata_has: Optional[Dict[str, Any]] = None, + device_ids: Optional[List[str]] = None, + device_type: Optional[str] = None, + device_types: Optional[List[str]] = None, + exclude_if: Optional[List[str]] = None, + include_if: Optional[List[str]] = None, + limit: Optional[float] = None, + manufacturer: Optional[str] = None, + user_identifier_key: Optional[str] = None + ) -> List[Device]: raise NotImplementedError() class AbstractThermostats(abc.ABC): + @property @abc.abstractmethod - def get( - self, *, device_id: Optional[str] = None, name: Optional[str] = None - ) -> Device: + def schedules(self) -> AbstractThermostatsSchedules: + raise NotImplementedError() + + @property + @abc.abstractmethod + def simulate(self) -> AbstractThermostatsSimulate: + raise NotImplementedError() + + @abc.abstractmethod + def activate_climate_preset( + self, + *, + climate_preset_key: str, + device_id: str, + wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = None + ) -> ActionAttempt: + raise NotImplementedError() + + @abc.abstractmethod + def cool( + self, + *, + device_id: str, + cooling_set_point_celsius: Optional[float] = None, + cooling_set_point_fahrenheit: Optional[float] = None, + sync: Optional[bool] = None, + wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = None + ) -> ActionAttempt: + raise NotImplementedError() + + @abc.abstractmethod + def create_climate_preset( + self, + *, + climate_preset_key: str, + device_id: str, + cooling_set_point_celsius: Optional[float] = None, + cooling_set_point_fahrenheit: Optional[float] = None, + fan_mode_setting: Optional[str] = None, + heating_set_point_celsius: Optional[float] = None, + heating_set_point_fahrenheit: Optional[float] = None, + hvac_mode_setting: Optional[str] = None, + manual_override_allowed: Optional[bool] = None, + name: Optional[str] = None + ) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def delete_climate_preset(self, *, climate_preset_key: str, device_id: str) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def heat( + self, + *, + device_id: str, + heating_set_point_celsius: Optional[float] = None, + heating_set_point_fahrenheit: Optional[float] = None, + sync: Optional[bool] = None, + wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = None + ) -> ActionAttempt: + raise NotImplementedError() + + @abc.abstractmethod + def heat_cool( + self, + *, + device_id: str, + cooling_set_point_celsius: Optional[float] = None, + cooling_set_point_fahrenheit: Optional[float] = None, + heating_set_point_celsius: Optional[float] = None, + heating_set_point_fahrenheit: Optional[float] = None, + sync: Optional[bool] = None, + wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = None + ) -> ActionAttempt: + raise NotImplementedError() + + @abc.abstractmethod + def list( + self, + *, + connect_webview_id: Optional[str] = None, + connected_account_id: Optional[str] = None, + connected_account_ids: Optional[List[str]] = None, + created_before: Optional[str] = None, + custom_metadata_has: Optional[Dict[str, Any]] = None, + device_ids: Optional[List[str]] = None, + device_type: Optional[str] = None, + device_types: Optional[List[str]] = None, + exclude_if: Optional[List[str]] = None, + include_if: Optional[List[str]] = None, + limit: Optional[float] = None, + manufacturer: Optional[str] = None, + user_identifier_key: Optional[str] = None + ) -> List[Device]: + raise NotImplementedError() + + @abc.abstractmethod + def off( + self, + *, + device_id: str, + sync: Optional[bool] = None, + wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = None + ) -> ActionAttempt: + raise NotImplementedError() + + @abc.abstractmethod + def set_fallback_climate_preset( + self, *, climate_preset_key: str, device_id: str + ) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def set_fan_mode( + self, + *, + device_id: str, + fan_mode: Optional[str] = None, + fan_mode_setting: Optional[str] = None, + sync: Optional[bool] = None, + wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = None + ) -> ActionAttempt: + raise NotImplementedError() + + @abc.abstractmethod + def set_hvac_mode( + self, + *, + device_id: str, + hvac_mode_setting: str, + cooling_set_point_celsius: Optional[float] = None, + cooling_set_point_fahrenheit: Optional[float] = None, + heating_set_point_celsius: Optional[float] = None, + heating_set_point_fahrenheit: Optional[float] = None, + wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = None + ) -> ActionAttempt: + raise NotImplementedError() + + @abc.abstractmethod + def set_temperature_threshold( + self, + *, + device_id: str, + lower_limit_celsius: Optional[float] = None, + lower_limit_fahrenheit: Optional[float] = None, + upper_limit_celsius: Optional[float] = None, + upper_limit_fahrenheit: Optional[float] = None + ) -> None: + raise NotImplementedError() + + @abc.abstractmethod + def update_climate_preset( + self, + *, + climate_preset_key: str, + device_id: str, + manual_override_allowed: bool, + cooling_set_point_celsius: Optional[float] = None, + cooling_set_point_fahrenheit: Optional[float] = None, + fan_mode_setting: Optional[str] = None, + heating_set_point_celsius: Optional[float] = None, + heating_set_point_fahrenheit: Optional[float] = None, + hvac_mode_setting: Optional[str] = None, + name: Optional[str] = None + ) -> None: raise NotImplementedError() @@ -1269,19 +2553,22 @@ def access_groups(self) -> AbstractAcsAccessGroups: @property @abc.abstractmethod - def credential_pools(self) -> AbstractAcsCredentialPools: + def credentials(self) -> AbstractAcsCredentials: raise NotImplementedError() @property @abc.abstractmethod - def credential_provisioning_automations( - self, - ) -> AbstractAcsCredentialProvisioningAutomations: + def encoders(self) -> AbstractAcsEncoders: raise NotImplementedError() @property @abc.abstractmethod - def credentials(self) -> AbstractAcsCredentials: + def entrances(self) -> AbstractAcsEntrances: + raise NotImplementedError() + + @property + @abc.abstractmethod + def systems(self) -> AbstractAcsSystems: raise NotImplementedError() @property @@ -1292,6 +2579,20 @@ def users(self) -> AbstractAcsUsers: @dataclass class AbstractRoutes(abc.ABC): + access_codes: AbstractAccessCodes acs: AbstractAcs + action_attempts: AbstractActionAttempts + bridges: AbstractBridges + client_sessions: AbstractClientSessions + connect_webviews: AbstractConnectWebviews + connected_accounts: AbstractConnectedAccounts devices: AbstractDevices + events: AbstractEvents + locks: AbstractLocks + networks: AbstractNetworks + noise_sensors: AbstractNoiseSensors + phones: AbstractPhones thermostats: AbstractThermostats + user_identities: AbstractUserIdentities + webhooks: AbstractWebhooks + workspaces: AbstractWorkspaces diff --git a/seam/routes/networks.py b/seam/routes/networks.py new file mode 100644 index 0000000..22cceb1 --- /dev/null +++ b/seam/routes/networks.py @@ -0,0 +1,28 @@ +from typing import Optional, Any, List, Dict, Union +from ..client import SeamHttpClient +from .models import AbstractNetworks, Network + + +class Networks(AbstractNetworks): + def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.client = client + self.defaults = defaults + + def get(self, *, network_id: str) -> Network: + json_payload = {} + + if network_id is not None: + json_payload["network_id"] = network_id + + res = self.client.post("/networks/get", json=json_payload) + + return Network.from_dict(res["network"]) + + def list( + self, + ) -> List[Network]: + json_payload = {} + + res = self.client.post("/networks/list", json=json_payload) + + return [Network.from_dict(item) for item in res["networks"]] diff --git a/seam/routes/noise_sensors.py b/seam/routes/noise_sensors.py new file mode 100644 index 0000000..b163194 --- /dev/null +++ b/seam/routes/noise_sensors.py @@ -0,0 +1,73 @@ +from typing import Optional, Any, List, Dict, Union +from ..client import SeamHttpClient +from .models import AbstractNoiseSensors, Device +from .noise_sensors_noise_thresholds import NoiseSensorsNoiseThresholds +from .noise_sensors_simulate import NoiseSensorsSimulate + + +class NoiseSensors(AbstractNoiseSensors): + def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.client = client + self.defaults = defaults + self._noise_thresholds = NoiseSensorsNoiseThresholds( + client=client, defaults=defaults + ) + self._simulate = NoiseSensorsSimulate(client=client, defaults=defaults) + + @property + def noise_thresholds(self) -> NoiseSensorsNoiseThresholds: + return self._noise_thresholds + + @property + def simulate(self) -> NoiseSensorsSimulate: + return self._simulate + + def list( + self, + *, + connect_webview_id: Optional[str] = None, + connected_account_id: Optional[str] = None, + connected_account_ids: Optional[List[str]] = None, + created_before: Optional[str] = None, + custom_metadata_has: Optional[Dict[str, Any]] = None, + device_ids: Optional[List[str]] = None, + device_type: Optional[str] = None, + device_types: Optional[List[str]] = None, + exclude_if: Optional[List[str]] = None, + include_if: Optional[List[str]] = None, + limit: Optional[float] = None, + manufacturer: Optional[str] = None, + user_identifier_key: Optional[str] = None + ) -> List[Device]: + json_payload = {} + + if connect_webview_id is not None: + json_payload["connect_webview_id"] = connect_webview_id + if connected_account_id is not None: + json_payload["connected_account_id"] = connected_account_id + if connected_account_ids is not None: + json_payload["connected_account_ids"] = connected_account_ids + if created_before is not None: + json_payload["created_before"] = created_before + if custom_metadata_has is not None: + json_payload["custom_metadata_has"] = custom_metadata_has + if device_ids is not None: + json_payload["device_ids"] = device_ids + if device_type is not None: + json_payload["device_type"] = device_type + if device_types is not None: + json_payload["device_types"] = device_types + if exclude_if is not None: + json_payload["exclude_if"] = exclude_if + if include_if is not None: + json_payload["include_if"] = include_if + if limit is not None: + json_payload["limit"] = limit + if manufacturer is not None: + json_payload["manufacturer"] = manufacturer + if user_identifier_key is not None: + json_payload["user_identifier_key"] = user_identifier_key + + res = self.client.post("/noise_sensors/list", json=json_payload) + + return [Device.from_dict(item) for item in res["devices"]] diff --git a/seam/routes/noise_sensors_noise_thresholds.py b/seam/routes/noise_sensors_noise_thresholds.py new file mode 100644 index 0000000..815dc60 --- /dev/null +++ b/seam/routes/noise_sensors_noise_thresholds.py @@ -0,0 +1,120 @@ +from typing import Optional, Any, List, Dict, Union +from ..client import SeamHttpClient +from .models import AbstractNoiseSensorsNoiseThresholds, NoiseThreshold + + +class NoiseSensorsNoiseThresholds(AbstractNoiseSensorsNoiseThresholds): + def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.client = client + self.defaults = defaults + + def create( + self, + *, + device_id: str, + ends_daily_at: str, + starts_daily_at: str, + name: Optional[str] = None, + noise_threshold_decibels: Optional[float] = None, + noise_threshold_nrs: Optional[float] = None, + sync: Optional[bool] = None + ) -> NoiseThreshold: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + if ends_daily_at is not None: + json_payload["ends_daily_at"] = ends_daily_at + if starts_daily_at is not None: + json_payload["starts_daily_at"] = starts_daily_at + if name is not None: + json_payload["name"] = name + if noise_threshold_decibels is not None: + json_payload["noise_threshold_decibels"] = noise_threshold_decibels + if noise_threshold_nrs is not None: + json_payload["noise_threshold_nrs"] = noise_threshold_nrs + if sync is not None: + json_payload["sync"] = sync + + res = self.client.post( + "/noise_sensors/noise_thresholds/create", json=json_payload + ) + + return NoiseThreshold.from_dict(res["noise_threshold"]) + + def delete( + self, *, device_id: str, noise_threshold_id: str, sync: Optional[bool] = None + ) -> None: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + if noise_threshold_id is not None: + json_payload["noise_threshold_id"] = noise_threshold_id + if sync is not None: + json_payload["sync"] = sync + + self.client.post("/noise_sensors/noise_thresholds/delete", json=json_payload) + + return None + + def get(self, *, noise_threshold_id: str) -> NoiseThreshold: + json_payload = {} + + if noise_threshold_id is not None: + json_payload["noise_threshold_id"] = noise_threshold_id + + res = self.client.post("/noise_sensors/noise_thresholds/get", json=json_payload) + + return NoiseThreshold.from_dict(res["noise_threshold"]) + + def list( + self, *, device_id: str, is_programmed: Optional[bool] = None + ) -> List[NoiseThreshold]: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + if is_programmed is not None: + json_payload["is_programmed"] = is_programmed + + res = self.client.post( + "/noise_sensors/noise_thresholds/list", json=json_payload + ) + + return [NoiseThreshold.from_dict(item) for item in res["noise_thresholds"]] + + def update( + self, + *, + device_id: str, + noise_threshold_id: str, + ends_daily_at: Optional[str] = None, + name: Optional[str] = None, + noise_threshold_decibels: Optional[float] = None, + noise_threshold_nrs: Optional[float] = None, + starts_daily_at: Optional[str] = None, + sync: Optional[bool] = None + ) -> None: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + if noise_threshold_id is not None: + json_payload["noise_threshold_id"] = noise_threshold_id + if ends_daily_at is not None: + json_payload["ends_daily_at"] = ends_daily_at + if name is not None: + json_payload["name"] = name + if noise_threshold_decibels is not None: + json_payload["noise_threshold_decibels"] = noise_threshold_decibels + if noise_threshold_nrs is not None: + json_payload["noise_threshold_nrs"] = noise_threshold_nrs + if starts_daily_at is not None: + json_payload["starts_daily_at"] = starts_daily_at + if sync is not None: + json_payload["sync"] = sync + + self.client.post("/noise_sensors/noise_thresholds/update", json=json_payload) + + return None diff --git a/seam/routes/noise_sensors_simulate.py b/seam/routes/noise_sensors_simulate.py new file mode 100644 index 0000000..d69e2f3 --- /dev/null +++ b/seam/routes/noise_sensors_simulate.py @@ -0,0 +1,21 @@ +from typing import Optional, Any, List, Dict, Union +from ..client import SeamHttpClient +from .models import AbstractNoiseSensorsSimulate + + +class NoiseSensorsSimulate(AbstractNoiseSensorsSimulate): + def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.client = client + self.defaults = defaults + + def trigger_noise_threshold(self, *, device_id: str) -> None: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + + self.client.post( + "/noise_sensors/simulate/trigger_noise_threshold", json=json_payload + ) + + return None diff --git a/seam/routes/phones.py b/seam/routes/phones.py new file mode 100644 index 0000000..7126f4d --- /dev/null +++ b/seam/routes/phones.py @@ -0,0 +1,52 @@ +from typing import Optional, Any, List, Dict, Union +from ..client import SeamHttpClient +from .models import AbstractPhones, Phone +from .phones_simulate import PhonesSimulate + + +class Phones(AbstractPhones): + def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.client = client + self.defaults = defaults + self._simulate = PhonesSimulate(client=client, defaults=defaults) + + @property + def simulate(self) -> PhonesSimulate: + return self._simulate + + def deactivate(self, *, device_id: str) -> None: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + + self.client.post("/phones/deactivate", json=json_payload) + + return None + + def get(self, *, device_id: str) -> Phone: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + + res = self.client.post("/phones/get", json=json_payload) + + return Phone.from_dict(res["phone"]) + + def list( + self, + *, + acs_credential_id: Optional[str] = None, + owner_user_identity_id: Optional[str] = None + ) -> List[Phone]: + json_payload = {} + + if acs_credential_id is not None: + json_payload["acs_credential_id"] = acs_credential_id + if owner_user_identity_id is not None: + json_payload["owner_user_identity_id"] = owner_user_identity_id + + res = self.client.post("/phones/list", json=json_payload) + + return [Phone.from_dict(item) for item in res["phones"]] diff --git a/seam/routes/phones_simulate.py b/seam/routes/phones_simulate.py new file mode 100644 index 0000000..9140964 --- /dev/null +++ b/seam/routes/phones_simulate.py @@ -0,0 +1,34 @@ +from typing import Optional, Any, List, Dict, Union +from ..client import SeamHttpClient +from .models import AbstractPhonesSimulate, Phone + + +class PhonesSimulate(AbstractPhonesSimulate): + def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.client = client + self.defaults = defaults + + def create_sandbox_phone( + self, + *, + user_identity_id: str, + assa_abloy_metadata: Optional[Dict[str, Any]] = None, + custom_sdk_installation_id: Optional[str] = None, + phone_metadata: Optional[Dict[str, Any]] = None + ) -> Phone: + json_payload = {} + + if user_identity_id is not None: + json_payload["user_identity_id"] = user_identity_id + if assa_abloy_metadata is not None: + json_payload["assa_abloy_metadata"] = assa_abloy_metadata + if custom_sdk_installation_id is not None: + json_payload["custom_sdk_installation_id"] = custom_sdk_installation_id + if phone_metadata is not None: + json_payload["phone_metadata"] = phone_metadata + + res = self.client.post( + "/phones/simulate/create_sandbox_phone", json=json_payload + ) + + return Phone.from_dict(res["phone"]) diff --git a/seam/routes/thermostats.py b/seam/routes/thermostats.py index d4300b9..396392f 100644 --- a/seam/routes/thermostats.py +++ b/seam/routes/thermostats.py @@ -1,23 +1,446 @@ from typing import Optional, Any, List, Dict, Union from ..client import SeamHttpClient -from .models import AbstractThermostats, Device +from .models import AbstractThermostats, ActionAttempt, Device +from .thermostats_schedules import ThermostatsSchedules +from .thermostats_simulate import ThermostatsSimulate +from ..modules.action_attempts import resolve_action_attempt class Thermostats(AbstractThermostats): def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): self.client = client self.defaults = defaults + self._schedules = ThermostatsSchedules(client=client, defaults=defaults) + self._simulate = ThermostatsSimulate(client=client, defaults=defaults) - def get( - self, *, device_id: Optional[str] = None, name: Optional[str] = None - ) -> Device: + @property + def schedules(self) -> ThermostatsSchedules: + return self._schedules + + @property + def simulate(self) -> ThermostatsSimulate: + return self._simulate + + def activate_climate_preset( + self, + *, + climate_preset_key: str, + device_id: str, + wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = None + ) -> ActionAttempt: + json_payload = {} + + if climate_preset_key is not None: + json_payload["climate_preset_key"] = climate_preset_key + if device_id is not None: + json_payload["device_id"] = device_id + + res = self.client.post( + "/thermostats/activate_climate_preset", json=json_payload + ) + + wait_for_action_attempt = ( + self.defaults.get("wait_for_action_attempt") + if wait_for_action_attempt is None + else wait_for_action_attempt + ) + + return resolve_action_attempt( + client=self.client, + action_attempt=ActionAttempt.from_dict(res["action_attempt"]), + wait_for_action_attempt=wait_for_action_attempt, + ) + + def cool( + self, + *, + device_id: str, + cooling_set_point_celsius: Optional[float] = None, + cooling_set_point_fahrenheit: Optional[float] = None, + sync: Optional[bool] = None, + wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = None + ) -> ActionAttempt: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + if cooling_set_point_celsius is not None: + json_payload["cooling_set_point_celsius"] = cooling_set_point_celsius + if cooling_set_point_fahrenheit is not None: + json_payload["cooling_set_point_fahrenheit"] = cooling_set_point_fahrenheit + if sync is not None: + json_payload["sync"] = sync + + res = self.client.post("/thermostats/cool", json=json_payload) + + wait_for_action_attempt = ( + self.defaults.get("wait_for_action_attempt") + if wait_for_action_attempt is None + else wait_for_action_attempt + ) + + return resolve_action_attempt( + client=self.client, + action_attempt=ActionAttempt.from_dict(res["action_attempt"]), + wait_for_action_attempt=wait_for_action_attempt, + ) + + def create_climate_preset( + self, + *, + climate_preset_key: str, + device_id: str, + cooling_set_point_celsius: Optional[float] = None, + cooling_set_point_fahrenheit: Optional[float] = None, + fan_mode_setting: Optional[str] = None, + heating_set_point_celsius: Optional[float] = None, + heating_set_point_fahrenheit: Optional[float] = None, + hvac_mode_setting: Optional[str] = None, + manual_override_allowed: Optional[bool] = None, + name: Optional[str] = None + ) -> None: + json_payload = {} + + if climate_preset_key is not None: + json_payload["climate_preset_key"] = climate_preset_key + if device_id is not None: + json_payload["device_id"] = device_id + if cooling_set_point_celsius is not None: + json_payload["cooling_set_point_celsius"] = cooling_set_point_celsius + if cooling_set_point_fahrenheit is not None: + json_payload["cooling_set_point_fahrenheit"] = cooling_set_point_fahrenheit + if fan_mode_setting is not None: + json_payload["fan_mode_setting"] = fan_mode_setting + if heating_set_point_celsius is not None: + json_payload["heating_set_point_celsius"] = heating_set_point_celsius + if heating_set_point_fahrenheit is not None: + json_payload["heating_set_point_fahrenheit"] = heating_set_point_fahrenheit + if hvac_mode_setting is not None: + json_payload["hvac_mode_setting"] = hvac_mode_setting + if manual_override_allowed is not None: + json_payload["manual_override_allowed"] = manual_override_allowed + if name is not None: + json_payload["name"] = name + + self.client.post("/thermostats/create_climate_preset", json=json_payload) + + return None + + def delete_climate_preset(self, *, climate_preset_key: str, device_id: str) -> None: + json_payload = {} + + if climate_preset_key is not None: + json_payload["climate_preset_key"] = climate_preset_key + if device_id is not None: + json_payload["device_id"] = device_id + + self.client.post("/thermostats/delete_climate_preset", json=json_payload) + + return None + + def heat( + self, + *, + device_id: str, + heating_set_point_celsius: Optional[float] = None, + heating_set_point_fahrenheit: Optional[float] = None, + sync: Optional[bool] = None, + wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = None + ) -> ActionAttempt: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + if heating_set_point_celsius is not None: + json_payload["heating_set_point_celsius"] = heating_set_point_celsius + if heating_set_point_fahrenheit is not None: + json_payload["heating_set_point_fahrenheit"] = heating_set_point_fahrenheit + if sync is not None: + json_payload["sync"] = sync + + res = self.client.post("/thermostats/heat", json=json_payload) + + wait_for_action_attempt = ( + self.defaults.get("wait_for_action_attempt") + if wait_for_action_attempt is None + else wait_for_action_attempt + ) + + return resolve_action_attempt( + client=self.client, + action_attempt=ActionAttempt.from_dict(res["action_attempt"]), + wait_for_action_attempt=wait_for_action_attempt, + ) + + def heat_cool( + self, + *, + device_id: str, + cooling_set_point_celsius: Optional[float] = None, + cooling_set_point_fahrenheit: Optional[float] = None, + heating_set_point_celsius: Optional[float] = None, + heating_set_point_fahrenheit: Optional[float] = None, + sync: Optional[bool] = None, + wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = None + ) -> ActionAttempt: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + if cooling_set_point_celsius is not None: + json_payload["cooling_set_point_celsius"] = cooling_set_point_celsius + if cooling_set_point_fahrenheit is not None: + json_payload["cooling_set_point_fahrenheit"] = cooling_set_point_fahrenheit + if heating_set_point_celsius is not None: + json_payload["heating_set_point_celsius"] = heating_set_point_celsius + if heating_set_point_fahrenheit is not None: + json_payload["heating_set_point_fahrenheit"] = heating_set_point_fahrenheit + if sync is not None: + json_payload["sync"] = sync + + res = self.client.post("/thermostats/heat_cool", json=json_payload) + + wait_for_action_attempt = ( + self.defaults.get("wait_for_action_attempt") + if wait_for_action_attempt is None + else wait_for_action_attempt + ) + + return resolve_action_attempt( + client=self.client, + action_attempt=ActionAttempt.from_dict(res["action_attempt"]), + wait_for_action_attempt=wait_for_action_attempt, + ) + + def list( + self, + *, + connect_webview_id: Optional[str] = None, + connected_account_id: Optional[str] = None, + connected_account_ids: Optional[List[str]] = None, + created_before: Optional[str] = None, + custom_metadata_has: Optional[Dict[str, Any]] = None, + device_ids: Optional[List[str]] = None, + device_type: Optional[str] = None, + device_types: Optional[List[str]] = None, + exclude_if: Optional[List[str]] = None, + include_if: Optional[List[str]] = None, + limit: Optional[float] = None, + manufacturer: Optional[str] = None, + user_identifier_key: Optional[str] = None + ) -> List[Device]: + json_payload = {} + + if connect_webview_id is not None: + json_payload["connect_webview_id"] = connect_webview_id + if connected_account_id is not None: + json_payload["connected_account_id"] = connected_account_id + if connected_account_ids is not None: + json_payload["connected_account_ids"] = connected_account_ids + if created_before is not None: + json_payload["created_before"] = created_before + if custom_metadata_has is not None: + json_payload["custom_metadata_has"] = custom_metadata_has + if device_ids is not None: + json_payload["device_ids"] = device_ids + if device_type is not None: + json_payload["device_type"] = device_type + if device_types is not None: + json_payload["device_types"] = device_types + if exclude_if is not None: + json_payload["exclude_if"] = exclude_if + if include_if is not None: + json_payload["include_if"] = include_if + if limit is not None: + json_payload["limit"] = limit + if manufacturer is not None: + json_payload["manufacturer"] = manufacturer + if user_identifier_key is not None: + json_payload["user_identifier_key"] = user_identifier_key + + res = self.client.post("/thermostats/list", json=json_payload) + + return [Device.from_dict(item) for item in res["devices"]] + + def off( + self, + *, + device_id: str, + sync: Optional[bool] = None, + wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = None + ) -> ActionAttempt: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + if sync is not None: + json_payload["sync"] = sync + + res = self.client.post("/thermostats/off", json=json_payload) + + wait_for_action_attempt = ( + self.defaults.get("wait_for_action_attempt") + if wait_for_action_attempt is None + else wait_for_action_attempt + ) + + return resolve_action_attempt( + client=self.client, + action_attempt=ActionAttempt.from_dict(res["action_attempt"]), + wait_for_action_attempt=wait_for_action_attempt, + ) + + def set_fallback_climate_preset( + self, *, climate_preset_key: str, device_id: str + ) -> None: + json_payload = {} + + if climate_preset_key is not None: + json_payload["climate_preset_key"] = climate_preset_key + if device_id is not None: + json_payload["device_id"] = device_id + + self.client.post("/thermostats/set_fallback_climate_preset", json=json_payload) + + return None + + def set_fan_mode( + self, + *, + device_id: str, + fan_mode: Optional[str] = None, + fan_mode_setting: Optional[str] = None, + sync: Optional[bool] = None, + wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = None + ) -> ActionAttempt: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + if fan_mode is not None: + json_payload["fan_mode"] = fan_mode + if fan_mode_setting is not None: + json_payload["fan_mode_setting"] = fan_mode_setting + if sync is not None: + json_payload["sync"] = sync + + res = self.client.post("/thermostats/set_fan_mode", json=json_payload) + + wait_for_action_attempt = ( + self.defaults.get("wait_for_action_attempt") + if wait_for_action_attempt is None + else wait_for_action_attempt + ) + + return resolve_action_attempt( + client=self.client, + action_attempt=ActionAttempt.from_dict(res["action_attempt"]), + wait_for_action_attempt=wait_for_action_attempt, + ) + + def set_hvac_mode( + self, + *, + device_id: str, + hvac_mode_setting: str, + cooling_set_point_celsius: Optional[float] = None, + cooling_set_point_fahrenheit: Optional[float] = None, + heating_set_point_celsius: Optional[float] = None, + heating_set_point_fahrenheit: Optional[float] = None, + wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = None + ) -> ActionAttempt: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + if hvac_mode_setting is not None: + json_payload["hvac_mode_setting"] = hvac_mode_setting + if cooling_set_point_celsius is not None: + json_payload["cooling_set_point_celsius"] = cooling_set_point_celsius + if cooling_set_point_fahrenheit is not None: + json_payload["cooling_set_point_fahrenheit"] = cooling_set_point_fahrenheit + if heating_set_point_celsius is not None: + json_payload["heating_set_point_celsius"] = heating_set_point_celsius + if heating_set_point_fahrenheit is not None: + json_payload["heating_set_point_fahrenheit"] = heating_set_point_fahrenheit + + res = self.client.post("/thermostats/set_hvac_mode", json=json_payload) + + wait_for_action_attempt = ( + self.defaults.get("wait_for_action_attempt") + if wait_for_action_attempt is None + else wait_for_action_attempt + ) + + return resolve_action_attempt( + client=self.client, + action_attempt=ActionAttempt.from_dict(res["action_attempt"]), + wait_for_action_attempt=wait_for_action_attempt, + ) + + def set_temperature_threshold( + self, + *, + device_id: str, + lower_limit_celsius: Optional[float] = None, + lower_limit_fahrenheit: Optional[float] = None, + upper_limit_celsius: Optional[float] = None, + upper_limit_fahrenheit: Optional[float] = None + ) -> None: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + if lower_limit_celsius is not None: + json_payload["lower_limit_celsius"] = lower_limit_celsius + if lower_limit_fahrenheit is not None: + json_payload["lower_limit_fahrenheit"] = lower_limit_fahrenheit + if upper_limit_celsius is not None: + json_payload["upper_limit_celsius"] = upper_limit_celsius + if upper_limit_fahrenheit is not None: + json_payload["upper_limit_fahrenheit"] = upper_limit_fahrenheit + + self.client.post("/thermostats/set_temperature_threshold", json=json_payload) + + return None + + def update_climate_preset( + self, + *, + climate_preset_key: str, + device_id: str, + manual_override_allowed: bool, + cooling_set_point_celsius: Optional[float] = None, + cooling_set_point_fahrenheit: Optional[float] = None, + fan_mode_setting: Optional[str] = None, + heating_set_point_celsius: Optional[float] = None, + heating_set_point_fahrenheit: Optional[float] = None, + hvac_mode_setting: Optional[str] = None, + name: Optional[str] = None + ) -> None: json_payload = {} + if climate_preset_key is not None: + json_payload["climate_preset_key"] = climate_preset_key if device_id is not None: json_payload["device_id"] = device_id + if manual_override_allowed is not None: + json_payload["manual_override_allowed"] = manual_override_allowed + if cooling_set_point_celsius is not None: + json_payload["cooling_set_point_celsius"] = cooling_set_point_celsius + if cooling_set_point_fahrenheit is not None: + json_payload["cooling_set_point_fahrenheit"] = cooling_set_point_fahrenheit + if fan_mode_setting is not None: + json_payload["fan_mode_setting"] = fan_mode_setting + if heating_set_point_celsius is not None: + json_payload["heating_set_point_celsius"] = heating_set_point_celsius + if heating_set_point_fahrenheit is not None: + json_payload["heating_set_point_fahrenheit"] = heating_set_point_fahrenheit + if hvac_mode_setting is not None: + json_payload["hvac_mode_setting"] = hvac_mode_setting if name is not None: json_payload["name"] = name - res = self.client.post("/thermostats/get", json=json_payload) + self.client.post("/thermostats/update_climate_preset", json=json_payload) - return Device.from_dict(res["thermostat"]) + return None diff --git a/seam/routes/thermostats_schedules.py b/seam/routes/thermostats_schedules.py new file mode 100644 index 0000000..1632d58 --- /dev/null +++ b/seam/routes/thermostats_schedules.py @@ -0,0 +1,109 @@ +from typing import Optional, Any, List, Dict, Union +from ..client import SeamHttpClient +from .models import AbstractThermostatsSchedules, ThermostatSchedule + + +class ThermostatsSchedules(AbstractThermostatsSchedules): + def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.client = client + self.defaults = defaults + + def create( + self, + *, + climate_preset_key: str, + device_id: str, + ends_at: str, + starts_at: str, + is_override_allowed: Optional[bool] = None, + max_override_period_minutes: Optional[int] = None, + name: Optional[str] = None + ) -> ThermostatSchedule: + json_payload = {} + + if climate_preset_key is not None: + json_payload["climate_preset_key"] = climate_preset_key + if device_id is not None: + json_payload["device_id"] = device_id + if ends_at is not None: + json_payload["ends_at"] = ends_at + if starts_at is not None: + json_payload["starts_at"] = starts_at + if is_override_allowed is not None: + json_payload["is_override_allowed"] = is_override_allowed + if max_override_period_minutes is not None: + json_payload["max_override_period_minutes"] = max_override_period_minutes + if name is not None: + json_payload["name"] = name + + res = self.client.post("/thermostats/schedules/create", json=json_payload) + + return ThermostatSchedule.from_dict(res["thermostat_schedule"]) + + def delete(self, *, thermostat_schedule_id: str) -> None: + json_payload = {} + + if thermostat_schedule_id is not None: + json_payload["thermostat_schedule_id"] = thermostat_schedule_id + + self.client.post("/thermostats/schedules/delete", json=json_payload) + + return None + + def get(self, *, thermostat_schedule_id: str) -> ThermostatSchedule: + json_payload = {} + + if thermostat_schedule_id is not None: + json_payload["thermostat_schedule_id"] = thermostat_schedule_id + + res = self.client.post("/thermostats/schedules/get", json=json_payload) + + return ThermostatSchedule.from_dict(res["thermostat_schedule"]) + + def list( + self, *, device_id: str, user_identifier_key: Optional[str] = None + ) -> List[ThermostatSchedule]: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + if user_identifier_key is not None: + json_payload["user_identifier_key"] = user_identifier_key + + res = self.client.post("/thermostats/schedules/list", json=json_payload) + + return [ + ThermostatSchedule.from_dict(item) for item in res["thermostat_schedules"] + ] + + def update( + self, + *, + thermostat_schedule_id: str, + climate_preset_key: Optional[str] = None, + ends_at: Optional[str] = None, + is_override_allowed: Optional[bool] = None, + max_override_period_minutes: Optional[int] = None, + name: Optional[str] = None, + starts_at: Optional[str] = None + ) -> None: + json_payload = {} + + if thermostat_schedule_id is not None: + json_payload["thermostat_schedule_id"] = thermostat_schedule_id + if climate_preset_key is not None: + json_payload["climate_preset_key"] = climate_preset_key + if ends_at is not None: + json_payload["ends_at"] = ends_at + if is_override_allowed is not None: + json_payload["is_override_allowed"] = is_override_allowed + if max_override_period_minutes is not None: + json_payload["max_override_period_minutes"] = max_override_period_minutes + if name is not None: + json_payload["name"] = name + if starts_at is not None: + json_payload["starts_at"] = starts_at + + self.client.post("/thermostats/schedules/update", json=json_payload) + + return None diff --git a/seam/routes/thermostats_simulate.py b/seam/routes/thermostats_simulate.py new file mode 100644 index 0000000..d738b3b --- /dev/null +++ b/seam/routes/thermostats_simulate.py @@ -0,0 +1,58 @@ +from typing import Optional, Any, List, Dict, Union +from ..client import SeamHttpClient +from .models import AbstractThermostatsSimulate + + +class ThermostatsSimulate(AbstractThermostatsSimulate): + def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.client = client + self.defaults = defaults + + def hvac_mode_adjusted( + self, + *, + device_id: str, + hvac_mode: str, + cooling_set_point_celsius: Optional[float] = None, + cooling_set_point_fahrenheit: Optional[float] = None, + heating_set_point_celsius: Optional[float] = None, + heating_set_point_fahrenheit: Optional[float] = None + ) -> None: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + if hvac_mode is not None: + json_payload["hvac_mode"] = hvac_mode + if cooling_set_point_celsius is not None: + json_payload["cooling_set_point_celsius"] = cooling_set_point_celsius + if cooling_set_point_fahrenheit is not None: + json_payload["cooling_set_point_fahrenheit"] = cooling_set_point_fahrenheit + if heating_set_point_celsius is not None: + json_payload["heating_set_point_celsius"] = heating_set_point_celsius + if heating_set_point_fahrenheit is not None: + json_payload["heating_set_point_fahrenheit"] = heating_set_point_fahrenheit + + self.client.post("/thermostats/simulate/hvac_mode_adjusted", json=json_payload) + + return None + + def temperature_reached( + self, + *, + device_id: str, + temperature_celsius: Optional[float] = None, + temperature_fahrenheit: Optional[float] = None + ) -> None: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + if temperature_celsius is not None: + json_payload["temperature_celsius"] = temperature_celsius + if temperature_fahrenheit is not None: + json_payload["temperature_fahrenheit"] = temperature_fahrenheit + + self.client.post("/thermostats/simulate/temperature_reached", json=json_payload) + + return None diff --git a/seam/routes/user_identities.py b/seam/routes/user_identities.py new file mode 100644 index 0000000..d6e2ab9 --- /dev/null +++ b/seam/routes/user_identities.py @@ -0,0 +1,187 @@ +from typing import Optional, Any, List, Dict, Union +from ..client import SeamHttpClient +from .models import AbstractUserIdentities, UserIdentity, Device, AcsSystem, AcsUser +from .user_identities_enrollment_automations import UserIdentitiesEnrollmentAutomations + + +class UserIdentities(AbstractUserIdentities): + def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.client = client + self.defaults = defaults + self._enrollment_automations = UserIdentitiesEnrollmentAutomations( + client=client, defaults=defaults + ) + + @property + def enrollment_automations(self) -> UserIdentitiesEnrollmentAutomations: + return self._enrollment_automations + + def add_acs_user(self, *, acs_user_id: str, user_identity_id: str) -> None: + json_payload = {} + + if acs_user_id is not None: + json_payload["acs_user_id"] = acs_user_id + if user_identity_id is not None: + json_payload["user_identity_id"] = user_identity_id + + self.client.post("/user_identities/add_acs_user", json=json_payload) + + return None + + def create( + self, + *, + email_address: Optional[str] = None, + full_name: Optional[str] = None, + phone_number: Optional[str] = None, + user_identity_key: Optional[str] = None + ) -> UserIdentity: + json_payload = {} + + if email_address is not None: + json_payload["email_address"] = email_address + if full_name is not None: + json_payload["full_name"] = full_name + if phone_number is not None: + json_payload["phone_number"] = phone_number + if user_identity_key is not None: + json_payload["user_identity_key"] = user_identity_key + + res = self.client.post("/user_identities/create", json=json_payload) + + return UserIdentity.from_dict(res["user_identity"]) + + def delete(self, *, user_identity_id: str) -> None: + json_payload = {} + + if user_identity_id is not None: + json_payload["user_identity_id"] = user_identity_id + + self.client.post("/user_identities/delete", json=json_payload) + + return None + + def get( + self, + *, + user_identity_id: Optional[str] = None, + user_identity_key: Optional[str] = None + ) -> UserIdentity: + json_payload = {} + + if user_identity_id is not None: + json_payload["user_identity_id"] = user_identity_id + if user_identity_key is not None: + json_payload["user_identity_key"] = user_identity_key + + res = self.client.post("/user_identities/get", json=json_payload) + + return UserIdentity.from_dict(res["user_identity"]) + + def grant_access_to_device(self, *, device_id: str, user_identity_id: str) -> None: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + if user_identity_id is not None: + json_payload["user_identity_id"] = user_identity_id + + self.client.post("/user_identities/grant_access_to_device", json=json_payload) + + return None + + def list( + self, *, credential_manager_acs_system_id: Optional[str] = None + ) -> List[UserIdentity]: + json_payload = {} + + if credential_manager_acs_system_id is not None: + json_payload["credential_manager_acs_system_id"] = ( + credential_manager_acs_system_id + ) + + res = self.client.post("/user_identities/list", json=json_payload) + + return [UserIdentity.from_dict(item) for item in res["user_identities"]] + + def list_accessible_devices(self, *, user_identity_id: str) -> List[Device]: + json_payload = {} + + if user_identity_id is not None: + json_payload["user_identity_id"] = user_identity_id + + res = self.client.post( + "/user_identities/list_accessible_devices", json=json_payload + ) + + return [Device.from_dict(item) for item in res["devices"]] + + def list_acs_systems(self, *, user_identity_id: str) -> List[AcsSystem]: + json_payload = {} + + if user_identity_id is not None: + json_payload["user_identity_id"] = user_identity_id + + res = self.client.post("/user_identities/list_acs_systems", json=json_payload) + + return [AcsSystem.from_dict(item) for item in res["acs_systems"]] + + def list_acs_users(self, *, user_identity_id: str) -> List[AcsUser]: + json_payload = {} + + if user_identity_id is not None: + json_payload["user_identity_id"] = user_identity_id + + res = self.client.post("/user_identities/list_acs_users", json=json_payload) + + return [AcsUser.from_dict(item) for item in res["acs_users"]] + + def remove_acs_user(self, *, acs_user_id: str, user_identity_id: str) -> None: + json_payload = {} + + if acs_user_id is not None: + json_payload["acs_user_id"] = acs_user_id + if user_identity_id is not None: + json_payload["user_identity_id"] = user_identity_id + + self.client.post("/user_identities/remove_acs_user", json=json_payload) + + return None + + def revoke_access_to_device(self, *, device_id: str, user_identity_id: str) -> None: + json_payload = {} + + if device_id is not None: + json_payload["device_id"] = device_id + if user_identity_id is not None: + json_payload["user_identity_id"] = user_identity_id + + self.client.post("/user_identities/revoke_access_to_device", json=json_payload) + + return None + + def update( + self, + *, + user_identity_id: str, + email_address: Optional[str] = None, + full_name: Optional[str] = None, + phone_number: Optional[str] = None, + user_identity_key: Optional[str] = None + ) -> None: + json_payload = {} + + if user_identity_id is not None: + json_payload["user_identity_id"] = user_identity_id + if email_address is not None: + json_payload["email_address"] = email_address + if full_name is not None: + json_payload["full_name"] = full_name + if phone_number is not None: + json_payload["phone_number"] = phone_number + if user_identity_key is not None: + json_payload["user_identity_key"] = user_identity_key + + self.client.post("/user_identities/update", json=json_payload) + + return None diff --git a/seam/routes/user_identities_enrollment_automations.py b/seam/routes/user_identities_enrollment_automations.py new file mode 100644 index 0000000..4edbf2a --- /dev/null +++ b/seam/routes/user_identities_enrollment_automations.py @@ -0,0 +1,82 @@ +from typing import Optional, Any, List, Dict, Union +from ..client import SeamHttpClient +from .models import AbstractUserIdentitiesEnrollmentAutomations, EnrollmentAutomation + + +class UserIdentitiesEnrollmentAutomations(AbstractUserIdentitiesEnrollmentAutomations): + def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.client = client + self.defaults = defaults + + def delete(self, *, enrollment_automation_id: str) -> None: + json_payload = {} + + if enrollment_automation_id is not None: + json_payload["enrollment_automation_id"] = enrollment_automation_id + + self.client.post( + "/user_identities/enrollment_automations/delete", json=json_payload + ) + + return None + + def get(self, *, enrollment_automation_id: str) -> EnrollmentAutomation: + json_payload = {} + + if enrollment_automation_id is not None: + json_payload["enrollment_automation_id"] = enrollment_automation_id + + res = self.client.post( + "/user_identities/enrollment_automations/get", json=json_payload + ) + + return EnrollmentAutomation.from_dict(res["enrollment_automation"]) + + def launch( + self, + *, + credential_manager_acs_system_id: str, + user_identity_id: str, + acs_credential_pool_id: Optional[str] = None, + create_credential_manager_user: Optional[bool] = None, + credential_manager_acs_user_id: Optional[str] = None + ) -> None: + json_payload = {} + + if credential_manager_acs_system_id is not None: + json_payload["credential_manager_acs_system_id"] = ( + credential_manager_acs_system_id + ) + if user_identity_id is not None: + json_payload["user_identity_id"] = user_identity_id + if acs_credential_pool_id is not None: + json_payload["acs_credential_pool_id"] = acs_credential_pool_id + if create_credential_manager_user is not None: + json_payload["create_credential_manager_user"] = ( + create_credential_manager_user + ) + if credential_manager_acs_user_id is not None: + json_payload["credential_manager_acs_user_id"] = ( + credential_manager_acs_user_id + ) + + self.client.post( + "/user_identities/enrollment_automations/launch", json=json_payload + ) + + return None + + def list(self, *, user_identity_id: str) -> List[EnrollmentAutomation]: + json_payload = {} + + if user_identity_id is not None: + json_payload["user_identity_id"] = user_identity_id + + res = self.client.post( + "/user_identities/enrollment_automations/list", json=json_payload + ) + + return [ + EnrollmentAutomation.from_dict(item) + for item in res["enrollment_automations"] + ] diff --git a/seam/routes/webhooks.py b/seam/routes/webhooks.py new file mode 100644 index 0000000..3de62fe --- /dev/null +++ b/seam/routes/webhooks.py @@ -0,0 +1,62 @@ +from typing import Optional, Any, List, Dict, Union +from ..client import SeamHttpClient +from .models import AbstractWebhooks, Webhook + + +class Webhooks(AbstractWebhooks): + def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.client = client + self.defaults = defaults + + def create(self, *, url: str, event_types: Optional[List[str]] = None) -> Webhook: + json_payload = {} + + if url is not None: + json_payload["url"] = url + if event_types is not None: + json_payload["event_types"] = event_types + + res = self.client.post("/webhooks/create", json=json_payload) + + return Webhook.from_dict(res["webhook"]) + + def delete(self, *, webhook_id: str) -> None: + json_payload = {} + + if webhook_id is not None: + json_payload["webhook_id"] = webhook_id + + self.client.post("/webhooks/delete", json=json_payload) + + return None + + def get(self, *, webhook_id: str) -> Webhook: + json_payload = {} + + if webhook_id is not None: + json_payload["webhook_id"] = webhook_id + + res = self.client.post("/webhooks/get", json=json_payload) + + return Webhook.from_dict(res["webhook"]) + + def list( + self, + ) -> List[Webhook]: + json_payload = {} + + res = self.client.post("/webhooks/list", json=json_payload) + + return [Webhook.from_dict(item) for item in res["webhooks"]] + + def update(self, *, event_types: List[str], webhook_id: str) -> None: + json_payload = {} + + if event_types is not None: + json_payload["event_types"] = event_types + if webhook_id is not None: + json_payload["webhook_id"] = webhook_id + + self.client.post("/webhooks/update", json=json_payload) + + return None diff --git a/seam/routes/workspaces.py b/seam/routes/workspaces.py new file mode 100644 index 0000000..00bf1fb --- /dev/null +++ b/seam/routes/workspaces.py @@ -0,0 +1,82 @@ +from typing import Optional, Any, List, Dict, Union +from ..client import SeamHttpClient +from .models import AbstractWorkspaces, Workspace, ActionAttempt + +from ..modules.action_attempts import resolve_action_attempt + + +class Workspaces(AbstractWorkspaces): + def __init__(self, client: SeamHttpClient, defaults: Dict[str, Any]): + self.client = client + self.defaults = defaults + + def create( + self, + *, + name: str, + company_name: Optional[str] = None, + connect_partner_name: Optional[str] = None, + is_sandbox: Optional[bool] = None, + webview_logo_shape: Optional[str] = None, + webview_primary_button_color: Optional[str] = None, + webview_primary_button_text_color: Optional[str] = None + ) -> Workspace: + json_payload = {} + + if name is not None: + json_payload["name"] = name + if company_name is not None: + json_payload["company_name"] = company_name + if connect_partner_name is not None: + json_payload["connect_partner_name"] = connect_partner_name + if is_sandbox is not None: + json_payload["is_sandbox"] = is_sandbox + if webview_logo_shape is not None: + json_payload["webview_logo_shape"] = webview_logo_shape + if webview_primary_button_color is not None: + json_payload["webview_primary_button_color"] = webview_primary_button_color + if webview_primary_button_text_color is not None: + json_payload["webview_primary_button_text_color"] = ( + webview_primary_button_text_color + ) + + res = self.client.post("/workspaces/create", json=json_payload) + + return Workspace.from_dict(res["workspace"]) + + def get( + self, + ) -> Workspace: + json_payload = {} + + res = self.client.post("/workspaces/get", json=json_payload) + + return Workspace.from_dict(res["workspace"]) + + def list( + self, + ) -> List[Workspace]: + json_payload = {} + + res = self.client.post("/workspaces/list", json=json_payload) + + return [Workspace.from_dict(item) for item in res["workspaces"]] + + def reset_sandbox( + self, wait_for_action_attempt: Optional[Union[bool, Dict[str, float]]] = None + ) -> ActionAttempt: + json_payload = {} + + res = self.client.post("/workspaces/reset_sandbox", json=json_payload) + + wait_for_action_attempt = ( + self.defaults.get("wait_for_action_attempt") + if wait_for_action_attempt is None + else wait_for_action_attempt + ) + + return resolve_action_attempt( + client=self.client, + action_attempt=ActionAttempt.from_dict(res["action_attempt"]), + wait_for_action_attempt=wait_for_action_attempt, + )