当前位置: 首页 > news >正文

【项目思路】基于STM32+ZigBee的智能家居--浴室场景设计

文章导读:本文全面解析了一套基于STM32F103RCT6微控制器的智能家居浴室系统解决方案。方案整合了Zigbee传感网络、WiFi云端互联和本地人机交互(HMI)三大核心模块,既适合物联网开发者与嵌入式工程师进行技术参考,也为智能家居爱好者提供了实用学习案例。

目录导航

  • 项目背景
  • 系统架构设计
  • 硬件选型配置
  • 软件架构实现
  • 通信协议设计
  • 上位机开发

项目背景

项目概述

项目设计了一套完整的智能浴室解决方案,基于STM32F103RCT6微控制器核心,实现了"环境感知 + 本地联动 + 远程可视化 + 云端连接"的一体化智能控制系统。

核心特色

特色功能技术实现应用价值
离线可用本地传感采集、场景联动、手动控制云端断连时系统正常工作
在线增值云端/上位机远程控制、历史数据分析提供远程监控和数据分析能力
安全可靠TLS加密、身份鉴权、CRC校验、看门狗保障系统稳定性和数据安全

技术栈

用户界面层:4.3寸USART HMI触摸屏 + Python上位机
通信层:ESP8266(WiFi) + CC2530(Zigbee协调器)
控制层:STM32F103RCT6 + FreeRTOS多任务系统
数据层:SQLite本地存储 + MQTT云端同步
设备层:智能传感器 + 执行器设备

系统架构设计

整体架构概览

本系统采用分层架构设计,实现设备层、控制层、通信层、应用层的结合:
在这里插入图片描述)

核心接口

接口类型连接方式协议规范主要功能性能指标
WiFi通信STM32 ↔ ESP8266AT指令(115200bps)云端MQTT连接延迟<100ms
Zigbee网络STM32 ↔ CC2530自定义帧协议传感器数据采集响应<500ms
人机界面STM32 ↔ HMI屏USART协议本地交互控制刷新率20fps
上位机Python ↔ ESP8266TCP/UDP远程监控管理并发连接>10

硬件选型配置

主控制器选型分析

STM32F103RCT6 核心参数
技术指标参数值应用优势资源分配
CPU频率72MHz满足多任务实时处理需求FreeRTOS调度开销<5%
Flash容量256KB存储应用代码+配置参数代码占用约180KB
SRAM容量48KB支持多任务栈空间任务栈总计约16KB
工作电压3.3V兼容大部分传感器模块低功耗设计
外设接口分配表

在这里插入图片描述)

无线通信模块

WiFi模块对比选择
模块型号优势特点技术规格选型理由
ESP8266-01S成本低,AT指令简单802.11 b/g/n, 80MHz推荐:性价比最优
ESP32-C3性能强,蓝牙支持双核160MHz, BLE5.0过度设计,成本高
RTL8710BN功耗极低100MHz ARM Cortex-M4生态支持不足
Zigbee协调器方案
CC2530 核心特性:
├──  技术参数
│   ├── CPU: 8051内核 @ 32MHz  
│   ├── Flash: 256KB
│   ├── RAM: 8KB
│   └── RF: 2.4GHz IEEE 802.15.4
├── 通信性能
│   ├── 传输距离: 室内30m, 室外100m
│   ├── 网络容量: 支持65000个节点
│   └── 功耗控制: 睡眠<1μA, 接收23mA
└──  接口设计├── UART: 115200bps 与STM32通信├── SPI: 可选高速数据传输└── GPIO: 状态指示与控制

人机交互设备

HMI触摸屏规格
技术参数规格值应用说明
屏幕尺寸4.3英寸适合浴室环境,视觉效果佳
分辨率480×272像素支持丰富的界面元素显示
触摸技术电阻式触摸防水性好,适合湿润环境
通信接口UART串口指令简单,实时性好

传感器设备

环境监测传感器
传感器类型型号推荐测量范围精度指标安装位置
温湿度SHT30/DHT22-40~80℃, 0~100%RH±0.3℃, ±2%RH浴室中央,避开热源
人体存在PIR+毫米波3-5米检测范围99%检测准确率门口或马桶上方
水浸检测电极式0~3mm水深1mm检测精度地漏周围,洗手台下
气体检测MQ-135CO2: 400-2000ppm±50ppm通风口附近
光照检测BH17500-65535 lux±20%窗户或镜前
智能执行器设备

软件架构实现

FreeRTOS 多任务系统设计

任务优先级与资源分配
任务名称优先级堆栈大小周期核心职责CPU占用率
WiFiTask4 (最高)512 Words事件驱动云端通信管理~15%
ZigbeeTask3 (高)256 Words50msZigbee网络管理~20%
ControlTask3 (高)256 Words100ms设备控制逻辑~10%
SensorTask2 (中)256 Words200ms传感器数据采集~25%
DisplayTask2 (中)384 Words50msHMI界面更新~20%
IdleTask0 (最低)128 Words-系统空闲处理~10%
系统启动与初始化流程
/*** @brief 系统主任务启动函数* @param argument 任务参数(未使用)* @note 完成系统初始化并创建所有业务任务*/
void StartDefaultTask(void *argument) {//硬件外设初始化HAL_Init();                    // HAL库初始化SystemClock_Config();          // 系统时钟配置 72MHz//串口通信初始化MX_GPIO_Init();                // GPIO端口初始化MX_USART1_UART_Init();         // ESP8266 WiFi模块 (115200bps)MX_USART2_UART_Init();         // CC2530 Zigbee协调器 (115200bps) MX_USART3_UART_Init();         // HMI触摸屏 (115200bps)MX_USB_DEVICE_Init();          // USB调试接口// 定时器与ADC初始化MX_TIM2_Init();                // 通用定时器MX_ADC1_Init();                // 模拟量采集MX_IWDG_Init();                // 独立看门狗// 创建任务间通信对象CreateQueuesAndMutexes();// 创建业务处理任务xTaskCreate(WiFiTask,     "WiFi_Task",     512, NULL, 4, &wifiTaskHandle);xTaskCreate(ZigbeeTask,   "Zigbee_Task",   256, NULL, 3, &zigbeeTaskHandle);xTaskCreate(ControlTask,  "Control_Task",  256, NULL, 3, &controlTaskHandle);xTaskCreate(SensorTask,   "Sensor_Task",   256, NULL, 2, &sensorTaskHandle);xTaskCreate(DisplayTask,  "Display_Task",  384, NULL, 2, &displayTaskHandle);// 启动任务调度器vTaskStartScheduler();// 正常情况下不会执行到这里while(1) {HAL_Delay(1000);}
}/*** @brief 创建队列、信号量等同步对象*/
static void CreateQueuesAndMutexes(void) {//消息队列创建sensorDataQueue = xQueueCreate(10, sizeof(SensorData_t));controlCmdQueue = xQueueCreate(5, sizeof(ControlCmd_t));displayEventQueue = xQueueCreate(8, sizeof(DisplayEvent_t));//互斥锁创建uartMutex = xSemaphoreCreateMutex();configMutex = xSemaphoreCreateMutex();//事件组创建systemEventGroup = xEventGroupCreate();//错误检查configASSERT(sensorDataQueue && controlCmdQueue && displayEventQueue);configASSERT(uartMutex && configMutex && systemEventGroup);
}

核心任务详细设计

1 WiFi通信任务 (WiFiTask)
/*** @brief WiFi通信管理任务* @param argument 任务参数* @features*   - ESP8266 AT指令控制*   - MQTT连接管理与重连*   - 云端数据收发*   - 网络状态监控*/
void WiFiTask(void *argument) {TickType_t lastWakeTime = xTaskGetTickCount();ESP8266_Status_t wifiStatus = ESP_IDLE;uint32_t reconnectDelay = 1000; // 初始重连延时1sfor(;;) {switch(wifiStatus) {case ESP_IDLE:if(ESP8266_Init() == ESP_OK) {wifiStatus = ESP_READY;LogInfo("WiFi模块初始化成功");}break;case ESP_READY:if(ESP8266_ConnectAP(WIFI_SSID, WIFI_PASSWORD) == ESP_OK) {wifiStatus = ESP_CONNECTED;reconnectDelay = 1000; // 重置重连延时xEventGroupSetBits(systemEventGroup, WIFI_CONNECTED_BIT);}break;case ESP_CONNECTED://  MQTT连接与数据收发处理if(MQTT_IsConnected()) {ProcessMQTTMessages();PublishSensorData();xEventGroupSetBits(systemEventGroup, MQTT_CONNECTED_BIT);} else {MQTT_Connect();}break;case ESP_ERROR://  指数退避重连策略vTaskDelay(pdMS_TO_TICKS(reconnectDelay));reconnectDelay = MIN(reconnectDelay * 2, 60000); // 最大60swifiStatus = ESP_IDLE;break;}//  100ms周期检查vTaskDelayUntil(&lastWakeTime, pdMS_TO_TICKS(100));}
}
2 Zigbee网络任务 (ZigbeeTask)
/*** @brief Zigbee网络管理任务* @param argument 任务参数* @features*   - CC2530协调器控制*   - 传感器节点管理*   - 数据帧解析与路由*   - 网络拓扑维护*/
void ZigbeeTask(void *argument) {uint8_t rxBuffer[ZIGBEE_RX_BUFFER_SIZE];ZigbeeFrame_t frame;TickType_t lastHeartbeat = xTaskGetTickCount();//  Zigbee网络启动if(Zigbee_StartCoordinator() != ZB_OK) {LogError("Zigbee协调器启动失败");vTaskSuspend(NULL);}for(;;) {// 📡 接收Zigbee数据帧if(Zigbee_ReceiveFrame(&frame, pdMS_TO_TICKS(50)) == ZB_OK) {switch(frame.cmd) {case ZB_SENSOR_REPORT:ProcessSensorReport(&frame);break;case ZB_DEVICE_JOIN:ProcessDeviceJoin(&frame);break;case ZB_DEVICE_LEAVE:ProcessDeviceLeave(&frame);break;case ZB_NETWORK_STATUS:UpdateNetworkStatus(&frame);break;default:LogWarning("未知Zigbee命令: 0x%02X", frame.cmd);break;}}//  网络心跳维护 (每30秒)if(xTaskGetTickCount() - lastHeartbeat > pdMS_TO_TICKS(30000)) {Zigbee_SendHeartbeat();lastHeartbeat = xTaskGetTickCount();}//  检查离线设备CheckOfflineDevices();}
}
3 传感器数据任务 (SensorTask)
/*** @brief 传感器数据处理任务* @param argument 任务参数* @features*   - 多传感器数据融合*   - 数字滤波与去噪*   - 阈值检测与告警*   - 数据有效性校验*/
void SensorTask(void *argument) {SensorData_t currentData = {0};SensorData_t filteredData = {0};AlarmStatus_t alarmStatus = {0};for(;;) {// 从Zigbee队列获取传感器数据if(xQueueReceive(sensorDataQueue, &currentData, pdMS_TO_TICKS(200)) == pdTRUE) {// 🔧 数据预处理与滤波ApplyDigitalFilter(&currentData, &filteredData);//  阈值检测与告警判断CheckAlarmConditions(&filteredData, &alarmStatus);//  更新历史数据缓存UpdateSensorHistory(&filteredData);//  发送处理后的数据到其他任务SendDataToDisplay(&filteredData);SendDataToControl(&filteredData);//  上报到云端 (如果WiFi已连接)if(xEventGroupGetBits(systemEventGroup) & MQTT_CONNECTED_BIT) {PublishToMQTT(&filteredData);}}//  超时告警处理HandleTimeoutAlarms();}
}/*** @brief 数字滤波算法实现* @param raw 原始数据* @param filtered 滤波后数据* @note 采用中值滤波+指数平滑算法*/
static void ApplyDigitalFilter(SensorData_t *raw, SensorData_t *filtered) {static float temp_history[FILTER_WINDOW_SIZE] = {0};static float hum_history[FILTER_WINDOW_SIZE] = {0};static uint8_t index = 0;//  更新历史数据窗口temp_history[index] = raw->temperature;hum_history[index] = raw->humidity;index = (index + 1) % FILTER_WINDOW_SIZE;//  中值滤波filtered->temperature = MedianFilter(temp_history, FILTER_WINDOW_SIZE);filtered->humidity = MedianFilter(hum_history, FILTER_WINDOW_SIZE);//  指数平滑 (α=0.3)static float temp_smooth = 25.0f, hum_smooth = 50.0f;temp_smooth = 0.3f * filtered->temperature + 0.7f * temp_smooth;hum_smooth = 0.3f * filtered->humidity + 0.7f * hum_smooth;filtered->temperature = temp_smooth;filtered->humidity = hum_smooth;//  其他传感器数据直接传递filtered->occupancy = raw->occupancy;filtered->water_leak = raw->water_leak;filtered->co2_level = raw->co2_level;filtered->lux_level = raw->lux_level;filtered->timestamp = HAL_GetTick();
}

任务间通信机制

消息队列设计
//  传感器数据结构
typedef struct {float temperature;      // 温度 (℃)float humidity;         // 湿度 (%)uint8_t occupancy;      // 人体存在 (0/1)uint8_t water_leak;     // 漏水状态 (0/1) uint16_t co2_level;     // CO2浓度 (ppm)uint16_t lux_level;     // 光照强度 (lux)uint32_t timestamp;     // 时间戳uint8_t device_id;      // 设备ID
} SensorData_t;//  控制命令结构
typedef struct {uint8_t device_type;    // 设备类型uint8_t device_id;      // 设备ID  uint8_t command;        // 控制命令uint16_t param1;        // 参数1uint16_t param2;        // 参数2uint8_t source;         // 命令源 (HMI/MQTT/自动)
} ControlCmd_t;//  显示事件结构
typedef struct {uint8_t event_type;     // 事件类型uint8_t page_id;        // 页面IDuint8_t widget_id;      // 控件IDuint32_t param;         // 事件参数
} DisplayEvent_t;

通信协议设计

MQTT云平台协议详解

云平台架构选择
云平台技术特点适用场景成本评估
阿里云IoT完整生态、设备管理强商业化产品推荐中等
腾讯云IoT微信生态集成需要微信集成时中等
私有EMQX完全可控、无云依赖企业内部部署低(部署成本高)
MQTT主题设计与数据流
Topic 层次结构设计:
├── 上行主题 (设备→云端)
│   ├── home/bathroom01/telemetry    # 遥测数据 (QoS1)
│   ├── home/bathroom01/event        # 事件告警 (QoS1) 
│   ├── home/bathroom01/status       # 设备状态 (QoS0)
│   └── home/bathroom01/response     # 命令响应 (QoS1)
│
└── 下行主题 (云端→设备)├── home/bathroom01/command      # 控制命令 (QoS1)├── home/bathroom01/config       # 配置下发 (QoS1)└── home/bathroom01/ota          # 固件升级 (QoS1)
MQTT消息格式标准
// 遥测数据格式
{"msgId": "msg_20241215_001","deviceId": "bathroom01", "timestamp": 1702636800,"data": {"temperature": 26.5,      // 温度 (℃)"humidity": 65.2,         // 湿度 (%)"occupancy": 1,           // 人体存在 (0/1)"water_leak": 0,          // 漏水状态 (0/1)"co2": 450,               // CO2浓度 (ppm)"lux": 320,               // 光照强度 (lux)"devices": {              // 设备状态"fan": 0,               // 风扇 (0=关闭, 1=开启)"heater": 1,            // 浴霸 (0=关闭, 1=开启) "light": 1,             // 照明 (0=关闭, 1=开启)"mirror": 0             // 除雾镜 (0=关闭, 1=开启)}}
}// 控制命令格式
{"msgId": "cmd_20241215_001","command": "device_control","params": {"device": "fan",          // 设备名称"action": "turn_on",      // 操作类型"duration": 1800,         // 持续时间(秒),0=永久"priority": "user"        // 优先级: user/auto/emergency},"timestamp": 1702636800,"expire": 1702636860       // 命令过期时间
}// 事件告警格式
{"msgId": "alert_20241215_001","deviceId": "bathroom01","event": {"type": "water_leak",     // 事件类型"level": "critical",      // 告警级别: info/warning/critical"message": "检测到漏水,位置:洗手台下方","location": "sink_area",  // 告警位置"actions": ["turn_off_water", "send_notification"]},"timestamp": 1702636800
}

HMI串口屏通信协议

指令格式与控件映射
HMI通信帧格式:指令 + 参数 + 结束符
├── STM32 → HMI (控制指令)
│   ├── 文本更新: t[id].txt="内容"
│   ├── 数值更新: n[id].val=数值
│   ├── 图片切换: p[id].pic=图片ID
│   ├── 进度条: j[id].val=百分比
│   ├── 曲线添加: add [id],通道,数值
│   └── 页面跳转: page 页面ID
│
└── HMI → STM32 (事件反馈)  ├── 按钮点击: 65 00 07 [页面ID] [控件ID] 01 FF FF FF├── 滑块变化: 65 00 07 [页面ID] [控件ID] [值H] [值L] FF FF FF  └── 页面切换: 65 00 04 01 [页面ID] FF FF FF
页面布局与控件设计
页面控件ID控件类型显示内容交互功能
P0 主页t0文本温度显示只读
t1文本湿度显示只读
t2文本CO2浓度只读
ico0图标人体存在状态指示
ico1图标漏水告警状态指示
P1 控制b0按钮排风扇开关控制
b1按钮浴霸开关控制
b2按钮照明开关控制
h0滑块亮度调节PWM输出
P2 历史waveform0波形温湿度曲线数据展示
t10文本最近告警日志显示

在这里插入图片描述)
参考)

HMI数据刷新策略
/*** @brief HMI界面刷新管理器*/
typedef struct {uint8_t page_id;          // 当前页面IDuint32_t last_update;     // 上次更新时间uint8_t need_refresh;     // 刷新标志float temp_cache;         // 温度缓存值float hum_cache;          // 湿度缓存值
} HMI_Manager_t;/*** @brief 智能刷新策略实现* @param data 传感器数据* @param hmi HMI管理器* @note 减少不必要的串口通信,提高响应速度*/
void HMI_SmartUpdate(SensorData_t *data, HMI_Manager_t *hmi) {uint32_t current_time = HAL_GetTick();//温度刷新:变化>0.1°C 或 超过2sif(fabs(data->temperature - hmi->temp_cache) > 0.1f || (current_time - hmi->last_update) > 2000) {HMI_SendCommand("t0.txt=\"%.1f°C\"", data->temperature);hmi->temp_cache = data->temperature;}//湿度刷新:变化>1% 或 超过2s  if(fabs(data->humidity - hmi->hum_cache) > 1.0f ||(current_time - hmi->last_update) > 2000) {HMI_SendCommand("t1.txt=\"%.0f%%\"", data->humidity);hmi->hum_cache = data->humidity;}// 告警状态:立即刷新if(data->water_leak) {HMI_SendCommand("ico1.pic=2");  // 显示告警图标HMI_SendCommand("page 3");      // 跳转告警页面}hmi->last_update = current_time;
}

Python上位机通信协议

网络层设计
"""
TCP/UDP通信协议实现
支持命令-响应模式和实时数据推送
"""
import socket, json, struct, threading
from typing import Dict, Callable, Optionalclass BathroomClient:def __init__(self, host: str = "192.168.1.100", port: int = 8888):self.host = hostself.port = portself.socket = Noneself.connected = Falseself.callbacks: Dict[str, Callable] = {}def connect(self) -> bool:"""建立TCP连接"""try:self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)self.socket.settimeout(5.0)self.socket.connect((self.host, self.port))self.connected = True# 启动接收线程threading.Thread(target=self._receive_loop, daemon=True).start()return Trueexcept Exception as e:print(f"连接失败: {e}")return Falsedef send_command(self, command: str, params: dict = None) -> Optional[dict]:"""发送命令并等待响应"""if not self.connected:return None# 构建请求包request = {"id": int(time.time() * 1000) % 10000,"command": command,"params": params or {},"timestamp": int(time.time())}# 发送长度前缀+JSON数据data = json.dumps(request, ensure_ascii=False).encode('utf-8')length_header = struct.pack('!H', len(data))try:self.socket.sendall(length_header + data)return self._wait_response(request["id"], timeout=3.0)except Exception as e:print(f"发送失败: {e}")return Nonedef _receive_loop(self):"""接收数据循环"""buffer = bytearray()while self.connected:try:chunk = self.socket.recv(4096)if not chunk:breakbuffer.extend(chunk)# 解析完整帧while len(buffer) >= 2:length = struct.unpack('!H', buffer[:2])[0]if len(buffer) < 2 + length:breakframe_data = bytes(buffer[2:2+length])del buffer[:2+length]# 处理接收到的消息try:message = json.loads(frame_data.decode('utf-8'))self._handle_message(message)except Exception as e:print(f"解析消息失败: {e}")except Exception as e:print(f"接收错误: {e}")breakself.connected = False# 📡 使用示例
if __name__ == "__main__":client = BathroomClient("192.168.1.100", 8888)if client.connect():# 查询传感器数据sensors = client.send_command("get_sensors")print(f"传感器数据: {sensors}")# ⚡ 控制设备result = client.send_command("control_device", {"device": "fan", "action": "on", "duration": 1800})print(f"控制结果: {result}")
命令集定义
命令类型命令名称参数格式响应格式用途说明
查询类get_sensors{}{temp, hum, co2, ...}获取实时传感器数据
get_devices{}{fan, light, heater, ...}获取设备状态
get_history{start, end, type}[{time, value}, ...]获取历史数据
控制类control_device{device, action, params}{success, message}设备控制
set_scene{scene_name, params}{success, message}场景控制
set_config{key, value}{success, message}参数配置
订阅类subscribe{types: []}{success}订阅实时数据推送
unsubscribe{types: []}{success}取消订阅

上位机开发

系统架构设计

在这里插入图片描述)

技术栈选择对比
框架/库优势特点适用场景推荐指数
PyQt5界面美观、功能丰富、跨平台桌面应用程序⭐⭐⭐⭐⭐
TkinterPython内置、简单易用简单工具⭐⭐⭐
Kivy触摸友好、移动端移动应用⭐⭐⭐
SQLite轻量级、无服务器、高性能本地数据存储⭐⭐⭐⭐⭐
PyQtGraph实时绘图、性能优秀数据可视化⭐⭐⭐⭐⭐

核心模块实现

1主界面设计 (MainWindow)
"""
智能浴室监控系统主界面
功能:实时数据展示、设备控制、历史数据查看
"""
import sys
import time
import json
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import pyqtgraph as pg
import sqlite3
from datetime import datetime, timedeltaclass BathroomMonitor(QMainWindow):def __init__(self):super().__init__()self.setWindowTitle("智能浴室监控系统 v1.0")self.setGeometry(100, 100, 1200, 800)self.setStyleSheet("""QMainWindow {background-color: #f0f0f0;}QGroupBox {font: bold 14px;border: 2px solid #cccccc;border-radius: 5px;margin-top: 10px;padding-top: 10px;}QGroupBox::title {subcontrol-origin: margin;left: 10px;padding: 0 10px 0 10px;}""")#网络客户端初始化self.client = BathroomClient()self.connected = False#数据库初始化self.db_manager = DatabaseManager()#界面初始化self.init_ui()#定时器设置self.update_timer = QTimer()self.update_timer.timeout.connect(self.update_data)self.update_timer.start(1000)  # 1秒更新一次def init_ui(self):"""初始化用户界面"""central_widget = QWidget()self.setCentralWidget(central_widget)#主布局main_layout = QHBoxLayout(central_widget)#左侧面板:实时数据与控制left_panel = self.create_left_panel()main_layout.addWidget(left_panel, 1)#右侧面板:历史数据与图表right_panel = self.create_right_panel() main_layout.addWidget(right_panel, 2)#状态栏self.statusBar().showMessage("就绪")self.create_menu_bar()def create_left_panel(self):"""创建左侧控制面板"""panel = QWidget()layout = QVBoxLayout(panel)#连接状态组conn_group = QGroupBox("连接状态")conn_layout = QHBoxLayout(conn_group)self.status_indicator = QLabel("●")self.status_indicator.setStyleSheet("color: red; font-size: 20px;")self.status_label = QLabel("离线")self.connect_btn = QPushButton("连接")self.connect_btn.clicked.connect(self.toggle_connection)conn_layout.addWidget(self.status_indicator)conn_layout.addWidget(self.status_label)conn_layout.addStretch()conn_layout.addWidget(self.connect_btn)#传感器数据组sensor_group = QGroupBox("环境数据")sensor_layout = QFormLayout(sensor_group)self.temp_label = self.create_value_label("--", "°C", "red")self.hum_label = self.create_value_label("--", "%", "blue") self.co2_label = self.create_value_label("--", "ppm", "orange")self.lux_label = self.create_value_label("--", "lux", "green")sensor_layout.addRow("🌡️ 温度:", self.temp_label)sensor_layout.addRow("💧 湿度:", self.hum_label)sensor_layout.addRow("🌪️ CO2:", self.co2_label)sensor_layout.addRow("💡 光照:", self.lux_label)#状态指示组status_group = QGroupBox("状态指示")status_layout = QFormLayout(status_group)self.occupancy_led = self.create_led_indicator()self.leak_led = self.create_led_indicator()status_layout.addRow("👤 人体存在:", self.occupancy_led)status_layout.addRow("💧 漏水告警:", self.leak_led)#设备控制组control_group = QGroupBox("设备控制")control_layout = QGridLayout(control_group)self.fan_btn = self.create_device_button("🌪️ 排风扇", "fan")self.heater_btn = self.create_device_button("🔥 浴霸", "heater") self.light_btn = self.create_device_button("💡 照明", "light")self.mirror_btn = self.create_device_button("🪞 除雾镜", "mirror")control_layout.addWidget(self.fan_btn, 0, 0)control_layout.addWidget(self.heater_btn, 0, 1)control_layout.addWidget(self.light_btn, 1, 0)control_layout.addWidget(self.mirror_btn, 1, 1)#场景控制组scene_group = QGroupBox("场景模式")scene_layout = QVBoxLayout(scene_group)shower_btn = QPushButton("🚿 淋浴模式")shower_btn.clicked.connect(lambda: self.set_scene("shower"))toilet_btn = QPushButton("🚽 如厕模式") toilet_btn.clicked.connect(lambda: self.set_scene("toilet"))clean_btn = QPushButton("🧹 清洁模式")clean_btn.clicked.connect(lambda: self.set_scene("clean"))scene_layout.addWidget(shower_btn)scene_layout.addWidget(toilet_btn) scene_layout.addWidget(clean_btn)#添加到主布局layout.addWidget(conn_group)layout.addWidget(sensor_group)layout.addWidget(status_group)layout.addWidget(control_group)layout.addWidget(scene_group)layout.addStretch()return paneldef create_right_panel(self):"""创建右侧数据面板"""panel = QWidget()layout = QVBoxLayout(panel)# 历史数据图表chart_group = QGroupBox("历史数据")chart_layout = QVBoxLayout(chart_group)# 图表控制栏chart_controls = QHBoxLayout()self.chart_type = QComboBox()self.chart_type.addItems(["温湿度", "CO2浓度", "设备状态"])self.chart_type.currentTextChanged.connect(self.update_chart)self.time_range = QComboBox()self.time_range.addItems(["最近1小时", "最近6小时", "最近24小时", "最近7天"])self.time_range.currentTextChanged.connect(self.update_chart)export_btn = QPushButton("导出数据")export_btn.clicked.connect(self.export_data)chart_controls.addWidget(QLabel("显示类型:"))chart_controls.addWidget(self.chart_type)chart_controls.addWidget(QLabel("时间范围:"))chart_controls.addWidget(self.time_range)chart_controls.addStretch()chart_controls.addWidget(export_btn)# 图表绘制区域self.plot_widget = pg.PlotWidget()self.plot_widget.setBackground('w')self.plot_widget.setLabel('left', '数值')self.plot_widget.setLabel('bottom', '时间')self.plot_widget.showGrid(x=True, y=True)chart_layout.addLayout(chart_controls)chart_layout.addWidget(self.plot_widget)# 告警日志log_group = QGroupBox("告警日志")log_layout = QVBoxLayout(log_group)self.log_text = QTextEdit()self.log_text.setMaximumHeight(200)self.log_text.setReadOnly(True)clear_log_btn = QPushButton("清空日志")clear_log_btn.clicked.connect(self.log_text.clear)log_layout.addWidget(self.log_text)log_layout.addWidget(clear_log_btn)layout.addWidget(chart_group)layout.addWidget(log_group)return paneldef create_value_label(self, value, unit, color):"""创建数值显示标签"""label = QLabel(f"<span style='color: {color}; font-size: 18px; font-weight: bold;'>{value}</span> {unit}")return labeldef create_led_indicator(self):"""创建LED状态指示器"""indicator = QLabel("●")indicator.setStyleSheet("color: gray; font-size: 16px;")return indicatordef create_device_button(self, text, device_name):"""创建设备控制按钮"""btn = QPushButton(text)btn.setCheckable(True)btn.clicked.connect(lambda checked: self.control_device(device_name, checked))btn.setStyleSheet("""QPushButton {min-height: 50px;font-size: 14px;border: 2px solid #ddd;border-radius: 5px;}QPushButton:checked {background-color: #4CAF50;color: white;border-color: #45a049;}""")return btn
2 数据库管理模块
class DatabaseManager:"""数据库管理类 - 负责SQLite数据的存储与查询"""def __init__(self, db_path="bathroom_data.db"):self.db_path = db_pathself.init_database()def init_database(self):"""初始化数据库表结构"""conn = sqlite3.connect(self.db_path)cursor = conn.cursor()# 传感器数据表cursor.execute("""CREATE TABLE IF NOT EXISTS sensor_data (id INTEGER PRIMARY KEY AUTOINCREMENT,timestamp INTEGER NOT NULL,temperature REAL,humidity REAL,co2 INTEGER,lux INTEGER,occupancy INTEGER,water_leak INTEGER)""")# 设备状态表cursor.execute("""CREATE TABLE IF NOT EXISTS device_status (id INTEGER PRIMARY KEY AUTOINCREMENT,timestamp INTEGER NOT NULL,device_name TEXT NOT NULL,status INTEGER NOT NULL,action TEXT)""")# 告警事件表  cursor.execute("""CREATE TABLE IF NOT EXISTS alert_events (id INTEGER PRIMARY KEY AUTOINCREMENT,timestamp INTEGER NOT NULL,event_type TEXT NOT NULL,level TEXT NOT NULL,message TEXT,resolved INTEGER DEFAULT 0)""")conn.commit()conn.close()def insert_sensor_data(self, data):"""插入传感器数据"""conn = sqlite3.connect(self.db_path)cursor = conn.cursor()cursor.execute("""INSERT INTO sensor_data (timestamp, temperature, humidity, co2, lux, occupancy, water_leak)VALUES (?, ?, ?, ?, ?, ?, ?)""", (int(time.time()),data.get('temperature'),data.get('humidity'), data.get('co2'),data.get('lux'),data.get('occupancy', 0),data.get('water_leak', 0)))conn.commit()conn.close()def get_history_data(self, hours=24, data_type='all'):"""获取历史数据"""conn = sqlite3.connect(self.db_path)cursor = conn.cursor()start_time = int(time.time()) - (hours * 3600)cursor.execute("""SELECT timestamp, temperature, humidity, co2, luxFROM sensor_data WHERE timestamp > ?ORDER BY timestamp""", (start_time,))results = cursor.fetchall()conn.close()return results

界面效果展示

在这里插入图片描述

技术学习价值

本项目作为完整的IoT系统实现,具有极高的学习和参考价值:

知识体系覆盖
  • 嵌入式开发:STM32 + FreeRTOS多任务编程
  • 通信协议:UART/SPI/I2C/Zigbee/WiFi/MQTT全栈
  • 上位机开发:Python GUI编程与数据库操作
  • 系统集成:硬件选型、软件架构、安全设计
  • 产品思维:用户体验、成本控制、可维护性
🛠️ 实践技能提升
  1. 📖 学习路线建议

    • 基础:单片机 → FreeRTOS → 通信协议
    • 进阶:系统架构 → 安全设计 → 性能优化
    • 应用:产品化 → 市场分析 → 商业模式
  2. 🔧 开发能力培养

    • 代码规范与文档编写
    • 版本控制与团队协作
    • 测试验证与质量保证
    • 问题诊断与故障排除

结语

智能家居是物联网技术的重要应用场景,正处于快速发展阶段。本项目提供完整的技术方案详细的实现指南,为开发者打造了一个优质的学习范本和参考模板。

http://www.dtcms.com/a/366829.html

相关文章:

  • 服务器异常负载排查手册 · 隐蔽进程篇
  • QT面经(含相关知识)
  • elasticsearch学习(五)文档CRUD
  • 前端跨域终极指南:3 种优雅解决方案 + 可运行 Demo
  • App UI 自动化环境搭建指南
  • Java Stream 流式操作举例
  • QT Creator 使用
  • 【一文了解】C#泛型
  • 数据库集成:使用 SQLite 与 Electron
  • 新电脑硬盘如何分区?3个必知技巧避免“空间浪费症”!
  • [技术革命]Harmonizer:仅20MB模型如何实现8K图像_视频的完美和谐化?
  • 鸿蒙:AppStorageV2状态管理和数据共享
  • 泛型的通配符
  • axios请求缓存与重复拦截:“相同请求未完成时,不发起新请求”
  • TDengine TIMETRUNCATE 函数用户使用手册
  • 野火STM32Modbus主机读取寄存器/线圈失败(三)-尝试将存贮事件的地方改成数组(非必要解决方案)(附源码)
  • 腾讯云国际代理:如何在腾讯云GPU服务器上部署私有化大模型?附GPU简介
  • SQLmap 完整使用指南:环境搭建 + 命令详解 + 实操案例
  • 打开 solidworks当前文件 所在的文件夹 python pywin32
  • Effective Python 第10条 - 用赋值表达式减少重复代码
  • 上位机知识篇---conda run
  • KingbaseES一体化架构与多层防护体系如何保障企业级数据库的持续稳定与弹性扩展
  • 关于在自然语言处理深层语义分析中引入公理化体系的可行性、挑战与前沿展望
  • 谁才是企业级开源平台的优选?OpenCSG与Dify、Coze、Langflow、Ollama 的差异化之路
  • 深度学习——ResNet 卷积神经网络
  • 高并发商城 商品为了防止超卖,都做了哪些努力?
  • 2025国赛C题保姆级教程思路分析 NIPT 的时点选择与胎儿的异常判定
  • Spring Cloud Alibaba快速入门01
  • C语言结构体:轻松管理球员数据
  • SpringMVC的异常处理和拦截器