12 KiB
Povežite svoj IoT uređaj s oblakom - Wio Terminal
U ovom dijelu lekcije povezat ćete svoj Wio Terminal s IoT Hubom kako biste slali telemetriju i primali naredbe.
Povežite svoj uređaj s IoT Hubom
Sljedeći korak je povezivanje vašeg uređaja s IoT Hubom.
Zadatak - povezivanje s IoT Hubom
-
Otvorite projekt
soil-moisture-sensor
u VS Codeu. -
Otvorite datoteku
platformio.ini
. Uklonite ovisnost o biblioteciknolleary/PubSubClient
. Ova biblioteka je korištena za povezivanje s javnim MQTT brokerom i nije potrebna za povezivanje s IoT Hubom. -
Dodajte sljedeće ovisnosti o bibliotekama:
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
Biblioteka
Seeed Arduino RTC
omogućuje interakciju s real-time satom u Wio Terminalu, koji se koristi za praćenje vremena. Preostale biblioteke omogućuju vašem IoT uređaju povezivanje s IoT Hubom. -
Dodajte sljedeće na dno datoteke
platformio.ini
:build_flags = -DDONT_USE_UPLOADTOBLOB
Ovo postavlja zastavicu kompajlera koja je potrebna prilikom kompajliranja Arduino IoT Hub koda.
-
Otvorite zaglavlje
config.h
. Uklonite sve MQTT postavke i dodajte sljedeću konstantu za connection string uređaja:// IoT Hub settings const char *CONNECTION_STRING = "<connection string>";
Zamijenite
<connection string>
s connection stringom vašeg uređaja koji ste ranije kopirali. -
Povezivanje s IoT Hubom koristi token temeljen na vremenu. To znači da IoT uređaj mora znati trenutno vrijeme. Za razliku od operativnih sustava poput Windowsa, macOS-a ili Linuxa, mikrokontroleri ne sinkroniziraju automatski trenutno vrijeme putem Interneta. To znači da ćete morati dodati kod za dobivanje trenutnog vremena s NTP servera. Kada se vrijeme preuzme, može se pohraniti u real-time sat u Wio Terminalu, omogućujući kasnije dohvaćanje točnog vremena, pod uvjetom da uređaj ne izgubi napajanje. Dodajte novu datoteku pod nazivom
ntp.h
sa sljedećim kodom:#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); }
Detalji ovog koda nisu obuhvaćeni ovom lekcijom. Definira funkciju
initTime
koja dohvaća trenutno vrijeme s NTP servera i koristi ga za postavljanje sata na Wio Terminalu. -
Otvorite datoteku
main.cpp
i uklonite sav MQTT kod, uključujući zaglavljePubSubClient.h
, deklaraciju varijablePubSubClient
, metodereconnectMQTTClient
icreateMQTTClient
, te sve pozive tim varijablama i metodama. Ova datoteka treba sadržavati samo kod za povezivanje s WiFi-jem, dobivanje vlažnosti tla i stvaranje JSON dokumenta s tim podacima. -
Dodajte sljedeće
#include
direktive na vrh datotekemain.cpp
kako biste uključili zaglavlja za IoT Hub biblioteke i za postavljanje vremena:#include <AzureIoTHub.h> #include <AzureIoTProtocol_MQTT.h> #include <iothubtransportmqtt.h> #include "ntp.h"
-
Dodajte sljedeći poziv na kraj funkcije
setup
za postavljanje trenutnog vremena:initTime();
-
Dodajte sljedeću deklaraciju varijable na vrh datoteke, odmah ispod direktiva za uključivanje:
IOTHUB_DEVICE_CLIENT_LL_HANDLE _device_ll_handle;
Ovo deklarira
IOTHUB_DEVICE_CLIENT_LL_HANDLE
, ručku za povezivanje s IoT Hubom. -
Ispod toga dodajte sljedeći 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"); } }
Ovo deklarira callback funkciju koja će se pozvati kada se status veze s IoT Hubom promijeni, poput povezivanja ili prekida veze. Status se šalje na serijski port.
-
Ispod toga dodajte funkciju za povezivanje s IoT Hubom:
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); }
Ovaj kod inicijalizira IoT Hub bibliotečki kod, zatim stvara vezu koristeći connection string u zaglavlju
config.h
. Ova veza temelji se na MQTT-u. Ako veza ne uspije, to se šalje na serijski port - ako to vidite u izlazu, provjerite connection string. Na kraju se postavlja callback za status veze. -
Pozovite ovu funkciju u funkciji
setup
ispod pozivainitTime
:connectIoTHub();
-
Kao i kod MQTT klijenta, ovaj kod radi na jednom threadu pa treba vremena za obradu poruka koje hub šalje i prima. Dodajte sljedeće na vrh funkcije
loop
kako biste to omogućili:IoTHubDeviceClient_LL_DoWork(_device_ll_handle);
-
Izgradite i učitajte ovaj kod. Vidjet ćete vezu u serijskom monitoru:
Connecting to WiFi.. Connected! Fetched NTP epoch time is: 1619983687 Sending telemetry {"soil_moisture":391} The device client is connected to iothub
U izlazu možete vidjeti kako se dohvaća NTP vrijeme, nakon čega se uređaj povezuje s IoT Hubom. Može proći nekoliko sekundi da se poveže, pa ćete možda vidjeti vlažnost tla u izlazu dok se uređaj povezuje.
💁 UNIX vrijeme iz NTP-a možete pretvoriti u čitljiviji format koristeći web stranicu poput unixtimestamp.com
Slanje telemetrije
Sada kada je vaš uređaj povezan, možete slati telemetriju na IoT Hub umjesto na MQTT broker.
Zadatak - slanje telemetrije
-
Dodajte sljedeću funkciju iznad funkcije
setup
: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); }
Ovaj kod stvara IoT Hub poruku iz stringa proslijeđenog kao parametar, šalje je na hub, a zatim čisti objekt poruke.
-
Pozovite ovaj kod u funkciji
loop
, odmah nakon linije gdje se telemetrija šalje na serijski port:sendTelemetry(telemetry.c_str());
Obrada naredbi
Vaš uređaj treba obraditi naredbu s poslužiteljskog koda za upravljanje relejem. Ovo se šalje kao zahtjev za izravnu metodu.
Zadatak - obrada zahtjeva za izravnu metodu
-
Dodajte sljedeći kod prije funkcije
connectIoTHub
: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); } }
Ovaj kod definira callback metodu koju IoT Hub biblioteka može pozvati kada primi zahtjev za izravnu metodu. Metoda koja se traži šalje se u parametru
method_name
. Ova funkcija ispisuje pozvanu metodu na serijski port, a zatim uključuje ili isključuje relej ovisno o nazivu metode.💁 Ovo bi se također moglo implementirati u jednoj izravnoj metodi, prosljeđujući željeno stanje releja u payloadu koji se može proslijediti sa zahtjevom metode i koji je dostupan iz parametra
payload
. -
Dodajte sljedeći kod na kraj funkcije
directMethodCallback
: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;
Zahtjevi za izravne metode trebaju odgovor, a odgovor se sastoji od dva dijela - odgovora kao teksta i povratnog koda. Ovaj kod stvara rezultat kao sljedeći JSON dokument:
{ "Result": "" }
Ovo se zatim kopira u parametar
response
, a veličina ovog odgovora postavlja se u parametarresponse_size
. Ovaj kod zatim vraćaIOTHUB_CLIENT_OK
kako bi pokazao da je metoda ispravno obrađena. -
Povežite callback dodavanjem sljedećeg na kraj funkcije
connectIoTHub
:IoTHubClient_LL_SetDeviceMethodCallback(_device_ll_handle, directMethodCallback, NULL);
-
Funkcija
loop
će pozvati funkcijuIoTHubDeviceClient_LL_DoWork
za obradu događaja koje šalje IoT Hub. Ovo se poziva samo svakih 10 sekundi zbogdelay
, što znači da se izravne metode obrađuju samo svakih 10 sekundi. Kako bi ovo bilo učinkovitije, 10-sekundno kašnjenje može se implementirati kao mnogo kraćih kašnjenja, pozivajućiIoTHubDeviceClient_LL_DoWork
svaki put. Da biste to učinili, dodajte sljedeći kod iznad funkcijeloop
:void work_delay(int delay_time) { int current = 0; do { IoTHubDeviceClient_LL_DoWork(_device_ll_handle); delay(100); current += 100; } while (current < delay_time); }
Ovaj kod će se ponavljati, pozivajući
IoTHubDeviceClient_LL_DoWork
i odgađajući za 100 ms svaki put. To će činiti onoliko puta koliko je potrebno da se odgodi za vrijeme dano u parametrudelay_time
. To znači da uređaj čeka najviše 100 ms za obradu zahtjeva za izravne metode. -
U funkciji
loop
, uklonite pozivIoTHubDeviceClient_LL_DoWork
i zamijenite pozivdelay(10000)
sljedećim kako biste pozvali ovu novu funkciju:work_delay(10000);
💁 Ovaj kod možete pronaći u mapi code/wio-terminal.
😀 Vaš program za senzor vlažnosti tla povezan je s vašim IoT Hubom!
Odricanje od odgovornosti:
Ovaj dokument je preveden pomoću AI usluge za prevođenje Co-op Translator. Iako nastojimo osigurati točnost, imajte na umu da automatski prijevodi mogu sadržavati pogreške ili netočnosti. Izvorni dokument na izvornom jeziku treba smatrati autoritativnim izvorom. Za ključne informacije preporučuje se profesionalni prijevod od strane ljudskog prevoditelja. Ne preuzimamo odgovornost za bilo kakve nesporazume ili pogrešne interpretacije koje proizlaze iz korištenja ovog prijevoda.