# നിങ്ങളുടെ IoT ഉപകരണം ക്ലൗഡുമായി ബന്ധിപ്പിക്കുക - Wio Terminal ഈ പാഠഭാഗത്തിൽ, നിങ്ങളുടെ Wio Terminal നിങ്ങളുടെ IoT Hub-ലോട് കണക്റ്റ് ചെയ്ത് ടെലിമെട്രി അയയ്ക്കുകയും കമാൻഡുകൾ സ്വീകരിക്കുകയും ചെയ്യും. ## നിങ്ങളുടെ ഉപകരണം IoT Hub-ലേക്ക് കണക്റ്റ് ചെയ്യുക അടുത്ത ഘട്ടം നിങ്ങളുടെ ഉപകരണം IoT Hub-ലേക്ക് ബന്ധിപ്പിക്കുകയാണ്. ### ടാസ്‌ക് - IoT Hub-ലേക്ക് കണക്റ്റ് ചെയ്യുക 1. VS Code-ൽ `soil-moisture-sensor` പ്രോജക്റ്റ് തുറക്കൂ 1. `platformio.ini` ഫയൽ തുറക്കുക. `knolleary/PubSubClient` ലൈബ്രറി ഡിപ്പെൻഡൻസി നീക്കം ചെയ്യുക. ഇത് പബ്ലിക്ക് MQTT ബ്രോക്കറുമായി കണക്റ്റ് ചെയ്യാനായി ഉപയോഗിച്ചത്, IoT Hub-ലേക്ക് കണക്റ്റ് ചെയ്യാൻ ആവശ്യമില്ല. 1. താഴെക്കൊടുത്ത ലൈബ്രറി ഡിപ്പെൻഡൻസികൾ ചേർക്കുക: ```ini seeed-studio/Seeed Arduino RTC @ 2.0.0 arduino-libraries/AzureIoTHub @ 1.6.0 azure/AzureIoTUtility @ 1.6.1 azure/AzureIoTProtocol_MQTT @ 1.6.0 azure/AzureIoTProtocol_HTTP @ 1.6.0 azure/AzureIoTSocket_WiFi @ 1.0.2 ``` `Seeed Arduino RTC` ലൈബ്രറി Wio Terminal-ൽ റിയൽ-ടൈം ക്ലോക്കുമായി ഇടപഴകാൻ കോഡ് നൽകുന്നു, സമയമനുസരിച്ച് ട്രാക്ക് ചെയ്യാൻ. ശേഷിക്കുന്ന ലൈബ്രറികൾ നിങ്ങളുടെ IoT ഉപകരണം IoT Hub-ലേക്ക് കണക്റ്റ് ചെയ്യാൻ സഹായിക്കും. 1. `platformio.ini` ഫയലിന്റെ അടിയിൽ താഴെക്കൊടുത്തത് ചേർക്കുക: ```ini build_flags = -DDONT_USE_UPLOADTOBLOB ``` ഇത് Arduino IoT Hub കോഡ് കമ്പൈൽ ചെയ്യുമ്പോൾ ആവശ്യമായ കോമ്പൈലർ ഫ്ലാഗ് സെറ്റ് ചെയ്യുന്നു. 1. `config.h` ഹെഡർ ഫയൽ തുറക്കുക. മുഴുവൻ MQTT സജ്ജീകരണങ്ങളും നീക്കം ചെയ്ത് ചുവടെ കൊടുത്തിരിക്കുന്ന ഡിവൈസ് കണക്ഷൻ സ്ട്രിംഗ് കോൺസ്റ്റന്റ് ചേർക്കുക: ```cpp // ഐഒടി ഹബ് ക്രമീകരണങ്ങൾ const char *CONNECTION_STRING = ""; ``` ``-ന്റെ ഇടത്ത് മുൻപ് കോപ്പി ചെയ്ത നിങ്ങളുടെ ഉപകരണത്തിന്റെ കണക്ഷൻ സ്ട്രിങ്ങ് വച്ചിടുക. 1. IoT Hub-ലേക്ക് കണക്ഷൻ സമയം അടിസ്ഥാനമായ ടോക്കൺ ഉപയോഗിക്കുന്നു. അതായത്, IoT ഉപകരണം നിലവിലെ സമയം അറിയണം. Windows, macOS, Linux പോലുള്ള ഓപ്പറേറ്റിംഗ് സിസ്റ്റങ്ങളുപോലെ, മൈക്രോകൺട്രോളറുകൾ ഇന്റർനെറ്റിലൂടെ സ്വയം സമയം സിങ്ക് ചെയ്യുന്നതല്ല. അതിനാൽ [NTP](https://wikipedia.org/wiki/Network_Time_Protocol) സർവറിൽ നിന്നുള്ള നിലവിലെ സമയം നേടാൻ കോഡ് ചേർക്കേണ്ടതാണ്. സമയം കിട്ടിയ ശേഷം, അത് Wio Terminal-ലെ റിയൽ-ടൈം ക്ലോക്കിൽ സംഭരിക്കാം, ഉപകരണം പവർ നഷ്ടമാക്കാതെ കൃത്യമായ സമയമറിയാം. `ntp.h` എന്ന പുതിയ ഫയൽ താഴെക്കൊടുത്ത കോഡോടുകൂടി ചേർക്കുക: ```cpp #pragma once #include "DateTime.h" #include #include "samd/NTPClientAz.h" #include static void initTime() { WiFiUDP _udp; time_t epochTime = (time_t)-1; NTPClientAz ntpClient; ntpClient.begin(); while (true) { epochTime = ntpClient.getEpochTime("0.pool.ntp.org"); if (epochTime == (time_t)-1) { Serial.println("Fetching NTP epoch time failed! Waiting 2 seconds to retry."); delay(2000); } else { Serial.print("Fetched NTP epoch time is: "); char buff[32]; sprintf(buff, "%.f", difftime(epochTime, (time_t)0)); Serial.println(buff); break; } } ntpClient.end(); struct timeval tv; tv.tv_sec = epochTime; tv.tv_usec = 0; settimeofday(&tv, NULL); } ``` ഈ കോഡിന്റെ വിശദാംശങ്ങൾ ഈ പാഠഭാഗത്തിന്റെ പരിധിയ്ക്ക് പുറത്താണ്. `initTime` എന്ന ഫംഗ്ഷൻ നിർവ്വചിക്കുന്നു, NTP സർവറിൽ നിന്നുള്ള സമയം വാങ്ങി Wio Terminal-ലെ ക്ലോക്ക് സെറ്റ് ചെയ്യാൻ ഉപയോഗിക്കുന്നു. 1. `main.cpp` ഫയൽ തുറന്ന് മുഴുവൻ MQTT കോഡ് നീക്കം ചെയ്യുക, `PubSubClient.h` ഹെഡർ ഫയൽ, `PubSubClient` വേരിയേബിൾ പ്രഖ്യാപനവും, `reconnectMQTTClient` மற்றும் `createMQTTClient` രീതികൾ, ശുപാർശകളും നീക്കം ചെയ്യുക. ഈ ഫയൽ WiFi കണക്റ്റ് ചെയ്യുന്നതിനുള്ള, മണ്ണ് തോര്യത കൈമാറുന്നതിനുള്ള, JSON ഡോക്യുമെന്റ് സൃഷ്ടിക്കുന്നതിനുള്ള കോഡ് മാത്രമേ ഉള്ളൂ. 1. `main.cpp` ഫയലിന്റെ മുകളിൽ താഴെക്കൊടുത്ത `#include` നിർദ്ദേശങ്ങൾ ചേർക്കുക, IoT Hub ലൈബ്രറികൾക്കും സമയ സെറ്റിംഗിനും: ```cpp #include #include #include #include "ntp.h" ``` 1. `setup` ഫംഗ്ഷന്റെ അവസാനം നിലവിലെ സമയം സെറ്റ് ചെയ്യാൻ താഴെക്കൊടുത്ത കോൾ ചേർക്കുക: ```cpp initTime(); ``` 1. ഫയലിന്റെ മുകളിൽ, `#include` നിർദ്ദേശങ്ങളുടെ താഴെ, താഴെക്കൊടുത്ത വേരിയേബിൾ പ്രഖ്യാപനം ചേർക്കുക: ```cpp IOTHUB_DEVICE_CLIENT_LL_HANDLE _device_ll_handle; ``` ഇത് ഒരു `IOTHUB_DEVICE_CLIENT_LL_HANDLE` പ്രഖ്യാപിക്കുന്നു, IoT Hub-ലേക്ക് കണക്ഷൻ കൈകാര്യം ചെയ്യാനുള്ള ഹാൻഡിൽ. 1. ഇതിന് താഴെ, താഴെക്കൊടുത്ത കോഡ് ചേർക്കുക: ```cpp static void connectionStatusCallback(IOTHUB_CLIENT_CONNECTION_STATUS result, IOTHUB_CLIENT_CONNECTION_STATUS_REASON reason, void *user_context) { if (result == IOTHUB_CLIENT_CONNECTION_AUTHENTICATED) { Serial.println("The device client is connected to iothub"); } else { Serial.println("The device client has been disconnected"); } } ``` ഇത് ഒരു കോൾബാക്ക് ഫംഗ്ഷൻ പ്രഖ്യാപിക്കുന്നു, IoT Hub-ലേക്ക് കണക്ഷൻ നില മാറുമ്പോൾ (കണക്റ്റ് ചെയ്യുക അല്ലെങ്കിൽ ഡിസ്‌കണക്റ്റ് ചെയ്യുക) വിളിക്കപ്പെടും. നില സീരിയൽ പോർട്ടിലേക്ക് അയയ്ക്കുന്നു. 1. ഇതിന് താഴെ, IoT Hub-ലേക്ക് കണക്റ്റ് ചെയ്യാനുള്ള ഫംഗ്ഷൻ ചേർക്കുക: ```cpp void connectIoTHub() { IoTHub_Init(); _device_ll_handle = IoTHubDeviceClient_LL_CreateFromConnectionString(CONNECTION_STRING, MQTT_Protocol); if (_device_ll_handle == NULL) { Serial.println("Failure creating Iothub device. Hint: Check your connection string."); return; } IoTHubDeviceClient_LL_SetConnectionStatusCallback(_device_ll_handle, connectionStatusCallback, NULL); } ``` ഈ കോഡ് IoT Hub ലൈബ്രറി ഇൻഷ്യലൈസ് ചെയ്യുന്നു, ശേഷം `config.h` ഫയലിലുള്ള കണക്ഷൻ സ്ട്രിങ്ങ് ഉപയോഗിച്ച് MQTT അടിസ്ഥാനത്തിലുള്ള കണക്ഷൻ സൃഷ്ടിക്കുന്നു. കണക്ഷൻ പരാജയപ്പെടുന്നുവെങ്കിൽ, സീരിയൽ പോർട്ടിലേക്ക് പിഴവ് അയയ്ക്കുന്നു - ഇതു വന്നാൽ കണക്ഷൻ സ്ട്രിങ്ങ് പരിശോധിക്കുക. അവസാനം കണക്ഷൻ നില കോൾബാക്ക് സെറ്റ് ചെയ്യുന്നു. 1. ഈ ഫംഗ്ഷൻ `setup` ഫംഗ്ഷനിൽ `initTime` കോൾക്ക് താഴെ വിളിക്കുക: ```cpp connectIoTHub(); ``` 1. MQTT ക്ലയന്റ് പോലെയാണീ കോഡും single thread- ൽ പ്രവർത്തിക്കുന്നത് എന്നതിനാൽ ഹബ് വഴി അയക്കുന്ന സന്ദേശങ്ങൾ പ്രോസസ് ചെയ്യാൻ സമയമെടുക്കും. അതിനാൽ `loop` ഫംഗ്ഷന്റെ മുകളിൽ താഴെക്കൊടുത്തത് ചേർക്കുക: ```cpp IoTHubDeviceClient_LL_DoWork(_device_ll_handle); ``` 1. ഈ കോഡ് കമ്പൈൽ ചെയ്ത് അപ്‌ലോഡ് ചെയ്യുക. സീരിയൽ മോണിറ്ററിൽ കണക്ഷൻ കാണാം: ```output Connecting to WiFi.. Connected! Fetched NTP epoch time is: 1619983687 Sending telemetry {"soil_moisture":391} The device client is connected to iothub ``` ഔട്ട്പുട്ടിൽ NTP സമയം ലഭിക്കുന്നത്, തുടർന്ന് ഉപകരണം കണക്റ്റ് ആകുന്നത് കാണാം. കണക്ഷൻ പതുക്കെ ആയതിനാൽ, കണക്റ്റ് ചെയ്യുമ്പോൾ മണ്ണ് തോര്യത ഔട്ട്പുട്ടിൽ കാണാമാകാം. > 💁 UNIX സമയത്തെ വായനാസഹജമായ രൂപത്തിലേക്ക് മാറ്റാൻ [unixtimestamp.com](https://www.unixtimestamp.com) പോലുള്ള വെബ്‌സൈറ്റ് ഉപയോഗിക്കാം. ## ടെലിമെട്രി അയയ്ക്കുക ഇപ്പോൾ നിങ്ങളുടെ ഉപകരണം കണക്റ്റ് ചെയ്തതിനാൽ, MQTT ബ്രോക്കറിന് പകരം IoT Hub-ലേക്ക് ടെലിമെട്രി അയയ്ക്കാൻ കഴിയും. ### ടാസ്‌ക് - ടെലിമെട്രി അയയ്ക്കുക 1. `setup` ഫംഗ്ഷനു മുകളിൽ താഴെക്കൊടുത്ത ഫംഗ്ഷൻ ചേർക്കുക: ```cpp void sendTelemetry(const char *telemetry) { IOTHUB_MESSAGE_HANDLE message_handle = IoTHubMessage_CreateFromString(telemetry); IoTHubDeviceClient_LL_SendEventAsync(_device_ll_handle, message_handle, NULL, NULL); IoTHubMessage_Destroy(message_handle); } ``` ഈ കോഡ് സ്‌ട്രിങ്ങ് പാരാമീറ്ററായി ലഭിച്ച മാസേജിൽ നിന്ന് IoT Hub സന്ദേശം സൃഷ്ടിക്കുന്നു, ഹബ്-ലേക്ക് അയയ്ക്കുന്നു, തുടർന്ന് മെസേജ് ഒബ്ജക്ട് ക്ലീൻ ചെയ്യുന്നു. 1. `loop` ഫംഗ്ഷനിൽ ടെലിമെട്രി സീരിയൽ പോർട്ടിൽ അയയ്ക്കുന്ന വരിയ്ക്ക് അടുത്ത് താഴെക്കൊടുത്ത കോൾ ചേർക്കുക: ```cpp sendTelemetry(telemetry.c_str()); ``` ## കമാൻഡുകൾ കൈകാര്യം ചെയ്യുക സെർവർ കോഡിൽ നിന്നുള്ള റീലേ കൺട്രോൾ ചെയ്യാനുള്ള കമാൻഡുകൾ കൈകാര്യം ചെയ്യേണ്ടതുണ്ട്. ഇത് ഡയരക്റ്റ് മെത്തഡ് റിക്വസ്റ്റ് എന്ന രൂപത്തിൽ അയയ്ക്കുന്നു. ## ടാസ്‌ക് - ഡയരക്റ്റ് മെത്തഡ് റിക്വസ്റ്റ് ഹാൻഡിൽ ചെയ്യുക 1. `connectIoTHub` ഫംഗ്ഷനിലേക്ക് മുമ്പ് താഴെക്കൊടുത്ത കോഡ് ചേർക്കുക: ```cpp int directMethodCallback(const char *method_name, const unsigned char *payload, size_t size, unsigned char **response, size_t *response_size, void *userContextCallback) { Serial.printf("Direct method received %s\r\n", method_name); if (strcmp(method_name, "relay_on") == 0) { digitalWrite(PIN_WIRE_SCL, HIGH); } else if (strcmp(method_name, "relay_off") == 0) { digitalWrite(PIN_WIRE_SCL, LOW); } } ``` IoT Hub ലൈബ്രറി ഡയരക്റ്റ് മെത്തഡ് റിക്വസ്റ്റ് ലഭിക്കുമ്ബോള്‍ വിളിച്ചേക്കാവുന്ന കോൾബാക്ക് രീതിയാണ് ഇത്. അഭ്യർത്ഥിച്ച മെത്തഡ് `method_name` പാരാമീറ്ററിൽ ഉണ്ടാകും. ഈ ഫംഗ്ഷൻ വിളിച്ച മെത്തഡ് സീരിയൽ പോർട്ടിൽ പ്രിന്റ് ചെയ്യും, തുടർന്ന് മെത്തഡ് അനുസരിച്ച് റീലേ ഓണോ ഓഫ് ആക്കും. > 💁 ഇത് ഒരേ ഡയരക്റ്റ് മെത്തഡ് റിക്വസ്റ്റ് വഴി നടപ്പിലാക്കാം, റീലേയുടെ ആഗ്രഹിക്കുന്ന നില മെത്തഡ് അഭ്യർത്ഥനയോടൊപ്പം പാരാമീറ്ററായി പാസ്സ് ചെയ്യുക, ഇത് `payload`-ൽ നിന്നും ലഭിക്കും. 1. `directMethodCallback` ഫംഗ്ഷന്റെ അവസാനം താഴെക്കൊടുത്ത കോഡ് ചേർക്കുക: ```cpp char resultBuff[16]; sprintf(resultBuff, "{\"Result\":\"\"}"); *response_size = strlen(resultBuff); *response = (unsigned char *)malloc(*response_size); memcpy(*response, resultBuff, *response_size); return IOTHUB_CLIENT_OK; ``` ഡയരക്റ്റ് മെത്തഡ് അഭ്യർത്ഥനകൾക്ക് റസ്പോൺസ് ആവശ്യമാണ്, അത് രണ്ട് ഭാഗങ്ങൾ - ടെക്സ്റ്റ് റസ്പോൺസ്, റിട്ടേൺ കോഡ്. ഈ കോഡ് ചുവടെ കൊടുത്ത JSON ഫോർമാറ്റിൽ ഫലം ഉണ്ടാക്കും: ```JSON { "Result": "" } ``` ഇത് `response` പാരാമീറ്ററിലേക്ക് കോപ്പി ചെയ്യും, `response_size`-ൽ വലിപ്പം നൽകും. പിന്നീട് `IOTHUB_CLIENT_OK` റിട്ടേൺ ചെയ്യുന്നു, മെത്തഡ് ശരിയായി കൈകാര്യം ചെയ്തതായി സൂചിപ്പിക്കാൻ. 1. കോൾബാക്ക് ബന്ധിപ്പിക്കാൻ `connectIoTHub` ഫംഗ്ഷന്റെ അവസാനം താഴെ കൊടുത്തത് ചേർക്കുക: ```cpp IoTHubClient_LL_SetDeviceMethodCallback(_device_ll_handle, directMethodCallback, NULL); ``` 1. `loop` ഫംഗ്ഷൻ IoTHubDeviceClient_LL_DoWork ഫംഗ്ഷൻ കോൾചെയ്തു ഹബ് അയക്കുന്ന ഇവന്റുകൾ പ്രോസസ് ചെയ്യും. ഇത് ഓരോ 10 സെക്കൻഡുകൾക്ക് ഒരിക്കൽ `delay` മൂലം മാത്രമാണ് വിളിക്കപ്പെടുക, അതിനാൽ ഡയരക്റ്റ് മെത്തഡ് പ്രോസസിങ് 10 സെക്കൻഡ് ഇടവേള മാത്രമേ ഉണ്ടായിരിക്കൂ. ഇത് കാര്യക്ഷമമാക്കാൻ 10 സെക്കൻഡ് ഡിലേ പല ചെറിയ ഡിലേഷനായി മാറ്റി ഓരോ പ്രാവശ്യം `IoTHubDeviceClient_LL_DoWork` വിളിക്കാം. അതിനായി `loop`-ക്ക് മുൻപ് താഴെക്കൊടുത്ത കോഡ് ചേർക്കുക: ```cpp void work_delay(int delay_time) { int current = 0; do { IoTHubDeviceClient_LL_DoWork(_device_ll_handle); delay(100); current += 100; } while (current < delay_time); } ``` ഈ കോഡ് ആവർത്തിച്ച് പ്രവർത്തിക്കുകയാണ്, ഓരോ തവണയും `IoTHubDeviceClient_LL_DoWork` വിളിച്ച് 100ms ഡിലേ ചെയ്യുന്നു. ഇത് `delay_time` പാരാമീറ്ററിൽ നൽകിയ സമയത്തേക്ക് ആവശ്യത്തിന് ആവരും. അതായത്, ഉപകരണം കൂടുതൽ 100ms ഉണ്ടാകാതെ ഡയരക്റ്റ് മെത്തഡ് അഭ്യർത്ഥനകൾ പ്രാസസ്സ് ചെയ്യാൻ സാധിക്കും. 1. `loop` ഫംഗ്ഷനിൽ `IoTHubDeviceClient_LL_DoWork` കോൾ നീക്കം ചെയ്ത് `delay(10000)` താഴെക്കൊടുത്ത കോഡിൽ മാറ്റുക: ```cpp work_delay(10000); ``` > 💁 ഈ കോഡ് [code/wio-terminal](../../../../../2-farm/lessons/4-migrate-your-plant-to-the-cloud/code/wio-terminal) ഫോളഡറിൽ ലഭ്യമാണ്. 😀 നിങ്ങളുടെ മണ്ണ് തോര്യത സെൻസർ പ്രോഗ്രാം നിങ്ങളുടെ IoT Hub-ലിനോട് കണക്റ്റ് ചെയ്തു! --- **അസൂയപ്പെടുത്തൽ**: ഈ രേഖ AI വിവർത്തന സേവനം [Co-op Translator](https://github.com/Azure/co-op-translator) ഉപയോഗിച്ച് വിവർത്തനം ചെയ്തതാണ്. നാം സതിനിശ്ചിതത്വം ഉറപ്പാക്കാനുള്ള ശ്രമം നടത്തുന്നെങ്കിലും, ഓട്ടോമാറ്റിക് വിവർത്തനങ്ങളിൽ പിശകുകളോ അക്ഷമതകളോ ഉണ്ടാകാം എന്നതിന് ദയവായി ശ്രദ്ധിക്കുക. മാതൃഭാഷയിലെ യഥാർത്ഥ രേഖ authoritative ഉറവിടമായിരിക്കണം. നിർണ്ണായക വിവരങ്ങൾക്ക്, പ്രൊഫഷണൽ മനുഷ്യ വിവർത്തനം ശുപാർശ ചെയ്തതാണ്. ഈ വിവർത്തനം ഉപയോഗിച്ചുനിലവിലെ തെറ്റുകൾ അല്ലെങ്കിൽ തെറ്റിദ്ധാരണകൾക്ക 우리는 ഉത്തരവാദികൾ അല്ല.