基于ESP32的掌上网关智能家居控制设备:集成MQTT、后端Node.js、MongoDB、React(代码示例)

avatar
作者
猴君
阅读量:0

一、项目概述

本项目旨在设计并实现一个基于ESP32的掌上网关智能家居控制设备。该设备可以作为智能家居系统的核心控制单元,实现对家庭中各种智能设备的集中管理和控制。用户可以通过手机APP或Web界面远程操控家中的智能灯、空调、窗帘等设备,还可以设置自动化场景和定时任务,打造一个智能、便捷、舒适的家居环境。

二、系统架构

基于项目需求,我们设计了如下系统架构:

ESP32掌上网关 WiFi模块 蓝牙模块 ZigBee模块 MQTT客户端 MQTT服务器 后端服务器 数据库 手机APP Web界面

主要组件说明:

  1. 核心控制器:ESP32单片机,集成WiFi和蓝牙功能

  2. 通信协议:WiFi、蓝牙、ZigBee用于与各种智能设备通信

  3. 消息队列:MQTT协议用于设备与服务器之间的通信

  4. 后端服务:Node.js实现业务逻辑和数据处理

  5. 数据库:MongoDB存储设备信息和用户数据

  6. 前端界面:React Native开发跨平台手机APP,React开发Web管理界面

三、环境搭建

  1. ESP32开发环境:
  • 安装Arduino IDE

  • 添加ESP32开发板支持

  • 安装必要的库文件(WiFi、BLE、ZigBee等)

  1. MQTT服务器:
  • 安装Mosquitto MQTT Broker

    sudo apt-get install mosquitto mosquitto-clients 
  1. Node.js后端环境:

    npm init npm install express mongoose mqtt 
  • 安装Node.js和npm

  • 创建项目并安装依赖

  1. MongoDB数据库:
  • 安装MongoDB

  • 创建数据库和集合

  1. 前端开发环境:
  • 安装React Native CLI

  • 安装React开发工具

四、代码实现

4.1 ESP32固件

#include <WiFi.h> #include <PubSubClient.h> #include <ArduinoJson.h>  const char* ssid = "YourWiFiSSID"; const char* password = "YourWiFiPassword"; const char* mqtt_server = "YourMQTTServerIP";  WiFiClient espClient; PubSubClient client(espClient);  void setup_wifi() {   delay(10);   Serial.println("Connecting to WiFi..");   WiFi.begin(ssid, password);   while (WiFi.status() != WL_CONNECTED) {     delay(500);     Serial.print(".");   }   Serial.println("WiFi connected"); }  void callback(char* topic, byte* payload, unsigned int length) {   StaticJsonDocument<200> doc;   deserializeJson(doc, payload, length);      String device = doc["device"];   String action = doc["action"];      if (device == "light") {     if (action == "on") {       digitalWrite(LED_PIN, HIGH);     } else if (action == "off") {       digitalWrite(LED_PIN, LOW);     }   }   // 处理其他设备... }  void reconnect() {   while (!client.connected()) {     Serial.print("Attempting MQTT connection...");     if (client.connect("ESP32Client")) {       Serial.println("connected");       client.subscribe("home/devices/#");     } else {       Serial.print("failed, rc=");       Serial.print(client.state());       Serial.println(" try again in 5 seconds");       delay(5000);     }   } }  void setup() {   Serial.begin(115200);   setup_wifi();   client.setServer(mqtt_server, 1883);   client.setCallback(callback); }  void loop() {   if (!client.connected()) {     reconnect();   }   client.loop();      float temperature = readTemperature();   float humidity = readHumidity();      StaticJsonDocument<200> doc;   doc["temperature"] = temperature;   doc["humidity"] = humidity;      char buffer[256];   serializeJson(doc, buffer);   client.publish("home/sensors", buffer);      delay(5000); } 

代码说明:

  1. 首先引入必要的库:WiFi、PubSubClient(MQTT客户端)和ArduinoJson。

  2. 定义WiFi和MQTT服务器的连接信息。

  3. setup_wifi()函数用于连接WiFi网络。

  4. callback()函数处理接收到的MQTT消息,解析JSON数据并执行相应的操作。

  5. reconnect()函数用于重新连接MQTT服务器。

  6. setup()函数初始化串口、WiFi连接和MQTT客户端。

  7. loop()函数中持续检查MQTT连接,读取传感器数据并发布到MQTT主题。

4.2 Node.js后端服务

const express = require('express'); const mongoose = require('mongoose'); const mqtt = require('mqtt');  const app = express(); const port = 3000;  mongoose.connect('mongodb://localhost/smart_home', { useNewUrlParser: true, useUnifiedTopology: true });  const Device = mongoose.model('Device', {   name: String,   type: String,   status: String });  const client = mqtt.connect('mqtt://localhost');  client.on('connect', () => {   console.log('Connected to MQTT server');   client.subscribe('home/sensors'); });  client.on('message', (topic, message) => {   console.log(`Received message on topic ${topic}: ${message.toString()}`);   if (topic.startsWith('home/devices/')) {     const deviceName = topic.split('/')[2];     const status = JSON.parse(message.toString()).status;     updateDeviceStatus(deviceName, status);   } else if (topic === 'home/sensors') {     const data = JSON.parse(message.toString());     saveSensorData(data);   } });  async function updateDeviceStatus(name, status) {   try {     await Device.findOneAndUpdate({ name }, { status }, { upsert: true });     console.log(`Updated status for device ${name}`);   } catch (error) {     console.error('Error updating device status:', error);   } }  function saveSensorData(data) {   // 实现数据保存逻辑,例如存入数据库   console.log('Sensor data received:', data); }  app.use(express.json());  app.get('/devices', async (req, res) => {   try {     const devices = await Device.find();     res.json(devices);   } catch (error) {     res.status(500).json({ error: 'Error fetching devices' });   } });  app.post('/control', (req, res) => {   const { device, action } = req.body;   const message = JSON.stringify({ device, action });   client.publish(`home/devices/${device}`, message);   res.json({ success: true, message: 'Command sent' }); });  app.listen(port, () => {   console.log(`Server running on port ${port}`); }); 

代码说明:

  1. 使用Express框架创建Web服务器。

  2. 通过Mongoose连接MongoDB数据库,并定义Device模型。

  3. 连接MQTT服务器并订阅相关主题。

  4. 实现MQTT消息处理逻辑,包括更新设备状态和保存传感器数据。

  5. 定义API路由:

  • GET /devices:获取所有设备信息

  • POST /control:发送控制命令到指定设备

  1. 启动服务器监听指定端口。

4.3 React Native移动应用

import React, { useState, useEffect } from 'react'; import { View, Text, FlatList, TouchableOpacity, StyleSheet } from 'react-native'; import axios from 'axios';  const API_URL = 'http://your-backend-url:3000';  const App = () => {   const [devices, setDevices] = useState([]);    useEffect(() => {     fetchDevices();   }, []);    const fetchDevices = async () => {     try {       const response = await axios.get(`${API_URL}/devices`);       setDevices(response.data);     } catch (error) {       console.error('Error fetching devices:', error);     }   };    const controlDevice = async (device, action) => {     try {       await axios.post(`${API_URL}/control`, { device, action });       fetchDevices(); // 刷新设备列表     } catch (error) {       console.error('Error controlling device:', error);     }   };    const renderDevice = ({ item }) => (     <View style={styles.deviceItem}>       <Text>{item.name} - {item.status}</Text>       <View style={styles.buttonContainer}>         <TouchableOpacity           style={styles.button}           onPress={() => controlDevice(item.name, 'on')}         >           <Text>开启</Text>         </TouchableOpacity>         <TouchableOpacity           style={styles.button}           onPress={() => controlDevice(item.name, 'off')}         >           <Text>关闭</Text>         </TouchableOpacity>       </View>     </View>   );    return (     <View style={styles.container}>       <Text style={styles.title}>智能家居控制</Text>       <FlatList         data={devices}         renderItem={renderDevice}         keyExtractor={item => item.name}         refreshing={false}         onRefresh={fetchDevices}       />     </View>   ); };  const styles = StyleSheet.create({   container: {     flex: 1,     padding: 20,     backgroundColor: '#f5f5f5',   },   title: {     fontSize: 24,     fontWeight: 'bold',     marginBottom: 20,     textAlign: 'center',   },   deviceItem: {     backgroundColor: 'white',     padding: 15,     borderRadius: 10,     marginBottom: 10,     elevation: 3,   },   buttonContainer: {     flexDirection: 'row',     justifyContent: 'space-around',     marginTop: 10,   },   button: {     backgroundColor: '#007AFF',     padding: 10,     borderRadius: 5,     width: 80,     alignItems: 'center',   }, });  export default App; 

代码说明:

  1. 使用React Hooks(useState和useEffect)管理组件状态和副作用。

  2. fetchDevices函数从后端API获取设备列表。

  3. controlDevice函数发送控制命令到后端。

  4. renderDevice函数渲染每个设备项,包括设备名称、状态和控制按钮。

  5. 使用FlatList组件高效渲染设备列表,支持下拉刷新功能。

  6. 使用StyleSheet创建样式,使界面美观易用。

4.4 React Web管理界面

import React, { useState, useEffect } from 'react'; import axios from 'axios'; import './App.css';  const API_URL = 'http://your-backend-url:3000';  function App() {   const [devices, setDevices] = useState([]);   const [sensorData, setSensorData] = useState(null);    useEffect(() => {     fetchDevices();     fetchSensorData();     const interval = setInterval(fetchSensorData, 5000);     return () => clearInterval(interval);   }, []);    const fetchDevices = async () => {     try {       const response = await axios.get(`${API_URL}/devices`);       setDevices(response.data);     } catch (error) {       console.error('Error fetching devices:', error);     }   };    const fetchSensorData = async () => {     try {       const response = await axios.get(`${API_URL}/sensors`);       setSensorData(response.data);     } catch (error) {       console.error('Error fetching sensor data:', error);     }   };    const controlDevice = async (device, action) => {     try {       await axios.post(`${API_URL}/control`, { device, action });       fetchDevices();     } catch (error) {       console.error('Error controlling device:', error);     }   };    return (     <div className="App">       <h1>智能家居管理系统</h1>       <div className="device-list">         <h2>设备列表</h2>         {devices.map(device => (           <div key={device.name} className="device-item">           <span>{device.name} - {device.status}</span>             <div className="device-controls">               <button onClick={() => controlDevice(device.name, 'on')}>开启</button>               <button onClick={() => controlDevice(device.name, 'off')}>关闭</button>             </div>           </div>         ))}       </div>       {sensorData && (         <div className="sensor-data">           <h2>传感器数据</h2>           <p>温度: {sensorData.temperature}°C</p>           <p>湿度: {sensorData.humidity}%</p>         </div>       )}     </div>   ); }  export default App; 

CSS样式(App.css):

.App {   max-width: 800px;   margin: 0 auto;   padding: 20px;   font-family: Arial, sans-serif; }  h1, h2 {   text-align: center; }  .device-list {   margin-bottom: 30px; }  .device-item {   display: flex;   justify-content: space-between;   align-items: center;   background-color: #f0f0f0;   padding: 10px;   margin-bottom: 10px;   border-radius: 5px; }  .device-controls button {   margin-left: 10px;   padding: 5px 10px;   background-color: #007bff;   color: white;   border: none;   border-radius: 3px;   cursor: pointer; }  .sensor-data {   background-color: #e9ecef;   padding: 15px;   border-radius: 5px; } 

代码说明:

  1. 使用React Hooks管理组件状态和副作用。

  2. fetchDevices函数获取设备列表,fetchSensorData函数获取传感器数据。

  3. 使用useEffect在组件挂载时获取数据,并设置定时器定期更新传感器数据。

  4. controlDevice函数发送控制命令到后端。

  5. 渲染设备列表,每个设备项显示名称、状态和控制按钮。

  6. 显示最新的传感器数据(温度和湿度)。

  7. 使用CSS样式美化界面,提高用户体验。

五、项目总结

本项目成功设计并实现了一个基于ESP32的掌上网关智能家居控制设备。通过整合多种技术和组件,我们构建了一个功能完整、灵活可扩展的智能家居系统。以下是项目的主要成果和特点:

  1. 核心功能实现:
  • 设备控制:用户可以通过移动应用或Web界面远程控制家中的智能设备。

  • 状态监控:实时显示各设备的当前状态。

  • 环境感知:通过传感器采集并展示温度、湿度等环境数据。

  1. 技术栈整合:
  • 硬件层:采用ESP32作为核心控制器,集成WiFi、蓝牙等通信模块。

  • 通信协议:使用MQTT实现设备与服务器之间的高效通信。

  • 后端服务:基于Node.js构建,处理业务逻辑和数据管理。

  • 数据存储:使用MongoDB存储设备信息和传感器数据。

  • 前端应用:开发了React Native移动应用和React Web管理界面,提供直观的用户交互。

  1. 可扩展性:
  • 模块化设计使得系统易于扩展,可以方便地添加新的设备类型和功能。

  • 采用标准化的通信协议,便于与其他智能家居系统集成。

  1. 用户体验:
  • 提供了移动应用和Web界面两种交互方式,满足不同场景的使用需求。

  • 实时更新设备状态和环境数据,确保用户随时掌握家居情况。

  1. 未来展望:
  • 增强安全性:实现端到端加密和用户认证机制。

  • 智能化提升:引入机器学习算法,实现智能场景联动和个性化推荐。

  • 语音控制:集成语音识别技术,支持语音命令控制设备。

  • 能源管理:添加能耗监测和分析功能,助力节能减排。

通过本项目,我们不仅实现了一个功能完备的智能家居控制系统,还积累了物联网、嵌入式系统、Web开发等多个领域的实践经验。这个项目为今后开发更复杂、更智能的家居系统奠定了坚实的基础。

    广告一刻

    为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!