forked from dsutanto/bytetrack-counter-cpp
Update Today
This commit is contained in:
1 parent
896a07b5fa
commit
eefff48953
7 files changed
+2827
-12
No files matched your search
+2781
-7
File diff suppressed because it is too large.
Load diff
@@ -33,3 +33,23 @@ make -j$(nproc)
|
||||
systemctl restart bytetrack-counter
|
||||
journalctl -u bytetrack-counter -f
|
||||
```
|
||||
|
||||
## Reset via .reset file
|
||||
|
||||
Place a `.reset` file in `SHM_DIR` (default `/dev/shm/bytetrack-counter`) to trigger a full state reset:
|
||||
|
||||
- **Startup**: deleting `.reset` before service starts clears all state files on boot
|
||||
- **Runtime**: dropping `.reset` while service runs calls `BatchStore::reset()` — ends active batch, clears in-memory state, deletes `STATE_FILE`, clears live stream JPEG + writes blank frame on next write
|
||||
|
||||
```bash
|
||||
touch /dev/shm/bytetrack-counter/.reset
|
||||
```
|
||||
|
||||
## Shared memory
|
||||
|
||||
`SHM_DIR` (`/dev/shm/bytetrack-counter` by default) stores:
|
||||
- `LIVE_STREAM_FRAME_PATH` JPEG snapshot
|
||||
- `RECORD_SHM_DIR` video recordings before move to disk
|
||||
- `.reset` trigger file
|
||||
|
||||
Directory auto-created at startup.
|
||||
@@ -20,12 +20,16 @@ Talenan crossing → close batch. Persist to SQLite + JSON.
|
||||
|
||||
```
|
||||
env: .env KEY=VALUE file — all config per config.env.example
|
||||
env: LIVE_STREAM_FRAME_PATH → JPEG snapshot path (/dev/shm/bytetrack-counter/live_frame.jpg)
|
||||
env: SHM_DIR → shared memory directory (/dev/shm/bytetrack-counter)
|
||||
env: LIVE_STREAM_FRAME_PATH → JPEG snapshot path
|
||||
env: RECORD_VIDEO, RECORD_DELAY_SECONDS, RECORD_END_DELAY, RECORD_RETENTION_DAYS
|
||||
cmd: bytetrack-counter <config.env>
|
||||
db: SQLite batches(id,counting_date,batch_number,camera_name,object_label,count,start_time,end_time)
|
||||
db: SQLite daily_summaries(id,counting_date,camera_name,object_label,total_count,total_batches)
|
||||
file: JSON state — batch_number,count,start_time,last_detection_time,counted_event_ids[]
|
||||
file: CSV crossing log — batch,frame,timestamp,chicken_id
|
||||
file: SHM_DIR/.reset → trigger full state reset
|
||||
file: SHM_DIR/batch_N_HHMMSS.mp4 → per-batch video recording (moved to OUTPUT_DIR/YYYY-MM-DD/)
|
||||
sig: SIGTERM|SIGINT → shutdown_requested → graceful exit
|
||||
```
|
||||
|
||||
@@ -42,7 +46,10 @@ V7: counting_date rolls at DAILY_CUTOFF_TIME → cutoff_watcher thread
|
||||
V8: ayam & talenan → separate ByteTrack instances (match_thresh_0=0.8, match_thresh_1=0.6)
|
||||
V9: live_stream_enabled → parent dir of LIVE_STREAM_FRAME_PATH created @ startup
|
||||
V10: stale track (> TRACKED_PRUNE_SEC unseen) → prune from external tracking maps
|
||||
V11: DIRECTORY for LIVE_STREAM_FRAME_PATH must exist — created by code and by tmpfiles.d on boot (/dev/shm is volatile)
|
||||
V11: all dirs (output_dir, shm_dir, live_stream parent) created @ startup
|
||||
V12: SHM_DIR/.reset → BatchStore::reset() — end active batch, clear memory, delete state_file, write blank live JPEG
|
||||
V13: video recording: motion → SPECULATING (≤RECORD_DELAY_SECONDS), ayam → CONFIRMED → talenan/batch-end → STOPPING (+RECORD_END_DELAY) → move to OUTPUT_DIR/YYYY-MM-DD/
|
||||
V14: video retention: day-dirs > RECORD_RETENTION_DAYS old → removed @ startup & @ each CUTOFF_TIME
|
||||
```
|
||||
|
||||
## §T — Tasks
|
||||
@@ -64,7 +71,7 @@ T12|x|CsvLogger for crossing events|I.file
|
||||
T13|x|Live JPEG snapshot to shared memory|V9
|
||||
T14|x|systemd service with ProtectSystem + ReadWritePaths|I.cmd
|
||||
T15|x|Graceful shutdown: SIGTERM → close batch → save state|I.sig
|
||||
T16|x|Video per batch recording (config exists, impl ⊥ in C++) to shared memory for speed reason. To identify batch is between talenan (index=1), save with different name. Once completed, spawn new process (non blocking) to move recorded file to final destination (from config env). To identify first batch, record and wait X seconds (X default is 10 seconds, can be defined in config env), until first ayam (index=0) detected|-
|
||||
T16|x|Video per-batch recording: motion-triggered → speculating in shm, confirmed when ayam detected ≤ RECORD_DELAY_SECONDS, stopped RECORD_END_DELAY after batch close, moved to OUTPUT_DIR/YYYY-MM-DD/ via fork, retention cleanup at startup & cutoff. Unconfirmed recordings deleted.|V13,V14
|
||||
T17|~?|Python DEBUG_TRACKING equivalent (per-frame score/track dump)|-
|
||||
```
|
||||
|
||||
|
||||
Binary file not shown.
@@ -413,6 +413,17 @@ void BatchStore::set_batch_closed_callback(std::function<void(int)> cb) {
|
||||
batch_closed_cb_ = std::move(cb);
|
||||
}
|
||||
|
||||
void BatchStore::reset() {
|
||||
std::lock_guard<std::mutex> lock(state_mutex_);
|
||||
if (!current_state_.is_null()) {
|
||||
end_batch_locked("reset");
|
||||
}
|
||||
current_state_ = nullptr;
|
||||
batch_timer_running_ = false;
|
||||
std::error_code ec;
|
||||
std::filesystem::remove(state_file_, ec);
|
||||
}
|
||||
|
||||
bool BatchStore::check_cutoff_reset() {
|
||||
return cutoff_triggered_.exchange(false);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ public:
|
||||
int display_total();
|
||||
|
||||
void set_batch_closed_callback(std::function<void(int)> cb);
|
||||
void reset();
|
||||
|
||||
bool check_cutoff_reset();
|
||||
|
||||
|
||||
+4
-2
@@ -150,12 +150,13 @@ int main(int argc, char* argv[]) {
|
||||
std::filesystem::create_directories(live_p.parent_path());
|
||||
}
|
||||
|
||||
bool startup_reset = false;
|
||||
{
|
||||
std::string reset_file = g_config.shm_dir + "/.reset";
|
||||
if (std::filesystem::exists(reset_file)) {
|
||||
std::cout << "[RESET] [INFO] .reset detected — clearing state" << std::endl;
|
||||
startup_reset = true;
|
||||
std::error_code ec;
|
||||
std::filesystem::remove(g_config.state_file, ec);
|
||||
std::filesystem::remove(g_config.live_stream_frame_path, ec);
|
||||
std::filesystem::remove(reset_file, ec);
|
||||
}
|
||||
@@ -177,6 +178,7 @@ int main(int argc, char* argv[]) {
|
||||
g_config.min_duration_per_batch,
|
||||
logger);
|
||||
store.start_cutoff_watcher();
|
||||
if (startup_reset) store.reset();
|
||||
|
||||
std::unique_ptr<CsvLogger> cross_logger;
|
||||
if (g_config.export_csv) {
|
||||
@@ -258,8 +260,8 @@ int main(int argc, char* argv[]) {
|
||||
std::string reset_file = g_config.shm_dir + "/.reset";
|
||||
if (std::filesystem::exists(reset_file)) {
|
||||
std::cout << "[" << now_str() << "] [INFO] [RESET] .reset detected — clearing state" << std::endl;
|
||||
store.reset();
|
||||
std::error_code ec;
|
||||
std::filesystem::remove(g_config.state_file, ec);
|
||||
std::filesystem::remove(g_config.live_stream_frame_path, ec);
|
||||
std::filesystem::remove(reset_file, ec);
|
||||
blank_live_frame = true;
|
||||
|
||||
Reference in new issue
Block a user