基于MQTT+WebSocket的物联网实践

整体概述

本项目基于“物联网技术与应用”课程的学期大作业。

esp8266收集dht11的温湿度数据通过mqtt发布,并订阅web端发送的数据打印到SSD1306的OLED显示屏上,web端通过echarts来显示收到的数据,并可以发布数据给esp8266端。

MQTT服务器搭建

这里使用阿里云服务器,所以要事先购买一个阿里云服务器。

下载EMQ X Broker的安装包到阿里云服务器上。

可以去emq的官网下载对应版本的EMQ X Broker

官网地址:https://www.emqx.io/cn/

这里下载v4.0-rc.3的版本

基于MQTT+WebSocket的物联网实践_第1张图片
EMQ X Broker版本

下载好后可以通过Xshell将安装包上传到阿里云(具体的上传过程就不写了,网上有很多教程)

上传成功后可以在阿里云上看到之前下载的安装包

基于MQTT+WebSocket的物联网实践_第2张图片
最下面的就是上传的安装包

输入下面的命令来安装emq x

sudo rpm -ivh emqx-centos7-v4.0-rc.3.x86_64.rpm

安装成功后输入以下命令启动

emqx start

启动成功后还没完,还要去安全组打开相应的端口。

去阿里云的安全组打开相应端口,分别为8083、1883、18083这三个端口


基于MQTT+WebSocket的物联网实践_第3张图片
安全组

点击配置规则打开安全组规则配置的界面

基于MQTT+WebSocket的物联网实践_第4张图片
点击配置规则

添加三个安全组规则,其中端口范围就是上述的三个端口,授权对象可以填你允许或拒绝访问的对象,0.0.0.0/0表示所有对象


基于MQTT+WebSocket的物联网实践_第5张图片
添加安全组规则

添加完后再重启服务器,mqtt服务器就搭建好了(当初因为没有重启服务器,测试了好久都不成功)

IoT端实现

我使用的库是simpleDHT11.h、PubSubClient.h和SSD1306Wire.h

int pinDHT11 = 5;//dht11的pin脚

SimpleDHT11 dht11(pinDHT11);

const char* ssid = "******";//wifi账号

const char* password = "*****";//wifi密码

const char* mqtt_server = "*****"; // MQTT服务器

const char* TOPIC = "*****"; // 订阅信息主题

const char* client_id = "*****";  // 标识当前设备的客户端编号

int linePx = 11;//规定打印的行

WiFiClient espClient;  // 定义wifiClient实例

PubSubClient client(espClient);  // 定义PubSubClient的实例

SSD1306Wire display(0x3c, D4, D5);//设置OLED屏相关数据

setup函数

void setup() {

  display.init();初始化OLED屏

  Serial.begin(115200);

  setup_wifi();//连接wifi

  client.setServer(mqtt_server, 1883); //设定MQTT服务器与使用的端口,1883是默认的MQTT端口

  client.setCallback(callback);  //设定回调方式,当ESP8266收到订阅的消息时会调用此方法

}

loop函数

void loop() {

  display.drawString(0, 0, "Broker Message:");

  display.display();

  if (!client.connected()) {

    reconnect();

  }

  client.loop();

  // read without samples.

  byte temperature = 0;

  byte humidity = 0;

  int err = SimpleDHTErrSuccess;

  if ((err = dht11.read(&temperature, &humidity, NULL)) != SimpleDHTErrSuccess) {

    Serial.print("Read DHT11 failed, err=");

    Serial.println(err);

    delay(1000);

    return;

  }//读取DHT11上的温湿度数据

  int temp = (int)temperature;

  int hum = (int)humidity;

  char json[100];

  sprintf(json,"%s%d%s%d%s","{\"temp\":\"",temp,"\",\"hum\":\"",hum,"\"}");//以json的格式发布消息

  Serial.print("Send Message:");

  Serial.print(json);

  Serial.print("\n");

  client.publish("******",json);//以自定义的主题发布消息

  //DHT11 sampling rate is 1HZ

  delay(2000);

}

连接mqtt服务器函数

void reconnect() {

  while (!client.connected()) {

    Serial.print("Attempting MQTT connection...");

    // Attempt to connect

    if (client.connect(client_id)) {

      Serial.println("connected");

      // 连接成功时订阅主题TOPIC

      client.subscribe(TOPIC);

    } else {

      Serial.print("failed, rc=");

      Serial.print(client.state());

      Serial.println(" try again in 5 seconds");

      // Wait 5 seconds before retrying

      delay(5000);

    }

  }

}

回调函数callback

void callback(char* topic, byte* payload, unsigned int length) {

  Serial.print("Message arrived [");

  Serial.print(topic);

  Serial.print("] ");

  String a="";

//接受订阅主题的消息

  for (int i = 0; i < length; i++) {

    a = a+(char)payload[i];

    Serial.print((char)payload[i]);

  }

  Serial.println();

  if(linePx<45){

    display.drawString(0, linePx, a);

    linePx += 11;

  }else{

    display.drawString(0, 50, "Too many Messages");

  }

  Serial.println(linePx);

  display.display();//每打印一行,为了避免后面与前面打印的重叠,需要增加打印所在的行数linePx

  if ((char)payload[0] == '1') {

    digitalWrite(BUILTIN_LED, LOW);  // Turn the LED on (Note that LOW is the voltage level

  } else {

    digitalWrite(BUILTIN_LED, HIGH);  // Turn the LED off by making the voltage HIGH

  }

}

Web端实现

web端采用了websocke和echarts的js文件来实现

echarts的js文件名

echarts.min.js

websocket的js文件名

mqttws31.min.js

其中echarts的js文件可以去官网https://www.echartsjs.com/zh/index.html直接下载

websocket方面代码

连接服务器

client = new Paho.MQTT.Client("服务器地址", Number(8083), "客户端ID");//建立客户端实例

client.connect({onSuccess:onConnect});//连接服务器并注册连接成功处理事件

function onConnect() {

    client.subscribe("******");//订阅主题

}

client.onConnectionLost = onConnectionLost;//注册连接断开处理事件

client.onMessageArrived = onMessageArrived;//注册消息接收处理事件

function onConnectionLost(responseObject) {

    if (responseObject.errorCode !== 0) {

          console.log("onConnectionLost:"+responseObject.errorMessage);

           alert("连接断开");

      }

}


接受并解析json数据

function onMessageArrived(message) {

  var obj = JSON.parse(message.payloadString);//将收到的json消息解析

  humData = obj.hum;

  tempData = obj.temp;//json格式:{"temp":"tempData","hum":"humData"}

}

发布主题消息函数

function SendMessage(){

message = new Paho.MQTT.Message(document.getElementById("sendMessage").value);

message.destinationName = "******"; //发布的主题

client.send(message);

}

关闭websocke连接

function disConnect(){

client.disconnect();

alert("WebSocket连接已关闭!");

}

echarts方面看看官方手册就足够了,需要说明的是,要做到实时刷新的话,新建两个温度湿度的数组,大小自己定,每次有新数据进来时,push后去掉第一个数据即可

Time.push(now);//往时间中添加数据

Temp.push(tempData);//往温度中添加数据

Hum.push(humData);//往湿度中添加数据

if(Time.length>10){

Time.shift();//去掉时间数组中第一个数据

Temp.shift();//去掉温度数组中第一个数据

Hum.shift();//去掉湿度数组中第一个数据

}

你可能感兴趣的:(基于MQTT+WebSocket的物联网实践)