Friday, November 10, 2017

MQTT แบบย่นย่อ


บทความนี้เกี่ยวกับอินเตอร์เนตออฟติง (Internet of Things: IoT) โปรโตคอล MQTT MQTT โบรกเกอร์ อุปกรณ์อายโอที (IoT device) ขนาดเล็ก การเขียนโปรแกรมภาษาซีใน ESP 8266 การเขียนภาษาไพธอนในราสเบอรีพาย

สิ่งที่ท่านจะได้เรียนในบทความนี้
  1. วิธีเขียนโค้ดใช้งานโปรโตคอล MQTT แบบง่าย
  2. วิธีเขียนภาษาซึเพื่อรับเมสเสจจาก MQTT โบรกเกอร์ ไป ESP 8266
  3. วิธีเขียนภาษาไพธอนเพื่อส่งข้อมูลไปยัง MQTT โบรกเกอร์ จาก ราสเบอรีพาย

MQTT โบรกเกอร์


MQTT คือโปรโตคอลที่ถูกออกแบบมาให้มีขนาดเล็ก กินทรัพยากรน้อย เหมาะใช้กับอุปกรณ์อายโอที (IoT device) ขนาดเล็กที่ีมีทรัพยากรจำกัด

โมดูลอีเอสพีแปดสองหกหกได้รับความนิยมหนักมาก ในการนำไปใช้สร้างอุปกรณ์อายโอที (IoT device) เพราะมีขนาดเล็ก (เล็กกว่าเอสดีการ์ด) กินไฟน้อย มีวายฟาย แคอมแพตติเบิ้ลกับอาร์ดูโน จึงมีเครื่องมือพัฒนาอย่างอุดม ละที่สำคัญคือราคาถูกมาก

ลองนึกภาพว่าเราฝังอุปกรณ์อายโอที (IoT device) ซึ่งเป็นกล่องเล็กๆ ไว้ในดิน กลางไร่นา มีเซนเซอร์อ่านค่าความชื้นในดิน เราต้องการส่งค่าที่อุปกรณ์อายโอที (IoT device) อ่านได้จากเซนเซอร์ไปเก็บที่ดาต้าเบส

ดาต้าเบสเซอฟเวอร์อยู่ที่ไหน คำคอบคืออยู่ในเมฆ (คลาวน์เซอร์วิส เช่น แอมะซอนเอดับเบิ้ลยูเอส หรือไมโครซอฟต์แอเชอร์ ) ปัญหาคืออุปกรณ์อายโอที (IoT device) ขนาดเล็ก มีแรงน้อย ไม่มีอาจส่งข้อมูลไปถึงเมฆได้ เราจึงให้อุปกรณ์อายโอที (IoT device) ส่งข้อมูลไปที่ฟิลด์เกตเวย์ จากนั้นฟิลด์เกตเวย์จึงส่งเมฆอีกทอดหนึ่ง


ฟิลด์เกตเวย์แบบที่ใช้ในอุตสาหกรรม

ปรกติการส่งค่าที่อุปกรณ์อายโอที (IoT device) อ่านได้จากเซนเซอร์ไปยังฟิลด์เกตเวย์ เราจะทำแบบไร้สายผ่านซิกโลแพน บลูทูทโลเพาเวอร์ วายฟาย หรืออื่นๆ ต่อไปถ้ามีผู้ให้บริการซิกฟอกซ์หรือลอร่า เราอาจส่งข้อมูลจากอุปกรณ์อายโอที (IoT device) ไปเมฆได้โดยตรง ไม่ต้องผ่านฟิลด์เกตเวย์แล้ว

การคุยกันระหว่างอุปกรณ์อายโอที (IoT device) กับดาต้าเบสเซอฟเวอร์ในเมฆ จะต้องมีตัวกลางที่เรียกว่าโบรกเกอร์ โบรกเกอร์มีหลายแบบหลายโปรโตคอล ในบทความนี้ผมจะพูดถึง MQTT โบรกเกอร์เท่าน้ั้น


MQTT ใช้หลักการ Publish/Subscribe ดีไวซ์ส่งข้อมูลไปยังเบคเอ็นด์ด้วยการพับลิชของโบรกเกอร์ ในทางกลับกัน เบคเอ็นด์วอนหาข้อมูลจากดีไวซ์ได้ด้วยการซับสไคร์บ

งานใหญ่เราจะส่งเชื่อมกับเมฆ แต่ถ้าเป็นงานเล็ก (มีดิไวซ์น้อย) หรือใช้ทดสอบบนดิน เราจัดตั้ง MQTT โบรกเกอร์ไว้ในเดกส์ทอปของเราก็ได้ยังได้ และในบทความนี้ผมจะทำอย่างนั้น

ยุงโหด


MQTT โบรกเกอร์ที่คนนิยมใช้กันมาคือ "ยุงโหด" (Mosquitto มอสคิโต้) ที่ว่าโหดเพราะฟรี มีให้ใช้ทั้งในวินโดวส์ ไลนิกซ์ และแมค หรือถ้าใจถึงจะดาวน์โหลดซอร์สมาคอมไพล์เองก็ยังไหว (ดีที่สุดคือฟอร์กแล้วปรับโค้ดให้มีประสิทธิภาพสูงกว่าเดิม)



ให้ท่านดาว์นโหลดและติดตั้งให้พร้อมใช้งาน เอาเวอร์ชันล่าสุดที่มีบักน้อยไว้ก่อน ผมจะไม่อธิบายวิธีติดตั้งในบทความนี้ ถ้าท่านต้องการให้ผมเขียนวิธีติดตั้งโดยละเอียดให้ขอมาในคอมเมนต์

เมื่อติดตั้งเสร็จให้ไปที่โฟลเดอร์ที่ติดตั้ง mosquitto เปิดคอนโซล แล้วพิมพ์ mosquitto -v กดเอนเตอร์แล้วควรจะเห็นผลลัพธ์แบบนี้ (-v คือให้แสดงข้อความสถานะการทำงาน)


บอกให้เรารู้ว่า mosquitto รันแล้วพร้อมใช้งานและพอร์ทที่ mosquitto ใช้ ดีฟอลท์คือ 1883 ทั้งไอพีวีสี่และวีหก

อันดับต่อไปทดสอบ sub โดยเปิดอีกคอนโซลแล้วพิมพ์ดังนี้
mosquitto_sub -h 127.0.0.1 -i testSub -t debug

อันดับต่อไปทดสอบ pub โดยเปิดอีกคอนโซลแล้วพิมพ์ดังนี้
mosquitto_pub -h 127.0.0.1 -i testPublish -t debug -m 'Hello World'

จะได้ผลลัพธ์แบบนี้


ประเด็นสำคัญคืออะไรที่เราพับลิชจะต้องไปแสดงที่ซับสไคร์บ


สคริปในพาย


เมื่อทดสอบโบรคเกอร์ว่าพร้อมใช้งานแล้วต่อไปก็เขียนโปรแกรมในราสเบอรีพาย ไลบราลี MQTT ที่จะใช้ในบทความนี้คือ phato-mqtt ให้ติดตั้งโดยใช้คำสั่งนี้

pip install paho-mqtt

จากนั้นเขียนสคริปทดสอบเป็นภาษาไพธอนดังนี้

import paho.mqtt.publish as publish
import time
print("Sending 0...")
publish.single("ledStatus", "0", hostname="mypc1")
time.sleep(1)
print("Sending 1...")
publish.single("ledStatus", "1", hostname="mypc1")

มีแค่นี้จริงๆ อะไรจะสั้นขนาดนั้น


โปรแกรมใน ESP8266


สิ่งท่ี่เราจะทำคือให้ ESP8266 รับแมสเสจ ถ้า ledStatus = 1 ให้ปิดดวงแสงไฟที่เอลอีดี (บนบอร์ด) ถ้า ledStatus = 0 ให้ดับไฟ

ก่อนเขียนโปรแกรมให้ติดตั้งไลบราลี PubSubClient


จากนั้นป้อนโค้ดนี้

#include <EEPROM.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <Adafruit_INA219.h>
// Connect to the WiFi
const char* ssid = "test";
const char* password = "password123";
const char* mqtt_server = "myc1";
WiFiClient espClient;
PubSubClient client(espClient);
const byte ledPin = 0; // Pin with LED on Adafruit Huzzah
void callback(char* topic, byte* payload, unsigned int length) {
 Serial.print("Message arrived [");
 Serial.print(topic);
 Serial.print("] ");
 for (int i=0;i<length;i++) {
  char receivedChar = (char)payload[i];
  Serial.print(receivedChar);
  if (receivedChar == '0')
  // ESP8266 Huzzah outputs are "reversed"
  digitalWrite(ledPin, HIGH);
  if (receivedChar == '1')
   digitalWrite(ledPin, LOW);
  }
  Serial.println();
}
void reconnect() {
 // Loop until we're reconnected
 while (!client.connected()) {
 Serial.print("Attempting MQTT connection...");
 // Attempt to connect
 if (client.connect("ESP8266 Client")) {
  Serial.println("connected");
  // ... and subscribe to topic
  client.subscribe("ledStatus");
 } else {
  Serial.print("failed, rc=");
  Serial.print(client.state());
  Serial.println(" try again in 5 seconds");
  // Wait 5 seconds before retrying
  delay(5000);
  }
 }
}
void setup()
{
 Serial.begin(9600);
 client.setServer(mqtt_server, 1883);
 client.setCallback(callback);
 pinMode(ledPin, OUTPUT);
}
void loop()
{
 if (!client.connected()) {
  reconnect();
 }
 client.loop();
}

โค้ดที่เป็นหัวใจคือฟังก์ชัน callback ที่จะทำงานเมื่อได้รับแมสเสจจากโบรคเกอร์ (กำหนดไว้ที่บรรทัด 57) สิ่งที่ม้นทำก็ไม่มีอะไรมาก แค่เอาแมสเสจมาดู ถ้าเป็น 1 ก็สั่งเปิดไฟ 0 ก็ปิดไฟ จากนั้นโปรแกรมจะพยายามเชื่อมต่อกับโบรคเกอร์ใหม่ และทำงานวนซ้ำไปเรื่อย

นี่พยายามเขียนแบบย่นย่อสุด เอาแบบเนื้อๆ จริงๆ ถ้าใครติดอะไรถามมาในคอมเมนต์ข้างล่างได้เลยครับ



No comments:

Post a Comment

เตียมซอฟท์แวร์ก่อนเรียนคอร์ส Essential ML.NET

  ผู้จะเรียนวิชา Essential ML.NET ทุกคนโปรดเตรียมฮาร์ดแวร์และซอฟท์แวร์ต่อไปนี้ ระบบปฏิบัติการ Windows 10 (ถ้าใช้ MacOS หรือ Linux จะไม่สามาร...