diff --git a/python/hfc/hfc.py b/python/hfc/hfc.py index 7727300..a63bf70 100644 --- a/python/hfc/hfc.py +++ b/python/hfc/hfc.py @@ -17,6 +17,9 @@ import subprocess import platform import logging +import paho.mqtt.client as mqtt +import json + class ModbusGasAnalyzer: def __init__(self, root): self.root = root @@ -65,6 +68,16 @@ class ModbusGasAnalyzer: "送样单位": "", } + # 服务器MQTT信息 - 初始化值 + self.mqtt_info = { + "服务器地址": "122.112.229.121", + "端口号": "1883", + "主题": "xiaofang/sensor/data", + "用户名": "xiaofang", + "密码": "xiaofang@qwer", + } + self.mqtt_client = None + # 创建页面 self.create_page1() @@ -310,12 +323,95 @@ class ModbusGasAnalyzer: tk.Button(button_frame, text="保存报告", font=('Arial', 12), command=self.save_report, bg='blue', fg='white').pack(side='left', padx=20) + tk.Button(button_frame, text="上传到云", font=('Arial', 12), + command=self.upload_mqtt, bg='green', fg='white').pack(side='left', padx=20) + tk.Button(button_frame, text="退出", font=('Arial', 12), command=self.root.quit, bg='red', fg='white').pack(side='right', padx=20) # 自动保存报告 self.save_report() + def create_page4(self): + """创建第四个页面""" + self.clear_window() + + # 创建一个主容器,包含顶部内容区和底部按钮区 + container = tk.Frame(self.root, bg=self.custom_blue) + container.pack(fill='both', expand=True, padx=20, pady=20) + + # 顶部内容框架 + content_frame = tk.Frame(container, bg=self.custom_blue) + content_frame.pack(fill='both', expand=True) + + # 左侧区域 + left_frame = tk.Frame(content_frame, bg=self.custom_blue) + left_frame.pack(side='left', fill='both', expand=True, padx=(0, 10), pady=(50, 0)) + + # 右侧区域 + right_frame = tk.Frame(content_frame, bg=self.custom_blue) + right_frame.pack(side='right', fill='both', expand=True, padx=(10, 0)) + + # 左侧内容 + # 服务器地址 + tk.Label(left_frame, text="服务器地址:", font=('Arial', 12), bg=self.custom_blue).grid(row=0, column=0, sticky='w', pady=15, padx=(30, 20)) + self.ip_entry = tk.Entry(left_frame, font=('Arial', 12), width=20) + self.ip_entry.grid(row=0, column=1, sticky='ew', pady=10) + # 保留之前填写的信息 + if self.mqtt_info["服务器地址"]: + self.ip_entry.insert(0, self.mqtt_info["服务器地址"]) + + # 端口号 + tk.Label(left_frame, text="端口号:", font=('Arial', 12), bg=self.custom_blue).grid(row=1, column=0, sticky='w', pady=15, padx=(30, 20)) + self.port_entry = tk.Entry(left_frame, font=('Arial', 12), width=20) + self.port_entry.grid(row=1, column=1, sticky='ew', pady=10) + # 自动填入当前时间,但如果已有信息则保留 + if self.mqtt_info["端口号"]: + self.port_entry.insert(0, self.mqtt_info["端口号"]) + + # 主题 + tk.Label(left_frame, text="主题:", font=('Arial', 12), bg=self.custom_blue).grid(row=2, column=0, sticky='w', pady=15, padx=(30, 20)) + self.topic_entry = tk.Entry(left_frame, font=('Arial', 12), width=20) + self.topic_entry.grid(row=2, column=1, sticky='ew', pady=10) + if self.mqtt_info["主题"]: + self.topic_entry.insert(0, self.mqtt_info["主题"]) + + # 用户名 + tk.Label(left_frame, text="用户名:", font=('Arial', 12), bg=self.custom_blue).grid(row=3, column=0, sticky='w', pady=15, padx=(30, 20)) + self.user_name_entry = tk.Entry(left_frame, font=('Arial', 12), width=20) + self.user_name_entry.grid(row=3, column=1, sticky='ew', pady=10) + if self.mqtt_info["用户名"]: + self.user_name_entry.insert(0, self.mqtt_info["用户名"]) + + # 密码 + tk.Label(left_frame, text="密码:", font=('Arial', 12), bg=self.custom_blue).grid(row=4, column=0, sticky='w', pady=15, padx=(30, 20)) + self.user_password_entry = tk.Entry(left_frame, font=('Arial', 12), show="*", width=20) + self.user_password_entry.grid(row=4, column=1, sticky='ew', pady=10) + if self.mqtt_info["密码"]: + self.user_password_entry.insert(0, self.mqtt_info["密码"]) + + # 右侧内容 - 标题 + title_label = tk.Label(right_frame, text="HFC-RapidScan多通道\n灭火剂气体快检仪", + font=('Arial', 18, 'bold'), bg=self.custom_blue, + justify='center') + title_label.pack(pady=40) + + # 开始上传按钮 + self.upload_mqtt_start_button = tk.Button(right_frame, text="开始上传", font=('Arial', 16, 'bold'), + bg='green', fg='white', width=15, height=2, + command=self.upload_mqtt_start) + self.upload_mqtt_start_button.pack(pady=40) + + # 底部按钮框架 - 放在容器的最下方 + button_frame = tk.Frame(container, bg=self.custom_blue) + button_frame.pack(side='bottom', fill='x', pady=(20, 10)) + + tk.Button(button_frame, text="重新测试", font=('Arial', 12), + command=self.back_to_page1, bg='green', fg='white').pack(side='left', padx=50) + + tk.Button(button_frame, text="退出", font=('Arial', 12), + command=self.root.quit, bg='red', fg='white').pack(side='right', padx=50) + def save_report(self): """保存汇总信息为JPG图片""" try: @@ -628,6 +724,78 @@ class ModbusGasAnalyzer: return False + def upload_mqtt(self): + # 切换到MQTT页面准备将数据上传 + self.create_page4() + + def upload_mqtt_start(self): + # 保存MQTT信息 + self.mqtt_info = { + "服务器地址": self.ip_entry.get(), + "端口号": self.port_entry.get(), + "主题": self.topic_entry.get(), + "用户名": self.user_name_entry.get(), + "密码": self.user_password_entry.get(), + } + # 将数据通过MQTT上传到服务器 + print(f"开始上传到MQTT"); + """连接MQTT服务器""" + try: + self.mqtt_client = mqtt.Client() + self.mqtt_client.username_pw_set( + self.mqtt_info["用户名"], + self.mqtt_info["密码"] + ) + def on_connect(client, userdata, flags, rc): + if rc == 0: + print(f"MQTT连接成功: {rc}") + else: + messagebox.showerror("错误", f"MQTT连接失败: {rc}") + return + self.mqtt_client.on_connect = on_connect + self.mqtt_client.connect( + self.mqtt_info["服务器地址"], + int(self.mqtt_info["端口号"]), + 3 + ) + self.mqtt_client.loop_start() + except ValueError as e: + # 处理端口号转换错误 + messagebox.showerror("错误", f"端口号必须是数字: {str(e)}") + return + except Exception as e: + messagebox.showerror("错误", f"MQTT连接错误: {str(e)}") + return + """整理MQTT数据""" + mqtt_payload = [] + for key, value in self.user_info.items(): + mqtt_payload.append(f"{key}: {value}") + mqtt_payload.append(f"浓度: {max(0.0, min(self.show_concentration, 99.990)):.3f}%") + """上传数据到MQTT""" + try: + if self.mqtt_client: + result = self.mqtt_client.publish( + self.mqtt_info["主题"], + "\r\n".join(mqtt_payload), + qos=1 #服务质量等级 + ) + if result.rc == mqtt.MQTT_ERR_SUCCESS: + messagebox.showinfo("成功", f"MQTT上传成功") + else: + messagebox.showerror("错误", f"MQTT上传失败: {result}") + return + except Exception as e: + messagebox.showerror("错误", f"MQTT上传错误: {str(e)}") + return + """断开MQTT连接""" + try: + self.mqtt_client.loop_stop() + self.mqtt_client.disconnect() + self.mqtt_client = None + except Exception as e: + print(f"MQTT断开错误: {e}") + return + def get_windows_serial_number(): """ 获取Windows系统的唯一序列号