Track sleep state and adjust data freshness checks for improved recovery logic
This commit is contained in:
parent
8514180505
commit
e11b4564f0
28
main.py
28
main.py
@ -155,6 +155,7 @@ class GadgetbridgeMQTT:
|
|||||||
|
|
||||||
# New: Track data freshness for watchdog
|
# New: Track data freshness for watchdog
|
||||||
self.last_data_timestamp = 0
|
self.last_data_timestamp = 0
|
||||||
|
self.is_sleeping = False # Track sleep state to skip stale checks during sleep
|
||||||
|
|
||||||
# Register signal handlers for graceful shutdown
|
# Register signal handlers for graceful shutdown
|
||||||
signal.signal(signal.SIGTERM, self._signal_handler)
|
signal.signal(signal.SIGTERM, self._signal_handler)
|
||||||
@ -404,7 +405,10 @@ class GadgetbridgeMQTT:
|
|||||||
row = cursor.fetchone()
|
row = cursor.fetchone()
|
||||||
if row:
|
if row:
|
||||||
data["heart_rate"] = row[0]
|
data["heart_rate"] = row[0]
|
||||||
self.last_data_timestamp = row[1] # <--- NEW: Update timestamp
|
# Only update timestamp if DB has newer data than our last recovery
|
||||||
|
# This prevents the recovery loop when DB timestamp is stale
|
||||||
|
if row[1] > self.last_data_timestamp:
|
||||||
|
self.last_data_timestamp = row[1]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.debug(f"Heart rate query failed: {e}")
|
logger.debug(f"Heart rate query failed: {e}")
|
||||||
|
|
||||||
@ -497,6 +501,9 @@ class GadgetbridgeMQTT:
|
|||||||
)
|
)
|
||||||
data["is_awake"] = is_awake
|
data["is_awake"] = is_awake
|
||||||
|
|
||||||
|
# Update sleep state for watchdog (use longer stale threshold during sleep)
|
||||||
|
self.is_sleeping = not is_awake
|
||||||
|
|
||||||
stage_names = {
|
stage_names = {
|
||||||
0: "not_sleep",
|
0: "not_sleep",
|
||||||
1: "unknown",
|
1: "unknown",
|
||||||
@ -518,10 +525,12 @@ class GadgetbridgeMQTT:
|
|||||||
data["sleep_stage"] = "not_sleep" if is_awake else "unknown"
|
data["sleep_stage"] = "not_sleep" if is_awake else "unknown"
|
||||||
data["sleep_stage_code"] = 0
|
data["sleep_stage_code"] = 0
|
||||||
else:
|
else:
|
||||||
|
# No sleep data - user is awake
|
||||||
data["is_awake"] = True
|
data["is_awake"] = True
|
||||||
data["in_sleep_session"] = False
|
data["in_sleep_session"] = False
|
||||||
data["sleep_stage"] = "not_sleep"
|
data["sleep_stage"] = "not_sleep"
|
||||||
data["sleep_stage_code"] = 0
|
data["sleep_stage_code"] = 0
|
||||||
|
self.is_sleeping = False
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.debug(f"Sleep query failed: {e}")
|
logger.debug(f"Sleep query failed: {e}")
|
||||||
@ -598,9 +607,14 @@ class GadgetbridgeMQTT:
|
|||||||
# Use retain=True so HA gets values on restart
|
# Use retain=True so HA gets values on restart
|
||||||
self.mqtt_client.publish(topic, str(value), qos=1, retain=True)
|
self.mqtt_client.publish(topic, str(value), qos=1, retain=True)
|
||||||
|
|
||||||
|
# Log key metrics including sleep status
|
||||||
|
sleep_info = f"sleep={data.get('sleep_duration', 0)}h" if 'sleep_duration' in data else "sleep=N/A"
|
||||||
|
awake_info = f"awake={data.get('is_awake', 'N/A')}"
|
||||||
|
|
||||||
logger.info(f"Published: steps={data.get('daily_steps', 'N/A')}, "
|
logger.info(f"Published: steps={data.get('daily_steps', 'N/A')}, "
|
||||||
f"hr={data.get('heart_rate', 'N/A')}, "
|
f"hr={data.get('heart_rate', 'N/A')}, "
|
||||||
f"battery={data.get('battery_level', 'N/A')}%")
|
f"battery={data.get('battery_level', 'N/A')}%, "
|
||||||
|
f"{sleep_info}, {awake_info}")
|
||||||
|
|
||||||
def process_database(self):
|
def process_database(self):
|
||||||
"""Read database and publish data"""
|
"""Read database and publish data"""
|
||||||
@ -636,15 +650,21 @@ class GadgetbridgeMQTT:
|
|||||||
def check_and_recover_connection(self):
|
def check_and_recover_connection(self):
|
||||||
"""
|
"""
|
||||||
WATCHDOG: Checks if data is stale (>20 mins) and forces Bluetooth restart if so.
|
WATCHDOG: Checks if data is stale (>20 mins) and forces Bluetooth restart if so.
|
||||||
|
|
||||||
|
During sleep, the band syncs data less frequently, so we use a longer
|
||||||
|
threshold (60 mins) to avoid false recovery triggers.
|
||||||
"""
|
"""
|
||||||
if self.last_data_timestamp == 0:
|
if self.last_data_timestamp == 0:
|
||||||
return # No data seen yet, skip check
|
return # No data seen yet, skip check
|
||||||
|
|
||||||
|
# Use longer threshold during sleep (band syncs less frequently)
|
||||||
|
threshold = STALE_THRESHOLD_SECONDS * 3 if self.is_sleeping else STALE_THRESHOLD_SECONDS
|
||||||
|
|
||||||
current_ts = int(time.time())
|
current_ts = int(time.time())
|
||||||
time_diff = current_ts - self.last_data_timestamp
|
time_diff = current_ts - self.last_data_timestamp
|
||||||
|
|
||||||
if time_diff > STALE_THRESHOLD_SECONDS:
|
if time_diff > threshold:
|
||||||
logger.warning(f"Data stale ({time_diff}s > {STALE_THRESHOLD_SECONDS}s). Triggering recovery...")
|
logger.warning(f"Data stale ({time_diff}s > {threshold}s). Triggering recovery...")
|
||||||
if self.device_mac:
|
if self.device_mac:
|
||||||
# 1. Disconnect and wait
|
# 1. Disconnect and wait
|
||||||
trigger_bluetooth_reconnect(self.device_mac)
|
trigger_bluetooth_reconnect(self.device_mac)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user