精度到0.1

main
risingLee 2026-02-04 11:35:09 +08:00
parent b4e8bcb9c9
commit e2eaf3cbe5
25 changed files with 631 additions and 52 deletions

View File

@ -195,3 +195,5 @@ chmod +x start_frontend.sh
前端默认连接 `http://localhost:5000`,如需修改,编辑 `frontend/wrench_gui.py` 中的 `api_base_url` 变量。

View File

@ -109,3 +109,5 @@ simulator = WrenchSimulator(
2. **端口被占用**:修改端口号或关闭占用端口的程序
3. **无响应**:检查网络连接和防火墙设置

250
SSH_TUNNEL_README.md Normal file
View File

@ -0,0 +1,250 @@
# SSH反向隧道配置指南
## 问题分析
错误信息 `sh: ssh -fN -R 2222:localhost:22 root@123.56.98.4: command not found` 表示:
1. **SSH客户端未安装** - 系统找不到 `ssh` 命令
2. 需要先安装 `openssh-client``openssh-clients`
## 快速解决方案
### 步骤1安装SSH客户端
**CentOS/RHEL系统**
```bash
sudo yum install -y openssh-clients openssh-server
```
**Debian/Ubuntu系统**
```bash
sudo apt-get update
sudo apt-get install -y openssh-client openssh-server
```
**Arch Linux**
```bash
sudo pacman -S openssh
```
### 步骤2验证安装
```bash
# 检查SSH是否安装成功
ssh -V
# 应该显示类似OpenSSH_8.0p1, OpenSSL 1.1.1g
```
### 步骤3建立SSH反向隧道
```bash
# 基本命令
ssh -fN -R 2222:localhost:22 root@123.56.98.4 -p 22
# 参数说明:
# -f: 后台运行
# -N: 不执行远程命令
# -R: 反向隧道
# 2222: 阿里云服务器上的端口
# localhost:22: 本地SSH端口
# root@123.56.98.4: 阿里云服务器地址
# -p 22: SSH端口
```
### 步骤4测试连接
在**任何能访问阿里云服务器的机器**上:
```bash
# 先SSH到阿里云服务器
ssh root@123.56.98.4
# 然后在阿里云服务器上连接内网服务器
ssh -p 2222 root@localhost
```
## 使用提供的脚本(推荐)
### 方法1使用自动设置脚本
```bash
# 1. 下载并运行设置脚本
chmod +x ssh_tunnel_setup.sh
./ssh_tunnel_setup.sh
# 脚本会自动:
# - 检测并安装SSH客户端
# - 配置SSH服务
# - 生成SSH密钥
# - 测试连接
```
### 方法2使用自动重连脚本
```bash
# 1. 编辑 ssh_tunnel_auto.sh修改配置参数
vim ssh_tunnel_auto.sh
# 2. 运行自动重连脚本(前台运行)
chmod +x ssh_tunnel_auto.sh
./ssh_tunnel_auto.sh
# 或者后台运行
nohup ./ssh_tunnel_auto.sh > /dev/null 2>&1 &
```
### 方法3配置为系统服务开机自启
```bash
# 1. 使用root权限运行
sudo chmod +x ssh_tunnel_service.sh
sudo ./ssh_tunnel_service.sh
# 2. 服务会自动:
# - 创建systemd服务
# - 设置开机自启
# - 自动重连
```
## 常见问题排查
### 1. SSH命令找不到
**问题:** `command not found: ssh`
**解决:**
```bash
# 检查是否安装
which ssh
# 如果为空安装SSH客户端
# CentOS/RHEL:
sudo yum install openssh-clients
# Ubuntu/Debian:
sudo apt-get install openssh-client
```
### 2. 连接被拒绝
**问题:** `Connection refused`
**可能原因:**
- 阿里云服务器防火墙未开放22端口
- SSH服务未启动
- 用户名或密码错误
**解决:**
```bash
# 检查SSH服务状态
sudo systemctl status sshd
# 启动SSH服务
sudo systemctl start sshd
sudo systemctl enable sshd
# 检查防火墙
sudo firewall-cmd --list-ports # CentOS
sudo ufw status # Ubuntu
```
### 3. 隧道建立后无法连接
**问题:** 在阿里云服务器上 `ssh -p 2222 root@localhost` 失败
**检查:**
```bash
# 1. 检查隧道是否建立
ps aux | grep ssh | grep 2222
# 2. 检查端口是否监听(在阿里云服务器上)
netstat -tlnp | grep 2222
# 或
ss -tlnp | grep 2222
# 3. 检查阿里云服务器SSH配置
sudo vim /etc/ssh/sshd_config
# 确保有GatewayPorts yes
sudo systemctl restart sshd
```
### 4. 连接频繁断开
**解决:** 使用自动重连脚本,或添加保活参数:
```bash
ssh -fN -R 2222:localhost:22 \
-o ServerAliveInterval=30 \
-o ServerAliveCountMax=3 \
root@123.56.98.4 -p 22
```
## 安全建议
1. **使用SSH密钥认证**(推荐)
```bash
# 生成密钥对
ssh-keygen -t rsa -b 2048
# 复制公钥到阿里云服务器
ssh-copy-id root@123.56.98.4
```
2. **修改SSH端口**(可选)
```bash
# 编辑 /etc/ssh/sshd_config
sudo vim /etc/ssh/sshd_config
# 修改Port 2222
# 重启服务
sudo systemctl restart sshd
```
3. **禁用密码登录**(使用密钥后)
```bash
# 编辑 /etc/ssh/sshd_config
PasswordAuthentication no
# 重启服务
sudo systemctl restart sshd
```
## 验证连接
### 在阿里云服务器上验证
```bash
# 1. 检查端口监听
ss -tlnp | grep 2222
# 2. 测试连接
ssh -p 2222 root@localhost
# 3. 查看隧道进程
ps aux | grep "ssh.*-R.*2222"
```
### 从外部访问
```bash
# 1. SSH到阿里云服务器
ssh root@123.56.98.4
# 2. 通过隧道连接内网服务器
ssh -p 2222 root@localhost
```
## 文件说明
- `ssh_tunnel_setup.sh` - 自动设置脚本安装SSH、配置密钥等
- `ssh_tunnel_auto.sh` - 自动重连脚本(监控并自动重连)
- `ssh_tunnel_service.sh` - 创建systemd服务开机自启
- `SSH_TUNNEL_README.md` - 本文档
## 下一步
1. 运行 `ssh_tunnel_setup.sh` 完成初始设置
2. 运行 `ssh_tunnel_auto.sh` 建立隧道
3. 或运行 `ssh_tunnel_service.sh` 配置为系统服务
如有问题,请检查日志或联系技术支持。

View File

@ -75,3 +75,5 @@ conn.close()
print("\n" + "="*60)

View File

@ -26,3 +26,5 @@ else:
conn.close()

View File

@ -66,3 +66,5 @@ print("\n" + "="*60)
print("诊断完成")
print("="*60)

View File

@ -111,3 +111,5 @@ def migrate_add_device_info():
if __name__ == "__main__":
migrate_add_device_info()

View File

@ -53,3 +53,5 @@ print("2. 后端服务器日志中的调试信息")
print("3. 重启后端服务器")
print("="*60)

View File

@ -1,3 +1,5 @@
Flask==2.3.3
flask-cors==4.0.0

View File

@ -8,3 +8,5 @@ cd /d %~dp0
python app.py
pause

View File

@ -6,3 +6,5 @@ echo ""
cd "$(dirname "$0")"
python3 app.py

View File

@ -40,3 +40,5 @@ def test_query():
if __name__ == "__main__":
test_query()

Binary file not shown.

View File

@ -1,2 +1,4 @@
requests==2.31.0

View File

@ -8,3 +8,5 @@ cd /d %~dp0
python wrench_gui.py
pause

View File

@ -6,3 +6,5 @@ echo ""
cd "$(dirname "$0")"
python3 wrench_gui.py

81
ssh_tunnel_auto.sh Normal file
View File

@ -0,0 +1,81 @@
#!/bin/bash
# SSH反向隧道自动重连脚本
# 配置参数
REMOTE_HOST="123.56.98.4"
REMOTE_USER="root"
REMOTE_PORT=22
TUNNEL_PORT=2222
LOCAL_PORT=22
CHECK_INTERVAL=60 # 检查间隔(秒)
echo "=== SSH反向隧道自动重连脚本 ==="
echo "远程服务器: ${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_PORT}"
echo "隧道端口: ${TUNNEL_PORT} -> localhost:${LOCAL_PORT}"
echo "检查间隔: ${CHECK_INTERVAL}"
echo ""
# 检查SSH是否安装
if ! command -v ssh &> /dev/null; then
echo "错误: SSH客户端未安装请先运行 ssh_tunnel_setup.sh"
exit 1
fi
# 函数建立SSH隧道
establish_tunnel() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] 建立SSH反向隧道..."
# 先检查是否已有连接
PID=$(pgrep -f "ssh.*-R.*${TUNNEL_PORT}:localhost:${LOCAL_PORT}.*${REMOTE_USER}@${REMOTE_HOST}")
if [ ! -z "$PID" ]; then
echo "发现已有隧道进程 (PID: $PID),先关闭..."
kill $PID 2>/dev/null
sleep 2
fi
# 建立新连接
ssh -fN -R ${TUNNEL_PORT}:localhost:${LOCAL_PORT} \
-o ServerAliveInterval=30 \
-o ServerAliveCountMax=3 \
-o ExitOnForwardFailure=yes \
-o StrictHostKeyChecking=no \
-p ${REMOTE_PORT} \
${REMOTE_USER}@${REMOTE_HOST}
if [ $? -eq 0 ]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ✓ 隧道建立成功"
return 0
else
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ✗ 隧道建立失败"
return 1
fi
}
# 函数:检查隧道是否存活
check_tunnel() {
PID=$(pgrep -f "ssh.*-R.*${TUNNEL_PORT}:localhost:${LOCAL_PORT}.*${REMOTE_USER}@${REMOTE_HOST}")
if [ ! -z "$PID" ]; then
# 检查进程是否真的在运行
if ps -p $PID > /dev/null 2>&1; then
return 0
fi
fi
return 1
}
# 主循环
echo "开始监控SSH隧道..."
establish_tunnel
while true; do
sleep ${CHECK_INTERVAL}
if ! check_tunnel; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ⚠ 检测到隧道断开,重新连接..."
establish_tunnel
else
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ✓ 隧道连接正常"
fi
done

74
ssh_tunnel_service.sh Normal file
View File

@ -0,0 +1,74 @@
#!/bin/bash
# 创建systemd服务文件用于开机自启
REMOTE_HOST="123.56.98.4"
REMOTE_USER="root"
TUNNEL_PORT=2222
# 获取脚本所在目录
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
AUTO_SCRIPT="${SCRIPT_DIR}/ssh_tunnel_auto.sh"
echo "=== 创建SSH隧道systemd服务 ==="
# 检查是否以root运行
if [ "$EUID" -ne 0 ]; then
echo "请使用sudo运行此脚本"
exit 1
fi
# 创建服务文件
SERVICE_FILE="/etc/systemd/system/ssh-tunnel.service"
cat > ${SERVICE_FILE} << EOF
[Unit]
Description=SSH Reverse Tunnel to ${REMOTE_HOST}
After=network.target ssh.service
Wants=network-online.target
[Service]
Type=simple
User=root
ExecStart=/bin/bash ${AUTO_SCRIPT}
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
EOF
echo "✓ 服务文件已创建: ${SERVICE_FILE}"
# 重新加载systemd
systemctl daemon-reload
echo "✓ systemd配置已重新加载"
# 启用服务
systemctl enable ssh-tunnel.service
echo "✓ 服务已设置为开机自启"
# 启动服务
read -p "是否立即启动服务?(y/n): " start_now
if [ "$start_now" = "y" ] || [ "$start_now" = "Y" ]; then
systemctl start ssh-tunnel.service
echo "✓ 服务已启动"
echo ""
echo "查看服务状态: systemctl status ssh-tunnel"
echo "查看服务日志: journalctl -u ssh-tunnel -f"
fi
echo ""
echo "=== 服务配置完成 ==="
echo ""
echo "常用命令:"
echo " 启动服务: sudo systemctl start ssh-tunnel"
echo " 停止服务: sudo systemctl stop ssh-tunnel"
echo " 查看状态: sudo systemctl status ssh-tunnel"
echo " 查看日志: sudo journalctl -u ssh-tunnel -f"
echo " 禁用自启: sudo systemctl disable ssh-tunnel"

107
ssh_tunnel_setup.sh Normal file
View File

@ -0,0 +1,107 @@
#!/bin/bash
# SSH反向隧道设置脚本
echo "=== SSH反向隧道设置脚本 ==="
# 1. 检查SSH客户端是否安装
echo "1. 检查SSH客户端..."
if command -v ssh &> /dev/null; then
echo "✓ SSH客户端已安装: $(which ssh)"
ssh -V
else
echo "✗ SSH客户端未安装开始安装..."
# 检测Linux发行版
if [ -f /etc/redhat-release ]; then
# CentOS/RHEL
echo "检测到 CentOS/RHEL 系统"
sudo yum install -y openssh-clients openssh-server
elif [ -f /etc/debian_version ]; then
# Debian/Ubuntu
echo "检测到 Debian/Ubuntu 系统"
sudo apt-get update
sudo apt-get install -y openssh-client openssh-server
elif [ -f /etc/arch-release ]; then
# Arch Linux
echo "检测到 Arch Linux 系统"
sudo pacman -S --noconfirm openssh
else
echo "无法自动检测系统类型,请手动安装 openssh-client"
exit 1
fi
# 验证安装
if command -v ssh &> /dev/null; then
echo "✓ SSH客户端安装成功"
ssh -V
else
echo "✗ SSH客户端安装失败请手动安装"
exit 1
fi
fi
echo ""
echo "2. 检查SSH服务是否运行..."
if systemctl is-active --quiet sshd || systemctl is-active --quiet ssh; then
echo "✓ SSH服务正在运行"
else
echo "⚠ SSH服务未运行启动SSH服务..."
sudo systemctl start sshd 2>/dev/null || sudo systemctl start ssh
sudo systemctl enable sshd 2>/dev/null || sudo systemctl enable ssh
fi
echo ""
echo "3. 生成SSH密钥如果不存在..."
if [ ! -f ~/.ssh/id_rsa ]; then
echo "生成SSH密钥..."
ssh-keygen -t rsa -b 2048 -f ~/.ssh/id_rsa -N ""
echo "✓ SSH密钥已生成"
else
echo "✓ SSH密钥已存在"
fi
echo ""
echo "4. 配置SSH密钥免密登录可选..."
read -p "是否配置免密登录到阿里云服务器?(y/n): " setup_key
if [ "$setup_key" = "y" ] || [ "$setup_key" = "Y" ]; then
read -p "请输入阿里云服务器IP: " server_ip
read -p "请输入阿里云服务器用户名默认root: " server_user
server_user=${server_user:-root}
echo "复制SSH公钥到阿里云服务器..."
ssh-copy-id -p 22 ${server_user}@${server_ip}
if [ $? -eq 0 ]; then
echo "✓ 免密登录配置成功"
else
echo "⚠ 免密登录配置失败,请手动配置或使用密码登录"
fi
fi
echo ""
echo "5. 测试SSH连接..."
read -p "请输入阿里云服务器IP用于测试连接: " test_ip
read -p "请输入用户名默认root: " test_user
test_user=${test_user:-root}
echo "测试连接到 ${test_user}@${test_ip}..."
ssh -o ConnectTimeout=5 -p 22 ${test_user}@${test_ip} "echo '连接成功!'"
if [ $? -eq 0 ]; then
echo "✓ SSH连接测试成功"
else
echo "✗ SSH连接测试失败请检查"
echo " - 网络连接是否正常"
echo " - 阿里云服务器防火墙是否开放22端口"
echo " - 用户名和密码是否正确"
fi
echo ""
echo "=== 设置完成 ==="
echo ""
echo "使用方法:"
echo " 手动连接: ssh -fN -R 2222:localhost:22 root@123.56.98.4 -p 22"
echo ""
echo " 或者使用自动重连脚本(见下方)"

View File

@ -7,3 +7,5 @@ echo.
python wrench_simulator.py
pause

View File

@ -5,3 +5,5 @@ echo "========================================"
echo ""
python3 wrench_simulator.py

View File

@ -79,3 +79,5 @@ if __name__ == "__main__":
print("4. 设备地址码不匹配")
print("=" * 60)

View File

@ -70,3 +70,5 @@ def test_simulator():
if __name__ == "__main__":
test_simulator()

View File

@ -316,7 +316,7 @@ class WrenchController:
return self._send_command(bytes(data))
def set_torque_parameters(self,
target_torque: int,
target_torque: float,
mode: int = 1,
torque_tolerance: float = 0.10,
target_angle: int = 0,
@ -329,7 +329,7 @@ class WrenchController:
controller_sn: str = None) -> bytes:
"""
设定扭矩参数功能码0x10
:param target_torque: 目标扭矩(Nm)
:param target_torque: 目标扭矩(Nm支持一位小数协议中按Nm×10编码为整数)
:param mode: 模式 1=M1模式(扭矩模式), 2=M2模式(角度模式)
:param torque_tolerance: 扭矩偏差百分比(仅M1模式)如0.10表示±10%
:param target_angle: 目标角度()M1模式填0
@ -353,13 +353,18 @@ class WrenchController:
# 获取当前时间
now = datetime.now()
# 计算扭矩上下限
# 计算扭矩上下限(以物理量 Nm 计算,可带一位小数)
if mode == 1: # M1模式
torque_min = int(target_torque * (1 - torque_tolerance))
torque_max = int(target_torque * (1 + torque_tolerance))
torque_min_nm = target_torque * (1 - torque_tolerance)
torque_max_nm = target_torque * (1 + torque_tolerance)
else: # M2模式
torque_min = int(target_torque * 0.8) # 默认下限
torque_max = int(target_torque * 1.2) # 默认上限
torque_min_nm = target_torque * 0.8 # 默认下限
torque_max_nm = target_torque * 1.2 # 默认上限
# 协议中扭矩以 0.1Nm 精度编码:协议值 = Nm × 10
target_torque_val = int(round(target_torque * 10))
torque_min_val = int(round(torque_min_nm * 10))
torque_max_val = int(round(torque_max_nm * 10))
# 角度需要乘10
angle_value = target_angle * 10
@ -401,14 +406,14 @@ class WrenchController:
# 参数模式
data.append(mode)
# 目标扭矩 (2字节)
data.extend(struct.pack('>H', target_torque))
# 目标扭矩 (2字节Nm×10)
data.extend(struct.pack('>H', target_torque_val))
# 扭矩下限 (2字节)
data.extend(struct.pack('>H', torque_min))
# 扭矩下限 (2字节Nm×10)
data.extend(struct.pack('>H', torque_min_val))
# 扭矩上限 (2字节)
data.extend(struct.pack('>H', torque_max))
# 扭矩上限 (2字节Nm×10)
data.extend(struct.pack('>H', torque_max_val))
# 目标角度 (2字节)
data.extend(struct.pack('>H', angle_value))
@ -427,8 +432,8 @@ class WrenchController:
mode_str = "M1(扭矩模式)" if mode == 1 else "M2(角度模式)"
print(f"\n设定扭矩参数:")
print(f" 模式: {mode_str}")
print(f" 目标扭矩: {target_torque} Nm")
print(f" 扭矩范围: {torque_min}-{torque_max} Nm")
print(f" 目标扭矩: {target_torque:.1f} Nm")
print(f" 扭矩范围: {torque_min_nm:.1f}-{torque_max_nm:.1f} Nm")
print(f" 目标角度: {target_angle}°")
print(f" 角度范围: {angle_min}-{angle_max}°")
print(f" 报文: {data.hex(' ').upper()}")
@ -512,12 +517,17 @@ class WrenchController:
mode = "M1(扭矩模式)" if response[26] == 0x01 else "M2(角度模式)"
target_torque = struct.unpack('>H', response[27:29])[0]
actual_torque = struct.unpack('>H', response[29:31])[0]
# 扭矩以 0.1Nm 精度编码,需要还原为物理量
target_torque_raw = struct.unpack('>H', response[27:29])[0]
actual_torque_raw = struct.unpack('>H', response[29:31])[0]
target_torque = target_torque_raw / 10.0
actual_torque = actual_torque_raw / 10.0
target_angle = struct.unpack('>H', response[31:33])[0] / 10
actual_angle = struct.unpack('>H', response[33:35])[0] / 10
torque_max = struct.unpack('>H', response[35:37])[0]
torque_min = struct.unpack('>H', response[37:39])[0]
torque_max_raw = struct.unpack('>H', response[35:37])[0]
torque_min_raw = struct.unpack('>H', response[37:39])[0]
torque_max = torque_max_raw / 10.0
torque_min = torque_min_raw / 10.0
angle_max = struct.unpack('>H', response[39:41])[0] / 10
angle_min = struct.unpack('>H', response[41:43])[0] / 10
@ -533,7 +543,7 @@ class WrenchController:
"actual_torque": actual_torque,
"target_angle": target_angle,
"actual_angle": actual_angle,
"torque_range": f"{torque_min}-{torque_max} Nm",
"torque_range": f"{torque_min:.1f}-{torque_max:.1f} Nm",
"angle_range": f"{angle_min}-{angle_max}°"
}

View File

@ -106,9 +106,15 @@ class WrenchSimulator:
second = data[73]
mode = data[74]
target_torque = struct.unpack('>H', data[75:77])[0]
torque_min = struct.unpack('>H', data[77:79])[0]
torque_max = struct.unpack('>H', data[79:81])[0]
# 扭矩以 0.1Nm 精度编码,协议值 = Nm×10
target_torque_raw = struct.unpack('>H', data[75:77])[0]
torque_min_raw = struct.unpack('>H', data[77:79])[0]
torque_max_raw = struct.unpack('>H', data[79:81])[0]
target_torque = target_torque_raw / 10.0
torque_min = torque_min_raw / 10.0
torque_max = torque_max_raw / 10.0
target_angle = struct.unpack('>H', data[81:83])[0] / 10
angle_max = struct.unpack('>H', data[83:85])[0] / 10
angle_min = struct.unpack('>H', data[85:87])[0] / 10
@ -121,7 +127,7 @@ class WrenchSimulator:
"controller_sn": controller_sn,
"timestamp": f"{year}-{month:02d}-{day:02d} {hour:02d}:{minute:02d}:{second:02d}",
"mode": mode,
"target_torque": target_torque,
"target_torque": target_torque, # Nm支持一位小数
"torque_min": torque_min,
"torque_max": torque_max,
"target_angle": target_angle,
@ -138,8 +144,8 @@ class WrenchSimulator:
print(f" 控制器SN: {controller_sn}")
print(f" 时间: {params['timestamp']}")
print(f" 模式: {'M1(扭矩模式)' if mode == 1 else 'M2(角度模式)'}")
print(f" 目标扭矩: {target_torque} Nm")
print(f" 扭矩范围: {torque_min}-{torque_max} Nm")
print(f" 目标扭矩: {target_torque:.1f} Nm")
print(f" 扭矩范围: {torque_min:.1f}-{torque_max:.1f} Nm")
print(f" 目标角度: {target_angle}°")
print(f" 角度范围: {angle_min}-{angle_max}°")
@ -174,19 +180,34 @@ class WrenchSimulator:
if params is None:
params = self.current_parameters
# 使用当前参数或默认值
# 使用当前参数或默认值(以物理量计算)
employee_id = params.get("employee_id", "2222222222")
mode = params.get("mode", 1)
target_torque = params.get("target_torque", 300)
torque_min = params.get("torque_min", 270)
torque_max = params.get("torque_max", 330)
target_angle = int(params.get("target_angle", 0) * 10)
angle_min = int(params.get("angle_min", 1) * 10)
angle_max = int(params.get("angle_max", 360) * 10)
# 扭矩以 Nm 表示,支持一位小数
target_torque_nm = float(params.get("target_torque", 300.0))
torque_min_nm = float(params.get("torque_min", 270.0))
torque_max_nm = float(params.get("torque_max", 330.0))
# 角度以度表示协议中仍按×10存整数
target_angle_deg = float(params.get("target_angle", 0.0))
angle_min_deg = float(params.get("angle_min", 1.0))
angle_max_deg = float(params.get("angle_max", 360.0))
# 模拟实际值(略高于目标值,表示成功)
actual_torque = target_torque + 5 # 实际扭矩略高于目标
actual_angle = int(params.get("target_angle", 45) * 10) if mode == 2 else 0
actual_torque_nm = target_torque_nm + 0.5 # 实际扭矩略高于目标
actual_angle_deg = float(params.get("target_angle", 45.0)) if mode == 2 else 0.0
# 协议编码:扭矩 Nm×10角度 deg×10
target_torque_val = int(round(target_torque_nm * 10))
torque_min_val = int(round(torque_min_nm * 10))
torque_max_val = int(round(torque_max_nm * 10))
actual_torque_val = int(round(actual_torque_nm * 10))
target_angle_val = int(round(target_angle_deg * 10))
angle_min_val = int(round(angle_min_deg * 10))
angle_max_val = int(round(angle_max_deg * 10))
actual_angle_val = int(round(actual_angle_deg * 10))
# 获取当前时间
now = datetime.now()
@ -219,29 +240,29 @@ class WrenchSimulator:
# 参数模式 (1字节)
data.append(mode)
# 目标扭矩 (2字节)
data.extend(struct.pack('>H', target_torque))
# 目标扭矩 (2字节Nm×10)
data.extend(struct.pack('>H', target_torque_val))
# 实际扭矩 (2字节)
data.extend(struct.pack('>H', actual_torque))
# 实际扭矩 (2字节Nm×10)
data.extend(struct.pack('>H', actual_torque_val))
# 目标角度 (2字节)
data.extend(struct.pack('>H', target_angle))
# 目标角度 (2字节deg×10)
data.extend(struct.pack('>H', target_angle_val))
# 实际角度 (2字节)
data.extend(struct.pack('>H', actual_angle))
# 实际角度 (2字节deg×10)
data.extend(struct.pack('>H', actual_angle_val))
# 扭矩上限 (2字节)
data.extend(struct.pack('>H', torque_max))
# 扭矩上限 (2字节Nm×10)
data.extend(struct.pack('>H', torque_max_val))
# 扭矩下限 (2字节)
data.extend(struct.pack('>H', torque_min))
# 扭矩下限 (2字节Nm×10)
data.extend(struct.pack('>H', torque_min_val))
# 角度上限 (2字节)
data.extend(struct.pack('>H', angle_max))
# 角度上限 (2字节deg×10)
data.extend(struct.pack('>H', angle_max_val))
# 角度下限 (2字节)
data.extend(struct.pack('>H', angle_min))
# 角度下限 (2字节deg×10)
data.extend(struct.pack('>H', angle_min_val))
# 计算并添加校验码
checksum = self._calculate_checksum(data)