diff --git a/README_ARCHITECTURE.md b/README_ARCHITECTURE.md index 7292c4e..d701cfe 100644 --- a/README_ARCHITECTURE.md +++ b/README_ARCHITECTURE.md @@ -195,3 +195,5 @@ chmod +x start_frontend.sh 前端默认连接 `http://localhost:5000`,如需修改,编辑 `frontend/wrench_gui.py` 中的 `api_base_url` 变量。 + + diff --git a/SIMULATOR_README.md b/SIMULATOR_README.md index 44b39a6..ea49b9b 100644 --- a/SIMULATOR_README.md +++ b/SIMULATOR_README.md @@ -109,3 +109,5 @@ simulator = WrenchSimulator( 2. **端口被占用**:修改端口号或关闭占用端口的程序 3. **无响应**:检查网络连接和防火墙设置 + + diff --git a/SSH_TUNNEL_README.md b/SSH_TUNNEL_README.md new file mode 100644 index 0000000..c7e5006 --- /dev/null +++ b/SSH_TUNNEL_README.md @@ -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` 配置为系统服务 + +如有问题,请检查日志或联系技术支持。 + + diff --git a/backend/check_db.py b/backend/check_db.py index 860b084..052abf0 100644 --- a/backend/check_db.py +++ b/backend/check_db.py @@ -75,3 +75,5 @@ conn.close() print("\n" + "="*60) + + diff --git a/backend/check_results.py b/backend/check_results.py index 25cc1e4..937caec 100644 --- a/backend/check_results.py +++ b/backend/check_results.py @@ -26,3 +26,5 @@ else: conn.close() + + diff --git a/backend/diagnose.py b/backend/diagnose.py index a3a4687..003b906 100644 --- a/backend/diagnose.py +++ b/backend/diagnose.py @@ -66,3 +66,5 @@ print("\n" + "="*60) print("诊断完成") print("="*60) + + diff --git a/backend/migrate_add_device_info.py b/backend/migrate_add_device_info.py index 4aeb3e8..f5a4a2a 100644 --- a/backend/migrate_add_device_info.py +++ b/backend/migrate_add_device_info.py @@ -111,3 +111,5 @@ def migrate_add_device_info(): if __name__ == "__main__": migrate_add_device_info() + + diff --git a/backend/quick_test.py b/backend/quick_test.py index cbd9b49..c7bff49 100644 --- a/backend/quick_test.py +++ b/backend/quick_test.py @@ -53,3 +53,5 @@ print("2. 后端服务器日志中的调试信息") print("3. 重启后端服务器") print("="*60) + + diff --git a/backend/requirements.txt b/backend/requirements.txt index 5ab5760..2a62ec4 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -1,3 +1,5 @@ Flask==2.3.3 flask-cors==4.0.0 + + diff --git a/backend/start_backend.bat b/backend/start_backend.bat index cb23426..1ec6b6f 100644 --- a/backend/start_backend.bat +++ b/backend/start_backend.bat @@ -8,3 +8,5 @@ cd /d %~dp0 python app.py pause + + diff --git a/backend/start_backend.sh b/backend/start_backend.sh index dd31b2c..f39731c 100644 --- a/backend/start_backend.sh +++ b/backend/start_backend.sh @@ -6,3 +6,5 @@ echo "" cd "$(dirname "$0")" python3 app.py + + diff --git a/backend/test_api.py b/backend/test_api.py index 52e1afe..ac8c2d8 100644 --- a/backend/test_api.py +++ b/backend/test_api.py @@ -40,3 +40,5 @@ def test_query(): if __name__ == "__main__": test_query() + + diff --git a/backend/wrench.db b/backend/wrench.db index b1a844a..c3ceff7 100644 Binary files a/backend/wrench.db and b/backend/wrench.db differ diff --git a/frontend/requirements.txt b/frontend/requirements.txt index b405fdc..2f4a072 100644 --- a/frontend/requirements.txt +++ b/frontend/requirements.txt @@ -1,2 +1,4 @@ requests==2.31.0 + + diff --git a/frontend/start_frontend.bat b/frontend/start_frontend.bat index 29a5178..337ecc6 100644 --- a/frontend/start_frontend.bat +++ b/frontend/start_frontend.bat @@ -8,3 +8,5 @@ cd /d %~dp0 python wrench_gui.py pause + + diff --git a/frontend/start_frontend.sh b/frontend/start_frontend.sh index a6f6f5e..ab1a459 100644 --- a/frontend/start_frontend.sh +++ b/frontend/start_frontend.sh @@ -6,3 +6,5 @@ echo "" cd "$(dirname "$0")" python3 wrench_gui.py + + diff --git a/ssh_tunnel_auto.sh b/ssh_tunnel_auto.sh new file mode 100644 index 0000000..4582c16 --- /dev/null +++ b/ssh_tunnel_auto.sh @@ -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 + + diff --git a/ssh_tunnel_service.sh b/ssh_tunnel_service.sh new file mode 100644 index 0000000..32cdf74 --- /dev/null +++ b/ssh_tunnel_service.sh @@ -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" + + diff --git a/ssh_tunnel_setup.sh b/ssh_tunnel_setup.sh new file mode 100644 index 0000000..82ba33b --- /dev/null +++ b/ssh_tunnel_setup.sh @@ -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 " 或者使用自动重连脚本(见下方)" + + diff --git a/start_simulator.bat b/start_simulator.bat index 0e01b28..cb4a335 100644 --- a/start_simulator.bat +++ b/start_simulator.bat @@ -7,3 +7,5 @@ echo. python wrench_simulator.py pause + + diff --git a/start_simulator.sh b/start_simulator.sh index b6ed9e2..924cd5e 100644 --- a/start_simulator.sh +++ b/start_simulator.sh @@ -5,3 +5,5 @@ echo "========================================" echo "" python3 wrench_simulator.py + + diff --git a/test_device_connection.py b/test_device_connection.py index b8f75ae..14f04aa 100644 --- a/test_device_connection.py +++ b/test_device_connection.py @@ -79,3 +79,5 @@ if __name__ == "__main__": print("4. 设备地址码不匹配") print("=" * 60) + + diff --git a/test_simulator.py b/test_simulator.py index ecbce55..1a6c6b1 100644 --- a/test_simulator.py +++ b/test_simulator.py @@ -70,3 +70,5 @@ def test_simulator(): if __name__ == "__main__": test_simulator() + + diff --git a/wrench_controller.py b/wrench_controller.py index 9776541..4783494 100644 --- a/wrench_controller.py +++ b/wrench_controller.py @@ -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}°" } diff --git a/wrench_simulator.py b/wrench_simulator.py index 4a1ec5b..77052f8 100644 --- a/wrench_simulator.py +++ b/wrench_simulator.py @@ -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)