"""Models used by PyNest.""" from __future__ import annotations import datetime from dataclasses import dataclass, field from typing import Any from .enums import BucketType @dataclass class NestLimits: """Nest Limits.""" thermostats_per_structure: int structures: int smoke_detectors_per_structure: int smoke_detectors: int thermostats: int @dataclass class NestUrls: """Nest Urls.""" rubyapi_url: str czfe_url: str log_upload_url: str transport_url: str weather_url: str support_url: str direct_transport_url: str @dataclass class NestResponse: """Class that reflects a Nest API response.""" access_token: float email: str expires_in: str userid: str is_superuser: bool language: str weave: dict[str, str] user: str is_staff: bool error: dict | None = None urls: NestUrls = field(default_factory=NestUrls) limits: NestLimits = field(default_factory=NestLimits) _2fa_state: str = None _2fa_enabled: bool = None _2fa_state_changed: str = None def is_expired(self): """Check if session is expired.""" # Tue, 01-Mar-2022 23:15:55 GMT expiry_date = datetime.datetime.strptime( self.expires_in, "%a, %d-%b-%Y %H:%M:%S %Z" ) return expiry_date <= datetime.datetime.now() @dataclass class Bucket: """Class that reflects a Nest API response.""" object_key: str object_revision: int object_timestamp: int # value: dict[str, Any] value: dict[str, Any] | TopazBucketValue | WhereBucketValue type: str = "" def __post_init__(self): """Set the bucket type during post init.""" self.type = BucketType(self.object_key.split(".")[0]) # if self.type == BucketType.TOPAZ: # self.value = TopazBucketValue(**self.value) if self.type == BucketType.WHERE: if isinstance(self.value, WhereBucketValue): # It's already the correct type, no need to reinitialize pass else: # Convert dictionary to WhereBucketValue instance self.value = WhereBucketValue(**self.value) @dataclass class Where: """TODO.""" name: str where_id: str @dataclass class BucketValue: """Nest Protect values.""" # def __iter__(self): # return (getattr(self, field.name) for field in fields(self)) @dataclass class WhereBucketValue(BucketValue): """Nest Protect values.""" wheres: list[Where] = field(default_factory=Where) def __post_init__(self): """TODO.""" self.wheres = [Where(**w) for w in self.wheres] if self.wheres else [] @dataclass class WhereBucket(Bucket): """Class that reflects a Nest API response.""" object_key: str object_revision: str object_timestamp: str value: WhereBucketValue = field(default_factory=WhereBucketValue) @dataclass class TopazBucketValue(BucketValue): """Nest Protect values.""" spoken_where_id: str creation_time: int installed_locale: str ntp_green_led_brightness: int component_buzzer_test_passed: bool wifi_ip_address: str wired_led_enable: bool wifi_regulatory_domain: str co_blame_duration: int is_rcs_capable: bool fabric_id: str battery_health_state: int steam_detection_enable: bool hushed_state: bool capability_level: float home_alarm_link_type: int model: str component_smoke_test_passed: bool component_speaker_test_passed: bool removed_from_base: bool smoke_sequence_number: int home_away_input: bool device_locale: str co_blame_threshold: int kl_software_version: str component_us_test_passed: bool auto_away: bool night_light_enable: bool component_als_test_passed: bool speaker_test_results: 32768 wired_or_battery: int is_rcs_used: bool replace_by_date_utc_secs: int certification_body: 2 component_pir_test_passed: bool structure_id: str software_version: str component_hum_test_passed: bool home_alarm_link_capable: bool night_light_brightness: int device_external_color: str latest_manual_test_end_utc_secs: int smoke_status: int latest_manual_test_start_utc_secs: int component_temp_test_passed: bool home_alarm_link_connected: bool co_status: int heat_status: int product_id: int night_light_continuous: bool co_previous_peak: int auto_away_decision_time_secs: int component_co_test_passed: bool where_id: str serial_number: str component_heat_test_passed: bool latest_manual_test_cancelled: bool thread_mac_address: str resource_id: str buzzer_test_results: int wifi_mac_address: str line_power_present: bool gesture_hush_enable: bool device_born_on_date_utc_secs: int ntp_green_led_enable: bool component_led_test_passed: bool co_sequence_number: int thread_ip_address: list[str] component_wifi_test_passed: bool heads_up_enable: bool battery_level: int last_audio_self_test_end_utc_secs: int last_audio_self_test_start_utc_secs: int @dataclass class TopazBucket(Bucket): """Class that reflects a Nest API response.""" value: TopazBucketValue = field(default_factory=TopazBucketValue) @dataclass class GoogleAuthResponse: """Class that reflects a Google Auth response.""" access_token: str scope: str token_type: str expires_in: int id_token: str expiry_date: datetime.datetime = field(init=False) def __post_init__(self): """Set the expiry date during post init.""" self.expiry_date = datetime.datetime.now() + datetime.timedelta( seconds=self.expires_in ) def is_expired(self): """Check if access token is expired.""" return self.expiry_date <= datetime.datetime.now() @dataclass class GoogleAuthResponseForCookies(GoogleAuthResponse): """Class that reflects a Google Auth response for cookies.""" login_hint: str session_state: dict[str, dict[str, str]] = field(default_factory=dict) # TODO rewrite to snake_case @dataclass class NestAuthClaims: """TODO.""" subject: Any | None = None expirationTime: str | None = None policyId: str | None = None structureConstraint: str | None = None @dataclass class NestAuthResponse: """TODO.""" jwt: str | None = None claims: NestAuthClaims = field(default_factory=NestAuthClaims) error: dict | None = None @dataclass class NestEnvironment: """Class to describe a Nest environment.""" name: str client_id: str host: str @dataclass class Weather: """TODO.""" icon: str sunrise: str sunset: str temp_c: str @dataclass class Location: """TODO.""" city: str country: str state: str zip: str @dataclass class WeatherForStructures: """TODO.""" current: Weather location: Location @dataclass class ServiceUrls: """TODO.""" czfe_url: str direct_transport_url: str log_upload_url: str rubyapi_url: str support_url: str transport_url: str weather_url: str @dataclass class Weave: """TODO.""" access_token: str pairing_token: str service_config: str @dataclass class Limits: """TODO.""" smoke_detectors: int smoke_detectors_per_structure: int structures: int thermostats: int thermostats_per_structure: int @dataclass class FirstDataAPIResponse: """TODO.""" weather_for_structures: dict[str, WeatherForStructures] service_urls: dict[str, ServiceUrls | Weave | Limits] _2fa_enabled: bool updated_buckets: list[Bucket] def __post_init__(self): """TODO.""" self.updated_buckets = ( [Bucket(**b) for b in self.updated_buckets] if self.updated_buckets else [] )