Files
UPC-Resent/README.md
2026-04-04 21:26:16 +08:00

489 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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,
"keep_alive": true // TCP长连接模式可选默认false
},
{
"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` |
| `keep_alive` | **TCP 专用** 是否保持连接(长连接模式) | `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` 来查找进程,确保系统中没有同名脚本冲突。