ESP-12F 網路智慧開關(MQTT)

學習如何學習!

物聯網

當我們要做一個遠端控制的專題時,最好的方式是讓該裝置連上網路,如果能跨網路且不侷限在區域網路內才能控制時,就需要有一個雲端伺服器。雲端伺服器可以自己架設,也可以找尋免費提供的伺服器。免費提供的伺服器最大的優點就是方便及免費,但缺點就是不穩定且安全性較差。

我們選擇一個輕量的通訊協定(MQTT) 來做控制,test.mosquitto.orgmqtt.eclipseprojects.io 提供免費的 MQTT 雲端伺服器(broker),不需要申請就能直接使用,因此不需要使用者帳號與密碼,也因為不需要使用者帳號與密碼,安全性堪慮,如果是重要的控制,最好還是使用需要申請的 MQTT broker比較安全,如果只是實習用,就上述2個伺服器選擇1個來用就行。

MQTT broker(經紀人) 接受用戶端(Client)發佈(publisher)主題(Topic)與內容,其它有訂閱(subscriber)此主題的用戶端,都能收到MQTT broker(經紀人)轉送來的內容。用戶端之間有 broker 伺服器當作中繼站,所以用戶端之間並不需要知道彼此的IP位址,可以跨網域控制。

設備與材料

個人電腦 × 1
ESP12F × 1
麵包板 × 1
智慧手機 × 1
PB按鈕 × 1
繼電器模組 × 1
連接線 若干

實體接線圖


手機設定

因為用手機控制我們的專題,手機部份必需有支援 MQTT 的程式才行,手機這部份的程式已有現成的程式,我的手機是 Android ,因此打開 Play 商店,輸入mqtt 篩選(如下左圖),目前覺得 Lapetov 推出的 MQTT dashboard 符合我的使用要求,只要下載來設定一下就能控制。安裝後(如下中圖)執行會出現如下右圖,他有2個範例控制面板提供你參考,按 + 可以新增控制面板,輸入 Name(名稱) 及 Description(描述) 按左上方 就可以新增我們的控制面板,左上功能選單可以進入MQTT connections 連線設定。


按 MQTT connections 進入 連線設定,他有3個連線範例,都是連到 test.mosquitto.org ,如果你用其它MQTT 伺服器,可以新增連線,或是直接修改都可以。


我們新增一個 “BLOCK IOT” 控制面板,點進去如下左圖畫面,按 + 就可以新增控制元件了(如下中圖),選擇 “Toggle” 形式的控制元件,輸入 Name 並開啟 MQTT enable。


選擇要連線到之前設定的那個伺服器,在 “Topic for publish” 輸入你在 ESP12F 程式內訂閱的主題,Retain 是保留選項,不需要勾選,”Qos for publish” 傳送品質用內定的 0 就可以。 “Toggle” 形式的控制元件會有2種狀態 State(ON)、State(OFF),先設定 State(ON) ,Payload 是 State(ON)時發佈主題的內容;Text 是 State(ON)時顯示在手機的文字,也可以選擇不顯示;ICON 是 State(ON)時顯示的圖示,圖示可以改,顏色也可以改,大小也可以變換。


State(OFF)設定方式與State(ON)相同,只是區別ON、OFF ,顏色不同, State(OFF)時發佈主題的內容不同,Uptime 是發佈的時間,可以選擇要不要顯示,控制元件的 Name 可以選擇要不要顯示,如果都設定好按左上方 就可以新增控制元件了。


控制元件可以變更大小與位置,按左上 + 圖示旁的 方框圖示,可以進入大小與位置變更。如果想要變更控制元件的設定,可以長按住控制元件,會出現選單,可以編輯、複製、刪除。


我們進去重新變 ICON 大小,也選擇不顯示控制元件邊框,最後完成如下右圖的控制元件。
你按一下控制元件,會發佈主題為 a1b2c3d4e5f6/IOTPowerPlug/set 內容為 0 到 test.mosquitto.org 伺服器,只要有在 test.mosquitto.org 伺服器 訂閱 主題為 a1b2c3d4e5f6/IOTPowerPlug/set 的設備,都會收到 0 這個內容;
再按一下控制元件,會發佈主題為 a1b2c3d4e5f6/IOTPowerPlug/set 內容為 1 到 test.mosquitto.org 伺服器,只要有在 test.mosquitto.org 伺服器 訂閱 主題為 a1b2c3d4e5f6/IOTPowerPlug/set 的設備,都會收到 1 這個內容。


開發環境

使用 Arduino IDE 安裝 ESP8266開發板,如果不知道如何安裝ESP8266開發板,可以參考 “準備你的 ESP12E/F 開發工具” ,安裝開發板之後,記得開發板選擇 “NodeMCU 1.0(ESP-12E Module)” ,之後安裝MQTT 程式庫,如下圖步骤。



ESP12F 範例程式

/*
 *  網路智慧開關
 *  開發工具 Arduino IDE 必需自行加入ESP12F 開發板
 *  開發板 ESP12F(ESP8266)   
 *  此程式為範例程式,並未加入對繼電器的控制,僅用板上LED來表示開關 ON OFF
 *  使用通訊協定 MQTT ,MQTT broker 使用 test.mosquitto.org
 *  程式會訂閱 subTopic 設定的主題,只要有對此主題發佈內容1 開關就 ON 內容0 開關就 OFF
 *  狀態改變,會發佈最新狀態到 pubTopic 設定的主題,內容為目前開關狀態(ON->1 OFF->0)
 *  程式每60秒會發佈 到 pubTopic 設定的主題,內容為目前開關狀態(ON->1 OFF->0)
 *  https://www.block.tw/blog
 */

// 引用 Wifi AP 程式庫(連上wifi無線AP用)
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
// 引用 Wifi  程式庫(連上網際網路用)
#include <WiFiClient.h>

//引用 MQTT 程式庫 需要自行安裝程式庫 https://github.com/knolleary/pubsubclient
#include <PubSubClient.h>

//宣告 wifi AP網路 連線物件
ESP8266WiFiMulti wifiMulti;

//宣告 wifi 網路連線物件
WiFiClient espClient;

//宣告 MQTT 連線物件
PubSubClient client(espClient);

//WIFI SSID 跟密碼
#define   APSSID  "2.4G wifi 的SSID"
#define   APPW    "2.4G wifi 的密碼"

// MQTT test.mosquitto.org 伺服器 不需要使用者名稱 密碼
// 所以每個人都能用,如果有人跟你有相同的主題(topic)就能控制你的設備
const char* brokerUser  = "";  //使用者名稱
const char* brokerPass  = "";  //使用者密碼
const char* broker      = "test.mosquitto.org";
//const char* broker      = "mqtt.eclipseprojects.io";
const char* pubTopic    = "a1b2c3d4e5f6/IOTPowerPlug/state";
const char* subTopic    = "a1b2c3d4e5f6/IOTPowerPlug/set";
byte        state       = 0;
char        msg[10]     ;
long        currentTime, lastTime;

void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
  //內建板上 LED 滅
  digitalWrite(LED_BUILTIN, HIGH);
  Serial.begin(115200);
  setupWiFi();
  client.setServer(broker, 1883);
  client.setCallback(callback);
}

void loop()
{
  if (!client.connected())
  {
    //連接 MQTT 伺服器
    MQTTconnect();
  }
  client.loop();
  currentTime = millis();
  
  //60秒發一次訊息
  if(currentTime - lastTime > 60000)
  {
    Serial.print("Sending messages:\t");        
    dtostrf(state, 1, 0, msg);             //byte 轉 char *
    Serial.println(msg);
    client.publish(pubTopic,msg);          //發佈
    lastTime = millis();
  }
   
}

//訂閱的主題有人發佈訊息時的處理函式
void callback(char* topic, byte* payload, unsigned int len)
{
  Serial.print("Received messages: ");
  Serial.println(subTopic);
  for (unsigned int i = 0; i < len; i++)
  {
    Serial.print((char) payload[i]);

    if (len == 1 && payload[0] == '1'){
      // 1
      state=1;
      digitalWrite(LED_BUILTIN, LOW);      
      dtostrf(state, 1, 0, msg);    
      client.publish(pubTopic,msg);
    }else if (len == 1 && payload[0] == '0'){
      // 0
      state=0;
      digitalWrite(LED_BUILTIN, HIGH);      
      dtostrf(state, 1, 0, msg);    
      client.publish(pubTopic,msg);
    }
  }
  Serial.println();
}

//連接無線 wifi 的處理函式
void setupWiFi()
{
  delay(100);

  //連接無線 wifi
  wifiMulti.addAP(APSSID, APPW);

  Serial.println("Wifi Connecting ...");

  //內建板上 LED 亮
  digitalWrite(LED_BUILTIN, LOW);

  while (wifiMulti.run() != WL_CONNECTED)
  {
    delay(250);
    Serial.print('.');
  }

  //內建板上 LED 滅
  digitalWrite(LED_BUILTIN, HIGH);

  Serial.println('\n');
  Serial.print("Connected to:\t");
  Serial.println(WiFi.SSID());

  Serial.print("IP address:\t");
  Serial.println(WiFi.localIP());
}


void MQTTconnect()
{
  while (!client.connected())
  {
    //連接 MQTT 伺服器,因為是免費無使用帳號跟密碼,所以底下隨便輸入的
    if (client.connect("MQTT_CLIENT_ID", "brokerUser", "brokerPass")) {
      Serial.print("\nConnected to ");
      Serial.println(broker);
      //訂閱主題
      client.subscribe(subTopic);
    } else {
      Serial.println("Connecting");
      delay(2500);
    }
  }
}

序列埠監控視窗畫面


功能要求

1.加上繼電器模組,板上 LED 只指示是否連上 Wifi
2.增加1按鈕,按一下狀態變 ON,再按一下狀態變 OFF
3.修改手機 MQTT 應用程式,將原來的 “Toggle” 形式的控制元件(只發送,沒訂閱),新增訂閱 subTopic 所指定的主題,讓手機控制開關狀態與遠端裝置狀態相同
4.設定手機 MQTT 應用程式,多一個 “Toggle” 形式的控制元件(只訂閱,不發送),用來顯示目前裝置 ON 或 OFF

入門
知識
語法
流程
函式
實習

發佈留言