自定义映射
This commit is contained in:
184
README.md
184
README.md
@@ -42,11 +42,24 @@ upc_resent/
|
||||
"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",
|
||||
"protocol": "tcp", // 协议类型: tcp 或 udp
|
||||
"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,
|
||||
@@ -55,7 +68,9 @@ upc_resent/
|
||||
{
|
||||
"id": "dev2",
|
||||
"name": "设备2-UDP",
|
||||
"protocol": "udp", // 使用UDP协议
|
||||
"listen_protocol": "udp",
|
||||
"device_protocol": "udp",
|
||||
"command_set": "set1",
|
||||
"upc_ip": "192.168.8.200",
|
||||
"upc_port": 502,
|
||||
"listen_port": 10080,
|
||||
@@ -112,26 +127,93 @@ crontab crontab.txt
|
||||
|-----|------|-----|
|
||||
| `id` | 设备唯一标识(用于文件名) | `"dev1"` |
|
||||
| `name` | 设备名称(用于日志显示) | `"设备1-TCP"` |
|
||||
| `protocol` | 协议类型:`tcp` 或 `udp` | `"tcp"` / `"udp"` |
|
||||
| `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` |
|
||||
|
||||
#### 指令定义 (commands)
|
||||
**协议组合说明**:
|
||||
- `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",
|
||||
"openall4": "000100000008010F00640004000F",
|
||||
"closeall4": "000100000008010F006400040000"
|
||||
"open2": "000100000008010F006500010001",
|
||||
"close2": "000100000008010F006500010000"
|
||||
}
|
||||
},
|
||||
"set2": {
|
||||
"name": "4路精简控制",
|
||||
"commands": {
|
||||
"open1": "000100000008010F006400010001",
|
||||
"close1": "000100000008010F006400010000",
|
||||
"openall": "000100000008010F00640004000F",
|
||||
"closeall": "000100000008010F006400040000"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
格式:指令名 -> 16进制字符串
|
||||
设备通过 `command_set` 字段指定使用的指令集:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "dev1",
|
||||
"command_set": "set1"
|
||||
}
|
||||
```
|
||||
|
||||
#### 指令映射 (mappings)
|
||||
|
||||
@@ -157,7 +239,7 @@ crontab crontab.txt
|
||||
|
||||
## 如何适配自己的设备
|
||||
|
||||
### 场景1:添加 TCP 设备
|
||||
### 场景1:添加 TCP 设备(客户端TCP -> 主机TCP -> 设备TCP)
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -165,7 +247,8 @@ crontab crontab.txt
|
||||
{
|
||||
"id": "dev_tcp",
|
||||
"name": "TCP设备",
|
||||
"protocol": "tcp",
|
||||
"listen_protocol": "tcp",
|
||||
"device_protocol": "tcp",
|
||||
"upc_ip": "192.168.1.100",
|
||||
"upc_port": 502,
|
||||
"listen_port": 10081,
|
||||
@@ -175,7 +258,7 @@ crontab crontab.txt
|
||||
}
|
||||
```
|
||||
|
||||
### 场景2:添加 UDP 设备
|
||||
### 场景2:添加 UDP 设备(客户端UDP -> 主机UDP -> 设备UDP)
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -183,7 +266,8 @@ crontab crontab.txt
|
||||
{
|
||||
"id": "dev_udp",
|
||||
"name": "UDP设备",
|
||||
"protocol": "udp",
|
||||
"listen_protocol": "udp",
|
||||
"device_protocol": "udp",
|
||||
"upc_ip": "192.168.1.200",
|
||||
"upc_port": 502,
|
||||
"listen_port": 10082,
|
||||
@@ -193,18 +277,86 @@ crontab crontab.txt
|
||||
}
|
||||
```
|
||||
|
||||
### 场景3:添加新的控制指令
|
||||
### 场景3:协议转换(客户端TCP -> 主机UDP -> 设备UDP)
|
||||
|
||||
```json
|
||||
{
|
||||
"commands": {
|
||||
"open9": "000100000008010F006C00010001",
|
||||
"close9": "000100000008010F006C00010000"
|
||||
"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:禁用某个设备
|
||||
### 场景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
|
||||
{
|
||||
|
||||
@@ -4,35 +4,9 @@
|
||||
"python_path": "/usr/bin/python3",
|
||||
"base_dir": "/home/smart/pythonPJ/upc_resent"
|
||||
},
|
||||
"devices": [
|
||||
{
|
||||
"id": "dev1",
|
||||
"name": "设备73-TCP",
|
||||
"protocol": "tcp",
|
||||
"upc_ip": "192.168.8.73",
|
||||
"upc_port": 502,
|
||||
"listen_port": 10079,
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": "dev2",
|
||||
"name": "设备125-TCP",
|
||||
"protocol": "tcp",
|
||||
"upc_ip": "192.168.8.125",
|
||||
"upc_port": 502,
|
||||
"listen_port": 10129,
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": "dev3",
|
||||
"name": "设备UDP示例",
|
||||
"protocol": "udp",
|
||||
"upc_ip": "192.168.8.200",
|
||||
"upc_port": 502,
|
||||
"listen_port": 10080,
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"command_sets": {
|
||||
"set1": {
|
||||
"name": "标准8路控制",
|
||||
"commands": {
|
||||
"open1": "000100000008010F006400010001",
|
||||
"close1": "000100000008010F006400010000",
|
||||
@@ -52,7 +26,77 @@
|
||||
"close7": "000100000008010F006A00010000",
|
||||
"open8": "000100000008010F006B00010001",
|
||||
"close8": "000100000008010F006B00010000"
|
||||
}
|
||||
},
|
||||
"set2": {
|
||||
"name": "4路精简控制",
|
||||
"commands": {
|
||||
"open1": "000100000008010F006400010001",
|
||||
"close1": "000100000008010F006400010000",
|
||||
"open2": "000100000008010F006500010001",
|
||||
"close2": "000100000008010F006500010000",
|
||||
"open3": "000100000008010F006600010001",
|
||||
"close3": "000100000008010F006600010000",
|
||||
"open4": "000100000008010F006700010001",
|
||||
"close4": "000100000008010F006700010000",
|
||||
"openall": "000100000008010F00640004000F",
|
||||
"closeall": "000100000008010F006400040000"
|
||||
}
|
||||
},
|
||||
"set3": {
|
||||
"name": "单路控制",
|
||||
"commands": {
|
||||
"open": "000100000008010F006400010001",
|
||||
"close": "000100000008010F006400010000"
|
||||
}
|
||||
}
|
||||
},
|
||||
"devices": [
|
||||
{
|
||||
"id": "dev1",
|
||||
"name": "设备1-8路控制",
|
||||
"listen_protocol": "tcp",
|
||||
"device_protocol": "tcp",
|
||||
"command_set": "set1",
|
||||
"upc_ip": "192.168.8.73",
|
||||
"upc_port": 502,
|
||||
"listen_port": 10079,
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": "dev2",
|
||||
"name": "设备2-8路控制",
|
||||
"listen_protocol": "tcp",
|
||||
"device_protocol": "tcp",
|
||||
"command_set": "set1",
|
||||
"upc_ip": "192.168.8.125",
|
||||
"upc_port": 502,
|
||||
"listen_port": 10129,
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": "dev3",
|
||||
"name": "设备3-4路控制",
|
||||
"listen_protocol": "udp",
|
||||
"device_protocol": "udp",
|
||||
"command_set": "set2",
|
||||
"upc_ip": "192.168.8.200",
|
||||
"upc_port": 502,
|
||||
"listen_port": 10080,
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"id": "dev4",
|
||||
"name": "设备4-单路控制",
|
||||
"listen_protocol": "tcp",
|
||||
"device_protocol": "udp",
|
||||
"command_set": "set3",
|
||||
"upc_ip": "192.168.8.201",
|
||||
"upc_port": 502,
|
||||
"listen_port": 10081,
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
"mappings": {
|
||||
"open": "openall4",
|
||||
"close": "closeall4",
|
||||
|
||||
236
control.sh
236
control.sh
@@ -1,236 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Auto-generated control script
|
||||
# Usage: ./control.sh {start|stop|restart|status}
|
||||
|
||||
BASE_DIR="/home/smart/pythonPJ/upc_resent"
|
||||
PYTHON_PATH="/usr/bin/python3"
|
||||
|
||||
# 设备列表: ID 名称 协议
|
||||
DEVICES=(
|
||||
"dev1" "设备73-TCP" "TCP"
|
||||
"dev2" "设备125-TCP" "TCP"
|
||||
"dev3" "设备UDP示例" "UDP"
|
||||
)
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
show_help() {
|
||||
echo "Usage: $0 {start|stop|restart|status}"
|
||||
echo ""
|
||||
echo "Commands:"
|
||||
echo " start 启动所有服务"
|
||||
echo " stop 停止所有服务"
|
||||
echo " restart 重启所有服务"
|
||||
echo " status 查看服务状态"
|
||||
}
|
||||
|
||||
check_root() {
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
echo -e "${YELLOW}Warning: 建议使用 root 权限运行${NC}"
|
||||
fi
|
||||
}
|
||||
|
||||
start_service() {
|
||||
local device_id=$1
|
||||
local device_name=$2
|
||||
local protocol=$3
|
||||
local script_path="$BASE_DIR/bin/$device_id.py"
|
||||
|
||||
# 检查进程是否已存在(使用更精确的匹配)
|
||||
local pid=$(pgrep -f "${PYTHON_PATH}.*${script_path}" | head -1)
|
||||
if [[ -n "$pid" ]]; then
|
||||
echo -e "[${YELLOW}SKIP${NC}] $device_name ($device_id) - ${protocol} 已在运行 (PID: $pid)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
echo -n "[START] $device_name ($device_id) - ${protocol} ... "
|
||||
nohup $PYTHON_PATH "$script_path" > /dev/null 2>&1 &
|
||||
sleep 1
|
||||
|
||||
# 检查是否启动成功
|
||||
pid=$(pgrep -f "${PYTHON_PATH}.*${script_path}" | head -1)
|
||||
if [[ -n "$pid" ]]; then
|
||||
echo -e "${GREEN}OK${NC} (PID: $pid)"
|
||||
return 0
|
||||
else
|
||||
echo -e "${RED}FAILED${NC}"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
stop_service() {
|
||||
local device_id=$1
|
||||
local device_name=$2
|
||||
local protocol=$3
|
||||
local script_path="$BASE_DIR/bin/$device_id.py"
|
||||
|
||||
# 使用更精确的匹配模式
|
||||
local pids=$(pgrep -f "${PYTHON_PATH}.*${script_path}")
|
||||
if [[ -z "$pids" ]]; then
|
||||
echo -e "[${YELLOW}SKIP${NC}] $device_name ($device_id) - 未运行"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# 获取第一个匹配的 PID
|
||||
local pid=$(echo "$pids" | head -1)
|
||||
echo -n "[STOP] $device_name ($device_id) - ${protocol} (PID: $pid) ... "
|
||||
|
||||
# 结束所有匹配的进程
|
||||
echo "$pids" | while read -r p; do
|
||||
kill "$p" 2>/dev/null
|
||||
done
|
||||
|
||||
# 等待进程结束
|
||||
local i
|
||||
for i in {1..10}; do
|
||||
sleep 0.5
|
||||
pids=$(pgrep -f "${PYTHON_PATH}.*${script_path}" || true)
|
||||
if [[ -z "$pids" ]]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# 检查是否还有残留进程
|
||||
pids=$(pgrep -f "${PYTHON_PATH}.*${script_path}" || true)
|
||||
if [[ -n "$pids" ]]; then
|
||||
# 强制结束残留进程
|
||||
echo "$pids" | while read -r p; do
|
||||
kill -9 "$p" 2>/dev/null
|
||||
done
|
||||
sleep 0.5
|
||||
fi
|
||||
|
||||
# 最终检查
|
||||
pids=$(pgrep -f "${PYTHON_PATH}.*${script_path}" || true)
|
||||
if [[ -z "$pids" ]]; then
|
||||
echo -e "${GREEN}OK${NC}"
|
||||
return 0
|
||||
else
|
||||
echo -e "${RED}FAILED${NC}"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
status_service() {
|
||||
local device_id=$1
|
||||
local device_name=$2
|
||||
local protocol=$3
|
||||
local script_path="$BASE_DIR/bin/$device_id.py"
|
||||
|
||||
local pid=$(pgrep -f "${PYTHON_PATH}.*${script_path}" | head -1)
|
||||
if [[ -n "$pid" ]]; then
|
||||
echo -e "${GREEN}[RUNNING]${NC} $device_name ($device_id) - ${protocol} (PID: $pid)"
|
||||
return 0
|
||||
else
|
||||
echo -e "${RED}[STOPPED]${NC} $device_name ($device_id) - ${protocol}"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
cmd_start() {
|
||||
echo "======================================="
|
||||
echo "启动 UPC Resent 服务"
|
||||
echo "======================================="
|
||||
check_root
|
||||
echo ""
|
||||
|
||||
local count=0
|
||||
local device_id device_name protocol
|
||||
for ((i=0; i<${#DEVICES[@]}; i+=3)); do
|
||||
device_id="${DEVICES[i]}"
|
||||
device_name="${DEVICES[i+1]}"
|
||||
protocol="${DEVICES[i+2]}"
|
||||
|
||||
if start_service "$device_id" "$device_name" "$protocol"; then
|
||||
((count++))
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "======================================="
|
||||
echo "启动完成: $count/$((${#DEVICES[@]}/3)) 个服务"
|
||||
echo "======================================="
|
||||
}
|
||||
|
||||
cmd_stop() {
|
||||
echo "======================================="
|
||||
echo "停止 UPC Resent 服务"
|
||||
echo "======================================="
|
||||
echo ""
|
||||
|
||||
local count=0
|
||||
local device_id device_name protocol
|
||||
for ((i=0; i<${#DEVICES[@]}; i+=3)); do
|
||||
device_id="${DEVICES[i]}"
|
||||
device_name="${DEVICES[i+1]}"
|
||||
protocol="${DEVICES[i+2]}"
|
||||
|
||||
if stop_service "$device_id" "$device_name" "$protocol"; then
|
||||
((count++))
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "======================================="
|
||||
echo "停止完成: $count/$((${#DEVICES[@]}/3)) 个服务"
|
||||
echo "======================================="
|
||||
}
|
||||
|
||||
cmd_restart() {
|
||||
cmd_stop
|
||||
echo ""
|
||||
sleep 1
|
||||
cmd_start
|
||||
}
|
||||
|
||||
cmd_status() {
|
||||
echo "======================================="
|
||||
echo "UPC Resent 服务状态"
|
||||
echo "======================================="
|
||||
echo ""
|
||||
|
||||
local running=0
|
||||
local stopped=0
|
||||
local device_id device_name protocol
|
||||
|
||||
for ((i=0; i<${#DEVICES[@]}; i+=3)); do
|
||||
device_id="${DEVICES[i]}"
|
||||
device_name="${DEVICES[i+1]}"
|
||||
protocol="${DEVICES[i+2]}"
|
||||
|
||||
if status_service "$device_id" "$device_name" "$protocol"; then
|
||||
((running++))
|
||||
else
|
||||
((stopped++))
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "======================================="
|
||||
echo "运行中: $running, 已停止: $stopped, 总计: $((${#DEVICES[@]}/3))"
|
||||
echo "======================================="
|
||||
}
|
||||
|
||||
# 主逻辑
|
||||
case "${1:-}" in
|
||||
start)
|
||||
cmd_start
|
||||
;;
|
||||
stop)
|
||||
cmd_stop
|
||||
;;
|
||||
restart)
|
||||
cmd_restart
|
||||
;;
|
||||
status)
|
||||
cmd_status
|
||||
;;
|
||||
*)
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -1,4 +0,0 @@
|
||||
* */1 * * * /usr/bin/python3 /home/smart/pythonPJ/upc_resent/crond/upcrond-dev1.py
|
||||
* */1 * * * /usr/bin/python3 /home/smart/pythonPJ/upc_resent/crond/upcrond-dev2.py
|
||||
* */1 * * * /usr/bin/python3 /home/smart/pythonPJ/upc_resent/crond/upcrond-dev3.py
|
||||
0 0 * * * /home/smart/pythonPJ/upc_resent/cutlog.sh
|
||||
@@ -60,10 +60,11 @@ def get_template_path(protocol, template_type):
|
||||
raise ValueError(f"未知的模板类型: {template_type}")
|
||||
|
||||
|
||||
def generate_listener(device, global_config, mappings):
|
||||
def generate_listener(device, global_config, mappings, command_sets, global_commands):
|
||||
"""生成监听服务文件"""
|
||||
protocol = device.get('protocol', 'tcp').lower()
|
||||
template_file = get_template_path(protocol, 'listener')
|
||||
listen_protocol = device.get('listen_protocol', 'tcp').lower()
|
||||
device_protocol = device.get('device_protocol', 'tcp').lower()
|
||||
template_file = get_template_path(listen_protocol, 'listener')
|
||||
|
||||
# 检查模板文件是否存在
|
||||
if not os.path.exists(template_file):
|
||||
@@ -73,16 +74,35 @@ def generate_listener(device, global_config, mappings):
|
||||
with open(template_file, 'r', encoding='utf-8') as f:
|
||||
template = f.read()
|
||||
|
||||
# 获取该设备的指令集
|
||||
command_set_id = device.get('command_set')
|
||||
if command_set_id and command_set_id in command_sets:
|
||||
device_commands = command_sets[command_set_id].get('commands', {})
|
||||
else:
|
||||
# 兼容旧配置
|
||||
device_commands = global_commands
|
||||
|
||||
# 构建命令映射字典字符串
|
||||
# 1. 首先添加该设备指令集中所有指令的默认映射(指令名映射到自身)
|
||||
device_mappings = {}
|
||||
for cmd in device_commands.keys():
|
||||
device_mappings[cmd] = cmd
|
||||
|
||||
# 2. 然后添加全局 mappings 中的映射(外部命令 -> 内部指令)
|
||||
# 但只添加目标指令在该设备指令集中存在的映射
|
||||
for external_cmd, internal_cmd in mappings.items():
|
||||
if internal_cmd in device_commands:
|
||||
device_mappings[external_cmd] = internal_cmd
|
||||
|
||||
# 3. 生成映射表字符串
|
||||
mappings_str = "{\n"
|
||||
for cmd, op in mappings.items():
|
||||
for cmd, op in device_mappings.items():
|
||||
mappings_str += f' "{cmd}": "{op}",\n'
|
||||
# 添加默认映射(open1-open8, close1-close8)
|
||||
for i in range(1, 9):
|
||||
mappings_str += f' "open{i}": "open{i}",\n'
|
||||
mappings_str += f' "close{i}": "close{i}",\n'
|
||||
mappings_str += " }"
|
||||
|
||||
# 确定使用哪个 sender 脚本(每个设备独立的 sender)
|
||||
sender_file = f"{global_config['base_dir']}/bin/sender_{device['id']}.py"
|
||||
|
||||
# 替换模板变量
|
||||
content = template.format(
|
||||
device_id=device['id'],
|
||||
@@ -93,7 +113,9 @@ def generate_listener(device, global_config, mappings):
|
||||
upc_port=device['upc_port'],
|
||||
base_dir=global_config['base_dir'],
|
||||
python_path=global_config['python_path'],
|
||||
command_mappings=mappings_str
|
||||
command_mappings=mappings_str,
|
||||
sender_file=sender_file,
|
||||
device_protocol=device_protocol.upper()
|
||||
)
|
||||
|
||||
output_file = os.path.join(global_config['base_dir'], 'bin', f"{device['id']}.py")
|
||||
@@ -101,14 +123,15 @@ def generate_listener(device, global_config, mappings):
|
||||
f.write(content)
|
||||
|
||||
os.chmod(output_file, 0o755)
|
||||
print(f"[生成] {output_file} ({protocol.upper()})")
|
||||
print(f"[生成] {output_file} (监听:{listen_protocol.upper()}, 设备:{device_protocol.upper()})")
|
||||
return output_file
|
||||
|
||||
|
||||
def generate_crond(device, global_config):
|
||||
"""生成保活检查文件"""
|
||||
protocol = device.get('protocol', 'tcp').lower()
|
||||
template_file = get_template_path(protocol, 'crond')
|
||||
listen_protocol = device.get('listen_protocol', 'tcp').lower()
|
||||
device_protocol = device.get('device_protocol', 'tcp').lower()
|
||||
template_file = get_template_path(listen_protocol, 'crond')
|
||||
|
||||
# 检查模板文件是否存在
|
||||
if not os.path.exists(template_file):
|
||||
@@ -124,7 +147,8 @@ def generate_crond(device, global_config):
|
||||
tms_server_ip=global_config['tms_server_ip'],
|
||||
listen_port=device['listen_port'],
|
||||
base_dir=global_config['base_dir'],
|
||||
python_path=global_config['python_path']
|
||||
python_path=global_config['python_path'],
|
||||
device_protocol=device_protocol.upper()
|
||||
)
|
||||
|
||||
output_file = os.path.join(global_config['base_dir'], 'crond', f"upcrond-{device['id']}.py")
|
||||
@@ -132,14 +156,15 @@ def generate_crond(device, global_config):
|
||||
f.write(content)
|
||||
|
||||
os.chmod(output_file, 0o755)
|
||||
print(f"[生成] {output_file} ({protocol.upper()})")
|
||||
print(f"[生成] {output_file} (监听:{listen_protocol.upper()}, 设备:{device_protocol.upper()})")
|
||||
return output_file
|
||||
|
||||
|
||||
def generate_sender(commands, global_config, protocol='tcp'):
|
||||
"""生成发送模块文件"""
|
||||
protocol = protocol.lower()
|
||||
template_file = get_template_path(protocol, 'sender')
|
||||
def generate_sender_for_device(device, command_set, global_config):
|
||||
"""为指定设备生成独立的发送模块文件"""
|
||||
device_id = device['id']
|
||||
device_protocol = device.get('device_protocol', device.get('protocol', 'tcp')).lower()
|
||||
template_file = get_template_path(device_protocol, 'sender')
|
||||
|
||||
# 检查模板文件是否存在
|
||||
if not os.path.exists(template_file):
|
||||
@@ -150,6 +175,7 @@ def generate_sender(commands, global_config, protocol='tcp'):
|
||||
template = f.read()
|
||||
|
||||
# 构建指令定义字典字符串
|
||||
commands = command_set.get('commands', {})
|
||||
cmd_defs = "{\n"
|
||||
for cmd, hex_str in commands.items():
|
||||
cmd_defs += f' "{cmd}": "{hex_str}",\n'
|
||||
@@ -159,31 +185,39 @@ def generate_sender(commands, global_config, protocol='tcp'):
|
||||
command_definitions=cmd_defs
|
||||
)
|
||||
|
||||
# 根据协议生成不同的文件名
|
||||
output_file = os.path.join(global_config['base_dir'], 'bin', f'sender_{protocol}.py')
|
||||
# 为每个设备生成独立的 sender 文件
|
||||
output_file = os.path.join(global_config['base_dir'], 'bin', f'sender_{device_id}.py')
|
||||
with open(output_file, 'w', encoding='utf-8') as f:
|
||||
f.write(content)
|
||||
|
||||
os.chmod(output_file, 0o755)
|
||||
print(f"[生成] {output_file} ({protocol.upper()})")
|
||||
print(f"[生成] {output_file} ({device_protocol.upper()}, 指令集: {command_set.get('name', '未命名')})")
|
||||
return output_file
|
||||
|
||||
|
||||
def generate_all_senders(config, global_config):
|
||||
"""为所有使用到的协议生成 sender 文件"""
|
||||
commands = config['commands']
|
||||
"""为所有设备生成独立的 sender 文件"""
|
||||
command_sets = config.get('command_sets', {})
|
||||
devices = config['devices']
|
||||
|
||||
# 收集所有使用的协议类型
|
||||
protocols = set()
|
||||
for device in devices:
|
||||
if device.get('enabled', True):
|
||||
protocol = device.get('protocol', 'tcp').lower()
|
||||
protocols.add(protocol)
|
||||
|
||||
generated = []
|
||||
for protocol in protocols:
|
||||
generated.append(generate_sender(commands, global_config, protocol))
|
||||
for device in devices:
|
||||
if not device.get('enabled', True):
|
||||
continue
|
||||
|
||||
# 获取设备使用的指令集
|
||||
command_set_id = device.get('command_set', 'default')
|
||||
if command_set_id not in command_sets:
|
||||
# 兼容旧配置:如果找不到指令集,使用全局 commands
|
||||
if 'commands' in config:
|
||||
command_set = {'name': '全局指令', 'commands': config['commands']}
|
||||
else:
|
||||
print(f"[!] 警告: 设备 {device['id']} 指定的指令集 '{command_set_id}' 不存在")
|
||||
continue
|
||||
else:
|
||||
command_set = command_sets[command_set_id]
|
||||
|
||||
generated.append(generate_sender_for_device(device, command_set, global_config))
|
||||
|
||||
return generated
|
||||
|
||||
@@ -220,13 +254,16 @@ def generate_control_script(devices, global_config):
|
||||
device_list = []
|
||||
for device in devices:
|
||||
if device.get('enabled', True):
|
||||
listen_protocol = device.get('listen_protocol', device.get('protocol', 'tcp')).upper()
|
||||
device_protocol = device.get('device_protocol', device.get('protocol', 'tcp')).upper()
|
||||
protocol_str = f"{listen_protocol}->{device_protocol}"
|
||||
device_list.append({
|
||||
'id': device['id'],
|
||||
'name': device['name'],
|
||||
'protocol': device.get('protocol', 'tcp').upper()
|
||||
'protocol': protocol_str
|
||||
})
|
||||
|
||||
# 构建设备列表字符串
|
||||
# 构建设备列表字符串: ID 名称 协议
|
||||
device_defs = "\n".join([
|
||||
f" \"{d['id']}\" \"{d['name']}\" \"{d['protocol']}\""
|
||||
for d in device_list
|
||||
@@ -253,7 +290,8 @@ def check_config(config):
|
||||
|
||||
global_cfg = config.get('global', {})
|
||||
devices = config.get('devices', [])
|
||||
commands = config.get('commands', {})
|
||||
command_sets = config.get('command_sets', {})
|
||||
commands = config.get('commands', {}) # 兼容旧配置
|
||||
mappings = config.get('mappings', {})
|
||||
|
||||
# 检查全局配置
|
||||
@@ -269,6 +307,15 @@ def check_config(config):
|
||||
device_ids = []
|
||||
listen_ports = []
|
||||
|
||||
# 收集所有指令(用于验证映射)
|
||||
all_commands = set()
|
||||
if command_sets:
|
||||
for set_id, cmd_set in command_sets.items():
|
||||
if 'commands' in cmd_set:
|
||||
all_commands.update(cmd_set['commands'].keys())
|
||||
if commands:
|
||||
all_commands.update(commands.keys())
|
||||
|
||||
for device in devices:
|
||||
device_id = device.get('id')
|
||||
if not device_id:
|
||||
@@ -284,10 +331,23 @@ def check_config(config):
|
||||
if field not in device:
|
||||
errors.append(f"设备 {device_id} 缺少字段: {field}")
|
||||
|
||||
# 检查协议类型
|
||||
protocol = device.get('protocol', 'tcp').lower()
|
||||
if protocol not in ['tcp', 'udp']:
|
||||
errors.append(f"设备 {device_id} 的协议类型无效: {protocol} (必须是 tcp 或 udp)")
|
||||
# 检查协议类型(支持新旧配置兼容)
|
||||
listen_protocol = device.get('listen_protocol', device.get('protocol', 'tcp')).lower()
|
||||
device_protocol = device.get('device_protocol', device.get('protocol', 'tcp')).lower()
|
||||
|
||||
if listen_protocol not in ['tcp', 'udp']:
|
||||
errors.append(f"设备 {device_id} 的监听协议类型无效: {listen_protocol} (必须是 tcp 或 udp)")
|
||||
|
||||
if device_protocol not in ['tcp', 'udp']:
|
||||
errors.append(f"设备 {device_id} 的设备协议类型无效: {device_protocol} (必须是 tcp 或 udp)")
|
||||
|
||||
# 检查指令集
|
||||
if 'command_set' in device:
|
||||
command_set_id = device['command_set']
|
||||
if command_set_id not in command_sets:
|
||||
errors.append(f"设备 {device_id} 指定的指令集 '{command_set_id}' 不存在")
|
||||
elif not commands and not command_sets:
|
||||
warnings.append(f"设备 {device_id} 未指定指令集,且没有全局指令")
|
||||
|
||||
if 'listen_port' in device:
|
||||
port = device['listen_port']
|
||||
@@ -295,27 +355,36 @@ def check_config(config):
|
||||
errors.append(f"设备 {device_id} 的监听端口 {port} 与其他设备冲突")
|
||||
listen_ports.append(port)
|
||||
|
||||
# 检查指令定义
|
||||
if not commands:
|
||||
warnings.append("没有定义任何指令")
|
||||
# 检查指令集
|
||||
if not command_sets and not commands:
|
||||
warnings.append("没有定义任何指令集或指令")
|
||||
|
||||
# 检查映射
|
||||
for cmd, op in mappings.items():
|
||||
if op not in commands and not any(op == f"open{i}" or op == f"close{i}" for i in range(1, 9)):
|
||||
warnings.append(f"映射 '{cmd}' -> '{op}' 的目标指令未在 commands 中定义")
|
||||
if op not in all_commands and not any(op == f"open{i}" or op == f"close{i}" for i in range(1, 9)):
|
||||
warnings.append(f"映射 '{cmd}' -> '{op}' 的目标指令未在任何指令集中定义")
|
||||
|
||||
# 检查模板文件是否存在
|
||||
protocols = set()
|
||||
listen_protocols = set()
|
||||
device_protocols = set()
|
||||
for device in devices:
|
||||
if device.get('enabled', True):
|
||||
protocols.add(device.get('protocol', 'tcp').lower())
|
||||
listen_protocols.add(device.get('listen_protocol', device.get('protocol', 'tcp')).lower())
|
||||
device_protocols.add(device.get('device_protocol', device.get('protocol', 'tcp')).lower())
|
||||
|
||||
for protocol in protocols:
|
||||
for template_type in ['listener', 'crond', 'sender']:
|
||||
# 检查监听协议模板
|
||||
for protocol in listen_protocols:
|
||||
for template_type in ['listener', 'crond']:
|
||||
template_file = get_template_path(protocol, template_type)
|
||||
if not os.path.exists(template_file):
|
||||
warnings.append(f"模板文件不存在: {template_file}")
|
||||
|
||||
# 检查设备协议模板(sender)
|
||||
for protocol in device_protocols:
|
||||
template_file = get_template_path(protocol, 'sender')
|
||||
if not os.path.exists(template_file):
|
||||
warnings.append(f"模板文件不存在: {template_file}")
|
||||
|
||||
# 输出检查结果
|
||||
if errors:
|
||||
print("\n[!] 配置错误:")
|
||||
@@ -381,9 +450,11 @@ def main():
|
||||
|
||||
# 2. 为每个设备生成监听服务和保活脚本
|
||||
print("\n[生成设备服务]")
|
||||
command_sets = config.get('command_sets', {})
|
||||
global_commands = config.get('commands', {})
|
||||
for device in devices:
|
||||
print(f"\n处理设备: {device['name']} ({device['id']}) - {device.get('protocol', 'tcp').upper()}")
|
||||
generated_files.append(generate_listener(device, global_config, config['mappings']))
|
||||
generated_files.append(generate_listener(device, global_config, config['mappings'], command_sets, global_commands))
|
||||
generated_files.append(generate_crond(device, global_config))
|
||||
|
||||
# 3. 生成 crontab
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
BASE_DIR="{base_dir}"
|
||||
PYTHON_PATH="{python_path}"
|
||||
|
||||
# 设备列表: ID 名称 协议
|
||||
# 设备列表: ID 名称 监听协议 设备协议
|
||||
DEVICES=(
|
||||
{device_defs}
|
||||
)
|
||||
|
||||
@@ -14,7 +14,7 @@ TMS_SERVER_IP = '{tms_server_ip}'
|
||||
TMS_PORT = {listen_port}
|
||||
UPC_DEV_IP = '{upc_ip}'
|
||||
UPC_DEV_PORT = '{upc_port}'
|
||||
SENDER_FILE = '{base_dir}/bin/sender_tcp.py'
|
||||
SENDER_FILE = '{sender_file}'
|
||||
LOG_FILE = '{base_dir}/log/{device_id}.log'
|
||||
PYTHON_PATH = '{python_path}'
|
||||
DEVICE_ID = '{device_id}'
|
||||
|
||||
@@ -14,7 +14,7 @@ TMS_SERVER_IP = '{tms_server_ip}'
|
||||
TMS_PORT = {listen_port}
|
||||
UPC_DEV_IP = '{upc_ip}'
|
||||
UPC_DEV_PORT = {upc_port}
|
||||
SENDER_FILE = '{base_dir}/bin/sender_udp.py'
|
||||
SENDER_FILE = '{sender_file}'
|
||||
LOG_FILE = '{base_dir}/log/{device_id}.log'
|
||||
PYTHON_PATH = '{python_path}'
|
||||
DEVICE_ID = '{device_id}'
|
||||
|
||||
Reference in New Issue
Block a user