From c9400c93d6495b3c0fab99f0295c070c9fc8fbab Mon Sep 17 00:00:00 2001 From: DigiH Date: Fri, 12 Jan 2024 21:48:55 +0100 Subject: [PATCH 1/2] [DISC] Timeout for discovered device trackers --- TheengsGateway/ble_gateway.py | 26 ++++++++++++++++++++++++++ TheengsGateway/config.py | 7 +++++++ TheengsGateway/discovery.py | 6 ++++++ 3 files changed, 39 insertions(+) diff --git a/TheengsGateway/ble_gateway.py b/TheengsGateway/ble_gateway.py index bccaf612..77a90c1b 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"]} @@ -472,6 +494,10 @@ def decode_advertisement( ) # Publish sensor data to Home Assistant MQTT discovery else: self.publish_json(decoded_json, decoded=True) + + # Check tracker timeouts + self.check_tracker_timeout() + elif self.configuration["publish_all"]: add_manufacturer(data_json) self.publish_json(data_json, decoded=False) 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: From 060c26ae4de6cb88c2173662515c3cd7482ae506 Mon Sep 17 00:00:00 2001 From: DigiH Date: Sun, 14 Jan 2024 01:53:47 +0100 Subject: [PATCH 2/2] Docs update --- docs/use/use.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/use/use.md b/docs/use/use.md index c309be77..4e153353 100644 --- a/docs/use/use.md +++ b/docs/use/use.md @@ -113,6 +113,9 @@ options: Enable (1) or disable (0) TLS (default: 0) -ts TIME_SYNC [TIME_SYNC ...], --time_sync TIME_SYNC [TIME_SYNC ...] Addresses of Bluetooth devices to synchronize the time + -to TIME_UNTIL, --tracker_timeout TIME_UNTIL + Seconds after which a discovered device tracker not being received is published as offline/away + (default: 120) -u USER, --user USER MQTT username -ws ENABLE_WEBSOCKET, --enable_websocket ENABLE_WEBSOCKET Enable (1) or disable (0) WebSocket (default: 0) @@ -199,6 +202,11 @@ The `IBEACON` and random MAC devices (`APPLE`*, `MS-CDP` and `GAEN`) are not dis Apple Watch, iPhone and iPad will be discovered if they are defined with their Identity MAC Address and IRK ::: +## Discovered device tracker timeout +:::tip NOTE +`-to TIME_UNTIL, --tracker_timeout` needs to be at least longer than TIME_BETWEEN + SCAN_DURATION to avoid any unwanted temporary offline status messages for discovered trackers. +::: + ## Passive scanning Passive scanning (`-s passive` or `--scanning_mode passive`) only works on Windows or Linux kernel >= 5.10 and BlueZ >= 5.56 with experimental features enabled.