From 66bb7575c3f73bfc112db90cdaf5f8c2c0b0544e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20Gro=C3=9Fklo=C3=9F?= Date: Sun, 7 Dec 2025 16:20:51 +0100 Subject: [PATCH] Fix: Filter all queries by DEVICE_ID to get data of most recent device --- main.py | 85 ++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 51 insertions(+), 34 deletions(-) diff --git a/main.py b/main.py index 605e8c0..1bbe883 100644 --- a/main.py +++ b/main.py @@ -90,6 +90,7 @@ class GadgetbridgeMQTT: self.config = config self.db_path = None self.device_name = "fitness_tracker" + self.device_id = None # Track device ID for filtering queries self.mqtt_client = None self.last_publish_time = 0 self.last_db_mtime = 0 @@ -140,20 +141,27 @@ class GadgetbridgeMQTT: self.mqtt_client.loop_stop() self.mqtt_client.disconnect() - def get_device_alias(self, cursor): - """Get device alias from database""" + def get_device_info(self, cursor): + """Get device ID and alias from database - picks device with most recent activity""" try: + # Find the device with the most recent activity data + # This ensures we get the currently active band, not an old one cursor.execute(""" - SELECT ALIAS FROM DEVICE - WHERE LOWER(NAME) LIKE '%band%' OR LOWER(NAME) LIKE '%watch%' + SELECT d._id, d.ALIAS, d.NAME FROM DEVICE d + WHERE (LOWER(d.NAME) LIKE '%band%' OR LOWER(d.NAME) LIKE '%watch%') + ORDER BY d._id DESC LIMIT 1 """) row = cursor.fetchone() - if row and row[0]: - return re.sub(r"\W+", "_", row[0]).lower() - except: - pass - return "fitness_tracker" + if row: + device_id = row[0] + alias = row[1] if row[1] else row[2] # Use ALIAS, fallback to NAME + device_name = re.sub(r"\W+", "_", alias).lower() if alias else "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): """Get timestamp for start of current day (4am)""" @@ -174,23 +182,23 @@ class GadgetbridgeMQTT: return int(midnight.timestamp()) * 1000 def query_sensors(self, cursor): - """Query all sensor data from database""" + """Query all sensor data from database - filtered by device_id""" data = {} day_start_ts = self.get_day_start_timestamp() now_ts = int(datetime.now().timestamp()) day_midnight_ms = self.get_day_midnight_timestamp_ms() - # Daily Steps + # Daily Steps (filtered by device) try: cursor.execute( - "SELECT SUM(STEPS) FROM XIAOMI_ACTIVITY_SAMPLE WHERE TIMESTAMP >= ? AND TIMESTAMP <= ?", - (day_start_ts, now_ts) + "SELECT SUM(STEPS) FROM XIAOMI_ACTIVITY_SAMPLE WHERE DEVICE_ID = ? AND TIMESTAMP >= ? AND TIMESTAMP <= ?", + (self.device_id, day_start_ts, now_ts) ) data["daily_steps"] = cursor.fetchone()[0] or 0 except Exception as e: logger.debug(f"Daily steps query failed: {e}") - # Weekly Steps + # Weekly Steps (filtered by device) try: now = datetime.now() week_start = now.date() - timedelta(days=now.date().weekday()) @@ -198,26 +206,30 @@ class GadgetbridgeMQTT: if now.date().weekday() == 0 and now.hour < 4: week_start_time -= timedelta(days=7) cursor.execute( - "SELECT SUM(STEPS) FROM XIAOMI_ACTIVITY_SAMPLE WHERE TIMESTAMP >= ? AND TIMESTAMP <= ?", - (int(week_start_time.timestamp()), now_ts) + "SELECT SUM(STEPS) FROM XIAOMI_ACTIVITY_SAMPLE WHERE DEVICE_ID = ? AND TIMESTAMP >= ? AND TIMESTAMP <= ?", + (self.device_id, int(week_start_time.timestamp()), now_ts) ) data["weekly_steps"] = cursor.fetchone()[0] or 0 except Exception as e: logger.debug(f"Weekly steps query failed: {e}") - # Battery Level + # Battery Level (filtered by device) 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() if row: data["battery_level"] = row[0] except Exception as e: logger.debug(f"Battery query failed: {e}") - # Latest Heart Rate + # Latest Heart Rate (filtered by device) try: 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() if row: @@ -225,11 +237,11 @@ class GadgetbridgeMQTT: except Exception as 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: cursor.execute( - "SELECT HR_RESTING, HR_MAX, HR_AVG, CALORIES FROM XIAOMI_DAILY_SUMMARY_SAMPLE WHERE TIMESTAMP >= ? ORDER BY TIMESTAMP DESC LIMIT 1", - (day_midnight_ms,) + "SELECT HR_RESTING, HR_MAX, HR_AVG, CALORIES FROM XIAOMI_DAILY_SUMMARY_SAMPLE WHERE DEVICE_ID = ? AND TIMESTAMP >= ? ORDER BY TIMESTAMP DESC LIMIT 1", + (self.device_id, day_midnight_ms) ) row = cursor.fetchone() if row: @@ -240,12 +252,12 @@ class GadgetbridgeMQTT: except Exception as e: logger.debug(f"Daily summary query failed: {e}") - # Sleep Data + # Sleep Data (filtered by device) try: day_ago_ms = (int(time.time()) - 24 * 3600) * 1000 cursor.execute( - "SELECT TOTAL_DURATION, IS_AWAKE, WAKEUP_TIME FROM XIAOMI_SLEEP_TIME_SAMPLE WHERE TIMESTAMP >= ? ORDER BY TIMESTAMP DESC LIMIT 1", - (day_ago_ms,) + "SELECT TOTAL_DURATION, IS_AWAKE, WAKEUP_TIME FROM XIAOMI_SLEEP_TIME_SAMPLE WHERE DEVICE_ID = ? AND TIMESTAMP >= ? ORDER BY TIMESTAMP DESC LIMIT 1", + (self.device_id, day_ago_ms) ) row = cursor.fetchone() if row: @@ -261,12 +273,12 @@ class GadgetbridgeMQTT: except Exception as e: logger.debug(f"Sleep query failed: {e}") - # Weight + # Weight (not device-specific, from scale) try: cursor.execute("SELECT WEIGHT_KG FROM MI_SCALE_WEIGHT_SAMPLE ORDER BY TIMESTAMP DESC LIMIT 1") row = cursor.fetchone() if row and row[0]: - data["weight"] = row[0] + data["weight"] = round(row[0], 1) # Round to 1 decimal except Exception as e: logger.debug(f"Weight query failed: {e}") @@ -340,8 +352,13 @@ class GadgetbridgeMQTT: conn = sqlite3.connect(self.db_path, timeout=10.0) cursor = conn.cursor() - # Get device name - self.device_name = self.get_device_alias(cursor) + # Get device ID and name + 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 data = self.query_sensors(cursor) @@ -400,14 +417,14 @@ class GadgetbridgeMQTT: # Publish discovery on first successful read if not discovery_published: - # Need to read device name first + # Need to read device info first try: conn = sqlite3.connect(self.db_path, timeout=5.0) cursor = conn.cursor() - self.device_name = self.get_device_alias(cursor) + self.device_id, self.device_name = self.get_device_info(cursor) conn.close() - except: - pass + except Exception as e: + logger.warning(f"Could not read device info: {e}") self.publish_discovery() discovery_published = True