一、项目概述

随着物联网(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库:

    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:

    sudo apt updatesudo apt install nodejs npm
    
  1. 数据库环境:
  • 安装MongoDB:

    sudo apt install -y mongodb
    
  • 安装InfluxDB:

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

    npx create-react-app my-iot-appcd my-iot-appnpm start
    

四、代码实现

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

1. ESP32设备代码

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

ESP32代码示例
#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代码示例
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安装
# 安装MongoDB (Ubuntu示例)
sudo apt updatesudo apt install -y mongodbsudo 
systemctl start mongodbsudo 
systemctl enable mongodb
InfluxDB安装
# 安装InfluxDB (Ubuntu示例)
sudo apt updatesudo apt install influxdbsudo 
systemctl start influxdbsudo 
systemctl enable influxdb
创建InfluxDB数据库

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

  1. 进入InfluxDB命令行:

    influx
    
  2. 创建数据库:

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

    CREATE DATABASE iot_data
    
  3. 查看已创建的数据库:

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

    SHOW DATABASES
    
  4. 创建时间序列数据的测量:

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

4. React 前端实现

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

React代码示例

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

npx create-react-app my-iot-app
cd my-iot-app
npm start

然后,修改src/App.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安全认证机制,确保数据的安全性和完整性。

更多推荐