- Updated argument parsing in manage_api.py to include new threshold parameters. - Enhanced _config_payload to include thresholds and webhook configurations. - Modified _build_summary to track queue metrics and adjust alert reporting. - Refactored DwellEngine to utilize queue thresholds for alerting and reporting. - Added queue metrics calculations and status change tracking in dwell_engine.py. - Updated notifier.py to support posting JSON events to webhooks. - Adjusted example configuration to reflect new threshold parameters. - Enhanced Docker entrypoint script for better process management. - Updated tests to cover new queue metrics and thresholds. - Improved ManagedServiceDetail and ManagedServices Vue components to display queue metrics.
8.5 KiB
8.5 KiB
Managed Queue Webhook 对接说明
本文档说明 managed/store_dwell_alert 和 managed/people_flow_project 两个工程新增的排队统计与 webhook 推送结构,便于接收方按统一协议完成对接。
业务规则
- 统计窗口固定为每 30 分钟一个窗口。
- 每个窗口统计两类人数:
over_threshold_count:该窗口内累计排队时间大于等于 5 分钟的人数。under_threshold_count:该窗口内累计排队时间小于 5 分钟但大于 0 的人数。
- 一阶段排队等级规则:
crowded:over_threshold_count > 5normal:2 <= over_threshold_count <= 5few:over_threshold_count < 2
- 状态变化规则:
queue_increased:normal -> crowded或few -> crowdedqueue_decreased:normal -> few或crowded -> fewqueue_normalized:crowded -> normal或few -> normalunchanged:窗口等级未变化initial:首个统计窗口,没有上一个窗口可比较
配置方式
store_dwell_alert
配置文件示例:managed/store_dwell_alert/config/config.example.yaml
thresholds:
queue_time_threshold_seconds: 300
crowded_count_threshold: 5
normal_count_threshold: 2
pause_timeout_seconds: 300
alert_cooldown_seconds: 600
webhook:
url: "https://receiver.example.com/queue-report"
timeout_seconds: 5.0
people_flow_project
配置文件示例:managed/people_flow_project/config/config.example.yaml
queue:
enabled: true
area: [0.0, 0.0, 1.0, 1.0]
area_mode: "normalized"
queue_time_threshold_seconds: 300
crowded_count_threshold: 5
normal_count_threshold: 2
pause_timeout_seconds: 5
source_id: "queue_cam_01"
webhook:
url: "https://receiver.example.com/queue-report"
timeout_seconds: 5.0
event_log_path: "outputs/rtsp_stream/webhook_events.jsonl"
说明:
queue.area用于限定排队区域,默认[0, 0, 1, 1]表示全画面。queue.area_mode=normalized表示区域坐标按画面宽高归一化。- 两个工程都会先把 webhook 数据写入本地结果文件,再尝试 HTTP POST。
推送时机
- 两个工程都会在每个 30 分钟窗口结束时推送一次
half_hour_report。 store_dwell_alert仍会继续生成本地事件日志;用于对接的窗口报文以本文档的half_hour_report结构为准。
公共字段
两个工程的 webhook 都包含以下公共字段:
| 字段 | 类型 | 说明 |
|---|---|---|
event |
string | 固定为 half_hour_report |
project_type |
string | 工程类型,值为 store_dwell_alert 或 people_flow_project |
source_id |
string | 数据源标识。store_dwell_alert 使用 camera_id,people_flow_project 使用 queue.source_id |
window_start |
string | 窗口开始时间,ISO 8601 |
window_end |
string | 窗口结束时间,ISO 8601 |
queue_metrics |
object | 排队统计主体 |
queue_metrics 结构:
| 字段 | 类型 | 说明 |
|---|---|---|
queue_time_threshold_seconds |
integer | 长等待阈值,当前默认 300 秒 |
over_threshold_count |
integer | 窗口内累计排队时间大于等于阈值的人数 |
under_threshold_count |
integer | 窗口内累计排队时间小于阈值但大于 0 的人数 |
queue_level |
string | few / normal / crowded |
previous_queue_level |
string/null | 上一个窗口的等级 |
status_change |
string | initial / unchanged / queue_increased / queue_decreased / queue_normalized |
people |
array | 当前窗口内参与统计的人员列表 |
queue_metrics.people[] 结构:
| 字段 | 类型 | 说明 |
|---|---|---|
person_id |
string | 人员标识 |
queue_seconds |
integer | 该窗口内累计排队秒数 |
bucket |
string | over_threshold 或 under_threshold |
store_dwell_alert 完整报文
store_dwell_alert 会额外带上门店停留会话明细:
{
"event": "half_hour_report",
"project_type": "store_dwell_alert",
"camera_id": "store_cam_01",
"source_id": "store_cam_01",
"window_start": "2026-05-08T09:00:00+08:00",
"window_end": "2026-05-08T09:30:00+08:00",
"active_customer_count": 3,
"active_customers": [
{
"person_id": "cust_101",
"session_id": "cust_101-s1",
"role": "customer",
"status": "active",
"dwell_seconds": 820,
"window_queue_seconds": 820
},
{
"person_id": "cust_102",
"session_id": "cust_102-s1",
"role": "customer",
"status": "active",
"dwell_seconds": 460,
"window_queue_seconds": 460
}
],
"closed_customers": [
{
"person_id": "cust_103",
"session_id": "cust_103-s1",
"final_dwell_seconds": 260,
"window_queue_seconds": 260
}
],
"staff_seen_count": 1,
"queue_metrics": {
"queue_time_threshold_seconds": 300,
"over_threshold_count": 6,
"under_threshold_count": 2,
"queue_level": "crowded",
"previous_queue_level": "normal",
"status_change": "queue_increased",
"people": [
{
"person_id": "cust_101",
"queue_seconds": 820,
"bucket": "over_threshold"
},
{
"person_id": "cust_102",
"queue_seconds": 460,
"bucket": "over_threshold"
},
{
"person_id": "cust_103",
"queue_seconds": 260,
"bucket": "under_threshold"
}
]
}
}
people_flow_project 完整报文
people_flow_project 会额外带上过线统计和属性统计结果:
{
"event": "half_hour_report",
"project_type": "people_flow_project",
"source_type": "rtsp",
"source": "rtsp://user:password@camera-ip:554/h264/ch1/main/av_stream",
"source_id": "queue_cam_01",
"window_index": 12,
"window_start": "2026-05-08T09:00:00+08:00",
"window_end": "2026-05-08T09:30:00+08:00",
"window_duration_seconds": 1800,
"config_path": "/opt/people_flow_project/config/local.yaml",
"line": {
"coordinates": [0.1, 0.55, 0.9, 0.55],
"mode": "normalized"
},
"total_people": 7,
"age_counts": {
"minor": 1,
"adult": 5,
"senior": 1
},
"gender_counts": {
"male": 4,
"female": 3
},
"unknown_attributes": 2,
"tracks": [
{
"track_id": 1,
"direction": "in",
"age": 26,
"age_bucket": "adult",
"gender": "male",
"samples_used": 3
}
],
"queue_metrics": {
"queue_time_threshold_seconds": 300,
"over_threshold_count": 6,
"under_threshold_count": 2,
"queue_level": "crowded",
"previous_queue_level": "normal",
"status_change": "queue_increased",
"people": [
{
"person_id": "track_12",
"queue_seconds": 810,
"bucket": "over_threshold"
},
{
"person_id": "track_21",
"queue_seconds": 180,
"bucket": "under_threshold"
}
]
}
}
接收方建议
- 按
event + project_type + source_id + window_end做幂等去重。 - 业务判断优先读取
queue_metrics.queue_level和queue_metrics.status_change。 - 如果只关心图片里的需求,最少只需要解析:
source_idwindow_startwindow_endqueue_metrics.over_threshold_countqueue_metrics.under_threshold_countqueue_metrics.queue_levelqueue_metrics.status_change