From b75288881283c679ab593f9d3c7f6001e41dae95 Mon Sep 17 00:00:00 2001
From: lilly
Date: Sun, 31 May 2026 20:53:14 +0200
Subject: [PATCH 1/3] api: fix mqtt reconnect logic errors
---
api/src/dooris_api/ccujack.py | 9 ++++++---
api/src/dooris_api/mqtt_client.py | 26 +++++++++++++++++---------
2 files changed, 23 insertions(+), 12 deletions(-)
diff --git a/api/src/dooris_api/ccujack.py b/api/src/dooris_api/ccujack.py
index 03d0480..a6b0640 100644
--- a/api/src/dooris_api/ccujack.py
+++ b/api/src/dooris_api/ccujack.py
@@ -162,15 +162,18 @@ class CCUJackClient:
while True:
try:
- await asyncio.sleep(15 * 60) # 15 minutes
logger.info("Running CCUJack cron")
- await self.find_locks()
- if not self.mqtt.is_connected():
+ if not self.mqtt.is_connected:
logger.warning("MQTT client was discovered to be disconnected; reconnecting now")
await self.mqtt.connect()
+ await self.find_locks()
+
except Exception as e:
logger.exception(f"Error in CCUJack cron task: {e}")
+ finally:
+ await asyncio.sleep(15 * 60) # 15 minutes
+
async def query_param_value(self, address: str) -> CCUValue:
if address in self.param_values:
diff --git a/api/src/dooris_api/mqtt_client.py b/api/src/dooris_api/mqtt_client.py
index 3df1f19..a090c5f 100644
--- a/api/src/dooris_api/mqtt_client.py
+++ b/api/src/dooris_api/mqtt_client.py
@@ -128,19 +128,21 @@ class AsyncMqttClient:
to_add = topics.difference(self.active_subscriptions)
if to_add:
- logger.info(f"mqtt client subscribing to topics {', '.join(to_add)}")
- self.fut_subscribe = asyncio.get_running_loop().create_future()
- self.client.subscribe([(i, qos) for i in to_add])
- await self.fut_subscribe
self.active_subscriptions.update(to_add)
+ if self.is_connected:
+ logger.info(f"mqtt client subscribing to topics {', '.join(to_add)}")
+ self.fut_subscribe = asyncio.get_running_loop().create_future()
+ self.client.subscribe([(i, qos) for i in to_add])
+ await self.fut_subscribe
to_remove = self.active_subscriptions.difference(topics)
if to_remove:
- logger.info(f"mqtt client unsubscribing from topics {','.join(to_remove)}")
- self.fut_unsubscribe = asyncio.get_running_loop().create_future()
- self.client.unsubscribe(list(to_remove))
- await self.fut_unsubscribe
self.active_subscriptions.difference_update(to_remove)
+ if self.is_connected:
+ logger.info(f"mqtt client unsubscribing from topics {','.join(to_remove)}")
+ self.fut_unsubscribe = asyncio.get_running_loop().create_future()
+ self.client.unsubscribe(list(to_remove))
+ await self.fut_unsubscribe
async def connect(self):
server_host, server_port = self.connection_string.rsplit(":", maxsplit=1)
@@ -157,13 +159,19 @@ class AsyncMqttClient:
# re-establish all supposed mqtt subscriptions
if len(self.active_subscriptions) > 0:
qos = 1
- await self.client.subscribe((i, qos) for i in self.active_subscriptions)
+ self.fut_subscribe = asyncio.get_running_loop().create_future()
+ self.client.subscribe([(i, qos) for i in self.active_subscriptions])
+ await self.fut_subscribe
async def disconnect(self):
+ if not self.is_connected:
+ return
+
logger.info("Disconnecting mqtt client from broker")
self.fut_disconnect = asyncio.get_running_loop().create_future()
self.client.disconnect()
await self.fut_disconnect
+ @property
def is_connected(self) -> bool:
return self.client.is_connected()
From 64ab73e9c30fce5c82c8599c407605fdad223ade Mon Sep 17 00:00:00 2001
From: lilly
Date: Sun, 31 May 2026 20:53:14 +0200
Subject: [PATCH 2/3] api: initialize ccujack asynchonously via immedietaly
running cron
---
api/src/dooris_api/ccujack.py | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/api/src/dooris_api/ccujack.py b/api/src/dooris_api/ccujack.py
index a6b0640..de08bbf 100644
--- a/api/src/dooris_api/ccujack.py
+++ b/api/src/dooris_api/ccujack.py
@@ -90,15 +90,12 @@ class CCUJackClient:
self.data_updated = asyncio.Event()
async def start(self):
- await self.mqtt.connect()
- await self.find_locks()
-
- self.task_cron= asyncio.get_running_loop().create_task(
- self.cron(), name="ccujack-cron"
- )
self.task_process_messages = asyncio.get_running_loop().create_task(
self.process_mqt_messages(), name="process-mqtt-messages"
)
+ self.task_cron= asyncio.get_running_loop().create_task(
+ self.cron(), name="ccujack-cron"
+ )
async def close_connections(self):
await asyncio.gather(self.mqtt.disconnect(), self.http.close())
From 279a45a9e8259b28c3fe6dff546ee613771426dc Mon Sep 17 00:00:00 2001
From: lilly
Date: Sun, 31 May 2026 20:53:14 +0200
Subject: [PATCH 3/3] api: don't print static tokens on startup (was only for
debugging)
---
api/src/dooris_api/__init__.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/api/src/dooris_api/__init__.py b/api/src/dooris_api/__init__.py
index cdf4d67..203d379 100644
--- a/api/src/dooris_api/__init__.py
+++ b/api/src/dooris_api/__init__.py
@@ -81,7 +81,6 @@ def main():
default=[i for i in os.environ.get("DOORIS_STATIC_API_TOKENS", "").split(",") if bool(i)],
)
args = argp.parse_args()
- print(args.static_api_tokens)
# setup logging
logging.basicConfig(