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

一、项目概述

本项目旨在设计并实现一个基于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开发等多个领域的实践经验。这个项目为今后开发更复杂、更智能的家居系统奠定了坚实的基础。

  • 28
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

极客小张

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值