基于pymodbus读取离散输入值并触发自动化任务的技术问询
代码问题修正与优化建议
一、修复代码中的语法与基础错误
你的代码存在语法、依赖及逻辑问题,先修正这些基础问题:
from pymodbus.client.sync import ModbusTcpClient import os import time # 补充缺失的time模块 host = '100.100.110.104' port = 502 client = ModbusTcpClient(host, port) # 初始化状态变量,避免重复触发 last_state = 0 while True: # 优化连接逻辑:仅在断开时重连 if not client.is_socket_open(): if not client.connect(): print("无法连接到PLC,等待重试...") time.sleep(5) continue try: # 读取起始地址1000的1个离散输入点 rr = client.read_discrete_inputs(1000, 1, unit=1) # 检查读取是否成功 if rr.isError(): print(f"读取失败: {rr}") time.sleep(5) continue current_state = rr.bits[0] # 仅在状态从0变为1时触发脚本 if current_state == 1 and last_state == 0: print("触发工单录入脚本") os.system('python AUTOMATED.pyw') # 更新状态记录 last_state = current_state except Exception as e: print(f"运行异常: {e}") client.close() # 异常后断开连接,下次循环重连 time.sleep(5)
二、无PLC测试的解决方案
可以用pymodbus搭建本地Modbus TCP模拟器,模拟PLC的离散输入状态:
模拟服务器代码(单独运行)
from pymodbus.server.sync import StartTcpServer from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext # 模拟1000个离散输入点,初始值全为0 store = ModbusSlaveContext(di=[0]*1000) context = ModbusServerContext(slaves=store, single=True) # 启动本地模拟服务器,端口502 StartTcpServer(context, address=("localhost", 502))
测试配置
把主代码里的host改为'localhost',运行模拟服务器后,你可以手动修改模拟数据的离散输入值(比如将di[999]设为1,对应起始地址1000),即可测试触发逻辑。
三、关键优化点说明
- 语法修正:if判断用
==而非=,补充语句末尾的冒号,导入缺失的time模块 - 连接优化:避免循环内重复连接,仅在断开时尝试重连
- 去重触发:通过状态变量记录上一次状态,仅在开关从断开变闭合时执行脚本,避免重复触发
- 异常处理:捕获读取和连接异常,避免程序直接崩溃
内容的提问来源于stack exchange,提问作者Peddlur
相关产品推荐
相关产品推荐

