From 591101c72c15018d04a2c98b3f88ac412e11c496 Mon Sep 17 00:00:00 2001 From: DigiH Date: Fri, 12 Jan 2024 21:48:55 +0100 Subject: [PATCH] [DISC] Timeout for discovered device trackers --- TheengsGateway/ble_gateway.py | 29 +++++++++++++++++++++++++++++ TheengsGateway/config.py | 7 +++++++ TheengsGateway/discovery.py | 6 ++++++ 3 files changed, 42 insertions(+) diff --git a/TheengsGateway/ble_gateway.py b/TheengsGateway/ble_gateway.py index bccaf612..e7e2907a 100644 --- a/TheengsGateway/ble_gateway.py +++ b/TheengsGateway/ble_gateway.py @@ -117,6 +117,7 @@ def __init__( self.stopped = False self.clock_updates: dict[str, float] = {} self.published_messages = 0 + self.discovered_trackers: dict[str, int] = {} def connect_mqtt(self) -> None: """Connect to MQTT broker.""" @@ -326,6 +327,27 @@ async def update_clock_times(self) -> None: ).strftime("%Y-%m-%d %H:%M:%S"), ) + def check_tracker_timeout(self) -> None: + """Check if tracker timeout is over timeout limit.""" + for address, timestamp in self.discovered_trackers.copy().items(): + if ( + round(time()) - timestamp >= self.configuration["tracker_timeout"] + and timestamp != 0 + ): + # If the timestamp is later than current time minus tracker_timeout + # Publish offline message + message = json.dumps( + {"id": address, "state": "offline", "unlocked": False} + ) + self.publish( + message, + self.configuration["publish_topic"] + + "/" + + address.replace(":", ""), + ) + + self.discovered_trackers[address] = 0 + async def ble_scan_loop(self) -> None: """Scan for BLE devices.""" scanner_kwargs = {"scanning_mode": self.configuration["scanning_mode"]} @@ -375,6 +397,8 @@ async def ble_scan_loop(self) -> None: self.configuration["ble_time_between_scans"], ) + # Check tracker timeouts + self.check_tracker_timeout() # Update time for all clocks once a day await self.update_clock_times() else: @@ -513,6 +537,11 @@ def publish_json( decoded: bool, # noqa: FBT001 ) -> None: """Publish JSON data to MQTT.""" + # Update tracker last received time + if data_json["id"] in self.discovered_trackers: + self.discovered_trackers[data_json["id"]] = round(time()) + logger.debug("Discovered Trackers @publish_json: %s", self.discovered_trackers) + # Remove "track" if PUBLISH_ADVDATA is 0 if not self.configuration["publish_advdata"] and "track" in data_json: data_json.pop("track", None) diff --git a/TheengsGateway/config.py b/TheengsGateway/config.py index 3b2395c6..d3f6c1ef 100644 --- a/TheengsGateway/config.py +++ b/TheengsGateway/config.py @@ -45,6 +45,7 @@ "enable_tls": 0, "enable_websocket": 0, "identities": {}, + "tracker_timeout": 120, "ble": 1, } @@ -215,6 +216,12 @@ def parse_args() -> argparse.Namespace: type=int, help="Enable (1) or disable (0) TLS (default: 0)", ) + parser.add_argument( + "-to", + "--tracker_timeout", + type=int, + help="Tracker timeout duration (seconds)", + ) parser.add_argument( "-ts", "--time_sync", diff --git a/TheengsGateway/discovery.py b/TheengsGateway/discovery.py index cc888b45..19c76955 100644 --- a/TheengsGateway/discovery.py +++ b/TheengsGateway/discovery.py @@ -23,6 +23,7 @@ import json import re +from time import time from TheengsDecoder import getProperties @@ -257,6 +258,11 @@ def publish_device_tracker( def copy_pub_device(self, device: dict) -> dict: """Copy pub_device and remove "track" if publish_advdata is false.""" + # Update tracker last received time + if "track" in device: + self.discovered_trackers[device["id"]] = round(time()) + logger.debug("Discovered Trackers: %s", self.discovered_trackers) + pub_device_copy = device.copy() # Remove "track" if PUBLISH_ADVDATA is 0 if not self.configuration["publish_advdata"] and "track" in pub_device_copy: