Skip to content

Commit

Permalink
Move sending of keepalives outside the library
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelarnauts committed Dec 15, 2022
1 parent 91a16ca commit 3899b40
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 26 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ $ python -m aiocomfoconnect set-speed low --host 192.168.1.213
$ python -m aiocomfoconnect set-speed medium --host 192.168.1.213
$ python -m aiocomfoconnect set-speed high --host 192.168.1.213

$ python -m aiocomfoconnect set-speed show-sensors --host 192.168.1.213
$ python -m aiocomfoconnect show-sensors --host 192.168.1.213
```

## Available methods
Expand Down
35 changes: 23 additions & 12 deletions aiocomfoconnect/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
from aiocomfoconnect import DEFAULT_NAME, DEFAULT_PIN, DEFAULT_UUID
from aiocomfoconnect.comfoconnect import ComfoConnect
from aiocomfoconnect.discovery import discover_bridges
from aiocomfoconnect.exceptions import ComfoConnectNotAllowed
from aiocomfoconnect.exceptions import (
AioComfoConnectNotConnected,
ComfoConnectNotAllowed,
)
from aiocomfoconnect.sensors import SENSORS

_LOGGER = logging.getLogger(__name__)
Expand Down Expand Up @@ -51,20 +54,18 @@ async def run_register(host: str, uuid: str, name: str, pin: int):

# Connect to the bridge
comfoconnect = ComfoConnect(bridges[0].host, bridges[0].uuid)
await comfoconnect.connect(uuid)

try:
# Login with the bridge
await comfoconnect.cmd_start_session()

await comfoconnect.connect(uuid)
print(f"UUID {uuid} is already registered.")

except ComfoConnectNotAllowed:
# We probably are not registered yet...
await comfoconnect.cmd_register_app(uuid, name, pin)

# Connect to the bridge
await comfoconnect.cmd_start_session()
await comfoconnect.cmd_start_session(True)

# ListRegisteredApps
print("Registered applications:")
Expand All @@ -85,7 +86,6 @@ async def run_set_speed(host: str, uuid: str, speed: Literal["away", "low", "med
# Connect to the bridge
comfoconnect = ComfoConnect(bridges[0].host, bridges[0].uuid)
await comfoconnect.connect(uuid)
await comfoconnect.cmd_start_session()

await comfoconnect.set_speed(speed)

Expand All @@ -94,10 +94,8 @@ async def run_set_speed(host: str, uuid: str, speed: Literal["away", "low", "med

async def run_show_sensors(host: str, uuid: str):
"""Connect to a bridge."""
loop = asyncio.get_running_loop()

# Discover bridge so we know the UUID
bridges = await discover_bridges(host, loop=loop)
bridges = await discover_bridges(host)
if not bridges:
raise Exception("No bridge found")

Expand All @@ -114,14 +112,27 @@ def sensor_callback(sensor, value):
# Connect to the bridge
comfoconnect = ComfoConnect(bridges[0].host, bridges[0].uuid, sensor_callback=sensor_callback, alarm_callback=alarm_callback)
await comfoconnect.connect(uuid)
await comfoconnect.cmd_start_session()

# Register all sensors
for key in SENSORS:
await comfoconnect.register_sensor(SENSORS[key])

# Wait for updates
await asyncio.sleep(60)
try:
while True:
# Wait for updates and send a keepalive every 60 seconds
await asyncio.sleep(60)

try:
print(f"Sending keepalive...")
await comfoconnect.cmd_keepalive()
except AioComfoConnectNotConnected as ex:
# Reconnect when connection has been dropped
await comfoconnect.connect(uuid)

except KeyboardInterrupt:
pass

print("Disconnecting...")
await comfoconnect.disconnect()


Expand Down
22 changes: 15 additions & 7 deletions aiocomfoconnect/bridge.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class Bridge:

PORT = 56747

def __init__(self, host: str, uuid: str):
def __init__(self, host: str, uuid: str, loop=None):
self.host: str = host
self.uuid: str = uuid
self._local_uuid: str = None
Expand All @@ -60,6 +60,8 @@ def __init__(self, host: str, uuid: str):
self.__sensor_callback_fn: callable = None
self.__alarm_callback_fn: callable = None

self._loop = loop or asyncio.get_running_loop()

def __repr__(self):
return "<Bridge {0}, UID={1}>".format(self.host, self.uuid)

Expand All @@ -71,18 +73,16 @@ def set_alarm_callback(self, callback: callable):
"""Set a callback to be called when an alarm is received."""
self.__alarm_callback_fn = callback

async def connect(self, uuid: str, loop=None):
async def connect(self, uuid: str):
"""Connect to the bridge."""
_LOGGER.debug("Connecting to bridge %s", self.host)
self._reader, self._writer = await asyncio.open_connection(self.host, self.PORT)
self._reference = 1 # random.randint(1000, 20000)
self._reference = 1
self._local_uuid = uuid
self._event_bus = EventBus()

# We are connected, start the background task
if loop is None:
loop = asyncio.get_event_loop()
self._read_task = loop.create_task(self._read_messages())
self._read_task = self._loop.create_task(self._read_messages())

async def disconnect(self):
"""Disconnect from the bridge."""
Expand All @@ -97,8 +97,16 @@ async def disconnect(self):
# Wait for background task to finish
await self._read_task

def is_connected(self) -> bool:
"""Returns True if the bridge is connected."""
return self._writer is not None and not self._writer.is_closing()

def _send(self, request, request_type, params: dict = None, reply: bool = True):
"""Sends a command and wait for a response if the request is known to return a result."""
# Check if we are actually connected
if not self.is_connected():
raise AioComfoConnectNotConnected()

# Construct the message
cmd = zehnder_pb2.GatewayOperation()
cmd.type = request_type
Expand Down Expand Up @@ -204,7 +212,7 @@ async def _read_messages(self):
return # Stop the background task

except IncompleteReadError:
_LOGGER.info("The other end has closed the connection.")
_LOGGER.info("The connection was closed.")
return # Stop the background task

except ComfoConnectError as exc:
Expand Down
19 changes: 13 additions & 6 deletions aiocomfoconnect/comfoconnect.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ class ComfoConnect(Bridge):

INITIAL_SENSOR_DELAY = 2 # 2 seconds cutoff seems fine

def __init__(self, host: str, uuid: str, sensor_callback=None, alarm_callback=None):
def __init__(self, host: str, uuid: str, loop=None, sensor_callback=None, alarm_callback=None):
"""Initialize the ComfoConnect class."""
super().__init__(host, uuid)
super().__init__(host, uuid, loop)

self.set_sensor_callback(self._sensor_callback) # Set the callback to our _sensor_callback method, so we can proces the callbacks.
self.set_alarm_callback(self._alarm_callback) # Set the callback to our _alarm_callback method, so we can proces the callbacks.
Expand All @@ -41,15 +41,22 @@ def _unhold_sensors(self):
if self._sensors_values[sensor_id] is not None:
self._sensor_callback(sensor_id, self._sensors_values[sensor_id])

async def connect(self, uuid: str, loop=None):
async def connect(self, uuid: str, start_session=True):
"""Connect to the bridge."""
loop = loop or asyncio.get_running_loop()
await super().connect(uuid)

self._sensors_values = {}

if self.INITIAL_SENSOR_DELAY:
_LOGGER.debug("Holding sensors for %s second(s)", self.INITIAL_SENSOR_DELAY)
self._sensor_hold = loop.call_later(self.INITIAL_SENSOR_DELAY, self._unhold_sensors)
self._sensor_hold = self._loop.call_later(self.INITIAL_SENSOR_DELAY, self._unhold_sensors)

if start_session:
await self.cmd_start_session(True)

await super().connect(uuid, loop)
# Register the sensors again (in case we lost the connection)
for sensor in self._sensors.values():
await self.cmd_rpdo_request(sensor.id, sensor.type)

async def register_sensor(self, sensor: Sensor):
"""Register a sensor on the bridge."""
Expand Down
6 changes: 6 additions & 0 deletions aiocomfoconnect/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,9 @@ class ComfoConnectNotExist(ComfoConnectError):

class ComfoConnectRmiError(ComfoConnectError):
pass


class AioComfoConnectNotConnected(Exception):
"""An error occured because the bridge is not connected."""

pass

0 comments on commit 3899b40

Please sign in to comment.