MQTT (Message Queue Telemetry Transport) - mrolarik/simple-iot GitHub Wiki

MQTT (Message Queue Telemetry Transport) เป็นโปรโตคอล (Protocol) เพื่อใช้สำหรับ Internet of Things (IoT) โดยเฉพาะซึ่งเป็นโปรโตคอลที่ทำงานแบบ machine-to-machine (M2M) ซึ่งออกแบบมาเพื่อให้รับส่งข้อความ/ข้อมูล (Messaging Transport) ระหว่าง Server และ Client โดยผ่านตัวกลางซึ่งเรียกว่า MQTT Broker เพื่อให้สามารถ Publish และ Subscribe ข้อความ/ข้อมูล ระหว่างกัน

ลักษณะการทำงานของ MQTT

MQTT ที่มา [https://www.segger.com/products/connectivity/embosip/add-ons/mqtt-client/]

  • จากรูปภาพ Server จะทำการ publish ข้อมูลผ่าน MQTT Broker เพื่อให้ Client สามารถ Subscribe เพื่อใช้ข้อมูลหรือส่งข้อมูลผ่านไปยัง Server

ติดตั้งโปรแกรม mosquitto - MQTT broker

อ่านรายละเอียดเพิ่มเติมจากเว็บไซต์ https://mosquitto.org/

  • การติดตั้งทำได้ ดังนี้
  1. เพิ่ม external APT repository ลงไปใน /etc/apt/sources.list หรือ /etc/apt/sources.list.d
$ sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa
[sudo] password for cocobot: 
 
 More info: https://launchpad.net/~mosquitto-dev/+archive/ubuntu/mosquitto-ppa
Press [ENTER] to continue or ctrl-c to cancel adding it

gpg: keyring `/tmp/tmp1f584mvv/secring.gpg' created
gpg: keyring `/tmp/tmp1f584mvv/pubring.gpg' created
gpg: requesting key 262C4500 from hkp server keyserver.ubuntu.com
gpg: /tmp/tmp1f584mvv/trustdb.gpg: trustdb created
gpg: key 262C4500: public key "Launchpad mosquitto" imported
gpg: Total number processed: 1
gpg:               imported: 1  (RSA: 1)
OK
  1. update ระบบ Linux เพื่อให้สามารถติดตั้งโปรแกรม mosquitto ได้
$ sudo apt-get update
  1. ติดตั้งโปรแกรม mosquitto
$ sudo apt-get install mosquitto mosquitto-clients python-mosquitto

ผลลัพธ์ที่ได้

Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following packages were automatically installed and are no longer required:
  libvtk5.10 libvtk5.10-qt4 linux-headers-4.10.0-42
  linux-headers-4.10.0-42-generic linux-headers-4.13.0-31
  linux-headers-4.13.0-31-generic linux-headers-4.13.0-32
  linux-image-extra-4.13.0-31-generic linux-image-extra-4.13.0-32-generic
  linux-image-extra-4.13.0-45-generic
Use 'sudo apt autoremove' to remove them.
The following additional packages will be installed:
  libc-ares2 libmosquitto1
The following NEW packages will be installed:
  libc-ares2 libmosquitto1 mosquitto-clients
0 upgraded, 3 newly installed, 0 to remove and 74 not upgraded.
Need to get 144 kB of archives.
After this operation, 336 kB of additional disk space will be used.
Do you want to continue? [Y/n] y
Get:1 http://th.archive.ubuntu.com/ubuntu xenial-updates/main amd64 libc-ares2 amd64 1.10.0-3ubuntu0.2 [34.1 kB]
Get:2 http://ppa.launchpad.net/mosquitto-dev/mosquitto-ppa/ubuntu xenial/main amd64 libmosquitto1 amd64 1.4.15-0mosquitto1~xenial1 [54.6 kB]
Get:3 http://ppa.launchpad.net/mosquitto-dev/mosquitto-ppa/ubuntu xenial/main amd64 mosquitto-clients amd64 1.4.15-0mosquitto1~xenial1 [55.6 kB]
Fetched 144 kB in 2s (65.0 kB/s)             
Selecting previously unselected package libc-ares2:amd64.
(Reading database ... 810003 files and directories currently installed.)
Preparing to unpack .../libc-ares2_1.10.0-3ubuntu0.2_amd64.deb ...
Unpacking libc-ares2:amd64 (1.10.0-3ubuntu0.2) ...
Selecting previously unselected package libmosquitto1:amd64.
Preparing to unpack .../libmosquitto1_1.4.15-0mosquitto1~xenial1_amd64.deb ...
Unpacking libmosquitto1:amd64 (1.4.15-0mosquitto1~xenial1) ...
Selecting previously unselected package mosquitto-clients.
Preparing to unpack .../mosquitto-clients_1.4.15-0mosquitto1~xenial1_amd64.deb ...
Unpacking mosquitto-clients (1.4.15-0mosquitto1~xenial1) ...
Processing triggers for libc-bin (2.23-0ubuntu10) ...
Processing triggers for man-db (2.7.5-1) ...
Setting up libc-ares2:amd64 (1.10.0-3ubuntu0.2) ...
Setting up libmosquitto1:amd64 (1.4.15-0mosquitto1~xenial1) ...
Setting up mosquitto-clients (1.4.15-0mosquitto1~xenial1) ...
Processing triggers for libc-bin (2.23-0ubuntu10) ...

ติดตั้งโปรแกรม paho-mqtt

การติดตั้ง Paho MQTT สามารถติดตั้งผ่าน pip โดยพิมพ์คำสั่งดังต่อไปนี้

$ sudo pip install paho-mqtt

ผลลัพธ์ที่ได้จากการติดตั้ง

Collecting paho-mqtt
  Downloading https://files.pythonhosted.org/packages/2a/5f/cf14b8f9f8ed1891cda893a2a7d1d6fa23de2a9fb4832f05cef02b79d01f/paho-mqtt-1.3.1.tar.gz (80kB)
    100% |████████████████████████████████| 81kB 764kB/s 
Installing collected packages: paho-mqtt
  Running setup.py install for paho-mqtt ... done
Successfully installed paho-mqtt-1.3.1

ทดสอบการทำงานไลบรารี่ paho.mqtt

เมื่อติดตั้งเสร็จเรียบร้อยสามารถทดสอบการทำงาน paho.mqtt ดังต่อไปนี้

$ python
>>> import paho.mqtt
>>>
  • หากการติดตั้งสมบูรณ์ จะไม่ปรากฎข้อความใด ๆ หลังจากที่อิมพอร์ท paho.mqtt
  • การติดตั้ง paho mqtt สามารถอ่านรายละเอียดได้จากเว็บ https://pypi.org/project/paho-mqtt/

ทดสอบการทำงานของโปรแกรม mosquitto - MQTT Broker

เพื่อให้ง่ายต่อการทดสอบ ให้ติดตั้ง mosquitto ด้วยคำสั่ง sudo apt-get install mosquitto mosquitto-clients python-mosquitto ทั้งเครื่อง Server และเครื่อง Client

สำหรับการทดสอบ จะทดสอบโดยจำลองเครื่องคอมพิวเตอร์ให้เป็นเครื่อง Server และจำลองเครื่อง Raspberry Pi (RPi) ให้เป็น Client ทั้งนี้เนื่องจากต้องการใช้ RPi ทำการส่งข้อมูลจากเซ็นเซอร์ไปเก็บไว้ที่เครื่อง Server ดังนั้น

  • Server จึงจำลองให้เป็น Subscriber
  • RPi จึงถูกจำลองให้เป็น Publisher

1. ฝั่ง Server / Subscriber

  • เปิด Terminal และพิมพ์คำสั่ง
$ mosquitto_sub -t "test/chat" -h 10.33.1.204 -d

โดยที่

  • mosquitto_sub เป็นการทำงานในฝั่งของ subscriber
  • -t "test/chat" เป็น topic ของ message ที่จะใช้สื่อสารระหว่าง publisher และ subscriber โดยการสื่อสารทั้งสองฝั่งจะต้องกำหนดให้ topic เป็นชื่อเดียวกัน
  • -h 10.33.1.204 เป็น host หรือ Server ที่จะใช้สำหรับรับข้อมูล ในที่นี้คือ 10.33.1.204 โดยหมายเลข ip address หรือ host name ที่กำหนดจะต้องตรงกันทั้ง Publisher และ Subscriber ดังนั้น หากต้องการทราบหมายเลข ip address ของเครื่องที่จะจำลองเป็น server สามารถทำได้โดยพิมพ์คำสั่ง ifconfig

จากนั้นโปรแกรมจะเริ่มทำงานเพื่อรอรับข้อมูลจาก Publisher โดยแสดงหน้าจอการทำงานดังนี้

Client mosqusub|29784-ubuntu-Ma sending CONNECT
Client mosqusub|29784-ubuntu-Ma received CONNACK
Client mosqusub|29784-ubuntu-Ma sending SUBSCRIBE (Mid: 1, Topic: test/chat, QoS: 0)
Client mosqusub|29784-ubuntu-Ma received SUBACK
subscribed (mid: 1): 0
  • โปรแกรมจะรอรับค่าที่จะถูกส่งมาจาก Publisher

2. ฝั่ง Raspberry Pi / Publisher

  • เปิด Terminal และพิมพ์คำสั่ง
$ mosquitto_pub -t "test/chat" -m "sending iot data" -h 10.33.1.204 -d

โดยที่

  • mosquitto_pub เป็นการทำงานในฝั่งของ publisher
  • -t "test/chat" เป็น topic ของ message ที่จะใช้สื่อสารระหว่าง publisher และ subscriber โดยการสื่อสารทั้งสองฝั่งจะต้องกำหนดให้ topic เป็นชื่อเดียวกัน
  • -m "sending iot data" คือข้อความ (Message) "sending iot data" ที่จะส่งไปยัง Subscriber
  • -h 10.33.1.204 เป็น host หรือ Server ที่จะใช้สำหรับรับข้อมูล ในที่นี้คือ 10.33.1.204 โดยหมายเลข ip address หรือ host name ที่กำหนดจะต้องตรงกันทั้ง Publisher และ Subscriber

จากนั้นโปรแกรมจะเริ่มทำงานเพื่อส่งข้อมูลไปยัง Subscriber โดยแสดงหน้าจอการทำงานดังนี้

$ mosquitto_pub -t "test/chat" -m "sending iot data" -h 10.33.1.204 -d
Client mosqpub|3106-mrolarik-o sending CONNECT
Client mosqpub|3106-mrolarik-o received CONNACK
Client mosqpub|3106-mrolarik-o sending PUBLISH (d0, q0, r0, m1, 'test/chat', ... (16 bytes))
Client mosqpub|3106-mrolarik-o sending DISCONNECT

จากตัวอย่าง ระบบจะทำการส่งข้อมูล "sending iot data" ไปยังเครื่อง Server เพียง 1 ครั้ง

3. ฝั่ง Server / Subscriber

จากข้อ 2. เมื่อฝั่ง Client ทำการส่งข้อมูลออกไปยัง Server ดังนั้น Server ก็จะสามารถรรับและแสดงผลข้อมูล ซึ่งแสดงผลดังนี้

Client mosqusub|29784-ubuntu-Ma sending CONNECT
Client mosqusub|29784-ubuntu-Ma received CONNACK
Client mosqusub|29784-ubuntu-Ma sending SUBSCRIBE (Mid: 1, Topic: test/chat, QoS: 0)
Client mosqusub|29784-ubuntu-Ma received SUBACK
subscribed (mid: 1): 0
Client mosqusub|29784-ubuntu-Ma received PUBLISH (d0, q0, r0, m0, 'test/chat', ... (16 bytes))
sending iot data

ดังนั้น ทางฝั่ง Client สามารถส่งข้อมูลมายังฝั่ง Server ได้เรื่อย ๆ การรับข้อมูลแสดงดังตัวอย่างต่อไปนี้

Client mosqusub|29784-ubuntu-Ma sending CONNECT
Client mosqusub|29784-ubuntu-Ma received CONNACK
Client mosqusub|29784-ubuntu-Ma sending SUBSCRIBE (Mid: 1, Topic: test/chat, QoS: 0)
Client mosqusub|29784-ubuntu-Ma received SUBACK
subscribed (mid: 1): 0
Client mosqusub|29784-ubuntu-Ma received PUBLISH (d0, q0, r0, m0, 'test/chat', ... (16 bytes))
sending iot data
Client mosqusub|29784-ubuntu-Ma sending PINGREQ
Client mosqusub|29784-ubuntu-Ma received PINGRESP
Client mosqusub|29784-ubuntu-Ma received PUBLISH (d0, q0, r0, m0, 'test/chat', ... (16 bytes))
sending iot data
Client mosqusub|29784-ubuntu-Ma sending PINGREQ
Client mosqusub|29784-ubuntu-Ma received PINGRESP
Client mosqusub|29784-ubuntu-Ma received PUBLISH (d0, q0, r0, m0, 'test/chat', ... (16 bytes))
sending iot data
  • หากไม่ต้องการให้แสดงข้อความ เช่น
Client mosqusub|29784-ubuntu-Ma sending PINGREQ
Client mosqusub|29784-ubuntu-Ma received PINGRESP
Client mosqusub|29784-ubuntu-Ma received PUBLISH (d0, q0, r0, m0, 'test/chat', ... (16 bytes))

สามารถใช้คำสั่งดังนี้

  • subscriber
$ mosquitto_sub -t "test/chat" -h 10.33.1.204 
  • publisher
$ mosquitto_pub -t "test/chat" -m "sending iot data" -h 10.33.1.204 

Code ภาษา Python

ฝั่ง Subscriber

#----------mqtt_sub.py----------
import paho.mqtt.client as mqtt

def on_connect(client, userdata, flags, rc):
    print("Connected with result code " + str(rc))
    client.subscribe("mqtt-CocoBot")

def on_message(client, userdata, msg):
    print(msg.topic + " ", str(msg.payload))

client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message

client.connect("10.33.1.204", 1883)
client.loop_forever()

ฝั่ง Publisher

#----------mqtt_pub.py----------
import paho.mqtt.client as mqtt
import time
import datetime

mqttc = mqtt.Client()
mqttc.connect("10.33.1.204", 1883)
topic = "mqtt-CocoBot"

while True:
    dt = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    msg = "Hello World! " + dt
    mqttc.publish(topic, msg)
    print("publisher", msg)
    time.sleep(2)

ผลลัพธ์ที่ได้จากการทดลอง

  • ผลลัพธ์ฝั่ง Client/Subscriber
$ python mqtt_sub.py
Connected with result code 0
(u'mqtt-CocoBot ', 'Hello World! 2018-08-01 21:11:25')
(u'mqtt-CocoBot ', 'Hello World! 2018-08-01 21:11:27')
(u'mqtt-CocoBot ', 'Hello World! 2018-08-01 21:11:29')
(u'mqtt-CocoBot ', 'Hello World! 2018-08-01 21:11:31')
  • ผลลัพธ์ฝั่ง Server/Publisher
$ python mqtt_pub.py
('publisher', 'Hello World! 2018-08-01 21:11:25')
('publisher', 'Hello World! 2018-08-01 21:11:27')
('publisher', 'Hello World! 2018-08-01 21:11:29')
('publisher', 'Hello World! 2018-08-01 21:11:31')

รายละเอียดเพิ่มเติม