M5-T07: add latest-reading cards and Recharts trend charts; readings return most-recent rows

This commit is contained in:
2026-06-22 14:17:59 +02:00
parent 2dc469274a
commit 68165f0e01
13 changed files with 1454 additions and 23 deletions
+13 -4
View File
@@ -304,8 +304,16 @@ def get_readings(
) -> ModbusReadingsResponse:
"""Return time-range readings for a device.
Results are ordered by ``recorded_at`` ascending and capped by ``limit``
(max {_READINGS_LIMIT_MAX}) to prevent accidental full-table exports.
When the window contains more rows than ``limit``, the **most recent** N rows
are returned (``ORDER BY recorded_at DESC LIMIT n``), then reversed to
ascending order before being sent to the client. This ensures that for long
time-range requests (e.g. 6 h / 24 h) the caller always sees the latest data
rather than the oldest segment of the window.
When the window has fewer rows than ``limit`` the full window is returned in
ascending order — behaviour is identical to a plain ascending query.
The response schema is unchanged: items are always ``recorded_at`` ascending.
The query uses the ``(device_id, recorded_at)`` composite index for
efficient time-window scans.
@@ -320,7 +328,7 @@ def get_readings(
stmt = (
select(ModbusReading)
.where(ModbusReading.device_id == device.id)
.order_by(ModbusReading.recorded_at)
.order_by(ModbusReading.recorded_at.desc())
.limit(limit)
)
@@ -329,7 +337,8 @@ def get_readings(
if end is not None:
stmt = stmt.where(ModbusReading.recorded_at <= end)
rows = db.execute(stmt).scalars().all()
# Fetch most-recent N rows, then reverse to restore ascending order for the response.
rows = list(reversed(db.execute(stmt).scalars().all()))
items = [ModbusReadingResponse(recorded_at=r.recorded_at, payload=r.payload) for r in rows]
return ModbusReadingsResponse(items=items)