feat: odometer in trips/overview, trips upload toggle, fix video count
- OBD odometer now logged to tracking rows on every GPS snapshot - trips table: START_ODOMETER/END_ODOMETER columns (migration) - build_trip_summaries: picks odometer from first/last tracking row - list_trips: uses real OBD odo, falls back to cumulative distance - overview stats: odometer_km (max seen from OBD), video_count fixed - history page: Odometer column shows start→end km per trip - app_upload: TRIPS_UPLOAD_SETTING_KEY, is_trips_upload_enabled() - _upload_tracking_batch: skips when trips upload is off - settings: separate 'Upload trips & GPS' toggle from dashcam toggle Co-authored-by: Copilot <[email protected]>
This commit is contained in:
+48
-19
@@ -90,7 +90,9 @@ SQL_CREATE_TRIPS_TABLE = """CREATE TABLE IF NOT EXISTS trips (
|
||||
DURATION_SECONDS integer NOT NULL,
|
||||
POINT_COUNT integer NOT NULL,
|
||||
AVERAGE_SPEED_KMH float NOT NULL DEFAULT 0,
|
||||
MAX_SPEED_KMH float NOT NULL DEFAULT 0
|
||||
MAX_SPEED_KMH float NOT NULL DEFAULT 0,
|
||||
START_ODOMETER float,
|
||||
END_ODOMETER float
|
||||
);"""
|
||||
|
||||
SQL_CREATE_TRIP_BUILD_STATE_TABLE = """CREATE TABLE IF NOT EXISTS trip_build_state (
|
||||
@@ -180,6 +182,8 @@ def _migrate_trips_table(conn):
|
||||
additions = {
|
||||
"AVERAGE_SPEED_KMH": "float NOT NULL DEFAULT 0",
|
||||
"MAX_SPEED_KMH": "float NOT NULL DEFAULT 0",
|
||||
"START_ODOMETER": "float",
|
||||
"END_ODOMETER": "float",
|
||||
}
|
||||
for name, definition in additions.items():
|
||||
if name not in existing_columns:
|
||||
@@ -271,7 +275,7 @@ def refresh_trips(force=False):
|
||||
if intersecting_trip[0] is not None:
|
||||
rebuild_start_id = min(rebuild_start_id, intersecting_trip[0])
|
||||
rows = conn.execute(
|
||||
"""SELECT id, DATETIME, GPSX, GPSY, SPEED
|
||||
"""SELECT id, DATETIME, GPSX, GPSY, SPEED, ODOMETER
|
||||
FROM tracking WHERE id >= ? ORDER BY id ASC""",
|
||||
(rebuild_start_id,),
|
||||
).fetchall()
|
||||
@@ -289,13 +293,15 @@ def refresh_trips(force=False):
|
||||
START_DATETIME, END_DATETIME,
|
||||
START_GPSX, START_GPSY, END_GPSX, END_GPSY,
|
||||
DISTANCE_KM, DURATION_SECONDS, POINT_COUNT,
|
||||
AVERAGE_SPEED_KMH, MAX_SPEED_KMH
|
||||
AVERAGE_SPEED_KMH, MAX_SPEED_KMH,
|
||||
START_ODOMETER, END_ODOMETER
|
||||
) VALUES (
|
||||
:id, :start_tracking_id, :end_tracking_id,
|
||||
:start_datetime, :end_datetime,
|
||||
:start_gpsx, :start_gpsy, :end_gpsx, :end_gpsy,
|
||||
:distance_km, :duration_seconds, :point_count,
|
||||
:average_speed_kmh, :max_speed_kmh
|
||||
:average_speed_kmh, :max_speed_kmh,
|
||||
:start_odometer, :end_odometer
|
||||
)""",
|
||||
trips,
|
||||
)
|
||||
@@ -325,15 +331,25 @@ def get_overview_stats():
|
||||
COALESCE(SUM(DURATION_SECONDS),0), COALESCE(MAX(MAX_SPEED_KMH),0)
|
||||
FROM trips
|
||||
""").fetchone()
|
||||
odo_row = conn.execute("""
|
||||
SELECT MAX(ODOMETER) FROM tracking WHERE ODOMETER IS NOT NULL AND ODOMETER > 0
|
||||
""").fetchone()
|
||||
dtc_row = conn.execute("""
|
||||
SELECT COUNT(*) FROM dtc_codes WHERE cleared_at IS NULL
|
||||
""").fetchone() if _table_exists(conn, "dtc_codes") else (0,)
|
||||
from modules import app_video as _av
|
||||
try:
|
||||
video_count = sum(1 for _ in _av.list_local_videos().get("files", []))
|
||||
except Exception:
|
||||
video_count = 0
|
||||
return {
|
||||
"trip_count": row[0],
|
||||
"total_km": row[1],
|
||||
"total_duration_s": row[2],
|
||||
"all_time_max_speed": row[3],
|
||||
"active_dtc": dtc_row[0] if dtc_row else 0,
|
||||
"video_count": video_count,
|
||||
"odometer_km": odo_row[0] if odo_row and odo_row[0] else None,
|
||||
}
|
||||
|
||||
|
||||
@@ -353,21 +369,34 @@ def list_trips():
|
||||
"""SELECT id, START_DATETIME, END_DATETIME,
|
||||
START_GPSX, START_GPSY, END_GPSX, END_GPSY,
|
||||
DISTANCE_KM, DURATION_SECONDS, POINT_COUNT,
|
||||
AVERAGE_SPEED_KMH, MAX_SPEED_KMH
|
||||
FROM trips ORDER BY START_DATETIME DESC"""
|
||||
AVERAGE_SPEED_KMH, MAX_SPEED_KMH,
|
||||
START_ODOMETER, END_ODOMETER
|
||||
FROM trips ORDER BY START_DATETIME ASC"""
|
||||
).fetchall()
|
||||
return [{
|
||||
"id": row[0],
|
||||
"start_datetime": row[1],
|
||||
"end_datetime": row[2],
|
||||
"start": {"latitude": row[3], "longitude": row[4]},
|
||||
"end": {"latitude": row[5], "longitude": row[6]},
|
||||
"distance_km": row[7],
|
||||
"duration_seconds": row[8],
|
||||
"point_count": row[9],
|
||||
"average_speed_kmh": row[10],
|
||||
"max_speed_kmh": row[11],
|
||||
} for row in rows]
|
||||
# If real OBD odometer is available use it; otherwise fall back to cumulative distance
|
||||
result = []
|
||||
cumulative_km = 0.0
|
||||
for row in rows:
|
||||
dist = row[7] or 0
|
||||
start_odo = row[12] if row[12] is not None else round(cumulative_km, 1)
|
||||
end_odo = row[13] if row[13] is not None else round(cumulative_km + dist, 1)
|
||||
cumulative_km += dist
|
||||
result.append({
|
||||
"id": row[0],
|
||||
"start_datetime": row[1],
|
||||
"end_datetime": row[2],
|
||||
"start": {"latitude": row[3], "longitude": row[4]},
|
||||
"end": {"latitude": row[5], "longitude": row[6]},
|
||||
"distance_km": row[7],
|
||||
"duration_seconds": row[8],
|
||||
"point_count": row[9],
|
||||
"average_speed_kmh": row[10],
|
||||
"max_speed_kmh": row[11],
|
||||
"odo_start_km": start_odo,
|
||||
"odo_end_km": end_odo,
|
||||
})
|
||||
result.reverse() # newest first for display
|
||||
return result
|
||||
|
||||
|
||||
def get_trip_route(trip_id, max_points=2000):
|
||||
@@ -674,7 +703,7 @@ def _log_loop():
|
||||
)
|
||||
if should_log_tracking(
|
||||
position, speed, last_position, seconds_since_log
|
||||
) and insert_tracking(position[0], position[1], speed):
|
||||
) and insert_tracking(position[0], position[1], speed, app_obd.odometer):
|
||||
last_position = position
|
||||
last_logged_at = now
|
||||
|
||||
|
||||
Reference in New Issue
Block a user