Adjust daily steps query to start at 4am
This commit is contained in:
parent
43930562cb
commit
4db6a97733
100
main.py
100
main.py
@ -56,6 +56,20 @@ class GadgetbridgeMQTTPublisher:
|
|||||||
"password": os.getenv("MQTT_PASSWORD", ""),
|
"password": os.getenv("MQTT_PASSWORD", ""),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def get_day_start_timestamp(self) -> int:
|
||||||
|
"""Get the timestamp for the start of the current day (4am)"""
|
||||||
|
now = datetime.now()
|
||||||
|
today = now.date()
|
||||||
|
|
||||||
|
# Day starts at 4am
|
||||||
|
day_start_time = datetime.combine(today, datetime.min.time()).replace(hour=4)
|
||||||
|
|
||||||
|
# If current time is before 4am, we're still in "yesterday's" day
|
||||||
|
if now.hour < 4:
|
||||||
|
day_start_time -= timedelta(days=1)
|
||||||
|
|
||||||
|
return int(day_start_time.timestamp())
|
||||||
|
|
||||||
def initialize_sensors(self):
|
def initialize_sensors(self):
|
||||||
"""Initialize sensor definitions after device_name is available"""
|
"""Initialize sensor definitions after device_name is available"""
|
||||||
self.sensors = [
|
self.sensors = [
|
||||||
@ -166,6 +180,14 @@ class GadgetbridgeMQTTPublisher:
|
|||||||
"state_class": "measurement",
|
"state_class": "measurement",
|
||||||
"query": self.query_total_sleep_duration,
|
"query": self.query_total_sleep_duration,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Server Time",
|
||||||
|
"unique_id": "server_time",
|
||||||
|
"state_topic": f"gadgetbridge/{self.device_name}/server_time",
|
||||||
|
"icon": "mdi:clock-outline",
|
||||||
|
"device_class": "timestamp",
|
||||||
|
"query": self.query_server_time,
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
async def publish_home_assistant_discovery(
|
async def publish_home_assistant_discovery(
|
||||||
@ -211,36 +233,58 @@ class GadgetbridgeMQTTPublisher:
|
|||||||
)
|
)
|
||||||
|
|
||||||
def query_daily_steps(self, cursor) -> Any:
|
def query_daily_steps(self, cursor) -> Any:
|
||||||
today = datetime.now().date()
|
day_start_ts = self.get_day_start_timestamp()
|
||||||
today_start = int(datetime.combine(today, datetime.min.time()).timestamp())
|
now_ts = int(datetime.now().timestamp())
|
||||||
today_end = int(datetime.combine(today, datetime.max.time()).timestamp())
|
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"SELECT SUM(STEPS) FROM XIAOMI_ACTIVITY_SAMPLE WHERE TIMESTAMP >= ? AND TIMESTAMP <= ?",
|
"SELECT SUM(STEPS) FROM XIAOMI_ACTIVITY_SAMPLE WHERE TIMESTAMP >= ? AND TIMESTAMP <= ?",
|
||||||
(today_start, today_end),
|
(day_start_ts, now_ts),
|
||||||
)
|
)
|
||||||
return cursor.fetchone()[0] or 0
|
return cursor.fetchone()[0] or 0
|
||||||
|
|
||||||
def query_weekly_steps(self, cursor) -> Any:
|
def query_weekly_steps(self, cursor) -> Any:
|
||||||
today = datetime.now().date()
|
now = datetime.now()
|
||||||
|
today = now.date()
|
||||||
|
|
||||||
|
# Week starts on Monday at 4am
|
||||||
week_start = today - timedelta(days=today.weekday())
|
week_start = today - timedelta(days=today.weekday())
|
||||||
week_start_ts = int(
|
week_start_time = datetime.combine(week_start, datetime.min.time()).replace(hour=4)
|
||||||
datetime.combine(week_start, datetime.min.time()).timestamp()
|
|
||||||
)
|
# If we're before 4am on Monday, the week actually started last Monday
|
||||||
|
if today.weekday() == 0 and now.hour < 4:
|
||||||
|
week_start_time -= timedelta(days=7)
|
||||||
|
|
||||||
|
week_start_ts = int(week_start_time.timestamp())
|
||||||
|
now_ts = int(now.timestamp())
|
||||||
|
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"SELECT SUM(STEPS) FROM XIAOMI_ACTIVITY_SAMPLE WHERE TIMESTAMP >= ?",
|
"SELECT SUM(STEPS) FROM XIAOMI_ACTIVITY_SAMPLE WHERE TIMESTAMP >= ? AND TIMESTAMP <= ?",
|
||||||
(week_start_ts,),
|
(week_start_ts, now_ts),
|
||||||
)
|
)
|
||||||
return cursor.fetchone()[0] or 0
|
return cursor.fetchone()[0] or 0
|
||||||
|
|
||||||
def query_monthly_steps(self, cursor) -> Any:
|
def query_monthly_steps(self, cursor) -> Any:
|
||||||
today = datetime.now().date()
|
now = datetime.now()
|
||||||
|
today = now.date()
|
||||||
|
|
||||||
|
# Month starts on 1st at 4am
|
||||||
month_start = today.replace(day=1)
|
month_start = today.replace(day=1)
|
||||||
month_start_ts = int(
|
month_start_time = datetime.combine(month_start, datetime.min.time()).replace(hour=4)
|
||||||
datetime.combine(month_start, datetime.min.time()).timestamp()
|
|
||||||
)
|
# If we're before 4am on the 1st, the month actually started last month's 1st
|
||||||
|
if today.day == 1 and now.hour < 4:
|
||||||
|
# Go back to previous month
|
||||||
|
if month_start.month == 1:
|
||||||
|
month_start_time = month_start_time.replace(year=month_start.year - 1, month=12)
|
||||||
|
else:
|
||||||
|
month_start_time = month_start_time.replace(month=month_start.month - 1)
|
||||||
|
|
||||||
|
month_start_ts = int(month_start_time.timestamp())
|
||||||
|
now_ts = int(now.timestamp())
|
||||||
|
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"SELECT SUM(STEPS) FROM XIAOMI_ACTIVITY_SAMPLE WHERE TIMESTAMP >= ?",
|
"SELECT SUM(STEPS) FROM XIAOMI_ACTIVITY_SAMPLE WHERE TIMESTAMP >= ? AND TIMESTAMP <= ?",
|
||||||
(month_start_ts,),
|
(month_start_ts, now_ts),
|
||||||
)
|
)
|
||||||
return cursor.fetchone()[0] or 0
|
return cursor.fetchone()[0] or 0
|
||||||
|
|
||||||
@ -266,29 +310,41 @@ class GadgetbridgeMQTTPublisher:
|
|||||||
return row[0] if row else None
|
return row[0] if row else None
|
||||||
|
|
||||||
def query_hr_resting(self, cursor) -> Any:
|
def query_hr_resting(self, cursor) -> Any:
|
||||||
|
day_start_ts = self.get_day_start_timestamp()
|
||||||
|
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"SELECT HR_RESTING FROM XIAOMI_DAILY_SUMMARY_SAMPLE ORDER BY TIMESTAMP DESC LIMIT 1"
|
"SELECT HR_RESTING FROM XIAOMI_DAILY_SUMMARY_SAMPLE WHERE TIMESTAMP >= ? ORDER BY TIMESTAMP DESC LIMIT 1",
|
||||||
|
(day_start_ts,)
|
||||||
)
|
)
|
||||||
row = cursor.fetchone()
|
row = cursor.fetchone()
|
||||||
return row[0] if row else None
|
return row[0] if row else None
|
||||||
|
|
||||||
def query_hr_max(self, cursor) -> Any:
|
def query_hr_max(self, cursor) -> Any:
|
||||||
|
day_start_ts = self.get_day_start_timestamp()
|
||||||
|
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"SELECT HR_MAX FROM XIAOMI_DAILY_SUMMARY_SAMPLE ORDER BY TIMESTAMP DESC LIMIT 1"
|
"SELECT HR_MAX FROM XIAOMI_DAILY_SUMMARY_SAMPLE WHERE TIMESTAMP >= ? ORDER BY TIMESTAMP DESC LIMIT 1",
|
||||||
|
(day_start_ts,)
|
||||||
)
|
)
|
||||||
row = cursor.fetchone()
|
row = cursor.fetchone()
|
||||||
return row[0] if row else None
|
return row[0] if row else None
|
||||||
|
|
||||||
def query_hr_avg(self, cursor) -> Any:
|
def query_hr_avg(self, cursor) -> Any:
|
||||||
|
day_start_ts = self.get_day_start_timestamp()
|
||||||
|
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"SELECT HR_AVG FROM XIAOMI_DAILY_SUMMARY_SAMPLE ORDER BY TIMESTAMP DESC LIMIT 1"
|
"SELECT HR_AVG FROM XIAOMI_DAILY_SUMMARY_SAMPLE WHERE TIMESTAMP >= ? ORDER BY TIMESTAMP DESC LIMIT 1",
|
||||||
|
(day_start_ts,)
|
||||||
)
|
)
|
||||||
row = cursor.fetchone()
|
row = cursor.fetchone()
|
||||||
return row[0] if row else None
|
return row[0] if row else None
|
||||||
|
|
||||||
def query_calories(self, cursor) -> Any:
|
def query_calories(self, cursor) -> Any:
|
||||||
|
day_start_ts = self.get_day_start_timestamp()
|
||||||
|
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
"SELECT CALORIES FROM XIAOMI_DAILY_SUMMARY_SAMPLE ORDER BY TIMESTAMP DESC LIMIT 1"
|
"SELECT CALORIES FROM XIAOMI_DAILY_SUMMARY_SAMPLE WHERE TIMESTAMP >= ? ORDER BY TIMESTAMP DESC LIMIT 1",
|
||||||
|
(day_start_ts,)
|
||||||
)
|
)
|
||||||
row = cursor.fetchone()
|
row = cursor.fetchone()
|
||||||
return row[0] if row else None
|
return row[0] if row else None
|
||||||
@ -309,6 +365,10 @@ class GadgetbridgeMQTTPublisher:
|
|||||||
# Convert minutes to hours, round to 2 decimals
|
# Convert minutes to hours, round to 2 decimals
|
||||||
return round(row[0] / 60, 2) if row and row[0] is not None else None
|
return round(row[0] / 60, 2) if row and row[0] is not None else None
|
||||||
|
|
||||||
|
def query_server_time(self, cursor) -> Any:
|
||||||
|
"""Return current server time in ISO 8601 format for Home Assistant timestamp"""
|
||||||
|
return datetime.now().isoformat()
|
||||||
|
|
||||||
def get_sensor_data(self) -> Dict[str, Any]:
|
def get_sensor_data(self) -> Dict[str, Any]:
|
||||||
"""Query all sensors and return their values as a dict"""
|
"""Query all sensors and return their values as a dict"""
|
||||||
if not os.path.exists(self.db_path):
|
if not os.path.exists(self.db_path):
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user