教程:开发适用于 Windows 设备的 C IoT Edge 模块Tutorial: Develop C IoT Edge modules for Windows devices

本文介绍如何使用 Visual Studio 开发 C 代码并将其部署到运行 Azure IoT Edge 的 Windows 设备。This article shows you how to use Visual Studio to develop C code and deploy it to a Windows device that's running Azure IoT Edge.

可以使用 Azure IoT Edge 模块来部署直接在 IoT Edge 设备中实现业务逻辑的代码。You can use Azure IoT Edge modules to deploy code that implements your business logic directly in your IoT Edge devices. 本教程详细介绍如何创建并部署用于筛选传感器数据的 IoT Edge 模块。This tutorial walks you through creating and deploying an IoT Edge module that filters sensor data.

在本教程中,你将了解如何执行以下操作:In this tutorial, you learn how to:

  • 使用 Visual Studio 创建基于 C SDK 的 IoT Edge 模块。Use Visual Studio to create an IoT Edge module that's based on the C SDK.
  • 使用 Visual Studio 和 Docker 创建 Docker 映像并将其发布到注册表。Use Visual Studio and Docker to create a Docker image and publish it to your registry.
  • 将模块部署到 IoT Edge 设备。Deploy the module to your IoT Edge device.
  • 查看生成的数据。View generated data.

在本教程中创建的 IoT Edge 模块可以筛选由设备生成的温度数据。The IoT Edge module that you create in this tutorial filters the temperature data that's generated by your device. 模块仅在温度超过指定阈值时向上游发送消息。The module sends messages upstream only if the temperature exceeds a specified threshold. 在边缘进行的此类分析适用于减少传递到云中和存储在云中的数据量。This type of analysis at the edge is useful for reducing the amount of data that's communicated to and stored in the cloud.

如果没有 Azure 试用版订阅,请在开始前创建一个试用版订阅If you don't have an Azure trail subscription, create a trial subscription before you begin.

先决条件Prerequisites

本教程演示如何使用 Visual Studio 2019 并采用 C 开发模块,以及如何将其部署到 Windows 设备。This tutorial demonstrates how to develop a module in C by using Visual Studio 2019 and then deploy it to a Windows device. 若要开发适用于 Linux 设备的模块,请转到开发适用于 Linux 设备的 C IoT Edge 模块If you're developing modules for Linux devices, go to Develop C IoT Edge modules for Linux devices instead.

若要了解用于开发 C 模块并将其部署到 Windows 设备的选项,请参阅下表:To understand your options for developing and deploying C modules to Windows devices, refer to the following table:

CC Visual Studio CodeVisual Studio Code Visual Studio 2017 和 2019Visual Studio 2017 and 2019
Windows AMD64Windows AMD64 在 Visual Studio 中开发 WinAMD64 的 C 模块

在开始本教程之前,请按照开发适用于 Windows 设备的 IoT Edge 模块教程中的说明设置开发环境。Before you begin this tutorial, set up your development environment by following the instructions in the Develop IoT Edge modules for Windows devices tutorial. 完成后,你的环境会包含以下必备组件:After you complete it, your environment will contain the following prerequisites:

运行以下命令,通过 vcpkg 安装适用于 Windows x64 的 Azure IoT C SDK:Install the Azure IoT C SDK for Windows x64 through vcpkg by running the following commands:

git clone https://github.com/Microsoft/vcpkg
cd vcpkg
.\bootstrap-vcpkg.bat
.\vcpkg install azure-iot-sdk-c:x64-windows
.\vcpkg --triplet x64-windows integrate install

提示

如果使用的是 Visual Studio 2017(版本 15.7 或更高版本),请从 Visual Studio Marketplace 下载并安装适用于 Visual Studio 2017 的 Azure IoT Edge Tools。If you're using Visual Studio 2017 (version 15.7 or later), download and install Azure IoT Edge Tools for Visual Studio 2017 from Visual Studio Marketplace.

创建模块项目Create a module project

在本部分中,你使用 Visual Studio 和 Azure IoT Edge Tools 扩展创建基于 C SDK 的 IoT Edge 模块项目。In this section, you create an IoT Edge module project that's based on the C SDK by using Visual Studio and the Azure IoT Edge Tools extension. 创建项目模板后,你将添加新代码,使模块根据其报告属性筛选出消息。After you create a project template, you'll add new code so that the module filters out messages based on their reported properties.

创建新项目Create a new project

创建可以使用自己的代码进行自定义的 C 解决方案模板。Create a C solution template that you can customize with your own code.

  1. 打开 Visual Studio 2019,然后选择“创建新项目”。Open Visual Studio 2019, and then select Create New Project.

  2. 在“创建新项目”窗格上,搜索“IoT Edge”,然后在结果列表中,选择“Azure IoT Edge (Windows amd64)”项目 。On the Create a new project pane, search for IoT Edge and then, in the results list, select the Azure IoT Edge (Windows amd64) project.

    IoT Edge“创建新项目”窗格的屏幕截图。

  3. 选择“下一页”。Select Next.

    “配置新项目”窗格随即打开。The Configure your new project pane opens.

    “配置新项目”窗格的屏幕截图。

  4. 在“配置新项目”窗格中,重命名项目和解决方案,使名称更具描述性,例如 CTutorialApp 。On the Configure your new project pane, rename the project and solution to something more descriptive, such as CTutorialApp.

  5. 选择“创建”来创建项目。Select Create to create the project.

    “添加模块”窗格随即打开。The Add Module pane opens.

    用于配置项目的“添加模块”窗格的屏幕截图。

  6. 在“配置新项目”页上执行以下操作:On the Configure your new project page, do the following:

    a.a. 在左侧窗格中,选择“C 模块”模板。On the left pane, select the C Module template.
    b.b. 在“模块名称”框中,输入“CModule” 。In the Module Name box, enter CModule.
    c.c. 在“存储库 URL”框中,将 localhost:5000 替换为 Azure 容器注册表中的“登录服务器”值,格式如下:<registry name>.azurecr.io/cmodule In the Repository Url box, replace localhost:5000 with the Login server value from your Azure container registry, in the following format: <registry name>.azurecr.io/cmodule

    备注

    映像存储库包含容器注册表的名称和容器映像的名称。An image repository includes the name of your container registry and the name of your container image. 系统已基于模块项目名称值预先填充容器映像。Your container image is prepopulated from the module project-name value. 可以在 Azure 门户的容器注册表的“概述”页面中检索登录服务器。You can retrieve the login server from the overview page of your container registry in the Azure portal.

  7. 选择“添加” 以创建项目。Select Add to create the project.

添加注册表凭据Add your registry credentials

部署清单与 IoT Edge 运行时共享容器注册表的凭据。The deployment manifest shares the credentials for your container registry with the IoT Edge runtime. 此运行时需要这些凭据才能将专用映像拉取到 IoT Edge 设备中。The runtime needs these credentials to pull your private images onto the IoT Edge device. 使用 Azure 容器注册表的“访问密钥”部分提供的凭据。 Use the credentials from the Access keys section of your Azure container registry.

  1. 在 Visual Studio 解决方案资源管理器中打开 deployment.template.json 文件。In Visual Studio Solution Explorer, open the deployment.template.json file.

  2. 在 $edgeAgent 所需属性中查找 registryCredentials 属性。Look for the registryCredentials property in the $edgeAgent desired properties. 该属性的注册表地址应使用创建项目时提供的信息自动填充。The registry address of the property should be autofilled with the information you provided when you created the project. 用户名和密码字段应包含变量名称。The username and password fields should contain variable names. 例如:For example:

    "registryCredentials": {
      "<registry name>": {
        "username": "$CONTAINER_REGISTRY_USERNAME_<registry name>",
        "password": "$CONTAINER_REGISTRY_PASSWORD_<registry name>",
        "address": "<registry name>.azurecr.cn"
      }
    }
    
  3. 在模块解决方案中打开环境 (ENV) 文件。Open the environment (ENV) file in your module solution. 默认情况下,此文件会隐藏在解决方案资源管理器中,可能需要选择“显示所有文件”按钮才能显示它。By default, the file is hidden in Solution Explorer, so you might need to select the Show All Files button to display it. 该 ENV 文件应包含与你在 deployment.template.json 文件中看到的相同的用户名和密码变量。The ENV file should contain the same username and password variables that you saw in the deployment.template.json file.

  4. 从 Azure 容器注册表中添加“用户名”和“密码”值。 Add the Username and Password values from your Azure container registry.

  5. 保存对 ENV 文件所做的更改。Save your changes to the ENV file.

使用自定义代码更新模块Update the module with custom code

默认模块代码在输入队列上接收消息,并通过输出队列传递消息。The default module code receives messages in an input queue and passes them along through an output queue. 让我们添加一些额外的代码,以便模块在将消息转发到 IoT 中心之前,在边缘处理消息。Let's add some more code so that the module processes the messages at the edge before forwarding them to your IoT hub. 更新模块,以便模块分析每条消息中的温度数据,只有在温度超过特定阈值时才将消息发送到 IoT 中心。Update the module so that it analyzes the temperature data in each message and sends the message to the IoT hub only if the temperature exceeds a certain threshold.

  1. 在此场景中,来自传感器的数据采用 JSON 格式。The data from the sensor in this scenario comes in JSON format. 若要筛选 JSON 格式的消息,请导入用于 C 的 JSON 库。本教程使用 Parson。To filter messages in JSON format, import a JSON library for C. This tutorial uses Parson.

    a.a. 下载 Parson GitHub 存储库Download the Parson GitHub repository.
    b.b. 将 parson.c 和 parson.h 文件复制到 CModule 项目中 。Copy the parson.c and parson.h files to the CModule project.
    c.c. 在 Visual Studio 中,打开 CModule 项目文件夹中的 CMakeLists.txt 文件。In Visual Studio, open the CMakeLists.txt file from the CModule project folder.
    d.d. 在文件顶部,导入名为 my_parson 的充当库的 Parson 文件。At the top of the file, import the Parson files as a library called my_parson.

    add_library(my_parson
        parson.c
        parson.h
    )
    

    e.e. my_parson 添加到 CMakeLists.txt 文件的“target_link_libraries”部分中的库列表。Add my_parson to the list of libraries in the "target_link_libraries" section of the CMakeLists.txt file.
    f.f. 保存 CMakeLists.txt 文件。Save the CMakeLists.txt file.
    g.g. 打开“CModule” > “main.c” 。Select CModule > main.c. 在 include 语句列表的底部,添加一个新的语句,以便包括适用于 JSON 支持的 parson.hAt the bottom of the list of include statements, add a new statement to include parson.h for JSON support:

    #include "parson.h"
    
  2. 在 main.c 文件中,在 messagesReceivedByInput1Queue 变量旁边添加名为 temperatureThreshold 的全局变量。In the main.c file, add a global variable called temperatureThreshold next to the messagesReceivedByInput1Queue variable. 此变量设置一个值,若要向 IoT 中心发送数据,测量的温度必须超出该值。This variable sets the value that the measured temperature must exceed for the data to be sent to your IoT hub.

    static double temperatureThreshold = 25;
    
  3. 在 main.c 中找到 CreateMessageInstance 函数。Find the CreateMessageInstance function in main.c. 将内部的 if-else 语句替换为以下代码,这将添加几行功能:Replace the inner if-else statement with the following code, which adds a few lines of functionality:

    if ((messageInstance->messageHandle = IoTHubMessage_Clone(message)) == NULL)
    {
        free(messageInstance);
        messageInstance = NULL;
    }
    else
    {
        messageInstance->messageTrackingId = messagesReceivedByInput1Queue;
        MAP_HANDLE propMap = IoTHubMessage_Properties(messageInstance->messageHandle);
        if (Map_AddOrUpdate(propMap, "MessageType", "Alert") != MAP_OK)
        {
           printf("ERROR: Map_AddOrUpdate Failed!\r\n");
        }
    }
    

    else 语句中的新代码行将一个新属性添加到消息,用于将消息标记为警报。The new lines of code in the else statement add a new property to the message, which labels the message as an alert. 此代码将所有消息标记为警报,因为仅当报告了较高的温度时,我们要添加的功能才会向 IoT 中心发送消息。This code labels all messages as alerts, because we'll add functionality that sends messages to the IoT hub only if they report high temperatures.

  4. 找到 InputQueue1Callback 函数,并将整个函数替换为以下代码。Find the InputQueue1Callback function, and replace the whole function with the following code. 此函数实现实际的消息传送筛选器。This function implements the actual messaging filter. 收到消息后,它会检查报告的温度是否超过阈值。When a message is received, it checks whether the reported temperature exceeds the threshold. 如果温度超出阈值,函数便会通过其输出队列转发消息。If the temperature does exceed the threshold, the function forwards the message through its output queue. 如果温度未超出阈值,函数会忽略该消息。If it doesn't exceed the threshold, the function ignores the message.

    static unsigned char *bytearray_to_str(const unsigned char *buffer, size_t len)
    {
        unsigned char *ret = (unsigned char *)malloc(len + 1);
        memcpy(ret, buffer, len);
        ret[len] = '\0';
        return ret;
    }
    
    static IOTHUBMESSAGE_DISPOSITION_RESULT InputQueue1Callback(IOTHUB_MESSAGE_HANDLE message, void* userContextCallback)
    {
        IOTHUBMESSAGE_DISPOSITION_RESULT result;
        IOTHUB_CLIENT_RESULT clientResult;
        IOTHUB_MODULE_CLIENT_LL_HANDLE iotHubModuleClientHandle = (IOTHUB_MODULE_CLIENT_LL_HANDLE)userContextCallback;
    
        unsigned const char* messageBody;
        size_t contentSize;
    
        if (IoTHubMessage_GetByteArray(message, &messageBody, &contentSize) == IOTHUB_MESSAGE_OK)
        {
            messageBody = bytearray_to_str(messageBody, contentSize);
        } else
        {
            messageBody = "<null>";
        }
    
        printf("Received Message [%zu]\r\n Data: [%s]\r\n",
                messagesReceivedByInput1Queue, messageBody);
    
        // Check whether the message reports temperatures that exceed the threshold
        JSON_Value *root_value = json_parse_string(messageBody);
        JSON_Object *root_object = json_value_get_object(root_value);
        double temperature;
    
        // If temperature exceeds the threshold, send to output1
        if (json_object_dotget_value(root_object, "machine.temperature") != NULL && (temperature = json_object_dotget_number(root_object, "machine.temperature")) > temperatureThreshold)
        {
            printf("Machine temperature %f exceeds threshold %f\r\n", temperature, temperatureThreshold);
            // This message should be sent to next stop in the pipeline, namely "output1".  What happens at "outpu1" is determined
            // by the configuration of the Edge routing table setup.
            MESSAGE_INSTANCE *messageInstance = CreateMessageInstance(message);
            if (NULL == messageInstance)
            {
                result = IOTHUBMESSAGE_ABANDONED;
            }
            else
            {
                printf("Sending message (%zu) to the next stage in pipeline\n", messagesReceivedByInput1Queue);
    
                clientResult = IoTHubModuleClient_LL_SendEventToOutputAsync(iotHubModuleClientHandle, messageInstance->messageHandle, "output1", SendConfirmationCallback, (void *)messageInstance);
                if (clientResult != IOTHUB_CLIENT_OK)
                {
                    IoTHubMessage_Destroy(messageInstance->messageHandle);
                    free(messageInstance);
                    printf("IoTHubModuleClient_LL_SendEventToOutputAsync failed on sending msg#=%zu, err=%d\n", messagesReceivedByInput1Queue, clientResult);
                    result = IOTHUBMESSAGE_ABANDONED;
                }
                else
                {
                    result = IOTHUBMESSAGE_ACCEPTED;
                }
            }
        }
        // If message does not exceed the threshold, do not forward
        else
        {
            printf("Not sending message (%zu) to the next stage in pipeline.\r\n", messagesReceivedByInput1Queue);
            result = IOTHUBMESSAGE_ACCEPTED;
        }
    
        messagesReceivedByInput1Queue++;
        return result;
    }
    
  5. 添加 moduleTwinCallback 函数。Add a moduleTwinCallback function. 此方法从孪生模块接收所需属性的更新,然后更新 temperatureThreshold 变量,使之匹配。This method receives updates on the desired properties from the module twin, and updates the temperatureThreshold variable to match. 所有模块都有自己的模块孪生,因此可以直接从云中配置在模块中运行的代码。All modules have their own module twin, which lets you configure the code that's running inside the module directly from the cloud.

    static void moduleTwinCallback(DEVICE_TWIN_UPDATE_STATE update_state, const unsigned char* payLoad, size_t size, void* userContextCallback)
    {
        printf("\r\nTwin callback called with (state=%s, size=%zu):\r\n%s\r\n",
            MU_ENUM_TO_STRING(DEVICE_TWIN_UPDATE_STATE, update_state), size, payLoad);
        JSON_Value *root_value = json_parse_string(payLoad);
        JSON_Object *root_object = json_value_get_object(root_value);
        if (json_object_dotget_value(root_object, "desired.TemperatureThreshold") != NULL) {
            temperatureThreshold = json_object_dotget_number(root_object, "desired.TemperatureThreshold");
        }
        if (json_object_get_value(root_object, "TemperatureThreshold") != NULL) {
            temperatureThreshold = json_object_get_number(root_object, "TemperatureThreshold");
        }
    }
    
  6. 查找 SetupCallbacksForModule 函数。Look for the SetupCallbacksForModule function. 将函数替换为以下代码,这将添加一个 else-if 语句,以检查模块孪生是否已更新。Replace the function with the following code, which adds an else-if statement to check whether the module twin has been updated.

    static int SetupCallbacksForModule(IOTHUB_MODULE_CLIENT_LL_HANDLE iotHubModuleClientHandle)
    {
        int ret;
    
        if (IoTHubModuleClient_LL_SetInputMessageCallback(iotHubModuleClientHandle, "input1", InputQueue1Callback, (void*)iotHubModuleClientHandle) != IOTHUB_CLIENT_OK)
        {
            printf("ERROR: IoTHubModuleClient_LL_SetInputMessageCallback(\"input1\")..........FAILED!\r\n");
            ret = MU_FAILURE;
        }
        else if (IoTHubModuleClient_LL_SetModuleTwinCallback(iotHubModuleClientHandle, moduleTwinCallback, (void*)iotHubModuleClientHandle) != IOTHUB_CLIENT_OK)
        {
            printf("ERROR: IoTHubModuleClient_LL_SetModuleTwinCallback(default)..........FAILED!\r\n");
            ret = MU_FAILURE;
        }
        else
        {
            ret = 0;
        }
    
        return ret;
    }
    
  7. 保存 main.c 文件。Save the main.c file.

  8. 打开 deployment.template.json 文件。Open the deployment.template.json file.

  9. 将 CModule 模块孪生添加到部署清单。Add the CModule module twin to the deployment manifest. moduleContent 节底部 $edgeHub 模块孪生后插入以下 JSON 内容:Insert the following JSON content at the bottom of the moduleContent section, after the $edgeHub module twin:

    "CModule": {
        "properties.desired":{
            "TemperatureThreshold":25
        }
    }
    

    屏幕截图,显示正在添加到部署模板的模块孪生。

  10. 保存 deployment.template.json 文件。Save the deployment.template.json file.

生成并推送模块Build and push your module

在上一部分,你已创建一个 IoT Edge 解决方案并将代码添加到了 CModule,该函数会筛选出其中报告的计算机温度低于可接受阈值的消息。In the preceding section, you created an IoT Edge solution and added code to CModule to filter out messages where the reported machine temperature is below the acceptable threshold. 现在需将解决方案生成为容器映像并将其推送到容器注册表。Now you need to build the solution as a container image and push it to your container registry.

登录 DockerSign in to Docker

向开发计算机上的 Docker 提供容器注册表凭据,以便它可以推送要存储在注册表中的容器映像。Provide your container registry credentials to Docker on your development machine so that it can push your container image to be stored in the registry.

  1. 打开 PowerShell 或命令提示符窗口。Open PowerShell or a Command Prompt window.

  2. 使用创建注册表后保存的 Azure 容器注册表凭据登录 Docker。Sign in to Docker with the Azure container registry credentials that you saved after you created the registry.

    docker login -u <ACR username> -p <ACR password> <ACR login server>
    

    你可能会收到一条建议使用 --password-stdin 的安全警告。You might receive a security warning that recommends the use of --password-stdin. 虽然建议将其作为生产方案的最佳做法,但这不在本教程的讨论范围内。Although we recommend this as a best practice for production scenarios, it's outside the scope of this tutorial. 有关详细信息,请参阅 docker login 参考For more information, see the docker login reference.

生成并推送Build and push

开发计算机现在可以访问容器注册表,IoT Edge 设备也将拥有相应访问权限。Your development machine now has access to your container registry, and your IoT Edge devices will too. 现在可将项目代码转换为容器映像。It's time to turn the project code into a container image.

  1. 在 Visual Studio 解决方案资源管理器中,右键单击要生成的项目的名称。In Visual Studio Solution Explorer, right-click the name of the project that you want to build. 默认名称是 AzureIotEdgeApp1。The default name is AzureIotEdgeApp1. 对于本教程,我们选择名称 CTutorialApp ,由于你要构建 Windows 模块,因此扩展名应为 Windows.Amd64 。For this tutorial, we chose the name CTutorialApp and, because you're building a Windows module, the extension should be Windows.Amd64.

  2. 选择“生成并推送 IoT Edge 模块”。Select Build and Push IoT Edge Modules.

    “生成并推送”命令会启动三项操作:The build and push command starts three operations:

    • 首先,它在名为 config 的解决方案中创建一个新文件夹,其中包含完整的部署清单。First, it creates a new folder in the solution named config, which holds the full deployment manifest. 它是根据部署模板和其他解决方案文件中的信息生成的。It's built from information in the deployment template and other solution files.
    • 其次,它会运行 docker build,以基于目标体系结构的相应 Dockerfile 生成容器映像。Second, it runs docker build to build the container image, based on the appropriate Dockerfile for your target architecture.
    • 最后,它会运行 docker push,以将映像存储库推送到容器注册表。Finally, it runs docker push to push the image repository to your container registry.

    首次执行此过程可能需要几分钟时间,但下次运行命令时速度将会更快。This process might take several minutes the first time, but it will go faster the next time you run the commands.

将模块部署到设备Deploy modules to the device

使用 Visual Studio Cloud Explorer 和 Azure IoT Edge Tools 扩展将模块项目部署到 IoT Edge 设备。Use Visual Studio Cloud Explorer and the Azure IoT Edge Tools extension to deploy the module project to your IoT Edge device. 你已经为方案准备了部署清单,即 config 文件夹中的 deployment.windows-amd64.json 文件 。You've already prepared a deployment manifest for your scenario, the deployment.windows-amd64.json file in the config folder. 现在需要做的就是选择一个设备来接收部署。All you need to do now is select a device to receive the deployment.

确保 IoT Edge 设备已启动并运行。Make sure that your IoT Edge device is up and running.

  1. 在 Visual Studio Cloud Explorer 中,展开资源以查看 IoT 设备列表。In Visual Studio Cloud Explorer, expand the resources to view your list of IoT devices.

  2. 右键单击要接收部署的 IoT Edge 设备的名称。Right-click the name of the IoT Edge device that you want to receive the deployment.

  3. 选择“创建部署”。Select Create Deployment.

  4. 在 Visual Studio 文件资源管理器中,选择解决方案的 config 文件夹中的 deployment.windows-amd64.json 文件 。In Visual Studio File Explorer, select the deployment.windows-amd64.json file in the config folder of your solution.

  5. 刷新 Cloud Explorer,以查看设备下面列出的已部署模块。Refresh Cloud Explorer to view the deployed modules that are listed under your device.

查看生成的数据View generated data

将部署清单应用到 IoT Edge 设备以后,设备上的 IoT Edge 运行时就会收集新的部署信息并开始在其上执行操作。After you apply the deployment manifest to your IoT Edge device, the IoT Edge runtime on the device collects the new deployment information and starts executing on it. 在设备上运行但未包括在部署清单中的任何模块都会停止。Any modules that are running on the device but not included in the deployment manifest are stopped. 设备中缺失的任何模块都会启动。Any modules that are missing from the device are started.

可以使用 IoT Edge Tools 扩展查看抵达 IoT 中心的消息。You can use the IoT Edge Tools extension to view messages as they arrive at your IoT hub.

  1. 在 Visual Studio Cloud Explorer 中,选择 IoT Edge 设备的名称。In Visual Studio Cloud Explorer, select the name of your IoT Edge device.

  2. 在“操作”列表中,选择“开始监视内置事件终结点”。 In the Actions list, select Start Monitoring Built-in Event Endpoint.

  3. 查看抵达 IoT 中心的消息。View the messages that are arriving at your IoT hub. 消息可能需要在一段时间后才会抵达,因为 IoT Edge 设备必须接收其新部署并启动所有模块。It might take a while for the messages to arrive, because the IoT Edge device has to receive its new deployment and start all the modules. 对 CModule 代码所做的更改必须等到计算机温度达到 25 度,然后才能发送消息。The changes to the CModule code must wait until the machine temperature reaches 25 degrees before the messages can be sent. 此代码还会将消息类型“警报”添加到指示已达到该温度阈值的任何消息。The code also adds the message type Alert to any messages that reach that temperature threshold.

    显示抵达 IoT 中心的消息的“输出”窗口的屏幕截图。

编辑模块孪生Edit the module twin

你已使用 CModule 模块孪生将温度阈值设置为 25 度。You used the CModule module twin to set the temperature threshold at 25 degrees. 可以使用模块孪生来更改功能,而无需更新模块代码。You can use the module twin to change the functionality without having to update the module code.

  1. 在 Visual Studio 中打开 deployment.windows-amd64.json 文件。In Visual Studio, open the deployment.windows-amd64.json file.

    不要打开 deployment.template 文件 。Do not open the deployment.template file. 如果在解决方案资源管理器中的 config 文件内未看到部署清单,请在解决方案资源管理器工具栏中选择“显示所有文件”图标。If you don't see the deployment manifest in the config file in Solution Explorer, select the Show all files icon in the Solution Explorer toolbar.

  2. 查找 CModule 孪生,将 temperatureThreshold 参数的值更改为比上次报告的温度高出 5 到 10 度的新温度。Look for the CModule twin, and change the value of the temperatureThreshold parameter to a new temperature that's 5 to 10 degrees higher than the latest reported temperature.

  3. 保存 deployment.windows-amd64.json 文件。Save the deployment.windows-amd64.json file.

  4. 再次按照部署说明操作,将更新的部署清单应用到设备。Follow the deployment instructions again to apply the updated deployment manifest to your device.

  5. 监视传入的设备到云消息。Monitor the incoming device-to-cloud messages. 在达到新的温度阈值之前,消息会停止发送。The messages should stop until the new temperature threshold is reached.

清理资源Clean up resources

如果打算继续学习下一篇建议的文章,则可以保留并重复使用在本教程中创建的资源和配置。If you plan to continue to the next recommended article, you can keep and reuse the resources and configurations that you created in this tutorial. 还可以继续使用相同的 IoT Edge 设备作为测试设备。You can also keep using the same IoT Edge device as a test device.

否则,为避免产生费用,你可以删除此处使用的本地配置和 Azure 资源。Otherwise, to avoid incurring charges, you can delete the local configurations and the Azure resources that you used here.

删除 Azure 资源Delete Azure resources

删除 Azure 资源和资源组的操作不可逆。Deleting Azure resources and resource groups is irreversible. 请确保不要意外删除错误的资源组或资源。Make sure that you don't accidentally delete the wrong resource group or resources. 如果在现有的包含要保留资源的资源组中创建了 IoT 中心,请只删除 IoT 中心资源本身,而不要删除资源组。If you created the IoT hub inside an existing resource group that has resources that you want to keep, delete only the IoT hub resource itself, instead of deleting the resource group.

若要删除资源,请执行以下操作:To delete the resources:

  1. 登录到 Azure 门户,然后选择“资源组”。 Sign in to the Azure portal and select Resource groups.

  2. 选择包含 IoT Edge 测试资源的资源组的名称。Select the name of the resource group that contains your IoT Edge test resources.

  3. 查看包含在资源组中的资源的列表。Review the list of resources contained in your resource group. 若要删除这一切,可以选择“删除资源组”。 If you want to delete all of them, you can select Delete resource group. 如果只需删除部分内容,可以单击要单独删除的每个资源。If you want to delete only some of them, you can click into each resource to delete them individually.

后续步骤Next steps

在本教程中,你已创建一个 IoT Edge 模块,其中包含用于筛选 IoT Edge 设备生成的原始数据的代码。In this tutorial, you created an IoT Edge module with code to filter raw data that's generated by your IoT Edge device.

若要了解如何借助 Azure IoT Edge 部署 Azure 云服务以在边缘位置处理和分析数据,请继续学习后续教程。To learn how Azure IoT Edge can help you deploy Azure cloud services to process and analyze data at the edge, continue on to the next tutorials.