Add method to get midnight timestamp and update queries to use it

This commit is contained in:
Oliver Großkloß 2025-12-07 12:57:18 +01:00
parent e96626b641
commit 282e30f008

62
main.py
View File

@ -70,6 +70,21 @@ class GadgetbridgeMQTTPublisher:
return int(day_start_time.timestamp())
def get_day_midnight_timestamp_ms(self) -> int:
"""Get the timestamp for midnight of the current day in milliseconds.
Used for XIAOMI_DAILY_SUMMARY_SAMPLE which stores data at midnight."""
now = datetime.now()
today = now.date()
# Daily summary is stored at midnight
day_midnight = datetime.combine(today, datetime.min.time())
# If current time is before 4am, use yesterday's midnight
if now.hour < 4:
day_midnight -= timedelta(days=1)
return int(day_midnight.timestamp()) * 1000
def initialize_sensors(self):
"""Initialize sensor definitions after device_name is available"""
self.sensors = [
@ -304,47 +319,47 @@ class GadgetbridgeMQTTPublisher:
def query_latest_heart_rate(self, cursor) -> Any:
cursor.execute(
"SELECT HEART_RATE FROM XIAOMI_ACTIVITY_SAMPLE ORDER BY TIMESTAMP DESC LIMIT 1"
"SELECT HEART_RATE FROM XIAOMI_ACTIVITY_SAMPLE WHERE HEART_RATE > 0 AND HEART_RATE < 255 ORDER BY TIMESTAMP DESC LIMIT 1"
)
row = cursor.fetchone()
return row[0] if row else None
def query_hr_resting(self, cursor) -> Any:
day_start_ts = self.get_day_start_timestamp()
day_midnight_ts_ms = self.get_day_midnight_timestamp_ms()
cursor.execute(
"SELECT HR_RESTING FROM XIAOMI_DAILY_SUMMARY_SAMPLE WHERE TIMESTAMP >= ? ORDER BY TIMESTAMP DESC LIMIT 1",
(day_start_ts,)
(day_midnight_ts_ms,)
)
row = cursor.fetchone()
return row[0] if row else None
def query_hr_max(self, cursor) -> Any:
day_start_ts = self.get_day_start_timestamp()
day_midnight_ts_ms = self.get_day_midnight_timestamp_ms()
cursor.execute(
"SELECT HR_MAX FROM XIAOMI_DAILY_SUMMARY_SAMPLE WHERE TIMESTAMP >= ? ORDER BY TIMESTAMP DESC LIMIT 1",
(day_start_ts,)
(day_midnight_ts_ms,)
)
row = cursor.fetchone()
return row[0] if row else None
def query_hr_avg(self, cursor) -> Any:
day_start_ts = self.get_day_start_timestamp()
day_midnight_ts_ms = self.get_day_midnight_timestamp_ms()
cursor.execute(
"SELECT HR_AVG FROM XIAOMI_DAILY_SUMMARY_SAMPLE WHERE TIMESTAMP >= ? ORDER BY TIMESTAMP DESC LIMIT 1",
(day_start_ts,)
(day_midnight_ts_ms,)
)
row = cursor.fetchone()
return row[0] if row else None
def query_calories(self, cursor) -> Any:
day_start_ts = self.get_day_start_timestamp()
day_midnight_ts_ms = self.get_day_midnight_timestamp_ms()
cursor.execute(
"SELECT CALORIES FROM XIAOMI_DAILY_SUMMARY_SAMPLE WHERE TIMESTAMP >= ? ORDER BY TIMESTAMP DESC LIMIT 1",
(day_start_ts,)
(day_midnight_ts_ms,)
)
row = cursor.fetchone()
return row[0] if row else None
@ -355,23 +370,34 @@ class GadgetbridgeMQTTPublisher:
# 1. No data at all -> Assume Awake
if not row:
return True
last_ts_epoch = row[0]
last_ts_epoch = row[0] // 1000 # Convert from milliseconds to seconds
is_awake_val = row[1] # This can be 1, 0, or None (NULL)
# 2. Timeout Safety: If last sleep data is older than 4 hours, force Awake
# This handles "Band Removed" or "Sync Failed" scenarios where the
# user has been up for hours but no new "awake" row was inserted.
import time
if (int(time.time()) - last_ts_epoch) > (4 * 3600):
wakeup_time = row[2] # Wakeup time in milliseconds
# 2. Check if WAKEUP_TIME is in the past (user has woken up)
current_time_ms = int(time.time()) * 1000
if wakeup_time and wakeup_time <= current_time_ms:
return True
# 3. Explicit Status Check
# 3. Timeout Safety: If last sleep data is older than 12 hours, force Awake
# This handles "Band Removed" or "Sync Failed" scenarios
if (int(time.time()) - last_ts_epoch) > (12 * 3600):
return True
# 4. Explicit Status Check
if is_awake_val == 1:
return True
# If is_awake_val is 0 or None, the user is likely asleep (TODO: verify None)
# If is_awake_val is 0 or None, the user is likely asleep
return False
def query_total_sleep_duration(self, cursor) -> Any:
# Get sleep from the last 24 hours
day_ago_ts = (int(time.time()) - 24 * 3600) * 1000 # 24 hours ago in milliseconds
cursor.execute(
"SELECT TOTAL_DURATION FROM XIAOMI_SLEEP_TIME_SAMPLE ORDER BY TIMESTAMP DESC LIMIT 1"
"SELECT TOTAL_DURATION FROM XIAOMI_SLEEP_TIME_SAMPLE WHERE TIMESTAMP >= ? ORDER BY TIMESTAMP DESC LIMIT 1",
(day_ago_ts,)
)
row = cursor.fetchone()
# Convert minutes to hours, round to 2 decimals