def __init__(self, hass, said, name, backend_selector: BackendSelector, auth: Auth): """Initialize the entity.""" self._aircon = Aircon(backend_selector, auth, said, self.async_write_ha_state) self.entity_id = generate_entity_id(ENTITY_ID_FORMAT, said, hass=hass) self._attr_name = name if name is not None else said self._attr_unique_id = said
def __init__(self, said, auth: Auth): """Initialize the entity.""" self._aircon = Aircon(auth, said, self.schedule_update_ha_state) self._supported_features = SUPPORT_TARGET_TEMPERATURE self._supported_features |= SUPPORT_FAN_MODE self._supported_features |= SUPPORT_SWING_MODE
class AirConEntity(ClimateEntity): """Representation of an air conditioner.""" _attr_fan_modes = SUPPORTED_FAN_MODES _attr_hvac_modes = SUPPORTED_HVAC_MODES _attr_max_temp = SUPPORTED_MAX_TEMP _attr_min_temp = SUPPORTED_MIN_TEMP _attr_supported_features = ( ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.FAN_MODE | ClimateEntityFeature.SWING_MODE ) _attr_swing_modes = SUPPORTED_SWING_MODES _attr_target_temperature_step = SUPPORTED_TARGET_TEMPERATURE_STEP _attr_temperature_unit = TEMP_CELSIUS _attr_should_poll = False def __init__(self, hass, said, name, backend_selector: BackendSelector, auth: Auth): """Initialize the entity.""" self._aircon = Aircon(backend_selector, auth, said, self.async_write_ha_state) self.entity_id = generate_entity_id(ENTITY_ID_FORMAT, said, hass=hass) self._attr_name = name if name is not None else said self._attr_unique_id = said async def async_added_to_hass(self) -> None: """Connect aircon to the cloud.""" await self._aircon.connect() @property def available(self) -> bool: """Return True if entity is available.""" return self._aircon.get_online() @property def current_temperature(self) -> float: """Return the current temperature.""" return self._aircon.get_current_temp() @property def target_temperature(self) -> float: """Return the temperature we try to reach.""" return self._aircon.get_temp() async def async_set_temperature(self, **kwargs: Any) -> None: """Set new target temperature.""" await self._aircon.set_temp(kwargs.get(ATTR_TEMPERATURE)) @property def current_humidity(self) -> int: """Return the current humidity.""" return self._aircon.get_current_humidity() @property def target_humidity(self) -> int: """Return the humidity we try to reach.""" return self._aircon.get_humidity() async def async_set_humidity(self, humidity: int) -> None: """Set new target humidity.""" await self._aircon.set_humidity(humidity) @property def hvac_mode(self) -> HVACMode | None: """Return current operation ie. heat, cool, fan.""" if not self._aircon.get_power_on(): return HVACMode.OFF mode: AirconMode = self._aircon.get_mode() return AIRCON_MODE_MAP.get(mode) async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None: """Set HVAC mode.""" if hvac_mode == HVACMode.OFF: await self._aircon.set_power_on(False) return if not (mode := HVAC_MODE_TO_AIRCON_MODE.get(hvac_mode)): raise ValueError(f"Invalid hvac mode {hvac_mode}") await self._aircon.set_mode(mode) if not self._aircon.get_power_on(): await self._aircon.set_power_on(True)
def __init__(self, said, auth: Auth): """Initialize the entity.""" self._aircon = Aircon(auth, said, self.async_write_ha_state) self._attr_name = said self._attr_unique_id = said
class AirConEntity(ClimateEntity): """Representation of an air conditioner.""" _attr_fan_modes = SUPPORTED_FAN_MODES _attr_hvac_modes = SUPPORTED_HVAC_MODES _attr_max_temp = SUPPORTED_MAX_TEMP _attr_min_temp = SUPPORTED_MIN_TEMP _attr_supported_features = (ClimateEntityFeature.TARGET_TEMPERATURE | ClimateEntityFeature.FAN_MODE | ClimateEntityFeature.SWING_MODE) _attr_swing_modes = SUPPORTED_SWING_MODES _attr_target_temperature_step = SUPPORTED_TARGET_TEMPERATURE_STEP _attr_temperature_unit = TEMP_CELSIUS _attr_should_poll = False def __init__(self, said, auth: Auth): """Initialize the entity.""" self._aircon = Aircon(auth, said, self.async_write_ha_state) self._attr_name = said self._attr_unique_id = said async def async_added_to_hass(self) -> None: """Connect aircon to the cloud.""" await self._aircon.connect() try: name = await self._aircon.fetch_name() if name is not None: self._attr_name = name except (asyncio.TimeoutError, aiohttp.ClientError): _LOGGER.exception("Failed to get name") @property def available(self) -> bool: """Return True if entity is available.""" return self._aircon.get_online() @property def current_temperature(self): """Return the current temperature.""" return self._aircon.get_current_temp() @property def target_temperature(self): """Return the temperature we try to reach.""" return self._aircon.get_temp() async def async_set_temperature(self, **kwargs): """Set new target temperature.""" await self._aircon.set_temp(kwargs.get(ATTR_TEMPERATURE)) @property def current_humidity(self): """Return the current humidity.""" return self._aircon.get_current_humidity() @property def target_humidity(self): """Return the humidity we try to reach.""" return self._aircon.get_humidity() async def async_set_humidity(self, humidity: int) -> None: """Set new target humidity.""" await self._aircon.set_humidity(humidity) @property def hvac_mode(self): """Return current operation ie. heat, cool, fan.""" if not self._aircon.get_power_on(): return HVAC_MODE_OFF mode: AirconMode = self._aircon.get_mode() return AIRCON_MODE_MAP.get(mode) async def async_set_hvac_mode(self, hvac_mode): """Set HVAC mode.""" if hvac_mode == HVAC_MODE_OFF: await self._aircon.set_power_on(False) return if not (mode := HVAC_MODE_TO_AIRCON_MODE.get(hvac_mode)): raise ValueError(f"Invalid hvac mode {hvac_mode}") await self._aircon.set_mode(mode) if not self._aircon.get_power_on(): await self._aircon.set_power_on(True)
class AirConEntity(ClimateEntity): """Representation of an air conditioner.""" def __init__(self, said, auth: Auth): """Initialize the entity.""" self._aircon = Aircon(auth, said, self.schedule_update_ha_state) self._supported_features = SUPPORT_TARGET_TEMPERATURE self._supported_features |= SUPPORT_FAN_MODE self._supported_features |= SUPPORT_SWING_MODE async def _async_connect(self): """Connect aircon to the cloud.""" await self._aircon.connect() @property def min_temp(self) -> float: """Return the minimum temperature.""" return 16 @property def max_temp(self) -> float: """Return the maximum temperature.""" return 30 @property def supported_features(self): """Return the list of supported features.""" return self._supported_features @property def name(self): """Return the name of the aircon.""" return self._aircon._said # TODO: return user-given-name from the API @property def unique_id(self): """Return a unique ID.""" return self._aircon._said @property def available(self) -> bool: """Return True if entity is available.""" return self._aircon.get_online() @property def temperature_unit(self): """Return the unit of measurement which this thermostat uses.""" return TEMP_CELSIUS @property def current_temperature(self): """Return the current temperature.""" return self._aircon.get_current_temp() @property def target_temperature(self): """Return the temperature we try to reach.""" return self._aircon.get_temp() @property def target_temperature_step(self): """Return the supported step of target temperature.""" return 1 async def async_set_temperature(self, **kwargs): """Set new target temperature.""" await self._aircon.set_temp(kwargs.get(ATTR_TEMPERATURE)) @property def current_humidity(self): """Return the current humidity.""" return self._aircon.get_current_humidity() @property def target_humidity(self): """Return the humidity we try to reach.""" return self._aircon.get_humidity() @property def target_humidity_step(self): """Return the supported step of target humidity.""" return 10 async def async_set_humidity(self, **kwargs): """Set new target humidity.""" await self._aircon.set_humidity(kwargs.get(ATTR_HUMIDITY)) @property def hvac_modes(self): """Return the list of available operation modes.""" return [ HVAC_MODE_COOL, HVAC_MODE_HEAT, HVAC_MODE_FAN_ONLY, HVAC_MODE_OFF ] @property def hvac_mode(self): """Return current operation ie. heat, cool, fan.""" if not self._aircon.get_power_on(): return HVAC_MODE_OFF mode: AirconMode = self._aircon.get_mode() if mode == AirconMode.Cool: return HVAC_MODE_COOL elif mode == AirconMode.Heat: return HVAC_MODE_HEAT elif mode == AirconMode.Fan: return HVAC_MODE_FAN_ONLY return None async def async_set_hvac_mode(self, hvac_mode): """Set HVAC mode.""" if hvac_mode == HVAC_MODE_OFF: await self._aircon.set_power_on(False) mode = None if hvac_mode == HVAC_MODE_COOL: mode = AirconMode.Cool elif hvac_mode == HVAC_MODE_HEAT: mode = AirconMode.Heat elif hvac_mode == HVAC_MODE_FAN_ONLY: mode = AirconMode.Fan if not mode: return await self._aircon.set_mode(mode) if not self._aircon.get_power_on(): await self._aircon.set_power_on(True) @property def fan_modes(self): """List of available fan modes.""" return [FAN_OFF, FAN_AUTO, FAN_LOW, FAN_MEDIUM, FAN_HIGH] @property def fan_mode(self): """Return the fan setting.""" fanspeed = self._aircon.get_fanspeed() if fanspeed == AirconFanSpeed.Auto: return FAN_AUTO elif fanspeed == AirconFanSpeed.Low: return FAN_LOW elif fanspeed == AirconFanSpeed.Medium: return FAN_MEDIUM elif fanspeed == AirconFanSpeed.High: return FAN_HIGH return FAN_OFF async def async_set_fan_mode(self, fan_mode): """Set fan mode.""" fanspeed = None if fan_mode == FAN_AUTO: fanspeed = AirconFanSpeed.Auto elif fan_mode == FAN_LOW: fanspeed = AirconFanSpeed.Low elif fan_mode == FAN_MEDIUM: fanspeed = AirconFanSpeed.Medium elif fan_mode == FAN_HIGH: fanspeed = AirconFanSpeed.High if not fanspeed: return await self._aircon.set_fanspeed(fanspeed) @property def swing_modes(self): """List of available swing modes.""" return [SWING_HORIZONTAL, SWING_OFF] @property def swing_mode(self): """Return the swing setting.""" return SWING_HORIZONTAL if self._aircon.get_h_louver_swing( ) else SWING_OFF async def async_set_swing_mode(self, swing_mode): """Set new target temperature.""" if swing_mode == SWING_HORIZONTAL: await self._aircon.set_h_louver_swing(True) else: await self._aircon.set_h_louver_swing(False) async def async_turn_on(self): """Turn device on.""" await self._aircon.set_power_on(True) async def async_turn_off(self): """Turn device off.""" await self._aircon.set_power_on(False)
async def show_aircon_menu(backend_selector, auth, said): def print_menu(): print("\n") print(30 * "-", "MENU", 30 * "-") print("1. Turn on") print("0. Turn off") print("+. Temp up") print("-. Temp down") print("C. Mode: Cool") print("H. Mode: Heat") print("F. Mode: Fan") print("S. Mode: Sixth Sense") print("2. Swing toggle") print("3. Turbo toggle") print("4. Eco toggle") print("5. Quiet toggle") print("6. Display toggle") print("u. Update status from server") print("p. Print status") print("v. Print raw status") print("c. Custom command") print("q. Exit") print(67 * "-") def print_status(ac: Aircon): print("online: " + str(ac.get_online())) print("power_on: " + str(ac.get_power_on())) print("temp: " + str(ac.get_temp())) print("humidity: " + str(ac.get_humidity())) print("current_temp: " + str(ac.get_current_temp())) print("current_humidity: " + str(ac.get_current_humidity())) print("mode: " + str(ac.get_mode())) print("sixthsense_mode: " + str(ac.get_sixthsense_mode())) print("fanspeed: " + str(ac.get_fanspeed())) print("h_louver_swing: " + str(ac.get_h_louver_swing())) print("turbo_mode: " + str(ac.get_turbo_mode())) print("eco_mode: " + str(ac.get_eco_mode())) print("quiet_mode: " + str(ac.get_quiet_mode())) print("display_on: " + str(ac.get_display_on())) def attr_upd(): print("Attributes updated") ac = Aircon(backend_selector, auth, said, attr_upd) await ac.connect() loop = True while loop: print_menu() choice = await aioconsole.ainput("Enter your choice: ") if choice == "1": await ac.set_power_on(True) elif choice == "0": await ac.set_power_on(False) elif choice == "+": temp = ac.get_temp() + 1 await ac.set_temp(temp) elif choice == "-": temp = ac.get_temp() - 1 await ac.set_temp(temp) elif choice == "C": await ac.set_mode(Mode.Cool) elif choice == "H": await ac.set_mode(Mode.Heat) elif choice == "F": await ac.set_mode(Mode.Fan) elif choice == "S": await ac.set_mode(Mode.SixthSense) elif choice == "2": await ac.set_h_louver_swing(not ac.get_h_louver_swing()) elif choice == "3": await ac.set_turbo_mode(not ac.get_turbo_mode()) elif choice == "4": await ac.set_eco_mode(not ac.get_eco_mode()) elif choice == "5": await ac.set_quiet_mode(not ac.get_quiet_mode()) elif choice == "6": await ac.set_display_on(not ac.get_display_on()) elif choice == "p": print_status(ac) elif choice == "u": await ac.fetch_data() print_status(ac) elif choice == "v": print(ac._data_dict) elif choice == "c": cmd = aioconsole.ainput("Command: ") val = aioconsole.ainput("Value: ") await ac.send_attributes({cmd: val}) elif choice == "q": await ac.disconnect() auth.cancel_auto_renewal() print("Bye") loop = False else: print("Wrong option selection. Enter any key to try again..")
def print_status(ac: Aircon): print("online: " + str(ac.get_online())) print("power_on: " + str(ac.get_power_on())) print("temp: " + str(ac.get_temp())) print("humidity: " + str(ac.get_humidity())) print("current_temp: " + str(ac.get_current_temp())) print("current_humidity: " + str(ac.get_current_humidity())) print("mode: " + str(ac.get_mode())) print("sixthsense_mode: " + str(ac.get_sixthsense_mode())) print("fanspeed: " + str(ac.get_fanspeed())) print("h_louver_swing: " + str(ac.get_h_louver_swing())) print("turbo_mode: " + str(ac.get_turbo_mode())) print("eco_mode: " + str(ac.get_eco_mode())) print("quiet_mode: " + str(ac.get_quiet_mode())) print("display_on: " + str(ac.get_display_on()))
async def test_attributes(caplog, aio_httpclient): caplog.set_level(logging.DEBUG) auth = MagicMock() aio_httpclient.get.return_value = MockResponse(json.dumps(DATA1), 200) aircon = Aircon(BackendSelectorMock(), auth, SAID, None) await aircon.connect() assert aircon.get_online() is False assert aircon.get_power_on() is False assert aircon.get_display_on() is False assert aircon.get_current_temp() == 23 assert aircon.get_current_humidity() == 56 assert aircon.get_temp() == 30 assert aircon.get_humidity() == 40 assert aircon.get_mode() == Mode.Heat assert aircon.get_sixthsense_mode() is False assert aircon.get_fanspeed() == FanSpeed.Off assert aircon.get_h_louver_swing() is True assert aircon.get_turbo_mode() is False assert aircon.get_eco_mode() is False assert aircon.get_quiet_mode() is False await aircon.disconnect() aio_httpclient.get.return_value = MockResponse(json.dumps(DATA2), 200) await aircon.connect() assert aircon.get_online() is True assert aircon.get_power_on() is True assert aircon.get_display_on() is True assert aircon.get_current_temp() == 30 assert aircon.get_current_humidity() == 31 assert aircon.get_temp() == 29 assert aircon.get_humidity() == 45 assert aircon.get_mode() == Mode.Fan assert aircon.get_sixthsense_mode() is True assert aircon.get_fanspeed() == FanSpeed.Auto assert aircon.get_h_louver_swing() is False assert aircon.get_turbo_mode() is True assert aircon.get_eco_mode() is True assert aircon.get_quiet_mode() is True await aircon.disconnect()
async def test_setters(caplog, aio_httpclient): caplog.set_level(logging.DEBUG) auth = MagicMock() aio_httpclient.get.return_value = MockResponse(json.dumps(DATA1), 200) aio_httpclient.post.return_value = MockResponse("", 200) cmd_data = { "header": {"said": SAID, "command": "setAttributes"}, } aircon = Aircon(BackendSelectorMock(), auth, SAID, None) await aircon.connect() await aircon.set_power_on(True) cmd_data["body"] = {"Sys_OpSetPowerOn": "1"} aio_httpclient.post.assert_called_once_with(ANY, json=cmd_data) aio_httpclient.post.reset_mock() await aircon.set_power_on(False) cmd_data["body"] = {"Sys_OpSetPowerOn": "0"} aio_httpclient.post.assert_called_once_with(ANY, json=cmd_data) aio_httpclient.post.reset_mock() await aircon.set_temp(30) cmd_data["body"] = {"Sys_OpSetTargetTemp": "300"} aio_httpclient.post.assert_called_once_with(ANY, json=cmd_data) aio_httpclient.post.reset_mock() await aircon.set_humidity(45) cmd_data["body"] = {"Sys_OpSetTargetHumidity": "45"} aio_httpclient.post.assert_called_once_with(ANY, json=cmd_data) aio_httpclient.post.reset_mock() await aircon.set_mode(Mode.Cool) cmd_data["body"] = {"Cavity_OpSetMode": "1"} aio_httpclient.post.assert_called_once_with(ANY, json=cmd_data) aio_httpclient.post.reset_mock() await aircon.set_fanspeed(FanSpeed.Auto) cmd_data["body"] = {"Cavity_OpSetFanSpeed": "1"} aio_httpclient.post.assert_called_once_with(ANY, json=cmd_data) aio_httpclient.post.reset_mock() await aircon.set_h_louver_swing(True) cmd_data["body"] = {"Cavity_OpSetHorzLouverSwing": "1"} aio_httpclient.post.assert_called_once_with(ANY, json=cmd_data) aio_httpclient.post.reset_mock() await aircon.set_turbo_mode(False) cmd_data["body"] = {"Cavity_OpSetTurboMode": "0"} aio_httpclient.post.assert_called_once_with(ANY, json=cmd_data) aio_httpclient.post.reset_mock() await aircon.set_eco_mode(False) cmd_data["body"] = {"Sys_OpSetEcoModeEnabled": "0"} aio_httpclient.post.assert_called_once_with(ANY, json=cmd_data) aio_httpclient.post.reset_mock() await aircon.set_quiet_mode(False) cmd_data["body"] = {"Sys_OpSetQuietModeEnabled": "0"} aio_httpclient.post.assert_called_once_with(ANY, json=cmd_data) aio_httpclient.post.reset_mock() await aircon.set_display_on(True) cmd_data["body"] = {"Sys_DisplaySetBrightness": "4"} aio_httpclient.post.assert_called_once_with(ANY, json=cmd_data) await aircon.disconnect()
class AirConEntity(ClimateEntity): """Representation of an air conditioner.""" _attr_fan_modes = [FAN_AUTO, FAN_HIGH, FAN_MEDIUM, FAN_LOW, FAN_OFF] _attr_hvac_modes = [ HVAC_MODE_COOL, HVAC_MODE_HEAT, HVAC_MODE_FAN_ONLY, HVAC_MODE_OFF, ] _attr_max_temp = 30 _attr_min_temp = 16 _attr_supported_features = (SUPPORT_TARGET_TEMPERATURE | SUPPORT_FAN_MODE | SUPPORT_SWING_MODE) _attr_swing_modes = [SWING_HORIZONTAL, SWING_OFF] _attr_target_temperature_step = 1 _attr_temperature_unit = TEMP_CELSIUS _attr_should_poll = False def __init__(self, said, auth: Auth): """Initialize the entity.""" self._aircon = Aircon(auth, said, self.async_write_ha_state) self._attr_name = said self._attr_unique_id = said async def async_added_to_hass(self) -> None: """Connect aircon to the cloud.""" await self._aircon.connect() try: name = await self._aircon.fetch_name() if name is not None: self._attr_name = name except (asyncio.TimeoutError, aiohttp.ClientError): _LOGGER.exception("Failed to get name") @property def available(self) -> bool: """Return True if entity is available.""" return self._aircon.get_online() @property def current_temperature(self): """Return the current temperature.""" return self._aircon.get_current_temp() @property def target_temperature(self): """Return the temperature we try to reach.""" return self._aircon.get_temp() async def async_set_temperature(self, **kwargs): """Set new target temperature.""" await self._aircon.set_temp(kwargs.get(ATTR_TEMPERATURE)) @property def current_humidity(self): """Return the current humidity.""" return self._aircon.get_current_humidity() @property def target_humidity(self): """Return the humidity we try to reach.""" return self._aircon.get_humidity() async def async_set_humidity(self, humidity: int) -> None: """Set new target humidity.""" await self._aircon.set_humidity(humidity) @property def hvac_mode(self): """Return current operation ie. heat, cool, fan.""" if not self._aircon.get_power_on(): return HVAC_MODE_OFF mode: AirconMode = self._aircon.get_mode() return AIRCON_MODE_MAP.get(mode, None) async def async_set_hvac_mode(self, hvac_mode): """Set HVAC mode.""" if hvac_mode == HVAC_MODE_OFF: await self._aircon.set_power_on(False) return mode = HVAC_MODE_TO_AIRCON_MODE.get(hvac_mode) if not mode: _LOGGER.warning("Unexpected hvac mode: %s", hvac_mode) return await self._aircon.set_mode(mode) if not self._aircon.get_power_on(): await self._aircon.set_power_on(True) @property def fan_mode(self): """Return the fan setting.""" fanspeed = self._aircon.get_fanspeed() return AIRCON_FANSPEED_MAP.get(fanspeed, FAN_OFF) async def async_set_fan_mode(self, fan_mode): """Set fan mode.""" fanspeed = FAN_MODE_TO_AIRCON_FANSPEED.get(fan_mode) if not fanspeed: return await self._aircon.set_fanspeed(fanspeed) @property def swing_mode(self): """Return the swing setting.""" return SWING_HORIZONTAL if self._aircon.get_h_louver_swing( ) else SWING_OFF async def async_set_swing_mode(self, swing_mode): """Set new target temperature.""" await self._aircon.set_h_louver_swing(swing_mode == SWING_HORIZONTAL) async def async_turn_on(self): """Turn device on.""" await self._aircon.set_power_on(True) async def async_turn_off(self): """Turn device off.""" await self._aircon.set_power_on(False)