MQTT

**MQTT** (ראשי תיבות של *Message Queuing Telemetry Transport*) הוא פרוטוקול תקשורת קל משקל אשר משמש להעברת הודעות בין מכשירים ברשת. הפרוטוקול פותח על מנת לענות על הצורך בתקשורת פשוטה ויעילה בין חיישנים ומכשירים, ומאופיין בכך שהוא חסכוני במשאבים וידידותי לשימוש בסביבות שבהן רוחב הפס מוגבל, כמו רשתות סלולריות או רשתות IoT (האינטרנט של הדברים).

הפרוטוקול MQTT נוצר בשנת 1999 על ידי אנדי סטנפורד-קלארק מחברת IBM וארלן ניפר, שעבד אז ביורוטק. הם רצו לפתח דרך יעילה לתקשר עם חיישנים ומכשירים מרוחקים שעוקבים אחרי צינורות נפט. התקשורת התבצעה דרך לוויינים שהיו יקרים מאוד, ולכן הם חיפשו פרוטוקול שיעביר מידע בצורה חסכונית, לא יכביד על חיבור האינטרנט ולא יצרוך הרבה סוללה.

בשנת 2013, IBM הגישה את MQTT v3.1 לגוף המפרט OASIS עם אמנה שהבטיחה שיתקבלו רק שינויים קלים במפרט. לאחר השתלטות על התחזוקה של התקן מ-IBM, OASIS הוציאה את גרסה 3.1.1 ב-29 באוקטובר 2014.  שדרוג משמעותי יותר לגרסה 5 של MQTT, המוסיף מספר תכונות חדשות,  שוחרר ב-7 במרץ 2019.

ב-2013, IBM שחררה את תקן MQTT לציבור, והעבירה את האחריות על התקן לארגון OASIS. מאז, הפרוטוקול עבר עדכונים, והגרסה המתקדמת ביותר שלו, MQTT 5, יצאה ב-2019 עם תוספות חדשות. בנוסף, נוצרה גרסה בשם MQTT-SN, שמתאימה במיוחד למכשירים קטנים שמחוברים ברשתות חסכוניות באנרגיה כמו Zigbee.

## סקירה כללית
אופן הפעולה של פרטוקול MQTT בין מכשירים ברשת עובד במודל שנקרא Pub/Sub (פרסם/הירשם). המודל הזה מאפשר למכשירים לשתף מידע בצורה גמישה ויעילה. במערכת כזו יש שלושה מרכיבים עיקריים:
* מפרסמים (Publishers) – מכשירים ששולחים מידע על נושאים מסוימים. למשל, חיישן שמודד טמפרטורה יכול לפרסם נתונים בנושא "חדר1/טמפרטורה".
* מנויים (Subscribers) – מכשירים שמבקשים לקבל עדכונים על נושאים שחשובים להם. בדוגמה, מערכת מיזוג אוויר יכולה להירשם לנושא "חדר1/טמפרטורה" כדי לקבל את נתוני החיישן ולעדכן את הטמפרטורה בחדר.
* מתווך (Broker) – שרת שמנהל את כל ההודעות ומחבר בין המפרסמים והמנויים. הוא מקבל את ההודעות מהמפרסמים, ומעביר אותן רק למנויים המתאימים.

היתרון במודל הזה הוא שהמפרסמים והמנויים לא צריכים להכיר זה את זה – המתווך דואג להעביר את ההודעות. כך, מפרסם אחד יכול לשלוח הודעה להרבה מנויים, ומנוי אחד יכול לקבל הודעות מהרבה מפרסמים, בקלות וללא צורך בחיבורים ישירים בין כל מכשיר ומכשיר.

**עוד תכונות של פרוטוקול MQTT**

המידע במערכת מאורגן בנושאים, כמו "חדר1/טמפרטורה". כך כל מכשיר יכול לבחור את הנושא שבו הוא מתעניין.

אם המתווך מקבל הודעה בנושא שאין לו כרגע מנויים עליו, הוא פשוט זורק את ההודעה, אלא אם היא מוגדרת כהודעת "שימור" שתישמר למנויים עתידיים.

MQTT בנוי כך שהודעות יכולות להיות קטנות מאוד, כדי לחסוך ברוחב פס ולהתאים למכשירים עם סוללה חלשה.

MQTT מבוסס על פרוטוקול TCP להעברת נתונים, כאשר הנתונים נשלחים בטקסט פשוט (ללא הצפנה). כדי להבטיח את פרטיות התקשורת, ניתן להפעיל הצפנה באמצעות TLS. כברירת מחדל, הפורט 1883 משמש לתקשורת לא מוצפנת, ואילו הפורט 8883 מיועד לתקשורת מוצפנת.

## ברוקר MQTT
מתווך MQTT הוא תוכנה שפועלת על מחשב (בתשתית מקומית או בענן) ויכולה להיות נבנית עצמאית או מנוהלת על ידי ספק חיצוני. קיימות גרסאות קוד פתוח וגרסאות קנייניות למתווך.

המתווך מתפקד כמו משרד דואר. לקוחות MQTT אינם משתמשים בכתובת חיבור ישירה של הנמען, אלא בכותרת נושא הנקראת "Topic". כל מי שנרשם לנושא מקבל עותק מכל ההודעות עבור אותו נושא. מספר לקוחות יכולים להירשם לנושא אחד ממתווך יחיד (יכולת מרובה משתתפים), ולקוח יחיד יכול לרשום נושאים ממספר מתווכים (יכולת רבים לאחד).

כל לקוח יכול גם לשלוח וגם לקבל נתונים באמצעות פרסום והרשמה, כלומר המכשירים יכולים לפרסם נתוני חיישנים ועדיין לקבל מידע קונפיגורציה או פקודות שליטה (MQTT הוא פרוטוקול תקשורת דו-כיווני). כך ניתן לשתף נתונים, לנהל ולשלוט במכשירים. לקוח לא יכול לשדר את אותם נתונים למספר נושאים בבת אחת, ועליו לפרסם מספר הודעות למתווך, כל אחת עם נושא בודד.

באדריכלות MQTT, המכשירים והיישום על השרת מנותקים זה מזה. כך נשמרת הפרדה בין המידע של כל לקוח. ניתן להגדיר את MQTT להשתמש בהצפנה באמצעות TLS ולהגן על החיבור עם תעודת אבטחה, שם משתמש וסיסמה. בנוסף, ניתן להגדיר שהחיבור ידרוש תעודה שהלקוח מספק ושעליה להתאים לגרסת השרת.

במקרה של כשל, המתווך והתוכנות על הלקוחות יכולים לעבור אוטומטית למתווך גיבוי. מתווכי גיבוי יכולים גם לחלוק את העומס בין מספר שרתים באתר, בענן או בשילוב של שניהם.

המתווך תומך גם במפרט הסטנדרטי של MQTT וגם בגרסה התואמת MQTT, כגון Sparkplug. ניתן לעשות זאת על אותו שרת, בו זמנית, וברמות אבטחה זהות.

המתווך עוקב אחר כל המידע על החיבור כשהמכשיר מתחבר ומתנתק, בתכונה הנקראת "מושבים מתמשכים". במצב זה, המתווך שומר מידע על כל לקוח, נושאים שכל לקוח נרשם אליהם, וכל הודעה לנושא עם QoS של 1 או 2.

היתרונות המרכזיים של מתווך MQTT הם:
* מבטל חיבורים פגיעים ולא מאובטחים של לקוחות, אם הוגדר כך
* יכול להתרחב בקלות ממכשיר יחיד לאלפים
* מנהל ועוקב אחר כל מצבי החיבור של הלקוחות, כולל אישורי אבטחה ותעודות, אם הוגדר כך
* מפחית את עומס הרשת מבלי להתפשר על האבטחה, אם הוגדר כך (ברשתות סלולריות או לווייניות)

## דוגמה לשימוש בפרוטוקול
הנה דוגמה לפרויקט ב-ESP32 (בתור "מנוי") שמשתמש בפרוטוקול MQTT כדי לבדוק מה מזג האוויר ולעדכן תצוגה עם טמפרטורה מעודכנת:

התוכנה מורכבת מארבעה שלבים:
# **חיבור ל-WiFi**: הקוד מתחיל בחיבור של ה-ESP32 לרשת ה-WiFi.
# **חיבור לשרת MQTT**: לאחר החיבור ל-WiFi, ה-ESP32 מתחבר לשרת MQTT.
# **מנוי לנושא**: ה-ESP32 נרשם לנושא מסוים (למשל, `weather/temperature`), שממנו יגיעו עדכוני הטמפרטורה.
# **עדכון טמפרטורה**: כשה-ESP32 מקבל הודעה בנושא הזה, הוא מציג את הטמפרטורה על גבי תצוגה מחוברת (למשל, OLED).

```c++
#include <WiFi.h>
#include <PubSubClient.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// הגדרות חיבור WiFi
const char* ssid = "your_SSID";
const char* password = "your_PASSWORD";

// הגדרות MQTT
const char* mqtt_server = "your_mqtt_broker_address";
const int mqtt_port = 1883;
const char* temperature_topic = "weather/temperature";

// משתנים גלובליים
WiFiClient espClient;
PubSubClient client(espClient);
Adafruit_SSD1306 display(128, 64, &Wire, -1);

// פונקציה שמתחברת ל-WiFi
void setup_wifi() {
  delay(10);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
}

// פונקציה שתופעל כאשר מתקבלת הודעה חדשה בנושא temperature_topic
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");

  String temperature = "";
  for (int i = 0; i < length; i++) {
    temperature += (char)payload[i];
  }

  Serial.println("Temperature: " + temperature);

  // הצגת הטמפרטורה על התצוגה
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0,0);
  display.print("Temp: ");
  display.print(temperature);
  display.print(" C");
  display.display();
}

// פונקציה שמתחברת ל-MQTT
void reconnect() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");

    if (client.connect("ESP32Client")) {
      Serial.println("connected");

      // הירשמות לנושא
      client.subscribe(temperature_topic);
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");

      delay(5000);
    }
  }
}

void setup() {
  Serial.begin(115200);
  setup_wifi();
  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(callback);

  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0,0);
  display.println("Connecting to MQTT...");
  display.display();
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
}
```


## ראו גם
* מדריך באתר "אינטרנט ישראל" - למימוש הפרטוקול ב - Raspberry Pi.

## קישורים חיצוניים
* 

## הערות שוליים

קטגוריה:פרוטוקולי תקשורת