Skip to content

Commit

Permalink
Merge pull request #30 from jbergler/master
Browse files Browse the repository at this point in the history
Mostly logging updates
  • Loading branch information
jbergler authored Mar 26, 2023
2 parents b87373e + eb71f1c commit f5eb801
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 28 deletions.
3 changes: 1 addition & 2 deletions custom_components/intesisbox/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=

async def async_setup_entry(hass, entry, async_add_entities):
controller = hass.data[DOMAIN][entry.entry_id]
controller.poll_status()
async_add_entities([IntesisBoxAC(controller)], True)

class IntesisBoxAC(ClimateEntity):
Expand Down Expand Up @@ -250,7 +249,7 @@ def set_swing_mode(self, swing_mode):
async def async_update(self):
"""Copy values from controller dictionary to climate device."""
if not self._controller.is_connected:
await asyncio.sleep(1) # per device specs, wait min 1 sec before re-connecting
await asyncio.sleep(60) # per device specs, wait min 1 sec before re-connecting
await self.hass.async_add_executor_job(self._controller.connect)
self._connection_retries += 1
else:
Expand Down
86 changes: 60 additions & 26 deletions custom_components/intesisbox/intesisbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from asyncio import ensure_future
from time import sleep

_LOGGER = logging.getLogger('pyintesisbox')
_LOGGER = logging.getLogger(__name__)

API_DISCONNECTED = "Disconnected"
API_CONNECTING = "Connecting"
Expand All @@ -35,7 +35,7 @@
FUNCTION_ERRSTATUS = 'ERRSTATUS'
FUNCTION_ERRCODE = 'ERRCODE'

NULL_VALUE = '32768'
NULL_VALUE = '-32768'


class IntesisBox(asyncio.Protocol):
Expand Down Expand Up @@ -74,30 +74,35 @@ async def keep_alive(self):
"""Send a keepalive command to reset it's watchdog timer."""
while self.is_connected:
_LOGGER.debug("Sending keepalive")
self._transport.write("PING\r".encode('ascii'))
self._write("PING")
await asyncio.sleep(45)
else:
_LOGGER.debug("Not connected, skipping keepalive")

async def query_initial_state(self):
self._transport.write("ID\r".encode('ascii'))
await asyncio.sleep(1)
self._transport.write("LIMITS:SETPTEMP\r".encode('ascii'))
await asyncio.sleep(1)
self._transport.write("LIMITS:FANSP\r".encode('ascii'))
await asyncio.sleep(1)
self._transport.write("LIMITS:MODE\r".encode('ascii'))
await asyncio.sleep(1)
self._transport.write("LIMITS:VANEUD\r".encode('ascii'))
await asyncio.sleep(1)
self._transport.write("LIMITS:VANELR\r".encode('ascii'))
cmds = [
"ID",
"LIMITS:SETPTEMP",
"LIMITS:FANSP",
"LIMITS:MODE",
"LIMITS:VANEUD",
"LIMITS:VANELR",
]
for cmd in cmds:
self._write(cmd)
await asyncio.sleep(1)

def _write(self, cmd):
self._transport.write(f"{cmd}\r".encode('ascii'))
_LOGGER.debug(f"Data sent: {cmd!r}")

def data_received(self, data):
"""asyncio callback when data is received on the socket"""
decoded_data = data.decode('ascii')
_LOGGER.debug("Data received: {}".format(decoded_data))
linesReceived = decoded_data.splitlines()
linesReceived = data.decode('ascii').splitlines()
statusChanged = False

for line in linesReceived:
_LOGGER.debug(f"Data received: {line!r}")
cmdList = line.split(':', 1)
cmd = cmdList[0]
args = None
Expand All @@ -107,12 +112,16 @@ def data_received(self, data):
self._parse_id_received(args)
self._connectionStatus = API_AUTHENTICATED
asyncio.ensure_future(self.keep_alive())
asyncio.ensure_future(self.poll_status())
elif cmd == 'CHN,1':
self._parse_change_received(args)
statusChanged = True
elif cmd == 'LIMITS':
self._parse_limits_received(args)
statusChanged = True

self._send_update_callback()
if statusChanged:
self._send_update_callback()

def _parse_id_received(self, args):
# ID:Model,MAC,IP,Protocol,Version,RSSI
Expand All @@ -123,13 +132,24 @@ def _parse_id_received(self, args):
self._firmversion = info[4]
self._rssi = info[5]

_LOGGER.debug(
"Updated info:",
f"model:{self._model}",
f"mac:{self._mac}",
f"version:{self._firmversion}",
f"rssi:{self._rssi}",
)


def _parse_change_received(self, args):
function = args.split(',')[0]
value = args.split(',')[1]
if value == NULL_VALUE:
value = None
self._device[function] = value

_LOGGER.debug(f"Updated state: {self._device!r}")

def _parse_limits_received(self, args):
split_args = args.split(',', 1)

Expand All @@ -148,6 +168,16 @@ def _parse_limits_received(self, args):
self._vertical_vane_list = values
elif function == FUNCTION_VANELR:
self._horizontal_vane_list = values

_LOGGER.debug(
"Updated limits: ",
f"{self._setpoint_minimum=}",
f"{self._setpoint_maximum=}",
f"{self._fan_speed_list=}",
f"{self._operation_list=}",
f"{self._vertical_vane_list=}",
f"{self._horizontal_vane_list=}",
)
return

def connection_lost(self, exc):
Expand All @@ -172,18 +202,27 @@ def connect(self):
ensure_future(coro, loop=self._eventLoop)
else:
_LOGGER.debug("Missing IP address or port.")
self._connectionStatus = API_DISCONNECTED

except Exception as e:
_LOGGER.error('%s Exception. %s / %s', type(e), repr(e.args), e)
self._connectionStatus = API_DISCONNECTED
else:
_LOGGER.debug('connect() called but already connecting')

def stop(self):
"""Public method for shutting down connectivity with the envisalink."""
self._connectionStatus = API_DISCONNECTED
self._transport.close()

def poll_status(self, sendcallback=False):
self._transport.write("GET,1:*\r".encode('ascii'))
async def poll_status(self, sendcallback=False):
"""Periodically poll for updates since the controllers don't always update reliably"""
while self.is_connected:
_LOGGER.debug("Polling for update")
self._write("GET,1:*")
await asyncio.sleep(60*5) # 5 minutes
else:
_LOGGER.debug("Not connected, skipping poll_status()")

def set_temperature(self, setpoint):
"""Public method for setting the temperature"""
Expand All @@ -204,10 +243,8 @@ def set_horizontal_vane(self, vane: str):

def _set_value(self, uid, value):
"""Internal method to send a command to the API"""
message = "SET,{}:{},{}\r".format(1, uid, value)
try:
self._transport.write(message.encode('ascii'))
_LOGGER.debug("Data sent: {!r}".format(message))
self._write(f"SET,1:{uid},{value}")
except Exception as e:
_LOGGER.error('%s Exception. %s / %s', type(e), e.args, e)

Expand Down Expand Up @@ -292,9 +329,6 @@ def ambient_temperature(self) -> float:
temperature = self._device.get(FUNCTION_AMBTEMP)
if temperature:
temperature = int(temperature) / 10
# When unsupported, -32768 is reported
if temperature == -3276.8:
temperature = None
return temperature

@property
Expand Down

0 comments on commit f5eb801

Please sign in to comment.