全栈物联网云平台搭建:MQTT、Node.js、MongoDB、InfluxDB与React的应用示例

一、项目概述

随着物联网(IoT)技术的迅速发展,越来越多的设备和应用需要连接到互联网,实现数据的实时采集、传输和分析。本项目旨在搭建一个物联网云平台,能够支持多种传感器数据的采集与处理,为用户提供实时监控、数据分析及决策支持。平台将涵盖设备管理、数据存储与处理、可视化界面等功能,为智能家居、工业监控和环境监测等应用场景提供支持。

二、系统架构

本系统架构分为四个主要层次:边缘层、传输层、云层和应用层。

  1. 边缘层:
  • 单片机:选择ESP32作为设备的核心控制器,具备Wi-Fi和蓝牙功能,适合IoT应用。

  • 传感器技术:使用温湿度传感器(如DHT11)、光照传感器等,采集环境数据。

  1. 传输层:
  • 无线通信协议:采用MQTT协议进行设备与云端的通信,因其轻量级和低延迟的特点,适合物联网场景。
  1. 云层:
  • 云计算平台:选择AWS作为云服务提供商,利用其丰富的服务支持。

  • 大数据处理:使用Apache Spark进行数据处理与分析。

  • 数据库:选择MongoDB存储传感器数据,使用InfluxDB进行时间序列数据的存储。

  1. 应用层:
  • API设计:使用RESTful API进行前后端数据交互,GraphQL用于复杂数据查询。

  • 前端开发:使用React框架开发用户界面,方便用户查看实时数据。

  • 后端开发:使用Node.js构建后端服务,提供数据处理和API接口。

  1. 安全技术:
  • 实施SSL/TLS加密,确保数据在传输过程中的安全性。

  • 使用OAuth 2.0进行身份验证和授权管理。

三、环境搭建

根据系统架构的技术栈,以下是环境搭建的步骤:

  1. 单片机开发环境:
  • 下载并安装Arduino IDE,配置ESP32开发环境。

  • 使用以下命令在Arduino IDE中安装ESP32库:

    bash 复制代码
    File -> Preferences -> Additional Board Manager URLs: https://dl.espressif.com/dl/package\_esp32\_index.json
    Tools -> Board -> Board Manager -> 搜索ESP32并安装
  1. 云环境:
  • 注册AWS账号,创建EC2实例,选择Ubuntu Server作为操作系统。

  • 安装Node.js和npm:

    bash 复制代码
    sudo apt updatesudo apt install nodejs npm
  1. 数据库环境:
  • 安装MongoDB:

    bash 复制代码
    sudo apt install -y mongodb
  • 安装InfluxDB:

    bash 复制代码
    sudo apt install influxdb
  1. 大数据处理环境:
  1. 前端环境:
  • 使用Create React App快速搭建前端开发环境:

    bash 复制代码
    npx create-react-app my-iot-appcd my-iot-appnpm start

四、代码实现

本部分将详细实现物联网云平台的各个组件,包括ESP32设备的代码、Node.js后端服务、MongoDB数据库、InfluxDB时间序列存储、以及React前端界面。每个部分都将附上详细的代码示例和说明。

1. ESP32设备代码

ESP32作为边缘设备,负责采集温度数据并通过MQTT协议发送到云端。以下是ESP32的代码示例:

ESP32代码示例
cpp 复制代码
#include <WiFi.h>
#include <PubSubClient.h>

// WiFi和MQTT Broker的配置
const char* ssid = "YOUR_SSID";               // WiFi名称
const char* password = "YOUR_PASSWORD";       // WiFi密码
const char* mqttServer = "YOUR_MQTT_BROKER"; // MQTT Broker地址
const int mqttPort = 1883;                     // MQTT Broker端口

WiFiClient espClient;                          // WiFi客户端
PubSubClient client(espClient);                // MQTT客户端

// 温度传感器引脚
const int sensorPin = 34;                     // 假设温度传感器连接在GPIO 34引脚

void setup() {
  Serial.begin(115200);                        // 初始化串口
  connectWiFi();                               // 连接到WiFi
  client.setServer(mqttServer, mqttPort);     // 设置MQTT服务器
}

// 主循环
void loop() {
  if (!client.connected()) {                    // 检查MQTT连接
    reconnect();
  }
  client.loop();                               // 处理MQTT消息

  // 模拟温度数据采集
  int rawValue = analogRead(sensorPin);        // 读取传感器的原始值
  float voltage = (rawValue / 4095.0) * 3.3;   // 将原始值转换为电压
  float temperature = (voltage - 0.5) * 100;   // 将电压转换为温度(假设传感器为LM35)

  String payload = String(temperature);        // 将温度数据转换为字符串
  client.publish("home/temperature", payload.c_str()); // 发送数据到MQTT主题
  delay(5000);                                 // 每5秒发送一次数据
}

// 连接WiFi
void connectWiFi() {
  WiFi.begin(ssid, password);                  // 开始连接WiFi
  while (WiFi.status() != WL_CONNECTED) {     // 等待连接成功
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");        // 连接成功
}

// 重新连接MQTT
void reconnect() {
  while (!client.connected()) {                 // 循环直到重新连接
    Serial.print("Attempting MQTT connection...");
    if (client.connect("ESP32Client")) {      // 尝试连接
      Serial.println("connected");              // 连接成功
    } else {
      Serial.print("failed, rc=");             // 连接失败
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);                             // 5秒后重试
    }
  }
}

代码说明:

  • WiFi配置:将WiFi网络名称、密码和MQTT Broker地址进行配置。

  • 数据采集:从连接的温度传感器读取原始模拟值,并将其转换为温度。

  • MQTT发布:通过MQTT协议将采集到的温度数据发布到主题home/temperature

  • 连接管理:实现WiFi和MQTT的连接管理,确保设备始终保持在线。

2. Node.js 后端服务

后端服务的主要功能是接收来自MQTT Broker的消息,并将温度数据存储到MongoDB和InfluxDB中,同时提供RESTful API供前端访问。

Node.js代码示例
js 复制代码
const express = require('express');             // 引入Express框架
const mongoose = require('mongoose');           // 引入Mongoose库
const mqtt = require('mqtt');                   // 引入MQTT库
const Influx = require('influx');               // 引入InfluxDB库

const app = express();                           // 创建Express应用
const PORT = process.env.PORT || 3000;          // 设定端口
// MongoDB连接
mongoose.connect('mongodb://localhost:27017/iotdata', { 
  useNewUrlParser: true, 
  useUnifiedTopology: true 
});

// 定义温度数据模型
const TemperatureSchema = new mongoose.Schema({
  value: Number,
  timestamp: { type: Date, default: Date.now } // 默认时间戳
});
const Temperature = mongoose.model('Temperature', TemperatureSchema); // 创建模型

// InfluxDB连接
const influx = new Influx.InfluxDB({
  host: 'localhost',
  database: 'iot_data',
  schema: [
    {
      measurement: 'temperature',
      fields: {
        value: Influx.FieldType.FLOAT
      },
      tags: [
        'sensor' // 可以添加更多标签以区分传感器
      ]
    }
  ]
});

// MQTT连接
const mqttClient = mqtt.connect('mqtt://YOUR_MQTT_BROKER');

mqttClient.on('connect', () => {
  mqttClient.subscribe('home/temperature', (err) => {
    if (!err) {
      console.log('Subscribed to home/temperature');
    }
  });
});

// 处理MQTT消息
mqttClient.on('message', (topic, message) => {
  const temperatureValue = parseFloat(message.toString()); // 解析温度值
  const newTemperature = new Temperature({ value: temperatureValue }); // 创建新的温度记录
  newTemperature.save().then(() => console.log('Temperature saved to MongoDB')); // 保存到MongoDB

  // 保存到InfluxDB
  influx.writePoints([
    {
      measurement: 'temperature',
      tags: { sensor: 'ESP32' }, // 添加传感器标签
      fields: { value: temperatureValue },
    }
  ]).catch(err => {
    console.error(`Error saving data to InfluxDB! ${err.stack}`)
  });
});

// API接口:获取最新的10条温度数据
app.get('/temperature', async (req, res) => {
  try {
    const temperatures = await Temperature.find().sort({ timestamp: -1 }).limit(10); // 从MongoDB获取数据
    res.json(temperatures); // 返回温度数据
  } catch (error) {
    res.status(500).send(error); // 处理错误
  }
});

// API接口:获取InfluxDB中的温度数据
app.get('/influx/temperature', async (req, res) => {
  try {
    const result = await influx.query(`SELECT * FROM temperature ORDER BY time DESC LIMIT 10`); // 从InfluxDB获取数据
    res.json(result); // 返回温度数据
  } catch (err) {
    res.status(500).send(err); // 处理错误
  }
});

// 启动Express服务器
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});

代码说明:

  • MongoDB连接:使用Mongoose连接到MongoDB数据库,并定义温度记录的Schema。

  • InfluxDB连接:使用InfluxDB库连接到InfluxDB数据库,并定义数据的schema。

  • MQTT连接:连接到MQTT Broker并订阅home/temperature主题,处理接收到的消息。

  • 消息处理:将接收到的温度数据保存到MongoDB和InfluxDB中。

  • RESTful API:

  • /temperature接口:从MongoDB中获取最近的10条温度记录并返回。

  • /influx/temperature接口:从InfluxDB中获取最近的10条温度记录并返回。

  • 启动服务器:启动Express服务器,监听指定端口。

3. MongoDB和InfluxDB数据库

MongoDB用于存储温度数据,InfluxDB用于时间序列数据的高效存储和查询。确保您在本地或云端安装并运行这两个数据库。

MongoDB安装
bash 复制代码
# 安装MongoDB (Ubuntu示例)
sudo apt updatesudo apt install -y mongodbsudo 
systemctl start mongodbsudo 
systemctl enable mongodb
InfluxDB安装
bash 复制代码
# 安装InfluxDB (Ubuntu示例)
sudo apt updatesudo apt install influxdbsudo 
systemctl start influxdbsudo 
systemctl enable influxdb
创建InfluxDB数据库

在InfluxDB中,我们需要创建一个用于存储温度数据的数据库。以下是创建数据库的步骤:

  1. 进入InfluxDB命令行:

    sql 复制代码
    influx
  2. 创建数据库:

    在InfluxDB命令行界面中,输入以下命令以创建数据库:

    sql 复制代码
    CREATE DATABASE iot_data
  3. 查看已创建的数据库:

    运行以下命令查看当前数据库列表,确保iot_data数据库已成功创建:

    sql 复制代码
    SHOW DATABASES
  4. 创建时间序列数据的测量:

    在我们的Node.js应用中,已经在InfluxDB连接时定义了测量(measurement)为temperature。不需要手动创建,数据会在插入时自动生成。

4. React 前端实现

前端将展示从后端获取的温度数据。我们将使用React构建用户界面,允许用户查看最新的温度数据。

React代码示例

首先,确保你已经使用create-react-app创建了一个新的React应用:

bash 复制代码
npx create-react-app my-iot-app
cd my-iot-app
npm start

然后,修改src/App.js文件如下:

js 复制代码
import React, { useEffect, useState } from 'react';

const App = () => {
  const [temperatures, setTemperatures] = useState([]); // 存储温度数据
  const [influxData, setInfluxData] = useState([]); // 存储InfluxDB数据

  // 获取MongoDB温度数据
  const fetchTemperatures = async () => {
    const response = await fetch('http://localhost:3000/temperature');
    const data = await response.json();
    setTemperatures(data); // 更新状态
  };

  // 获取InfluxDB温度数据
  const fetchInfluxData = async () => {
    const response = await fetch('http://localhost:3000/influx/temperature');
    const data = await response.json();
    setInfluxData(data); // 更新状态
  };

  useEffect(() => {
    fetchTemperatures(); // 组件挂载时获取数据
    fetchInfluxData(); // 组件挂载时获取InfluxDB数据
  }, []);

  return (
    <div>
      <h1>温度数据(来自MongoDB)</h1>
      <ul>
        {temperatures.map((temp, index) => (
          <li key={index}>
            温度: {temp.value} °C, 时间: {new Date(temp.timestamp).toLocaleString()}
          </li>
        ))}
      </ul>

      <h1>温度数据(来自InfluxDB)</h1>
      <ul>
        {influxData.map((data, index) => (
          <li key={index}>
            温度: {data.value} °C, 时间: {new Date(data.time).toLocaleString()}
          </li>
        ))}
      </ul>
    </div>
  );
};

export default App;

代码说明:

  • 状态管理:使用useState钩子来管理从MongoDB和InfluxDB获取的温度数据。

  • 数据获取:定义fetchTemperaturesfetchInfluxData函数,分别从后端API获取MongoDB和InfluxDB的温度数据。

  • 组件挂载:使用useEffect钩子在组件挂载时调用数据获取函数。

  • 数据显示:使用map函数遍历温度数据并在网页上显示。

五、项目总结

本项目成功搭建了一个物联网(IoT)云平台,涵盖了数据采集、传输、存储和可视化的完整流程。选择ESP32作为边缘设备,连接温度传感器(如LM35)以实时采集环境温度数据。通过MQTT协议进行数据传输,ESP32将采集到的温度数据发布到主题home/temperature,确保数据及时传输至云端。后端使用Node.js创建服务,处理来自MQTT Broker的消息并将数据存储到MongoDB和InfluxDB中,提供RESTful API接口以获取最新的温度记录。MongoDB用于快速检索和管理温度数据,而InfluxDB则作为时间序列数据库,支持复杂的时序数据分析。前端应用使用React构建,用户可以通过API实时查看温度变化。此外,项目在数据传输过程中采用SSL/TLS加密技术和OAuth 2.0安全认证机制,确保数据的安全性和完整性。

相关推荐
.Eyes1 小时前
OceanBase 分区裁剪(Partition Pruning)原理解读
数据库·oceanbase
OEC小胖胖1 小时前
【React 设计模式】受控与非受控:解构 React 组件设计的核心模式
前端·react.js·设计模式·前端框架·web
MrZhangBaby2 小时前
SQL-leetcode— 2356. 每位教师所教授的科目种类的数量
数据库
一水鉴天2 小时前
整体设计 之定稿 “凝聚式中心点”原型 --整除:智能合约和DBMS的在表层挂接 能/所 依据的深层套接 之2
数据库·人工智能·智能合约
翔云1234562 小时前
Python 中 SQLAlchemy 和 MySQLdb 的关系
数据库·python·mysql
孙霸天3 小时前
Ubuntu20系统上离线安装MongoDB
数据库·mongodb·ubuntu·备份还原
Java 码农3 小时前
nodejs mongodb基础
数据库·mongodb·node.js
TDengine (老段)3 小时前
TDengine IDMP 运维指南(4. 使用 Docker 部署)
运维·数据库·物联网·docker·时序数据库·tdengine·涛思数据
TDengine (老段)3 小时前
TDengine IDMP 最佳实践
大数据·数据库·物联网·ai·时序数据库·tdengine·涛思数据
彬彬醤4 小时前
Mac怎么连接VPS?可以参考这几种方法
大数据·运维·服务器·数据库·线性代数·macos·矩阵