13 KiB
Prijunkite savo IoT įrenginį prie debesies - Wio Terminal
Šioje pamokos dalyje prijungsite savo Wio Terminal prie IoT Hub, kad galėtumėte siųsti telemetriją ir gauti komandas.
Prijunkite savo įrenginį prie IoT Hub
Kitas žingsnis - prijungti savo įrenginį prie IoT Hub.
Užduotis - prisijungti prie IoT Hub
-
Atidarykite
soil-moisture-sensorprojektą VS Code. -
Atidarykite
platformio.inifailą. Pašalinkiteknolleary/PubSubClientbibliotekos priklausomybę. Ji buvo naudojama prisijungti prie viešojo MQTT brokerio, tačiau nėra reikalinga jungiantis prie IoT Hub. -
Pridėkite šias bibliotekų priklausomybes:
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.2Seeed Arduino RTCbiblioteka suteikia kodą, skirtą sąveikai su realaus laiko laikrodžiu Wio Terminal įrenginyje, kuris naudojamas laikui sekti. Likusios bibliotekos leidžia jūsų IoT įrenginiui prisijungti prie IoT Hub. -
Pridėkite šį kodą į
platformio.inifailo apačią:build_flags = -DDONT_USE_UPLOADTOBLOBTai nustato kompiliatoriaus vėliavą, kuri reikalinga kompiliuojant Arduino IoT Hub kodą.
-
Atidarykite
config.hantraštės failą. Pašalinkite visus MQTT nustatymus ir pridėkite šią konstantą įrenginio prisijungimo eilutei:// IoT Hub settings const char *CONNECTION_STRING = "<connection string>";Pakeiskite
<connection string>į jūsų įrenginio prisijungimo eilutę, kurią nukopijavote anksčiau. -
Prisijungimas prie IoT Hub naudoja laiko pagrindu sukurtą žetoną. Tai reiškia, kad IoT įrenginys turi žinoti dabartinį laiką. Skirtingai nuo operacinių sistemų, tokių kaip Windows, macOS ar Linux, mikrovaldikliai automatiškai nesinchronizuoja dabartinio laiko per internetą. Todėl turėsite pridėti kodą, kuris gautų dabartinį laiką iš NTP serverio. Kai laikas bus gautas, jis gali būti saugomas realaus laiko laikrodyje Wio Terminal įrenginyje, leidžiant vėliau gauti teisingą laiką, jei įrenginys nepraranda maitinimo. Sukurkite naują failą pavadinimu
ntp.hsu šiuo kodu:#pragma once #include "DateTime.h" #include <time.h> #include "samd/NTPClientAz.h" #include <sys/time.h> 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); }Šio kodo detalės nėra šios pamokos dalis. Jis apibrėžia funkciją
initTime, kuri gauna dabartinį laiką iš NTP serverio ir naudoja jį laikrodžio nustatymui Wio Terminal įrenginyje. -
Atidarykite
main.cppfailą ir pašalinkite visą MQTT kodą, įskaitantPubSubClient.hantraštės failą,PubSubClientkintamojo deklaraciją,reconnectMQTTClientircreateMQTTClientmetodus bei visus šių kintamųjų ir metodų iškvietimus. Šiame faile turėtų likti tik kodas, skirtas prisijungti prie WiFi, gauti dirvožemio drėgmės duomenis ir sukurti JSON dokumentą su šiais duomenimis. -
Pridėkite šias
#includedirektyvas įmain.cppfailo viršų, kad įtrauktumėte antraštės failus, skirtus IoT Hub bibliotekoms ir laikui nustatyti:#include <AzureIoTHub.h> #include <AzureIoTProtocol_MQTT.h> #include <iothubtransportmqtt.h> #include "ntp.h" -
Pridėkite šį iškvietimą į
setupfunkcijos pabaigą, kad nustatytumėte dabartinį laiką:initTime(); -
Pridėkite šią kintamojo deklaraciją failo viršuje, iškart po
includedirektyvų:IOTHUB_DEVICE_CLIENT_LL_HANDLE _device_ll_handle;Tai deklaruoja
IOTHUB_DEVICE_CLIENT_LL_HANDLE, kuris yra ryšio su IoT Hub rankena. -
Po to pridėkite šį kodą:
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"); } }Tai deklaruoja atgalinio iškvietimo funkciją, kuri bus iškviečiama, kai ryšio su IoT Hub būsena pasikeis, pvz., prisijungiant ar atsijungiant. Būsena bus išsiųsta į serijinį prievadą.
-
Po to pridėkite funkciją, skirtą prisijungti prie IoT Hub:
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); }Šis kodas inicializuoja IoT Hub bibliotekos kodą, tada sukuria ryšį, naudodamas prisijungimo eilutę iš
config.hantraštės failo. Šis ryšys yra pagrįstas MQTT. Jei ryšys nepavyksta, tai bus išsiųsta į serijinį prievadą - jei tai matote išvestyje, patikrinkite prisijungimo eilutę. Galiausiai nustatomas ryšio būsenos atgalinis iškvietimas. -
Iškvieskite šią funkciją
setupfunkcijoje, poinitTimeiškvietimo:connectIoTHub(); -
Kaip ir su MQTT klientu, šis kodas veikia viename siūle, todėl jam reikia laiko apdoroti žinutes, siunčiamas iš hub'o ir į hub'ą. Pridėkite šį kodą į
loopfunkcijos viršų, kad tai atliktumėte:IoTHubDeviceClient_LL_DoWork(_device_ll_handle); -
Sukompiliuokite ir įkelkite šį kodą. Serijiniame monitoriuje pamatysite ryšį:
Connecting to WiFi.. Connected! Fetched NTP epoch time is: 1619983687 Sending telemetry {"soil_moisture":391} The device client is connected to iothubIšvestyje galite matyti, kaip gaunamas NTP laikas, po to įrenginio klientas prisijungia. Prisijungimas gali užtrukti kelias sekundes, todėl galite matyti dirvožemio drėgmės duomenis išvestyje, kol įrenginys jungiasi.
💁 UNIX laiką iš NTP galite konvertuoti į labiau suprantamą formatą naudodami tokias svetaines kaip unixtimestamp.com
Siųskite telemetriją
Dabar, kai jūsų įrenginys prijungtas, galite siųsti telemetriją į IoT Hub vietoj MQTT brokerio.
Užduotis - siųsti telemetriją
-
Pridėkite šią funkciją virš
setupfunkcijos: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); }Šis kodas sukuria IoT Hub žinutę iš eilutės, perduotos kaip parametras, išsiunčia ją į hub'ą, tada išvalo žinutės objektą.
-
Iškvieskite šį kodą
loopfunkcijoje, iškart po eilutės, kur telemetrija siunčiama į serijinį prievadą:sendTelemetry(telemetry.c_str());
Apdorokite komandas
Jūsų įrenginys turi apdoroti komandą iš serverio kodo, kad valdytų relę. Tai siunčiama kaip tiesioginio metodo užklausa.
Užduotis - apdoroti tiesioginio metodo užklausą
-
Pridėkite šį kodą prieš
connectIoTHubfunkciją: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); } }Šis kodas apibrėžia atgalinio iškvietimo metodą, kurį IoT Hub biblioteka gali iškviesti, kai gauna tiesioginio metodo užklausą. Metodas, kuris yra užklaustas, perduodamas
method_nameparametru. Ši funkcija išspausdina iškviestą metodą į serijinį prievadą, tada įjungia arba išjungia relę, priklausomai nuo metodo pavadinimo.💁 Tai taip pat galėtų būti įgyvendinta vienoje tiesioginio metodo užklausoje, perduodant norimą relės būseną kaip naudingąją apkrovą, kurią galima perduoti su metodo užklausa ir pasiekti iš
payloadparametro. -
Pridėkite šį kodą į
directMethodCallbackfunkcijos pabaigą: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;Tiesioginio metodo užklausoms reikia atsakymo, kuris susideda iš dviejų dalių - atsakymo kaip teksto ir grąžinimo kodo. Šis kodas sukurs rezultatą kaip šį JSON dokumentą:
{ "Result": "" }Tada jis bus nukopijuotas į
responseparametrą, o šio atsakymo dydis bus nustatytasresponse_sizeparametru. Šis kodas grąžinsIOTHUB_CLIENT_OK, kad parodytų, jog metodas buvo tinkamai apdorotas. -
Prijunkite atgalinį iškvietimą, pridėdami šį kodą į
connectIoTHubfunkcijos pabaigą:IoTHubClient_LL_SetDeviceMethodCallback(_device_ll_handle, directMethodCallback, NULL); -
loopfunkcija iškviesIoTHubDeviceClient_LL_DoWorkfunkciją, kad apdorotų įvykius, siunčiamus IoT Hub. Tai iškviečiama tik kas 10 sekundžių dėldelay, todėl tiesioginiai metodai apdorojami tik kas 10 sekundžių. Kad tai būtų efektyviau, 10 sekundžių vėlavimą galima įgyvendinti kaip daug trumpesnių vėlavimų, kiekvieną kartą iškviečiantIoTHubDeviceClient_LL_DoWork. Norėdami tai padaryti, pridėkite šį kodą viršloopfunkcijos:void work_delay(int delay_time) { int current = 0; do { IoTHubDeviceClient_LL_DoWork(_device_ll_handle); delay(100); current += 100; } while (current < delay_time); }Šis kodas kartosis, iškviesdamas
IoTHubDeviceClient_LL_DoWorkir vėluodamas po 100 ms kiekvieną kartą. Tai darys tiek kartų, kiek reikia, kad vėluotų nurodytą laikądelay_timeparametru. Tai reiškia, kad įrenginys laukia daugiausiai 100 ms, kad apdorotų tiesioginio metodo užklausas. -
loopfunkcijoje pašalinkiteIoTHubDeviceClient_LL_DoWorkiškvietimą ir pakeiskitedelay(10000)iškvietimu šiuo kodu:work_delay(10000);
💁 Šį kodą galite rasti code/wio-terminal aplanke.
😀 Jūsų dirvožemio drėgmės jutiklio programa prijungta prie jūsų IoT Hub!
Atsakomybės apribojimas:
Šis dokumentas buvo išverstas naudojant AI vertimo paslaugą Co-op Translator. Nors siekiame tikslumo, prašome atkreipti dėmesį, kad automatiniai vertimai gali turėti klaidų ar netikslumų. Originalus dokumentas jo gimtąja kalba turėtų būti laikomas autoritetingu šaltiniu. Kritinei informacijai rekomenduojama naudoti profesionalų žmogaus vertimą. Mes neprisiimame atsakomybės už nesusipratimus ar klaidingus interpretavimus, atsiradusius dėl šio vertimo naudojimo.