نقشه راه اتصال 2 رله با برد توسعه توسط کتابخانه آردینو AirNgin

نمونه پروژه

کنترل 2 عدد رله توسط سامانه اِیر اِنجی

مقدمه

رله دو کاناله به طور گسترده در سیستم‌های خانه هوشمند و اینترنت اشیا برای کنترل دستگاه‌ها و تجهیزات مختلف استفاده می‌شود. این رله‌ها می‌توانند به عنوان یک سوییچ مکانیکی اقدام به قطع و وصل برق کنند. این برق می تواند متناسب با نوع رله متفاوت باشد.

برای مثال، با اتصال رله دو کاناله به یک سیستم تهویه هوا، می‌توان یک دمای مناسب در داخل خانه حفظ کرد. زمانی که دمای محیط از یک آستانه خاص مانند 30 درجه سانتی‌گراد عبور کند، رله می‌تواند به طور خودکار یک تهویه مطبوع را روشن کند تا دمای اتاق کاهش یابد. برعکس، وقتی دما به زیر حد مشخصی مثل 22 درجه سانتی‌گراد برسد، رله دستگاه تهویه مطبوع را خاموش می‌کند. این کار نه تنها باعث حفظ دمای مطلوب در محیط می‌شود، بلکه به صرفه‌جویی در مصرف انرژی و کاهش هزینه‌های برق نیز کمک می‌کند.

با استفاده از پلتفرم AirNgin، می‌توانید یک رله دو کاناله هوشمند را از صفر بسازید و راه‌اندازی کنید. در این پروژه، از یک برد برد توسعه ESP32 WROOM-32D​، برد ارتباطی Wi-Fi ESP32و 2 عدد رله نرمال اوپن استفاده می‌شود. در این مثال ما دو رله را به پلتفرم ابری وصل می نماییم و تمامی مراحل را قدم به قدم با یکدیگر جلو می رویم.

مواد لازم

قدم اول معرفی ابزار

برای شروع ابتدا به پنل تولیدکنندگان بروید و ثبت نام خود را تکمیل کنید. سپس از منوی سمت راست به قسمت ابزارهای ابری بروید.

داشبورد ایر انجین

شما از این قسمت وارد مرحله اول تعریف ابزار خود می شوید. با کلیک بر روی ابزار جدید، صفحه تعریف ابزار برای شما باز می شود.

تعریف اولیه ابزار

صفحه زیر باز می شود.

توجه: تمامی اطلاعات وارده تا قبل از ارسال ابزار جهت تایید قابل تغییر می باشد. پس آموزش را گام به گام با ما ادامه دهید.

تعریف ابزار در ایر انجین

گزینه های فرم بالا به شرح زیر است (با دقت مطالعه نمایید) :

نام:

این نام ابزار است که در نرم‌افزار موبایل نیز هنگام اضافه کردن ابزار توسط کاربر نهایی نمایش داده می‌شود. بنابراین، اگر نیاز است، مدل ابزار را نیز در ادامه همین نام قرار دهید.

دسته بندی:

از این بخش باید دسته‌بندی ابزار خود را انتخاب نمایید. این دسته‌بندی در پیدا کردن ابزار شما توسط کاربر نهایی در نرم‌افزار موبایل و همچنین نمایش بخش‌بندی در نرم‌افزار موبایل اهمیت دارد.

توجه: اگر دسته‌بندی مورد نظر شما موجود نمی‌باشد، از بخش تیکت درخواست اضافه شدن آن دسته‌بندی را اعلام نمایید.

نوع آنالیز

ما در حال حاضر دو نوع آنالیز داریم که صرفاً تا انتهای سال ۱۴۰۳ توسط “فایل NodeJs” قابل استفاده خواهد بود و بخش لینک هنوز فعال نمی‌باشد.

آنالیز توسط فایل NodeJs:

در این حالت به دو فایل JS نیاز داریم که حتماً در ادامه به توضیح آنها خواهیم پرداخت.

یک فایل Generate:

این فایل مشخص می‌کند که داده‌های دریافتی از نرم‌افزارهای موبایل به چه داده‌هایی تبدیل شده و به سمت ابزار شما ارسال می‌شوند. در واقع، این کار برای جلوگیری از تغییرات گسترده در پروژه‌های شما انجام می‌شود. علاوه بر این، در آینده قابلیت اتصال به خدمات مختلف ابری و استفاده از APIهای شخصی توسط خود شما در این فایل‌ها میسر خواهد شد.

برای بهره مندی از نمونه و تست فایل Generator می توانید فایل زیر را دانلود نمایید.

دانلود فایل نمونه

سپس به بخش آزمایشگاه > تست فایل JS جهت ارسال داده به ابزار بروید و فایل را بارگذاری کنید و متناسب با ابزار هایی که اضافه کرده اید آن را تست و ویرایش کنید.

آزمایشگاه فایل js generate برای تست در ایر انجین

 

یک فایل برای Analyzer:

این فایل مشخص می‌کند که داده‌های دریافتی از سخت‌افزارهای شما دقیقاً چه معنایی برای سرور خواهند داشت. در واقع، این کار برای جلوگیری از تغییرات گسترده در پروژه‌های شما انجام می‌شود. علاوه بر این، در آینده قابلیت اتصال به خدمات مختلف ابری و استفاده از APIهای شخصی توسط خود شما در این فایل‌ها میسر خواهد شد.

برای بهره مندی از نمونه و تست فایل آنالیز می توانید فایل زیر را دانلود نمایید.

دانلود فایل نمونه

سپس به بخش آزمایشگاه > تست فایل JS جهت دریافت داده از ابزار بروید و فایل را بارگذاری کنید و متناسب با ابزار هایی که اضافه کرده اید آن را تست و ویرایش کنید.

آزمایشگاه تست فایل JS برای آنالیز ایر انجین

 

فایل راهنما

این فایل از نوع html است و بسیار مهم است زیرا به عنوان راهنمای گام به گام برای کاربر جهت افزودن ابزار به مکان خود نمایش داده می‌شود و شامل تنظیمات اضافی آن ابزار و نکات مهمی است که باید برای استفاده صحیح رعایت شوند. همچنین، این فایل می‌تواند در عیب‌یابی به کاربران کمک کند. هدف از این کار این است که شما نیازی به بروشورهای کاغذی نداشته باشید که معمولاً ممکن است توسط کاربر گم شوند و همچنین این امکان را فراهم می‌آورد که بتوانید با استفاده از ویدیو، به کاربران نهایی آموزش دهید.

این فایل راهنما در دو قسمت قابل مشاهده است:

1- افزودن یک ابزار توسط کاربرنهایی:ابتدا کاربر نهایی در نرم افزار موبایل دسته بندی ابزار را انتخاب می کند. سپس از لیست ابزار های لود شده ابزار شما را انتخاب می کند.بعد از انتخاب ابزار بصورت خودکار این فایل راهنما برای کاربر به نمایش در می آید تا اطلاع از اقدامات اولیه برای افزودن ابزار و همچنین نحوه استفاده از آن ابزار داشته باشد.

2 – پس از افزودن یک ابزار در قسمت اطلاعات هر ابزار در نرم افزار موبایل کماکان این فایل راهنما قابل مشاهده است.

از آنجایی که ممکن است شما برای ساخت این فایل نیاز به کمک داشته باشید یک ویرایشگر html برای شما در پنل آزمایشگاه > ویرایشگر html طراحی شده است.

می توانید همین نمونه را متناسب با نیاز خود تغییر دهید و سپس از طریق دکمه دانلود فایل html آن را دانلود نمایید.

قدم دوم تنظیمات پنل اِیر اِنجین بعد از افزودن ابزار

ویرایشگر html ابر انجین

 

فایل تنظیمات (اجباری نمی باشد):

این فایل نیز از نوع html است. یکی از مزایای این فایل، افزودن تنظیمات اضافی به ابزار شما است. تنظیماتی مانند تغییر رنگ چراغ، تغییر حالت‌های یک رله یا یک دکمه و هر آنچه که برای شما مورد نیاز است.

برای این بخش هنوز ویرایشگری تعبیه نشده است، اما می‌توانید از بخش مستندات آموزشی، APIهای آن را مشاهده کنید.

آموزش تنظیمات اختصاصی برای ابزار

امکان ارسال دستور از طریق پیامک (در این آموزش تیک آن را نزنید):

این گزینه صرفاً برای ابزارهایی است که دارای GSM درونی هستند، مانند SIM800. توضیحات این بخش به آموزش‌های دیگری که همراه با GSM است سپرده می‌شود. البته، اگر نیاز به توضیحات بیشتر دارید، می‌توانید به مستندات درگاه پیامکی مراجعه کنید.

عکس:

عکس محصول دقیقا همان عکسی می باشد که هنگام اضافه کردن ابزار به کاربر جهت انتخاب محصول مورد نظر خود نمایش می دهیم. پس لازم است یک عکس واقعی از محصول خود را آپلود نمایید.

در انتها این ابزار را ذخیره نمایید. نگران نباشید در آینده درصورت نیاز می شود تمامی این اطلاعات تا قبل از ارسال نهایی یک ابزار به بخش پشتیبانی، ویرایش کرد.

قدم دوم تنظیمات پنل اِیر اِنجین بعد از افزودن ابزار

بعد از افزودن یک ابزار به پنل کاربری خود، زمانی که به ابزارهای ابری از منوی سمت راست رجوع نمایید می توانید ابزاری که به پنل خود اضافه کرده اید را مشاهده کنید.

اضافه شدن نهایی ابزار به ایر انجین

حال بر روی اسم ابزار خود کلیک نمایید تا وارد بخش تنظیمات آن ابزار شوید.

پنل تنظیمات ابزار

با صفحه بالا روبرو می شوید. در منوی عمومی می توانید اطلاعات اولیه ابزار را ویرایش نمایید.

 

دستورات

دستورات :

در قدم اول نیاز است به قسمت دستورات بروید.

پنل دستورات ابزار

این قدم بسیار مهم می باشد. بر روی دستور جدید کلیک نمایید.

افزودن دستور جدید

کانال:

منظور از کانال در واقع قابلیت های ابزار شما است. منظور قابلیت ها مثل رله 1 کاناله دارای 1 کانال است. رله 2 کاناله دارای 2 کانال است و یا یک رله 2 کاناله همراه با یک عدد سنسور دما دارای 3 کانال است، 2 کانال رله و یک کانال سنسور.

بخش کانال دارای پارامترهای زیر است: 

ظاهر نرم افزار: با این بخش مشخص می نمایید این کانال که در حال تعریف آن هستید، چه نوع ابزاری است و باید چه نوع UI در نرم افزارهای موبایل به نمایش بگذارد. پس در انتخاب این بخش دقت نمایید. چون ما در این قسمت رله داریم می توانیم هم کلید روشنایی انتخاب نماییم و هم رله پریز (تفاوت در آیکن می باشد، در آینده اجازه میدهیم آیکن ها توسط کاربران انتخاب شوند).

کانال، درواقع قابلیت های یک ابزار است.

نام (operationName):

نام کانال چیست؟
نام کانال شما همان operationName است که در پلتفرم اینترنت اشیا استفاده می‌شود.

operationName در واقع نامی است که شما برای هر کانال مشخص می‌کنید. به این معنا که شما باید تصمیم بگیرید که هر کانال، مانند یک رله، چه معنایی برای شما دارد. به عنوان مثال، در کد نمونه ما، برای رله‌ها از نام‌های ch1 و ch2 استفاده کرده‌ایم تا کانال‌های 1 و 2 را شناسایی کنیم.

با این حال، این انتخاب کاملاً به شما بستگی دارد. ممکن است شما به رله اول نام relay1 و به رله دوم نام relay2 بدهید. بنابراین، operationName همان نام دلخواهی است که شما برای هر کانال انتخاب می‌کنید و این کاملاً اختیاری است.

این flexibility به شما این امکان را می‌دهد که نام‌ها را به روشی متناسب با نیازها و ساختار پروژه خود انتخاب کرده و از آن‌ها به راحتی استفاده کنید.

نوع دستور:

اگر دستور شما مربوط به یک دستگاه فعال‌سازی مانند رله باشد، به آن عملگر می‌گوییم، اما اگر دستور شما مربوط به یک دستگاه اندازه‌گیری مانند سنسور باشد، به آن سنسور می‌گوییم.

به عبارت دیگر، در پلتفرم اینترنت اشیا، هر دستگاه را بر اساس نوع عملکرد آن دسته‌بندی می‌کنیم. برای مثال:

  • عملگر: برای دستگاه‌هایی که به طور مستقیم اقدام به تغییر وضعیت می‌کنند، مانند رله‌ها (که می‌توانند یک مدار را باز یا بسته کنند).
  • سنسور: برای دستگاه‌هایی که داده‌ها یا اندازه‌گیری‌هایی از محیط جمع‌آوری می‌کنند، مانند سنسورها (که می‌توانند دما، رطوبت، حرکت و غیره را اندازه‌گیری کنند).

این تفکیک کمک می‌کند تا در سیستم، تشخیص داده‌ها و دستورات به درستی صورت گیرد و عملیات مورد نظر با دقت و صحت انجام شود.

تکمیل شده فرم بصورت بالا می باشد. حال روی ثبت و مرحله بعد کلیک می نماییم. 

در مرحله بعد دستورات آن ابزار متناسب با ظاهر انتخاب شده بصورت خودکار برای ما به نمایش در می آید.

همانطور که در بالا مشاهده می نمایید برای یک رله دستور روشن و خاموش معنی دارد. گزینه های این بخش به شرح زیر است:

نام: نام هر دستور است، این نام در بخش های مختلف مانند سناریو نویسی به نمایش در می آید. پس نیاز است نامی انتخاب نمایید که کاملا معنی آن دستور را می دهد.

مقدار سیستمی: 

این مقدار دقیقا همان مقداری می باشد که نرم افزارهای موبایل به سمت سرور ارسال می کند و شما توسط فایل generate باید آن را بررسی و دستور منحصر خود را به سمت ابزار ارسال کنید.دقت نمایید در تمامی دستورات ما به این مقدار سیتمی value می گوییم که در ادامه بررسی فایل های analyze و generate که برای سرور مورد نیاز است توضیح خواهیم داد. 

دستور:

در آینده این قسمت به کار می آید.

روی ثبت کلیک نمایید.

**تبریک می گویم شما اولین کانال خود را ثبت کرده اید.**

همین کار را برای کانال دوم رله نیز انجام می دهیم.

نکته: تا قبل از استفاده یک ابزار در یک پروژه می توانید با کلیک بر روی نام دستور مقادیر را تغییر دهید.

لیست دستورات

بسیار عالی.

سریال ها:

توسط این قسمت می توانید سریال ابزارها را اضافه نمایید. 

سریال ابزار برای چیست: 

برای اینکه هر ابزار بتواند به سرور وصل شود نیاز است یک سریال داشته باشد. جهت توضیحات کامل تر در این رابطه به بخش مستندات فنی رجوع نمایید.

نکته: سریال دارای قواعد خود می باشد حتما به مستندات فنی رجوع نمایید.

کد تولید کننده را که بصورت خودکار به شما ارایه می شود می توانید از بخش عمومی در پنل کاربری خود با کلیک بر روی آیکن یوزر در سمت چپ بالا > گزینه تولید کننده مشاهده نمایید.

مزیت های سریال:

ابزار شما یونیک می شود و تنها ابزارهایی که شما تولید کرده اید و به لیست سریال ها اضافه کرده اید قابلیت اتصال به سرور ابری اِیر اِنجین را دارند و همچنین قابل رهگیری نیز می باشند (رهگیری صرفا توسط بخش پشتیبانی سامانه آن هم با دستور مقام قضایی ممکن می باشد و به هیچ عنوان به دلیل حفظ حریم شخصی توسط تولید کننده قابل انجام نمی باشد).

تا این قسمت شما به درستی توانسته اید در پنل کاربری خود ابزار را اضافه نمایید و صرفا تغییرات فایل های analyzer و generate مانده که در ادامه که کدها را توضیح می دهیم این دو فایل را کامل می نماییم.

قدم سوم کدنویسی و تغییرات فایل های JS

کتابخانه مخصوص اِیر اِنجین برای آردینو را می توانید از آدرس زیر دانلود نمایید.

دانلود کتابخانه برای Esp32

توضیحات فایل control-2-relay.ino :

فایل control-2-relay.ino که در پوشه example قرار دارد، در هنگام نصب به عنوان فایل Example به آردینو شما اضافه می شود.

#include <AirNgin.h>

#define KEY_OF_CENTER "AIRN"  // IT'S PRODUCER CENTER CODE

#define Pushbotton 23  // PIN FOR GO TO Config Panel and AP MODE
#define RELAY1 16      // RELAY ONE
#define RELAY2 17      // RELAY TWO

#define Pushbutton_RELAY1 32  // push botton RELAY ONE
#define Pushbutton_RELAY2 33  // push botton RELAY TWO

#define CALL_Global_Mqtt_CALLBACK true  // if is true just call this airnginClient.setOnMessageCallback(myMqttCallback); \
                                        // else is false desn't call airnginClient.setOnMessageCallback(myMqttCallback); and call other callback

AirNginClient airnginClient;

String _SerialNo = "";

unsigned long _TimerSecCurrent, _TimerSecOld = 0;
byte _TimerSecDef = 0;
byte _TimerKeyPush = 0;


void MqttSend(String topic, String data) {

  airnginClient.Mqtt_Send(topic, data);
}



void setup() {

  Serial.begin(9600);
  Tools__SerialBarcodeReload();
  airnginClient.begin("", "", _SerialNo);
  airnginClient.setOnMessageCallback(myMqttCallback);
  airnginClient.setOnSaveScenarioCallback(saveScenarioCallback);
  airnginClient.setOnDebuggerCallback(debuggerCallback);
  airnginClient.setOnMessage_From_Topic_DeviceToDevice_Callback(message_From_Topic_DeviceToDevice_Callback);
  airnginClient.setOnMessage_From_Topic_ServerToDevice_Callback(message_From_Topic_ServerToDevice_Callback);

  pinMode(Pushbotton, INPUT_PULLUP);
  pinMode(Pushbutton_RELAY1, INPUT_PULLUP);
  pinMode(Pushbutton_RELAY2, INPUT_PULLUP);

  pinMode(RELAY1, OUTPUT);
  pinMode(RELAY2, OUTPUT);
}


void loop() {
  delay(1000);
  airnginClient.client_Loop();
  TimerSec_Refresh();  //read Time
  if (digitalRead(Pushbutton_RELAY1) == LOW) {
    _TimerKeyPush += _TimerSecDef;
  } else
    _TimerKeyPush = 0;
  if (_TimerKeyPush >= 5) {  //
    _TimerKeyPush = 0;
    if (airnginClient.isConfigMode) {
      airnginClient.Tools__SetMode(airnginClient._StartMode == "config_panel" ? "normal" : "config_panel", false);
      airnginClient.isConfigMode = false;
      airnginClient._Mqtt_TryConnecting = false;

    } else {
      airnginClient.Tools__SetMode(airnginClient._StartMode == "config_panel" ? "normal" : "config_panel", false);
      airnginClient.isConfigMode = true;
      airnginClient._Mqtt_TryConnecting = true;
      airnginClient.Config__Setup();
    }
  }


  if (digitalRead(Pushbutton_RELAY1) == LOW) {
    if (digitalRead(RELAY1) == LOW) {
      digitalWrite(RELAY1, HIGH);
      MqttSend("DeviceToServer", "ch1on");
      Serial.println("relay 1 : on");
    } else {
      digitalWrite(RELAY1, LOW);
      MqttSend("DeviceToServer", "ch1off");
      Serial.println("relay 1 : off");
    }
  }

  if (digitalRead(Pushbutton_RELAY2) == LOW) {
    if (digitalRead(RELAY2) == LOW) {
      digitalWrite(RELAY2, HIGH);
      MqttSend("DeviceToServer", "ch2on");
      Serial.println("relay 2 : on");
    } else {
      digitalWrite(RELAY2, LOW);
      MqttSend("DeviceToServer", "ch2off");
      Serial.println("relay 2 : off");
    }
  }
}


void Tools__SerialBarcodeReload() {

  String chip = (String(airnginClient.Tools__GetChipID()) + "0000000").substring(0, 7);
  if (chip == "0000000")
    chip = (String(airnginClient.Tools__Random(1000000, 9999998)) + "0000000").substring(0, 7);
  _SerialNo = KEY_OF_CENTER + ("000" + chip).substring(0, 10);


  Serial.println("_SerialNo : " + _SerialNo);
}


void TimerSec_Refresh() {
  //-------------------------------------------- TIMER
  try {
    _TimerSecCurrent = millis();
    _TimerSecDef = ((_TimerSecCurrent - _TimerSecOld) / 1000) & 0xFF;
    if (_TimerSecDef < 0)
      _TimerSecDef = 1;
    if (_TimerSecDef >= 1)
      _TimerSecOld = _TimerSecCurrent;
  } catch (...) {
  }
}


void myMqttCallback(char *topic, uint8_t *payload, unsigned int length) {

  Serial.print("Received data from topic: ");
  Serial.println(topic);

  Serial.print("Data: ");
  for (unsigned int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);  // تبدیل هر بایت به کاراکتر
  }
  Serial.println();

  String projectTopic = String(topic);
  int p = projectTopic.indexOf('/');
  if (projectTopic.substring(0, p) != airnginClient._ProjectCode)  // فرض بر این است که متدی برای گرفتن ProjectCode وجود دارد
    return;
  projectTopic = projectTopic.substring(p + 1);


  JsonDocument doc;
  doc.clear();

  DeserializationError error = deserializeJson(doc, payload, length);
  if (error) {
    Serial.println("JSON parse failed!");
    return;
  }

  if (projectTopic == "DeviceSetting") {
    String opr = doc["operationName"].as<String>();
    if (opr == "save_scenario" || opr == "delete_scenario") {
      // کد مربوط به ذخیره یا حذف سناریو
    } else if (opr == "save_setting") {
      if (doc["deviceSerial"].as<String>() == airnginClient._SerialCloud) {
        String cmd, d = doc["value"].as<String>();
        if (d != "") {
          deserializeJson(doc, d);
          if (doc["request"]["commandName"] && doc["request"]["commandData"]) {
            cmd = doc["request"]["commandName"].as<String>();
            if (cmd == "saveScenarioOperation") {
              JsonVariant inp = doc["scenarioOperation"].as<JsonVariant>();
              // پردازش سناریو
            }
            // سایر دستورات...
          }
        }
      }
    }
  } else if (projectTopic == "ServerToDevice") { // اگر داده ارسالی از سمت سرور باشد
    
    // خروجی ما بصورت زیر است 
    //{"data":"{\"type\":\"command\",\"value\":\"ch2on\"}","deviceSerial":"AIRN0001208520"}
    // دقت نمایید همیشه خروجی شما از طریق js generate 
    // درون یک json بصورت بالا 
    // در کلید data
    // قرار می گیرد

    // اسختراج سریال ابزاری که سرور برای آن داده را ارسال کرده ، جهت اینکه بدانید برای کدام ابزار است و با سریال خودتان در ادامه قیاس نمایید.
    String deviceSerial = doc["deviceSerial"].as<String>();

    if ((doc["data"])) {

        if (deviceSerial == airnginClient._SerialCloud) { // مطمین شویم که این داده برای ما ارسال شده است.

      String cmd = doc["data"].as<String>(); // اگر دیتا داشت چون خروجی فایل جاوااسکریپت ما هم یک json بوده 
                                           // تشکیل یک json در json داده ایم
                                           // پس نیاز است ابتدا json خودمان را
                                           // از json درون data
                                           // استخراج نماییم و سپس json خودمان را
      if (cmd != "") {
          doc.clear();
          deserializeJson(doc, cmd);
          String type = doc["type"].as<String>();
          String value = doc["value"].as<String>();
          Serial.println(" type > " + type);
          Serial.println(" value > " + value);

          if (type == "command") {
            if (value == "ch1on") {
              digitalWrite(RELAY1, HIGH);
              Serial.println(" with command from server  >  Relay 1 : on");

            } else if (value == "ch1off") {
              digitalWrite(RELAY1, LOW);
              Serial.println(" with command from server  >  Relay 1 : OFF");

            } else if (value == "ch2on") {
              digitalWrite(RELAY2, HIGH);
              Serial.println(" with command from server  >  Relay 2 : on");

            } else if (value == "ch2off") {
              digitalWrite(RELAY2, LOW);
              Serial.println(" with command from server  >  Relay 2 : OFF");
            }
              MqttSend("DeviceToServer", value); // حتما تغییرات را برای ثبت در سرور و ایجاد تغییر در اپلیکیشن ها به سمت سرور ارسال می نماییم.
          }
        }
      }
    }
  } else if (projectTopic == "Time/Tehran") {
    Serial.println(String((char *)payload));
  }
}


// تعریف Callback برای ذخیره سناریو
void saveScenarioCallback(JsonDocument &doc) {
  Serial.println("Save scenario callback triggered!");
  // پردازش مربوط به ذخیره سناریو
}

// تعریف Callback برای دیباگر
void debuggerCallback(String value) {
  Serial.println("Debugger callback triggered with value: " + value);
  // فقط حالت زمانی که operationNme == "debugger" و value == "special"
  // مابقی عملیات ها را کتابخانه اجرا می نماید
}

// تعریف Callback برای دریافت داده از DeviceToDevice
void message_From_Topic_DeviceToDevice_Callback(uint8_t *payload) {
  Serial.println("message on DeviceToDevice Callback with value: " + String((char *)payload));
}


// تعریف Callback برای دریافت داده از سرور جهت اجرای دستورات
void message_From_Topic_ServerToDevice_Callback(String value) {
  Serial.println("message on ServerToDevice Callback with value: " + value);
}


//Mqtt_Send(String topic, String data);

همانطور که می بنید صرفا نیاز است که کتابخانه اصلی به پروژه اضافه شود و کتابخانه هایی مانند WIFI.h دیگر نیاز نیست به پروژه اضافه شود زیرا در فایل اصلی کتابخانه موجود است.

پنل کانفیگ

در نمونه کد control-2-relay.ino ، پین 23 به‌عنوان یک پوش‌باتن در نظر گرفته شده است. هنگامی که این پوش‌باتن به مدت 6 ثانیه فشار داده شود، پنل کانفیگ راه‌اندازی می‌شود و برد ESP32 شما به حالت Access Point (AP) می‌رود و یک شبکه وای‌فای ایجاد می‌کند.

در این حالت می‌توانید با استفاده از نرم‌افزار موبایل یا با اتصال به ابزار (رمز عبور: 00000000) و وارد کردن آدرس 192.168.1.1، به پنل کانفیگ دسترسی پیدا کنید.

همچنین پایه های رله 16 و 17 تعریف شده است که به واسطه آن اقدام به سویچ کردن دیتا می نماییم.

همچنین 2 عدد پوش باتن دیگر توسط پایه های 32 و 33 نیز تعریف کرده ایم که جهت کنترل رله بصورت دستی از آنها استفاده می نماییم تا بتوانیم تست دو طرفه را به خوبی بگیریم.

اتصال خودکار به بروکر

این کتابخانه به‌صورت خودکار به بروکر متصل می‌شود و در صورت بروز قطعی، فرآیند اتصال مجدد را مدیریت می‌کند.

قابلیت آپدیت OTA

این قابلیت به شما امکان می‌دهد تا فریمور ابزار خود از راه دور به‌روزرسانی کنید. این ویژگی برای رفع مشکلات نرم‌افزاری و افزودن قابلیت‌های جدید به ابزار بسیار کاربردی است و تنها با درخواست کاربر قابل انجام خواهد بود. پس از آپلود فایل‌های آپدیت در پنل تولیدکنندگان، این فایل‌ها به کاربران نمایش داده می‌شوند و با تأیید کاربر، درخواست به سمت ابزار ارسال شده و عملیات به‌روزرسانی به‌صورت خودکار انجام می‌شود.

لطفاً توجه داشته باشید که هنگام پروگرام اولیه ابزار، حالت Partition Scheme را از منوی Tools بر روی گزینه Minimal SPIFFS تنظیم کنید تا بیشترین فضای ممکن برای به‌روزرسانی فریمور فراهم شود.


متدهای Callback متنوع

اگر متغیر سراسری زیر را true کنید، تنها یک Callback عمومی به نام myMqttCallback فعال می‌شود:

#define CALL_Global_Mqtt_CALLBACK true

زمانی که متفییر سراسری بالا True باشد، می توانید توسط متد Callback زیر مقادیر دریافتی را توسط متد زیر دریافت نمایید و مطابق مستندات فنی برای حالت های مختلف کدنویسی نمایید:

متدهای Callback متنوع

اگر متغیر سراسری زیر را falseکنید، تمامی Callback های زیر فعال می‌شود:

  airnginClient.setOnSaveScenarioCallback(saveScenarioCallback);
  airnginClient.setOnDebuggerCallback(debuggerCallback);
  airnginClient.setOnMessage_From_Topic_DeviceToDevice_Callback(message_From_Topic_DeviceToDevice_Callback);
  airnginClient.setOnMessage_From_Topic_ServerToDevice_Callback(message_From_Topic_ServerToDevice_Callback);
setOnSaveScenarioCallback : جهت ذخیره سناریو داخلی می باشد که در مثال سناریو نویسی داخلی قابل مشاهده است.
 
setOnDebuggerCallback : جهت دریافت دستور در حالتی می باشد که operationName=”devugger” باشد و مقدار شما value=”special” می باشد.
 
setOnMessage_From_Topic_DeviceToDevice_Callback : دریافت اطلاعات از تاپیک DeviceToDevice است.
 
setOnMessage_From_Topic_ServerToDevice_Callback : دریافت اطلاعات از سرور می باشد.

توجه : دقت نمایید در حالتی که CALL_Global_Mqtt_CALLBACK برابر true است تمامی عملیات ها مانند آپدیت فریمورک و ریبوت ابزار را خودتان برنامه نویسی کنید.

ارسال داده

توسط متد زیر اقدام به ارسال داده می نماییم.

void MqttSend(String topic, String data){

  airnginClient.Mqtt_Send(topic, data);

}
تطبیق فایل های Node Js با کدها :

آخرین قدم این است که ما مطمین شویم که فایل های Node Js ما با کدهایمان همانگی لازم را دارد. 

همان طور که در بخش آنالیز مطالعه کرده اید ما به 2 فایل نیاز داریم یکی برای تفسیر داده هایی که از ابزار به سرور ارسال می شود. در واقع همان تاپیک DeviceToServer

function main(inputJsonString, outputJsonString) {
    if(inputJson=="ch1on"){
            outputJson.status.push({
            key: "ch1",
            value: "on"
        });
        outputJson.result = "OK";
    }else if(inputJson=="ch1off"){
        outputJson.status.push({
            key: "ch1",
            value: "off"
        });
        outputJson.result = "OK";
    } else if(inputJson=="ch2on"){
        outputJson.status.push({
            key: "ch2",
            value: "on"
        });
        outputJson.result = "OK";

    }else if(inputJson=="ch2off"){
        outputJson.status.push({
            key: "ch2",
            value: "off"
        });
        outputJson.result = "OK";
    }else{
        outputJson.result = 'Invalid command!';
    }

    return JSON.stringify(outputJson);
}

در کد بالا موارد به شرح زیر است :

inputJsonString: دقیقا همان مقداری می باشد که شما در زمان ارسال وضعیت خود به سمت بروکر ارسال می کنید.

در کدهای همین پروژه می توانید فانکشن زیر را به عنوان مثال در نظر بگیرید.

MqttSend(“DeviceToServer”, “ch1on”);

در خط کد بالا : inputJsonString = ch1on

نکته : شما می توانید داده های خود را بصورت json نیز ازسال نمایید و یا حتی بجای نوشته String از اعداد استفاده نمایید مانند : 11،10،21،20 تمامی این بستگی به نوع تفکر و نیاز و برنامه نویسی شما دارد.

var inputJson = inputJsonString;

این یک تابع json ثابت از سمت سرور می باشد که نیاز است مطابق با کامندهایی که در سرور هنگام ثبت یک ابزار آنها را مشاهده کرده اید مقادیر آن را پر نماییید.

var outputJson = JSON.parse(outputJsonString);

شما باید پروتکل خود را با قوانین سرور منطبق نمایید
ما فرض می نماییم داده ch1on که از ابزار شما ارسال می شود دقیقا همان مقدار سیستمی ch1 در سرور می باشد که حالت روشن یا همان on است.

outputJsonString : یک لیست می باشد که شامل دو مقدار زیر است.

 key , value

key : همان operationName می باشد
value : همان مقدار command می باشد.

شاید سوال این باشد چرا از همان اسم های operationName و command استفاده نکرده ایم؟! دلیل آن دید توسعه به این سکوی اینترنت اشیا است.

برای دریافت operationName و command های سیستمی به پنل و ابزار مورد نظر خود مراجعه نمایید. این بخش قبلا در بخش تعریف ابزار و مقدار های سیستمی توضیح داده شده است.

حال نیاز است مقدار outputJsonString را پر نماییم و به سرور برگردانیم :

توسط دستور زیر که بخشی از فایل اصلی آنالیز است، ما دستور را مطابق با مقدار های سیستمی به لیست اضافه می نماییم. 

چرا لیست است؟ زیر ممکن است شما بخواهید در هر زمان که نیاز داشته باشید جهت افزایش سرعت ابزار خود یک یا چند داده را (مثلا وضعیت یک رله کارت 10 کاناله) با هم اراسال نمایید. پس مقدار بازگشتی لیست در نظرگرفته شده است تا پاسخ این نیاز باشد.

به همین سادگی ابزار شما وضعیت خودش را به سرور اطلاع داده است.

 

 outputJson.status.push({
            key: "ch1",
            value: "on"
        });
        outputJson.result = "OK";

حال سراغ هماهنگی فایل generate برای ارسال دستور از سرور ( نرم افزارهای موبایل ) به ابزار می رویم. دقیقا همان تاپیک ServerToDevice :

function main(inputJsonString) {
       var inputJson = JSON.parse(inputJsonString);

    var outPut = "";
    switch (inputJson.operationName) {
        case "ch1": 
            if (inputJson.value == "on") { 
                outPut = 'ch1on';             } else if (inputJson.value == "off") {
                outPut = 'ch1off';
            }
            break;
        case "ch2":
            if (inputJson.value == "on") {
                outPut = 'ch2on';
            } else if (inputJson.value == "off") {
                outPut = 'ch2off';
            }
            break;
        default:
            outPut = "";
            break;
    }

   
    var result = { type: 'command', value: outPut };
    return JSON.stringify(result);
}

inputJsonString : دقیقا دستوری می باشد که کاربر از نرم افزار موبایل در خواست داده است و می خواهد به سمت ابزار ارسال کند. شما با بررسی این ورودی می توانید درخواست کاربر را برای ابزار خود ترجمه نمایید.

نکته : تمامی این مقدار ها در زمان ثبت ابزار در قسمت دستورات به عنوان مقدار سیستمی تعریف شده است.

از آنجایی که داده ها با فایل Node js شما برای generate داده های مخصوص ابزار شما بصورت json است، ابتدا آن را deserialize می نماییم.

var inputJson = JSON.parse(inputJsonString);

پس از deserilize داده وروردی سرور شما تنها دارای دو مقدار هستید.

inputJson.operationName : همان کانال شما در زمان تعریف ابزار است. (مانند ch1,ch2,….,ch1xx)

inputJson.value : دومین مقدار سیستمی دستور درخواستی ابزار توسط کاربر می باشد که متناسب با نوع ابزارها متفاوت است. برای رله صرفا on و off است.

حال با یک شرط ساده می گویید اگر inputJson.operationName  برابر با ch1 بود ( این را شما در هنگام تعریف یک ابزار به عنوان یکی از کانال ها تعریف کرده اید) و inputJson.value برابر با on بود ( مقدار سیستمی بعد از تعریف کانال (های) ابزار می باشد) برای ابزار شما به معنی ch1on است.

در انتها برای آنکه شما کار با json را فرا بگیرید، ما مقدار خود را بصورت زیر تعریف کرده ایم : 

var result = { type: ‘command', value: outPut };

یک type که به ما بگوید نوع دستور چیست ( اصلا نیاز نمی باشد و صرفا برای کد نویسی شخصی خودمان گذاشته ایم و مشا می توانید از فایل generate و کدهای اصلی فایل نمونه حذف کنید).

یک value که مقدار درخواستی کاربر می باشد که بعد از تحلیل ما ch1on شد است.

سپس متغییر result را با خط کد زیر تبدیل به یک json می نماییم و آن را به سرور با کلمه return بر می گردانیم.

return JSON.stringify(result);

سوالات متداول :
آیا می تواند مقدار سیستمی ابزار ها را تغییر دهم؟

تغییر مقدار سیستم ابزارها فعلا امکان پذیر نمی باشد.

آیا می توانم مقدار کانال را تغییر دهم ؟

بله، شما می توانید مقدار کانال ابزار را به هر مقداری که می خواهید تغییر دهید، فقط باید فایل Node Js را مطابق با مقدار خود نمایید.

 

آیا نیاز است من مقدار خود را برای ابزار json ارسال کنم ؟

خیر، اما توصیه می نماییم کار با json را فراگیرید. اما اگر قصد ندارید داده json به سمت ابزار ارسال کنید، مقدار خود را مستقیم return نمایید. البته که نیاز است شما در انتها هنگام دریافت یک بار مانند فایل نمونه مقدار data را deserialize نمایید.

من مشکل دارم چطور حل کنم ؟

کافیست مشکلات خود را با بخش پشتیبانی فنی از طریق تیکت، در میان بگذارید. پشتیبانی ما کاملا برای کمک به شما آماده می باشد.

قدم دوم تنظیمات پنل اِیر اِنجین بعد از افزودن ابزار