first commit
This commit is contained in:
commit
f7ef038def
14 files changed
+5558
No files matched your search
+179
@@ -0,0 +1,179 @@
|
||||
# Runtime Control — Start/Stop Counting
|
||||
|
||||
The counter can pause and resume object detection & counting **on the fly**,
|
||||
without restarting the process. There are three interchangeable ways to control
|
||||
it, and they all converge on a single source of truth: the **control file**.
|
||||
|
||||
- **Control file** — a small JSON file the counter polls.
|
||||
- **TCP control socket** — line commands over the network that update the file.
|
||||
- **Dashboard button** — a COUNTING ON/OFF toggle that writes the file via its API.
|
||||
|
||||
When counting is **OFF**, the counter skips inference entirely (no detection, no
|
||||
counting, lower CPU/NPU load), the video/live stream keeps running, and a
|
||||
`COUNTING PAUSED` badge is drawn on the frame. When **ON**, normal counting
|
||||
resumes.
|
||||
|
||||
---
|
||||
|
||||
## 1. Enable runtime control
|
||||
|
||||
Runtime control is opt-in. In your `.env`:
|
||||
|
||||
```ini
|
||||
# Master switch — required for ALL control methods (file, socket, dashboard).
|
||||
CONTROL_ENABLED=true
|
||||
|
||||
# Shared control file. MUST be identical for the counter and the dashboard.
|
||||
CONTROL_FILE=/opt/zenai-ktc-counter/control.json
|
||||
|
||||
# Counting state on startup / when the control file does not exist yet.
|
||||
CONTROL_DEFAULT_COUNTING=true
|
||||
|
||||
# How often (seconds) the counter re-reads the control file.
|
||||
CONTROL_POLL_SEC=1.0
|
||||
```
|
||||
|
||||
When `CONTROL_ENABLED=false`, the counter always counts, the control file is
|
||||
ignored, and the dashboard hides the toggle button.
|
||||
|
||||
> Changes take effect within `CONTROL_POLL_SEC` seconds (default 1s), because the
|
||||
> counter re-reads the file on a timer.
|
||||
|
||||
---
|
||||
|
||||
## 2. Control file
|
||||
|
||||
### Format
|
||||
|
||||
```json
|
||||
{ "counting": true }
|
||||
```
|
||||
|
||||
- `"counting": true` → counting **ON**
|
||||
- `"counting": false` → counting **OFF** (paused)
|
||||
|
||||
The counter creates this file on startup (seeded from `CONTROL_DEFAULT_COUNTING`)
|
||||
if it does not exist. All writers (counter, dashboard, socket) write it
|
||||
**atomically** (temp file + rename), so readers never see a half-written file.
|
||||
|
||||
### Toggle by editing the file
|
||||
|
||||
Pause counting:
|
||||
|
||||
```bash
|
||||
printf '{"counting": false}\n' > /opt/bytetrack-counter/control.json
|
||||
```
|
||||
|
||||
Resume counting:
|
||||
|
||||
```bash
|
||||
printf '{"counting": true}\n' > /opt/bytetrack-counter/control.json
|
||||
```
|
||||
|
||||
Check current state:
|
||||
|
||||
```bash
|
||||
cat /opt/bytetrack-counter/control.json
|
||||
```
|
||||
|
||||
> Use the exact path from your `CONTROL_FILE` setting. If you write it by hand,
|
||||
> keep it valid JSON — an unreadable file falls back to `CONTROL_DEFAULT_COUNTING`.
|
||||
|
||||
---
|
||||
|
||||
## 3. TCP control socket
|
||||
|
||||
The socket lets you toggle counting over the network. It updates the same control
|
||||
file, so changes still apply within `CONTROL_POLL_SEC`.
|
||||
|
||||
### Enable
|
||||
|
||||
```ini
|
||||
# Requires CONTROL_ENABLED=true as well.
|
||||
CONTROL_SOCKET_ENABLED=true
|
||||
|
||||
# 127.0.0.1 = local only. Use 0.0.0.0 to allow remote clients.
|
||||
CONTROL_SOCKET_HOST=127.0.0.1
|
||||
|
||||
# TCP port.
|
||||
CONTROL_SOCKET_PORT=5090
|
||||
```
|
||||
|
||||
### Commands
|
||||
|
||||
Newline-terminated, case-insensitive. One connection can send multiple commands.
|
||||
|
||||
| Command | Effect | Reply |
|
||||
|----------------------------|-------------------------------|-----------------------|
|
||||
| `START` / `RESUME` / `ON` | Counting ON | `OK counting=on` |
|
||||
| `STOP` / `PAUSE` / `OFF` | Counting OFF | `OK counting=off` |
|
||||
| `TOGGLE` | Flip current state | `OK counting=on/off` |
|
||||
| `STATUS` / `GET` | Report state (no change) | `OK counting=on/off` |
|
||||
| *(anything else)* | — | `ERR unknown command` |
|
||||
|
||||
### Examples
|
||||
|
||||
Using `nc` (netcat):
|
||||
|
||||
```bash
|
||||
printf 'STOP\n' | nc 127.0.0.1 5090
|
||||
printf 'START\n' | nc 127.0.0.1 5090
|
||||
printf 'TOGGLE\n' | nc 127.0.0.1 5090
|
||||
printf 'STATUS\n' | nc 127.0.0.1 5090
|
||||
```
|
||||
|
||||
Using bash `/dev/tcp` (no netcat needed):
|
||||
|
||||
```bash
|
||||
exec 3<>/dev/tcp/127.0.0.1/5090
|
||||
printf 'STATUS\n' >&3
|
||||
head -n1 <&3
|
||||
exec 3>&-
|
||||
```
|
||||
|
||||
Python client:
|
||||
|
||||
```python
|
||||
import socket
|
||||
|
||||
def control(cmd, host="127.0.0.1", port=5090):
|
||||
with socket.create_connection((host, port), timeout=2) as s:
|
||||
s.sendall((cmd + "\n").encode())
|
||||
return s.recv(256).decode().strip()
|
||||
|
||||
print(control("STATUS")) # OK counting=on
|
||||
print(control("STOP")) # OK counting=off
|
||||
```
|
||||
|
||||
> **Security:** the socket has **no authentication**. Keep `CONTROL_SOCKET_HOST`
|
||||
> on `127.0.0.1`, or restrict access with a firewall / trusted network if you
|
||||
> bind to `0.0.0.0`.
|
||||
|
||||
---
|
||||
|
||||
## 4. Dashboard button
|
||||
|
||||
When `CONTROL_ENABLED=true`, the dashboard header shows a **COUNTING ON/OFF**
|
||||
button (green when on, red when off). Clicking it flips the state immediately.
|
||||
|
||||
The dashboard must point at the **same** `CONTROL_FILE` as the counter (set it in
|
||||
the dashboard's environment too). The dashboard exposes:
|
||||
|
||||
- `GET /api/control` → `{ "enabled": true, "counting": true }`
|
||||
- `POST /api/control` with body `{ "counting": false }` → writes the control file
|
||||
(returns `403` if `CONTROL_ENABLED=false`)
|
||||
|
||||
---
|
||||
|
||||
## Notes & behavior
|
||||
|
||||
- **Single source of truth:** the socket and dashboard both write the control
|
||||
file; the counter reacts only to the file. This avoids race conditions between
|
||||
control methods.
|
||||
- **Latency:** expect up to `CONTROL_POLL_SEC` (default 1s) between issuing a
|
||||
command and the counter reacting.
|
||||
- **Live stream keeps running** while paused, so you still see the camera feed
|
||||
with the `COUNTING PAUSED` overlay.
|
||||
- **Shared path requirement:** counter and dashboard must use the same
|
||||
`CONTROL_FILE`. If they run on different machines, use the TCP socket (or a
|
||||
shared network path) instead.
|
||||
Reference in new issue
Block a user