前言
之前总是没时间整理这一部分的内容,现在抽空整理一下arduino使用esp8266连接自己搭建的emqx服务器的内容吧!关于如何自建emqx服务器,可以自己百度百度,抽空我再整理一下如何连接emqx服务器!敬请期待。
为什么要连接emqx呢?优点如下:
(1)大部分的物联网平台对设备连接数量或者消息转发数量是有限制的,比如blinker是设备连接有限,而阿里云IOT平台的消息转发数量有限,还收到阿里云IOT的很多限制。那不如尝试一下自己购买一个云服务器,然后搭建一个自己的emqx服务器!
(2)自己搭建一个物联网服务器不酷吗?
硬件准备
- nodemcu 开发板一块! 当然也可以使用esp01!用做联网。
- DHT11温湿度传感器(其他传感器也可以),数据上行。
- WIFI继电器一个(不用继电器用LED灯也可以),数据下行。
- 其他硬件若干。
硬件连线
nodemcu | 系统外设 |
---|---|
D7 | DHT11 |
D0 | LED1 |
D5 | LED2 |
D10 | 继电器 (LED3) |
硬件程序
说明:由于时间原因,该代码没有使用smartConfig技术一键配网,感兴趣的同学可以尝试修改连接wifi部分的代码!
(1)首先必不可少头文件,老规矩,一定要把需要用到的第三方头文件放到文档->arduino->libraries下,否则程序源码读不到该头文件的内容, 白费了就!具体的头文件这里就不再给出。
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
//系统外设
#include <DHT.h>//包含DHT头文件
(2)宏定义,为了方便一些引脚编号和变量的后期修改!
#define DHTPIN 13 //D7
#define LED1 16 //D0
#define LED2 14 //D5
#define jidianqi 1 //D10
#define DHTTYPE DHT11 // 使用温度湿度模块的类型为DHT11
#define wifi_ssid "*****" //wifi名称
#define wifi_password "******" //wifi密码
#define mqtt_server "changyuan.store" // EMQX服务器的域名
#define publish_topic "/client2/pub" //发布消息主题
#define subscribe_topic "/client2/sub" //订阅消息的主题
(3)连接emqx服务器的最首先也是需要连接wifi的,这里不再描述smartConfig一键配网,如果有用安信可一键配网的同学,最好把手机热点的AP频段设置为2.4HZ,目前不支持5GHZ。
void setup_wifi() {
delay(10);
WiFi.begin(wifi_ssid, wifi_password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
}
(4)连接emqx服务器首先需要自己的emqx服务器的域名,mqtt_server
为自己的域名,一定要连接1883端口,这是emqx默认的端口号,其他端口无效。
client.setServer(mqtt_server, 1883);
(5)上行数据的上报。数据上行数据的上报一般是上报JSON字符串类型的数据,通过JSON字符串的拼接,代码如下所示。其中sprintf函数可以理解为printf()
函数,功能差不多吧,然后通过publish函数上报主题消息。
#define BODY_FORMAT "{\"clientId\":\"%s\",\"params\":{\"humi\":\"%d\",\"temp\":\"%d\"}}"
char jsonBuf[128];//存放payload主题内容
sprintf(jsonBuf,BODY_FORMAT,clientId.c_str(),humiData,tempData);
client.publish(publish_topic, jsonBuf);
(6)下行数据的解析。下行数据的解析首先是订阅服务器下发的主题信息,然后客户端监听服务器下发的消息,最后是解析下发消息并做出响应的动作。其中解析JSON的方式和python中键值对的取值方法又差不多。
client.subscribe(subscribe_topic); //订阅主题
client.setCallback(callback); //监听服务器下发的消息
DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.parseObject(message);
String LED1State = root["LED1"];
String LED2State = root["LED2"];
String LED3State = root["LED3"];
(7)代码总结!全部代码可以参考如下代码。可包毕设,有意者联系。
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
//系统外设
#include <DHT.h>//包含DHT头文件
#define DHTPIN 13 //D7
#define LED1 16 //D0
#define LED2 14 //D5
#define jidianqi 1 //D10
#define DHTTYPE DHT11 // 使用温度湿度模块的类型为DHT11
DHT dht(DHTPIN, DHTTYPE); //定义dht
#define wifi_ssid "*****" //wifi名称
#define wifi_password "******" //wifi密码
#define mqtt_server "changyuan.store" // EMQX服务器的域名
#define publish_topic "/client2/pub" //发布消息主题
#define subscribe_topic "/client2/sub" //订阅消息的主题
#define BODY_FORMAT "{\"clientId\":\"%s\",\"params\":{\"humi\":\"%d\",\"temp\":\"%d\"}}"
WiFiClient espClient;
PubSubClient client(espClient);
String clientId="client2";
int tempData;
int humiData;
String state;
void setup() {
Serial.begin(115200);
dht.begin();//初始化DHT传感器
pinMode(jidianqi, OUTPUT);//定义io口为输出
digitalWrite(jidianqi,HIGH);
pinMode(LED2, OUTPUT);//定义io口为输出
digitalWrite(LED2,HIGH);
pinMode(LED1, OUTPUT);//定义io口为输出
digitalWrite(LED1,HIGH);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback); //监听服务器下发的消息
}
void loop() {
if (!client.connected()) {
reconnect();
}
else{
DHTWORK();
Serial.print("温度:");
Serial.print(tempData);
Serial.print(",湿度:");
Serial.print(humiData);
char jsonBuf[128];//存放payload主题内容
sprintf(jsonBuf,BODY_FORMAT,clientId.c_str(),humiData,tempData,lux,state.c_str());
client.publish(publish_topic, jsonBuf);
client.subscribe(subscribe_topic);
}
client.loop();
delay(1000);
}
void setup_wifi() {
delay(10);
WiFi.begin(wifi_ssid, wifi_password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
}
void DHTWORK(){
float h = dht.readHumidity();//读取DHT11传感器的湿度 并赋值给h
float t = dht.readTemperature();//读取传感器的温度 并赋值给t
if (isnan(h) || isnan(t))//判断是否成功读取到温湿度数据
{
Serial.println("error");
}else{
tempData=(int)t;
humiData=(int)h;
}
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
if (client.connect("nodeMcuRFID")) {
Serial.println("connected");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
void callback(char *topic, byte *payload, unsigned int length) {
Serial.print("Message arrived in topic: ");
Serial.println(topic);
Serial.print("Message:");
String message;
for (int i = 0; i < length; i++) {
message = message + (char) payload[i]; // convert *byte to string
}
Serial.print(message);
//解析json
DynamicJsonBuffer jsonBuffer;
JsonObject& root = jsonBuffer.parseObject(message);
String LED1State = root["LED1"];
String LED2State = root["LED2"];
String LED3State = root["LED3"];
if(LED1State=="true")
{
//读取
int button1Sate = digitalRead(LED1);
if(button1Sate==1)//高电平置为低
{
digitalWrite(LED1,HIGH);
delay(200);
digitalWrite(LED1, LOW);
}else{//低电平置为高
digitalWrite(LED1,LOW);
delay(200);
digitalWrite(LED1,HIGH);
}
}
if(LED2State=="true")
{
//读取
int button2Sate = digitalRead(LED2);
if(button2Sate==1)//高电平置为低
{
digitalWrite(LED2,HIGH);
delay(200);
digitalWrite(LED2, LOW);
}else{//低电平置为高
digitalWrite(LED2,LOW);
delay(200);
digitalWrite(LED2,HIGH);
}
}
if(LED3State=="true")
{
//读取
int button3Sate = digitalRead(jidianqi);
if(button3Sate==1)//高电平置为低
{
digitalWrite(jidianqi,HIGH);
delay(200);
digitalWrite(jidianqi,LOW);
}else{//低电平置为高
digitalWrite(jidianqi,LOW);
delay(200);
digitalWrite(jidianqi,HIGH);
}
}
Serial.println();
}