# orchards **Repository Path**: bodhifan/orchards ## Basic Information - **Project Name**: orchards - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-01-12 - **Last Updated**: 2026-01-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 🍎 果园机器人监控系统 一个基于 Docker Compose 的分布式果园机器人视频采集和数据监控系统。 ## 🆕 最新版本:v2.0.0 **重大架构升级!** 现在采用更高效的架构: - ✨ **果园节点**:只负责数据转发(资源占用降低 87%) - ✨ **中央服务器**:统一处理所有数据(集中式管理) - ✨ **部署更简单**:配置项减少 60% 📖 查看详细说明: - [架构文档](ARCHITECTURE.md) - [迁移指南](MIGRATION_GUIDE.md)(从 v1.0 升级) - [更新日志](CHANGELOG.md) ## 📋 系统架构(v2.0) ``` 果园1 中央服务器 ├─ 机器人A ──┐ ┌──────────────────┐ ├─ 机器人B ──┼─> UDP转发 ──数据────────>│ 数据处理服务 │ └─ 机器人C ──┘ │ │ - UDP 接收 │ │ │ - 数据解析 │ │ │ - 数据库存储 │ │ │ - WebSocket广播 │ │ └──────────────────┘ │ │ └─> RTMP转发 ──视频────────>│ ↓ 果园2 ┌─────────────┐ ├─ 机器人D ──┐ │ ZLMediaKit │ └─ 机器人E ──┼─> 转发服务 ──> 同上 │ 视频服务器 │ ┘ └─────────────┘ │ ┌──────────────┐ │ PostgreSQL │ │ 数据库 │ └──────────────┘ │ ┌──────────────┐ │ Web 前端 │ └──────────────┘ ``` ## 🎯 核心功能 - ✅ **多果园支持**:每个果园独立部署轻量级转发节点 - ✅ **多机器人支持**:每个果园可接入多个机器人 - ✅ **视频流管理**:RTMP 转发 → ZLMediaKit 统一管理 - ✅ **实时数据推送**:UDP 转发 → 中央处理 → WebSocket 推送 - ✅ **数据持久化**:PostgreSQL 存储所有历史数据 - ✅ **Web 监控界面**:实时显示视频和机器人状态 - 🆕 **集中式处理**:所有数据在中央服务器统一处理 - 🆕 **轻量化部署**:果园节点资源占用 < 256MB ## 🚀 快速开始 ### 前置要求 - Docker 20.10+ - Docker Compose 2.0+ - 中央服务器:至少 4GB 可用内存 - 果园节点:至少 512MB 可用内存 ### 1️⃣ 部署中央服务器 ```bash cd central-server/ # 配置环境变量 cp env.central.example .env nano .env # 修改配置(如数据库密码) # 启动所有服务 docker-compose -f docker-compose-central.yml up -d # 查看日志 docker-compose -f docker-compose-central.yml logs -f ``` ### 2️⃣ 部署果园转发节点 ```bash cd orchard-relay/ # 配置环境变量 cp env.orchard.example .env nano .env # 配置果园ID和中央服务器地址 # 启动转发服务 docker-compose -f docker-compose-orchard.yml up -d # 查看日志 docker-compose -f docker-compose-orchard.yml logs -f ``` ### 3️⃣ 访问前端界面 浏览器打开:http://中央服务器IP:3000 ### 4️⃣ 测试机器人推流 使用提供的测试脚本模拟机器人: ```bash # 进入测试目录 cd test # 安装依赖(仅首次) pip install -r requirements.txt # 运行UDP数据推送测试 python test_udp_data.py --orchard orchard1 --robot robotA # 运行视频推流测试(需要准备测试视频文件) python test_video_stream.py --orchard orchard1 --robot robotA ``` ## 📦 服务组件 ### 中央服务器(central-server/) #### 1. PostgreSQL 数据库 - **端口**: 54322 (映射到容器内 5432) - **用户**: robot / robot123 - **数据库**: robot_db #### 2. ZLMediaKit 视频服务器 - **RTMP 端口**: 1935(接收各果园视频) - **HTTP-FLV/HLS 端口**: 8080 - **RTSP 端口**: 8554 #### 3. 数据处理服务(🆕 v2.0) - **UDP 端口**: 5006(接收各果园数据) - **WebSocket**: 8765(供前端连接) - **功能**:接收、解析、存储、广播所有果园数据 #### 4. REST API 服务 - **HTTP 端口**: 5000 - **功能**:查询果园、机器人、数据等信息 #### 5. 前端 Web 服务 - **HTTP 端口**: 3000 - **功能**:视频播放、数据可视化 ### 果园转发节点(orchard-relay/) #### 1. UDP 转发服务(🆕 v2.0) - **UDP 端口**: 5006(接收本地机器人数据) - **功能**:转发数据到中央服务器 - **资源占用**: < 256MB #### 2. RTMP 转发服务 - **RTMP 端口**: 1936(接收本地机器人视频) - **功能**:转发视频到中央服务器 ## 🔧 配置说明 ### 添加新果园 新架构下,添加果园非常简单: 1. **在新果园部署转发节点**: ```bash cd orchard-relay/ # 配置新果园的环境变量 cp env.orchard.example .env nano .env # 设置果园唯一ID ORCHARD_ID=orchard3 # 设置中央服务器地址 CENTRAL_SERVER_HOST=123.45.67.89 ZLM_HOST=123.45.67.89 # 启动服务 docker-compose -f docker-compose-orchard.yml up -d ``` 2. **在数据库中注册果园**: ```sql -- 在中央服务器数据库中添加果园信息 INSERT INTO orchards (name, lon, lat, description, ws_host, ws_port) VALUES ('orchard3', 116.4, 39.9, '新果园', 'data-processor', 8765); ``` 就这么简单!无需修改中央服务器配置。 ### 添加机器人 在数据库中添加机器人信息即可: ```sql -- 在中央服务器数据库中添加机器人 INSERT INTO robots (orchard_id, name, model) SELECT orchard_id, 'robotD', 'Model-X' FROM orchards WHERE name = 'orchard1'; ``` ## 📡 机器人接入 ### RTMP 视频推流 ```bash # 机器人使用 FFmpeg 推送视频到果园转发节点 ffmpeg -i /dev/video0 \ -c:v libx264 -preset ultrafast \ -f flv rtmp://<果园转发节点IP>:1936/live/orchard1/robotA/sensor1 ``` **流名称格式**:`orchard_id/robot_id/sensor_id` ### UDP 状态数据 机器人发送 28字节二进制数据包到果园转发节点(使用机器人协议): ```python import socket from robot_protocol import RobotProtocol # 打包数据 packet = RobotProtocol.pack_robot_data( robot_id=1, # 机器人ID (1=robotA, 2=robotB, 3=robotC) robot_status=1, # 运行状态 frame_index=100, # 帧序号 left_tree_index=10, # 左树编号 right_tree_index=11, # 右树编号 hour=14, minute=30, second=45, lat_degree=39, lat_minute=54, lat_second=30, lat_direction=0x4E, # 北纬 lon_degree=116, lon_minute=23, lon_second=15, lon_direction=0x45, # 东经 azimuth=180, # 方位角 velocity=15, # 速度 (1.5 m/s) eyepoint_height=150, # 摄像头高度 (1.5 m) bat_voltage=240, # 电池电压 (24.0 V) soc=85 # 电量 (85%) ) # 发送到果园转发节点 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.sendto(packet, ('<果园转发节点IP>', 5006)) ``` 数据包会被自动添加果园ID并转发到中央服务器处理。 ## 📊 数据库表结构 ### robot_data - 机器人数据表 ```sql id SERIAL PRIMARY KEY orchard_id TEXT NOT NULL robot_id TEXT NOT NULL timestamp TIMESTAMPTZ NOT NULL data JSONB NOT NULL ``` ### orchards - 果园信息表 ```sql id SERIAL PRIMARY KEY orchard_id TEXT UNIQUE NOT NULL name TEXT NOT NULL location TEXT ``` ### robots - 机器人信息表 ```sql id SERIAL PRIMARY KEY robot_id TEXT UNIQUE NOT NULL orchard_id TEXT NOT NULL name TEXT NOT NULL status TEXT DEFAULT 'offline' ``` ## 🔍 故障排查 ### 视频流无法播放 1. **检查中央服务器 ZLMediaKit**: ```bash docker logs central_zlmediakit curl http://中央服务器:8080/index/api/getMediaList ``` 2. **检查果园 RTMP 转发服务**: ```bash docker logs orchard_rtmp_orchard1 ``` 3. **测试网络连通性**: ```bash # 在果园服务器测试到中央服务器的连接 ping 中央服务器IP telnet 中央服务器IP 1935 ``` ### UDP 数据未接收 1. **检查中央数据处理服务日志**: ```bash docker logs -f central_data_processor # 应该看到:📥 收到数据包 ... 来自果园 xxx ``` 2. **检查果园 UDP 转发服务日志**: ```bash docker logs -f orchard_udp_forwarder_orchard1 # 应该看到:📥 收到数据包 ... 来自本地 # 应该看到:📤 已转发数据到 ... ``` 3. **测试 UDP 连通性**: ```bash # 在果园服务器测试到中央服务器的 UDP nc -u 中央服务器IP 5006 ``` ### WebSocket 连接失败 前端现在连接到中央服务器的数据处理服务: ```bash # 检查中央数据处理服务 docker logs central_data_processor # 测试 WebSocket 连接 wscat -c ws://中央服务器:8765 ``` ### 数据库连接问题 ```bash # 进入中央服务器数据库容器 docker exec -it central_db psql -U robot -d robot_db # 查询最新数据 SELECT * FROM robot_data ORDER BY timestamp DESC LIMIT 10; ``` ## 📈 监控和维护 ### 查看服务状态 ```bash docker-compose ps ``` ### 查看资源使用 ```bash docker stats ``` ### 数据库备份 ```bash docker exec robot_db pg_dump -U robot robot_db > backup.sql ``` ### 清理旧数据 ```sql -- 清理30天前的数据 SELECT cleanup_old_robot_data(30); ``` ## 🛠️ 开发调试 ### 修改代码后重新构建 ```bash # 重新构建特定服务 docker-compose build relay_orchard1 # 重启服务 docker-compose up -d relay_orchard1 ``` ### 查看实时日志 ```bash # 所有服务 docker-compose logs -f # 特定服务 docker-compose logs -f relay_orchard1 ``` ## 📝 API 接口 ### ZLMediaKit API - 获取流列表:`GET http://localhost:8080/index/api/getMediaList` - 关闭流:`GET http://localhost:8080/index/api/close_stream?app=live&stream=orchard1/robotA` ### WebSocket 消息格式 客户端接收: ```json { "orchard_id": "orchard1", "robot_id": "robotA", "timestamp": "2026-01-12T10:30:00", "data": { "position": {"x": 1.5, "y": 2.3, "z": 0.0}, "battery": 85, "status": "working" } } ``` ## 🔐 安全建议 1. 修改默认数据库密码(在 docker-compose.yml 中) 2. 配置 ZLMediaKit 的 API secret 3. 生产环境使用 HTTPS/WSS 4. 配置防火墙规则限制端口访问 5. 定期备份数据库 ## 📄 许可证 MIT License ## 👥 贡献 欢迎提交 Issue 和 Pull Request! ## 📞 联系方式 如有问题,请提交 Issue 或联系维护者。