13 KiB
IoT Cihazınızı Buluta Bağlayın - Wio Terminal
Bu dersin bu bölümünde, Wio Terminal cihazınızı IoT Hub'a bağlayarak telemetri gönderecek ve komutlar alacaksınız.
Cihazınızı IoT Hub'a Bağlayın
Bir sonraki adım, cihazınızı IoT Hub'a bağlamaktır.
Görev - IoT Hub'a bağlanın
-
VS Code'da
soil-moisture-sensor
projesini açın. -
platformio.ini
dosyasını açın.knolleary/PubSubClient
kütüphane bağımlılığını kaldırın. Bu, genel bir MQTT broker'a bağlanmak için kullanılıyordu ve IoT Hub'a bağlanmak için gerekli değildir. -
Aşağıdaki kütüphane bağımlılıklarını ekleyin:
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
kütüphanesi, Wio Terminal'deki gerçek zamanlı saatle etkileşim kurmak için kod sağlar ve zamanı takip etmek için kullanılır. Diğer kütüphaneler, IoT cihazınızın IoT Hub'a bağlanmasını sağlar. -
platformio.ini
dosyasının sonuna aşağıdakileri ekleyin:build_flags = -DDONT_USE_UPLOADTOBLOB
Bu, Arduino IoT Hub kodunu derlerken gerekli olan bir derleyici bayrağını ayarlar.
-
config.h
başlık dosyasını açın. Tüm MQTT ayarlarını kaldırın ve cihaz bağlantı dizesi için aşağıdaki sabiti ekleyin:// IoT Hub settings const char *CONNECTION_STRING = "<connection string>";
<connection string>
kısmını daha önce kopyaladığınız cihaz bağlantı dizesiyle değiştirin. -
IoT Hub bağlantısı zaman tabanlı bir token kullanır. Bu, IoT cihazının mevcut zamanı bilmesi gerektiği anlamına gelir. Windows, macOS veya Linux gibi işletim sistemlerinin aksine, mikrodenetleyiciler mevcut zamanı otomatik olarak İnternet üzerinden senkronize etmez. Bu, mevcut zamanı bir NTP sunucusundan alacak kod eklemeniz gerektiği anlamına gelir. Zaman alındıktan sonra, cihazın güç kaybetmediği sürece daha sonraki bir tarihte doğru zamanın istenmesine olanak tanıyan Wio Terminal'deki gerçek zamanlı saate kaydedilebilir.
ntp.h
adında yeni bir dosya oluşturun ve aşağıdaki kodu ekleyin:#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); }
Bu kodun detayları bu dersin kapsamı dışındadır. Bu, bir NTP sunucusundan mevcut zamanı alıp Wio Terminal'deki saati ayarlayan
initTime
adlı bir fonksiyon tanımlar. -
main.cpp
dosyasını açın ve tüm MQTT kodlarını kaldırın. BunaPubSubClient.h
başlık dosyası,PubSubClient
değişkeninin bildirimi,reconnectMQTTClient
vecreateMQTTClient
yöntemleri ve bu değişkenlere ve yöntemlere yapılan tüm çağrılar dahildir. Bu dosya yalnızca WiFi'ye bağlanmak, toprak nemini almak ve bununla bir JSON belgesi oluşturmak için kod içermelidir. -
IoT Hub kütüphanelerini ve zamanı ayarlamak için başlık dosyalarını dahil etmek üzere
main.cpp
dosyasının üstüne aşağıdaki#include
yönergelerini ekleyin:#include <AzureIoTHub.h> #include <AzureIoTProtocol_MQTT.h> #include <iothubtransportmqtt.h> #include "ntp.h"
-
Mevcut zamanı ayarlamak için
setup
fonksiyonunun sonuna aşağıdaki çağrıyı ekleyin:initTime();
-
Dosyanın üst kısmına, include yönergelerinin hemen altına aşağıdaki değişken bildirimini ekleyin:
IOTHUB_DEVICE_CLIENT_LL_HANDLE _device_ll_handle;
Bu, IoT Hub'a bir bağlantı için bir
IOTHUB_DEVICE_CLIENT_LL_HANDLE
tanımlar. -
Bunun altına aşağıdaki kodu ekleyin:
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"); } }
Bu, IoT Hub'a bağlantı durumu değiştiğinde (örneğin bağlanma veya bağlantının kesilmesi gibi) çağrılacak bir geri çağırma fonksiyonu tanımlar. Durum seri porta gönderilir.
-
Bunun altına IoT Hub'a bağlanmak için bir fonksiyon ekleyin:
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); }
Bu kod, IoT Hub kütüphane kodunu başlatır ve ardından
config.h
başlık dosyasındaki bağlantı dizesini kullanarak bir bağlantı oluşturur. Bu bağlantı MQTT tabanlıdır. Bağlantı başarısız olursa, bu seri porta gönderilir - eğer çıktıda bunu görürseniz, bağlantı dizesini kontrol edin. Son olarak, bağlantı durumu geri çağırması ayarlanır. -
Bu fonksiyonu
setup
fonksiyonundainitTime
çağrısının altına çağırın:connectIoTHub();
-
MQTT istemcisinde olduğu gibi, bu kod tek bir iş parçacığında çalışır, bu nedenle hub tarafından gönderilen ve hub'a gönderilen mesajları işlemek için zamana ihtiyaç duyar. Bunu yapmak için,
loop
fonksiyonunun üstüne aşağıdakileri ekleyin:IoTHubDeviceClient_LL_DoWork(_device_ll_handle);
-
Bu kodu derleyip yükleyin. Seri monitörde bağlantıyı göreceksiniz:
Connecting to WiFi.. Connected! Fetched NTP epoch time is: 1619983687 Sending telemetry {"soil_moisture":391} The device client is connected to iothub
Çıktıda, NTP zamanının alındığını ve ardından cihaz istemcisinin bağlandığını görebilirsiniz. Bağlanması birkaç saniye sürebilir, bu nedenle cihaz bağlanırken çıktıda toprak nemini görebilirsiniz.
💁 NTP için UNIX zamanını daha okunabilir bir sürüme dönüştürmek için unixtimestamp.com gibi bir web sitesi kullanabilirsiniz.
Telemetri Gönderin
Artık cihazınız bağlı olduğuna göre, telemetriyi MQTT broker yerine IoT Hub'a gönderebilirsiniz.
Görev - telemetri gönderin
-
setup
fonksiyonunun üstüne aşağıdaki fonksiyonu ekleyin: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); }
Bu kod, bir parametre olarak geçirilen bir string'den bir IoT Hub mesajı oluşturur, bunu hub'a gönderir ve ardından mesaj nesnesini temizler.
-
Bu kodu
loop
fonksiyonunda, telemetri seri porta gönderildikten hemen sonra çağırın:sendTelemetry(telemetry.c_str());
Komutları İşleyin
Cihazınızın, röleyi kontrol etmek için sunucu kodundan gelen bir komutu işlemesi gerekir. Bu, doğrudan bir yöntem isteği olarak gönderilir.
Görev - doğrudan bir yöntem isteğini işleyin
-
connectIoTHub
fonksiyonunun öncesine aşağıdaki kodu ekleyin: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); } }
Bu kod, IoT Hub kütüphanesinin doğrudan bir yöntem isteği aldığında çağırabileceği bir geri çağırma yöntemi tanımlar. İstenen yöntem
method_name
parametresinde gönderilir. Bu fonksiyon, çağrılan yöntemi seri porta yazdırır ve yöntem adına bağlı olarak röleyi açar veya kapatır.💁 Bu, yöntemin istenen durumunu bir yük olarak geçirerek ve bu yükü
payload
parametresinden alarak tek bir doğrudan yöntem isteği olarak da uygulanabilir. -
directMethodCallback
fonksiyonunun sonuna aşağıdaki kodu ekleyin: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;
Doğrudan yöntem isteklerinin bir yanıtı olması gerekir ve yanıt iki bölümden oluşur - metin olarak bir yanıt ve bir dönüş kodu. Bu kod, aşağıdaki JSON belgesi olarak bir sonuç oluşturur:
{ "Result": "" }
Bu daha sonra
response
parametresine kopyalanır ve bu yanıtın boyuturesponse_size
parametresinde ayarlanır. Bu kod daha sonra yöntemin doğru bir şekilde işlendiğini göstermek içinIOTHUB_CLIENT_OK
döndürür. -
Geri çağırmayı bağlamak için
connectIoTHub
fonksiyonunun sonuna aşağıdakileri ekleyin:IoTHubClient_LL_SetDeviceMethodCallback(_device_ll_handle, directMethodCallback, NULL);
-
loop
fonksiyonu, IoT Hub tarafından gönderilen olayları işlemek içinIoTHubDeviceClient_LL_DoWork
fonksiyonunu çağıracaktır. Bu, yalnızcadelay
nedeniyle her 10 saniyede bir çağrılır, bu da doğrudan yöntemlerin yalnızca her 10 saniyede bir işlenmesi anlamına gelir. Bunu daha verimli hale getirmek için, 10 saniyelik gecikme, her seferindeIoTHubDeviceClient_LL_DoWork
fonksiyonunu çağırarak birçok kısa gecikme olarak uygulanabilir. Bunu yapmak için,loop
fonksiyonunun üstüne aşağıdaki kodu ekleyin:void work_delay(int delay_time) { int current = 0; do { IoTHubDeviceClient_LL_DoWork(_device_ll_handle); delay(100); current += 100; } while (current < delay_time); }
Bu kod,
delay_time
parametresinde verilen süre boyunca beklemek için gereken kadar kezIoTHubDeviceClient_LL_DoWork
fonksiyonunu çağırarak ve her seferinde 100ms gecikerek tekrar tekrar döngü yapar. Bu, cihazın doğrudan yöntem isteklerini işlemek için en fazla 100ms beklediği anlamına gelir. -
loop
fonksiyonunda,IoTHubDeviceClient_LL_DoWork
çağrısını kaldırın vedelay(10000)
çağrısını aşağıdaki kodla değiştirin:work_delay(10000);
💁 Bu kodu code/wio-terminal klasöründe bulabilirsiniz.
😀 Toprak nem sensörü programınız IoT Hub'a bağlandı!
Feragatname:
Bu belge, AI çeviri hizmeti Co-op Translator kullanılarak çevrilmiştir. Doğruluğu sağlamak için çaba göstersek de, otomatik çevirilerin hata veya yanlışlık içerebileceğini lütfen unutmayın. Belgenin orijinal dili, yetkili kaynak olarak kabul edilmelidir. Kritik bilgiler için profesyonel insan çevirisi önerilir. Bu çevirinin kullanımından kaynaklanan yanlış anlamalar veya yanlış yorumlamalar için sorumluluk kabul etmiyoruz.