修改步进电机接口、通讯方式和EMV的接口
This commit is contained in:
518
EMV/EMV_test.py
518
EMV/EMV_test.py
@ -1,37 +1,37 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
# @Time : 2026/1/8 16:52
|
||||
# @Time : 2025/12/12 14:39
|
||||
# @Author : reenrr
|
||||
# @File : EMV_test.py
|
||||
# @Desc : 网络继电器控制输入、输出设备测试程序
|
||||
# @File : EMV.py
|
||||
# @Desc : 网络继电器控制输入、输出设备 修改了接口,需测试
|
||||
'''
|
||||
import socket
|
||||
import binascii
|
||||
import time
|
||||
from threading import Event, Lock
|
||||
import threading
|
||||
import logging
|
||||
|
||||
from typing import Union
|
||||
|
||||
# 网络继电器的 IP 和端口
|
||||
HOST = '192.168.5.18'
|
||||
PORT = 50000
|
||||
|
||||
# 控件命名映射
|
||||
SOLENOID_VALVE1 = 'solenoid_valve1' # 控制排料机构NG时的电磁阀1
|
||||
SOLENOID_VALVE2 = 'solenoid_valve2' # 控制排料机构NG时的电磁阀2
|
||||
ABSORB_SOLENOID_VALVE1 = 'absorb_solenoid_valve1' # 控制吸取设备的电磁阀1
|
||||
ABSORB_SOLENOID_VALVE2 = 'absorb_solenoid_valve2' # 控制吸取设备的电磁阀2
|
||||
ABSORB_SOLENOID_VALVE3 = 'absorb_solenoid_valve3' # 控制吸取设备的电磁阀3
|
||||
ABSORB_SOLENOID_VALVE4 = 'absorb_solenoid_valve4' # 控制吸取设备的电磁阀4
|
||||
ABSORB_SOLENOID_VALVE5 = 'absorb_solenoid_valve5' # 控制吸取设备的电磁阀5
|
||||
SOLENOID_VALVE1 = 'solenoid_valve1' # 控制排料机构NG时的电磁阀1
|
||||
SOLENOID_VALVE2 = 'solenoid_valve2' # 控制排料机构NG时的电磁阀2
|
||||
ABSORB_SOLENOID_VALVE1 = 'absorb_solenoid_valve1' # 控制吸取设备的电磁阀1
|
||||
ABSORB_SOLENOID_VALVE2 = 'absorb_solenoid_valve2' # 控制吸取设备的电磁阀2
|
||||
ABSORB_SOLENOID_VALVE3 = 'absorb_solenoid_valve3' # 控制吸取设备的电磁阀3
|
||||
ABSORB_SOLENOID_VALVE4 = 'absorb_solenoid_valve4' # 控制吸取设备的电磁阀4
|
||||
ABSORB_SOLENOID_VALVE5 = 'absorb_solenoid_valve5' # 控制吸取设备的电磁阀5
|
||||
|
||||
# 传感器命名映射
|
||||
CONVEYOR1_SENSOR = 'conveyor1_sensor' # 传送带1的行程开关
|
||||
CONVEYOR2_SENSOR = 'conveyor2_sensor' # 传送带2的行程开关
|
||||
PRESS_SENSOR1 = 'press_sensor1' # 传送带1旁边的按压开关1
|
||||
PRESS_SENSOR2 = 'press_sensor2' # 传送带1旁边的按压开关2
|
||||
FIBER_SENSOR = 'fiber_sensor' # 传送带1旁边的光纤传感器
|
||||
CONVEYOR1_SENSOR = 'conveyor1_sensor' # 传送带1的行程开关
|
||||
CONVEYOR2_SENSOR = 'conveyor2_sensor' # 传送带2的行程开关
|
||||
PRESS_SENSOR1 = 'press_sensor1' # 传送带1旁边的按压开关1
|
||||
PRESS_SENSOR2 = 'press_sensor2' # 传送带1旁边的按压开关2
|
||||
FIBER_SENSOR = 'fiber_sensor' # 传送带1旁边的光纤传感器
|
||||
|
||||
# 控件控制报文
|
||||
valve_commands = {
|
||||
@ -48,19 +48,19 @@ valve_commands = {
|
||||
'close': '000000000006010500020000',
|
||||
},
|
||||
ABSORB_SOLENOID_VALVE2: {
|
||||
'open': '00000000000601050002FF00',
|
||||
'open': '00000000000601050003FF00',
|
||||
'close': '000000000006010500030000',
|
||||
},
|
||||
ABSORB_SOLENOID_VALVE3: {
|
||||
'open': '00000000000601050002FF00',
|
||||
'open': '00000000000601050004FF00',
|
||||
'close': '000000000006010500040000',
|
||||
},
|
||||
ABSORB_SOLENOID_VALVE4: {
|
||||
'open': '00000000000601050002FF00',
|
||||
'open': '00000000000601050005FF00',
|
||||
'close': '000000000006010500050000',
|
||||
},
|
||||
ABSORB_SOLENOID_VALVE5: {
|
||||
'open': '00000000000601050002FF00',
|
||||
'open': '00000000000601050006FF00',
|
||||
'close': '000000000006010500060000',
|
||||
}
|
||||
}
|
||||
@ -80,7 +80,6 @@ device_bit_map = {
|
||||
ABSORB_SOLENOID_VALVE3: 4,
|
||||
ABSORB_SOLENOID_VALVE4: 5,
|
||||
ABSORB_SOLENOID_VALVE5: 6
|
||||
|
||||
}
|
||||
|
||||
device_name_map = {
|
||||
@ -111,50 +110,77 @@ sensor_name_map = {
|
||||
CONVEYOR2_SENSOR: '传送带2开关'
|
||||
}
|
||||
|
||||
|
||||
# -------------全局事件-------------
|
||||
press_sensors_triggered = Event()
|
||||
fiber_triggered = Event() # 光纤传感器触发事件
|
||||
fiber_lock = Lock() # 线程锁,保护共享变量
|
||||
valve1_open_flag = False # 电磁阀1打开标志
|
||||
|
||||
|
||||
class RelayController:
|
||||
def __init__(self):
|
||||
"""初始化继电器控制器"""
|
||||
self.socket = None
|
||||
self.sock = None
|
||||
self.is_connected = False # 长连接状态标记
|
||||
|
||||
# 线程相关状态
|
||||
self.fiber_thread = None # 保存光纤传感器线程对象
|
||||
self.fiber_monitor_running = False # 光纤传感器监听线程运行标志
|
||||
def connect(self) -> bool:
|
||||
"""
|
||||
建立长连接
|
||||
:return: True-连接成功,False-连接失败
|
||||
"""
|
||||
if not self.is_connected:
|
||||
try:
|
||||
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.sock.settimeout(3)
|
||||
self.sock.connect((HOST, PORT))
|
||||
self.is_connected = True
|
||||
print(f"长连接建立成功:{HOST}:{PORT}")
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"长连接建立失败:{e}")
|
||||
self.sock = None
|
||||
self.is_connected = False
|
||||
return False
|
||||
return True
|
||||
|
||||
self.press_sensors_thread = None # 保存按压开关线程对象
|
||||
self.press_sensors_monitor_running = False # 按压传感器监听线程运行标志
|
||||
self.last_press_sensor_status = False # 记录传感器上一次状态,初始为无信号(用于上升沿检测)
|
||||
def disconnect(self):
|
||||
"""断开长连接"""
|
||||
if self.sock and self.is_connected:
|
||||
try:
|
||||
self.sock.shutdown(socket.SHUT_RDWR)
|
||||
self.sock.close()
|
||||
print("长连接已正常断开")
|
||||
except Exception as e:
|
||||
print(f"断开长连接时出现异常:{e}")
|
||||
finally:
|
||||
self.sock = None
|
||||
self.is_connected = False
|
||||
|
||||
def send_command(self, command):
|
||||
def send_command(self, command: str) -> Union[bytes, bool]:
|
||||
"""
|
||||
将十六进制字符串转换为字节数据并发送
|
||||
:param command: 十六进制字符串
|
||||
:return: 响应字节数据 / False
|
||||
"""
|
||||
try:
|
||||
byte_data = binascii.unhexlify(command)
|
||||
|
||||
# 创建套接字并连接到继电器
|
||||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
|
||||
sock.connect((HOST, PORT))
|
||||
sock.send(byte_data)
|
||||
# 接收响应
|
||||
response = sock.recv(1024)
|
||||
# logging.info(f"收到响应: {binascii.hexlify(response)}")
|
||||
# 校验响应
|
||||
return response
|
||||
except Exception as e:
|
||||
logging.info(f"通信错误: {e}")
|
||||
if not self.is_connected or not self.sock:
|
||||
print("长连接未建立,无法发送指令")
|
||||
return False
|
||||
|
||||
def get_all_device_status(self, command_type='devices'):
|
||||
try:
|
||||
byte_data = binascii.unhexlify(command)
|
||||
self.sock.sendall(byte_data) # sendall确保数据全部发送
|
||||
# 接收响应
|
||||
response = self.sock.recv(1024)
|
||||
if not response:
|
||||
logging.warning("长连接接收空响应,可能连接已断开")
|
||||
self.is_connected = False
|
||||
return False
|
||||
# print(f"收到响应: {binascii.hexlify(response)}")
|
||||
# 校验响应
|
||||
return response
|
||||
except socket.timeout:
|
||||
print("长连接发送/接收超时")
|
||||
self.is_connected = False
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"通信错误: {e}")
|
||||
self.is_connected = False
|
||||
return False
|
||||
|
||||
def get_all_device_status(self, command_type: str='devices') -> dict[str, bool]:
|
||||
"""
|
||||
获取所有设备/传感器状态
|
||||
:param command_type: 'devices'(控件) / 'sensors'(传感器)
|
||||
@ -162,7 +188,7 @@ class RelayController:
|
||||
"""
|
||||
command = read_status_command.get(command_type)
|
||||
if not command:
|
||||
logging.info(f"未知的读取类型: {command_type}")
|
||||
print(f"未知的读取类型: {command_type}")
|
||||
return {}
|
||||
|
||||
response = self.send_command(command)
|
||||
@ -179,295 +205,143 @@ class RelayController:
|
||||
bit_map = sensor_bit_map
|
||||
name_map = sensor_name_map
|
||||
else:
|
||||
logging.info("不支持的映射类型")
|
||||
return{}
|
||||
print("不支持的映射类型")
|
||||
return {}
|
||||
|
||||
for key, bit_index in bit_map.items():
|
||||
state = status_bin[bit_index] == '1'
|
||||
status_dict[key] = state
|
||||
# readable = "开启" if state else "关闭"
|
||||
# logging.info(f"{device.capitalize()} 状态: {readable}")
|
||||
# print(f"{device.capitalize()} 状态: {readable}")
|
||||
else:
|
||||
logging.info("读取状态失败或响应无效")
|
||||
print("读取状态失败或响应无效")
|
||||
|
||||
return status_dict
|
||||
|
||||
def get_device_status(self, device_name, command_type='devices'):
|
||||
def set_device(self, device_name: str, state: bool):
|
||||
"""
|
||||
获取单个控件/传感器状态
|
||||
:param device_name:设备名称
|
||||
:param command_type: 'devices'/'sensors'
|
||||
:return:True(开启) / False(关闭) / None(无法读取)
|
||||
设置指定输出设备(DO)的开关状态
|
||||
:param device_name: 设备名称
|
||||
:param state: 目标状态 True--打开 FALSE--关闭
|
||||
"""
|
||||
status = self.get_all_device_status(command_type)
|
||||
return status.get(device_name, None)
|
||||
if device_name not in valve_commands:
|
||||
raise ValueError(f"未知设备:{device_name}")
|
||||
|
||||
def open(self, solenoid_valve1=False, solenoid_valve2=False, absorb_solenoid_valve1=False,
|
||||
absorb_solenoid_valve2=False, absorb_solenoid_valve3=False, absorb_solenoid_valve4=False,
|
||||
absorb_solenoid_valve5=False):
|
||||
"""
|
||||
根据状态决定是否执行开操作
|
||||
:param solenoid_valve1:是否打开电磁阀1
|
||||
:param solenoid_valve2:是否打开电磁阀2
|
||||
:param absorb_solenoid_valve1:是否打开吸取装置电磁阀1
|
||||
:param absorb_solenoid_valve2:是否打开吸取装置电磁阀2
|
||||
:param absorb_solenoid_valve3:是否打开吸取装置电磁阀3
|
||||
:param absorb_solenoid_valve4:是否打开吸取装置电磁阀4
|
||||
:param absorb_solenoid_valve5:是否打开吸取装置电磁阀5
|
||||
try:
|
||||
current = self.get_all_device_status()
|
||||
is_on = current.get(device_name, False)
|
||||
|
||||
:return:
|
||||
"""
|
||||
global valve1_open_time, valve1_open_flag
|
||||
status = self.get_all_device_status()
|
||||
if state and not is_on:
|
||||
self.send_command(valve_commands[device_name]['open'])
|
||||
elif not state and is_on:
|
||||
self.send_command(valve_commands[device_name]['close'])
|
||||
|
||||
if solenoid_valve1 and not status.get(SOLENOID_VALVE1, False):
|
||||
print("打开电磁阀1")
|
||||
self.send_command(valve_commands[SOLENOID_VALVE1]['open'])
|
||||
# 记录电磁阀1打开时的时间戳和标志
|
||||
with fiber_lock:
|
||||
valve1_open_time = time.time()
|
||||
valve1_open_flag = True
|
||||
|
||||
if solenoid_valve2 and not status.get(SOLENOID_VALVE2, False):
|
||||
print("打开电磁阀2")
|
||||
self.send_command(valve_commands[SOLENOID_VALVE2]['open'])
|
||||
|
||||
if absorb_solenoid_valve1 and not status.get(ABSORB_SOLENOID_VALVE1, False):
|
||||
print("打开吸取装置电磁阀1")
|
||||
self.send_command(valve_commands[ABSORB_SOLENOID_VALVE1]['open'])
|
||||
time.sleep(1) # 实际测试需要考虑这个延时是否合适
|
||||
|
||||
if absorb_solenoid_valve2 and not status.get(ABSORB_SOLENOID_VALVE2, False):
|
||||
print("打开吸取装置电磁阀2")
|
||||
self.send_command(valve_commands[ABSORB_SOLENOID_VALVE2]['open'])
|
||||
time.sleep(1) # 实际测试需要考虑这个延时是否合适
|
||||
|
||||
if absorb_solenoid_valve3 and not status.get(ABSORB_SOLENOID_VALVE3, False):
|
||||
print("打开吸取装置电磁阀3")
|
||||
self.send_command(valve_commands[ABSORB_SOLENOID_VALVE3]['open'])
|
||||
time.sleep(1) # 实际测试需要考虑这个延时是否合适
|
||||
|
||||
if absorb_solenoid_valve4 and not status.get(ABSORB_SOLENOID_VALVE4, False):
|
||||
print("打开吸取装置电磁阀4")
|
||||
self.send_command(valve_commands[ABSORB_SOLENOID_VALVE4]['open'])
|
||||
time.sleep(1) # 实际测试需要考虑这个延时是否合适
|
||||
|
||||
if absorb_solenoid_valve5 and not status.get(ABSORB_SOLENOID_VALVE5, False):
|
||||
print("打开吸取装置电磁阀5")
|
||||
self.send_command(valve_commands[ABSORB_SOLENOID_VALVE5]['open'])
|
||||
time.sleep(1) # 实际测试需要考虑这个延时是否合适
|
||||
|
||||
# 根据状态决定是否执行关操作
|
||||
def close(self, solenoid_valve1=False, solenoid_valve2=False, absorb_solenoid_valve1=False,
|
||||
absorb_solenoid_valve2=False, absorb_solenoid_valve3=False, absorb_solenoid_valve4=False,
|
||||
absorb_solenoid_valve5=False):
|
||||
"""
|
||||
根据状态决定是否执行关操作
|
||||
:param solenoid_valve1:是否关闭电磁阀1
|
||||
:param solenoid_valve2:是否关闭电磁阀2
|
||||
:param absorb_solenoid_valve1:是否关闭吸取电磁阀1
|
||||
:param absorb_solenoid_valve2:是否关闭吸取电磁阀2
|
||||
:param absorb_solenoid_valve3:是否关闭吸取电磁阀3
|
||||
:param absorb_solenoid_valve4:是否关闭吸取电磁阀4
|
||||
:param absorb_solenoid_valve5:是否关闭吸取电磁阀5
|
||||
|
||||
:return:
|
||||
"""
|
||||
global valve1_open_flag
|
||||
|
||||
status = self.get_all_device_status()
|
||||
|
||||
if solenoid_valve1 and status.get(SOLENOID_VALVE1, True):
|
||||
print("关闭电磁阀1")
|
||||
self.send_command(valve_commands[SOLENOID_VALVE1]['close'])
|
||||
# 重置电磁阀1打开标志
|
||||
with fiber_lock:
|
||||
valve1_open_flag = False
|
||||
|
||||
if solenoid_valve2 and status.get(SOLENOID_VALVE2, True):
|
||||
print("关闭电磁阀2")
|
||||
self.send_command(valve_commands[SOLENOID_VALVE2]['close'])
|
||||
|
||||
if absorb_solenoid_valve1 and status.get(ABSORB_SOLENOID_VALVE1, True):
|
||||
print("关闭吸取装置电磁阀1")
|
||||
self.send_command(valve_commands[ABSORB_SOLENOID_VALVE1]['close'])
|
||||
time.sleep(1) # 实际测试需要考虑这个延时是否合适
|
||||
|
||||
if absorb_solenoid_valve2 and status.get(ABSORB_SOLENOID_VALVE2, True):
|
||||
print("关闭吸取装置电磁阀2")
|
||||
self.send_command(valve_commands[ABSORB_SOLENOID_VALVE2]['close'])
|
||||
time.sleep(1) # 实际测试需要考虑这个延时是否合适
|
||||
|
||||
if absorb_solenoid_valve3 and status.get(ABSORB_SOLENOID_VALVE3, True):
|
||||
print("关闭吸取装置电磁阀3")
|
||||
self.send_command(valve_commands[ABSORB_SOLENOID_VALVE3]['close'])
|
||||
time.sleep(1) # 实际测试需要考虑这个延时是否合适
|
||||
|
||||
if absorb_solenoid_valve4 and status.get(ABSORB_SOLENOID_VALVE4, True):
|
||||
print("关闭吸取装置电磁阀4")
|
||||
self.send_command(valve_commands[ABSORB_SOLENOID_VALVE4]['close'])
|
||||
time.sleep(1) # 实际测试需要考虑这个延时是否合适
|
||||
|
||||
if absorb_solenoid_valve5 and status.get(ABSORB_SOLENOID_VALVE5, True):
|
||||
print("关闭吸取装置电磁阀5")
|
||||
self.send_command(valve_commands[ABSORB_SOLENOID_VALVE5]['close'])
|
||||
time.sleep(1) # 实际测试需要考虑这个延时是否合适
|
||||
|
||||
def fiber_sensor_monitor(self):
|
||||
"""
|
||||
光纤传感器监听线程,专门检测电磁阀打开后的触发状态
|
||||
"""
|
||||
global fiber_triggered, valve1_open_flag
|
||||
logging.info("光纤传感器监听线程已启动")
|
||||
|
||||
while self.fiber_monitor_running:
|
||||
try:
|
||||
# 增加短休眠,降低CPU占用,避免错过信号
|
||||
time.sleep(0.005)
|
||||
|
||||
# 获取光纤传感器状态
|
||||
fiber_status = self.get_device_status(FIBER_SENSOR, 'sensors')
|
||||
# 检测是否检测到信号
|
||||
if fiber_status:
|
||||
with fiber_lock:
|
||||
# 检查电磁阀1是否处于打开状态
|
||||
if valve1_open_flag:
|
||||
fiber_triggered.set()
|
||||
# 防止重复触发
|
||||
time.sleep(0.1)
|
||||
fiber_triggered.clear()
|
||||
except Exception as e:
|
||||
logging.info(f"光纤传感器监听异常:{e}")
|
||||
time.sleep(0.1) # 异常时增加休眠
|
||||
|
||||
def start_fiber_monitor(self):
|
||||
"""启动光纤传感器监听线程"""
|
||||
# 检查线程是否已在运行
|
||||
if self.fiber_monitor_running or (self.fiber_thread and self.fiber_thread.is_alive()):
|
||||
logging.warning("光纤传感器监听线程已在运行,无需重复启动")
|
||||
return
|
||||
|
||||
# 启动线程
|
||||
self.fiber_monitor_running = True
|
||||
self.fiber_thread = threading.Thread(
|
||||
target=self.fiber_sensor_monitor,
|
||||
daemon=True
|
||||
)
|
||||
self.fiber_thread.start()
|
||||
logging.info("光纤传感器监听线程启动成功")
|
||||
|
||||
def stop_fiber_monitor(self):
|
||||
"""停止光纤传感器监听线程"""
|
||||
self.fiber_monitor_running = False
|
||||
# 等待线程完全退出
|
||||
if self.fiber_thread and self.fiber_thread.is_alive():
|
||||
self.fiber_thread.join(timeout=1)
|
||||
logging.info("光纤传感器监听线程已停止")
|
||||
|
||||
def press_sensors_monitor(self, check_interval=0.1):
|
||||
"""
|
||||
双压传感器监听线程
|
||||
:param check_interval: 检测间隔
|
||||
:return:
|
||||
"""
|
||||
global press_sensors_triggered
|
||||
logging.info("双压传感器监听线程已启动")
|
||||
|
||||
while self.press_sensors_monitor_running:
|
||||
try:
|
||||
# 检测两个传感器任意一个是否触发
|
||||
press_sensor1_status = self.get_device_status(PRESS_SENSOR1, 'sensors')
|
||||
press_sensor2_status = self.get_device_status(PRESS_SENSOR2, 'sensors')
|
||||
current_sensor_state = press_sensor1_status or press_sensor2_status
|
||||
|
||||
# 上升沿触发(仅从无信号-->有信号时,才触发事件)
|
||||
if current_sensor_state and not self.last_press_sensor_status:
|
||||
press_sensors_triggered.set() # 触发事件,通知主线程
|
||||
logging.info("双压传感器触发:线条已落到传送带")
|
||||
|
||||
# 更新上一次传感器状态,为下一次上升沿检测做准备
|
||||
self.last_press_sensor_status = current_sensor_state
|
||||
# 传感器检测间隔
|
||||
time.sleep(check_interval)
|
||||
except Exception as e:
|
||||
logging.info(f"双压传感器监听异常: {e}")
|
||||
time.sleep(0.1) # 异常时增加休眠
|
||||
|
||||
def start_press_sensors_monitor(self):
|
||||
"""启动双压传感器监听线程"""
|
||||
# 检查线程是否已在运行
|
||||
if self.press_sensors_monitor_running or (self.press_sensors_thread and self.press_sensors_thread.is_alive()):
|
||||
logging.warning("双压传感器监听线程已在运行,无需重复启动")
|
||||
return
|
||||
|
||||
# 启动线程
|
||||
self.press_sensors_monitor_running = True
|
||||
self.press_sensors_thread = threading.Thread(
|
||||
target=self.press_sensors_monitor,
|
||||
daemon=True
|
||||
)
|
||||
self.press_sensors_thread.start()
|
||||
logging.info("双压传感器监听线程启动成功")
|
||||
|
||||
def stop_press_sensors_monitor(self):
|
||||
"""停止光纤传感器监听线程"""
|
||||
self.press_sensors_monitor_running = False
|
||||
# 等待线程完全退出
|
||||
if self.press_sensors_thread and self.press_sensors_thread.is_alive():
|
||||
self.press_sensors_thread.join(timeout=1)
|
||||
logging.info("双压传感器监听线程已停止")
|
||||
except Exception as e:
|
||||
raise RuntimeError(f"设置设备 '{device_name}' 状态失败: {e}") from e
|
||||
|
||||
|
||||
# 全局继电器实例
|
||||
global_relay = RelayController()
|
||||
# 全局变量
|
||||
GLOBAL_RELAY = None
|
||||
|
||||
# ------------对外接口----------
|
||||
def control_solenoid():
|
||||
"""
|
||||
线条不合格场景专用:控制电磁阀+监听光纤传感器
|
||||
执行流程:启动监听-->打开电磁阀-->等待检测-->关闭电磁阀-->停止监听
|
||||
"""
|
||||
global fiber_triggered, global_relay
|
||||
# --------对外接口--------
|
||||
def init_relay():
|
||||
"""初始化网络继电器实例+建立长连接"""
|
||||
global GLOBAL_RELAY
|
||||
|
||||
try:
|
||||
# 启动光纤传感器监听线程
|
||||
global_relay.start_fiber_monitor()
|
||||
|
||||
# 重置光纤传感器触发事件,准备检测
|
||||
fiber_triggered.clear()
|
||||
|
||||
# 同时打开电磁阀1、2
|
||||
global_relay.open(solenoid_valve1=True, solenoid_valve2=True)
|
||||
logging.info("电磁阀1、2已打开")
|
||||
|
||||
# 等待线条掉落(最多等待2秒)
|
||||
timeout = 3.0
|
||||
start_time = time.time()
|
||||
fiber_detected = False
|
||||
# 等待光纤传感器触发或超时
|
||||
while time.time() - start_time < timeout:
|
||||
if fiber_triggered.is_set():
|
||||
fiber_detected = True
|
||||
logging.info("该NG线条掉入费料区")
|
||||
break
|
||||
time.sleep(0.01) # 降低CPU空转
|
||||
|
||||
if not fiber_detected:
|
||||
logging.info("出问题!!!,红外传感器未检测到线条")
|
||||
|
||||
# 关闭电磁阀1、2
|
||||
time.sleep(0.2) # 等待线条掉落
|
||||
global_relay.close(solenoid_valve1=True, solenoid_valve2=True)
|
||||
logging.info("电磁阀1、2已关闭")
|
||||
|
||||
# 停止光纤传感器监听线程
|
||||
global_relay.stop_fiber_monitor()
|
||||
GLOBAL_RELAY = RelayController()
|
||||
GLOBAL_RELAY.connect()
|
||||
|
||||
except Exception as e:
|
||||
logging.info(f"操作电磁阀失败:{str(e)}")
|
||||
# 异常时也要停止线程,避免残留
|
||||
global_relay.stop_fiber_monitor()
|
||||
raise ValueError(f"初始化失败{e}")
|
||||
|
||||
def deinit_relay():
|
||||
"""断开长连接"""
|
||||
global GLOBAL_RELAY
|
||||
|
||||
if GLOBAL_RELAY is not None:
|
||||
GLOBAL_RELAY.disconnect()
|
||||
GLOBAL_RELAY = None
|
||||
|
||||
def ng_push():
|
||||
"""NG推料流程"""
|
||||
try:
|
||||
# 同时打开电磁阀1、2
|
||||
write_do(SOLENOID_VALVE1, True)
|
||||
write_do(SOLENOID_VALVE2, True)
|
||||
print(f"电磁阀1、2已打开")
|
||||
|
||||
# 等待线条掉落
|
||||
time.sleep(0.5)
|
||||
|
||||
write_do(SOLENOID_VALVE1, False)
|
||||
write_do(SOLENOID_VALVE2, False)
|
||||
print(f"电磁阀1、2已关闭")
|
||||
|
||||
except Exception as e:
|
||||
print(f"NG推料失败:{e}")
|
||||
raise RuntimeError("NG推料流程异常") from e
|
||||
|
||||
def write_do(device_name: str, state: bool):
|
||||
"""
|
||||
控制单个数字输出设备(DO)的开关状态
|
||||
:param device_name: 设备名称
|
||||
:param state: True:打开 False:关闭
|
||||
"""
|
||||
global GLOBAL_RELAY
|
||||
if GLOBAL_RELAY is None:
|
||||
raise ValueError("未初始化实例")
|
||||
|
||||
# 验证设备是否存在
|
||||
if device_name not in device_bit_map:
|
||||
valid_devices = list(device_bit_map.keys())
|
||||
raise ValueError(f"无效的设备名 '{device_name}'。有效设备: {valid_devices}")
|
||||
|
||||
# 确保已连接
|
||||
if not GLOBAL_RELAY.is_connected:
|
||||
if not GLOBAL_RELAY.connect():
|
||||
raise RuntimeError("无法连接到网络继电器")
|
||||
|
||||
try:
|
||||
GLOBAL_RELAY.set_device(device_name, state)
|
||||
|
||||
except Exception as e:
|
||||
raise RuntimeError(f"控制设备 '{device_name}' 失败: {e}")
|
||||
|
||||
def read_all_io() -> dict[str, dict[str, bool]]:
|
||||
"""
|
||||
读取所有DI(传感器)和DO(设备)状态
|
||||
:return: {'devices': {...}, 'sensors': {...}}
|
||||
"""
|
||||
global GLOBAL_RELAY
|
||||
if GLOBAL_RELAY is None:
|
||||
raise ValueError("未初始化")
|
||||
|
||||
try:
|
||||
devices = GLOBAL_RELAY.get_all_device_status('devices')
|
||||
sensors = GLOBAL_RELAY.get_all_device_status('sensors')
|
||||
return {'devices': devices, 'sensors': sensors}
|
||||
|
||||
except Exception as e:
|
||||
print(f"读取IO状态失败:{e}")
|
||||
raise RuntimeError("读取IO失败") from e
|
||||
|
||||
# ------------测试接口-------------
|
||||
if __name__ == '__main__':
|
||||
control_solenoid()
|
||||
init_relay()
|
||||
|
||||
write_do(SOLENOID_VALVE1, True)
|
||||
|
||||
time.sleep(5)
|
||||
|
||||
io_status = read_all_io()
|
||||
for name, status in io_status['devices'].items():
|
||||
status_str = "开启" if status else "关闭"
|
||||
print(f"{device_name_map.get(name, name)}: {status_str}")
|
||||
|
||||
deinit_relay()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user