Kaynağa Gözat

docs: 新增双机16路部署说明与README

- docs/dual_board.md: 架构/编号规则/两台配置示例/网页切换A-B/性能带宽/部署检查清单/验证与故障排查
- README.md: 项目简介、目录结构、编译运行、主要配置、文档入口
dev 8 saat önce
ebeveyn
işleme
09a543fbeb
2 değiştirilmiş dosya ile 281 ekleme ve 0 silme
  1. 62 0
      README.md
  2. 219 0
      docs/dual_board.md

+ 62 - 0
README.md

@@ -0,0 +1,62 @@
+# ZoneAlarm — 视频监控电子围栏 + 姿态识别
+
+基于 RK3588(RKNN NPU + MPP 硬解)的 AI 视频监控系统,支持:
+
+- **目标识别**(YOLOv5s)与电子围栏报警、继电器联动
+- **姿态识别**(YOLOv8-pose):跌倒、倒地、举手呼救、异常蹲坐、半躺、手近嘴部、疲劳瞌睡、长时间静止、疑似离岗
+- **报警历史**(围栏 + 姿态统一列表,含截图)
+- **Web 管理**:实时监控、电子围栏、报警历史、继电器控制、通道管理、系统设置
+- **手机 H5**:视频预览 + 报警历史(`/mobile.html`)
+- **HDMI 直出**:4×4 宫格全屏显示
+- **双机 16 路单屏**:主从角色可切换(详见 [docs/dual_board.md](docs/dual_board.md))
+
+## 目录结构
+
+```
+src/            源码
+web/            Web 页面(index.html / mobile.html / preview.html / config.html)
+config/         config.json、fences.json
+models/         RKNN 模型(.rknn 不入库)
+scripts/        模型转换、RTSP 端口转发
+deploy/         打包/安装脚本
+docs/           文档
+data/           报警数据库与截图(不入库)
+```
+
+## 编译
+
+```bash
+./build.sh
+```
+
+## 运行
+
+```bash
+./start.sh
+# 或
+./build/zone_alarm config/config.json
+# systemd
+systemctl restart zone_alarm
+```
+
+## 主要配置(config/config.json)
+
+| 项 | 说明 |
+|---|---|
+| `model_path` / `pose_model_path` | 目标/姿态 RKNN 模型 |
+| `target_enabled` / `pose_enabled` | 是否启用目标/姿态识别 |
+| `skip_frames` | 每 N+1 帧推理一次 |
+| `display_fps` | 本机显示帧生成帧率 |
+| `grid_output` / `steel_output` | HDMI 网格/钢包位输出 |
+| `node_role` / `local_base` / `peer` | 单机/主从角色与对端 |
+| `watchdog_sec` | 主循环卡死看门狗 |
+
+## 文档
+
+- [双机 16 路单屏部署说明](docs/dual_board.md)
+
+## 访问
+
+- PC:`http://<板子IP>:8080/`
+- 手机:`http://<板子IP>:8080/mobile.html`
+- 默认账号:`admin / admin`

+ 219 - 0
docs/dual_board.md

@@ -0,0 +1,219 @@
+# 双机 16 路单屏部署说明
+
+本系统支持用 **两台 RK3588** 组成 16 路视频监控,并通过一块 HDMI 屏幕以 4×4 宫格显示。
+两台板运行**同一份程序**,仅配置不同;`master` / `slave` 角色可在网页中切换(重启生效)。
+
+---
+
+## 1. 架构
+
+```
+                千兆交换机
+   ┌───────────────┴───────────────┐
+8×摄像头(子码流)                 8×摄像头(子码流)
+   │                                │
+ 节点2 (slave, 无屏)            节点1 (master, HDMI)
+ ·8路解码 + 姿态推理              ·8路解码 + 姿态推理
+ ·输出 /stream 供对端拉取          ·拉取对端8路画面 → 4×4 一屏
+ ·本地报警入库                     ·本地报警 + 聚合对端报警
+                                   ·Web / 手机 APP 统一入口
+```
+
+- **master**:接 HDMI 屏,负责 16 宫格显示、Web/手机访问、报警聚合。
+- **slave**:不接屏(也可接),专注采集与推理,暴露 `/stream`、报警 API 供对端读取。
+- 两台各自把报警写入本地 SQLite;master 在查询时合并两台数据。
+
+---
+
+## 2. 通道编号规则(重要)
+
+每台板有一个固定不变的 `local_base`:
+
+| 板子 | `local_base` | 拥有通道 |
+|---|---|---|
+| 节点1 | `0` | CH0 ~ CH7 |
+| 节点2 | `8` | CH8 ~ CH15 |
+
+`local_base` **与角色无关**:无论谁当 master,编号都不变。
+角色只决定“谁显示、谁聚合”。
+
+> 界面中的通道号从 0 开始(CH0~CH15)。
+
+---
+
+## 3. 配置示例
+
+### 3.1 节点1(master,接屏)
+
+`config/config.json` 关键项:
+
+```json
+{
+  "node_role": "master",
+  "local_base": 0,
+  "grid_output": true,
+  "steel_output": false,
+  "enable_bucket": false,
+  "display_fps": 12,
+  "watchdog_sec": 120,
+
+  "peer": {
+    "enabled": true,
+    "host": "192.168.1.232",
+    "port": 8080,
+    "username": "admin",
+    "password": "admin",
+    "local_base": 8,
+    "count": 8,
+    "fps": 8
+  },
+
+  "rtsp": [
+    { "id": 0, "name": "cam1", "url": "rtsp://user:pass@192.168.1.121:554/Streaming/Channels/102" },
+    { "id": 1, "name": "cam2", "url": "rtsp://user:pass@192.168.1.122:554/Streaming/Channels/102" },
+    { "id": 2, "name": "cam3", "url": "rtsp://user:pass@192.168.1.123:554/Streaming/Channels/102" },
+    { "id": 3, "name": "cam4", "url": "rtsp://user:pass@192.168.1.124:554/Streaming/Channels/102" },
+    { "id": 4, "name": "cam5", "url": "rtsp://user:pass@192.168.1.125:554/Streaming/Channels/102" },
+    { "id": 5, "name": "cam6", "url": "rtsp://user:pass@192.168.1.126:554/Streaming/Channels/102" },
+    { "id": 6, "name": "cam7", "url": "rtsp://user:pass@192.168.1.127:554/Streaming/Channels/102" },
+    { "id": 7, "name": "cam8", "url": "rtsp://user:pass@192.168.1.128:554/Streaming/Channels/102" }
+  ]
+}
+```
+
+### 3.2 节点2(slave,无屏)
+
+```json
+{
+  "node_role": "slave",
+  "local_base": 8,
+  "grid_output": false,
+  "steel_output": false,
+  "enable_bucket": false,
+  "peer": { "enabled": false },
+
+  "rtsp": [
+    { "id": 0, "name": "cam9",  "url": "rtsp://user:pass@192.168.1.129:554/Streaming/Channels/102" },
+    { "id": 1, "name": "cam10", "url": "rtsp://user:pass@192.168.1.130:554/Streaming/Channels/102" },
+    { "id": 2, "name": "cam11", "url": "rtsp://user:pass@192.168.1.131:554/Streaming/Channels/102" },
+    { "id": 3, "name": "cam12", "url": "rtsp://user:pass@192.168.1.132:554/Streaming/Channels/102" },
+    { "id": 4, "name": "cam13", "url": "rtsp://user:pass@192.168.1.133:554/Streaming/Channels/102" },
+    { "id": 5, "name": "cam14", "url": "rtsp://user:pass@192.168.1.134:554/Streaming/Channels/102" },
+    { "id": 6, "name": "cam15", "url": "rtsp://user:pass@192.168.1.135:554/Streaming/Channels/102" },
+    { "id": 7, "name": "cam16", "url": "rtsp://user:pass@192.168.1.136:554/Streaming/Channels/102" }
+  ]
+}
+```
+
+### 3.3 配置项说明
+
+| 配置项 | 说明 |
+|---|---|
+| `node_role` | `standalone` / `master` / `slave` |
+| `local_base` | 本机通道全局起点,节点1=0,节点2=8 |
+| `peer.enabled` | master 才需要开启 |
+| `peer.host` / `peer.port` | 对端板 IP 与 Web 端口 |
+| `peer.username` / `peer.password` | 对端登录凭据(用于拉流/报警/截图) |
+| `peer.local_base` | 对端通道起点(节点1填8,节点2填0) |
+| `peer.count` | 拉取对端通道数量(默认8) |
+| `peer.fps` | 拉取对端画面帧率(默认8) |
+| `display_fps` | 本机显示帧生成帧率(默认12) |
+| `watchdog_sec` | 主循环卡死看门狗,超时自动重启(默认120,0=禁用) |
+
+---
+
+## 4. 网页切换 A/B 角色(谁当主)
+
+1. 浏览器登录该板 Web(默认 `admin/admin`)。
+2. 进入 **系统设置 → 双机模式**。
+3. 设置:
+   - 本机角色:`主节点` 或 `从节点` / `单机`
+   - 本机通道起点:节点1=`0`,节点2=`8`
+   - 对端 IP / 端口 / 用户名 / 密码
+   - 对端通道起点:与对端 `local_base` 一致
+4. 保存后**重启生效**(页面会提示)。
+5. 把 HDMI 屏接到新的 master 板上。
+
+> 也可直接修改 `config/config.json` 后重启服务。
+
+重启命令:
+
+```bash
+systemctl restart zone_alarm
+```
+
+---
+
+## 5. 性能与带宽
+
+基于 RK3588 实测(8 路/台,**仅姿态识别**,子码流 1280×720,skip_frames=9):
+
+| 项 | 参考值 |
+|---|---|
+| 单板 CPU | 约 80 ~ 130% |
+| NPU | 三核各约 60 ~ 90% |
+| 跨机流量(master ← slave) | 约 8 Mbps(8 路 JPEG@8fps) |
+| 千兆交换机 | 充裕 |
+
+建议:
+
+- **全部使用子码流**(`.../Channels/102`)。
+- 16 路**仅姿态**;如同时开目标识别,建议降 `pose_input_size`(640→416)或增大 `skip_frames`。
+- 非重点通道可在姿态配置里关闭。
+
+---
+
+## 6. 部署检查清单
+
+- [ ] 两台板在同一千兆交换机、同网段,互相能 `ping` 通。
+- [ ] 两台板 **NTP 对时**(否则报警合并排序会乱)。
+- [ ] 节点1 `local_base=0`、节点2 `local_base=8`,且互不重复。
+- [ ] master 的 `peer.host` 指向对端 IP(不能填本机同一端口)。
+- [ ] 两台 Web 登录凭据与 `peer.username/password` 一致。
+- [ ] HDMI 接在 master 上。
+- [ ] 花生壳/外网访问**只需映射 master**。
+- [ ] 防火墙放行 8080(或配置的 `web_port`)。
+- [ ] 若使用工位/钢包位功能,请确认 `enable_bucket` 与 `local_base` 不冲突(16 路场景建议关闭)。
+
+---
+
+## 7. 验证方法
+
+在 master 上登录后检查:
+
+```bash
+# 角色与通道(应看到本机8 + 对端8,共16路)
+curl -s -b cookies.txt http://<master-ip>:8080/api/status
+
+# 对端通道画面(用于确认跨机拉流)
+curl -s -b cookies.txt -o test.jpg http://<master-ip>:8080/stream/8
+
+# 合并后的姿态报警
+curl -s -b cookies.txt "http://<master-ip>:8080/api/pose/alarms?limit=5"
+```
+
+- `/api/status` 中 `"remote": true` 的通道来自对端,`online` 为在线状态。
+- 报警条目带 `"src": "local"` 或 `"peer"`,用于区分来源与删除分发。
+
+---
+
+## 8. 故障排查
+
+| 现象 | 排查 |
+|---|---|
+| 对端通道一直离线 | 检查 `peer.host/port`、网络、对端 `node_role=slave` 且 Web 可访问;查看 master 日志 `[Peer]` |
+| 对端通道画面黑/无数据 | 确认对端已加载对应摄像头且 `online`;对端 `/stream/<其全局id>` 是否可访问 |
+| 报警不合并 | 确认 master `peer.enabled=true`;对端时间是否同步;检查 `peer.local_base` 是否与对端 `local_base` 一致 |
+| 对端截图打不开 | 检查 `/api/peer/image/<文件名>`;确认对端 `data/screenshots` 存在该文件 |
+| 保存角色后不生效 | 角色需**重启**生效;确认写入的是运行目录下的 `config/config.json` |
+| 对端地址填成本机 | 程序会提示并禁用对端(防止状态查询递归死锁) |
+| 画面卡顿 | 检查 master CPU/NPU;适当降低 `peer.fps` / `display_fps`,或增大 `skip_frames` |
+| 服务反复重启 | 查看 `journalctl -u zone_alarm`;看门狗触发说明主循环卡死(NPU 异常会自动恢复) |
+
+---
+
+## 9. 单机与双机切换
+
+- **单机(8 路)**:`node_role=standalone`,`peer.enabled=false`。
+- **双机(16 路)**:一台 `master` + 一台 `slave`,配置如上。
+- 切换到双机或互换角色:只需调整 `node_role` / `peer` 并重启,**无需重新编译**。