一种基于Wemos(ESP8266)将数据通过MQTT上传至EMQX服务器并转存到MySQL的方法

文章目录

  • 前言
  • 一、项目准备
    • 1、硬件准备
    • 2、软件准备
    • 3、使用前须知
  • 二、宝塔面板安装与配置
    • 1、安装宝塔面板
    • 2、创建数据库
    • 3、新建表并设置字段
      • 3.1、Navicat For MySQL方法
      • 3.2、phpMyAdmin方法
  • 三、EMQ X Enterprise的安装与规则创建
    • 1、安装EMQ X Enterprise
    • 2、EMQ X Entterprise配置
    • 3、MQTTX测试
  • 四、代码
    • 1、核心代码
      • 1.1、时间戳获取
      • 1.2、设备消息发布
      • 1.3、数据库消息
    • 2、完整代码
  • 五、总结


前言

注:本文系湛江市第十七中学星火创客团队及岭南师范学院物联网俱乐部原创部分参赛项目,转载请保留声明。

一般在做物联网相关项目的时候,物联网与软件对接的时候,需要先采集数据,将数据上传至云端后,再将数据转存到MySQL中,方便后台人员去调取数据,本文采用的方法是一种使用Wemos(ESP8266)将采集到的数据通过MQTT协议上传至EMQX服务器,再由EMQX服务器将数据转存至MySQL。这样就可以让后端人员很方便的去调取所需要的数据内容。


提示:以下是本篇文章正文内容,下面案例可供参考

一、项目准备

1、硬件准备

硬件 数量
Wemos 1
DHT11 1
杜邦线 若干

2、软件准备

软件
Ubuntu 18.04 LTS
Arduino IDE
宝塔面板
EMQ X Enterprise
MQTTX
Navicat

3、使用前须知

在项目开始前,要记得在云服务器的 “安全组/防火墙” 那边开放宝塔的默认端口(8888),再顺便把MQTT(1883)、WebSocket(8083)、EMQX(18083)、MySQL(3306)、phpMyAdmin(888)这些端口开放

二、宝塔面板安装与配置

1、安装宝塔面板

宝塔面板安装链接:https://www.bt.cn/bbs/thread-19376-1-1.html
在云服务器上安装宝塔面板,阿里云、腾讯云、华为云等云平台均可,只需在下载的时候选对自己的云服务器所对应的系统及版本

我这里用的是阿里云的Ubuntu 18.04 LTS 云服务器
一种基于Wemos(ESP8266)将数据通过MQTT上传至EMQX服务器并转存到MySQL的方法_第1张图片
在云服务器中运行以下指令,自动安装,安装完后,在网页端打开宝塔面板(xxx.xxx.xxx.xxx:8888)默认选择LNMP
(注意,云服务器不能在安装宝塔面板之前,安装过(Apache、MySQL、PHP、Nginx)等环境,不然会导致出错)

wget -O install.sh http://download.bt.cn/install/install-ubuntu_6.0.sh && sudo bash install.sh

一种基于Wemos(ESP8266)将数据通过MQTT上传至EMQX服务器并转存到MySQL的方法_第2张图片

安装完宝塔后,即可通过外网面板地址进入登录界面,使用“username”“password”登入宝塔面板
(若是觉得默认的 “username” 和 “password” 比较难记或者麻烦,也可以在宝塔面板的“面板设置”中进行修改)

2、创建数据库

在宝塔面板中 “数据库”,点击“添加数据库”新建一个数据库
数据库编码格式中选择 “utf8mb4”,避免出现编码问题
一种基于Wemos(ESP8266)将数据通过MQTT上传至EMQX服务器并转存到MySQL的方法_第3张图片

3、新建表并设置字段

3.1、Navicat For MySQL方法

  • (如果没有Navicat For MySQL,可跳过3.1小节,观看3.2小节)

打开**“Navicat For MySQL”**来对数据库进行管理操作,
首先建立一个新的连接
一种基于Wemos(ESP8266)将数据通过MQTT上传至EMQX服务器并转存到MySQL的方法_第4张图片
填写好内容,不保证参数正确的话,可以测试连接,确保测试连接通过,提交后,即可成功创建连接,双击即可连接
一种基于Wemos(ESP8266)将数据通过MQTT上传至EMQX服务器并转存到MySQL的方法_第5张图片

“新建表”,在表中添加4个字段
一种基于Wemos(ESP8266)将数据通过MQTT上传至EMQX服务器并转存到MySQL的方法_第6张图片

字段 用途
ID 用于数据的序号展示
Temperature 储存温度值
Humidity 储存湿度值
ts 储存数据上传时的时间戳

Ps:“ID” 字段要勾上 “自动递增” 方便排序,在数据表中看上去更直观
一种基于Wemos(ESP8266)将数据通过MQTT上传至EMQX服务器并转存到MySQL的方法_第7张图片
并将表名命名为 “Temp_Humi_Data”
一种基于Wemos(ESP8266)将数据通过MQTT上传至EMQX服务器并转存到MySQL的方法_第8张图片

3.2、phpMyAdmin方法

点击 “phpMyAdmin” 或 “管理” 进入phpMyAdmin进行数据库管理
一种基于Wemos(ESP8266)将数据通过MQTT上传至EMQX服务器并转存到MySQL的方法_第9张图片
“新建表” 添加以下4个字段,并将表命名为 “Temp_Humi_Data”
一种基于Wemos(ESP8266)将数据通过MQTT上传至EMQX服务器并转存到MySQL的方法_第10张图片

三、EMQ X Enterprise的安装与规则创建

1、安装EMQ X Enterprise

下载链接:https://www.emqx.cn/downloads
这里使用的是Ubuntu 18.04 LTS,我使用的是以下下载方法
一种基于Wemos(ESP8266)将数据通过MQTT上传至EMQX服务器并转存到MySQL的方法_第11张图片
若系统是Ubuntu 18.04LTS,选择的参数与上图一致,则可依次执行以下指令

  • 下载Zip压缩包
wget https://www.emqx.cn/downloads/enterprise/v4.2.5/emqx-ee-ubuntu18.04-4.2.5-x86_64.zip
  • 解压下载好的Zip压缩包
unzip emqx-ee-ubuntu18.04-4.2.5-x86_64.zip
  • 进入解压后的文件夹emqx
cd ./emqx
  • 开启EMQ X服务
./bin/emqx start

2、EMQ X Entterprise配置

在网址栏输入“云服务器公网IP:18083”,进入 EMQ X Dashboard
一种基于Wemos(ESP8266)将数据通过MQTT上传至EMQX服务器并转存到MySQL的方法_第12张图片
在左侧选中“规则引擎”—“资源”—“创建”,按照下图填写
(注意:带有MySQL字样的参数,都是在宝塔中新建数据库的参数,要保证参数一致)
一种基于Wemos(ESP8266)将数据通过MQTT上传至EMQX服务器并转存到MySQL的方法_第13张图片
创建完资源后,接着创建规则,在 “SQL输入” 中输入以下SQL语句
一种基于Wemos(ESP8266)将数据通过MQTT上传至EMQX服务器并转存到MySQL的方法_第14张图片

SELECT
  payload.Temperature AS Temperature,
  payload.Humidity AS Humidity,
  payload.ts AS ts

FROM
  "Device_pubTopic/Temp_Humi" 

这里是获取 “Device_pubTopic/Temp_Humi” payload中“Temperature”、“Humidity”、“ts”字段的值

然后下去添加响应动作
一种基于Wemos(ESP8266)将数据通过MQTT上传至EMQX服务器并转存到MySQL的方法_第15张图片
其中 “使用资源” 为我们刚才创建的资源
SQL模板:

INSERT INTO 
	`Temp_Humi_Data` (`Temperature`, `Humidity`, `ts`)
VALUES 
	(${Temperature}, ${Humidity}, ${ts});

这里的意思是,向 “Temp_Humi_Data” 数据表中写入“Temperature”、“Humidity”、“ts”的值

配置好后,本规则就可以将payload中的 “温湿度及时间戳” 数据提取出来,并转存到MySQL中相应数据库的相应数据表中

3、MQTTX测试

下载链接:https://mqttx.app/cn/
接下来使用MQTTX进行测试,打开MQTTX,新建一个连接,填写以下参数
一种基于Wemos(ESP8266)将数据通过MQTT上传至EMQX服务器并转存到MySQL的方法_第16张图片

在EMQ X Dashboard界面左侧“工具”—“WebSocket”填写 “”连接配置“” 的参数,并订阅设备发布的主题 “Device_pubTopic/Temp_Humi”

注意事项:Client_ID不要和MQTTX中的Client_ID相同,不然会导致MQTTX连接后自动断开
一种基于Wemos(ESP8266)将数据通过MQTT上传至EMQX服务器并转存到MySQL的方法_第17张图片
由下图可看出消息的发布与接收均正常
(红色为MQTTX发布到服务器的JSON数据,蓝色为服务器发布到MQTTX的JSON数据)
一种基于Wemos(ESP8266)将数据通过MQTT上传至EMQX服务器并转存到MySQL的方法_第18张图片

四、代码

1、核心代码

1.1、时间戳获取

本项目获取的时间戳是使用了苏宁网站的授时网页提供的
http://quan.suning.com/getSysTime.do
在这里插入图片描述
对此需要对网站内容进行JSON格式解析,提取出 “sysTime2” 字段的值 “2021-04-20 20:29:03”

核心代码

http.setTimeout(5000);	//设置5s超时
http.begin("http://quan.suning.com/getSysTime.do"); //HTTP初始化
int httpCode = http.GET();	//发送HTTP请求,返回状态码
if (httpCode > 0) {
     
  Serial.printf("[HTTP] GET... code: %d\n", httpCode);
  if (httpCode == HTTP_CODE_OK) {
     
    //读取响应内容
    JSON_DATA = http.getString();
    //这里返回的是json格式的字符串
    deserializeJson(Doc, JSON_DATA);
    JsonObject Obj = Doc.as<JsonObject>();
    Field_Val = Obj["sysTime2"];  //获取Json数据中的字段值Field(2020-04-20 20:29:03)
  }
} else {
     
  Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
}
http.end();	//接收完数据后,触发end事件

1.2、设备消息发布

利用
核心代码

unsigned long now = millis();
if (now - lastMsg > 10000) {
     
  Get_Time();       //从网站获得网页内容
  Get_Temp_Humi();  //获取温湿度数据
  lastMsg = now;
  //String MQTT_Msg = "{\"Temperature\": \"%.1f\",\"Humidity\": \"%.1f\",\"ts\": \"%s\"}";
  //将消息模板和温湿度、时间戳数据合并到一起
  snprintf (Msg, Msg_LEN, MQTT_Msg, Temp, Humi, Field_Val.c_str());
  Serial.print("Publish message: ");
  Serial.println(Msg);
  client.publish(pubTopic, Msg);
}

1.3、数据库消息

一种基于Wemos(ESP8266)将数据通过MQTT上传至EMQX服务器并转存到MySQL的方法_第19张图片

2、完整代码

#include 
#include 
#include 
#include 
#include 

/*连接的Wi-Fi、服务器地址*/
const char* ssid        = "SSID";
const char* password    = "PASSWORD";
const char* mqtt_server = "xxx.xxx.xxx.xxx";

/*设置发布和订阅的主题*/
const char* subTopic = "Cloud_pubTopic";            //subTopic
const char* pubTopic = "Device_pubTopic/Temp_Humi"; //pubTopic

#define MQTT_Msg "{\"Temperature\": \"%.1f\",\"Humidity\": \"%.1f\",\"ts\": \"%s\"}"

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
#define Msg_LEN 100
char Msg[Msg_LEN];

HTTPClient http;
String GetUrl = "http://quan.suning.com/getSysTime.do";
String JSON_DATA;
#define JSON_LEN 100
DynamicJsonDocument Doc(JSON_LEN);
String Target = "sysTime2";
String Field_Val = "";

dht DHT;
#define DHT11_PIN D2
float Temp, Humi;

void setup_wifi() {
     
  delay(10);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
     
    delay(500);
    Serial.print(".");
  }

  randomSeed(micros());

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* payload, unsigned int length) {
     
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
     
    Serial.print((char)payload[i]);
  }
  Serial.println();

  // Switch on the LED if an 1 was received as first character
  if ((char)payload[0] == '1') {
     
    digitalWrite(BUILTIN_LED, LOW);   // Turn the LED on (Note that LOW is the voltage level
    // but actually the LED is on; this is because
    // it is active low on the ESP-01)
  } else {
     
    digitalWrite(BUILTIN_LED, HIGH);  // Turn the LED off by making the voltage HIGH
  }

}

void reconnect() {
     
  // Loop until we're reconnected
  while (!client.connected()) {
     
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (client.connect(clientId.c_str())) {
     
      Serial.println("connected");
      // Once connected, publish an announcement...
      //      client.publish(pubTopic, "hello world");
      // ... and resubscribe
      client.subscribe(subTopic);
    } else {
     
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup() {
     
  pinMode(BUILTIN_LED, OUTPUT);     // Initialize the BUILTIN_LED pin as an output
  Serial.begin(115200);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);

  // 连接苏宁网站的授时网页
  http.setTimeout(5000);
  http.begin(GetUrl);
}

void loop() {
     

  if (!client.connected()) {
     
    reconnect();
  }
  client.loop();

  unsigned long now = millis();
  if (now - lastMsg > 10000) {
     
    Get_Time();       //从网站获得网页内容
    Get_Temp_Humi();  //获取温湿度数据
    lastMsg = now;
    //String MQTT_Msg = "{\"Temperature\": \"%.1f\",\"Humidity\": \"%.1f\",\"ts\": \"%s\"}";    
    snprintf (Msg, Msg_LEN, MQTT_Msg, Temp, Humi, Field_Val.c_str());
    Serial.print("Publish message: ");
    Serial.println(Msg);
    client.publish(pubTopic, Msg);
  }
}

/**********
 * 读取DHT11的温湿度数据
 **********/
void Get_Temp_Humi() {
     
  int chk = DHT.read11(DHT11_PIN);
  switch (chk)
  {
     
    case DHTLIB_OK:
      Serial.print("OK,\t");
      break;
    case DHTLIB_ERROR_CHECKSUM:
      Serial.print("Checksum error,\t");
      break;
    case DHTLIB_ERROR_TIMEOUT:
      Serial.print("Time out error,\t");
      break;
    default:
      Serial.print("Unknown error,\t");
      break;
  }

  Temp = DHT.temperature;
  Humi = DHT.humidity;
}

void Get_Time() {
     
  int httpCode = http.GET();
  if (httpCode > 0) {
     
    Serial.printf("[HTTP] GET... code: %d\n", httpCode);
    if (httpCode == HTTP_CODE_OK) {
     
      //读取响应内容
      JSON_DATA = http.getString();
      //这里返回的是json格式的字符串
      Field_Val = Get_JSON_Field(JSON_DATA, "sysTime2");  //获取Json数据中的字段值Field
    }
  } else {
     
    Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
  }
  http.end();
}

String Get_JSON_Field(String JSON_FORMAT_DATA, String Target) {
     
  // 将 JSON_FORMAT_DATA 替换成你想处理的字符串
  deserializeJson(Doc, JSON_FORMAT_DATA);
  JsonObject Obj = Doc.as<JsonObject>();
  String Params = Obj[Target];  //将Target字段的值提取出来赋给Params
  return Params;
}

一种基于Wemos(ESP8266)将数据通过MQTT上传至EMQX服务器并转存到MySQL的方法_第20张图片

五、总结

以上就是使用Wemos(ESP8266)通过MQTT将数据传输到服务器并转存到MySQL中,本文仅仅简单介绍了Wemos(ESP8266)上传数据至云服务器的使用,如有写的不好的地方,欢迎大家提点宝贵的建议。

你可能感兴趣的:(EMQX,MySQL,ESP8266,mysql,物联网)