打造智能家居:用React、Node.js和WebSocket构建ESP32设备控制面板(代码说明)
一、项目概述
在物联网(IoT)时代,智能设备的远程控制变得越来越重要。本文介绍了一个构建智能设备控制面板的项目,允许用户通过 Web 应用来控制多个 ESP32 设备。用户可以通过该面板查看设备列表,实时了解设备状态,并对设备进行操作(例如开关、调节亮度等)。
二、系统架构
为了满足项目需求,我们设计了一套系统架构,包括前端、后端、数据库和通信协议,如下图所示:
1. 单片机和设备
-
单片机:ESP32
-
设备:智能灯光、智能插座等
2. 通信协议
-
WebSocket:用于实时通信,保证设备状态的实时更新
-
RESTful API:用于设备的管理操作
3. 技术栈
-
前端:React、Vue.js 或 Angular(本文选择 React)
-
后端:Node.js、Flask 或 Django(本文选择 Node.js)
-
数据库:MongoDB 或 Firebase(本文选择 MongoDB)
三、环境搭建
1. 前端环境
安装 React 开发环境:
npx create-react-app smart-device-control-panel
cd smart-device-control-panel
npm start
2. 后端环境
安装 Node.js 和 Express:
mkdir backend
cd backend
npm init -y
npm install express mongoose body-parser ws
3. 数据库环境
安装 MongoDB:
# 对于 macOS 用户
brew tap mongodb/brew
brew install mongodb-community@5.0# 启动 MongoDB
brew services start mongodb/brew/mongodb-community
四、代码实现
1. 前端代码
在 src 目录下创建组件和服务,主要包括设备列表管理、设备控制和实时状态更新。
设备列表组件
DeviceList 组件用于显示所有设备的列表。
// src/components/DeviceList.js
import React from 'react';function DeviceList({ devices }) {return (<div><h2>设备列表</h2><ul>{devices.map((device) => (<li key={device.id}>{device.name} - {device.status}</li>))}</ul></div>);
}export default DeviceList;
设备控制组件
DeviceControl 组件用于控制设备的状态。
// src/components/DeviceControl.js
import React, { useState } from 'react';function DeviceControl({ onControl }) {const [deviceId, setDeviceId] = useState('');const [command, setCommand] = useState('');const handleSubmit = (e) => {e.preventDefault();if (deviceId && command) {onControl(deviceId, command);}};return (<div><h2>设备控制</h2><form onSubmit={handleSubmit}><div><label htmlFor="deviceId">设备 ID:</label><inputtype="text"id="deviceId"value={deviceId}onChange={(e) => setDeviceId(e.target.value)}/></div><div><label htmlFor="command">指令:</label><inputtype="text"id="command"value={command}onChange={(e) => setCommand(e.target.value)}/></div><button type="submit">发送</button></form></div>);
}export default DeviceControl;
服务模块
deviceService 模块用于与后端进行通信。
// src/services/deviceService.js
const API_URL = 'http://localhost:3000';export async function getDevices() {const response = await fetch(`${API_URL}/devices`);return response.json();
}export async function controlDevice(id, command) {await fetch(`${API_URL}/control/${id}`, {method: 'POST',headers: {'Content-Type': 'application/json',},body: JSON.stringify({ command }),});
}export function subscribeToDeviceUpdates(callback) {const ws = new WebSocket('ws://localhost:8080');ws.onmessage = (event) => {const device = JSON.parse(event.data);callback(device);};
}
主应用组件
App 组件是主应用组件,负责管理设备列表和控制操作。
// src/App.js
import React, { useState, useEffect } from 'react';
import DeviceList from './components/DeviceList';
import DeviceControl from './components/DeviceControl';
import { getDevices, controlDevice, subscribeToDeviceUpdates } from './services/deviceService';function App() {const [devices, setDevices] = useState([]);useEffect(() => {getDevices().then(setDevices);subscribeToDeviceUpdates((updatedDevice) => {setDevices((prevDevices) =>prevDevices.map((device) => (device.id === updatedDevice.id ? updatedDevice : device)));});}, []);const handleControl = (id, command) => {controlDevice(id, command);};return (<div className="App"><DeviceList devices={devices} /><DeviceControl onControl={handleControl} /></div>);
}export default App;
2. 后端代码
在 backend 目录下创建服务器和路由,处理设备管理和控制请求。
设备模型
Device 模型定义设备的结构。
// backend/models/Device.js
const mongoose = require('mongoose');const deviceSchema = new mongoose.Schema({name: String,status: String,
});module.exports = mongoose.model('Device', deviceSchema);
服务器和路由
server.js 文件设置服务器,处理设备列表和控制请求,并通过 WebSocket 实现实时状态更新。
// backend/server.js
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const WebSocket = require('ws');
const Device = require('./models/Device');const app = express();
const wss = new WebSocket.Server({ port: 8080 });
app.use(bodyParser.json());// RESTful API
app.get('/devices', async (req, res) => {const devices = await Device.find();res.json(devices);
});app.post('/control/:id', async (req, res) => {const { id } = req.params;const { command } = req.body;// 发送控制命令给设备// 这里可以通过与 ESP32 设备通信的特定实现来发送命令const device = await Device.findById(id);if (device) {// 更新设备状态逻辑device.status = command.status; // 假设 command 包含 status 属性await device.save();// 通知所有 WebSocket 客户端wss.clients.forEach((client) => {if (client.readyState === WebSocket.OPEN) {client.send(JSON.stringify(device));}});res.sendStatus(200);} else {res.sendStatus(404);}
});// WebSocket
wss.on('connection', (ws) => {ws.on('message', (message) => {const { id, status } = JSON.parse(message);Device.findByIdAndUpdate(id, { status }, { new: true }, (err, device) => {if (err) return;wss.clients.forEach((client) => {if (client.readyState === WebSocket.OPEN) {client.send(JSON.stringify(device));}});});});
});app.listen(3000, () => {console.log('后端服务器在 http://localhost:3000 运行');
});
代码说明
前端代码说明
- DeviceList 组件 (
DeviceList.js)
-
用于显示设备列表。
-
从
props获取设备数据,并生成设备列表的 HTML 元素。
- DeviceControl 组件 (
DeviceControl.js)
-
用于控制设备。
-
包含设备 ID 和控制指令的输入框,并在表单提交时调用
onControl函数。
- deviceService 模块 (
deviceService.js)
-
getDevices函数:从后端获取设备列表。 -
controlDevice函数:向后端发送控制设备的指令。 -
subscribeToDeviceUpdates函数:通过 WebSocket 订阅设备状态更新。
- App 组件 (
App.js)
-
主应用组件,管理设备列表和控制操作。
-
使用
useEffect钩子在组件挂载时获取设备列表,并订阅设备状态更新。 -
handleControl函数调用controlDevice发送控制指令。
后端代码说明
- 设备模型 (
Device.js)
- 定义设备的 Mongoose 模型,包含
name和status属性。
- 服务器和路由 (
server.js)
-
监听客户端连接和消息,更新设备状态并通知所有客户端。
-
GET /devices:获取所有设备。 -
POST /control/:id:控制指定 ID 的设备,并通过 WebSocket 通知所有客户端。 -
使用 Express 创建服务器,并连接到 MongoDB 数据库。
五、项目总结
在本项目中,我们构建了一个智能设备控制面板,用户可以通过 Web 应用控制多个 ESP32 设备。项目使用 React 构建前端,用 Node.js 和 Express 搭建后端,使用 MongoDB 存储设备数据,并通过 WebSocket 实现设备状态的实时更新。项目架构清晰,功能完备,为用户提供了良好的体验。
相关文章:
打造智能家居:用React、Node.js和WebSocket构建ESP32设备控制面板(代码说明)
一、项目概述 在物联网(IoT)时代,智能设备的远程控制变得越来越重要。本文介绍了一个构建智能设备控制面板的项目,允许用户通过 Web 应用来控制多个 ESP32 设备。用户可以通过该面板查看设备列表,实时了解设备状态&am…...
计网:从输入URL到网页显示期间发生了什么
1、URL包含的信息 我们输入的url中包含着一些信息: http:表示的此次我们使用的什么协议/www.baidu.com:表示的是我们想要访问的服务器名称,也就是域名dir3/home.html:表示我们所要访问的资源 2、通过DNS解析URL获得I…...
龚宇引以为傲的“爆款制造营”,爱奇艺怕是要爽约了
文:互联网江湖 作者:刘致呈 人们经常用人红戏不红,来形容毯星,综艺上咋咋呼呼,一提都知道,可问及代表作,不好意思,这个真没有。 今年的爱奇艺,貌似也迎来了这一宿命。 …...
org.springframework.web.client.HttpClientErrorException$NotFound异常
springCloud报错信息:org.springframework.web.client.HttpClientErrorException$NotFound: 404 null第一点: 第二点:没有httpclient工具类 注入RestTmeplate类时,改类需要RestController或ResponseBody...
在开关电源转换器中充分利用碳化硅器件的性能优势
在过去的几十年中,半导体行业已经采取了许多措施来改善基于硅 MOSFET (parasitic parameters),以满足开关转换器(开关电源)设计人员的需求。行业效率標準以及市场对效率技术需求的双重作用,导致了对于可用于构建更高效…...
QObject::connect: Cannot queue arguments of type ‘QList<QString>‘
QObject::connect: Cannot queue arguments of type ‘QList’ QObject::connect: Cannot queue arguments of type QList<QString> (Make sure QList<QString> is registered using qRegisterMetaType().)使用信号和槽时,QList无法当做参数被传递&…...
基于K8S部署安装Jenkins
基于K8S部署安装Jenkins 1.Jenkins Kubernetes 清单文件2.Kubernetes Jenkins 部署1:为 Jenkins 创建 Namespace。 最好将所有DevOps工具分类为与其他应用程序分开的命名空间。2:创建“serviceAccount.yaml”文件并复制以下管理员服务帐户清单。1. kubec…...
24-8-4-读书笔记(十三)-《莎士比亚全集》(第一卷(续)) [英] 威廉·莎士比亚 [译]朱生豪
文章目录 《莎士比亚全集》(第一卷(续))目录阅读笔记记录总结《莎士比亚全集》(第一卷(续)) 《莎士比亚全集》朱生豪的经典译本,非常值得花时间去读一读,莎氏的巨作有其独特的韵味,与莫里哀、契诃夫、曹禺等其他国家的剧作家有其鲜明的特点,这既是源于其所处的时代…...
linux nicstat
nicstat 是一个用于监控和报告网络接口统计信息的工具。它可以提供关于网络接口的详细性能数据,包括传输速率、错误率、丢包率等。nicstat 对于诊断网络性能问题和优化网络配置非常有用。 安装 nicstat nicstat 可能不在所有Linux发行版的默认软件库中,…...
程序员如何积累人脉?光靠技术不行了~
从事技术的人,还没被社会“塑造”前,总会有一个“固有思维”,就是这个世界大概率是“由代码和逻辑主宰的世界”,人脉积累并不在考虑范围内,而我们也常被误解为只懂得与机器对话的technician。 事实上,游戏…...
初识增强现实(AR)
初识增强现实(AR) 笔记来源: 1.2023年中国增强现实(AR)行业研究报告 2.wiki/Augmented reality 3.In-Depth Review of Augmented Reality: Tracking Technologies, Development Tools, AR Displays, Collaborative AR…...
开关电源起振是什么看了就知道
接触开关电源的朋友都知道,含有电源管理芯片的开关电源有输入,没输出时常说是不是电路没起振,到底这句话是什么意思呢?什么是“起振”先不做 的解释,简单打个比方,大家就容易懂了,就好像抢救心…...
Modbus_Ascii协议
设备必须要有RTU协议!这是Modbus协议上规定的,且默认模式必须是RTU,ASCII作为选项。(也就是说,一般的设备只有RTU这个协议,ASCII一般很少)所以说,一般学习Modbus协议,只需…...
树莓派在功能和成本之间的 “惊人平衡 “支持了全球数字标牌的成功故事!
树莓派的“功能和成本之间的惊人平衡”支撑全球数字标牌成功故事 数字标牌已经成为一个数十亿美元的行业。Yodeck很快预测到了其中的潜力:他们需要硬件来支持他们可靠、具有成本效益和易于管理的服务,而不会影响性能。事实证明,树莓派 4 证明…...
C++ 学习记录
文章目录 继承重载和重写区别重载重写 参考文献 继承 继承顾名思义就是对长辈本有的东西进行获取与使用,即两个以及两个类以上的关系在获取与使用时会存在一些情况: public:长辈对外公开的自身所有物,最终都会是后代的protected&…...
C#中的TCP和UDP
TcpClient TCP客户端 UDP客户端 tcp和udp的区别 TCP(传输控制协议)和UDP(用户数据报协议)是两种在网络通信中常用的传输层协议,它们在C#或任何其他编程语言中都具有相似的特性。下面是TCP和UDP的主要区别:…...
Spring中使用嵌套事务及事务保存点
嵌套事务及事务保存点 Spring中的嵌套事务与事务保存点1. 什么是嵌套事务?2. 为什么使用嵌套事务?3. 如何在Spring中使用嵌套事务?4. 使用事务保存点5. 总结 Spring框架提供了强大的事务管理功能,包括对嵌套事务的支持。在Spring中…...
SFT、RLHF、DPO、IFT —— LLM 微调的进化之路
TL;DR • SFT、RLHF 和 DPO 都是先估计 LLMs 本身的偏好,再与人类的偏好进行对齐; • SFT 只通过 LLMs 生成的下一个单词进行估计,而 RLHF 和 DPO 通过 LLMs 生成的完整句子进行估计,显然后者的估计会更准确; • 虽然…...
【数据结构】LinkedList与链表
目录 链表 1、链表的概念及结构 2、LinkedList的使用 2、1什么是LinkedList 2、2LinkedList的使用 3、LinkedList的遍历 4、LinkedList的模拟实现 5、ArrayList和LinkedList的区别 上篇已经熟悉了ArrayList的使用,ArrayList底层使用数组来存储元素。由于其底层…...
《LeetCode热题100》---<5.①普通数组篇五道>
本篇博客讲解LeetCode热题100道普通数组篇中的五道题 第一道:最大子数组和(中等) 第二道:合并区间(中等) 第一道:最大子数组和(中等) 法一:贪心算法 class So…...
JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...
LLM基础1_语言模型如何处理文本
基于GitHub项目:https://github.com/datawhalechina/llms-from-scratch-cn 工具介绍 tiktoken:OpenAI开发的专业"分词器" torch:Facebook开发的强力计算引擎,相当于超级计算器 理解词嵌入:给词语画"…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...
HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...
