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
ที่มา [https://www.segger.com/products/connectivity/embosip/add-ons/mqtt-client/]
- จากรูปภาพ Server จะทำการ publish ข้อมูลผ่าน MQTT Broker เพื่อให้ Client สามารถ Subscribe เพื่อใช้ข้อมูลหรือส่งข้อมูลผ่านไปยัง Server
ติดตั้งโปรแกรม mosquitto - MQTT broker
อ่านรายละเอียดเพิ่มเติมจากเว็บไซต์ https://mosquitto.org/
- การติดตั้งทำได้ ดังนี้
- เพิ่ม 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
update
ระบบ Linux เพื่อให้สามารถติดตั้งโปรแกรม mosquitto ได้
$ sudo apt-get update
- ติดตั้งโปรแกรม 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')