Chapterبەش 7 · Lectureوانە 7.1
Sending IoT Data: HTTP, JSON and MQTTناردنی دراوەی IoT: HTTP، JSON و MQTT
How a reading travels from a board to the cloud: writing it as JSON (RFC 8259) and the rules devices break, HTTP requests and responses (POST, status codes) and their cost for small devices, MQTT publish/subscribe with a broker, topics and wildcards, QoS 0, 1 and 2, retained messages, last will and keep alive, a Nano ESP32 sketch that publishes over TLS on port 8883, and how to choose between HTTP and MQTT.
خوێندنەوەیەک چۆن لە بۆردێکەوە دەگاتە هەور: نووسینی وەک (RFC 8259) و ئەو یاسایانەی ئامێرەکان دەیانشکێنن، و (POST، ) و تێچوویان بۆ ئامێری بچووک، بە ، و ، QoS 0، 1 و 2، ، و هێشتنەوەی پەیوەندی، Nano ESP32 کە لەسەر لە پۆرتی 8883 بڵاو دەکاتەوە و چۆن لە نێوان و هەڵبژێریت.
What you will learnچی فێر دەبیت
- Write a sensor reading as valid JSON and avoid the common errors (NaN, quotes, trailing commas).
- Read an HTTP request and response and explain what HTTP costs a small device.
- Explain MQTT publish/subscribe with a broker, and design topics and wildcard filters.
- Choose QoS 0, 1 or 2, and use retained messages, last will and TLS on port 8883.
- Choose between HTTP and MQTT for a given IoT job.
- خوێندنەوەی وەک دروست بنووسیت و خۆت لە هەڵە باوەکان بپارێزیت (NaN، کەوانە، فاریزەی کۆتایی).
- و بخوێنیتەوە و ڕوون بکەیتەوە چی لە ئامێرێکی بچووک دەخوات.
- بە ڕوون بکەیتەوە و و فلتەری دیزاین بکەیت.
- QoS 0، 1 یان 2 هەڵبژێریت و ، و لەسەر پۆرتی 8883 بەکار بهێنیت.
- لە نێوان و بۆ کارێکی دیاریکراوی IoT هەڵبژێریت.
From the board to the cloudلە بۆردەکەوە بۆ هەور
A sensor reading is useful only when it reaches somewhere: a database, a dashboard, a phone. In the IoT data path this is the step “gateway or device → cloud”. Two questions must be answered every time: what do we send — how is the reading written down — and how is it carried?
خوێندنەوەی تەنیا ئەو کاتە بەسوودە کە بگاتە شوێنێک: ، ، مۆبایلێک. لە ڕێڕەوی دراوەی IoTـدا ئەمە هەنگاوی «دەروازە یان ئامێر ← هەور»ـە. هەموو جارێک دەبێت وەڵامی دوو پرسیار بدرێتەوە: چی دەنێرین — خوێندنەوەکە چۆن دەنووسرێت — و چۆن دەگوازرێتەوە؟
This lesson answers both. The reading is written as JSON, a small text format. It is carried by HTTP, the protocol of the web, or by MQTT, a light protocol made for IoT. Both ride on TCP/IP, which delivers bytes complete and in order (TCP). The LoRaWAN and Wi-Fi radios get the data off the device; these protocols take it the rest of the way.
ئەم وانەیە وەڵامی هەردووکیان دەداتەوە. خوێندنەوەکە بە دەنووسرێت، کە شێوازێکی دەقیی بچووکە. بە ، وێب، یان بە ، سووک کە بۆ IoT دروست کراوە، دەگوازرێتەوە. هەردووکیان لەسەر دەڕۆن، کە بە تەواوی و بە ڕیز دەگەیەنێت (TCP). ڕادیۆکانی LoRaWAN و لە ئامێرەکە دەردەهێنن؛ ئەم دوو باقیی ڕێگاکەی پێ دەبڕن.
A reading as JSONخوێندنەوەیەک وەک JSON
JSON (JavaScript Object Notation) writes data as plain text that people can read and every language can parse. An object is wrapped in { } and holds name–value pairs such as "temperature": 24.5. Values can be strings in double quotes, numbers, true or false, null (no value), arrays in [ ] and other objects. Today’s standard is RFC 8259 (standards); how web APIs use JSON is in JSON: the language of APIs.
(JavaScript Object Notation) وەک دەقێکی سادە دەنووسێت کە مرۆڤ دەیخوێنێتەوە و هەموو زمانێک شیی دەکاتەوە. لە ناو { }ـدایە و هەڵدەگرێت وەک "temperature": 24.5. نرخەکان دەتوانن لە ناو جووتە کەوانەدا، ژمارە، true یان false، null (بێ نرخ)، لە ناو [ ]ـدا و تر بن. ستانداردی ئەمڕۆ RFC 8259ـە (ستانداردەکان)؛ APIـەکانی وێب چۆن بەکار دەهێنن لە JSON: زمانی APIـەکاندایە.
{
"device": "cage-01",
"temperature": 24.5,
"humidity": 40,
"cover_open": false,
"battery": null,
"tags": ["indoor", "bird-room"]
}Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 3-4
Numbers have no quotes and no unit: the unit belongs in the documentation or in the name, such as temperature_c.
ژمارەکان نە کەوانەیان هەیە نە یەکە: یەکە لە بەڵگەنامەکەدا یان لە ناوەکەدا دەبێت، وەک temperature_c.
- Lineدێڕی 6
nullsays “no value”, for example a board without a battery sensor.nullدەڵێت «نرخ نییە»، بۆ نموونە بۆردێک کە نییە.
A reading as JSONخوێندنەوەیەک وەک JSON
JSON rules that devices breakیاساکانی JSON کە ئامێرەکان دەیانشکێنن
A server rejects the whole message if one character is wrong, so a device must follow the rules exactly. These three mistakes are common in sketches; each was fed to Python’s JSON checker (python3 -m json.tool), which printed the error shown.
هەموو پەیامەکە ڕەت دەکاتەوە ئەگەر تەنیا یەک پیت هەڵە بێت، بۆیە ئامێرێک دەبێت ڕێک پەیڕەوی یاساکان بکات. ئەم سێ هەڵەیە لە باون؛ هەریەکەیان درایە پشکنەری Python (python3 -m json.tool)، کە ئەو هەڵەیەی چاپ کرد کە لێرە پیشان دراوە.
| Wrongهەڵە | Checker saysپشکنەرەکە دەڵێت | Rightڕاست |
|---|---|---|
{'device': 'cage-01'} | Expecting property name enclosed in double quotes | {"device": "cage-01"} |
{"temperature": nan} | Expecting value | {"temperature": null} |
{"temperature": 24.5,} | Illegal trailing comma before end of object | {"temperature": 24.5} |
- Text sent between systems must be UTF-8.
- No comments are allowed inside JSON.
- A failed sensor gives NaN (“not a number”), which Arduino prints as
nan: sendnullinstead.
- دەقێک کە لە نێوان سیستەمەکاندا دەنێردرێت دەبێت UTF-8 بێت.
- هیچ تێبینییەک لە ناو ڕێگەپێدراو نییە.
- تێکچوو NaN دەدات («ژمارە نییە»)، کە Arduino وەک
nanچاپی دەکات: لەبری ئەوەnullبنێرە.
A reading as JSONخوێندنەوەیەک وەک JSON
Building JSON on the boardدروستکردنی JSON لەسەر بۆردەکە
For one small reading you do not need a library: join strings, and turn a failed reading into null. This sketch builds the JSON every 2 seconds and prints it. For bigger documents the ArduinoJson library builds and checks JSON for you.
بۆ خوێندنەوەیەکی بچووک پێویستت بە نییە: پێکەوە بلکێنە و خوێندنەوەیەکی تێکچوو بکە بە null. ئەم هەر 2 چرکە جارێک دروست دەکات و چاپی دەکات. بۆ بەڵگەنامەی گەورەتر ArduinoJson بۆت دروست دەکات و دەیپشکنێت.
// Build one reading as JSON text and print it (UNO or any board, DHT11 on pin 2)
#include <DHT.h>
DHT dht(2, DHT11);
String jsonNumber(float v) {
if (isnan(v)) return "null"; // NaN is not allowed in JSON
return String(v, 1); // one decimal: 24.5
}
void setup() {
Serial.begin(9600);
dht.begin();
}
void loop() {
float t = dht.readTemperature();
float h = dht.readHumidity();
String json = "{\"device\":\"cage-01\",\"temperature\":" + jsonNumber(t) +
",\"humidity\":" + jsonNumber(h) + "}";
Serial.println(json);
delay(2000); // the DHT11 needs about 1 s between readings
}{"device":"cage-01","temperature":null,"humidity":null}
{"device":"cage-01","temperature":24.5,"humidity":40.0}
{"device":"cage-01","temperature":24.5,"humidity":40.0}CêIT Arduino checker; scenario: the DHT11 gives no reading until 1 s, then 24.5 °C and 40 %. Every line was checked with python3 -m json.tool.
پشکنەری Arduinoـی CêIT؛ سیناریۆ: DHT11 تا 1 چرکە هیچ نادات، پاشان 24.5 °C و 40 %. هەموو دێڕێک بە python3 -m json.tool پشکنرا.
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 6-9
jsonNumber()returnsnullfor a failed reading and one decimal otherwise.jsonNumber()بۆ خوێندنەوەی تێکچووnullو بۆ خوێندنەوەی ڕاست یەک ژمارەی دوای فاریزە دەگەڕێنێتەوە.- Lineدێڕی 19-20
Inside a C++ string,
\"writes one double quote.لە ناو C++ـدا،
\"یەک کەوانەی دووانە دەنووسێت.
HTTP: ask and answerHTTP: پرسیار و وەڵام
HTTP is the protocol of the web, defined today in RFC 9110. The device is the client: it sends a request, and a server sends back one response. A request has a request line (the method and the path), headers such as Content-Type: application/json, an empty line and an optional body. The method says what to do: GET reads, POST sends new data, for example a reading to store. The response begins with a status code. Web Programming teaches the request cycle in detail: the request and the response and status codes.
وێبە و ئەمڕۆ لە RFC 9110ـدا پێناسە کراوە. ئامێرەکە : دەنێرێت و یەک دەگەڕێنێتەوە. هێڵی ( و )، وەک Content-Type: application/json، هێڵێکی بەتاڵ و هەڵبژاردەی هەیە. دەڵێت چی بکرێت: GET دەخوێنێتەوە، POST نوێ دەنێرێت، بۆ نموونە خوێندنەوەیەک بۆ هەڵگرتن. بە دەست پێ دەکات. بەرنامەسازیی وێب خولی بە وردی فێر دەکات: داواکاری و وەڵام و کۆدەکانی دۆخ.
POST /api/readings HTTP/1.1
Host: iot.example.com
Content-Type: application/json
Content-Length: 39
{"device":"cage-01","temperature":24.5}
HTTP/1.1 201 Created
Content-Length: 0Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 4
Content-Length counts the body’s bytes: the reading is 39 bytes.
Content-Length جەستەکە دەژمێرێت: خوێندنەوەکە 39 .
- Lineدێڕی 8
201 Created: the server stored a new record.
201 Created: نوێی هەڵگرت.
HTTP: ask and answerHTTP: پرسیار و وەڵام
HTTP for devices: easy, but heavyHTTP بۆ ئامێرەکان: ئاسان، بەڵام قورس
HTTP is easy to use from a board: every cloud service has an HTTP API, it passes through firewalls on port 443 (HTTPS), and REST APIs map tables to URLs, as the next lesson shows with a cloud database. But it has three costs for a small device:
لەسەر بۆرد بەکارهێنانی ئاسانە: هەموو خزمەتگوزارییەکی هەور APIـی هەیە، لە پۆرتی 443ـەوە () بە ناو تێدەپەڕێت و REST APIـەکان دەبەستنەوە بە ، وەک وانەی داهاتوو بە پیشانی دەدات. بەڵام بۆ ئامێرێکی بچووک سێ تێچووی هەیە:
- Repeated headers: every request carries its headers again — here 106 bytes of headers for a 39-byte reading.
- New connections: a new TCP and TLS handshake costs time and battery (the handshake).
- The device must ask: a server cannot start a conversation, so a device waiting for commands has to keep asking (polling).
- دووپاتە: هەموو دووپاتە هەڵدەگرێتەوە — لێرە 106 بۆ خوێندنەوەیەکی 39 .
- پەیوەندیی نوێ: نوێی و کات و دەخوات (دەستلێدان).
- ئامێرەکە دەبێت بپرسێت: ناتوانێت گفتوگۆ دەست پێ بکات، بۆیە ئامێرێک کە چاوەڕێی فەرمانە دەبێت هەر بپرسێت (polling).
MQTT: publish and subscribeMQTT: بڵاوکردنەوە و بەشداربوون
MQTT was created in 1999 by Andy Stanford-Clark of IBM and Arlen Nipper to watch oil pipelines over expensive satellite links, so it was built to use very few bytes and little device power. Today it is an OASIS standard: version 3.1.1 (also ISO/IEC 20922) and version 5.0 (March 2019) (who publishes MQTT). It runs over TCP/IP and keeps one connection open.
لە 1999ـدا لەلایەن Andy Stanford-Clark لە IBM و Arlen Nipperـەوە دروست کرا بۆ چاودێریی بۆرییەکانی نەوت لە ڕێگەی بەستەری مانگی دەستکردی گرانەوە، بۆیە بۆ بەکارهێنانی زۆر کەم و وزەیەکی کەمی ئامێر دروست کرا. ئەمڕۆ ستانداردێکی OASISـە: وەشانی 3.1.1 (هەروەها ISO/IEC 20922) و وەشانی 5.0 (ئازاری 2019) (کێ MQTT بڵاو دەکاتەوە). لەسەر کار دەکات و یەک پەیوەندی کراوە دەهێڵێتەوە.
MQTT uses the publish–subscribe pattern through a broker, a server in the middle. A device publishes a message under a topic, such as home/cage/temperature. Apps subscribe to the topics they want. The broker passes each message to every matching subscriber. Publishers and subscribers never talk directly and do not even know each other.
شێوازی لە ڕێگەی بەکار دەهێنێت، کە لە ناوەڕاستدا. ئامێرێک پەیامێک لە ژێر بڵاو دەکاتەوە، وەک home/cage/temperature. هەر ئەپێک بەشداری ئەو دەبێت کە دەیەوێت. هەر پەیامێک دەداتە هەموو بەشداربوویەکی گونجاو. بڵاوکەرەوە و بەشداربووەکان هەرگیز ڕاستەوخۆ قسە ناکەن و تەنانەت یەکتر ناناسن.
MQTT works like a Telegram channel. The channel’s name is the topic. Whoever posts sends the message once to Telegram (the broker), and every member who joined the channel receives it. The poster does not know how many members there are, and a new member can join at any time without the poster doing anything.
وەک کەناڵێکی تێلێگرام کار دەکات. ناوی کەناڵەکە . ئەوەی پۆست دەکات یەکجار پەیامەکە دەنێرێت بۆ تێلێگرام () و هەموو ئەندامێک کە چووەتە ناو کەناڵەکەوە وەریدەگرێت. پۆستکەرەکە نازانێت چەند ئەندام هەن و ئەندامێکی نوێ هەر کاتێک بیەوێت دەتوانێت بچێتە ناوەوە بێ ئەوەی پۆستکەرەکە هیچ بکات.
Where the analogy stops workingسنووری ئەم نموونەیە
Telegram keeps the whole history; an MQTT broker passes messages on and keeps at most the last retained one of each topic.
تێلێگرام هەموو مێژووەکە هەڵدەگرێت؛ پەیامەکان دەنێرێت و زۆرترین دوایین هەر دەهێڵێتەوە.
MQTT: publish and subscribeMQTT: بڵاوکردنەوە و بەشداربوون
One message, many receiversیەک پەیام، زۆر وەرگر
Watch one reading fan out. The broker compares the topic with every subscription and sends a copy to each match. Adding a fourth app tomorrow changes nothing on the sensor: this loose coupling is why MQTT suits systems that grow.
سەیری یەک خوێندنەوە بکە کە بڵاو دەبێتەوە. لەگەڵ هەموو بەشدارییەک بەراورد دەکات و کۆپییەک بۆ هەر یەکگرتنەوەیەک دەنێرێت. زیادکردنی ئەپێکی چوارەم بەیانی هیچ شتێک لە ناگۆڕێت: ئەم پەیوەندییە شلە هۆکاری ئەوەیە کە بۆ سیستەمی گەشەکەر گونجاوە.


Topics and wildcardsبابەتەکانی پەیام و هێماکانی جێگرەوە
A topic is a name made of levels separated by /, like a folder path: home/cage/temperature. Subscribers may use two wildcards in a topic filter: + matches exactly one level, and # matches all the levels below and may only stand at the end. The MQTT standard adds a few rules:
ناوێکە لە چەند ئاستێک کە بە / جیا دەکرێنەوە، وەک ڕێڕەوی بوخچە: home/cage/temperature. بەشداربووان دەتوانن دوو لە فلتەری بەکار بهێنن: + ڕێک یەک ئاست دەگرێتەوە و # هەموو ئاستەکانی خوارەوە دەگرێتەوە و تەنیا دەتوانێت لە کۆتاییدا بێت. ستانداردی چەند یاسایەکی تر زیاد دەکات:
- Topics are case-sensitive:
home/Cageandhome/cageare different topics. - A leading
/makes a different topic:/home/cageis nothome/cage. Do not start with/. - A device publishes on one exact topic; wildcards are only for subscribing.
- Topics starting with
$, such as$SYS/…for the broker’s own statistics, are not matched by#or+at the start.
- جیاوازی لە نێوان پیتی گەورە و بچووکدا دەکەن:
home/Cageوhome/cageدوو جیاوازن. /ـێکی سەرەتا جیاواز دروست دەکات:/home/cageهەمانhome/cageنییە. بە/دەست پێ مەکە.- ئامێرێک لەسەر یەک ڕێک بڵاو دەکاتەوە؛ تەنیا بۆ بەشداربوونن.
- کە بە
$دەست پێ دەکات، وەک$SYS/…بۆ ئامارەکانی خودی ، بە#یان+ـی سەرەتا ناگیرێتەوە.
QoS 0, 1 and 2: how sure is delivery?QoS 0، 1 و 2: گەیاندن چەند دڵنیایە؟
Not every message needs the same guarantee (delivery guarantees). In MQTT each message chooses a Quality of Service level:
هەموو پەیامێک هەمان دڵنیایی پێویست نییە (دڵنیایی گەیاندن). لە هەر پەیامێک هەڵدەبژێرێت:
- QoS 0 — at most once: sent once with no reply. Fast and light, but a message can be lost. Good for a reading that repeats every minute.
- QoS 1 — at least once: the receiver answers with PUBACK; the sender repeats until it gets one. Nothing is lost, but a message may arrive twice. Good for alarms, if a repeat does no harm.
- QoS 2 — exactly once: a four-step exchange (PUBLISH, PUBREC, PUBREL, PUBCOMP) makes sure the message arrives once and only once. The slowest; for commands that must not run twice, such as “add 100 litres”.
- QoS 0 — زۆرترین یەکجار: یەکجار دەنێردرێت بێ وەڵام. خێرا و سووکە، بەڵام پەیامێک دەتوانێت ون بێت. بۆ خوێندنەوەیەک کە هەموو خولەکێک دووپاتە دەبێتەوە باشە.
- QoS 1 — لانیکەم یەکجار: وەرگرەکە بە PUBACK وەڵام دەداتەوە؛ نێرەرەکە دووپاتەی دەکاتەوە تا وەریدەگرێت. هیچ شتێک ون نابێت، بەڵام پەیامێک لەوانەیە دوو جار بگات. بۆ ئاگاداری باشە، ئەگەر دووپاتەبوونەوە زیانی نەبێت.
- QoS 2 — ڕێک یەکجار: ئاڵوگۆڕێکی چوار هەنگاوی (PUBLISH، PUBREC، PUBREL، PUBCOMP) دڵنیا دەبێتەوە کە پەیامەکە یەکجار و تەنیا یەکجار دەگات. خاوترینە؛ بۆ فەرمانێک کە نابێت دوو جار جێبەجێ بکرێت، وەک «100 لیتر زیاد بکە».
QoS works between two parties at a time: publisher → broker, then broker → subscriber. A subscriber receives at most the QoS it asked for: a QoS 2 message sent to a QoS 0 subscription arrives at QoS 0.
لە هەر جارێکدا لە نێوان دوو لادا کار دەکات: بڵاوکەرەوە ← ، پاشان ← بەشداربوو. بەشداربوویەک زۆرترین ئەو QoSـە وەردەگرێت کە داوای کردووە: پەیامێکی QoS 2 کە بۆ بەشدارییەکی QoS 0 دەنێردرێت بە QoS 0 دەگات.
Retained messages, last will and keep aliveپەیامی هەڵگیراو، پەیامی وەسیەت و هێشتنەوەی پەیوەندی
- Retained message: published with the retain flag, it is kept by the broker as the last message of its topic and sent at once to every new subscriber. Publishing an empty retained message on the topic deletes it.
- Last will: a message the device leaves with the broker when it connects. If the device disappears without a proper goodbye (power cut, crash, lost Wi-Fi), the broker publishes it, for example
offline. - Keep alive: when there is nothing to send, the client sends a small PINGREQ and the broker answers PINGRESP. If the broker hears nothing for one and a half times the keep-alive time, it closes the connection and sends the will.
- : بە نیشانەی retain بڵاو دەکرێتەوە، وەک دوایین پەیامی هەڵیدەگرێت و یەکسەر دەینێرێت بۆ هەر بەشداربوویەکی نوێ. بڵاوکردنەوەی بەتاڵ لەسەر هەمان دەیسڕێتەوە.
- : پەیامێک کە ئامێرەکە لە کاتی پەیوەستبووندا لای دایدەنێت. ئەگەر ئامێرەکە بێ ماڵئاوایی ون بێت (بڕانی کارەبا، تێکچوون، لەدەستچوو)، بڵاوی دەکاتەوە، بۆ نموونە
offline. - هێشتنەوەی پەیوەندی (keep alive): کاتێک هیچ نییە بۆ ناردن، PINGREQـێکی بچووک دەنێرێت و بە PINGRESP وەڵام دەداتەوە. ئەگەر بۆ یەک و نیو هێندەی ئەو ماوەیە هیچ نەبیستێت، پەیوەندییەکە دادەخات و دەنێرێت.
Together they give a reliable “is the device online?” light: retain online when connecting, and set the will to a retained offline.
پێکەوە نیشانەیەکی پشتپێبەستراوی «ئایا ئامێرەکە سەرهێڵە؟» دەدەن: لە کاتی پەیوەستبووندا online بە retain بڵاو بکەرەوە و بکە بە offlineـێکی هەڵگیراو.
Publishing from the boardبڵاوکردنەوە لە بۆردەکەوە
This sketch for a Wi-Fi board, the Nano ESP32 (boards for IoT), uses the official ArduinoMqttClient library. It connects over TLS on port 8883, sets a retained last will, announces online, and publishes a JSON reading every minute at QoS 1 without blocking the loop (millis()).
ئەم بۆ بۆردێکی ، Nano ESP32 (بۆردەکان بۆ IoT)، فەرمیی ArduinoMqttClient بەکار دەهێنێت. لەسەر پۆرتی 8883 بە پەیوەست دەبێت، هەڵگیراو دادەنێت، online ڕادەگەیەنێت و هەر خولەکێک خوێندنەوەیەکی بە QoS 1 بڵاو دەکاتەوە بێ ئەوەی ڕابگرێت (millis()).
#define SECRET_SSID "your-wifi-name"
#define SECRET_PASS "your-wifi-password"
#define SECRET_MQTT_USER "cage-01"
#define SECRET_MQTT_PASS "your-broker-password"
#define SECRET_ROOT_CA "-----BEGIN CERTIFICATE-----\n...the broker's root certificate...\n-----END CERTIFICATE-----\n"Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 1-5
Placeholders only. Your real Wi-Fi password, broker password and certificate go here, and this file is never shared.
تەنیا جێگرەوەن. ڕاستەقینەی ، و بڕوانامەکەت لێرە دادەنرێن و ئەم فایلە هەرگیز بڵاو ناکرێتەوە.
// Publish a JSON reading to an MQTT broker over TLS every minute (Nano ESP32, DHT11 on pin 2)
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <ArduinoMqttClient.h>
#include <DHT.h>
#include "arduino_secrets.h" // Wi-Fi, broker login and the root certificate
WiFiClientSecure tls; // the encrypted connection (TLS)
MqttClient mqtt(tls); // MQTT runs inside it
DHT dht(2, DHT11);
const char BROKER[] = "broker.example.com"; // your broker's address
const int PORT = 8883; // MQTT over TLS
const char TOPIC[] = "home/cage/temperature";
const char STATUS[] = "home/cage/status";
unsigned long lastSend = 0;
void setup() {
Serial.begin(115200);
dht.begin();
WiFi.begin(SECRET_SSID, SECRET_PASS);
while (WiFi.status() != WL_CONNECTED) delay(250);
Serial.println("Wi-Fi connected");
tls.setCACert(SECRET_ROOT_CA); // check that it is the real broker
mqtt.setId("cage-01");
mqtt.setUsernamePassword(SECRET_MQTT_USER, SECRET_MQTT_PASS);
mqtt.beginWill(STATUS, true, 1); // last will: retained, QoS 1
mqtt.print("offline");
mqtt.endWill();
if (!mqtt.connect(BROKER, PORT)) {
Serial.print("MQTT connection failed, error ");
Serial.println(mqtt.connectError());
while (true) {}
}
Serial.println("Connected to the broker");
mqtt.beginMessage(STATUS, true, 1); // retained: new subscribers see it at once
mqtt.print("online");
mqtt.endMessage();
}
void loop() {
mqtt.poll(); // keep the connection alive
if (lastSend == 0 || millis() - lastSend >= 60000) {
lastSend = millis();
float t = dht.readTemperature();
if (isnan(t)) return; // no reading this time
String json = "{\"device\":\"cage-01\",\"temperature\":" + String(t, 1) + "}";
mqtt.beginMessage(TOPIC, false, 1); // not retained, QoS 1
mqtt.print(json);
mqtt.endMessage();
Serial.println("Published " + json);
}
}Wi-Fi connected
Connected to the broker
Published {"device":"cage-01","temperature":24.5}
Published {"device":"cage-01","temperature":24.5}
Published {"device":"cage-01","temperature":24.7}CêIT Arduino checker with a small stand-in for the MQTT library (it logs CONNECT and PUBLISH; no real broker); scenario: 24.5 °C, then 24.7 °C after 100 s; 125 s simulated. The log also shows the will and the retained online on home/cage/status.
پشکنەری Arduinoـی CêIT لەگەڵ جێگرەوەیەکی بچووکی (CONNECT و PUBLISH تۆمار دەکات؛ هیچ ڕاستەقینە نییە)؛ سیناریۆ: 24.5 °C، پاشان 24.7 °C دوای 100 چرکە؛ 125 چرکە لاسایی کراوەتەوە. تۆمارەکە و onlineـی هەڵگیراویش لەسەر home/cage/status پیشان دەدات.
Explain the codeڕوونکردنەوەی کۆدەکە
- Lineدێڕی 8-9
MQTT runs inside an encrypted TLS connection.
لە ناو پەیوەندییەکی شفرەکراوی کار دەکات.
- Lineدێڕی 25
The device checks the broker’s certificate with this root certificate.
ئامێرەکە بەم بڕوانامە ڕەگە دەپشکنێت.
- Lineدێڕی 28-30
The last will: a retained
offlineat QoS 1, sent by the broker if the board disappears.:
offlineـێکی هەڵگیراو بە QoS 1، کە دەینێرێت ئەگەر بۆردەکە ون بێت.- Lineدێڕی 37-39
A retained
online: anyone who subscribes later sees it at once.onlineـێکی هەڵگیراو: هەر کەسێک دواتر بەشدار ببێت یەکسەر دەیبینێت.- Lineدێڕی 43
poll()keeps the connection alive and handles incoming packets: call it often.poll()پەیوەندییەکە زیندوو دەهێڵێتەوە و هاتوو بەڕێوە دەبات: زۆر جار بانگی بکە.- Lineدێڕی 49
Not retained, QoS 1: every reading should arrive at least once.
بێ retain، QoS 1: هەموو خوێندنەوەیەک دەبێت لانیکەم یەکجار بگات.
MQTT over TLS: port 8883MQTT لەسەر TLS: پۆرتی 8883
MQTT itself encrypts nothing. On port 1883 (plain MQTT) the readings, and even the username and password, cross the network as readable text. On port 8883 MQTT runs inside TLS, the same encryption that protects HTTPS: nobody on the path can read or change the messages, and the device checks the broker’s certificate, so it cannot be fooled by a fake broker (certificates and TLS). Both port numbers are registered with IANA (well-known ports).
خۆی هیچ شتێک شفرە ناکات. لەسەر پۆرتی 1883 ( ئاسایی) خوێندنەوەکان و تەنانەت و وەک دەقی خوێنراوە بە دەڕۆن. لەسەر پۆرتی 8883 لە ناو کار دەکات، هەمان کە دەپارێزێت: کەس لە ڕێگادا ناتوانێت پەیامەکان بخوێنێتەوە یان بیانگۆڕێت و ئامێرەکە دەپشکنێت، بۆیە بە ساختە فریو ناخوات (بڕوانامە و TLS). هەردوو ژمارەی پۆرتەکە لە IANAـدا تۆمار کراون (پۆرتە ناسراوەکان).
A broker should also ask every client to log in (a username and password, or a client certificate) and limit which topics each one may publish or subscribe to, so a stolen sensor cannot read the whole house.
هەروەها دەبێت داوا لە هەموو بکات بچێتە ژوورەوە ( و ، یان بڕوانامەی ) و سنوور دابنێت کە هەر لەسەر کام دەتوانێت بڵاو بکاتەوە یان بەشدار بێت، بۆ ئەوەی دزراو نەتوانێت هەموو ماڵەکە بخوێنێتەوە.
HTTP or MQTT?HTTP یان MQTT؟
| Featureتایبەتمەندی | HTTP(S) () | MQTT |
|---|---|---|
| Patternشێواز | request–response: the device asks–: ئامێرەکە دەپرسێت | publish–subscribe through a broker لە ڕێگەی |
| Connectionپەیوەندی | often a new one per requestزۆر جار نوێ بۆ هەر | one, kept openیەک، کراوە دەمێنێتەوە |
| Bytes per small reading بۆ خوێندنەوەیەکی بچووک | hundreds (headers each time)سەدان ( هەموو جارێک) | tensدەیان |
| Commands to the deviceفەرمان بۆ ئامێرەکە | only when the device asksتەنیا کاتێک ئامێرەکە دەپرسێت | at once, pushed by the brokerیەکسەر، دەینێرێت |
| Delivery levelsئاستی گەیاندن | a status code per request بۆ هەر | QoS 0, 1, 2; retained; last willQoS 0، 1، 2؛ ؛ |
| Ports (TLS)پۆرت () | port 443پۆرتی 443 | port 8883پۆرتی 8883 |
| Best forباشترین بۆ | readings now and then to a web APIخوێندنەوەی جارجار بۆ APIـی وێب | many devices, live data, commandsزۆر ئامێر، زیندوو، فەرمان |
Both are fine choices, and many systems use both: devices publish over MQTT, and a server stores the readings through an HTTP API. Two more you will meet: CoAP, a tiny web protocol over UDP for very small devices (IETF protocols for IoT), and LoRaWAN networks, which hand decoded readings to apps by MQTT or webhooks (the formatter).
هەردووکیان هەڵبژاردەی باشن و زۆر سیستەم هەردووکیان بەکار دەهێنن: ئامێرەکان بە بڵاو دەکەنەوە و خوێندنەوەکان لە ڕێگەی APIـیەکی هەڵدەگرێت. دوو تر کە دەیانبینیت: ، وێبی زۆر بچووک لەسەر بۆ ئامێرە زۆر بچووکەکان (پرۆتۆکۆڵەکانی IETF بۆ IoT)؛ هەروەها ، کە خوێندنەوە شیکراوەکان بە یان webhook دەدەنە ئەپەکان (شیکەرەوەکە).
Common mistakesهەڵە باوەکان
Exercisesڕاهێنانەکان
Write one JSON object for this reading of a greenhouse sensor called gh-02: temperature 31.2 °C, soil moisture 18 %, the fan is on, and the light sensor is missing.
یەک بۆ ئەم خوێندنەوەیەی گوڵخانە بە ناوی gh-02 بنووسە: پلەی گەرمی 31.2 °C، شێی خاک 18 %، پانکەکە هەڵکراوە و ڕووناکی نییە.
Show answerوەڵامەکە پیشان بدە
{
"device": "gh-02",
"temperature": 31.2,
"soil_moisture": 18,
"fan_on": true,
"light": null
}What is wrong with this message from a board? {'device': "cage-01", "temperature": nan, "humidity": 40,}
ئەم پەیامەی بۆردێک چ هەڵەیەکی هەیە؟ {'device': "cage-01", "temperature": nan, "humidity": 40,}
Show answerوەڵامەکە پیشان بدە
(1) 'device' uses single quotes: names need double quotes. (2) nan is not a JSON value: send null. (3) The comma before } is not allowed. Correct: {"device": "cage-01", "temperature": null, "humidity": 40}.
(1) 'device' کەوانەی تاکی هەیە: ناوەکان جووتە کەوانەیان دەوێت. (2) nan نرخێکی نییە: null بنێرە. (3) فاریزە پێش } ڕێگەپێدراو نییە. ڕاستەکەی: {"device": "cage-01", "temperature": null, "humidity": 40}.
A school has three classrooms (room1, room2, room3), each with a temperature and a CO₂ sensor. (a) Design the topics. (b) Which filter gives a dashboard every CO₂ reading? (c) Which gives everything from room2?
قوتابخانەیەک سێ پۆلی هەیە (room1، room2، room3) و هەریەکە پلەی گەرمی و CO₂ـی هەیە. (a) دیزاین بکە. (b) کام فلتەر هەموو خوێندنەوەیەکی CO₂ دەداتە ؟ (c) کامیان هەموو شتێکی room2 دەدات؟
Show answerوەڵامەکە پیشان بدە
(a) school/room1/temperature, school/room1/co2, and the same for room2 and room3. (b) school/+/co2. (c) school/room2/#.
(a) school/room1/temperature، school/room1/co2 و هەمان شت بۆ room2 و room3. (b) school/+/co2. (c) school/room2/#.
Choose QoS 0, 1 or 2 and say why: (a) a temperature every 30 seconds; (b) “the door was forced open”; (c) “dispense one dose of medicine”.
QoS 0، 1 یان 2 هەڵبژێرە و بڵێ بۆچی: (a) پلەی گەرمی هەر 30 چرکە جارێک؛ (b) «دەرگاکە بە زۆر کرایەوە»؛ (c) «یەک ژەم دەرمان بدە».
Show answerوەڵامەکە پیشان بدە
(a) QoS 0: a lost reading is replaced 30 seconds later. (b) QoS 1: it must arrive; a duplicate alarm is harmless. (c) QoS 2: it must arrive, and running twice would give a double dose.
(a) QoS 0: خوێندنەوەیەکی ونبوو 30 چرکە دواتر جێگەی دەگیرێتەوە. (b) QoS 1: دەبێت بگات؛ ئاگادارییەکی دووپاتە زیانی نییە. (c) QoS 2: دەبێت بگات و دوو جار جێبەجێبوون دوو ژەم دەدات.
Choose and explain: (a) a weather station that uploads one reading every 10 minutes to a cloud database with a REST API; (b) smart lights that must switch on within half a second when a phone button is pressed.
هەڵبژێرە و ڕوونی بکەرەوە: (a) وێستگەیەکی کەشوهەوا کە هەر 10 خولەک جارێک خوێندنەوەیەک بۆ بە API هەڵبار دەکات؛ (b) گڵۆپی هۆشمەند کە دەبێت لە ماوەی نیو چرکەدا هەڵبکرێن کاتێک دوگمەیەکی مۆبایل دادەگیرێت.
Show answerوەڵامەکە پیشان بدە
(a) HTTPS: one POST every 10 minutes to the REST API is simple, and the station needs no commands. (b) MQTT: the lights keep a connection open, so the broker can push “on” at once; with HTTP the lights would have to keep asking.
(a) : یەک POST هەر 10 خولەک جارێک بۆ API سادەیە و وێستگەکە پێویستی بە فەرمان نییە. (b) : گڵۆپەکان پەیوەندییەک کراوە دەهێڵنەوە، بۆیە دەتوانێت «هەڵکردن» یەکسەر بنێرێت؛ بە گڵۆپەکان دەبێت هەر بپرسن.
Summaryپوختە
- Two questions: what to send (JSON) and how to carry it (HTTP or MQTT), both over TCP/IP.
- JSON (RFC 8259): objects of name–value pairs; names in double quotes; numbers without units;
true,false,null; no NaN, no comments, no trailing commas. - HTTP (RFC 9110): the device sends a request (method, path, headers, body) and gets one response with a status code; simple, but heavy and the device must ask.
- MQTT (OASIS 3.1.1 and 5.0): publish/subscribe through a broker; topics with
/levels,+and#wildcards; QoS 0 at most once, 1 at least once, 2 exactly once; retained messages, last will, keep alive. - Encrypt: HTTPS on 443, MQTT over TLS on 8883 (1883 is plain text); keep secrets out of shared code.
- دوو پرسیار: چی بنێرین () و چۆن بیگوازینەوە ( یان )، هەردووکیان لەسەر .
- (RFC 8259): جووتی ناو و نرخ؛ ناو لە ناو جووتە کەوانەدا؛ ژمارە بێ یەکە؛
true،false،null؛ نە NaN، نە تێبینی، نە فاریزەی کۆتایی. - (RFC 9110): ئامێرەکە دەنێرێت (، ، ، ) و یەک بە وەردەگرێت؛ سادەیە، بەڵام قورسە و ئامێرەکە دەبێت بپرسێت.
- (OASIS 3.1.1 و 5.0): لە ڕێگەی ؛ بە ئاستی
/،+و#؛ QoS 0 زۆرترین یەکجار، 1 لانیکەم یەکجار، 2 ڕێک یەکجار؛ ، ، هێشتنەوەی پەیوەندی. - شفرە بکە: لەسەر 443، لەسەر لە پۆرتی 8883؛ پۆرتی 1883 دەقی ئاشکرایە؛ نهێنییەکان لە کۆدی هاوبەش دوور بخەرەوە.
Next: store the readings in a cloud database and show them in a dashboard and an app — Storing IoT readings in the cloud.
داهاتوو: خوێندنەوەکان لە هەڵبگرە و لە و ئەپێکدا پیشانیان بدە — هەڵگرتنی خوێندنەوەکانی IoT لە هەوردا.
Lesson complete!وانەکە تەواو بوو!
Well done. Review the key terms, then go on to the next lesson.دەستخۆش. سەیرێکی زاراوە سەرەکییەکان بکەرەوە، پاشان بڕۆ بۆ وانەی داهاتوو.
Key termsزاراوە سەرەکییەکان
Storing IoT Readings in the Cloudهەڵگرتنی خوێندنەوەکانی IoT لە هەوردا
Related lecturesوانە پەیوەندیدارەکان
- Storing IoT Readings in the Cloudهەڵگرتنی خوێندنەوەکانی IoT لە هەوردا
- LoRaWAN: the Network Behind LoRaLoRaWAN: ڕایەڵەکەی پشت LoRa
- Who Writes the Rules? IoT Standardsکێ یاساکان دەنووسێت؟ ستانداردەکانی IoT
- The Questions Behind Every IoT Designئەو پرسیارانەی لە پشت هەموو دیزاینێکی IoTـەوەن
- Web APIs and JSONAPIـی وێب و JSON
- TCP and UDPTCP و UDP
- Port Numbers and Socketsژمارەی پۆرت و سۆکێتەکان
- Encryption, Hashing and Digital Signaturesشفرەکردن، هاشکردن و واژووە دیجیتاڵییەکان
- Arduino Boards and the Arduino IDEبۆردەکانی Arduino و Arduino IDE
References and further readingسەرچاوەکان و خوێندنەوەی زیاتر
- mqtt.org: MQTT, the standard for IoT messaging
- mqtt.org: FAQ (creators, 1999, ports 1883 and 8883, OASIS and ISO)
- Wikipedia: MQTT (history: Stanford-Clark and Nipper, 1999, oil-pipeline SCADA over satellite links; versions 3.1.1 and 5.0)
- OASIS: MQTT Version 5.0, OASIS Standard, 7 March 2019 (QoS flows, retained messages, Will Message, Keep Alive)
- OASIS: MQTT Version 3.1.1 (topic names, filters and wildcards, IANA ports)
- RFC 8259: The JavaScript Object Notation (JSON) Data Interchange Format
- RFC 9110: HTTP Semantics
- Arduino: ArduinoMqttClient library (MqttClient API)
- test.mosquitto.org: public test broker, ports and warnings
This lecture is a first edition. The Kurdish text and terminology are waiting for review by Kurdish IT teachers.ئەم وانەیە چاپی یەکەمە. دەقە کوردییەکە و زاراوەکانی چاوەڕێی پێداچوونەوەی مامۆستایانی کوردی بواری IT ن.