diff --git a/custom_components/panasonic_smart_app/const.py b/custom_components/panasonic_smart_app/const.py index e07cd86..f779acd 100644 --- a/custom_components/panasonic_smart_app/const.py +++ b/custom_components/panasonic_smart_app/const.py @@ -31,26 +31,34 @@ CONF_UPDATE_INTERVAL = "update_interval" +DEVICE_CLASS_SWITCH = "switch" + DEFAULT_UPDATE_INTERVAL = 180 DEVICE_STATUS_CODES = { DEVICE_TYPE_AC: [ - "0x00", - "0x01", - "0x04", - "0x03", - "0x02", - "0x0f", - "0x21", - "0x0b", - "0x0c", - "0x08", - "0x1b", - "0x1e", - "0x1a", + "0x00", # AC power status + "0x01", # AC operation mode + "0x04", # AC current termperature + "0x03", # AC target temperature + "0x02", # AC fan level + "0x0F", # AC fan position (horizontal) + "0x21", # AC outdoor temperature + "0x0B", # AC on timer + "0x0C", # AC off timer + "0x08", # AC nanoeX + "0x1B", # AC ECONAVI + "0x1E", # AC buzzer + "0x1A", # AC turbo mode + "0x18", # AC self clean + "0x05", # AC sleep mode + "0x17", # AC dryer + # "0x11", # AC fan position (vertical) + # "0x19", # AC motion detection + # "0x1F", # AC indicator light ], DEVICE_TYPE_DEHUMIDIFIER: [ - "0x00", # Dehumidifier online status + "0x00", # Dehumidifier power status "0x01", # Dehumidifier operation mode "0x02", # Dehumidifier off timer "0x07", # Dehumidifier humidity sensor @@ -119,6 +127,10 @@ ICON_TURBO = "mdi:clock-fast" ICON_FAN = "mdi:fan" ICON_ENERGY = "mdi:flash" +ICON_DRYER = "mdi:weather-windy" +ICON_SLEEP = "mdi:sleep" +ICON_CLEAN = "mdi:broom" + LABEL_DEHUMIDIFIER = "" LABEL_CLIMATE = "" @@ -130,6 +142,9 @@ LABEL_CLIMATE_ON_TIMER = "定時開機(分)" LABEL_CLIMATE_ON_TIMER = "定時開機" LABEL_CLIMATE_OFF_TIMER = "定時關機" +LABEL_CLIMATE_DRYER = "乾燥防霉" +LABEL_CLIMATE_SLEEP = "舒眠" +LABEL_CLIMATE_CLEAN = "自體淨" LABEL_OUTDOOR_TEMPERATURE = "室外溫度" LABEL_PM25 = "PM2.5" LABEL_NANOE = "nanoe" diff --git a/custom_components/panasonic_smart_app/switch.py b/custom_components/panasonic_smart_app/switch.py index abd1035..1fde5af 100644 --- a/custom_components/panasonic_smart_app/switch.py +++ b/custom_components/panasonic_smart_app/switch.py @@ -9,14 +9,21 @@ DEVICE_TYPE_AC, DATA_CLIENT, DATA_COORDINATOR, + DEVICE_CLASS_SWITCH, LABEL_NANOE, LABEL_ECONAVI, LABEL_BUZZER, LABEL_TURBO, + LABEL_CLIMATE_DRYER, + LABEL_CLIMATE_SLEEP, + LABEL_CLIMATE_CLEAN, ICON_NANOE, ICON_ECONAVI, ICON_BUZZER, ICON_TURBO, + ICON_SLEEP, + ICON_DRYER, + ICON_CLEAN, ) _LOGGER = logging.getLogger(__package__) @@ -76,6 +83,33 @@ async def async_setup_entry(hass, entry, async_add_entities) -> bool: device, ) ) + if "0x05" in command_types: + switches.append( + PanasonicACSleepMode( + coordinator, + index, + client, + device, + ) + ) + if "0x17" in command_types: + switches.append( + PanasonicACDryer( + coordinator, + index, + client, + device, + ) + ) + if "0x18" in command_types: + switches.append( + PanasonicACSelfClean( + coordinator, + index, + client, + device, + ) + ) async_add_entities(switches, True) @@ -101,7 +135,7 @@ def icon(self) -> str: @property def device_class(self) -> str: - return "switch" + return DEVICE_CLASS_SWITCH @property def is_on(self) -> int: @@ -143,7 +177,7 @@ def icon(self) -> str: @property def device_class(self) -> str: - return "switch" + return DEVICE_CLASS_SWITCH @property def is_on(self) -> int: @@ -185,7 +219,7 @@ def icon(self) -> str: @property def device_class(self) -> str: - return "switch" + return DEVICE_CLASS_SWITCH @property def is_on(self) -> int: @@ -227,24 +261,150 @@ def icon(self) -> str: @property def device_class(self) -> str: - return "switch" + return DEVICE_CLASS_SWITCH @property def is_on(self) -> int: status = self.coordinator.data[self.index]["status"] - _nanoe_status = status.get("0x1a") - if _nanoe_status == None: + _turbo_status = status.get("0x08", None) + if _turbo_status == None: return STATE_UNAVAILABLE - _is_on = bool(int(_nanoe_status)) + _is_on = bool(int(_turbo_status)) _LOGGER.debug(f"[{self.label}] is_on: {_is_on}") return _is_on async def async_turn_on(self) -> None: - _LOGGER.debug(f"[{self.label}] Turning on buzzer") + _LOGGER.debug(f"[{self.label}] Turning on turbo mode") await self.client.set_command(self.auth, 154, 1) await self.coordinator.async_request_refresh() async def async_turn_off(self) -> None: - _LOGGER.debug(f"[{self.label}] Turning off buzzer") + _LOGGER.debug(f"[{self.label}] Turning off turbo mode") await self.client.set_command(self.auth, 154, 0) await self.coordinator.async_request_refresh() + + +class PanasonicACSleepMode(PanasonicBaseEntity, SwitchEntity): + """ Panasonic AC sleep mode switch """ + + @property + def available(self) -> bool: + status = self.coordinator.data[self.index]["status"] + _is_on_status = bool(int(status.get("0x00", 0))) + return _is_on_status + + @property + def label(self): + return f"{self.nickname} {LABEL_CLIMATE_SLEEP}" + + @property + def icon(self) -> str: + return ICON_SLEEP + + @property + def device_class(self) -> str: + return DEVICE_CLASS_SWITCH + + @property + def is_on(self) -> int: + status = self.coordinator.data[self.index]["status"] + _sleep_mode_status = status.get("0x05") + if _sleep_mode_status == None: + return STATE_UNAVAILABLE + _is_on = bool(int(_sleep_mode_status)) + _LOGGER.debug(f"[{self.label}] is_on: {_is_on}") + return _is_on + + async def async_turn_on(self) -> None: + _LOGGER.debug(f"[{self.label}] Turning on sleep mode") + await self.client.set_command(self.auth, 5, 1) + await self.coordinator.async_request_refresh() + + async def async_turn_off(self) -> None: + _LOGGER.debug(f"[{self.label}] Turning off sleep mode") + await self.client.set_command(self.auth, 5, 0) + await self.coordinator.async_request_refresh() + + +class PanasonicACDryer(PanasonicBaseEntity, SwitchEntity): + """ Panasonic AC dryer switch """ + + @property + def available(self) -> bool: + status = self.coordinator.data[self.index]["status"] + _is_on_status = bool(int(status.get("0x00", 0))) + return _is_on_status + + @property + def label(self): + return f"{self.nickname} {LABEL_CLIMATE_DRYER}" + + @property + def icon(self) -> str: + return ICON_DRYER + + @property + def device_class(self) -> str: + return DEVICE_CLASS_SWITCH + + @property + def is_on(self) -> int: + status = self.coordinator.data[self.index]["status"] + _dryer_status = status.get("0x17") + if _dryer_status == None: + return STATE_UNAVAILABLE + _is_on = bool(int(_dryer_status)) + _LOGGER.debug(f"[{self.label}] is_on: {_is_on}") + return _is_on + + async def async_turn_on(self) -> None: + _LOGGER.debug(f"[{self.label}] Turning on dryer") + await self.client.set_command(self.auth, 23, 1) + await self.coordinator.async_request_refresh() + + async def async_turn_off(self) -> None: + _LOGGER.debug(f"[{self.label}] Turning off dryer") + await self.client.set_command(self.auth, 23, 0) + await self.coordinator.async_request_refresh() + + +class PanasonicACSelfClean(PanasonicBaseEntity, SwitchEntity): + """ Panasonic AC self clean switch """ + + @property + def available(self) -> bool: + status = self.coordinator.data[self.index]["status"] + _is_on_status = bool(int(status.get("0x00", 0))) + return _is_on_status + + @property + def label(self): + return f"{self.nickname} {LABEL_CLIMATE_CLEAN}" + + @property + def icon(self) -> str: + return ICON_CLEAN + + @property + def device_class(self) -> str: + return DEVICE_CLASS_SWITCH + + @property + def is_on(self) -> int: + status = self.coordinator.data[self.index]["status"] + _self_clean_status = status.get("0x18") + if _self_clean_status == None: + return STATE_UNAVAILABLE + _is_on = bool(int(_self_clean_status)) + _LOGGER.debug(f"[{self.label}] is_on: {_is_on}") + return _is_on + + async def async_turn_on(self) -> None: + _LOGGER.debug(f"[{self.label}] Turning on self clean") + await self.client.set_command(self.auth, 24, 1) + await self.coordinator.async_request_refresh() + + async def async_turn_off(self) -> None: + _LOGGER.debug(f"[{self.label}] Turning off self clean") + await self.client.set_command(self.auth, 24, 0) + await self.coordinator.async_request_refresh()