Phase 7 #190: zone-filter в Frigate MQTT subscriber
Frigate 0.17 schema отвергает objects.filters.<obj>.required_zones
("Extra inputs not permitted" → safe mode), поэтому фильтрацию по зонам
делаем на стороне composer'а. cfc_overlay_detbox_match_zones() сверяет
after.current_zones события с whitelist'ом overlay'я. end-события
вызываются безусловно (no-op если рамки нет).
CLI: --detection-cell key,camera,dx,dy,dw,dh,detect_w,detect_h[,zone1:zone2:...]
9-е поле опционально (colon-separated). Без него filter выключен.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+42
-7
@@ -126,13 +126,21 @@ int main(int argc, char **argv)
|
||||
const char *frigate_mqtt_host = NULL;
|
||||
int frigate_mqtt_port = 1883;
|
||||
const char *frigate_topic = "frigate/events";
|
||||
/* --detection-cell key,camera,dx,dy,dw,dh,detect_w,detect_h
|
||||
/* --detection-cell key,camera,dx,dy,dw,dh,detect_w,detect_h[,zone1:zone2:...]
|
||||
* key — символьное имя для логов (например "parking")
|
||||
* camera — Frigate camera_key для MQTT match'а ("parking_overview")
|
||||
* dx,dy,dw,dh — координаты ячейки composer'а на output frame
|
||||
* detect_w,detect_h — Frigate detect.{width,height} (640,480) */
|
||||
* detect_w,detect_h — Frigate detect.{width,height} (640,480)
|
||||
* zones (опц.) — colon-separated whitelist; если задан, события вне
|
||||
* этих зон отбрасываются subscriber'ом (zone-filter
|
||||
* заменяет Frigate-side objects.filters.required_zones
|
||||
* который не работает в 0.17 schema). */
|
||||
#define DETCELL_ZONE_MAX 8
|
||||
typedef struct { char key[32], camera[48];
|
||||
int dx, dy, dw, dh, detect_w, detect_h; } detcell_t;
|
||||
int dx, dy, dw, dh, detect_w, detect_h;
|
||||
char zone_storage[DETCELL_ZONE_MAX][32];
|
||||
const char *zone_ptrs[DETCELL_ZONE_MAX];
|
||||
int num_zones; } detcell_t;
|
||||
detcell_t detcells[MAX_CELLS] = { 0 };
|
||||
int num_detcells = 0;
|
||||
|
||||
@@ -217,7 +225,7 @@ int main(int argc, char **argv)
|
||||
case 'T': frigate_topic = optarg; break;
|
||||
case 'D': {
|
||||
if (num_detcells >= MAX_CELLS) { fprintf(stderr, "max %d detcells\n", MAX_CELLS); return 1; }
|
||||
char buf[256]; strncpy(buf, optarg, sizeof(buf) - 1); buf[sizeof(buf)-1] = '\0';
|
||||
char buf[512]; strncpy(buf, optarg, sizeof(buf) - 1); buf[sizeof(buf)-1] = '\0';
|
||||
char *p = buf, *q;
|
||||
q = strchr(p, ','); if (!q) { fprintf(stderr, "bad --detection-cell\n"); return 1; }
|
||||
*q = '\0'; strncpy(detcells[num_detcells].key, p, 31); p = q + 1;
|
||||
@@ -233,7 +241,28 @@ int main(int argc, char **argv)
|
||||
*q = '\0'; detcells[num_detcells].dh = atoi(p); p = q + 1;
|
||||
q = strchr(p, ','); if (!q) { fprintf(stderr, "bad --detection-cell\n"); return 1; }
|
||||
*q = '\0'; detcells[num_detcells].detect_w = atoi(p); p = q + 1;
|
||||
detcells[num_detcells].detect_h = atoi(p);
|
||||
/* detect_h — может быть последним полем или иметь ',<zones>' после. */
|
||||
q = strchr(p, ',');
|
||||
if (q) {
|
||||
*q = '\0'; detcells[num_detcells].detect_h = atoi(p); p = q + 1;
|
||||
/* Парсим zones — colon-separated whitelist. */
|
||||
detcells[num_detcells].num_zones = 0;
|
||||
char *z = p;
|
||||
while (z && *z && detcells[num_detcells].num_zones < DETCELL_ZONE_MAX) {
|
||||
char *sep = strchr(z, ':');
|
||||
int len = sep ? (int)(sep - z) : (int)strlen(z);
|
||||
if (len > 31) len = 31;
|
||||
int idx = detcells[num_detcells].num_zones;
|
||||
memcpy(detcells[num_detcells].zone_storage[idx], z, len);
|
||||
detcells[num_detcells].zone_storage[idx][len] = '\0';
|
||||
detcells[num_detcells].zone_ptrs[idx] =
|
||||
detcells[num_detcells].zone_storage[idx];
|
||||
detcells[num_detcells].num_zones++;
|
||||
z = sep ? sep + 1 : NULL;
|
||||
}
|
||||
} else {
|
||||
detcells[num_detcells].detect_h = atoi(p);
|
||||
}
|
||||
num_detcells++;
|
||||
break;
|
||||
}
|
||||
@@ -415,6 +444,8 @@ int main(int argc, char **argv)
|
||||
.color_y = 210, .color_u = 50, .color_v = 100, /* кислотно-зелёный */
|
||||
.alpha = 240,
|
||||
.stale_ms = 8000,
|
||||
.required_zones = detcells[i].num_zones ? detcells[i].zone_ptrs : NULL,
|
||||
.required_zones_count = detcells[i].num_zones,
|
||||
};
|
||||
if (cfc_overlay_create_detection_boxes(&dc, &detbox_overlays[i]) != 0) {
|
||||
fprintf(stderr, "[grid_record] detbox create failed для '%s'\n",
|
||||
@@ -422,10 +453,14 @@ int main(int argc, char **argv)
|
||||
continue;
|
||||
}
|
||||
cfc_composer_add_overlay(comp, detbox_overlays[i]);
|
||||
fprintf(stderr, "[grid_record] detbox '%s' → cell %s (%d,%d %dx%d), detect %dx%d\n",
|
||||
fprintf(stderr, "[grid_record] detbox '%s' → cell %s (%d,%d %dx%d), detect %dx%d, zones=%d",
|
||||
detcells[i].camera, detcells[i].key,
|
||||
detcells[i].dx, detcells[i].dy, detcells[i].dw, detcells[i].dh,
|
||||
detcells[i].detect_w, detcells[i].detect_h);
|
||||
detcells[i].detect_w, detcells[i].detect_h,
|
||||
detcells[i].num_zones);
|
||||
for (int z = 0; z < detcells[i].num_zones; z++)
|
||||
fprintf(stderr, " %s", detcells[i].zone_storage[z]);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
/* Frigate MQTT subscriber (если задан --frigate-mqtt). */
|
||||
|
||||
Reference in New Issue
Block a user