diff --git a/batch_store.py b/batch_store.py index f2dfc2e..cfb6cbe 100644 --- a/batch_store.py +++ b/batch_store.py @@ -3,12 +3,16 @@ Production batch persistence for edge Jetson counter. Mirrors frigate-counter SQLite schema + current_batch.json contract. """ import json +import os import sqlite3 import threading import time from datetime import datetime, timedelta from pathlib import Path +_SHMD = os.getenv("SHM_DIR", "/dev/shm/bytetrack-counter") +_RESET_FLAG = Path(f"{_SHMD}/.reset") + class BatchStore: def __init__( @@ -195,9 +199,8 @@ class BatchStore: self.log('Ignore batch label cooldown finished') def _check_reset_signal(self): - reset_file = Path(str(self.state_file) + ".reset") - if reset_file.exists(): - reset_file.unlink(missing_ok=True) + if _RESET_FLAG.exists(): + _RESET_FLAG.unlink(missing_ok=True) if self.current_state is not None: self.log("External reset signal — clearing in-memory state") self.current_state = None diff --git a/config.env.example b/config.env.example index 94fd412..c0a673c 100644 --- a/config.env.example +++ b/config.env.example @@ -11,6 +11,8 @@ OUTPUT_DIR=/opt/bytetrack-counter DB_PATH=/opt/bytetrack-counter/bytetrack_counter.db # JSON file persisting the current active batch state STATE_FILE=/tmp/bytetrack_current_batch.json +# Shared memory directory used for reset signal (touch .reset to clear counter state) +SHM_DIR=/dev/shm/bytetrack-counter # --- Input source --- # RTSP / HTTP live stream, or a local video file path diff --git a/counter_dashboard.py b/counter_dashboard.py index 00dc923..5336f09 100644 --- a/counter_dashboard.py +++ b/counter_dashboard.py @@ -31,6 +31,7 @@ CURRENT_BATCH_PATH = os.getenv("STATE_FILE", os.getenv("CURRENT_BATCH_PATH", f"{ CUTOFF_TIME = os.getenv("CUTOFF_TIME", os.getenv("DAILY_CUTOFF_TIME", "20:00")) LIVE_STREAM_FRAME_PATH = os.getenv("LIVE_STREAM_FRAME_PATH", "/dev/shm/jetson-counter/live_frame.jpg") +SHM_DIR = os.getenv("SHM_DIR", "/dev/shm/bytetrack-counter") SITE_NAME = os.getenv("SITE_NAME", "LIVE") @@ -560,8 +561,9 @@ def api_reset(): paths.add(cb) for p in paths: Path(p).unlink(missing_ok=True) - Path(str(p) + ".reset").touch() Path(LIVE_STREAM_FRAME_PATH).unlink(missing_ok=True) + Path(SHM_DIR).mkdir(parents=True, exist_ok=True) + Path(f"{SHM_DIR}/.reset").touch() except Exception: pass return jsonify({"success": True, "message": "State + live frame cleared"})