diff --git a/aioairzone_cloud/aidoo.py b/aioairzone_cloud/aidoo.py index f311215..54a7055 100644 --- a/aioairzone_cloud/aidoo.py +++ b/aioairzone_cloud/aidoo.py @@ -4,7 +4,7 @@ from typing import Any -from .common import SpeedType +from .common import SpeedType, parse_int, parse_str from .const import ( API_MODE, API_NAME, @@ -33,8 +33,9 @@ def __init__(self, inst_id: str, ws_id: str, device_data: dict[str, Any]): self.speeds: dict[int, int] = {} self.speed_type: SpeedType | None = None - if API_NAME in device_data: - self.name = str(device_data[API_NAME]) + device_name = parse_str(device_data.get(API_NAME)) + if device_name is not None: + self.name = device_name else: self.name = f"Aidoo {ws_id}" @@ -92,9 +93,9 @@ def update_data(self, update: EntityUpdate) -> None: data = update.get_data() - speed = data.get(API_SPEED_CONF) + speed = parse_int(data.get(API_SPEED_CONF)) if speed is not None: - self.speed = int(speed) + self.speed = speed speed_type = data.get(API_SPEED_TYPE) if speed_type is not None: diff --git a/aioairzone_cloud/common.py b/aioairzone_cloud/common.py index 0dfbcd3..7319709 100644 --- a/aioairzone_cloud/common.py +++ b/aioairzone_cloud/common.py @@ -106,3 +106,31 @@ class TemperatureUnit(IntEnum): CELSIUS = 0 FAHRENHEIT = 1 + + +def parse_bool(data: Any) -> bool | None: + """Convert data to bool.""" + if data is not None: + return bool(data) + return None + + +def parse_float(data: Any) -> float | None: + """Convert data to float.""" + if data is not None: + return float(data) + return None + + +def parse_int(data: Any) -> int | None: + """Convert data to int.""" + if data is not None: + return int(data) + return None + + +def parse_str(data: Any) -> str | None: + """Convert data to string.""" + if data is not None: + return str(data) + return None diff --git a/aioairzone_cloud/device.py b/aioairzone_cloud/device.py index 02aab3d..c85d820 100644 --- a/aioairzone_cloud/device.py +++ b/aioairzone_cloud/device.py @@ -6,7 +6,7 @@ import logging from typing import Any -from .common import OperationMode +from .common import OperationMode, parse_bool, parse_int, parse_str from .const import ( API_AQ_PM_1, API_AQ_PM_2P5, @@ -72,8 +72,9 @@ def __init__(self, inst_id: str, ws_id: str, device_data: dict[str, Any]): self.webserver_id = ws_id self.ws_connected: bool = True - if API_IS_CONNECTED in device_data: - self.is_connected = bool(device_data[API_IS_CONNECTED]) + is_connected = parse_bool(device_data.get(API_IS_CONNECTED)) + if is_connected is not None: + self.is_connected = is_connected else: self.is_connected = True @@ -245,32 +246,32 @@ def update_data(self, update: EntityUpdate) -> None: """Update Device data.""" data = update.get_data() - is_connected = data.get(API_IS_CONNECTED) + is_connected = parse_bool(data.get(API_IS_CONNECTED)) if is_connected is not None: - self.is_connected = bool(is_connected) - ws_connected = data.get(API_WS_CONNECTED) + self.is_connected = is_connected + ws_connected = parse_bool(data.get(API_WS_CONNECTED)) if ws_connected is not None: - self.ws_connected = bool(ws_connected) + self.ws_connected = ws_connected - aq_pm_1 = data.get(API_AQ_PM_1) + aq_pm_1 = parse_int(data.get(API_AQ_PM_1)) if aq_pm_1 is not None: - self.aq_pm_1 = int(aq_pm_1) + self.aq_pm_1 = aq_pm_1 - aq_pm_2p5 = data.get(API_AQ_PM_2P5) + aq_pm_2p5 = parse_int(data.get(API_AQ_PM_2P5)) if aq_pm_2p5 is not None: - self.aq_pm_2p5 = int(aq_pm_2p5) + self.aq_pm_2p5 = aq_pm_2p5 - aq_pm_10 = data.get(API_AQ_PM_10) + aq_pm_10 = parse_int(data.get(API_AQ_PM_10)) if aq_pm_10 is not None: - self.aq_pm_10 = int(aq_pm_10) + self.aq_pm_10 = aq_pm_10 - aq_present = data.get(API_AQ_PRESENT) + aq_present = parse_bool(data.get(API_AQ_PRESENT)) if aq_present is not None: - self.aq_present = bool(aq_present) + self.aq_present = aq_present - aq_status = data.get(API_AQ_QUALITY) + aq_status = parse_str(data.get(API_AQ_QUALITY)) if aq_status is not None: - self.aq_status = str(aq_status) + self.aq_status = aq_status errors = data.get(API_ERRORS) if errors is not None: diff --git a/aioairzone_cloud/hvac.py b/aioairzone_cloud/hvac.py index 716c75e..d86e28c 100644 --- a/aioairzone_cloud/hvac.py +++ b/aioairzone_cloud/hvac.py @@ -4,7 +4,14 @@ from typing import Any -from .common import AirQualityMode, OperationAction, OperationMode +from .common import ( + AirQualityMode, + OperationAction, + OperationMode, + parse_bool, + parse_float, + parse_int, +) from .const import ( API_ACTIVE, API_AQ_ACTIVE, @@ -499,9 +506,9 @@ def update_data(self, update: EntityUpdate) -> None: data = update.get_data() if API_ACTIVE in data: - active = data.get(API_ACTIVE) + active = parse_bool(data.get(API_ACTIVE)) if active is not None: - self.active = bool(active) + self.active = active else: # API sends active as null instead of False self.active = False @@ -509,9 +516,9 @@ def update_data(self, update: EntityUpdate) -> None: if update.get_type() != UpdateType.WS_PARTIAL: self.active = None - aq_active = data.get(API_AQ_ACTIVE) + aq_active = parse_bool(data.get(API_AQ_ACTIVE)) if aq_active is not None: - self.aq_active = bool(aq_active) + self.aq_active = aq_active aq_mode_conf = data.get(API_AQ_MODE_CONF) if aq_mode_conf is not None: @@ -525,109 +532,110 @@ def update_data(self, update: EntityUpdate) -> None: humidity = data.get(API_HUMIDITY) if humidity is not None: - self.humidity = int(humidity) + self.humidity = parse_int(humidity) - local_temp = data.get(API_LOCAL_TEMP) + local_temp = parse_float(data.get(API_LOCAL_TEMP, {}).get(API_CELSIUS)) if local_temp is not None: - if API_CELSIUS in local_temp: - self.temp = float(local_temp[API_CELSIUS]) + self.temp = local_temp - power = data.get(API_POWER) + power = parse_bool(data.get(API_POWER)) if power is not None: - self.power = bool(power) + self.power = power - range_max_air = data.get(API_RANGE_MAX_AIR) + range_max_air = parse_float(data.get(API_RANGE_MAX_AIR, {}).get(API_CELSIUS)) if range_max_air is not None: - if API_CELSIUS in range_max_air: - self.temp_set_max = float(range_max_air[API_CELSIUS]) - range_sp_max_auto_air = data.get(API_RANGE_SP_MAX_AUTO_AIR) + self.temp_set_max = range_max_air + range_sp_max_auto_air = parse_float( + data.get(API_RANGE_SP_MAX_AUTO_AIR, {}).get(API_CELSIUS) + ) if range_sp_max_auto_air is not None: - if API_CELSIUS in range_sp_max_auto_air: - self.temp_set_max_auto_air = float(range_sp_max_auto_air[API_CELSIUS]) - range_sp_max_cool_air = data.get(API_RANGE_SP_MAX_COOL_AIR) + self.temp_set_max_auto_air = range_sp_max_auto_air + range_sp_max_cool_air = parse_float( + data.get(API_RANGE_SP_MAX_COOL_AIR, {}).get(API_CELSIUS) + ) if range_sp_max_cool_air is not None: - if API_CELSIUS in range_sp_max_cool_air: - self.temp_set_max_cool_air = float(range_sp_max_cool_air[API_CELSIUS]) - range_sp_max_dry_air = data.get(API_RANGE_SP_MAX_DRY_AIR) + self.temp_set_max_cool_air = range_sp_max_cool_air + range_sp_max_dry_air = parse_float( + data.get(API_RANGE_SP_MAX_DRY_AIR, {}).get(API_CELSIUS) + ) if range_sp_max_dry_air is not None: - if API_CELSIUS in range_sp_max_dry_air: - self.temp_set_max_dry_air = float(range_sp_max_dry_air[API_CELSIUS]) - range_sp_max_emerheat_air = data.get(API_RANGE_SP_MAX_EMERHEAT_AIR) + self.temp_set_max_dry_air = range_sp_max_dry_air + range_sp_max_emerheat_air = parse_float( + data.get(API_RANGE_SP_MAX_EMERHEAT_AIR, {}).get(API_CELSIUS) + ) if range_sp_max_emerheat_air is not None: - if API_CELSIUS in range_sp_max_emerheat_air: - self.temp_set_max_emerheat_air = float( - range_sp_max_emerheat_air[API_CELSIUS] - ) - range_sp_max_hot_air = data.get(API_RANGE_SP_MAX_HOT_AIR) + self.temp_set_max_emerheat_air = range_sp_max_emerheat_air + range_sp_max_hot_air = parse_float( + data.get(API_RANGE_SP_MAX_HOT_AIR, {}).get(API_CELSIUS) + ) if range_sp_max_hot_air is not None: - if API_CELSIUS in range_sp_max_hot_air: - self.temp_set_max_hot_air = float(range_sp_max_hot_air[API_CELSIUS]) - range_sp_max_stop_air = data.get(API_RANGE_SP_MAX_STOP_AIR) + self.temp_set_max_hot_air = range_sp_max_hot_air + range_sp_max_stop_air = parse_float( + data.get(API_RANGE_SP_MAX_STOP_AIR, {}).get(API_CELSIUS) + ) if range_sp_max_stop_air is not None: - if API_CELSIUS in range_sp_max_stop_air: - self.temp_set_max_stop_air = float(range_sp_max_stop_air[API_CELSIUS]) - range_sp_max_vent_air = data.get(API_RANGE_SP_MAX_VENT_AIR) + self.temp_set_max_stop_air = range_sp_max_stop_air + range_sp_max_vent_air = parse_float( + data.get(API_RANGE_SP_MAX_VENT_AIR, {}).get(API_CELSIUS) + ) if range_sp_max_vent_air is not None: - if API_CELSIUS in range_sp_max_vent_air: - self.temp_set_max_vent_air = float(range_sp_max_vent_air[API_CELSIUS]) + self.temp_set_max_vent_air = range_sp_max_vent_air - range_min_air = data.get(API_RANGE_MIN_AIR) + range_min_air = parse_float(data.get(API_RANGE_MIN_AIR, {}).get(API_CELSIUS)) if range_min_air is not None: - if API_CELSIUS in range_min_air: - self.temp_set_min = float(range_min_air[API_CELSIUS]) - range_sp_min_auto_air = data.get(API_RANGE_SP_MIN_AUTO_AIR) + self.temp_set_min = range_min_air + range_sp_min_auto_air = parse_float( + data.get(API_RANGE_SP_MIN_AUTO_AIR, {}).get(API_CELSIUS) + ) if range_sp_min_auto_air is not None: - if API_CELSIUS in range_sp_min_auto_air: - self.temp_set_min_auto_air = float(range_sp_min_auto_air[API_CELSIUS]) - range_sp_min_cool_air = data.get(API_RANGE_SP_MIN_COOL_AIR) + self.temp_set_min_auto_air = range_sp_min_auto_air + range_sp_min_cool_air = parse_float( + data.get(API_RANGE_SP_MIN_COOL_AIR, {}).get(API_CELSIUS) + ) if range_sp_min_cool_air is not None: - if API_CELSIUS in range_sp_min_cool_air: - self.temp_set_min_cool_air = float(range_sp_min_cool_air[API_CELSIUS]) - range_sp_min_dry_air = data.get(API_RANGE_SP_MIN_DRY_AIR) + self.temp_set_min_cool_air = range_sp_min_cool_air + range_sp_min_dry_air = parse_float( + data.get(API_RANGE_SP_MIN_DRY_AIR, {}).get(API_CELSIUS) + ) if range_sp_min_dry_air is not None: - if API_CELSIUS in range_sp_min_dry_air: - self.temp_set_min_dry_air = float(range_sp_min_dry_air[API_CELSIUS]) - range_sp_min_emerheat_air = data.get(API_RANGE_SP_MIN_EMERHEAT_AIR) + self.temp_set_min_dry_air = range_sp_min_dry_air + range_sp_min_emerheat_air = parse_float( + data.get(API_RANGE_SP_MIN_EMERHEAT_AIR, {}).get(API_CELSIUS) + ) if range_sp_min_emerheat_air is not None: - if API_CELSIUS in range_sp_min_emerheat_air: - self.temp_set_min_emerheat_air = float( - range_sp_min_emerheat_air[API_CELSIUS] - ) - range_sp_min_hot_air = data.get(API_RANGE_SP_MIN_HOT_AIR) + self.temp_set_min_emerheat_air = range_sp_min_emerheat_air + range_sp_min_hot_air = parse_float( + data.get(API_RANGE_SP_MIN_HOT_AIR, {}).get(API_CELSIUS) + ) if range_sp_min_hot_air is not None: - if API_CELSIUS in range_sp_min_hot_air: - self.temp_set_min_hot_air = float(range_sp_min_hot_air[API_CELSIUS]) - range_sp_min_stop_air = data.get(API_RANGE_SP_MIN_STOP_AIR) + self.temp_set_min_hot_air = range_sp_min_hot_air + range_sp_min_stop_air = parse_float( + data.get(API_RANGE_SP_MIN_STOP_AIR, {}).get(API_CELSIUS) + ) if range_sp_min_stop_air is not None: - if API_CELSIUS in range_sp_min_stop_air: - self.temp_set_min_stop_air = float(range_sp_min_stop_air[API_CELSIUS]) - range_sp_min_vent_air = data.get(API_RANGE_SP_MIN_VENT_AIR) + self.temp_set_min_stop_air = range_sp_min_stop_air + range_sp_min_vent_air = parse_float( + data.get(API_RANGE_SP_MIN_VENT_AIR, {}).get(API_CELSIUS) + ) if range_sp_min_vent_air is not None: - if API_CELSIUS in range_sp_min_vent_air: - self.temp_set_min_vent_air = float(range_sp_min_vent_air[API_CELSIUS]) + self.temp_set_min_vent_air = range_sp_min_vent_air - sp_air_cool = data.get(API_SP_AIR_COOL) + sp_air_cool = parse_float(data.get(API_SP_AIR_COOL, {}).get(API_CELSIUS)) if sp_air_cool is not None: - if API_CELSIUS in sp_air_cool: - self.temp_set_cool_air = float(sp_air_cool[API_CELSIUS]) - sp_air_dry = data.get(API_SP_AIR_DRY) + self.temp_set_cool_air = sp_air_cool + sp_air_dry = parse_float(data.get(API_SP_AIR_DRY, {}).get(API_CELSIUS)) if sp_air_dry is not None: - if API_CELSIUS in sp_air_dry: - self.temp_set_dry_air = float(data[API_SP_AIR_DRY][API_CELSIUS]) - sp_air_heat = data.get(API_SP_AIR_HEAT) + self.temp_set_dry_air = sp_air_dry + sp_air_heat = parse_float(data.get(API_SP_AIR_HEAT, {}).get(API_CELSIUS)) if sp_air_heat is not None: - if API_CELSIUS in sp_air_heat: - self.temp_set_hot_air = float(sp_air_heat[API_CELSIUS]) - sp_air_stop = data.get(API_SP_AIR_STOP) + self.temp_set_hot_air = sp_air_heat + sp_air_stop = parse_float(data.get(API_SP_AIR_STOP, {}).get(API_CELSIUS)) if sp_air_stop is not None: - if API_CELSIUS in sp_air_stop: - self.temp_set_stop_air = float(sp_air_stop[API_CELSIUS]) - sp_air_vent = data.get(API_SP_AIR_VENT) + self.temp_set_stop_air = sp_air_stop + sp_air_vent = parse_float(data.get(API_SP_AIR_VENT, {}).get(API_CELSIUS)) if sp_air_vent is not None: - if API_CELSIUS in sp_air_vent: - self.temp_set_vent_air = float(sp_air_vent[API_CELSIUS]) + self.temp_set_vent_air = sp_air_vent - step = data.get(API_STEP) + step = parse_float(data.get(API_STEP, {}).get(API_CELSIUS)) if step is not None: - if API_CELSIUS in step: - self.temp_step = float(step[API_CELSIUS]) + self.temp_step = step diff --git a/aioairzone_cloud/webserver.py b/aioairzone_cloud/webserver.py index 06e5f04..4805406 100644 --- a/aioairzone_cloud/webserver.py +++ b/aioairzone_cloud/webserver.py @@ -5,6 +5,7 @@ import logging from typing import Any +from .common import parse_bool, parse_int, parse_str from .const import ( API_CONFIG, API_CONNECTION_DATE, @@ -63,42 +64,42 @@ def update_data(self, update: EntityUpdate) -> None: """Update WebServer data.""" data = update.get_data() - ws_type = data.get(API_WS_TYPE) + ws_type = parse_str(data.get(API_WS_TYPE)) if ws_type is not None: - self.type = str(ws_type) + self.type = ws_type ws_config = data.get(API_CONFIG) if ws_config is not None: stat_ap_mac = ws_config.get(API_STAT_AP_MAC) if stat_ap_mac is not None: - self.wifi_mac = str(stat_ap_mac) - stat_channel = ws_config.get(API_STAT_CHANNEL) + self.wifi_mac = parse_str(stat_ap_mac) + stat_channel = parse_int(ws_config.get(API_STAT_CHANNEL)) if stat_channel is not None: - self.wifi_channel = int(stat_channel) + self.wifi_channel = stat_channel stat_ssid = ws_config.get(API_STAT_SSID) if stat_ssid is not None: - self.wifi_ssid = str(stat_ssid) + self.wifi_ssid = parse_str(stat_ssid) ws_fw = ws_config.get(API_WS_FW) if ws_fw is not None: - self.firmware = str(ws_fw) + self.firmware = parse_str(ws_fw) ws_status = data.get(API_STATUS) if ws_status is not None: connection_date = ws_status.get(API_CONNECTION_DATE) if connection_date is not None: - self.connection_date = str(connection_date) + self.connection_date = parse_str(connection_date) disconnection_date = ws_status.get(API_DISCONNECTION_DATE) if disconnection_date is not None: - self.disconnection_date = str(disconnection_date) - is_connected = ws_status.get(API_IS_CONNECTED) + self.disconnection_date = parse_str(disconnection_date) + is_connected = parse_bool(ws_status.get(API_IS_CONNECTED)) if is_connected is not None: - self.is_connected = bool(is_connected) - stat_quality = ws_status.get(API_STAT_QUALITY) + self.is_connected = is_connected + stat_quality = parse_int(ws_status.get(API_STAT_QUALITY)) if stat_quality is not None: - self.wifi_quality = int(stat_quality) - stat_rssi = ws_status.get(API_STAT_RSSI) + self.wifi_quality = stat_quality + stat_rssi = parse_int(ws_status.get(API_STAT_RSSI)) if stat_rssi is not None: - self.wifi_rssi = int(stat_rssi) + self.wifi_rssi = stat_rssi def data(self) -> dict[str, Any]: """Return WebServer data.""" diff --git a/aioairzone_cloud/zone.py b/aioairzone_cloud/zone.py index c25d1c6..4e3579a 100644 --- a/aioairzone_cloud/zone.py +++ b/aioairzone_cloud/zone.py @@ -6,6 +6,7 @@ from aioairzone_cloud.common import OperationMode +from .common import parse_str from .const import ( API_AQ_MODE_CONF, API_MODE, @@ -42,8 +43,9 @@ def __init__(self, inst_id: str, ws_id: str, device_data: dict[str, Any]): self.system_number = int(sub_data[API_SYSTEM_NUMBER]) self.zone_number = int(sub_data[API_ZONE_NUMBER]) - if API_NAME in device_data: - self.name = str(device_data[API_NAME]) + device_name = parse_str(device_data.get(API_NAME)) + if device_name is not None: + self.name = device_name else: self.name = f"Zone {self.system_number}:{self.zone_number}"