first commit
This commit is contained in:
85
src/divices/relay.py
Normal file
85
src/divices/relay.py
Normal file
@ -0,0 +1,85 @@
|
||||
import socket
|
||||
import binascii
|
||||
import time
|
||||
from src.utils.logger import app_logger
|
||||
|
||||
|
||||
class RelayController:
|
||||
"""网络继电器控制器"""
|
||||
|
||||
def __init__(self, host: str, port: int):
|
||||
self.host = host
|
||||
self.port = port
|
||||
self.logger = app_logger.getChild('RelayController')
|
||||
|
||||
# 设备DO端口映射 (将在初始化时从配置加载)
|
||||
self.device_mapping = {}
|
||||
|
||||
# 继电器控制命令
|
||||
self.relay_commands = {
|
||||
0: {'open': '00000000000601050000FF00', 'close': '000000000006010500000000'},
|
||||
1: {'open': '00000000000601050001FF00', 'close': '000000000006010500010000'},
|
||||
2: {'open': '00000000000601050002FF00', 'close': '000000000006010500020000'},
|
||||
3: {'open': '00000000000601050003FF00', 'close': '000000000006010500030000'},
|
||||
4: {'open': '00000000000601050004FF00', 'close': '000000000006010500040000'}
|
||||
}
|
||||
|
||||
# 读取状态命令
|
||||
self.read_status_command = '000000000006010100000008'
|
||||
|
||||
def set_device_mapping(self, mapping: dict):
|
||||
"""设置设备映射"""
|
||||
self.device_mapping = mapping
|
||||
|
||||
def send_command(self, command_hex: str):
|
||||
"""发送命令到网络继电器"""
|
||||
try:
|
||||
byte_data = binascii.unhexlify(command_hex)
|
||||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
|
||||
sock.settimeout(5) # 设置超时
|
||||
sock.connect((self.host, self.port))
|
||||
sock.send(byte_data)
|
||||
response = sock.recv(1024)
|
||||
self.logger.debug(f"收到继电器响应: {binascii.hexlify(response)}")
|
||||
return response
|
||||
except Exception as e:
|
||||
self.logger.error(f"继电器通信错误: {e}")
|
||||
return None
|
||||
|
||||
def get_status(self):
|
||||
"""获取继电器状态"""
|
||||
response = self.send_command(self.read_status_command)
|
||||
status_dict = {}
|
||||
|
||||
if response and len(response) >= 10:
|
||||
status_byte = response[9]
|
||||
status_bin = f"{status_byte:08b}"[::-1]
|
||||
|
||||
# 根据设备映射返回状态
|
||||
for device_name, bit_index in self.device_mapping.items():
|
||||
status_dict[device_name] = status_bin[bit_index] == '1'
|
||||
else:
|
||||
self.logger.warning("读取继电器状态失败或响应无效")
|
||||
|
||||
return status_dict
|
||||
|
||||
def control(self, device_name: str, action: str):
|
||||
"""控制继电器开关"""
|
||||
if device_name not in self.device_mapping:
|
||||
self.logger.error(f"无效的继电器设备: {device_name}")
|
||||
return False
|
||||
|
||||
bit_index = self.device_mapping[device_name]
|
||||
|
||||
if bit_index not in self.relay_commands:
|
||||
self.logger.error(f"不支持的DO端口: {bit_index}")
|
||||
return False
|
||||
|
||||
if action not in self.relay_commands[bit_index]:
|
||||
self.logger.error(f"无效的继电器动作: {action}")
|
||||
return False
|
||||
|
||||
self.logger.info(f"控制继电器 {device_name} ({bit_index}) {action}")
|
||||
result = self.send_command(self.relay_commands[bit_index][action])
|
||||
time.sleep(0.1) # 短暂延迟确保命令执行
|
||||
return result is not None
|
||||
Reference in New Issue
Block a user