اینترنت اشیا به تنهایی کاربردی برای ما ندارد اگر نتوانیم دیتایی رد و بدل کنیم. این مطلب درباره یکی از پروتکلهای تبادل دیتا صحبت میکند که بیشتر به درد این شیهای اینترنت دار میخوره. میدونم از آخرین مطلبم خیلی وقته گذشته ولی خب چه کنم دست و دلم به نوشتن نبود.
اینترنت اشیا یعنی همون چیزهایی که دور و برمون هست رو به اینترنت وصل کنیم. مثل لامپ، تلویزیون، ماشین لباسشویی و...
وصل شدن ماشین لباسشویی به تنهایی به اینترنت نه دردی از اون دوا میکنه نه از ما! یعنی صرف اینکه به اینترنت وصل بشه کافی نیست و در این بستر باید پیامی رد و بدل بشه تا خاصیتی داشته باشه. برای همین رد و بدل کردن پیام امری اجتناب ناپذیر از زمان کفتر کاکل به سر تا کنون بوده و هست.
حال برای این خبر که از ما ببره و بیاره راههای گوناگونی وجود داره. حتما کلمه پروتکل رو شنیدید. مثلا پروتکل HTTP. جناب HTTP اومده یه سری استاندارد و ادا و اصول تعریف کرده که شما میخای تو اینترنت یه چیزی رو ببینی، طی مراحل اداری خاصی اون چیز از جایی در اینترنت به سیستم شما فرستاده میشه و شما اونو خواهید دید. اینجا کاری به اون ادا و اصول نداریم و قصد نداریم دربارهاش صحبت کنیم. بریم سراغ اشیا خودمون.
این اشیا بدبخت مثل سیستمهای خفن شما که نیستند. معمولا سخت افزار ضعیف یا اینترنت ناپایداری دارند. تصور کنید دوربینی در جایی دور افتاده به زور اونم با اینترنت داغون ما! میخاد یه تصویر بفرسته. برای همین نمیشه همون راهی که برای یک PC استفاده میکنیم برای اونم به کار ببریم. نه که نشه! میشه ولی خب اینکه درست کار کنه و پایدار باشه با خداست.
پروتکل MQTT که مخفف Message Queuing Telemetry Transport است در سال ۱۹۹۹ برای استفاده در صنعت نفت و گاز و اینا اختراع شد. هدفش هم این بود که با کمترین پهنای باند و کمترین مصرف باتری و این چیزا بتونن وضعیت خطوط لوله رو مانیتور کنند. بعدا این پروتکل تغییراتی کرد که فراتر از این چهار کلمه شد ولی این MQTT روش موند.
این پروتکل سه بخش اصلی داره:
ناشر یه پیامی داره که میده به کفتر کاکل به سر های های! و میگه این خبر از من ببر های های! پیام باید موضوع (Topic) داشته باشه. این پیام میاد دست broker. جناب broker بر مبنای موضوع خبر، اون رو به دست کلاینت میرسونه. نکته مهم اینجاس که کلاینت باید بگه که من منتظر چه خبری هستم. برای همین باید موضوع رو بدونه و گوش به زنگ روی اون موضوع منتظر بمونه تا اگه خبری اومد broker بهش برسونه.
این ارتباطی که توضیح دادم یک به یک نیست. یعنی اینکه هر تعداد کلاینت میتونند گوش بزنگ روی یک موضوع بمونند. حال شما میتونید تعیین کنید که پیام رو اونی که زودتر گرفت برداره یا همه اون پیام رو بردارند.
برای اینکه مطلب کامل جا بیفته بیاید یه مثال عملی براتون بزنم. فرض کنید یک سنسور دما داریم که در جایی نصب شده و قراره دیتای اون رو به صورت متناوب دریافت کنیم. برای اینکه این مطلب طولانی نشه درباره سنسور دما و ماژول WiFi اینجا توضیح نمیدم میتونید از اینجا مفصل دربارهاش بخونید. (حتما بخونید و گرنه ادامه بحث رو متوجه نخواهید شد)
خب با توجه به لینک بالا یک برنامه نوشتم. این قسمت از برنامه ما مقدار دما رو از سنسور دریافت میکنه:
sensors.requestTemperatures(); float temperatureC = sensors.getTempCByIndex(0);
حالا میخواهیم مقدار دما رو با پروتکل MQTT ارسال کنیم. اول از همه باید کتابخونهاش رو به ادیتور آردوینو اضافه کنید. من از این کتابخونه استفاده کردم. اگه نمیدونید کتابخونه چجوری اضافه میشه اینجا رو ببینید. سپس در کد یه instance از کتابخونه ایجاد میکنیم. برای ایجاد این instance نیاز به WiFiClient داریم:
WiFiClient espClient; PubSubClient client(espClient);
خب حالا باید به یک broker وصل بشیم. اگر بروکر ندارین و یک سرور لینوکسی دارین میتونید روی سرورتون ستاپ کنید. وگرنه از بروکرهای رایگان که در اینترنت موجوده استفاده کنید. من در اینجا به یکی از این بروکرها وصل میشم:
client.setServer("broker.emqx.io", "1883");
حالا باید به سرور وصل بشیم:
while (!client.connected()) { String client_id = "esp8266-client-" client_id += String(WiFi.macAddress()); Serial.printf("The client %s connects to the public mqtt broker\n", client_id.c_str()); if (client.connect(client_id.c_str(), mqtt_username, mqtt_password)) { } else { Serial.print("failed with state "); Serial.print(client.state()); delay(2000); } }
و بلاخره میتونیم پیام مون ارسال کنیم.
client.publish(topic, temperatureC);
کد کامل شده رو در ادامه براتون میذارم. میدونم این نوشته کامل نیست و ممکنه ابهاماتی داشته باشه، برای همین راحت باشید و هر سوالی داشتید در قسمت کامنتها بپرسید.
#include <ESP8266WiFi.h> #include <PubSubClient.h> #include <OneWire.h> #include <DallasTemperature.h> // WiFi const char *ssid = "SSID" // Enter your WiFi name const char *password = "PASSWORD" // Enter WiFi password // MQTT Broker const char *mqtt_broker = "broker.emqx.io" const char *topic = "esp8266/test" const char *mqtt_username = "emqx" const char *mqtt_password = "public" const int mqtt_port = 1883; // GPIO where the DS18B20 is connected to const int oneWireBus = 4; // Setup a oneWire instance to communicate with any OneWire devices OneWire oneWire(oneWireBus); // Pass our oneWire reference to Dallas Temperature sensor DallasTemperature sensors(&oneWire); WiFiClient espClient; PubSubClient client(espClient); void setup() { // Set software serial baud to 115200; Serial.begin(115200); // connecting to a WiFi network WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.println("Connecting to WiFi.."); } Serial.println("Connected to the WiFi network"); //connecting to a mqtt broker client.setServer(mqtt_broker, mqtt_port); client.setCallback(callback); while (!client.connected()) { String client_id = "esp8266-client-" client_id += String(WiFi.macAddress()); Serial.printf("The client %s connects to the public mqtt broker\n", client_id.c_str()); if (client.connect(client_id.c_str(), mqtt_username, mqtt_password)) { Serial.println("Public emqx mqtt broker connected"); } else { Serial.print("failed with state "); Serial.print(client.state()); delay(2000); } } // Start the DS18B20 sensor sensors.begin(); } void loop() { client.loop(); sensors.requestTemperatures(); float temperatureC = sensors.getTempCByIndex(0); Serial.print(temperatureC); Serial.println("ºC"); client.publish(topic, temperatureC); delay(1000); }