将您的IoT设备连接到云端-Wio终端


文档摘要

将您的IoT设备连接到云端 - Wio终端 在本课程的这一部分中,您将把Wio终端连接到IoT Hub,以便发送遥测数据并接收命令。 将设备连接到IoT Hub 下一步是将设备连接到IoT Hub。 任务 - 连接到IoT Hub 在VS Code中打开 项目 打开 文件。移除 库依赖项。这是用来连接公共MQTT代理的,不需要连接到IoT Hub。 添加以下库依赖项: 库提供了与Wio终端中的实时时钟交互的代码,用于跟踪时间。其余的库允许您的IoT设备连接到IoT Hub。 在 文件的底部添加以下内容: 这设置了编译Arduino IoT Hub代码所需的编译器标志。 打开 头文件。

将您的IoT设备连接到云端 - Wio终端

在本课程的这一部分中,您将把Wio终端连接到IoT Hub,以便发送遥测数据并接收命令。

将设备连接到IoT Hub

下一步是将设备连接到IoT Hub。

任务 - 连接到IoT Hub

  1. 在VS Code中打开soil-moisture-sensor项目

  2. 打开platformio.ini文件。移除knolleary/PubSubClient库依赖项。这是用来连接公共MQTT代理的,不需要连接到IoT Hub。

  3. 添加以下库依赖项:

    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终端中的实时时钟交互的代码,用于跟踪时间。其余的库允许您的IoT设备连接到IoT Hub。

  4. platformio.ini文件的底部添加以下内容:

    build_flags = -DDONT_USE_UPLOADTOBLOB

    这设置了编译Arduino IoT Hub代码所需的编译器标志。

  5. 打开config.h头文件。移除所有MQTT设置,并添加以下设备连接字符串的常量:

    // IoT Hub settings const char *CONNECTION_STRING = "<connection string>";

    <连接字符串> with the connection string for your device you copied earlier.

  6. The connection to IoT Hub uses a time-based token. This means the IoT device needs to know the current time. Unlike operating systems like Windows, macOS or Linux, microcontrollers don't automatically synchronize the current time over the Internet. This means you will need to add code to get the current time from an NTP server. Once the time has been retrieved, it can be stored in a real-time clock in the Wio Terminal, allowing the correct time to be requested at a later date, assuming the device doesn't lose power. Add a new file called ntp.h替换为以下代码:

    #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); }

    该代码的详细信息超出了本课程的范围。它定义了一个名为initTime that gets the current time from an NTP server and uses it to set the clock on the Wio Terminal.

  7. Open the main.cpp file and remove all the MQTT code, including the PubSubClient.h header file, the declaration of the PubSubClient variable, the reconnectMQTTClient and createMQTTClient methods, and any calls to these variables and methods. This file should only contain code to connect to WiFi, get the soil moisture and create a JSON document with it in.

  8. Add the following #include directives to the top of the main.cpp文件以包含IoT Hub库的头文件,并设置时间:

    #include <AzureIoTHub.h> #include <AzureIoTProtocol_MQTT.h> #include <iothubtransportmqtt.h> #include "ntp.h"
  9. setup函数的末尾添加以下调用以设置当前时间:

    initTime();
  10. 在文件顶部,包含指令下方添加以下变量声明:

    IOTHUB_DEVICE_CLIENT_LL_HANDLE _device_ll_handle;

    这声明了一个IOTHUB_DEVICE_CLIENT_LL_HANDLE,即连接到IoT Hub的句柄。

  11. 在这之下,添加以下代码:

    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的连接状态发生变化时(如连接或断开),会调用此函数。状态会被发送到串行端口。

  12. 在这之下,添加一个连接到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); }

    此代码初始化IoT Hub库代码,然后使用config.h header file. This connection is based on MQTT. If the connection fails, this is sent to the serial port - if you see this in the output, check the connection string. Finally the connection status callback is set up.

  13. Call this function in the setup function below the call to initTime中的连接字符串创建连接。

  14. 就像MQTT客户端一样,这段代码在一个线程上运行,因此需要时间来处理来自中心的消息和发送到中心的消息。在loop函数的顶部添加以下代码以完成此操作:

    IoTHubDeviceClient_LL_DoWork(_device_ll_handle);
  15. 构建并上传此代码。您将在串行监视器中看到连接状态:

    Connecting to WiFi.. Connected! Fetched NTP epoch time is: 1619983687 Sending telemetry {"soil_moisture":391} The device client is connected to iothub

    在输出中,您可以看到获取NTP时间,随后设备客户端连接。连接可能需要几秒钟的时间,因此在此期间您可能会看到土壤湿度的数据。

    您可以使用像unixtimestamp.com这样的网站将NTP的UNIX时间转换为更易读的版本。

发送遥测数据

现在您的设备已连接,您可以将遥测数据发送到IoT Hub,而不是MQTT代理。

任务 - 发送遥测数据

  1. 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); }

    此代码从作为参数传递的字符串创建一个IoT Hub消息,将其发送到中心,然后清理消息对象。

  2. loop函数中,在向串行端口发送遥测数据的行之后调用此代码:

    sendTelemetry(telemetry.c_str());

处理命令

您的设备需要处理来自服务器代码的命令以控制继电器。此命令通过直接方法请求发送。

任务 - 处理直接方法请求

  1. 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); } }

    此代码定义了IoT Hub库可以调用的一个回调方法,当它收到直接方法请求时。请求的方法在method_name parameter. This function prints the method called to the serial port, then turns the relay on or off depending on the method name.

    This could also be implemented in a single direct method request, passing the desired state of the relay in a payload that can be passed with the method request and available from the payload parameter.

  2. Add the following code to the end of the 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;

    直接方法请求需要响应,响应分为两部分:文本响应和返回码。此代码将创建如下JSON文档的结果:

    { "Result": "" }

    然后将其复制到response parameter, and the size of this response is set in the response_size parameter. This code then returns IOTHUB_CLIENT_OK to show the method was handled correctly.

  3. Wire up the callback by adding the following to the end of the connectIoTHub函数:

    IoTHubClient_LL_SetDeviceMethodCallback(_device_ll_handle, directMethodCallback, NULL);
  4. loop function will call the IoTHubDeviceClient_LL_DoWork function to process events send by IoT Hub. This is only called every 10 seconds due to the delay, meaning direct methods are only processed every 10 seconds. To make this more efficient, the 10 second delay can be implemented as many shorter delays, calling IoTHubDeviceClient_LL_DoWork each time. To do this, add the following code above the loop函数中:

    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 and delaying for 100ms each time. It will do this as many times as needed to delay for the amount of time given in the delay_time parameter. This means the device is waiting at most 100ms to process direct method requests.

  5. In the loop function, remove the call to IoTHubDeviceClient_LL_DoWork, and replace the delay(10000)调用以调用此新函数:

    work_delay(10000);

您可以在code/wio-terminal文件夹中找到此代码。

您的土壤湿度传感器程序已连接到IoT Hub!

声明:
本文件灏天文库团队进行了翻译。尽管我们力求准确,但请注意,翻译可能包含错误或不准确之处。原文档以其原始语言为准。我们不对因使用此翻译而产生的任何误解或误译负责。


作者与出处
原作者: microsoft
来源:microsoft
许可证:MIT
整理: 灏天文库整理
由灏天文库结构化整理,提供目录导航、全文检索与在线阅读,便于系统化学习
发布者: 作者: microsoft 转发
评论区 (0)
U