esp8266 MQTT服务器 串口收发

参考资料:
https://www.jianshu.com/p/7f54b92d7a7b

image.png

下载MQTT库函数

  • 菜单“项目”-“加载库”-“管理库”,搜索安装“PubSubClient”

    image.png

通过菜单栏里"文件"→“示例”最下面找到PubSubClient查看是否下载成功

image.png

代码介绍

功能说明:
串口输入"ON"或者“OFF”到通过MQTT协议,以“LED”为主题发送到服务器,同时订阅“LED”,消息到服务器后就会立刻返回。根据返回的信息来控制NodeMCU板载LED灯。同时我们使用MQTT调试助手给“LED”主题发送“OFF”或者“ON”也可以实现板载LED的控制!

  • 定义常用变量

      #include <ESP8266WiFi.h>
      #include <PubSubClient.h>
      
      const char* ssid = "****";//连接的路由器的名字
      const char* password = "****";//连接的路由器的密码
      const char* mqtt_server = "****";//服务器的地址 
      const int port=****;//服务器端口号
      
      const char* topic_name = "LED";
      const char* client_id = "esp8266_0000001";
    

    首先导入ESP8266和MQTT协议的库,填写我们所连接服务器的信息,不可以定义成String类型,arduino里String是一个对象!topic_name为订阅的主题,client_id是客户端的名称,尽量保持唯一,否则如果有相同的名称登录,就会把当前连接给顶替!

  • 初始化:

      //初始化WIFI
      void setup_wifi() {//自动连WIFI接入网络
        delay(10);
        WiFi.begin(ssid, password);
        while (WiFi.status() != WL_CONNECTED) {
          delay(500);
          Serial.print("...");
          
        }
      }
    

    初始化WIFI连接,如果连接失败,延时0.5秒后继续尝试连接!

  • 连接服务器

      void reconnect() {//等待,直到连接上服务器
        while (!client.connected()) {//如果没有连接上
          if (client.connect(client_id)) {//接入时的用户名,尽量取一个很不常用的用户名
            client.subscribe(topic_name);//接收外来的数据时的intopic
            Serial.println("connect success");
          } else {
            Serial.print("failed, rc=");//连接失败
            Serial.print(client.state());//重新连接
            Serial.println(" try again in 5 seconds");//延时5秒后重新连接
            delay(5000);
          }
        }
      }
    

    连接服务器断开后会尝试从连,连接成功后发送接入的用户名,client.subscribe表示发送订阅的主题! 如果没有成功连接服务器,延时5秒后再次尝试连接。

  • 消息回调

      void callback(char* topic, byte* payload, unsigned int length) {
        String callMsg = "";
        Serial.print("Message arrived [");
        Serial.print(topic);   // 打印主题信息
        Serial.print("] ");
      
       
        for (int i = 0; i < length; i++) {
          callMsg += char(payload[i]);
        }
      
        Serial.println(callMsg);
      
        //如果返回ON关闭LED
        if(callMsg.equals("ON")){
             digitalWrite(LED_BUILTIN, LOW);   // Turn the LED on (Note that LOW is the voltage level
          }
      
         //如果返回OFF关闭LED
        if(callMsg.equals("OFF")){
             digitalWrite(LED_BUILTIN, HIGH);   // Turn the LED off by making the voltage HIGH
          }
    

    }

    当我们订阅的主题有消息传回时调用此方法,"topic":传来的是订阅的主题。 "payload"传递过来的内容是个二进制的流,所以可以任何的内容,当然上述代码中我们也可以将其转化为整数来用,另外还可以直接传递JSON格式的数据,这样能让数据更加可读。但在单片机的设备间通信还是以“小”为原则, 能传整数的时候绝不传字符串,这样可以大大减轻整体网络通信的负担同时也可以降低单片机运行的功耗。"length":传入的数据的长度!
    定义callMsg接收返回的字符转换成String对象,然后使用equals()方法判断,如果"ON"打开板载LED,如果为"OFF"关闭板载LED。板载LED输出"HIGH"为熄灭

    注意 void callback(char* topic, byte* payload, unsigned int length)的参数是固定的,是一个方法接口除了方法名可改,类型与参数个数都不能错。

  • 初始化函数

      void setup() {//初始化程序,只运行一遍
        Serial.begin(115200);//设置串口波特率(与烧写用波特率不是一个概念)
        setup_wifi();//自动连WIFI接入网络
        client.setServer(mqtt_server, port);//端口号
        client.setCallback(callback); //用于接收服务器接收的数据
      }
    

    程序初始化,初始化串口波特率:115200; 初始化WIFI和连接服务器。 setup函数程序只会执行一次,loop则会一直循环!

  • 主循环:

      void loop() {//主循环
        String msg = "";//用于存放
         reconnect();//确保连上服务器,否则一直等待。
         client.loop();//MUC接收数据的主循环函数。
        
         
        while (Serial.available() > 0)  
          {
              msg += char(Serial.read());
              delay(2);
          }
          int msglen = msg.length();
          if (msglen > 0)
          {
              Serial.println(msg);
              char msgArr[msglen+1];
              msg.toCharArray(msgArr,msglen + 1);
              client.publish(topic_name,msgArr);
          }
         
      }
    

    接收串口的消息发送给服务器,然后回调函数再从服务器接收到返回的消息选择打开还是关闭LED!程序中注意String类型,它和直接""双引号下的变量有区别的!

  • 完整代码

    #include <ESP8266WiFi.h>
    #include <PubSubClient.h>
    
    const char* ssid = "XXX";//连接的路由器的名字
    const char* password = "XXXXX";//连接的路由器的密码
    const char* mqtt_server = "XXXX";//服务器的地址 
    const int port=1883;//服务器端口号
    
    const char* topic_name = "LED";//订阅的主题
    const char* client_id = "esp8266_0000001";//尽量保持唯一,相同的id连接会被替代
    
    WiFiClient espClient;
    PubSubClient client(espClient);
    
    //初始化WIFI
    void setup_wifi() {//自动连WIFI接入网络
      delay(10);
      WiFi.begin(ssid, password);
      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print("...");
        
      }
    }
    
    
    void callback(char* topic, byte* payload, unsigned int length) {
      String callMsg = "";
      Serial.print("Message arrived [");
      Serial.print(topic);   // 打印主题信息
      Serial.print("] ");
    
      for (int i = 0; i < length; i++) {
        callMsg += char(payload[i]);
      }
      
      Serial.println(callMsg);
      
      //如果返回ON关闭LED
      if(callMsg.equals("ON")){
           digitalWrite(LED_BUILTIN, LOW);   // Turn the LED on (Note that LOW is the voltage level
        }
    
       //如果返回OFF关闭LED
      if(callMsg.equals("OFF")){
           digitalWrite(LED_BUILTIN, HIGH);   // Turn the LED off by making the voltage HIGH
        }
    }
    
    
    
    
    void reconnect() {//等待,直到连接上服务器
      while (!client.connected()) {//如果没有连接上
        if (client.connect(client_id)) {//接入时的用户名,尽量取一个很不常用的用户名
          client.subscribe(topic_name);//接收外来的数据时的intopic
          Serial.println("connect success");
        } else {
          Serial.print("failed, rc=");//连接失败
          Serial.print(client.state());//重新连接
          Serial.println(" try again in 5 seconds");//延时5秒后重新连接
          delay(5000);
        }
      }
    }
    
    
    void setup() {//初始化程序,只运行一遍
      Serial.begin(115200);//设置串口波特率(与烧写用波特率不是一个概念)
      
      pinMode(LED_BUILTIN, OUTPUT);     // Initialize the LED_BUILTIN pin as an output
      digitalWrite(LED_BUILTIN, HIGH);
      
      setup_wifi();//自动连WIFI接入网络
      client.setServer(mqtt_server, port);//端口号
      client.setCallback(callback); //用于接收服务器接收的数据
    }
    
    
    
    
    void loop() {//主循环
      String msg = "";//用于存放
       reconnect();//确保连上服务器,否则一直等待。
       client.loop();//MUC接收数据的主循环函数。
      
       
      while (Serial.available() > 0)  
        {
            msg += char(Serial.read());
            delay(2);
        }
        int msglen = msg.length();
        if (msglen > 0)
        {
            Serial.println(msg);
            char msgArr[msglen+1];
            msg.toCharArray(msgArr,msglen + 1);
            client.publish(topic_name,msgArr);
        }
       
    }

上传程序到我们的开发板成功后打开串口调试!

使用MQTT测试助手

  • 串口测试:

    image.png

    通过串口输入发送“ON”和“OFF”查看LED的变化,也可以使用MQTT调试助手测试,在google浏览器里搜索MQTTlens进行安装!

  • 连接服务器

    image.png
  • 给"LED"主题发送消息

    Publish里填入‘LED’主题,Message 填写要发送的消息


    image.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容