华荣三照明、合信、荣欣八组合馈电

This commit is contained in:
冯佳
2025-06-25 11:36:43 +08:00
parent 37d39f4578
commit 25b3cb7f2e
494 changed files with 114074 additions and 0 deletions

Binary file not shown.

34
Test/Temperature.py Normal file
View File

@ -0,0 +1,34 @@
import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt
# 读取数据
data = np.genfromtxt('10K 热敏电阻对照表25°为基准.csv', delimiter=',', skip_header=1,
usecols=(0, 2), names=['Temperature', 'Rnor'])
# 提取温度和Rnor数据
temperature = data['Temperature']
r_nor = data['Rnor']
# 定义拟合函数,这里采用二次函数作为示例
def fit_function(x, a, b, c):
return a * x ** 2 + b * x + c
# 进行曲线拟合
p0 = [1, 1, 1] # 初始猜测值
popt, pcov = curve_fit(fit_function, temperature, r_nor, p0=p0)
# 生成用于绘图的拟合数据
x_fit = np.linspace(-30, 300, 400)
y_fit = fit_function(x_fit, *popt)
# 绘制原始数据和拟合曲线
plt.scatter(temperature, r_nor, label='Original Data')
plt.plot(x_fit, y_fit, 'r-', label='Fitted Curve')
plt.xlabel('Temperature (°C)')
plt.ylabel('Rnor (k Ohms)')
plt.title('Thermistor Resistance vs Temperature Fitting')
plt.legend()
plt.grid(True)
plt.show()

23
Test/bmp_jpg.py Normal file
View File

@ -0,0 +1,23 @@
import os
from PIL import Image
# 输入目录和输出目录
input_directory = 'E:/Jfen_work/DWIN/GUI_PUMP_ICL/132-mode'
output_directory = 'E:/Jfen_work/DWIN/GUI_PUMP_ICL/132-mode-new'
# 确保输出目录存在
if not os.path.exists(output_directory):
os.makedirs(output_directory)
# 遍历输入目录中的所有文件
for filename in os.listdir(input_directory):
if filename.endswith('.bmp'):
# 打开 .bmp 文件
bmp_image_path = os.path.join(input_directory, filename)
with Image.open(bmp_image_path) as img:
# 创建 .jpg 文件路径
jpg_image_path = os.path.join(output_directory, os.path.splitext(filename)[0] + '.jpg')
# 将图片转换为 RGB 模式并保存为 .jpg 文件
img.convert('RGB').save(jpg_image_path, 'JPEG')
print("转换完成!")

112
Test/test.py Normal file
View File

@ -0,0 +1,112 @@
import sys
import logging
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QLineEdit
from PyQt5.QtCore import Qt
import modbus_tk.defines as cst
from modbus_tk import modbus_tcp
# 配置日志以十六进制形式显示报文
logging.basicConfig()
log = logging.getLogger('modbus_tk')
log.setLevel(logging.DEBUG)
class ModbusControlWindow(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Modbus Control Window")
self.setGeometry(100, 140, 400, 200)
self.label_ip = QLabel("IP Address:", self)
self.label_ip.move(20, 20)
self.text_ip = QLineEdit("192.168.1.181", self)
self.text_ip.setGeometry(120, 20, 200, 20)
self.label_device_id = QLabel("Device ID:", self)
self.label_device_id.move(20, 60)
self.text_device_id = QLineEdit("1", self)
self.text_device_id.setGeometry(120, 60, 200, 20)
self.btn_addr646 = QPushButton("向上", self)
self.btn_addr646.move(20, 100)
self.btn_addr646.clicked.connect(lambda: self.send_modbus_command(646))
self.btn_addr647 = QPushButton("向下", self)
self.btn_addr647.move(120, 100)
self.btn_addr647.clicked.connect(lambda: self.send_modbus_command(647))
self.btn_addr648 = QPushButton("确定", self)
self.btn_addr648.move(220, 100)
self.btn_addr648.clicked.connect(lambda: self.send_modbus_command(648))
self.btn_addr649 = QPushButton("复位", self)
self.btn_addr649.move(320, 100)
self.btn_addr649.clicked.connect(lambda: self.send_modbus_command(649))
self.bin_addr628 = QPushButton("短路试验", self)
self.bin_addr628.move(20, 140)
self.bin_addr628.clicked.connect(lambda: self.send_modbus_command(628))
self.bin_addr629 = QPushButton("漏电试验", self)
self.bin_addr629.move(120, 140)
self.bin_addr629.clicked.connect(lambda: self.send_modbus_command(629))
self.bin_addr641 = QPushButton("过压试验", self)
self.bin_addr641.move(220, 140)
self.bin_addr641.clicked.connect(lambda: self.send_modbus_command(641))
self.bin_addr642 = QPushButton("电流断相试验", self)
self.bin_addr642.move(320, 140)
self.bin_addr642.clicked.connect(lambda: self.send_modbus_command(642))
self.bin_addr636 = QPushButton("小车进", self)
self.bin_addr636.move(20, 180)
self.bin_addr636.clicked.connect(lambda: self.send_modbus_command(636))
self.bin_addr637 = QPushButton("小车退", self)
self.bin_addr637.move(120, 180)
self.bin_addr637.clicked.connect(lambda: self.send_modbus_command(637))
def send_modbus_command(self, addr):
ip_address = self.text_ip.text()
device_id = int(self.text_device_id.text())
# 连接Modbus设备
try:
master = modbus_tcp.TcpMaster(host=ip_address, port=502)
master.set_timeout(5.0)
except Exception as exc:
print(f"Failed to connect to Modbus device: {exc}")
return
# 发送Modbus功能码0x05
try:
master.execute(device_id, cst.WRITE_SINGLE_COIL, addr, output_value=1)
print(f"Modbus command to address {addr} sent successfully.")
except Exception as exc:
print(f"Failed to send Modbus command to address {addr}: {exc}")
finally:
master.close()
def keyPressEvent(self, event):
if event.key() == Qt.Key_Up:
self.send_modbus_command(646)
elif event.key() == Qt.Key_Down:
self.send_modbus_command(647)
elif event.key() == Qt.Key_Return or event.key() == Qt.Key_Enter:
self.send_modbus_command(648)
elif event.key() == Qt.Key_Space:
self.send_modbus_command(649)
elif event.key() == Qt.Key_A:
self.send_modbus_command(628)
else:
super().keyPressEvent(event)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = ModbusControlWindow()
window.show()
sys.exit(app.exec_())

285
Test/test_cuver.py Normal file
View File

@ -0,0 +1,285 @@
import sys
import serial
from serial.tools import list_ports
import struct
import threading
from PyQt5.QtWidgets import (
QApplication, QWidget, QVBoxLayout, QHBoxLayout, QTextEdit, QLineEdit, QPushButton,
QComboBox, QLabel, QCheckBox
)
from PyQt5.QtCore import QTimer
# 定义ZBUS命令类型
class ZBUS_CMD:
ZBUS_FRAME_NODE_INFO_REQUEST = 0
ZBUS_FRAME_NODE_ID_LOCK = 1 # 地址锁定命令
ZBUS_FRAME_NODE_ID_UNLOCK = 2
ZBUS_FRAME_ENTER_AUTO_BAUD = 3
ZBUS_FRAME_FLUSH_GLOBAL_STATUS = 4
ZBUS_FRAME_FLUSH_OUTPUT = 5
ZBUS_FRAME_FLUSH_INPUT = 6
ZBUS_FRAME_TOKEN_PASS = 7 # 令牌传递
ZBUS_FRAME_MODBUS = 8 # Modbus RTU数据
ZBUS_FRAME_CONFIG_TOKEN = 9
ZBUS_FRAME_PATH_TO_NEXT = 10
ZBUS_FRAME_TRANSMIT_AUTO_BAUD = 11 # 发送自动波特率帧, 方便从机配置波特率
ZBUS_FRAME_FILE_OPEN = 16 # 打开文件
ZBUS_FRAME_FILE_WRITE = 17 # 写入文件数据
ZBUS_FRAME_FILE_READ = 18 # 读取文件数据
ZBUS_FRAME_FILE_CLOSE = 19 # 文件关闭
ZBUS_FRAME_CUSTOM_COMMAND = 20 # 可以自定义命令
# ZBUS常量
ZBUS_LEAD_FLAG1 = 0x55
ZBUS_LEAD_FLAG2 = 0xAA
ZBUS_LEAD_FLAG_TOKEN = 0xDC
NODE_ID_GLOBAL = 0
NODE_ID_CONFIG = 1
NODE_ID_MODULE_AC12 = 2
STR_FORMAT_NAME = "name:"
STR_FORMAT_MODE = "mode:"
STR_FORMAT_WRITE = "write:"
# 定义ZBUS通讯类
class ZBUS:
def __init__(self) -> None:
self.SelfNodeId = NODE_ID_CONFIG # 配置节点Id
self.tx_frame_index = 0 # 发送帧索引
def ZBUS_CalculateLRC(self, buf_list):
lrc = sum(buf_list) # 使用 sum 函数简化计算
return lrc & 0xFFFF
def ZBUS_AssembleTxFrame(self, dest_node_id: int, source_node_id: int, frame_type: int, tx_buf: list):
# 组装一个发送帧
frame_index = self.tx_frame_index
self.tx_frame_index += 1
tx_list = []
if frame_type == ZBUS_CMD.ZBUS_FRAME_TRANSMIT_AUTO_BAUD:
tx_list = [0x55] * 32
return bytes(tx_list)
if frame_type == ZBUS_CMD.ZBUS_FRAME_TOKEN_PASS:
tx_list = struct.pack("BBB", ZBUS_LEAD_FLAG_TOKEN, dest_node_id, source_node_id)
return tx_list
cmd = frame_type # 获取枚举值
tx_list = struct.pack("BBBBBB", ZBUS_LEAD_FLAG1, ZBUS_LEAD_FLAG2, dest_node_id, source_node_id, cmd, frame_index)
if tx_buf is not None:
frame_size = len(tx_buf)
else:
frame_size = 0
tx_list += struct.pack("B", frame_size)
if tx_buf is not None:
tx_list += bytes(tx_buf)
lrc = self.ZBUS_CalculateLRC(tx_list)
tx_list += struct.pack("<H", lrc)
return tx_list
# GUI 类
class SerialGUI(QWidget):
def __init__(self) -> None:
super().__init__()
self.setWindowTitle("ZBUS 串口通讯")
self.setGeometry(100, 100, 800, 600)
self.layout = QVBoxLayout()
self.setLayout(self.layout)
self.text_area = QTextEdit()
self.layout.addWidget(self.text_area)
self.receive_area = QTextEdit()
self.layout.addWidget(self.receive_area)
self.hex_data_buffer = [] # 存储接收到的Hex数据
self.ascii_data_buffer = [] # 存储接收到的ASCII数据
self.display_mode = QCheckBox("显示Hex数据")
self.display_mode.stateChanged.connect(self.switch_display_mode)
self.layout.addWidget(self.display_mode)
self.create_widgets()
self.bus = ZBUS()
self.ser = None # 串口对象
self.serial_thread = None # 串口线程
self.timer = QTimer(self)
self.timer.timeout.connect(self.check_serial_insertion)
self.timer.start(1000)
self.available_ports = set() # 用于存储当前可用的串口设备
self.timer = QTimer(self)
self.timer.timeout.connect(self.check_serial_insertion)
self.timer.start(1000)
self.check_serial_insertion()
self.ThreadStop = False
def switch_display_mode(self):
self.receive_area.clear()
if self.display_mode.isChecked(): # 显示Hex数据
for line in self.hex_data_buffer:
self.receive_area.append(line)
else: # 显示ASCII数据
for line in self.ascii_data_buffer:
self.receive_area.append(line)
def create_widgets(self):
self.serial_port = QComboBox()
self.layout.addWidget(self.serial_port)
self.baud_rate = QLineEdit("115200")
self.layout.addWidget(self.baud_rate)
self.timeout = QLineEdit("0.5")
self.layout.addWidget(self.timeout)
self.send_hello_btn = QPushButton("发送 Hello")
self.send_hello_btn.clicked.connect(self.send_hello)
self.layout.addWidget(self.send_hello_btn)
self.send_auto_baud_btn = QPushButton("发送自动波特率帧")
self.send_auto_baud_btn.clicked.connect(self.send_auto_baud)
self.layout.addWidget(self.send_auto_baud_btn)
self.send_lock_btn = QPushButton("发送节点ID锁定帧")
self.send_lock_btn.clicked.connect(self.send_lock)
self.layout.addWidget(self.send_lock_btn)
self.get_node_status_btn = QPushButton("获取节点状态")
self.get_node_status_btn.clicked.connect(self.get_node_status)
self.layout.addWidget(self.get_node_status_btn)
self.zbus_file_open_btn = QPushButton("打开文件")
self.zbus_file_open_btn.clicked.connect(self.zbus_file_open_test)
self.layout.addWidget(self.zbus_file_open_btn)
self.send_custom_command_btn = QPushButton("发送自定义命令")
self.send_custom_command_btn.clicked.connect(self.send_custom_command)
self.layout.addWidget(self.send_custom_command_btn)
self.open_serial_btn = QPushButton("打开串口")
self.open_serial_btn.clicked.connect(self.open_serial)
self.layout.addWidget(self.open_serial_btn)
self.close_serial_btn = QPushButton("关闭串口")
self.close_serial_btn.clicked.connect(self.close_serial)
self.layout.addWidget(self.close_serial_btn)
def detect_serial_ports(self):
return set(port.device for port in list_ports.comports())
def check_serial_insertion(self):
current_ports = self.detect_serial_ports()
if current_ports != self.available_ports:
self.available_ports = current_ports
self.serial_port.clear()
self.serial_port.addItems(sorted(self.available_ports))
def open_serial(self):
try:
if not self.serial_port.currentText():
raise ValueError("请先选择一个串口")
self.ser = serial.Serial(
port=self.serial_port.currentText(),
baudrate=int(self.baud_rate.text()),
timeout=float(self.timeout.text())
)
self.ThreadStop = False
self.serial_thread = threading.Thread(target=self.serial_thread_func)
self.serial_thread.start()
self.log_text(f"成功打开串口: {self.serial_port.currentText()}")
except Exception as e:
self.log_text(f"打开串口失败: {str(e)}")
def close_serial(self):
try:
if self.ser and self.ser.is_open:
self.ThreadStop = True
self.serial_thread.join()
self.ser.close()
self.log_text("串口已关闭")
except Exception as e:
self.log_text(f"关闭串口失败: {str(e)}")
def serial_thread_func(self):
while not self.ThreadStop:
try:
if self.ser.in_waiting > 0:
data = self.ser.readline()
decoded_data = data.decode('utf-8', errors='replace').replace('\x00', '')
self.ascii_data_buffer.append(decoded_data)
hex_data = ' '.join(f'{byte:02X}' for byte in data)
self.hex_data_buffer.append(hex_data)
self.update_receive_area(decoded_data, hex_data)
except Exception as e:
self.log_text(f"读取串口数据失败: {str(e)}")
break
def update_receive_area(self, ascii_data, hex_data):
if self.display_mode.isChecked(): # 显示Hex数据
self.receive_area.append(hex_data)
else: # 显示ASCII数据
self.receive_area.append(ascii_data)
def send_data(self, data):
try:
if self.ser and self.ser.is_open:
self.ser.write(data)
self.log_text(f"发送数据: {data}")
else:
self.log_text("串口未打开")
except Exception as e:
self.log_text(f"发送数据失败: {str(e)}")
def send_hello(self):
data = b'Hello'
self.send_data(data)
def send_auto_baud(self):
data = self.bus.ZBUS_AssembleTxFrame(0, 1, ZBUS_CMD.ZBUS_FRAME_TRANSMIT_AUTO_BAUD, None)
self.send_data(data)
def send_lock(self):
data = self.bus.ZBUS_AssembleTxFrame(0, 1, ZBUS_CMD.ZBUS_FRAME_NODE_ID_LOCK, None)
self.send_data(data)
def get_node_status(self):
data = self.bus.ZBUS_AssembleTxFrame(0, 1, ZBUS_CMD.ZBUS_FRAME_NODE_INFO_REQUEST, None)
self.send_data(data)
def zbus_file_open_test(self):
filename = "example.txt"
data = list(f"{STR_FORMAT_NAME}{filename}\n".encode())
assembled_data = self.bus.ZBUS_AssembleTxFrame(0, 1, ZBUS_CMD.ZBUS_FRAME_FILE_OPEN, data)
self.send_data(assembled_data)
def send_custom_command(self):
data = b'Custom Command'
self.send_data(data)
def log_text(self, text):
self.text_area.append(text)
# 启动 GUI
if __name__ == "__main__":
app = QApplication(sys.argv)
gui = SerialGUI()
gui.show()
sys.exit(app.exec_())

343
Test/test_modscan.py Normal file
View File

@ -0,0 +1,343 @@
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton,
QLineEdit, QMessageBox, QComboBox, QTableWidget, QTableWidgetItem, QSpinBox, QGroupBox, QFormLayout, QAction, QMenuBar)
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtGui import QFont, QIcon
from modbus_tk import modbus_tcp, modbus_rtu
import serial
from modbus_tk.defines import *
class ModbusClient(QMainWindow):
def __init__(self):
super().__init__()
self.init_ui()
self.master = None
self.timer = QTimer()
self.timer.timeout.connect(self.update_data)
def init_ui(self):
self.setWindowTitle("Modbus 客户端")
self.setGeometry(100, 100, 900, 700)
self.setStyleSheet("""
QWidget {
background-color: #2e2e2e;
color: #ffffff;
font-family: Arial;
font-size: 14px;
}
QGroupBox {
font-weight: bold;
font-size: 16px;
border: 1px solid #555;
border-radius: 5px;
margin-top: 10px;
}
QGroupBox::title {
subcontrol-origin: margin;
subcontrol-position: top left;
padding: 10px;
}
QLabel {
font-size: 14px;
}
QLineEdit, QComboBox, QSpinBox {
padding: 5px;
border: 1px solid #555;
border-radius: 5px;
background-color: #444;
color: #fff;
}
QPushButton {
background-color: #555;
border: 1px solid #444;
border-radius: 5px;
padding: 5px;
}
QPushButton:hover {
background-color: #666;
}
QPushButton:pressed {
background-color: #777;
}
QTableWidget {
background-color: #444;
alternate-background-color: #555;
border: 1px solid #555;
}
QHeaderView::section {
background-color: #333;
color: #fff;
padding: 5px;
border: 1px solid #444;
}
""")
# 创建菜单栏
menu_bar = self.menuBar()
file_menu = menu_bar.addMenu('文件')
connection_menu = menu_bar.addMenu('连接')
action_menu = menu_bar.addMenu('操作')
# 创建文件菜单项
exit_action = QAction('退出', self)
exit_action.triggered.connect(self.close)
file_menu.addAction(exit_action)
# 创建连接菜单项
connect_action = QAction('连接', self)
connect_action.triggered.connect(self.connect_modbus)
connection_menu.addAction(connect_action)
disconnect_action = QAction('断开连接', self)
disconnect_action.triggered.connect(self.disconnect_modbus)
connection_menu.addAction(disconnect_action)
# 创建操作菜单项
execute_action = QAction('执行', self)
execute_action.triggered.connect(self.execute_action)
action_menu.addAction(execute_action)
monitor_action = QAction('开始监视', self)
monitor_action.triggered.connect(self.toggle_monitoring)
action_menu.addAction(monitor_action)
# 创建中心小部件
central_widget = QWidget()
self.setCentralWidget(central_widget)
main_layout = QVBoxLayout(central_widget)
# 连接部分
connection_group = QGroupBox("连接设置")
connection_layout = QFormLayout()
self.mode_combo = QComboBox()
self.mode_combo.addItem("TCP", "TCP")
self.mode_combo.addItem("RTU", "RTU")
self.mode_combo.currentIndexChanged.connect(self.toggle_mode)
connection_layout.addRow(QLabel("模式选择:"), self.mode_combo)
self.ip_edit = QLineEdit()
self.ip_edit.setPlaceholderText("输入 IP 地址")
connection_layout.addRow(QLabel("IP 地址 / 串口端口:"), self.ip_edit)
self.port_edit = QLineEdit()
self.port_edit.setPlaceholderText("输入端口号 / 波特率")
connection_layout.addRow(QLabel("端口号 / 波特率:"), self.port_edit)
self.connect_button = QPushButton("连接")
self.connect_button.clicked.connect(self.connect_modbus)
connection_layout.addRow(self.connect_button)
self.disconnect_button = QPushButton("断开连接")
self.disconnect_button.clicked.connect(self.disconnect_modbus)
self.disconnect_button.setEnabled(False)
connection_layout.addRow(self.disconnect_button)
connection_group.setLayout(connection_layout)
main_layout.addWidget(connection_group)
# 功能部分
function_group = QGroupBox("功能选择")
function_layout = QFormLayout()
self.function_combo = QComboBox()
self.function_combo.addItem("读线圈 (0)", READ_COILS)
self.function_combo.addItem("读输入 (1)", READ_DISCRETE_INPUTS)
self.function_combo.addItem("读保持寄存器 (3)", READ_HOLDING_REGISTERS)
self.function_combo.addItem("读输入寄存器 (4)", READ_INPUT_REGISTERS)
self.function_combo.addItem("写单个线圈 (5)", WRITE_SINGLE_COIL)
self.function_combo.addItem("写单个寄存器 (6)", WRITE_SINGLE_REGISTER)
self.function_combo.addItem("写多个寄存器 (16)", WRITE_MULTIPLE_REGISTERS)
self.function_combo.currentIndexChanged.connect(self.update_function_description)
function_layout.addRow(QLabel("功能码:"), self.function_combo)
self.function_description = QLabel()
function_layout.addRow(QLabel("功能描述:"), self.function_description)
self.device_edit = QLineEdit()
self.device_edit.setPlaceholderText("输入设备地址")
function_layout.addRow(QLabel("设备地址:"), self.device_edit)
self.address_edit = QLineEdit()
self.address_edit.setPlaceholderText("输入寄存器地址")
function_layout.addRow(QLabel("寄存器地址:"), self.address_edit)
self.value_edit = QLineEdit()
self.value_edit.setPlaceholderText("输入写入值")
function_layout.addRow(QLabel("写入值:"), self.value_edit)
self.execute_button = QPushButton("执行")
self.execute_button.clicked.connect(self.execute_action)
function_layout.addRow(self.execute_button)
function_group.setLayout(function_layout)
main_layout.addWidget(function_group)
# 数据部分
data_group = QGroupBox("数据")
data_layout = QVBoxLayout()
self.data_table = QTableWidget()
self.data_table.setColumnCount(2)
self.data_table.setHorizontalHeaderLabels(["地址", ""])
data_layout.addWidget(self.data_table)
data_group.setLayout(data_layout)
main_layout.addWidget(data_group)
# 实时监视部分
monitor_group = QGroupBox("实时监视")
monitor_layout = QFormLayout()
self.monitor_interval_edit = QSpinBox()
self.monitor_interval_edit.setRange(100, 5000) # 设置监视间隔范围
self.monitor_interval_edit.setValue(1000) # 设置默认值
monitor_layout.addRow(QLabel("监视间隔(ms):"), self.monitor_interval_edit)
self.start_address_edit = QLineEdit()
self.start_address_edit.setPlaceholderText("输入开始地址")
monitor_layout.addRow(QLabel("监视开始地址:"), self.start_address_edit)
self.length_edit = QSpinBox()
self.length_edit.setRange(1, 100)
monitor_layout.addRow(QLabel("长度:"), self.length_edit)
self.monitor_button = QPushButton("开始监视")
self.monitor_button.clicked.connect(self.toggle_monitoring)
monitor_layout.addRow(self.monitor_button)
monitor_group.setLayout(monitor_layout)
main_layout.addWidget(monitor_group)
self.update_function_description()
def toggle_mode(self):
mode = self.mode_combo.currentData()
if mode == "TCP":
self.ip_edit.setPlaceholderText("输入 IP 地址")
self.port_edit.setPlaceholderText("输入端口号")
elif mode == "RTU":
self.ip_edit.setPlaceholderText("输入串口端口")
self.port_edit.setPlaceholderText("输入波特率")
def connect_modbus(self):
mode = self.mode_combo.currentData()
try:
if mode == "TCP":
ip = self.ip_edit.text()
port = int(self.port_edit.text())
self.master = modbus_tcp.TcpMaster(ip, port)
self.master.open()
elif mode == "RTU":
port = self.ip_edit.text()
baudrate = int(self.port_edit.text())
self.master = modbus_rtu.RtuMaster(serial.Serial(port, baudrate))
self.master.open()
QMessageBox.information(self, "连接", f"成功连接到 Modbus {mode} 设备。")
self.connect_button.setEnabled(False)
self.disconnect_button.setEnabled(True)
except Exception as e:
QMessageBox.critical(self, "连接错误", f"无法连接到 Modbus 设备: {e}")
def disconnect_modbus(self):
if self.master:
self.master.close()
self.master = None
QMessageBox.information(self, "断开连接", "已断开与 Modbus 设备的连接。")
self.connect_button.setEnabled(True)
self.disconnect_button.setEnabled(False)
def update_function_description(self):
descriptions = {
READ_COILS: "读线圈状态",
READ_DISCRETE_INPUTS: "读离散输入状态",
READ_HOLDING_REGISTERS: "读保持寄存器值",
READ_INPUT_REGISTERS: "读输入寄存器值",
WRITE_SINGLE_COIL: "写单个位",
WRITE_SINGLE_REGISTER: "写单个寄存器",
WRITE_MULTIPLE_REGISTERS: "写多个寄存器",
}
function_code = self.function_combo.currentData()
self.function_description.setText(descriptions.get(function_code, ""))
def execute_action(self):
if not self.master:
QMessageBox.warning(self, "连接", "请先连接到 Modbus 设备。")
return
function_code = self.function_combo.currentData()
device = int(self.device_edit.text())
address = int(self.address_edit.text())
try:
if function_code in [READ_COILS, READ_DISCRETE_INPUTS]:
response = self.master.execute(device, function_code, address, 1)
data = response[0]
self.display_data({address: data})
elif function_code in [READ_HOLDING_REGISTERS, READ_INPUT_REGISTERS]:
response = self.master.execute(device, function_code, address, 1)
data = response[0]
self.display_data({address: data})
elif function_code == WRITE_SINGLE_COIL:
value = int(self.value_edit.text())
if value not in [0, 1]:
raise ValueError("写线圈的值必须为0或1")
self.master.execute(device, function_code, address, output_value=value)
QMessageBox.information(self, "写入", "写入操作成功完成。")
elif function_code == WRITE_SINGLE_REGISTER:
value = int(self.value_edit.text())
self.master.execute(device, function_code, address, output_value=value)
QMessageBox.information(self, "写入", "写入操作成功完成。")
elif function_code == WRITE_MULTIPLE_REGISTERS:
values_str = self.value_edit.text()
values = [int(val) for val in values_str.split(",")]
self.master.execute(device, function_code, address, output_value=values)
QMessageBox.information(self, "写入", "写入操作成功完成。")
except Exception as e:
QMessageBox.critical(self, "错误", f"执行操作时出错: {e}")
def display_data(self, data):
# 批量更新表格
self.data_table.setRowCount(len(data))
for i, (address, value) in enumerate(data.items()):
self.data_table.setItem(i, 0, QTableWidgetItem(str(address)))
self.data_table.setItem(i, 1, QTableWidgetItem(str(value)))
def toggle_monitoring(self):
if self.timer.isActive():
self.timer.stop()
self.monitor_button.setText("开始监视")
else:
self.timer.start(self.monitor_interval_edit.value())
self.monitor_button.setText("停止监视")
def update_data(self):
if not self.master:
self.timer.stop()
self.monitor_button.setText("开始监视")
QMessageBox.warning(self, "连接", "请先连接到 Modbus 设备。")
return
try:
device = int(self.device_edit.text())
start_address = int(self.start_address_edit.text())
length = self.length_edit.value()
response = self.master.execute(device, READ_HOLDING_REGISTERS, start_address, length)
# 将数据转换为地址-值对的字典
data = {start_address + i: val for i, val in enumerate(response)}
# 更新表格
self.display_data(data)
except Exception as e:
self.timer.stop()
self.monitor_button.setText("开始监视")
QMessageBox.critical(self, "错误", f"读取数据时出错: {e}")
if __name__ == "__main__":
app = QApplication([])
app.setFont(QFont("Arial", 10)) # 设置全局字体
window = ModbusClient()
window.show()
app.exec_()

35
Test/video.py Normal file
View File

@ -0,0 +1,35 @@
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QTextBrowser, QWidget, QLabel, QPushButton, QFileDialog
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtCore import QTimer, Qt
import cv2
class CameraWindow(QMainWindow):
def __init__(self):
super().__init__()
self.cap = cv2.VideoCapture(0) # 默认摄像头
self.timer = QTimer()
self.initUI()
self.timer.timeout.connect(self.update_frame)
def initUI(self):
self.setGeometry(100, 100, 640, 480)
self.setWindowTitle('Camera Feed')
self.show()
self.timer.start(20)
def update_frame(self):
ret, frame = self.cap.read()
if ret:
height, width, _ = frame.shape
bytes_per_line = 3 * width
cv2_img = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
qt_img = QImage(cv2_img.data, width, height, bytes_per_line, QImage.Format_RGB888)
qt_img = qt_img.scaled(self.width(), self.height(), Qt.KeepAspectRatio)
self.setCentralWidget(QLabel(self))
self.centralWidget().setPixmap(QPixmap.fromImage(qt_img))
if __name__ == '__main__':
app = QApplication(sys.argv)
window = CameraWindow()
sys.exit(app.exec_())