Skip to content

Commit 4c6ab17

Browse files
committed
update timestamp
1 parent df4b508 commit 4c6ab17

File tree

3 files changed

+86
-22
lines changed

3 files changed

+86
-22
lines changed

custom_components/eufylife_api/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@
88
"integration_type": "device",
99
"iot_class": "cloud_polling",
1010
"requirements": ["requests>=2.25.0"],
11-
"version": "2.0.8"
11+
"version": "2.0.9"
1212
}

custom_components/eufylife_api/sensor.py

Lines changed: 84 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ def __init__(self, hass: HomeAssistant, entry: EufyLifeConfigEntry) -> None:
4343
self._update_count = 0
4444
self._last_successful_update = None
4545
self._consecutive_failures = 0
46+
self._last_device_timestamp = None # Track last measurement timestamp
4647

4748
# Get update interval from config, fallback to default
4849
update_interval_seconds = entry.data.get(CONF_UPDATE_INTERVAL, DEFAULT_UPDATE_INTERVAL)
@@ -145,6 +146,15 @@ async def _fetch_data(self) -> dict[str, Any]:
145146
if device_data:
146147
_LOGGER.info("Device data endpoint returned %d records, processing...", len(device_data))
147148
processed_device_data = await self._process_device_data(device_data)
149+
150+
# Log what data we received
151+
if processed_device_data:
152+
for customer_id, customer_data in processed_device_data.items():
153+
last_update = customer_data.get("last_update")
154+
if last_update:
155+
_LOGGER.info("Customer %s: latest measurement at %s",
156+
customer_id[:8], last_update.strftime('%Y-%m-%d %H:%M:%S'))
157+
148158
return processed_device_data
149159
else:
150160
_LOGGER.warning("No device data available from API")
@@ -154,17 +164,27 @@ async def _fetch_device_data(self) -> dict[str, Any]:
154164
"""Fetch recent device data from EufyLife API."""
155165
data = self.entry.runtime_data
156166

157-
# Calculate timestamp for lookback period (configurable, default 30 days)
158167
import time as time_module
159-
lookback_days = self.entry.data.get(CONF_DATA_LOOKBACK_DAYS, DEFAULT_DATA_LOOKBACK_DAYS)
160-
since_timestamp = int(time_module.time()) - (lookback_days * 24 * 3600)
161168

162-
_LOGGER.info(
163-
"Fetching device data since timestamp %d (%d days lookback, %s)",
164-
since_timestamp,
165-
lookback_days,
166-
datetime.fromtimestamp(since_timestamp).strftime('%Y-%m-%d %H:%M:%S')
167-
)
169+
# Use last device timestamp if available, otherwise use lookback period
170+
if self._last_device_timestamp:
171+
# Get data since last measurement (add 1 second to avoid duplicates)
172+
since_timestamp = int(self._last_device_timestamp) + 1
173+
_LOGGER.info(
174+
"Fetching device data since last measurement: timestamp %d (%s)",
175+
since_timestamp,
176+
datetime.fromtimestamp(since_timestamp).strftime('%Y-%m-%d %H:%M:%S')
177+
)
178+
else:
179+
# First run - use configurable lookback period
180+
lookback_days = self.entry.data.get(CONF_DATA_LOOKBACK_DAYS, DEFAULT_DATA_LOOKBACK_DAYS)
181+
since_timestamp = int(time_module.time()) - (lookback_days * 24 * 3600)
182+
_LOGGER.info(
183+
"First run - fetching device data since timestamp %d (%d days lookback, %s)",
184+
since_timestamp,
185+
lookback_days,
186+
datetime.fromtimestamp(since_timestamp).strftime('%Y-%m-%d %H:%M:%S')
187+
)
168188

169189
headers = {
170190
"Host": "api.eufylife.com",
@@ -234,12 +254,20 @@ async def _fetch_device_data(self) -> dict[str, Any]:
234254

235255
return actual_data
236256
else:
237-
_LOGGER.warning(
238-
"No device data found in last %d days (since %s). "
239-
"Try taking a measurement on your scale to generate new data.",
240-
lookback_days,
241-
datetime.fromtimestamp(since_timestamp).strftime('%Y-%m-%d %H:%M:%S')
242-
)
257+
if self._last_device_timestamp:
258+
_LOGGER.warning(
259+
"No new device data found since last measurement (%s). "
260+
"Take a new measurement on your scale to generate fresh data.",
261+
datetime.fromtimestamp(since_timestamp - 1).strftime('%Y-%m-%d %H:%M:%S')
262+
)
263+
else:
264+
lookback_days = self.entry.data.get(CONF_DATA_LOOKBACK_DAYS, DEFAULT_DATA_LOOKBACK_DAYS)
265+
_LOGGER.warning(
266+
"No device data found in last %d days (since %s). "
267+
"Try taking a measurement on your scale to generate new data.",
268+
lookback_days,
269+
datetime.fromtimestamp(since_timestamp).strftime('%Y-%m-%d %H:%M:%S')
270+
)
243271
return {}
244272
else:
245273
_LOGGER.debug("Device data request failed with status %d", response.status)
@@ -252,8 +280,13 @@ async def _fetch_device_data(self) -> dict[str, Any]:
252280
async def _process_device_data(self, device_data: list) -> dict[str, Any]:
253281
"""Process device data into customer format."""
254282
processed_data = {}
283+
latest_timestamp = self._last_device_timestamp
284+
total_measurements = len(device_data)
255285

256-
_LOGGER.debug("Processing %d device data records", len(device_data))
286+
_LOGGER.info("Processing %d device data records (measurements)", total_measurements)
287+
if self._last_device_timestamp:
288+
_LOGGER.debug("Current last device timestamp: %s",
289+
datetime.fromtimestamp(self._last_device_timestamp).strftime('%Y-%m-%d %H:%M:%S'))
257290

258291
for i, record in enumerate(device_data):
259292
try:
@@ -276,6 +309,9 @@ async def _process_device_data(self, device_data: list) -> dict[str, Any]:
276309
if update_time:
277310
try:
278311
timestamp = datetime.fromtimestamp(update_time)
312+
# Track the latest timestamp for next API call
313+
if latest_timestamp is None or update_time > latest_timestamp:
314+
latest_timestamp = update_time
279315
except Exception as ts_err:
280316
_LOGGER.debug("Could not parse timestamp %s: %s", update_time, ts_err)
281317

@@ -352,15 +388,27 @@ async def _process_device_data(self, device_data: list) -> dict[str, Any]:
352388

353389
# Only process if we have some meaningful measurement data
354390
if any(key in customer_data for key in ["weight", "body_fat", "muscle_mass", "bmi"]):
355-
processed_data[customer_id] = customer_data
391+
# If we already have data for this customer, keep the most recent one
392+
if customer_id in processed_data:
393+
existing_timestamp = processed_data[customer_id].get("last_update")
394+
if timestamp and existing_timestamp and timestamp > existing_timestamp:
395+
processed_data[customer_id] = customer_data
396+
_LOGGER.debug("Updated customer %s with newer measurement (timestamp: %s)",
397+
customer_id[:8], timestamp.strftime('%Y-%m-%d %H:%M:%S'))
398+
else:
399+
_LOGGER.debug("Keeping existing measurement for customer %s (older or same timestamp)",
400+
customer_id[:8])
401+
else:
402+
processed_data[customer_id] = customer_data
356403

357404
_LOGGER.debug(
358-
"Processed device record #%d for customer %s: weight=%s kg, body_fat=%s%%, muscle_mass=%s kg, bmi=%s",
405+
"Processed device record #%d for customer %s: weight=%s kg, body_fat=%s%%, muscle_mass=%s kg, bmi=%s, timestamp=%s",
359406
i, customer_id[:8],
360407
customer_data.get("weight"),
361408
customer_data.get("body_fat"),
362409
customer_data.get("muscle_mass"),
363-
customer_data.get("bmi")
410+
customer_data.get("bmi"),
411+
timestamp.strftime('%Y-%m-%d %H:%M:%S') if timestamp else "None"
364412
)
365413
else:
366414
_LOGGER.debug("Device record #%d for customer %s contains no usable measurement data",
@@ -370,7 +418,18 @@ async def _process_device_data(self, device_data: list) -> dict[str, Any]:
370418
_LOGGER.warning("Error processing device record #%d: %s", i, err)
371419
continue
372420

373-
_LOGGER.info("Successfully processed device data for %d customers", len(processed_data))
421+
# Update the last device timestamp for next API call
422+
if latest_timestamp is not None:
423+
self._last_device_timestamp = latest_timestamp
424+
_LOGGER.info("Updated last device timestamp to %s for next API call",
425+
datetime.fromtimestamp(latest_timestamp).strftime('%Y-%m-%d %H:%M:%S'))
426+
427+
_LOGGER.info("Successfully processed %d measurements into data for %d customers",
428+
total_measurements, len(processed_data))
429+
430+
if total_measurements > len(processed_data):
431+
_LOGGER.debug("Some measurements were for the same customers - kept most recent per customer")
432+
374433
return processed_data
375434

376435

@@ -393,6 +452,11 @@ async def async_request_refresh(self) -> None:
393452
"""Request a manual refresh of data."""
394453
_LOGGER.info("Manual data refresh requested")
395454
await super().async_request_refresh()
455+
456+
def reset_device_timestamp(self) -> None:
457+
"""Reset the device timestamp to force full data reload on next update."""
458+
self._last_device_timestamp = None
459+
_LOGGER.info("Device timestamp reset - next update will use full lookback period")
396460

397461

398462
async def async_setup_entry(

version.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.0.8
1+
2.0.9

0 commit comments

Comments
 (0)