Machine-to-Machine (M2M) 協定目前常見的包括有 CoAP、XMPP、RESTful HTTP及MQTT 。
● CoAP (Constrained Application Protocol)受限應用協定,是採用UDP方式傳送用在受限制的資源上的一個類似HTML觀念的應用層協定。其協定最小資料為4 byte header
也就是說當你下一個類似coap://example.com:5683/~sensors./temp1.xml這樣的CoAP URI你就可以得到該感測器的資訊。
● XMPP (Extensible Messaging and Presence Protocol )大家應該就比較熟悉了,這是一個採用TCP連接並且可以透過XML進行雙向溝通的協定。經常用在即時通訊之類的軟體上。
● RESTful 符合REST(Representational State Transfer)原則的系統統稱為RESTful,REST同樣架構在HTTP over TCP上的一個協定,比較適合在雲端運算之類的環境。
● MQTT前一篇文章已經介紹過了這裡就不重複說明,下圖是Cisco原廠所做的比較表:
繼上一篇的MQTT推播訊息到Android文章後,接著本篇文章來驗證看看是不是真的可以從Arduino上來進行訊息的推播。
實作:
環境說明:
Arduino UNO
Arduino Ethernet Shield
Raspberry Pi
EDIMAX 訊舟 EW-7822Uan 300M USB無線網路
SanDisk 16G microSDHC card
作業系統:
RASPBIAN (NOOBS 1.4.0 2015-02-18 )
mosquitto 1.4
開發環境:
Win 8.1 X64專業版
Arduino IDE 1.6.1
事前準備:
1. 礙於篇幅,本文主題並不是Arduino的基礎教學,如果不清楚Arduino基礎操作者,請至網路搜尋一下相關入門教學。
2. 使用Ethernet Shield 或者是 WiFi Shield 皆可,只要確認Arduino能夠連上網路就行,由於WiFi Shield太貴了加上沒有Sponsors所以本文採用Ethernet Shield。詳細網路連線部分同樣屬於入門基礎,本文不會有太多說明。
3. 本文使用的Arduino程式碼是透過別人所寫好的函式庫(library)及範例,相關函式庫安裝同樣屬於入門基礎,本文不會有太多說明。
4. 當執行程式出問題時,請先用Ping指令確認Arduino、樹梅派、手機是否有相互連線以及其相關參數是否正確(尤其是Topic要確認正確)。
步驟:
1. 下載Arduino函式庫 MQTT Client Library
函式庫的官網:http://knolleary.net/arduino-client-for-mqtt/
目前為止最新版本為 1.9.1
我們要下載的檔案選擇 zip 其下載後的檔名為 pubsubclient-1.9.1.zip
2. 將 pubsubclient-1.9.1.zip 解壓縮後,把 PubSubClient 目錄拷貝到 Arduino IDE 的 libraries 目錄下。
3. 開啟Arduino IDE,接著用滑鼠點選上方的檔案-->範例-->PubSubClient--> mqtt_basic 此時會出現程式碼。
4. 接著我們只要改程式碼第15、16兩行的IP,改成樹梅派的IP及與樹梅派相同網段的IP,然後把程式燒錄至Arduino。
如果燒寫過程中出現錯誤,請先拔掉Ethernet Shield後再進行燒寫即可。
這裡說明一下程式碼中
第23行 把Arduino定義為發佈者(Publish)
第29行 其動作就是把"hello world"這串字傳送到名為outTopic的Topic。
第30行 把Arduino監聽inTopic的Topic訊息。
5. 此時連線到RPi上執行 mosquitto_sub -d -t outTopic
然後按下Arduino的Reset鍵,你將會看到下列訊息
Client mosqsub/3461-raspberryp received PUBLISH (d0, q0, r0, m0, 'outTopic', ... (11 bytes))
hello world
至此,我們確認Arduino已經將hello world傳送給Subscribe了。
6. 此時,我們再將Arduino的程式第29行的outTopic,改成上一篇所講的手機Topic (我測試手機的Topic為tokudu/34b2b406165a8b0d,請參考上一篇),這時候你就可以把Arduino上的"hello world"這串字傳送到你的手機上了。
7. 接著我們將Arduino的程式改成下面內容,然後燒錄到Arduino上。
/*
Basic MQTT example
- connects to an MQTT server
- publishes "hello world" to the topic "outTopic"
- subscribes to the topic "inTopic"
*/
#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>
// Update these with values suitable for your network.
byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED };
byte server[] = { 192, 168, 0, 135 }; //MQTT服務IP位址
byte ip[] = { 192, 168, 0, 10 }; // Arduino 設備IP位址
EthernetClient ethClient;
PubSubClient client(server, 1883, callback, ethClient);
char message_buff[100];
void setup()
{
Ethernet.begin(mac, ip);
if (client.connect("arduinoClient")) {
client.publish("outTopic","hello world");
client.subscribe("inTopic");
Serial.begin(9600);
Serial.println("Running......");
}
}
void loop()
{
// MQTT client loop processing
client.loop();
}
void callback(char* topic, byte* payload, unsigned int length) {
int i = 0;
Serial.println("Message arrived: topic: " + String(topic));
Serial.println("Length: " + String(length,DEC));
// create character buffer with ending null terminator (string)
for (i = 0; i < length; i++) {
message_buff[i] = payload[i];
}
message_buff[i] = '\0';
String msgString = String(message_buff);
Serial.println("Payload: " + msgString);
}
8. 此時,在RPi上執行 mosquitto_pub -d -t inTopic -m "on"
你將會在Arduino IDE中的序列埠監控視窗看到下面的訊息。
由上面的資訊,你可以確認由發佈者發布了一個"on"的字串到inTopic的Topic,此時Android會收到"on"這個字串,由此,我們只要在Arduino程式中加一個字串的判斷就可以控制GPIO輕鬆達到遠端開關的功能。
至此,我們即透過Arduino完成了一個簡單的MQTT之IoT應用。
最後,Raspberry Pi安裝MQTT之推播應用,我就用這兩篇文章來說明,日後還有看到其他應用在寫文章進行補充說明。
後記:
1. MQTT協定的訊息不像XML一樣,它沒有訊息標識,所以不容易理解;另外必須熟悉其訊息格式才能通訊。
但一般MCU在運算部分能力並不是很好,如果接收到的是XML訊息還要解析將會造成CPU的負擔,這時候MQTT的協定就有些優勢了。
2. 本文所提供的方式並非標準的IoT通用的通訊框架,如果考慮到未來IoT的相容性,建議參考「開放互連聯盟」(The Open Interconnect Consortium, OIC)標準組織所訂定的IoTivity。
不過值得注意的是由於國際上IoT的聯盟太多了,將來誰是主流還未勝負。所以IoTivity僅建議參考是需要觀察及審慎評估的,待時機成熟再擇一標準。
3. 這兩天寒流來了先不要管IoT通用的通訊框架了,下圖的結果是我把DHT11所收到的值,透過Arduino定時推播到我的手機上的結果,這樣就簡單地完成了一個行動氣象台了。
參考:
1.Beyond MQTT: A Cisco View on IoT Protocols
http://blogs.cisco.com/ioe/beyond-mqtt-a-cisco-view-on-iot-protocols
2.Arduino Client for MQTT
http://knolleary.net/arduino-client-for-mqtt/
https://github.com/knolleary/pubsubclient
3.Constrained Application Protocol(CoAP)
http://en.wikipedia.org/wiki/Constrained_Application_Protocol
4.Performance Evaluation of MQTT and CoAP via a Common Middleware
http://www.alvinvalera.net/wp-content/uploads/2014/10/issnip2014.pdf
5.什麼是REST跟RESTful?
https://ihower.tw/blog/archives/1542
6.IoTivity
https://www.iotivity.org/
7.台灣物聯網聯盟TIOTA
http://www.tiota.org.tw/
http://goo.gl/Mu66vS
==============延伸閱讀=====================
1. Raspberry Pi 第一次接觸
http://cheng-min-i-taiwan.blogspot.tw/2013/02/raspberry-pi.html
2.Raspberry Pi 網路設定
http://cheng-min-i-taiwan.blogspot.tw/2013/02/raspberry-pi_23.html
3.Raspberry Pi 應用之Windows檔案伺服器
http://cheng-min-i-taiwan.blogspot.tw/2013/02/raspberry-pi-windows.html
4.Raspberry Pi 應用之DLNA影音伺服器
http://cheng-min-i-taiwan.blogspot.tw/2013/02/raspberry-pi-dlna.html
5.Raspberry Pi 硬體控制-- Python 語言篇
http://cheng-min-i-taiwan.blogspot.tw/2013/04/raspberry-pi-python.html
6.Raspberry Pi 硬體控制-- C 語言篇
http://cheng-min-i-taiwan.blogspot.tw/2013/04/raspberry-pi-c.html
7.Raspberry Pi 2 Model B 使用心得
http://www.cheng-min-i-taiwan.blogspot.tw/2015/02/raspberry-pi-2-model-b.html
8.Raspberry Pi 藍牙4.0應用之iBeacon 發射器
http://www.cheng-min-i-taiwan.blogspot.tw/2015/03/raspberry-pi-40ibeacon.html
9.Raspberry Pi安裝MQTT之應用 -- Android訊息推播
http://www.cheng-min-i-taiwan.blogspot.tw/2015/03/raspberry-pimqtt-android.html
不好意思請問一下,是用任何wifi板的都可嗎?只要有網路功能即可。
回覆刪除只要arduino可以ping得到Raspberry Pi就可
刪除請問一下我是Arduino uno + Esp8266,是去libraries>mqtt_esp8266燒錄到Arduino uno就可以了嗎 ?
回覆刪除