Учебник. Разработка модулей IoT Edge на C# с использованием контейнеров Windows

Область применения:да значок IoT Edge 1.1

Важно!

IoT Edge 1.1 дата окончания поддержки — 13 декабря 2022 г. Чтобы получить сведения о поддержке определенного продукта, службы, технологии или API, перейдите на страницу Политика жизненного цикла поддержки Майкрософт. Дополнительные сведения об обновлении до последней версии IoT Edge см. в разделе Обновление IoT Edge.

В этой статье показано, как разрабатывать и развертывать код C# на устройствах Windows с Azure IoT Edge с помощью Visual Studio.

Примечание

IoT Edge 1.1 LTS — это последний канал выпусков, который поддерживает контейнеры Windows. Начиная с версии 1.2, контейнеры Windows не поддерживаются. Мы рекомендуем вам использовать IoT Edge для Linux в Windows для выполнения IoT Edge на устройствах Windows.

Вы можете использовать модули Azure IoT Edge для развертывания кода, который реализует бизнес-логику непосредственно на устройствах IoT Edge. В этом руководстве рассматриваются создание и развертывание модуля IoT Edge, который фильтрует данные датчика.

В этом руководстве описано следующее:

  • Создать модуль IoT Edge на основе пакета SDK C# с помощью Visual Studio.
  • Использовать Visual Studio и Docker для создания образа Docker и его публикации в реестре.
  • Развертывать модуль на устройстве IoT Edge.
  • Просматривать сформированные данные.

Модуль IoT Edge, создаваемый в этом руководстве, фильтрует данные температуры, которые создаются устройством. Он отправляет сообщения в потоке, только если температура превышает заданный порог. Такой тип пограничного анализа удобен для сокращения объема данных, передаваемых в облако и сохраняемых в нем.

Если у вас еще нет подписки Azure, создайте бесплатную учетную запись Azure, прежде чем начать работу.

Предварительные требования

В этом учебнике показано, как разработать модуль на языке C# с помощью Visual Studio 2019 и развернуть его на устройстве Windows. Если вы разрабатываете модули с использованием контейнеров Linux, перейдите к статье Разработка модулей IoT Edge на C# с использованием контейнеров Linux.

В следующей таблице приведены возможные варианты для разработки и развертывания модулей C# с использованием контейнеров Windows:

C# Visual Studio Code Visual Studio 2017 и 2019
Разработка Windows AMD64 Разработка модулей C# для WinAMD64 в Visual Studio Code Разработка модулей C# для WinAMD64 в Visual Studio
Отладка Windows AMD64 Отладка модулей C# для WinAMD64 в Visual Studio

Прежде чем начинать работу с этим руководством, настройте среду разработки, как описано в статье Разработка модулей IoT Edge с использованием контейнеров Windows. После этого среда будет содержать следующие необходимые компоненты:

Совет

Если вы используете Visual Studio 2017 (15.7 или более поздней версии), скачайте и установите Azure IoT Edge Tools для Visual Studio 2017 из Visual Studio Marketplace.

Создание проекта модуля

В этом разделе описывается создание проекта модуля IoT Edge с использованием Visual Studio и расширения Azure IoT Edge Tools. Создав шаблон проекта, добавьте новый код, чтобы модуль фильтровал сообщения по их сообщаемым свойствам.

Создание проекта

Расширение Azure IoT Edge Tools предоставляет шаблоны проектов для всех поддерживаемых языков модулей IoT Edge в Visual Studio. Эти шаблоны содержат все файлы и код, необходимые для развертывания рабочего модуля для тестирования IoT Edge. Они также могут послужить отправной точкой путем их настройки с помощью собственной бизнес-логики.

  1. Откройте Visual Studio 2019 и выберите Создать проект.

  2. В области Создание нового проекта введите IoT Edge для поиска, а затем в списке результатов выберите проект Azure IoT Edge (Windows AMD64) .

    Снимок экрана: область

  3. Выберите Далее.

    Откроется область Настроить новый проект.

    Снимок экрана: область

  4. В области Настроить новый проект переименуйте проект и решение, указав описательное имя, например CSharpTutorialApp.

  5. Выберите Создать, чтобы создать проект.

    Откроется область Добавление модуля.

    Снимок экрана: область

  6. На странице Настроить новый проект сделайте следующее:

    а. В области слева выберите шаблон Модуль С# .
    b. В поле Имя модуля введите CSharpModule.
    c. В поле URL-адрес репозитория замените localhost:5000 на значение сервера входа из реестра контейнеров Azure в следующем формате: <registry name>.azurecr.io/csharpmodule.

    Примечание

    Репозиторий изображений включает в себя имя реестра контейнеров и имя образа контейнера. Образ контейнера предварительно заполняется значением имени проекта модуля. Вы можете узнать значение сервера входа на странице "Обзор" реестра контейнеров на портале Azure.

  7. Нажмите кнопку Добавить, чтобы создать проект.

Добавление учетных данных реестра

Манифест развертывания совместно использует учетные данные для реестра контейнеров со средой выполнения IoT Edge. Среде выполнения нужны эти учетные данные, чтобы извлечь частный образ на устройство IoT Edge. Используйте учетные данные из раздела Ключи доступа в реестре контейнеров Azure.

  1. В Обозревателе решений Visual Studio откройте файл deployment.template.json.

  2. Найдите свойство registryCredentials в требуемых свойствах $edgeAgent. Адрес реестра свойства должен быть автоматически заполнен данными, которые вы указывали при создании проекта. Поля "имя пользователя" и "пароль" должны содержать имена переменных. Пример:

    "registryCredentials": {
      "<registry name>": {
        "username": "$CONTAINER_REGISTRY_USERNAME_<registry name>",
        "password": "$CONTAINER_REGISTRY_PASSWORD_<registry name>",
        "address": "<registry name>.azurecr.io"
      }
    }
    
  3. Откройте файл среды (ENV) в решении модуля. По умолчанию он скрыт в Обозревателе решений. Чтобы отобразить его, нажмите кнопку Показать все файлы. ENV-файл должен содержать те же переменные имени пользователя и пароля, которые вы видели в файле deployment.template.json.

  4. Добавьте значения имени пользователя и пароля, скопированные из реестра контейнеров Azure.

  5. Сохраните изменения в ENV-файле.

Обновление модуля с помощью пользовательского кода

Код стандартного модуля получает сообщения из очереди входящих сообщений и передает их через очередь исходящих сообщений. Давайте добавим еще немного кода, чтобы модуль обрабатывал сообщения на границе до передачи в Центр Интернета вещей. Обновите модуль так, чтобы он анализировал данные о температуре, получаемые в каждом сообщении, и отправлял в центр Интернета вещей только сообщения со сведениями о том, что температура превышает определенный порог.

  1. В Visual Studio выберите CSharpModule>Program.cs.

  2. В верхней части пространства имен CSharpModule добавьте три инструкции для типов, которые будут использоваться позже.

    using System.Collections.Generic;     // For KeyValuePair<>
    using Microsoft.Azure.Devices.Shared; // For TwinCollection
    using Newtonsoft.Json;                // For JsonConvert
    
  3. Добавьте переменную temperatureThreshold к классу Program после переменной счетчика. Для переменной temperatureThreshold указывается значение измеренной температуры, при превышении которого данные отправляются в Центр Интернета вещей.

    static int temperatureThreshold { get; set; } = 25;
    
  4. Добавьте классы MessageBody, Machine и Ambient к классу Program после объявления переменных. Эти классы определяют ожидаемую схему текста входящего сообщения.

    class MessageBody
    {
        public Machine machine {get;set;}
        public Ambient ambient {get; set;}
        public string timeCreated {get; set;}
    }
    class Machine
    {
        public double temperature {get; set;}
        public double pressure {get; set;}
    }
    class Ambient
    {
        public double temperature {get; set;}
        public int humidity {get; set;}
    }
    
  5. Найдите метод Init. Этот метод создает и настраивает объект ModuleClient, позволяющий модулю подключаться к локальной среде выполнения Azure IoT Edge для отправки и получения сообщений. Этот код также регистрирует обратный вызов для получения сообщений из центра IoT Edge через конечную точку input1.

    Замените весь метод Init приведенным ниже кодом.

    static async Task Init()
    {
        AmqpTransportSettings amqpSetting = new AmqpTransportSettings(TransportType.Amqp_Tcp_Only);
        ITransportSettings[] settings = { amqpSetting };
    
        // Open a connection to the Edge runtime.
        ModuleClient ioTHubModuleClient = await ModuleClient.CreateFromEnvironmentAsync(settings);
        await ioTHubModuleClient.OpenAsync();
        Console.WriteLine("IoT Hub module client initialized.");
    
        // Read the TemperatureThreshold value from the module twin's desired properties.
        var moduleTwin = await ioTHubModuleClient.GetTwinAsync();
        await OnDesiredPropertiesUpdate(moduleTwin.Properties.Desired, ioTHubModuleClient);
    
        // Attach a callback for updates to the module twin's desired properties.
        await ioTHubModuleClient.SetDesiredPropertyUpdateCallbackAsync(OnDesiredPropertiesUpdate, null);
    
        // Register a callback for messages that are received by the module.
        await ioTHubModuleClient.SetInputMessageHandlerAsync("input1", FilterMessages, ioTHubModuleClient);
    }
    

    Этот обновленный метод Init по-прежнему устанавливает подключение к среде выполнения IoT Edge с помощью ModuleClient, а также добавляет новые функции. Он считывает требуемые свойства двойника модуля, чтобы получить значение temperatureThreshold. Затем он создает обратный вызов, который прослушивает все будущие обновления требуемых свойств двойника модуля. С помощью этого обратного вызова можно удаленно обновить пороговое значение температуры в двойнике модуля, и эти изменения будут включены в модуль.

    Обновленный метод Init также изменяет существующий метод SetInputMessageHandlerAsync. В примере кода входящие сообщения на input1 обрабатываются с помощью функции PipeMessage. Но нам нужно изменить ее на функцию FilterMessages, которую создадим на следующих этапах.

  6. Добавьте новый метод onDesiredPropertiesUpdate к классу Program. Этот метод принимает изменения требуемых свойств из двойника модуля и соответствующим образом изменяет переменную temperatureThreshold. У каждого модуля есть собственный модуль-двойник, что позволяет настроить код, выполняемый в модуле, непосредственно из облака.

    static Task OnDesiredPropertiesUpdate(TwinCollection desiredProperties, object userContext)
    {
        try
        {
            Console.WriteLine("Desired property change:");
            Console.WriteLine(JsonConvert.SerializeObject(desiredProperties));
    
            if (desiredProperties["TemperatureThreshold"]!=null)
                temperatureThreshold = desiredProperties["TemperatureThreshold"];
    
        }
        catch (AggregateException ex)
        {
            foreach (Exception exception in ex.InnerExceptions)
            {
                Console.WriteLine();
                Console.WriteLine("Error when receiving desired property: {0}", exception);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine();
            Console.WriteLine("Error when receiving desired property: {0}", ex.Message);
        }
        return Task.CompletedTask;
    }
    
  7. Удалите пример метода PipeMessage и замените его новым методом FilterMessages. Этот метод вызывается каждый раз, когда модуль получает сообщение из центра IoT Edge. Он отфильтровывает сообщения о температуре ниже порогового значения, настроенного с помощью двойника модуля. Этот метод также добавляет свойство MessageType в сообщение со значением Alert.

    static async Task<MessageResponse> FilterMessages(Message message, object userContext)
    {
        var counterValue = Interlocked.Increment(ref counter);
        try
        {
            ModuleClient moduleClient = (ModuleClient)userContext;
            var messageBytes = message.GetBytes();
            var messageString = Encoding.UTF8.GetString(messageBytes);
            Console.WriteLine($"Received message {counterValue}: [{messageString}]");
    
            // Get the message body.
            var messageBody = JsonConvert.DeserializeObject<MessageBody>(messageString);
    
            if (messageBody != null && messageBody.machine.temperature > temperatureThreshold)
            {
                Console.WriteLine($"Machine temperature {messageBody.machine.temperature} " +
                    $"exceeds threshold {temperatureThreshold}");
                using(var filteredMessage = new Message(messageBytes))
                {
                    foreach (KeyValuePair<string, string> prop in message.Properties)
                    {
                        filteredMessage.Properties.Add(prop.Key, prop.Value);
                    }
    
                    filteredMessage.Properties.Add("MessageType", "Alert");
                    await moduleClient.SendEventAsync("output1", filteredMessage);
                }
            }
    
            // Indicate that the message treatment is completed.
            return MessageResponse.Completed;
        }
        catch (AggregateException ex)
        {
            foreach (Exception exception in ex.InnerExceptions)
            {
                Console.WriteLine();
                Console.WriteLine("Error in sample: {0}", exception);
            }
            // Indicate that the message treatment is not completed.
            var moduleClient = (ModuleClient)userContext;
            return MessageResponse.Abandoned;
        }
        catch (Exception ex)
        {
            Console.WriteLine();
            Console.WriteLine("Error in sample: {0}", ex.Message);
            // Indicate that the message treatment is not completed.
            ModuleClient moduleClient = (ModuleClient)userContext;
            return MessageResponse.Abandoned;
        }
    }
    
  8. Сохраните файл Program.cs.

  9. Откройте файл deployment.template.json в папке решения IoT Edge. Этот файл указывает агенту IoT Edge на модуль для развертывания, а центру IoT Edge на то, как маршрутизировать сообщения между ними. В этом случае развертываемыми модулями являются SimulatedTemperatureSensor и CSharpModule.

  10. Добавьте двойник модуля CSharpModule в манифест развертывания. Вставьте следующее содержимое JSON в нижней части раздела modulesContent после двойника модуля $edgeHub:

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

    Снимок экрана: двойник модуля, добавляемый в шаблон развертывания.

  11. Сохраните файл deployment.template.json.

Сборка и отправка модуля

В предыдущем разделе показано, как создать решение IoT Edge и добавить в CSharpModule код для фильтрации сообщений, в которых указана температура компьютера ниже допустимого порога. Теперь необходимо создать решение в качестве образа контейнера и передать его в реестр контейнеров.

Вход в Docker

  1. Используйте следующую команду, чтобы войти в Docker на компьютере разработки. Выполните вход в систему, используя имя пользователя, пароль и сервер входа из реестра контейнеров Azure. Вы можете получить эти значения в разделе Ключи доступа в разделе реестра на портале Azure.

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

    Возможно, появится предупреждение системы безопасности, в котором рекомендуется использовать --password-stdin. Для рабочих сценариев это лучший вариант, но мы не будем рассматривать его в этом руководстве. Дополнительные сведения см. в описании команды docker login в справочнике.

Создание и отправка

  1. В Обозревателе решений Visual Studio щелкните правой кнопкой мыши имя проекта, который нужно скомпилировать. Имя по умолчанию — AzureIotEdgeApp1, и так как вы создаете модуль Windows, должно быть расширение Windows.Amd64.

  2. Выберите Build and Push IoT Edge Modules (Создание и отправка модулей IoT Edge).

    Эта команда сборки и отправки запускает три операции.

    • Во-первых, она создает в решении новую папку с именем config, содержащую полный манифест развертывания на основе информации в шаблоне развертывания и других файлах решения.
    • Во-вторых, выполняется docker build для сборки образа контейнера на основе подходящего файла Dockerfile для целевой архитектуры.
    • В-третьих, выполняется docker push для отправки репозитория образа в реестр контейнеров.

    В первый раз выполнение этого процесса может занять несколько минут, но при следующем запуске команд он выполняется быстрее.

Развертывание модулей на устройстве

Разверните проект модуля на устройство IoT Edge с помощью Visual Studio Cloud Explorer и расширения Azure IoT Edge Tools. У вас уже есть манифест развертывания, подготовленный для вашего сценария (файл deployment.windows-amd64.json в папке config). Теперь вам осталось выбрать устройство для получения развертывания.

Убедитесь, что устройство IoT Edge работает.

  1. В Visual Studio Cloud Explorer разверните ресурсы, чтобы увидеть список устройств Интернета вещей.

  2. Щелкните правой кнопкой мыши имя устройства IoT Edge, на котором необходимо выполнить развертывание.

  3. Выберите Создать развертывание.

  4. В проводнике Visual Studio выберите файл deployment.windows-amd64.json в папке config решения.

  5. Обновите Cloud Explorer, чтобы отобразился список развернутых модулей для устройства.

Просмотр сформированных данных

Когда вы примените манифест развертывания к устройству IoT Edge, в среде выполнения IoT Edge на устройстве начнется сбор сведений о новом развертывании и выполнение операций. Работа всех выполняющихся на устройстве модулей, которые не включены в манифест развертывания, будет остановлена. А модули, которых нет на устройстве, будут запущены.

Расширение IoT Edge Tools можно использовать для просмотра сообщений по мере их поступления в центр Интернета вещей.

  1. В Visual Studio Cloud Explorer выберите имя устройства IoT Edge.

  2. Из списка Actions (Действия) выберите Start Monitoring Built-in Event Endpoint (Начать мониторинг встроенной конечной точки событий).

  3. Просмотрите сообщения, поступающие в центр Интернета вещей. Для поступления сообщений может потребоваться некоторое время, так как устройство IoT Edge должно сначала получить новое развертывание и запустить все модули. После этого измененный нами код CSharpModule ожидает, пока температура компьютера не достигнет 25 градусов, и лишь затем отправляет сообщения. Код также присваивает тип Оповещение всем сообщениям со сведениями о достижении порога температуры.

    Снимок экрана: окно вывода, в котором отображаются сообщения, поступающие в центр Интернета вещей.

Изменение двойника модуля

Мы использовали двойник модуля CSharpModule, чтобы задать порог температуры 25 градусов. С помощью двойника модуля вы можете изменять функциональные возможности без необходимости обновлять код модуля.

  1. В Visual Studio откройте файл deployment.windows-amd64.json.

    Не открывайте файл deployment.template. Если вы не видите манифест развертывания в файле config в Обозревателе решений, щелкните значок Показать все файлы на панели инструментов Обозревателя.

  2. Найдите двойник модуля CSharpModule и измените значение параметра temperatureThreshold на новое, которое будет на 5–10 градусов выше, чем последнее полученное значение температуры.

  3. Сохраните файл deployment.windows-amd64.json.

  4. Выполните шаги по развертыванию еще раз, чтобы применить к устройству обновленный манифест развертывания.

  5. Выполните мониторинг сообщений, поступающих с устройства в облако. Поток сообщений должен быть приостановлен, пока не будет достигнут новый порог температуры.

Очистка ресурсов

Если вы планируете перейти к следующей рекомендуемой статье, можно сохранить созданные и повторно используемые ресурсы и конфигурации, с которыми вы работали в этом руководстве. Это же устройство IoT Edge также можно использовать в качестве тестового устройства.

В противном случае вы можете удалить локальные конфигурации и ресурсы Azure, с которыми вы работали в этом руководстве, чтобы избежать расходов.

Удаление ресурсов Azure

Удаление ресурсов Azure и групп ресурсов является необратимым. Будьте внимательны, чтобы случайно не удалить не ту группу ресурсов или не те ресурсы. Если вы создали центр Интернета вещей в группе ресурсов, содержащей ресурсы, которые нужно сохранить, удалите только ресурс Центра Интернета вещей, не удаляя всю группу ресурсов.

Удаление ресурсов:

  1. Войдите на портал Azure и щелкните Группы ресурсов.

  2. Выберите группу ресурсов, содержащую тестовые ресурсы IoT Edge.

  3. Просмотрите список ресурсов, содержащихся в группе ресурсов. Если вы хотите удалить их все, щелкните Удалить группу ресурсов. Если вы хотите удалить только некоторые из них, щелкните нужные ресурсы отдельно.

Дальнейшие действия

В этом руководстве вы создали модуль IoT Edge с кодом для фильтрации необработанных данных, созданных устройством IoT Edge.

Перейдите к следующим руководствам, чтобы узнать, как Azure IoT Edge поможет развернуть облачные службы Azure для обработки и анализа данных на пограничном устройстве.