“zj” acf0306080 feat: sender 模板支持字符串和16进制两种格式发送
- 添加 is_valid_hex() 函数检测16进制格式
- 有效的16进制(偶数长度+0-9a-fA-F)按 bytes.fromhex() 发送
- 非16进制字符串按 UTF-8 编码直接发送
- 日志中标注发送类型 (hex/string)
2026-04-05 14:49:07 +08:00
2026-04-04 22:47:48 +08:00
2026-04-04 22:47:48 +08:00
1
2026-03-22 17:17:44 +08:00
2026-04-04 21:26:16 +08:00

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. 克隆仓库

git clone https://git.yuyujing.cn/zj/UPC-Resent/
cd UPC-Resent

2. 配置设备

编辑 config/devices.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. 生成代码

# 检查配置是否正确
python3 scripts/generate.py --check

# 生成代码
python3 scripts/generate.py

4. 部署与启动

# 查看服务状态
./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 客户端连接协议:tcpudp "tcp" / "udp"
device_protocol 设备通信协议:tcpudp "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

配置示例

// 场景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)

支持为不同设备配置不同的指令集:

{
  "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 字段指定使用的指令集:

{
  "id": "dev1",
  "command_set": "set1"
}

指令映射 (mappings)

{
  "mappings": {
    "open": "openall4",
    "close": "closeall4",
    "guanggao-guan": "closeall4"
  }
}

TCP vs UDP 差异

特性 TCP UDP
连接方式 面向连接 无连接
可靠性 可靠传输 尽力传输
响应 有确认响应 可选响应(可能超时)
适用场景 可靠性要求高 实时性要求高
保活检查 端口连通性检查 进程状态检查

如何适配自己的设备

场景1添加 TCP 设备客户端TCP -> 主机TCP -> 设备TCP

{
  "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

{
  "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

{
  "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

{
  "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不同设备使用不同指令集

{
  "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禁用某个设备

{
  "devices": [
    {
      "id": "dev2",
      "enabled": false
    }
  ]
}

测试指令发送

TCP 设备测试

# 向TCP设备发送开灯指令
echo "open1" | nc 192.168.8.9 10079

# 向TCP设备发送全关指令
echo "close" | nc 192.168.8.9 10079

UDP 设备测试

# 向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=写多个线圈)
       │  │ │ │ │  │ └──────────── 单元标识
       │  │ │ │ └───────────────── 协议标识
       │  │ │ └─────────────────── 长度
       │  └─────────────────────── 事务标识
       └────────────────────────── 事务标识

代码生成器用法

# 检查配置是否正确
python3 scripts/generate.py --check

# 生成代码
python3 scripts/generate.py

# 查看帮助
python3 scripts/generate.py --help

服务控制脚本

control.sh 提供以下命令:

命令 说明
start 启动所有服务
stop 停止所有服务
restart 重启所有服务
status 查看服务运行状态

示例:

./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 来查找进程,确保系统中没有同名脚本冲突。

Description
基于配置驱动的代码生成系统,支持 TCP 和 UDP 协议,监听端口接收外部指令,转换为 Modbus TCP/UDP 协议发送到控制设备(继电器/PLC等)。
Readme 127 KiB
Languages
Smarty 65%
Python 34.4%
Shell 0.6%