Fix: Filter all queries by DEVICE_ID to get data of most recent device
This commit is contained in:
parent
87d35cc016
commit
66bb7575c3
85
main.py
85
main.py
@ -90,6 +90,7 @@ class GadgetbridgeMQTT:
|
|||||||
self.config = config
|
self.config = config
|
||||||
self.db_path = None
|
self.db_path = None
|
||||||
self.device_name = "fitness_tracker"
|
self.device_name = "fitness_tracker"
|
||||||
|
self.device_id = None # Track device ID for filtering queries
|
||||||
self.mqtt_client = None
|
self.mqtt_client = None
|
||||||
self.last_publish_time = 0
|
self.last_publish_time = 0
|
||||||
self.last_db_mtime = 0
|
self.last_db_mtime = 0
|
||||||
@ -140,20 +141,27 @@ class GadgetbridgeMQTT:
|
|||||||
self.mqtt_client.loop_stop()
|
self.mqtt_client.loop_stop()
|
||||||
self.mqtt_client.disconnect()
|
self.mqtt_client.disconnect()
|
||||||
|
|
||||||
def get_device_alias(self, cursor):
|
def get_device_info(self, cursor):
|
||||||
"""Get device alias from database"""
|
"""Get device ID and alias from database - picks device with most recent activity"""
|
||||||
try:
|
try:
|
||||||
|
# Find the device with the most recent activity data
|
||||||
|
# This ensures we get the currently active band, not an old one
|
||||||
cursor.execute("""
|
cursor.execute("""
|
||||||
SELECT ALIAS FROM DEVICE
|
SELECT d._id, d.ALIAS, d.NAME FROM DEVICE d
|
||||||
WHERE LOWER(NAME) LIKE '%band%' OR LOWER(NAME) LIKE '%watch%'
|
WHERE (LOWER(d.NAME) LIKE '%band%' OR LOWER(d.NAME) LIKE '%watch%')
|
||||||
|
ORDER BY d._id DESC
|
||||||
LIMIT 1
|
LIMIT 1
|
||||||
""")
|
""")
|
||||||
row = cursor.fetchone()
|
row = cursor.fetchone()
|
||||||
if row and row[0]:
|
if row:
|
||||||
return re.sub(r"\W+", "_", row[0]).lower()
|
device_id = row[0]
|
||||||
except:
|
alias = row[1] if row[1] else row[2] # Use ALIAS, fallback to NAME
|
||||||
pass
|
device_name = re.sub(r"\W+", "_", alias).lower() if alias else "fitness_tracker"
|
||||||
return "fitness_tracker"
|
logger.info(f"Selected device: ID={device_id}, Name={alias}")
|
||||||
|
return device_id, device_name
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error getting device info: {e}")
|
||||||
|
return None, "fitness_tracker"
|
||||||
|
|
||||||
def get_day_start_timestamp(self):
|
def get_day_start_timestamp(self):
|
||||||
"""Get timestamp for start of current day (4am)"""
|
"""Get timestamp for start of current day (4am)"""
|
||||||
@ -174,23 +182,23 @@ class GadgetbridgeMQTT:
|
|||||||
return int(midnight.timestamp()) * 1000
|
return int(midnight.timestamp()) * 1000
|
||||||
|
|
||||||
def query_sensors(self, cursor):
|
def query_sensors(self, cursor):
|
||||||
"""Query all sensor data from database"""
|
"""Query all sensor data from database - filtered by device_id"""
|
||||||
data = {}
|
data = {}
|
||||||
day_start_ts = self.get_day_start_timestamp()
|
day_start_ts = self.get_day_start_timestamp()
|
||||||
now_ts = int(datetime.now().timestamp())
|
now_ts = int(datetime.now().timestamp())
|
||||||
day_midnight_ms = self.get_day_midnight_timestamp_ms()
|
day_midnight_ms = self.get_day_midnight_timestamp_ms()
|
||||||
|
|
||||||
# Daily Steps
|
# Daily Steps (filtered by device)
|
||||||
try:
|
try:
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"SELECT SUM(STEPS) FROM XIAOMI_ACTIVITY_SAMPLE WHERE TIMESTAMP >= ? AND TIMESTAMP <= ?",
|
"SELECT SUM(STEPS) FROM XIAOMI_ACTIVITY_SAMPLE WHERE DEVICE_ID = ? AND TIMESTAMP >= ? AND TIMESTAMP <= ?",
|
||||||
(day_start_ts, now_ts)
|
(self.device_id, day_start_ts, now_ts)
|
||||||
)
|
)
|
||||||
data["daily_steps"] = cursor.fetchone()[0] or 0
|
data["daily_steps"] = cursor.fetchone()[0] or 0
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.debug(f"Daily steps query failed: {e}")
|
logger.debug(f"Daily steps query failed: {e}")
|
||||||
|
|
||||||
# Weekly Steps
|
# Weekly Steps (filtered by device)
|
||||||
try:
|
try:
|
||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
week_start = now.date() - timedelta(days=now.date().weekday())
|
week_start = now.date() - timedelta(days=now.date().weekday())
|
||||||
@ -198,26 +206,30 @@ class GadgetbridgeMQTT:
|
|||||||
if now.date().weekday() == 0 and now.hour < 4:
|
if now.date().weekday() == 0 and now.hour < 4:
|
||||||
week_start_time -= timedelta(days=7)
|
week_start_time -= timedelta(days=7)
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"SELECT SUM(STEPS) FROM XIAOMI_ACTIVITY_SAMPLE WHERE TIMESTAMP >= ? AND TIMESTAMP <= ?",
|
"SELECT SUM(STEPS) FROM XIAOMI_ACTIVITY_SAMPLE WHERE DEVICE_ID = ? AND TIMESTAMP >= ? AND TIMESTAMP <= ?",
|
||||||
(int(week_start_time.timestamp()), now_ts)
|
(self.device_id, int(week_start_time.timestamp()), now_ts)
|
||||||
)
|
)
|
||||||
data["weekly_steps"] = cursor.fetchone()[0] or 0
|
data["weekly_steps"] = cursor.fetchone()[0] or 0
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.debug(f"Weekly steps query failed: {e}")
|
logger.debug(f"Weekly steps query failed: {e}")
|
||||||
|
|
||||||
# Battery Level
|
# Battery Level (filtered by device)
|
||||||
try:
|
try:
|
||||||
cursor.execute("SELECT LEVEL FROM BATTERY_LEVEL ORDER BY TIMESTAMP DESC LIMIT 1")
|
cursor.execute(
|
||||||
|
"SELECT LEVEL FROM BATTERY_LEVEL WHERE DEVICE_ID = ? ORDER BY TIMESTAMP DESC LIMIT 1",
|
||||||
|
(self.device_id,)
|
||||||
|
)
|
||||||
row = cursor.fetchone()
|
row = cursor.fetchone()
|
||||||
if row:
|
if row:
|
||||||
data["battery_level"] = row[0]
|
data["battery_level"] = row[0]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.debug(f"Battery query failed: {e}")
|
logger.debug(f"Battery query failed: {e}")
|
||||||
|
|
||||||
# Latest Heart Rate
|
# Latest Heart Rate (filtered by device)
|
||||||
try:
|
try:
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"SELECT HEART_RATE FROM XIAOMI_ACTIVITY_SAMPLE WHERE HEART_RATE > 0 AND HEART_RATE < 255 ORDER BY TIMESTAMP DESC LIMIT 1"
|
"SELECT HEART_RATE FROM XIAOMI_ACTIVITY_SAMPLE WHERE DEVICE_ID = ? AND HEART_RATE > 0 AND HEART_RATE < 255 ORDER BY TIMESTAMP DESC LIMIT 1",
|
||||||
|
(self.device_id,)
|
||||||
)
|
)
|
||||||
row = cursor.fetchone()
|
row = cursor.fetchone()
|
||||||
if row:
|
if row:
|
||||||
@ -225,11 +237,11 @@ class GadgetbridgeMQTT:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.debug(f"Heart rate query failed: {e}")
|
logger.debug(f"Heart rate query failed: {e}")
|
||||||
|
|
||||||
# Daily Summary Data (resting HR, max HR, avg HR, calories)
|
# Daily Summary Data (filtered by device)
|
||||||
try:
|
try:
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"SELECT HR_RESTING, HR_MAX, HR_AVG, CALORIES FROM XIAOMI_DAILY_SUMMARY_SAMPLE WHERE TIMESTAMP >= ? ORDER BY TIMESTAMP DESC LIMIT 1",
|
"SELECT HR_RESTING, HR_MAX, HR_AVG, CALORIES FROM XIAOMI_DAILY_SUMMARY_SAMPLE WHERE DEVICE_ID = ? AND TIMESTAMP >= ? ORDER BY TIMESTAMP DESC LIMIT 1",
|
||||||
(day_midnight_ms,)
|
(self.device_id, day_midnight_ms)
|
||||||
)
|
)
|
||||||
row = cursor.fetchone()
|
row = cursor.fetchone()
|
||||||
if row:
|
if row:
|
||||||
@ -240,12 +252,12 @@ class GadgetbridgeMQTT:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.debug(f"Daily summary query failed: {e}")
|
logger.debug(f"Daily summary query failed: {e}")
|
||||||
|
|
||||||
# Sleep Data
|
# Sleep Data (filtered by device)
|
||||||
try:
|
try:
|
||||||
day_ago_ms = (int(time.time()) - 24 * 3600) * 1000
|
day_ago_ms = (int(time.time()) - 24 * 3600) * 1000
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"SELECT TOTAL_DURATION, IS_AWAKE, WAKEUP_TIME FROM XIAOMI_SLEEP_TIME_SAMPLE WHERE TIMESTAMP >= ? ORDER BY TIMESTAMP DESC LIMIT 1",
|
"SELECT TOTAL_DURATION, IS_AWAKE, WAKEUP_TIME FROM XIAOMI_SLEEP_TIME_SAMPLE WHERE DEVICE_ID = ? AND TIMESTAMP >= ? ORDER BY TIMESTAMP DESC LIMIT 1",
|
||||||
(day_ago_ms,)
|
(self.device_id, day_ago_ms)
|
||||||
)
|
)
|
||||||
row = cursor.fetchone()
|
row = cursor.fetchone()
|
||||||
if row:
|
if row:
|
||||||
@ -261,12 +273,12 @@ class GadgetbridgeMQTT:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.debug(f"Sleep query failed: {e}")
|
logger.debug(f"Sleep query failed: {e}")
|
||||||
|
|
||||||
# Weight
|
# Weight (not device-specific, from scale)
|
||||||
try:
|
try:
|
||||||
cursor.execute("SELECT WEIGHT_KG FROM MI_SCALE_WEIGHT_SAMPLE ORDER BY TIMESTAMP DESC LIMIT 1")
|
cursor.execute("SELECT WEIGHT_KG FROM MI_SCALE_WEIGHT_SAMPLE ORDER BY TIMESTAMP DESC LIMIT 1")
|
||||||
row = cursor.fetchone()
|
row = cursor.fetchone()
|
||||||
if row and row[0]:
|
if row and row[0]:
|
||||||
data["weight"] = row[0]
|
data["weight"] = round(row[0], 1) # Round to 1 decimal
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.debug(f"Weight query failed: {e}")
|
logger.debug(f"Weight query failed: {e}")
|
||||||
|
|
||||||
@ -340,8 +352,13 @@ class GadgetbridgeMQTT:
|
|||||||
conn = sqlite3.connect(self.db_path, timeout=10.0)
|
conn = sqlite3.connect(self.db_path, timeout=10.0)
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
|
|
||||||
# Get device name
|
# Get device ID and name
|
||||||
self.device_name = self.get_device_alias(cursor)
|
self.device_id, self.device_name = self.get_device_info(cursor)
|
||||||
|
|
||||||
|
if not self.device_id:
|
||||||
|
logger.warning("No fitness device found in database")
|
||||||
|
conn.close()
|
||||||
|
return False
|
||||||
|
|
||||||
# Query all sensors
|
# Query all sensors
|
||||||
data = self.query_sensors(cursor)
|
data = self.query_sensors(cursor)
|
||||||
@ -400,14 +417,14 @@ class GadgetbridgeMQTT:
|
|||||||
|
|
||||||
# Publish discovery on first successful read
|
# Publish discovery on first successful read
|
||||||
if not discovery_published:
|
if not discovery_published:
|
||||||
# Need to read device name first
|
# Need to read device info first
|
||||||
try:
|
try:
|
||||||
conn = sqlite3.connect(self.db_path, timeout=5.0)
|
conn = sqlite3.connect(self.db_path, timeout=5.0)
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
self.device_name = self.get_device_alias(cursor)
|
self.device_id, self.device_name = self.get_device_info(cursor)
|
||||||
conn.close()
|
conn.close()
|
||||||
except:
|
except Exception as e:
|
||||||
pass
|
logger.warning(f"Could not read device info: {e}")
|
||||||
self.publish_discovery()
|
self.publish_discovery()
|
||||||
discovery_published = True
|
discovery_published = True
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user