Compare commits
2
Commits
763bcab3a6
...
6043197d72
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6043197d72 | ||
|
|
d909bc85bd |
No files matched your search
@@ -43,7 +43,7 @@ PYTHONNOUSERSITE=1 venv/bin/python recounting_dashboard_upload.py
|
|||||||
- **`numpy<2`** is required for `rknn-toolkit-lite2` compatibility.
|
- **`numpy<2`** is required for `rknn-toolkit-lite2` compatibility.
|
||||||
- **Install path in service files is `/opt/bytetrack-counter`** (not the `/opt/jetson-counter` mentioned in README/DEPLOY). The `.env.example` also reflects `/opt/bytetrack-counter`.
|
- **Install path in service files is `/opt/bytetrack-counter`** (not the `/opt/jetson-counter` mentioned in README/DEPLOY). The `.env.example` also reflects `/opt/bytetrack-counter`.
|
||||||
- Service user is **`root`**, not `jetson` (despite README saying otherwise).
|
- Service user is **`root`**, not `jetson` (despite README saying otherwise).
|
||||||
- Two systemd units: `bytetrack-counter.service` + `bytetrack-counter-dashboard.service`.
|
- Three systemd units: `bytetrack-counter.service`, `bytetrack-counter-dashboard.service`, and `bytetrack-recounting-upload-dashboard.service` (upload recounting dashboard, port 5003).
|
||||||
- `counter_live.py` (TensorRT) is Jetson-only and won't work on RK3588.
|
- `counter_live.py` (TensorRT) is Jetson-only and won't work on RK3588.
|
||||||
- **Reset flow**: `POST /api/reset` → deletes state JSON + touches `{SHM_DIR}/.reset`. `batch_store._check_reset_signal()` watches this marker and clears in-memory state on next crossing.
|
- **Reset flow**: `POST /api/reset` → deletes state JSON + touches `{SHM_DIR}/.reset`. `batch_store._check_reset_signal()` watches this marker and clears in-memory state on next crossing.
|
||||||
- **Upload filename contract**: uploads are expected as `batch_XX_YYYYMMDD_HHmmSS.mp4` (XX = batch number, timestamp = date). `recounting_dashboard_upload.py` parses both to query the live API's `/api/day-detail/<YYYY-MM-DD>` for the recorded count.
|
- **Upload filename contract**: uploads are expected as `batch_XX_YYYYMMDD_HHmmSS.mp4` (XX = batch number, timestamp = date). `recounting_dashboard_upload.py` parses both to query the live API's `/api/day-detail/<YYYY-MM-DD>` for the recorded count.
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Edge Counter Recounting Upload Dashboard (Flask, port 5003)
|
||||||
|
Documentation=file:///opt/bytetrack-counter/DEPLOY.md
|
||||||
|
After=network-online.target bytetrack-counter-dashboard.service
|
||||||
|
Wants=network-online.target bytetrack-counter-dashboard.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
User=root
|
||||||
|
Group=root
|
||||||
|
|
||||||
|
WorkingDirectory=/opt/bytetrack-counter
|
||||||
|
|
||||||
|
EnvironmentFile=/opt/bytetrack-counter/.env
|
||||||
|
Environment=PATH=/opt/bytetrack-counter/venv/bin:/usr/local/bin:/usr/bin:/bin
|
||||||
|
Environment=PYTHONNOUSERSITE=1
|
||||||
|
Environment=FLASK_DEBUG=false
|
||||||
|
|
||||||
|
ExecStart=/opt/bytetrack-counter/venv/bin/python recounting_dashboard_upload.py
|
||||||
|
|
||||||
|
TimeoutStopSec=15
|
||||||
|
KillSignal=SIGTERM
|
||||||
|
|
||||||
|
Restart=on-failure
|
||||||
|
RestartSec=5
|
||||||
|
StartLimitInterval=60s
|
||||||
|
StartLimitBurst=3
|
||||||
|
|
||||||
|
NoNewPrivileges=true
|
||||||
|
ProtectHome=true
|
||||||
|
PrivateTmp=false
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
@@ -8,6 +8,7 @@ import logging
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import shlex
|
import shlex
|
||||||
|
import signal
|
||||||
import subprocess
|
import subprocess
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
@@ -74,13 +75,31 @@ def _api_get(base_url, path, default=None):
|
|||||||
|
|
||||||
def _stop_recount_locked():
|
def _stop_recount_locked():
|
||||||
global _recount_proc
|
global _recount_proc
|
||||||
if _recount_proc:
|
proc = _recount_proc
|
||||||
|
_recount_proc = None
|
||||||
|
if proc is None:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
pgid = os.getpgid(proc.pid)
|
||||||
|
except (ProcessLookupError, PermissionError):
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
os.killpg(pgid, signal.SIGTERM)
|
||||||
|
except (ProcessLookupError, PermissionError):
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
proc.wait(timeout=5)
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
try:
|
try:
|
||||||
_recount_proc.kill()
|
os.killpg(pgid, signal.SIGKILL)
|
||||||
_recount_proc.wait(timeout=3)
|
except (ProcessLookupError, PermissionError):
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
proc.wait(timeout=3)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
_recount_proc = None
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def _folder_date(filepath, base):
|
def _folder_date(filepath, base):
|
||||||
@@ -179,7 +198,7 @@ def start_recount():
|
|||||||
_current_file = upload_path
|
_current_file = upload_path
|
||||||
cmd_str = RECOUNT_CMD.replace("{path}", shlex.quote(str(upload_path)))
|
cmd_str = RECOUNT_CMD.replace("{path}", shlex.quote(str(upload_path)))
|
||||||
try:
|
try:
|
||||||
_recount_proc = subprocess.Popen(cmd_str, shell=True)
|
_recount_proc = subprocess.Popen(cmd_str, shell=True, start_new_session=True)
|
||||||
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Recount started: {cmd_str}")
|
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Recount started: {cmd_str}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
_current_file = None
|
_current_file = None
|
||||||
|
|||||||
Reference in new issue
Block a user