释放深夜的灵魂:色多多APP在线下载网站,开启你的私人娱乐盛宴

核心内容摘要

【御手洗家兄妹OVA全集】解锁兄妹情深的禁忌之恋,一场视觉与心灵的双重盛宴!
探索非凡之美:超越界限的镜头语言

抖出生活新“阳”光:你的快乐,由“抖阳”定义!

基于 PyQt5 开发的ADAM4150 火灾报警监控系统可视化上位机程序核心实现与 ADAM4150 串口模块的通信交互完成传感器状态采集、报警灯智能控制及操作日志记录整体功能可分为以下核心模块逻辑闭环且交互友好

基础交互与串口管理提供可视化操作界面支持串口自动刷新、选择及串口的打开 / 关闭操作串口参数固定为 9600 波特率串口成功打开后自动发送 ADAM4150 初始读取命令通信异常时会记录错误日志保证串口交互稳定性。

传感器状态实时采集与解析通过定时定时器100ms循环读取串口返回的 ADAM4150 响应数据对合法响应帧进行解析提取响应帧中通道值字节转换为 8 位二进制并倒置后分别映射 DI0人体传感器、DI1烟雾传感器、DI2火焰传感器的状态在界面实时更新各传感器的检测状态检测到 / 未检测到并记录解析过程的关键数据。

报警灯双模式智能控制程序支持自动模式默认和手动模式两种模式互斥且可一键切换自动模式根据传感器状态自动触发报警灯当人体传感器检测到人、烟雾传感器检测到烟雾、火焰传感器检测到火焰任一条件满足时自动打开报警灯否则关闭手动模式自动模式禁用界面出现 “手动开灯 / 手动关灯” 可操作按钮支持用户手动控制报警灯开关状态报警灯的开关通过发送指定的 ADAM4150 串口控制命令实现灯的当前状态会在界面实时显示。

操作日志与状态记录界面内置只读日志显示区域自动记录所有关键操作串口开关、模式切换、命令发送、数据解析、通信异常、报警灯状态变更等日志支持自动滚动到底部方便用户实时查看最新操作和系统状态便于调试和问题排查。

核心辅助功能模式切换时自动禁用 / 启用对应操作按钮手动模式仅启用手动开关自动模式禁用提升操作体验提供串口命令发送、响应解析的专用方法保证代码模块化和可维护性所有串口操作、数据解析均增加异常捕获避免单个环节出错导致程序崩溃。

运行结果如下import sys import serial import serial.tools.list_ports from PyQt

QtWidgets import * from PyQt

QtCore import QTimer, Qt class FireAlarmSystem(QWidget): def __init__(self): super().__init__() self.ser None self.auto_mode True # 默认自动模式 self.init_ui() self.init_timer() def init_ui(self): self.setWindowTitle(ADAM4150 火灾报警监控系统) self.setGeometry(100, 100, 600,

# 串口选择区域 port_group QGroupBox(串口配置) port_layout QHBoxLayout() self.port_combo QComboBox() self.refresh_btn QPushButton(刷新串口) self.connect_btn QPushButton(打开串口) port_layout.addWidget(QLabel(串口)) port_layout.addWidget(self.port_combo) port_layout.addWidget(self.refresh_btn) port_layout.addWidget(self.connect_btn) port_group.setLayout(port_layout) # 状态显示区域 status_group QGroupBox(传感器状态) status_layout QGridLayout() self.di0_label QLabel(人体传感器: 未检测到) self.di1_label QLabel(烟雾传感器: 未检测到) self.di2_label QLabel(火焰传感器: 未检测到) status_layout.addWidget(self.di0_label, 0,

status_layout.addWidget(self.di1_label, 1,

status_layout.addWidget(self.di2_label, 2,

status_group.setLayout(status_layout) # 控制区域 control_group QGroupBox(报警灯控制) control_layout QVBoxLayout() self.auto_radio QRadioButton(自动模式传感器触发) self.manual_radio QRadioButton(手动模式) self.auto_radio.setChecked(True) self.manual_layout QHBoxLayout() self.on_btn QPushButton(手动开灯) self.off_btn QPushButton(手动关灯) self.manual_layout.addWidget(self.on_btn) self.manual_layout.addWidget(self.off_btn) control_layout.addWidget(self.auto_radio) control_layout.addWidget(self.manual_radio) control_layout.addLayout(self.manual_layout) self.alarm_status QLabel(报警灯状态: 关闭) control_layout.addWidget(self.alarm_status) control_group.setLayout(control_layout) # 日志显示 self.log_text QTextEdit() self.log_text.setReadOnly(True) # 主布局 main_layout QVBoxLayout() main_layout.addWidget(port_group) main_layout.addWidget(status_group) main_layout.addWidget(control_group) main_layout.addWidget(self.log_text) self.setLayout(main_layout) # 绑定事件 self.refresh_btn.clicked.connect(self.refresh_ports) self.connect_btn.clicked.connect(self.toggle_serial) self.auto_radio.toggled.connect(self.switch_mode) self.on_btn.clicked.connect(lambda: self.set_do0(True)) self.off_btn.clicked.connect(lambda: self.set_do0(False)) self.refresh_ports() def init_timer(self): self.timer QTimer() self.timer.timeout.connect(self.read_serial) self.timer.start(

# 100ms读取一次串口 def refresh_ports(self): self.port_combo.clear() ports serial.tools.list_ports.comports() for port in ports: self.port_combo.addItem(port.device) def toggle_serial(self): if self.ser and self.ser.is_open: self.ser.close() self.connect_btn.setText(打开串口) self.log(串口已关闭) else: try: port self.port_combo.currentText() self.ser serial.Serial(port, 9600, timeout

0.

self.connect_btn.setText(关闭串口) self.log(f串口 {port} 已打开) # 发送初始读取命令 self.send_command(b\x01\x01\x00\x00\x00\x07\x7D\xC

except Exception as e: self.log(f串口打开失败: {str(e)}) def switch_mode(self): self.auto_mode self.auto_radio.isChecked() self.on_btn.setEnabled(not self.auto_mode) self.off_btn.setEnabled(not self.auto_mode) self.log(f切换到{自动 if self.auto_mode else 手动}模式) def send_command(self, cmd): if self.ser and self.ser.is_open: self.ser.write(cmd) self.log(f发送命令: {.join([f{b:02X} for b in cmd])}) def read_serial(self): if self.ser and self.ser.is_open: try: data self.ser.read(

if len(data) 6 and data[0] 0x01 and data[1] 0x01: self.parse_response(data) except Exception as e: self.log(f串口读取错误: {str(e)}) def parse_response(self, response): # 解析响应帧01 01 01 00 51 88 channel_byte response[3] # 第4个字节索引3是通道值 # 转换为8位二进制并倒置 bin_str f{channel_byte:08b}[::-1] self.log(f解析通道值: {channel_byte:02X} - 二进制: {bin_str}) # 更新传感器状态 di0 int(bin_str[0]) # DI0: 人体传感器 di1 int(bin_str[1]) # DI1: 烟雾传感器 di2 int(bin_str[2]) # DI2: 火焰传感器 self.di0_label.setText(f人体传感器: {检测到有人 if di0 0 else 未检测到}) self.di1_label.setText(f烟雾传感器: {检测到烟雾 if di1 1 else 未检测到}) self.di2_label.setText(f火焰传感器: {检测到火焰 if di2 1 else 未检测到}) # 自动模式下控制报警灯 if self.auto_mode: # 有人或有烟雾时触发报警 alarm_trigger (di0

or (di1

or (di2

self.set_do0(alarm_trigger) def set_do0(self, state): # 发送DO0控制命令 if state: cmd b\x01\x05\x00\x10\xFF\x00\x8D\xFF # DO0 开 self.alarm_status.setText(报警灯状态: 打开) else: cmd b\x01\x05\x00\x10\x00\x00\xCC\x0F # DO0 关 self.alarm_status.setText(报警灯状态: 关闭) self.send_command(cmd) self.log(f报警灯已{打开 if state else 关闭}) def log(self, msg): self.log_text.append(msg) # 自动滚动到底部 self.log_text.moveCursor(self.log_text.textCursor().End) if __name__ __main__: app QApplication(sys.argv) window FireAlarmSystem() window.show() sys.exit(app.exec_())代码的详细解释该代码是基于 PyQt5 开发的可视化火灾报警监控系统通过串口与研华 ADAM4150 数字量 I/O 模块通信实现3 路数字输入DI传感器状态采集、1 路数字输出DO报警灯控制支持自动 / 手动双模式并提供实时日志记录功能整体为模块化的 GUI 应用程序设计。

整体架构与核心依赖

核心库导入python运行import sys # 系统交互用于PyQt程序退出import serial # 串口通信核心库import serial.tools.list_ports # 枚举可用串口from PyQt

QtWidgets import * # PyQt5所有可视化组件from PyQt

QtCore import QTimer, Qt # 定时器定时读串口、Qt常量串口通信依赖pyserial库需提前安装pip install pyserialGUI 界面依赖PyQt5需提前安装pip install pyqt5定时任务通过QTimer实现非阻塞式串口数据读取避免界面卡死。

主类设计核心类FireAlarmSystem继承自QWidgetPyQt5 基础窗口组件所有功能均封装在该类中遵循面向对象设计思想分为初始化方法__init__初始化全局变量、界面、定时器界面初始化init_ui构建所有可视化组件和布局串口操作refresh_ports/toggle_serial/send_command等串口枚举、开关、指令发送模式控制switch_mode自动 / 手动模式切换数据解析read_serial/parse_response串口数据读取、ADAM4150 响应帧解析设备控制set_do0控制 DO0 口报警灯开关日志记录log实时记录系统操作和数据交互。

初始化方法init程序入口的核心初始化定义全局变量并调用关键初始化方法python运行def __init__(self):super().__init__() # 调用父类QWidget的初始化方法self.ser None # 全局串口对象初始为None未打开self.auto_mode True # 全局模式标志默认自动模式self.init_ui() # 初始化GUI界面self.init_timer() # 初始化定时读串口定时器全局变量self.ser统一管理串口对象所有串口操作方法均通过该对象执行全局变量self.auto_mode标记当前工作模式联动控制手动按钮的可用状态。

界面初始化init_ui构建整个可视化界面分为4 大功能区域采用 PyQt5布局管理器QHBoxLayout/ QVBoxLayout/ QGridLayout实现界面自适应避免固定坐标导致的界面变形。

串口配置区域实现串口枚举、刷新、开关功能组件包括下拉框显示可用串口、刷新按钮、打开 / 关闭串口按钮python运行port_group QGroupBox(串口配置) # 分组框用于界面分区port_layout QHBoxLayout() # 水平布局self.port_combo QComboBox() # 串口选择下拉框self.refresh_btn QPushButton(刷新串口)self.connect_btn QPushButton(打开串口)# 组件添加到布局布局设置到分组框port_layout.addWidget(QLabel(串口))port_layout.addWidget(self.port_combo)port_layout.addWidget(self.refresh_btn)port_layout.addWidget(self.connect_btn)port_group.setLayout(port_layout)

传感器状态显示区域实时显示3 路 DI 传感器状态采用网格布局QGridLayout3 个标签分别对应人体、烟雾、火焰传感器python运行status_group QGroupBox(传感器状态)status_layout QGridLayout()self.di0_label QLabel(人体传感器: 未检测到) # DI0人体self.di1_label QLabel(烟雾传感器: 未检测到) # DI1烟雾self.di2_label QLabel(火焰传感器: 未检测到) # DI2火焰status_layout.addWidget(self.di0_label, 0,

# 第0行第0列status_layout.addWidget(self.di1_label, 1,

# 第1行第0列status_layout.addWidget(self.di2_label, 2,

# 第2行第0列status_group.setLayout(status_layout)

报警灯控制区域实现模式切换和手动控制组件包括单选按钮自动 / 手动、手动开关按钮、报警灯状态标签python运行control_group QGroupBox(报警灯控制)control_layout QVBoxLayout()self.auto_radio QRadioButton(自动模式传感器触发)self.manual_radio QRadioButton(手动模式)self.auto_radio.setChecked(True) # 默认选中自动模式# 手动控制子布局水平self.manual_layout QHBoxLayout()self.on_btn QPushButton(手动开灯)self.off_btn QPushButton(手动关灯)self.manual_layout.addWidget(self.on_btn)self.manual_layout.addWidget(self.off_btn)# 组装布局control_layout.addWidget(self.auto_radio)control_layout.addWidget(self.manual_radio)control_layout.addLayout(self.manual_layout)self.alarm_status QLabel(报警灯状态: 关闭)control_group.setLayout(control_layout)

日志显示区域采用只读文本框QTextEdit 记录所有系统操作串口开关、指令发送、数据解析、模式切换等python运行self.log_text QTextEdit()self.log_text.setReadOnly(True) # 设置为只读禁止用户编辑

主布局与事件绑定主布局将 4 大区域按垂直布局QVBoxLayout 组装设置为窗口主布局实现从上到下的区域排列事件绑定将组件的信号如点击、选中 绑定到槽函数自定义方法实现交互功能这是 PyQt5 的信号与槽核心机制python运行# 主布局组装main_layout QVBoxLayout()main_layout.addWidget(port_group)main_layout.addWidget(status_group)main_layout.addWidget(control_group)main_layout.addWidget(self.log_text)self.setLayout(main_layout)# 信号与槽绑定self.refresh_btn.clicked.connect(self.refresh_ports) # 刷新串口按钮→刷新方法self.connect_btn.clicked.connect(self.toggle_serial) # 串口开关按钮→串口切换方法self.auto_radio.toggled.connect(self.switch_mode) # 自动单选框→模式切换方法self.on_btn.clicked.connect(lambda: self.set_do0(True)) # 手动开灯→控制DO0开self.off_btn.clicked.connect(lambda: self.set_do0(False))# 手动关灯→控制DO0关self.refresh_ports() # 程序启动时自动刷新一次串口匿名函数lambda用于给按钮传递参数set_do0需要布尔值参数直接绑定无法传参通过 lambda 封装。

定时器初始化init_timer实现非阻塞式定时读取串口避免传统while True循环导致的 GUI 界面卡死python运行def init_timer(self):self.timer QTimer() # 创建定时器对象self.timer.timeout.connect(self.read_serial) # 定时器超时→调用读串口方法self.timer.start(

# 启动定时器超时时间100ms每秒读10次核心原理QTimer 是 PyQt5 的事件循环定时器运行在主线程但不阻塞界面刷新超时后自动触发绑定的槽函数100ms 间隔兼顾实时性和系统资源避免过于频繁读取导致串口缓冲区溢出。

串口核心操作方法

刷新串口refresh_ports枚举当前电脑所有可用串口更新到下拉框中python运行def refresh_ports(self):self.port_combo.clear() # 清空下拉框原有内容ports serial.tools.list_ports.comports() # 枚举所有可用串口for port in ports:self.port_combo.addItem(port.device) # 添加串口设备名如COM

/dev/ttyUSB0跨平台支持serial.tools.list_ports.comports()可在 Windows/Linux/Mac 上自动枚举串口设备名格式自动适配。

切换串口状态toggle_serial实现串口打开 / 关闭的一键切换包含异常处理避免串口占用、不存在等错误导致程序崩溃python运行def toggle_serial(self):if self.ser and self.ser.is_open: # 如果串口已打开→关闭self.ser.close()self.connect_btn.setText(打开串口)self.log(串口已关闭)else: # 如果串口未打开→尝试打开try:port self.port_combo.currentText() # 获取下拉框选中的串口# 初始化串口端口、波特率9600ADAM4150默认、超时

1sself.ser serial.Serial(port, 9600, timeout

0.

self.connect_btn.setText(关闭串口) # 按钮文字切换self.log(f串口 {port} 已打开)# 发送ADAM4150初始读命令Modbus-RTU协议读取DI0-DI7状态self.send_command(b\x01\x01\x00\x00\x00\x07\x7D\xC

except Exception as e: # 捕获所有异常串口占用、不存在等self.log(f串口打开失败: {str(e)})关键参数timeout

1s串口读取时如果无数据

1s 后返回空避免阻塞初始命令打开串口后立即发送读 DI 口命令确保快速获取传感器状态。

发送串口命令send_command封装串口写操作包含串口状态判断和16 进制日志记录所有对 ADAM4150 的指令均通过该方法发送python运行def send_command(self, cmd):if self.ser and self.ser.is_open: # 仅当串口已打开时发送self.ser.write(cmd) # 发送字节类型指令# 将字节转换为16进制字符串如b\x01\x01→0101便于日志查看self.log(f发送命令: {.join([f{b:02X} for b in cmd])})指令类型必须为字节bytes 类型ADAM4150 采用二进制 Modbus-RTU 协议16 进制格式化f{b:02X}将单个字节转换为 2 位大写 16 进制join拼接为完整指令字符串。

模式控制switch_mode实现自动 / 手动模式切换并联动控制手动按钮的可用状态自动模式下手动按钮禁用避免误操作python运行def switch_mode(self):self.auto_mode self.auto_radio.isChecked() # 更新全局模式标志# 手动按钮仅在手动模式下可用auto_modeFalse时启用self.on_btn.setEnabled(not self.auto_mode)self.off_btn.setEnabled(not self.auto_mode)self.log(f切换到{自动 if self.auto_mode else 手动}模式)核心逻辑self.auto_radio.isChecked()返回布尔值标记当前是否为自动模式交互优化按钮禁用 / 启用符合用户操作习惯避免模式冲突。

串口数据读取与解析

读取串口数据read_serial定时器每 100ms 触发一次实现串口数据循环读取包含数据有效性判断和异常处理python运行def read_serial(self):if self.ser and self.ser.is_open: # 仅串口打开时读取try:data self.ser.read(

# 每次读取最多10个字节ADAM4150响应帧最多8字节# 有效性判断数据长度≥6字节 帧头为0x01 0x01ADAM4150从站地址读输入寄存器功能码if len(data) 6 and data[0] 0x01 and data[1] 0x01:self.parse_response(data) # 解析有效响应帧except Exception as e: # 捕获读取错误如串口意外断开self.log(f串口读取错误: {str(e)})读取长度read(

预留足够长度避免截断响应帧无数据时返回空字节帧头校验ADAM4150 的 Modbus-RTU 响应帧头固定为0x01 0x01从站地址 1 读功能码 1过滤无效数据。

解析 ADAM4150 响应帧parse_response核心数据解析方法解析 Modbus-RTU 响应帧提取3 路 DI 传感器状态并在自动模式下自动触发报警灯python运行def parse_response(self, response):# 响应帧示例01 01 01 00 51 88共6字节符合Modbus-RTU规范channel_byte response[3] # 第4字节索引3是DI0-DI7的状态字节8位对应8路DI# 转换为8位二进制字符串再倒置ADAM4150的DI0对应二进制最低位需倒置匹配bin_str f{channel_byte:08b}[::-1]self.log(f解析通道值: {channel_byte:02X} - 二进制: {bin_str})# 提取3路DI状态倒置后索引0DI0索引1DI1索引2DI2di0 int(bin_str[0]) # DI0人体传感器0检测到1未检测到模块硬件定义di1 int(bin_str[1]) # DI1烟雾传感器1检测到0未检测到di2 int(bin_str[2]) # DI2火焰传感器1检测到0未检测到# 更新GUI界面的传感器状态标签self.di0_label.setText(f人体传感器: {检测到有人 if di0 0 else 未检测到})self.di1_label.setText(f烟雾传感器: {检测到烟雾 if di1 1 else 未检测到})self.di2_label.setText(f火焰传感器: {检测到火焰 if di2 1 else 未检测到})# 自动模式下满足任一触发条件则打开报警灯if self.auto_mode:# 触发条件人体检测到 OR 烟雾检测到 OR 火焰检测到alarm_trigger (di0

or (di1

or (di2

self.set_do0(alarm_trigger) # 自动控制报警灯关键解析逻辑说明状态字节位置ADAM4150 的 Modbus-RTU 响应中第 4 字节索引 3是 8 路 DI 口的状态汇总1 个字节 8 位对应 DI0-DI7二进制倒置ADAM4150 默认DI0 对应二进制最低位第 0 位而f{channel_byte:08b}转换的二进制字符串是高位在前如 00000001 表示 DI0 为 1因此需要[::-1]倒置让索引 0 对应 DI0传感器状态定义DI0人体传感器为低电平有效0 检测到DI1/DI2 为高电平有效1 检测到由 ADAM4150 模块硬件接线和传感器类型决定自动触发逻辑满足任一安全隐患条件即触发报警符合火灾报警系统的安全设计原则。

DO0 口报警灯控制set_do0封装ADAM4150 的 DO0 口控制逻辑根据传入的布尔值发送对应的 Modbus-RTU 指令控制报警灯的开 / 关并更新界面状态python运行def set_do0(self, state):# stateTrue开灯stateFalse关灯预定义Modbus-RTU指令适配ADAM4150 DO0口if state:# DO0打开指令01 05 00 10 FF 00 8D FFModbus-RTU写单个线圈地址0010对应DO0cmd b\x01\x05\x00\x10\xFF\x00\x8D\xFFself.alarm_status.setText(报警灯状态: 打开)else:# DO0关闭指令01 05 00 10 00 00 CC 0Fcmd b\x01\x05\x00\x10\x00\x00\xCC\x0Fself.alarm_status.setText(报警灯状态: 关闭)self.send_command(cmd) # 调用通用发送方法发送指令self.log(f报警灯已{打开 if state else 关闭})指令规范采用 Modbus-RTU写单个线圈功能码 05 指令00 10是 ADAM4150 DO0 口的寄存器地址FF 00表示置 1开灯00 00表示置 0关灯最后 2 字节是 CRC16 校验码预计算好直接使用界面联动控制指令发送后立即更新alarm_status标签实现操作与界面状态同步。

日志记录log封装日志记录功能实现实时追加日志和自动滚动到底部方便用户查看系统运行状态和数据交互过程python运行def log(self, msg):self.log_text.append(msg) # 追加日志信息到文本框# 自动滚动到底部将文本光标移到最后一行self.log_text.moveCursor(self.log_text.textCursor().End)只读保护日志文本框已设置setReadOnly(True)避免用户误编辑交互优化自动滚动确保用户始终看到最新的日志信息无需手动拖动滚动条。

程序入口mainPyQt5 程序的标准入口创建应用程序对象、主窗口对象显示窗口并启动事件循环python运行if __name__ __main__:app QApplication(sys.argv) # 创建PyQt5应用程序对象必选管理事件循环window FireAlarmSystem() # 创建主窗口对象window.show() # 显示主窗口sys.exit(app.exec_()) # 启动应用程序事件循环退出时返回系统状态码核心app.exec_()启动 PyQt5 的事件循环所有组件的信号如按钮点击、定时器超时都在该循环中处理是 GUI 程序运行的核心。

核心通信协议说明本程序与 ADAM4150 的通信基于Modbus-RTU 协议工业串口通信标准协议核心参数和指令规范串口参数波特率

8 位数据位、1 位停止位、无校验ADAM4150 出厂默认从站地址10x01核心指令读 DI0-DI7功能码01读输入线圈指令01 01 00 00 00 07 7D C8写 DO0功能码05写单个线圈开灯01 05 00 10 FF 00 8D FF关灯01 05 00 10 00 00 CC 0F校验方式CRC16所有指令最后 2 字节为 CRC16 校验码用于验证数据传输完整性。

程序运行流程启动程序→自动刷新可用串口→界面初始化完成默认自动模式手动按钮禁用用户选择串口→点击「打开串口」→串口成功打开后自动发送读 DI 口指令定时器每 100ms 读取一次串口→解析有效响应帧→更新传感器状态自动模式传感器满足触发条件→自动发送 DO0 开灯指令否则发送关灯指令手动模式用户可点击「手动开灯 / 关灯」→直接控制 DO0 口传感器状态仅显示不触发报警所有操作串口开关、模式切换、指令发送、数据解析均实时记录到日志框。

关键

注意事项库安装运行前需执行pip install pyserial pyqt5安装依赖库串口权限Linux/Mac 系统需给串口分配权限如sudo chmod 777 /dev/ttyUSB0硬件匹配ADAM4150 的 DI/DO 口接线需与代码定义一致DI0 人体、DI1 烟雾、DI2 火焰、DO0 报警灯协议匹配ADAM4150 需配置为 Modbus-RTU 协议串口参数与代码一致9600-N-

该代码是一个完整的工业级串口监控 GUI 程序兼具模块化、可扩展性和交互性可直接部署使用也可根据实际需求扩展传感器数量、增加报警音效、数据存储等功能。

污污污的app-污污污的应用

百度百家号客服电话人工服务

123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123