1. 程式人生 > >【ESP8266】ESP8266的MQTT客戶端搭建教程(基於NONS_SDK_v2.0)

【ESP8266】ESP8266的MQTT客戶端搭建教程(基於NONS_SDK_v2.0)

前言

MQTT是IBM開發的一個即時通訊協議,面向M2M和物聯網的連線,採用輕量級釋出和訂閱訊息傳輸機制,並且有可能成為物聯網的重要組成部分。

ESP8266是一款物美價廉的Wi-Fi晶片,整合Tensilica L106 鑽石系列的32 位處理器和片上SRAM,多達17 個GPIO口,並擁有IIC、IIS、UART、PWM、IR遙控等片上資源。

ESP8266還提供官方的軟體開發開發包(SDK),目前最新版本是「ESP8266 NONOS SDK V2.0.0」。

這篇文章主要講解如何使用ESP8266(基於NONS_SDK_v2.0)作為MQTT客戶端,並連上在本地電腦搭建的MQTT伺服器。

開發環境

首先簡單說明一下博主的開發環境:

  • ESP8266 SDK版本:esp8266_nonos_sdk_v2.0.0_16_08_10_0
  • MQTT伺服器:Apollo 1.7.1(本地搭建)
  • 作業系統:64位 Win10系統
  • ESP8266開發板:NodeMCU(4MB Flash)

提醒

閱讀本教程時,如果有使用esp8266_nonos_sdk_v2.0.0的開發經驗,會更輕鬆的使用本教程。如果遇到程式碼編譯出錯、燒寫下載不行以及下載後出現異常的問題,請先參考其他資料再繼續本文。

匯入工程

本教程基於ESP8266 IDE 2.0,如果讀者使用一樣的環境,那麼步驟1~4就好理解了,不是的話直接看圖片和步驟5:

  1. 在IDE環境中通過「File」->「Import」;
  2. 彈窗中選擇「C/C++」->「Existing Code as Makefile project」;
  3. 下一步「Browse…」,編譯器選擇「Cygwin GCC」;
  4. 之後匯入的工程目錄如上圖,其中給「dirver_lib」檔案下面的Makeflie新增bak字尾或刪除掉,免得編譯通不過。
  5. 從「example」資料夾中拷貝esp_mqtt_proj資料夾到主目錄,點選編譯按鈕,如果成功就完成這一步驟了。

工程目錄

工程目錄圖。注意紅色方塊內的檔案。

MQTT程式碼使用簡析

mqtt例程目錄

示例工程中最重要的是這兩個檔案:user目錄下的user_main.c

和inlcude目錄下的mqtt_config.h

其中user_main.c不用說了,玩過ESP8266的朋友都知道這是放主程式碼的地方,其中user_init函式是SDK提供開發者放置初始化程式碼的地方。下面主要分析mqtt_config.h。

mqtt_config.h程式碼清單

#ifndef __MQTT_CONFIG_H__
#define __MQTT_CONFIG_H__

#define CFG_HOLDER  0x00FF55A4  /* Change this value to load default configurations */
#define CFG_LOCATION    0x79    /* Please don't change or if you know what you doing */
#define MQTT_SSL_ENABLE

/*DEFAULT CONFIGURATIONS*/

#define MQTT_HOST           "192.168.1.100" //or "mqtt.yourdomain.com"
#define MQTT_PORT           1883
#define MQTT_BUF_SIZE       1024
#define MQTT_KEEPALIVE      120  /*second*/

#define MQTT_CLIENT_ID      "DVES_%08X"
#define MQTT_USER           "DVES_USER"
#define MQTT_PASS           "DVES_PASS"

#define STA_SSID "DVES_HOME"
#define STA_PASS "yourpassword"
#define STA_TYPE AUTH_WPA2_PSK

#define MQTT_RECONNECT_TIMEOUT  5   /*second*/

#define DEFAULT_SECURITY    0
#define QUEUE_BUFFER_SIZE               2048

#define PROTOCOL_NAMEv31    /*MQTT version 3.1 compatible with Mosquitto v0.15*/
//PROTOCOL_NAMEv311         /*MQTT version 3.11 compatible with https://eclipse.org/paho/clients/testing/*/

#endif // __MQTT_CONFIG_H__

在這個檔案中,有幾個巨集定義可能需要修改的:

  • MQTT_HOST:MQTT伺服器地址
  • MQTT_PORT:MQTT伺服器埠
  • MQTT_USER:MQTT伺服器使用者名稱
  • MQTT_PASS:MQTT伺服器密碼
  • STA_SSID:WI-FI帳號
  • STA_PASS:WI-FI密碼

注意
還有一個最重要的巨集定義——CFG_HOLDER,因為這個MQTT示例在ESP8266執行過一次後會把這些資訊儲存到FLASH中,如果要繼續修改這些資訊,記得要修改CFG_HOLDER這個巨集定義,改成另一個數值即可。

CFG_HOLDER作的用是:在CFG_Load函式中,如果發現從FLASH讀取出來的CFG_HOLDER數值和巨集定義的不一樣,則會更新這些資訊,並儲存到FLASH中。不修改CFG_HOLDER的話可能會發覺明明使用者名稱和密碼都正確但是就是連線不上去。

修改程式碼及測試

修改程式碼

根據上面分析,下面我們就可以修改示例程式碼:

  1. STA_SSIDSTA_PASS修改為自己的WiFI名和密碼;
  2. 修改MQTT_USERMQTT_PASS為對應的MQTT伺服器的使用者名稱和密碼,Apollo伺服器預設是adminpassword
  3. 修改MQTT_HOSTMQTT_PORT為MQTT伺服器IP和PORT,目前是使用本地的MQTT伺服器,所以是修改為自己電腦的IP和61613埠,PORT是整型值;
  4. 根據MQTT伺服器的協議不同,可能需要使用MQTT v3.1.1版本,所以把PROTOCOL_NAMEv31註釋掉,使用PROTOCOL_NAMEv311。原始碼的PROTOCOL_NAMEv311前面沒有#define,自己加上就行。
  5. 最後,修改CFG_HOLDER,以讓這些配置生效,直接給原來CFG_HOLDER定義的數值加1即可。

修改示例配置

編譯下載

編譯,檢視Console視窗,如果輸出

編譯輸出

那說明程式碼已經編譯成功。另外要注意,ESP8266 SDK v2.0版本生成的eagle.irom0text.bin燒寫起始地址是0x10000,而之前的版本燒寫地址是0x40000;eagle.flash.bin還是0x00000。由於博主使用的是4MB Flash的ESP8266,所以也建議讀者先確定手頭的ESP8266是不是4MB Flash(即32Mbit Flash,注意單位!4MB=32Mbit,Flash一般是以bit計算!)

另外如果Problems視窗報Errors的,只要Console視窗編譯通過,就可以不用管。

下載配置,僅供參考:

下載配置

提醒

blank.bin和default.bin燒寫一次就行,另外也要留意不同的Flash大小,blank.bin和default.bin燒寫地址也不同。

另外,給NodeMCU燒寫韌體的時候,SPI MODE選項可能要選DIO。詳細細節參考這裡
其他的ESP8266開發板一般則選擇預設的QIO就行了。

上電測試

如果前面一切順利,開啟串列埠,設定波特率為115200,上電後前面的亂碼不用管,之後串列埠列印資訊如下,省略了一部分資訊:

load ...
default configuration
MQTT_InitConnection
MQTT_InitClient
WIFI_INIT

……(省略)

connected with <WiFi名>, channel 6
dhcp client start...
STATION_IDLE
STATION_IDLE
ip:<ESP8266的IP>,mask:255.255.255.0,gw:<WiFi閘道器IP>
TCP: Connect to ip  <MQTT伺服器IP:PORT>
MQTT: Connected to broker <MQTT伺服器IP:PORT>
MQTT: Sending, type: 1, id: 0000
TCP: Sent
TCP: data received 4 bytes
MQTT: Connected to <MQTT伺服器IP:PORT>
MQTT: Connected
MQTT: queue subscribe, topic"/mqtt/topic/0", id: 1
MQTT: queue subscribe, topic"/mqtt/topic/1", id: 2
MQTT: queue subscribe, topic"/mqtt/topic/2", id: 3
MQTT: queuing publish, length: 23, queue size(66/2048)
MQTT: queuing publish, length: 25, queue size(91/2048)
MQTT: queuing publish, length: 25, queue size(118/2048)
……

其中帶尖括號的欄位根據測試環境不同而不同。

同時看原始碼和串列埠資訊可知,ESP8266向MQTT伺服器訂閱了三個主題,假設使用的是本地搭建的MQTT伺服器,那麼檢視MQTT伺服器後臺就可以看到:

ESP8266MQTT示例程式碼訂閱

同時在後臺的Connects頁面也可以看到ESP8266的連結:

ESP8266後臺連結

MQTT本地伺服器搭建教程Windows版連結在後面。

另外博主已經用ESP8266的MQTT連線上了OneNET雲,連線該雲需要註釋掉下面這條語句,在user_init函式下。

MQTT_InitLWT(&mqttClient, "/lwt", "offline", 0, 0);

原因是OneNET不支援MQTT協議的Will欄位,否則可能連線不上。

其他

評論統一回復

上電亂碼

評論區很多朋友回覆上電後列印亂碼,我都不知道你們的亂碼是怎樣的?請確保已經修改了WiFi帳號和密碼。同時請確定自己的ESP8266是否是4MB Flash(32Mbit Flash)。(評論區出現好幾個這樣的情況:第一次燒寫後重啟成功,之後重啟晶片就不行的情況,如果有讀者知道原因的希望告知下,謝謝。另,我估計絕對不是本教程的問題。)

上電啟動資訊預設波特率是76800bps,進入user_init後串列埠被初始化為115200bps。

如果反覆列印STATION_IDLE ,說明沒有連上WiFi。

load ...
default configuration
MQTT_InitConnection
MQTT_InitClient
WIFI_INIT

System started ...
mode : sta(18:fe:34:**:**:**)
add if0
STATION_IDLE
STATION_IDLE
STATION_IDLE
scandone
no your_wifi_ssid found, reconnect after 1s
reconnect
STATION_IDLE
STATION_IDLE
STATION_IDLE
STATION_IDLE
scandone
no your_wifi_ssid found, reconnect after 1s
reconnect
STATION_IDLE
STATION_IDLE
STATION_IDLE
STATION_IDLE
STATION_IDLE
scandone
no your_wifi_ssid found, reconnect after 1s
reconnect
STATION_NO_AP_FOUND
scandone
STATION_IDLE
STATION_IDLE
STATION_IDLE
STATION_IDLE
scandone
no your_wifi_ssid found, reconnect after 1s

另外一定要注意:ESP8266 SDK v2.0版本生成的檔案燒寫地址:

bin檔案 燒寫地址
eagle.flash.bin 0x00000
eagle.irom0text.bin 0x10000

燒寫錯誤會導致晶片不斷的重啟!請仔細閱讀「編譯下載」小節。

另外v2.0以下版本的SDK(不包括v2.0)eagle.irom0text.bin是燒寫在0x40000,請自行參考其他資料。

安全連線

關於MQTT的安全連線,在配置檔案中和這兩個巨集定義有關:

//第6行左右
#define MQTT_SSL_ENABLE

//第25行左右
#define DEFAULT_SECURITY    0

其中我檢視原始碼,巨集定義MQTT_SSL_ENABLE是SSL連線的預編譯,如果不定義MQTT_SSL_ENABLE則表示不支援SSL(最好看原始碼理解)。
DEFAULT_SECURITY是SSL是否使能,0為禁能,1為使能。

esp_mqtt_proj/mqtt/mqtt.c檔案下的MQTT_Connect函式部分原始碼:

void ICACHE_FLASH_ATTR
MQTT_Connect(MQTT_Client *mqttClient)
{
    //省略……
    if (mqttClient->security)
    {
    #ifdef MQTT_SSL_ENABLE
        espconn_secure_connect(mqttClient->pCon);
    #else
        INFO("TCP: Do not support SSL\r\n");
    #endif
    }
    else
    {
        espconn_connect(mqttClient->pCon);
    }
    //省略……
}

其中mqttClient->securityDEFAULT_SECURITY賦值。在esp_mqtt_proj/modules/config.c的CFG_Load函式裡。

sysCfg.security = DEFAULT_SECURITY; /* default non ssl */

最後會在user_init函式初始化。

MQTT_InitConnection(&mqttClient, sysCfg.mqtt_host, sysCfg.mqtt_port, sysCfg.security);

關於燒寫後第一次啟動正常,之後不斷重啟的問題

在makefile檔案裡面把SPI_SIZE_MAP?=0改為SPI_SIZE_MAP?=4。

參見評論區33樓。

update:2018-03-05

關於連線阿里雲百度雲等

因為這些雲平臺的mqtt_namemqtt_pass比較長,而MQTTconfig.h中儲存到Flash中的結構體的這些欄位不夠長,這樣就會導致連線不上雲平臺。解決辦法就是手動增大陣列大小。(感謝評論區35樓評論者的提醒)

// esp_mqtt_proj/include/module/config.h
typedef struct{
    uint32_t cfg_holder;
    uint8_t device_id[32];

    uint8_t sta_ssid[64];
    uint8_t sta_pwd[64];
    uint32_t sta_type;

    uint8_t mqtt_host[64];
    uint32_t mqtt_port;
    uint8_t mqtt_user[32];
    uint8_t mqtt_pass[32];
    uint32_t mqtt_keepalive;
    uint8_t security;
} SYSCFG;

update:2018-04-04

相關推薦

ESP8266ESP8266的MQTT客戶搭建教程基於NONS_SDK_v2.0

前言 MQTT是IBM開發的一個即時通訊協議,面向M2M和物聯網的連線,採用輕量級釋出和訂閱訊息傳輸機制,並且有可能成為物聯網的重要組成部分。 ESP8266是一款物美價廉的Wi-Fi晶片,整合Tensilica L106 鑽石系列的32 位處理器和片上S

原創MQTT客戶搭建-最清晰的MQTT協議架構

關於MQTT客戶端或者伺服器,在MQTT的github主頁上應該有不少的軟體和工具,很多時候我們的目的是用MQTT協議去開發自己的專案,而現成的軟體或者工具,主要是提供我們在開發前期的調研、開發過程的測試,都是必不可少的學習借鑑用的,所以,欲善其事,先利其器吧! MQT

PHP判斷客戶執行的環境pc與手機

class self_test { const PC = 'pc'; const SP = 'sp'; private $_splist = array('iPhone','Android','iPod','iPad','Tizen');//設定經常使用的sp終端

原創MQTT服務搭建-最快方式驗證自己開發的客戶

文章首發於同名微信公眾號:DigCore 歡迎關注同名微信公眾號:DigCore,及時獲取最新技術博文。 在上一篇文章《【原創】MQTT客戶端搭建-最清晰的MQTT協議架構》中提到了MQTT.fx工具作為客戶端使用時,使用了該工具官方提供的伺服器m2m.eclipse

轉載java 客戶鏈接不上redis解決方案 (jedis)

主機 rom number table 出現 gin 現在 start http 本文出自:http://blog.csdn.net/lulidaitian/article/details/51946169 出現問題描述: 1.Could not get a resou

vbs查詢客戶上的應用程序

spa uninstall fault play windows const war str jre 方法一: strHost?=?"."Const?HKLM?=?&H80000002Set?objReg?=?GetObject("winmgmts://"?&

解決GitHub 客戶下載後安裝在哪裡?

GitHub Desktop 配置環境變數 GitHub 安裝路徑 GitHub Shell、Bash 環境是 Windows 10。 從 GitHub 官網下載了 GitHub 的 Desktop 版本之後,它其實不僅是一個 GUI,還帶了 Shel

說說zookeeper_zkClient客戶

本文說說zookeeper最常用的兩個客戶端:zkClient和Curator。 zkClient zkClient是github上一個開源的zookeeper客戶端,在zookeeper原

redis知識盤點_客戶Jedis

系列文章:本篇文章主要介紹一下redis的客戶端Jedis。首先明確兩點:一、redis客戶端與服務端之間的通訊協議是在TCP協議之上構建的;二、Redis制定了RESP(REdis Serializa

分散式Zookeeper客戶基本的使用

  與mysql、redis等軟體一樣,zookeeper的軟體包中也提供了客戶端程式用於對伺服器上的資料進行操作。本節我們就來學習zookeeper客戶端的使用方法。不過在詳細講解zk客戶端的使用方法之前,我們會先來討論zookeeper的資料儲存結構,只有理解了zookeeper的資料儲存結構,才會真正明

GitGit客戶使用

Git的Gui不怎麼好用,建議使用Git Bash命令。 Git的結構如下: 本地工作區 - 本地暫存區 - 本地倉庫 - 遠端倉庫 倉庫中有分支,每個分支記錄了不同的commit資訊,取決於使用者commit到哪個分支。一般來講,不是大型專案,一般都只使用一個master分支。 提交資料流程如下

linuxmysql客戶emma中文亂碼問題解決

參考 詳情 emma預設用apt-get 安裝的話,emma是不支援中文的,配置檔案或直接修改emma程式原始檔(python)。 也可以通過ubuntu的軟體市場安裝 apt-get安裝emma sudo apt-get install e

GitGit客戶SourceTree的使用

git的客戶端,SourceTree當然不是唯一的選擇,有很多公司還用TortoiseGit。這篇部落格就簡單介紹一下SourceTree的使用,後續有機會再介紹TortoiseGit。首先是Sour

PHP獲取客戶瀏覽器資訊、獲取客戶系統資訊、獲取伺服器資訊

一、PHP獲取客戶端(瀏覽器)資訊函式/** * 獲取客戶端瀏覽器資訊 * @param null * @author https://blog.jjonline.cn/phptech/168.html * @return string */

NASNFS客戶掛載目錄後無寫入許可權的解決方案

在客戶機通過mount -o rw -t nfs 192.168.192.204:/mnt/cephfs /mnt/nfs命令將網路檔案mount到本地。執行完成之後,目錄是可以訪問了,但無法寫入。分析

資料庫oracle客戶PL/SQL

引言 不知為什麼,使用navicat客戶端(有一個版本既可以連線mysql,又可以連結oracle)連線oracle的時候總是崩掉(難道是因為我筆記本比較渣的原因),而且好像同事使用PL/SQL也比較多,決定使用PL/SQL試試(雖然覺得PL/SQL介面不怎麼

元旦三天假期,實現一個電商退單管理系統-手機客戶實現

需求變更  拆包出現異常,需要留下照片憑證,以防後期抵賴。這當然屬於手機端功能,於是強烈向電商老闆推薦手機客戶端。 另外近期出現了一個奇怪的bug,經常掃碼時重複出現同一個編碼,明明已經掃了別的碼了,系統裡接收一的還是前一個。非常難復現,初步懷疑是掃碼槍的快取功能造成的,但沒有辦法根治,造成倉庫抱怨

MongoDBNoSQL Manager for MongoDB 教程基礎篇

好的 log 很難 gpo ssi next 破解 情況 eight 前段時間,學習了一下mongodb,在客戶端工具方面,個人認為 NoSQL Manager for MongoDB 是體驗比較好的一個,功能也較齊全。可惜在找教程的時候,發現很難找到比較詳細的

微軟的Python入門教程

Overview >概述 The series of videos on Channel 9 is designed to help get you up to speed on Python. If you're a beginning developer who's looking to add

Appium的安裝-Mac平臺命令行 dmg

兼容性問題 壓縮 解壓 3.1 修改文件 9.png 根據 ref 成功 其實Appium的安裝方式主要有兩種: 1)自己安裝配置nodejs的環境,然後通過npm進行appium的安裝 2)直接下載官網提供的dmg進行安裝,dmg裏面已經有