diff --git a/.gitignore b/.gitignore index 894a44c..89f4f67 100644 --- a/.gitignore +++ b/.gitignore @@ -102,3 +102,9 @@ venv.bak/ # mypy .mypy_cache/ + +#.idea +/.idea + +# Ignore Mac DS_Store files +.DS_Store \ No newline at end of file diff --git a/custom_components/intesisbox/climate.py b/custom_components/intesisbox/climate.py index 705a7f3..e536152 100644 --- a/custom_components/intesisbox/climate.py +++ b/custom_components/intesisbox/climate.py @@ -4,6 +4,8 @@ https://github.com/jnimmo/hass-intesisbox """ +from __future__ import annotations + import asyncio from datetime import timedelta import logging @@ -406,8 +408,10 @@ def hvac_mode(self): @property def target_temperature(self): - """Return the current setpoint temperature if unit is on.""" - return self._target_temperature + """Return the current setpoint temperature if unit is on and not FAN or OFF Mode.""" + if self._power and self.hvac_mode not in [HVACMode.FAN_ONLY, HVACMode.OFF]: + return self._target_temperature + return None @property def supported_features(self): diff --git a/custom_components/intesisbox/intesisbox.py b/custom_components/intesisbox/intesisbox.py index 38105c9..7046aa4 100644 --- a/custom_components/intesisbox/intesisbox.py +++ b/custom_components/intesisbox/intesisbox.py @@ -1,5 +1,7 @@ """Communication with an Intesisbox device.""" +from __future__ import annotations + import asyncio from asyncio import BaseTransport, ensure_future from collections.abc import Callable @@ -78,6 +80,15 @@ async def keep_alive(self): else: _LOGGER.debug("Not connected, skipping keepalive") + async def poll_ambtemp(self): + """Retrieve Ambient Temperature to prevent integration timeouts.""" + while self.is_connected: + _LOGGER.debug("Sending AMBTEMP") + self._write("GET,1:AMBTEMP") + await asyncio.sleep(10) + else: + _LOGGER.debug("Not connected, skipping Ambient Temp Request") + async def query_initial_state(self): """Fetch configuration from the device upon connection.""" cmds = [ @@ -96,6 +107,12 @@ def _write(self, cmd): self._transport.write(f"{cmd}\r".encode("ascii")) _LOGGER.debug(f"Data sent: {cmd!r}") + async def _writeasync(self, cmd): + """Async write to slow down commands and await response from units.""" + self._transport.write(f"{cmd}\r".encode("ascii")) + _LOGGER.debug(f"Data sent: {cmd!r}") + await asyncio.sleep(1) + def data_received(self, data): """Asyncio callback when data is received on the socket.""" linesReceived = data.decode("ascii").splitlines() @@ -111,8 +128,8 @@ def data_received(self, data): if cmd == "ID": self._parse_id_received(args) self._connectionStatus = API_AUTHENTICATED - _ = asyncio.ensure_future(self.keep_alive()) _ = asyncio.ensure_future(self.poll_status()) + _ = asyncio.ensure_future(self.poll_ambtemp()) elif cmd == "CHN,1": self._parse_change_received(args) statusChanged = True @@ -244,17 +261,34 @@ def set_horizontal_vane(self, vane: str): def _set_value(self, uid: str, value: str | int) -> None: """Change a setting on the thermostat.""" try: - self._write(f"SET,1:{uid},{value}") + asyncio.run(self._writeasync(f"SET,1:{uid},{value}")) except Exception as e: _LOGGER.error("%s Exception. %s / %s", type(e), e.args, e) - def set_mode(self, mode: str) -> None: - """Change the thermostat mode (heat, cool, etc).""" - if not self.is_on: - self.set_power_on() - + def set_mode(self, mode): + """Send mode and confirm change before turning on.""" + """Some units return responses out of order""" + _LOGGER.debug(f"Setting MODE to {mode}.") if mode in MODES: self._set_value(FUNCTION_MODE, mode) + if not self.is_on: + """Check to ensure in correct mode before turning on""" + retry = 30 + while self.mode != mode and retry > 0: + _LOGGER.debug( + f"Waiting for MODE to return {mode}, currently {str(self.mode)}" + ) + _LOGGER.debug(f"Retry attempt = {retry}") + asyncio.run(self._writeasync("GET,1:MODE")) + retry -= 1 + else: + if retry != 0: + _LOGGER.debug( + f"MODE confirmed now {str(self.mode)}, proceed to Power On" + ) + self.set_power_on() + else: + _LOGGER.error("Cannot set Intesisbox mode giving up...") def set_mode_dry(self): """Public method to set device to dry asynchronously."""