# UPC Resent - 自动化控制设备指令转发系统 基于配置驱动的代码生成系统,支持 TCP 和 UDP 协议,监听端口接收外部指令,转换为 Modbus TCP/UDP 协议发送到控制设备(继电器/PLC等)。 ## 项目结构 ``` upc_resent/ ├── config/ │ └── devices.json # 设备配置文件(唯一需要修改的文件) ├── templates/ # 代码模板目录 │ ├── listener_tcp.py.tpl # TCP监听服务模板 │ ├── listener_udp.py.tpl # UDP监听服务模板 │ ├── crond_tcp.py.tpl # TCP保活检查模板 │ ├── crond_udp.py.tpl # UDP保活检查模板 │ ├── sender_tcp.py.tpl # TCP发送模块模板 │ ├── sender_udp.py.tpl # UDP发送模块模板 │ └── control.sh.tpl # 控制脚本模板 ├── scripts/ │ └── generate.py # 代码生成器 ├── bin/ # 生成的监听服务文件(自动生成) │ ├── sender_tcp.py # TCP发送模块 │ ├── sender_udp.py # UDP发送模块 │ └── {device_id}.py # 各设备监听服务 ├── crond/ # 生成的保活检查文件(自动生成) ├── log/ # 日志目录 ├── control.sh # 服务控制脚本(自动生成) ├── crontab.txt # 定时任务配置(自动生成) └── cutlog.sh # 日志清理脚本 ``` ## 快速开始 ### 1. 克隆仓库 ```bash git clone https://git.yuyujing.cn/zj/UPC-Resent/ cd UPC-Resent ``` ### 2. 配置设备 编辑 `config/devices.json`: ```json { "global": { "tms_server_ip": "192.168.8.9", "python_path": "/usr/bin/python3", "base_dir": "/opt/upc_resent" }, "command_sets": { "set1": { "name": "标准8路控制", "commands": { "open1": "000100000008010F006400010001", "close1": "000100000008010F006400010000", "open2": "000100000008010F006500010001", "close2": "000100000008010F006500010000" } } }, "devices": [ { "id": "dev1", "name": "设备1-TCP", "listen_protocol": "tcp", // 监听协议: tcp 或 udp "device_protocol": "tcp", // 设备协议: tcp 或 udp "command_set": "set1", // 使用的指令集 "upc_ip": "192.168.8.73", "upc_port": 502, "listen_port": 10079, "enabled": true }, { "id": "dev2", "name": "设备2-UDP", "listen_protocol": "udp", "device_protocol": "udp", "command_set": "set1", "upc_ip": "192.168.8.200", "upc_port": 502, "listen_port": 10080, "enabled": true } ] } ``` ### 3. 生成代码 ```bash # 检查配置是否正确 python3 scripts/generate.py --check # 生成代码 python3 scripts/generate.py ``` ### 4. 部署与启动 ```bash # 查看服务状态 ./control.sh status # 启动所有服务 ./control.sh start # 停止所有服务 ./control.sh stop # 重启所有服务 ./control.sh restart # 配置定时任务(保活) crontab crontab.txt ``` ## 配置文件详解 ### `config/devices.json` #### 全局配置 (global) | 参数 | 说明 | 示例 | |-----|------|-----| | `tms_server_ip` | 本机监听IP,接收外部指令 | `"192.168.8.9"` | | `python_path` | Python3 解释器路径 | `"/usr/bin/python3"` | | `base_dir` | 项目部署路径 | `"/opt/upc_resent"` | #### 设备配置 (devices) | 参数 | 说明 | 示例 | |-----|------|-----| | `id` | 设备唯一标识(用于文件名) | `"dev1"` | | `name` | 设备名称(用于日志显示) | `"设备1-TCP"` | | `listen_protocol` | 客户端连接协议:`tcp` 或 `udp` | `"tcp"` / `"udp"` | | `device_protocol` | 设备通信协议:`tcp` 或 `udp` | `"tcp"` / `"udp"` | | `command_set` | 使用的指令集ID | `"set1"` | | `upc_ip` | 控制设备的IP地址 | `"192.168.8.73"` | | `upc_port` | 控制设备的端口(Modbus默认502) | `502` | | `listen_port` | 本机监听端口(每个设备需不同) | `10079` | | `enabled` | 是否启用该设备 | `true` / `false` | **协议组合说明**: - `listen_protocol`: 主机监听客户端连接的协议(客户端 -> 主机) - `device_protocol`: 主机与设备通信的协议(主机 -> 设备) - 支持任意组合:TCP->TCP、UDP->UDP、TCP->UDP、UDP->TCP **配置示例**: ```json // 场景1: 客户端TCP -> 主机TCP -> 设备TCP { "id": "dev1", "name": "设备1-纯TCP", "listen_protocol": "tcp", "device_protocol": "tcp", "upc_ip": "192.168.8.73", "upc_port": 502, "listen_port": 10079 } // 场景2: 客户端TCP -> 主机UDP -> 设备UDP(协议转换) { "id": "dev2", "name": "设备2-TCP转UDP", "listen_protocol": "tcp", "device_protocol": "udp", "upc_ip": "192.168.8.200", "upc_port": 502, "listen_port": 10080 } // 场景3: 客户端UDP -> 主机TCP -> 设备TCP(协议转换) { "id": "dev3", "name": "设备3-UDP转TCP", "listen_protocol": "udp", "device_protocol": "tcp", "upc_ip": "192.168.8.201", "upc_port": 502, "listen_port": 10081 } ``` #### 指令集定义 (command_sets) 支持为不同设备配置不同的指令集: ```json { "command_sets": { "set1": { "name": "标准8路控制", "commands": { "open1": "000100000008010F006400010001", "close1": "000100000008010F006400010000", "open2": "000100000008010F006500010001", "close2": "000100000008010F006500010000" } }, "set2": { "name": "4路精简控制", "commands": { "open1": "000100000008010F006400010001", "close1": "000100000008010F006400010000", "openall": "000100000008010F00640004000F", "closeall": "000100000008010F006400040000" } } } } ``` 设备通过 `command_set` 字段指定使用的指令集: ```json { "id": "dev1", "command_set": "set1" } ``` #### 指令映射 (mappings) ```json { "mappings": { "open": "openall4", "close": "closeall4", "guanggao-guan": "closeall4" } } ``` ## TCP vs UDP 差异 | 特性 | TCP | UDP | |-----|-----|-----| | 连接方式 | 面向连接 | 无连接 | | 可靠性 | 可靠传输 | 尽力传输 | | 响应 | 有确认响应 | 可选响应(可能超时) | | 适用场景 | 可靠性要求高 | 实时性要求高 | | 保活检查 | 端口连通性检查 | 进程状态检查 | ## 如何适配自己的设备 ### 场景1:添加 TCP 设备(客户端TCP -> 主机TCP -> 设备TCP) ```json { "devices": [ { "id": "dev_tcp", "name": "TCP设备", "listen_protocol": "tcp", "device_protocol": "tcp", "upc_ip": "192.168.1.100", "upc_port": 502, "listen_port": 10081, "enabled": true } ] } ``` ### 场景2:添加 UDP 设备(客户端UDP -> 主机UDP -> 设备UDP) ```json { "devices": [ { "id": "dev_udp", "name": "UDP设备", "listen_protocol": "udp", "device_protocol": "udp", "upc_ip": "192.168.1.200", "upc_port": 502, "listen_port": 10082, "enabled": true } ] } ``` ### 场景3:协议转换(客户端TCP -> 主机UDP -> 设备UDP) ```json { "devices": [ { "id": "dev_tcp2udp", "name": "TCP转UDP设备", "listen_protocol": "tcp", "device_protocol": "udp", "upc_ip": "192.168.1.201", "upc_port": 502, "listen_port": 10083, "enabled": true } ] } ``` ### 场景4:协议转换(客户端UDP -> 主机TCP -> 设备TCP) ```json { "devices": [ { "id": "dev_udp2tcp", "name": "UDP转TCP设备", "listen_protocol": "udp", "device_protocol": "tcp", "upc_ip": "192.168.1.202", "upc_port": 502, "listen_port": 10084, "enabled": true } ] } ``` ### 场景5:不同设备使用不同指令集 ```json { "command_sets": { "set1": { "name": "8路控制", "commands": { "open1": "000100000008010F006400010001", "close1": "000100000008010F006400010000", "open8": "000100000008010F006B00010001", "close8": "000100000008010F006B00010000" } }, "set2": { "name": "4路控制", "commands": { "open1": "000100000008010F006400010001", "close1": "000100000008010F006400010000", "openall": "000100000008010F00640004000F", "closeall": "000100000008010F006400040000" } } }, "devices": [ { "id": "dev1", "name": "8路设备", "command_set": "set1", "upc_ip": "192.168.1.100" }, { "id": "dev2", "name": "4路设备", "command_set": "set2", "upc_ip": "192.168.1.200" } ] } ``` ### 场景6:禁用某个设备 ```json { "devices": [ { "id": "dev2", "enabled": false } ] } ``` ## 测试指令发送 ### TCP 设备测试 ```bash # 向TCP设备发送开灯指令 echo "open1" | nc 192.168.8.9 10079 # 向TCP设备发送全关指令 echo "close" | nc 192.168.8.9 10079 ``` ### UDP 设备测试 ```bash # 向UDP设备发送开灯指令 echo "open1" | nc -u 192.168.8.9 10080 # 向UDP设备发送全关指令 echo "close" | nc -u 192.168.8.9 10080 # 使用 socat 测试 UDP echo "open1" | socat - UDP:192.168.8.9:10080 ``` ## 支持的指令列表 | 外部指令 | 内部指令 | 功能 | |---------|---------|------| | `open` | `openall4` | 1-4路全开 | | `close` | `closeall4` | 1-4路全关 | | `open1`~`open8` | `open1`~`open8` | 第N路开 | | `close1`~`close8` | `close1`~`close8` | 第N路关 | | `guanggao-guan` | `closeall4` | 广告关闭(全关) | ## Modbus 指令格式 本项目支持 Modbus TCP/UDP 协议,指令为16进制字符串: ``` 示例:000100000008010F006400010001 │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └── 数据值 (01=开, 00=关) │ │ │ │ │ │ │ │ │ └──── 寄存器数量 │ │ │ │ │ │ │ │ └─────── 起始地址 (64=100) │ │ │ │ │ │ │ └────────── 功能码 (0F=写多个线圈) │ │ │ │ │ │ └──────────── 单元标识 │ │ │ │ └───────────────── 协议标识 │ │ │ └─────────────────── 长度 │ └─────────────────────── 事务标识 └────────────────────────── 事务标识 ``` ## 代码生成器用法 ```bash # 检查配置是否正确 python3 scripts/generate.py --check # 生成代码 python3 scripts/generate.py # 查看帮助 python3 scripts/generate.py --help ``` ## 服务控制脚本 `control.sh` 提供以下命令: | 命令 | 说明 | |-----|------| | `start` | 启动所有服务 | | `stop` | 停止所有服务 | | `restart` | 重启所有服务 | | `status` | 查看服务运行状态 | 示例: ```bash ./control.sh status ./control.sh start ./control.sh stop ./control.sh restart ``` ## 日志文件 | 文件 | 说明 | |-----|------| | `log/{device_id}.log` | 设备监听服务的日志 | | `log/crond-{device_id}.log` | 保活检查的日志 | 日志自动轮转:每天清理7天前的日志。 ## 注意事项 1. **不要直接修改** `bin/`、`crond/` 和 `control.sh`,这些文件是自动生成的,重新生成时会覆盖。 2. **修改配置后必须重新运行** `python3 scripts/generate.py` 才能生效。 3. 确保每个设备的 `listen_port` 不冲突,无论 TCP 还是 UDP,端口都不能重复。 4. UDP 是无连接协议,设备可能不会返回响应,这是正常现象。 5. 部署到生产环境前,请将 `base_dir` 修改为实际的部署路径(如 `/opt/upc_resent`)。 6. 控制脚本使用 `pgrep` 来查找进程,确保系统中没有同名脚本冲突。