Udostępnij za pośrednictwem


Samouczek: tworzenie modułów IoT Edge języka C# przy użyciu kontenerów systemu Windows

Dotyczy ikony:yes IoT Edge 1.1

Ważne

IoT Edge 1.1 data zakończenia wsparcia wynosiła 13 grudnia 2022 r. Zapoznaj się z cyklem życia produktów firmy Microsoft, aby uzyskać informacje na temat sposobu obsługi tego produktu lub interfejsu API albo tej usługi lub technologii. Aby uzyskać więcej informacji na temat aktualizowania do najnowszej wersji IoT Edge, zobacz Update IoT Edge.

W tym artykule przedstawiono sposób używania programu Visual Studio do tworzenia kodu w języku C# i wdrażania go na urządzeniu z systemem Windows, na którym działa usługa Azure IoT Edge.

Uwaga

IoT Edge 1.1 LTS to ostatni kanał wydania obsługujący kontenery systemu Windows. Począwszy od wersji 1.2, kontenery systemu Windows nie są obsługiwane. Rozważ użycie lub przejście do IoT Edge dla systemu Linux w systemie Windows w celu uruchomienia IoT Edge na urządzeniach z systemem Windows.

Za pomocą modułów usługi Azure IoT Edge można wdrożyć kod implementujący logikę biznesową bezpośrednio na urządzeniach IoT Edge. W tym samouczku przedstawiono sposób tworzenia i wdrażania modułu usługi IoT Edge, w którym są filtrowane dane czujnika.

Ten samouczek zawiera informacje na temat wykonywania następujących czynności:

  • Użyj programu Visual Studio, aby utworzyć moduł IoT Edge oparty na zestawie SDK języka C#.
  • Użyj programu Visual Studio i platformy Docker, aby utworzyć obraz platformy Docker i opublikować go w rejestrze.
  • Wdrażanie modułu na urządzeniu usługi IoT Edge.
  • Wyświetlanie wygenerowanych danych.

Utworzony w tym samouczku moduł usługi IoT Edge filtruje dane temperatury generowane przez urządzenie. Moduł wysyła komunikaty nadrzędne tylko wtedy, gdy temperatura przekroczy określony próg. Ten typ analizy brzegowej pomaga zmniejszyć ilość danych przekazywanych do chmury i w niej przechowywanych.

Jeśli nie masz subskrypcji platformy Azure, przed rozpoczęciem utwórz bezpłatne konto .

Wymagania wstępne

W tym samouczku pokazano, jak utworzyć moduł w języku C# przy użyciu programu Visual Studio 2019, a następnie wdrożyć go na urządzeniu z systemem Windows. Jeśli tworzysz moduły przy użyciu kontenerów systemu Linux, przejdź do pozycji Opracowywanie modułów IoT Edge języka C# przy użyciu kontenerów systemu Linux.

Aby poznać opcje tworzenia i wdrażania modułów języka C# przy użyciu kontenerów systemu Windows, zapoznaj się z następującą tabelą:

C# Visual Studio Code Visual Studio 2017 i 2019
Programowanie dla systemu Windows AMD64 Opracowywanie modułów języka C# dla winAMD64 w Visual Studio Code Tworzenie modułów języka C# dla winAMD64 w programie Visual Studio
Debugowanie systemu Windows AMD64 Debugowanie modułów języka C# dla winAMD64 w programie Visual Studio

Przed rozpoczęciem tego samouczka skonfiguruj środowisko programistyczne, postępując zgodnie z instrukcjami w samouczku Programowanie modułów IoT Edge przy użyciu kontenerów systemu Windows. Po jego ukończeniu środowisko będzie zawierać następujące wymagania wstępne:

Porada

Jeśli używasz programu Visual Studio 2017 (wersja 15.7 lub nowsza), pobierz i zainstaluj Azure IoT Edge Tools dla programu Visual Studio 2017 z witryny Visual Studio Marketplace.

Tworzenie projektu modułu

W tej sekcji utworzysz projekt modułu IoT Edge przy użyciu programu Visual Studio i rozszerzenia Azure IoT Edge Tools. Po utworzeniu szablonu projektu dodasz nowy kod, aby moduł filtrował komunikaty na podstawie ich zgłoszonych właściwości.

Tworzenie nowego projektu

Azure IoT Edge Tools udostępnia szablony projektów dla wszystkich obsługiwanych języków modułów IoT Edge w programie Visual Studio. Te szablony mają wszystkie pliki i kod, które należy wdrożyć moduł roboczy do testowania IoT Edge. Mogą one również dać punkt wyjścia do dostosowywania ich za pomocą własnej logiki biznesowej.

  1. Otwórz program Visual Studio 2019, a następnie wybierz pozycję Utwórz nowy projekt.

  2. W okienku Tworzenie nowego projektu wyszukaj IoT Edge, a następnie na liście wyników wybierz projekt Azure IoT Edge (Windows amd64).

    Zrzut ekranu przedstawiający okienko IoT Edge

  3. Wybierz opcję Dalej.

    Zostanie otwarte okienko Konfigurowanie nowego projektu .

    Zrzut ekranu przedstawiający okienko

  4. W okienku Konfigurowanie nowego projektu zmień nazwę projektu i rozwiązania na bardziej opisową, na przykład CSharpTutorialApp.

  5. Wybierz polecenie Create (Utwórz), aby utworzyć projekt.

    Zostanie otwarte okienko Dodawanie modułu .

    Zrzut ekranu przedstawiający okienko

  6. Na stronie Konfigurowanie nowego projektu wykonaj następujące czynności:

    a. W okienku po lewej stronie wybierz szablon Moduł języka C# .
    b. W polu Nazwa modułu wprowadź wartość CSharpModule.
    c. W polu Adres URL repozytorium zastąp ciąg localhost:5000 wartością serwera logowania z rejestru kontenerów platformy Azure w następującym formacie: <registry name>.azurecr.io/csharpmodule

    Uwaga

    Repozytorium obrazów zawiera nazwę rejestru kontenerów oraz nazwę obrazu kontenera. Obraz kontenera jest wstępnie wypełniany z wartości project-name modułu. Serwer logowania można pobrać ze strony przeglądu rejestru kontenerów w Azure Portal.

  7. Wybierz pozycję Dodaj , aby utworzyć projekt.

Dodawanie poświadczeń rejestru

Manifest wdrożenia udostępnia poświadczenia rejestru kontenerów za pomocą środowiska uruchomieniowego IoT Edge. Środowisko uruchomieniowe wymaga tych poświadczeń do ściągnięcia prywatnych obrazów na urządzenie usługi IoT Edge. Użyj poświadczeń z sekcji Klucze dostępu rejestru kontenerów platformy Azure.

  1. W programie Visual Studio Eksplorator rozwiązań otwórz plik deployment.template.json.

  2. Poszukaj właściwości registryCredentials we właściwościach $edgeAgent żądanych. Adres rejestru właściwości powinien zostać automatycznie wypełniony informacjami podanymi podczas tworzenia projektu. Pola nazwy użytkownika i hasła powinny zawierać nazwy zmiennych. Przykład:

    "registryCredentials": {
      "<registry name>": {
        "username": "$CONTAINER_REGISTRY_USERNAME_<registry name>",
        "password": "$CONTAINER_REGISTRY_PASSWORD_<registry name>",
        "address": "<registry name>.azurecr.io"
      }
    }
    
  3. Otwórz plik środowiska (ENV) w rozwiązaniu modułu. Domyślnie plik jest ukryty w Eksplorator rozwiązań, więc może być konieczne wybranie przycisku Pokaż wszystkie pliki, aby go wyświetlić. Plik ENV powinien zawierać te same zmienne nazwy użytkownika i hasła, które przedstawiono w pliku deployment.template.json .

  4. Dodaj wartości Nazwa użytkownika i Hasło z rejestru kontenerów platformy Azure.

  5. Zapisz zmiany w pliku ENV.

Aktualizowanie modułu przy użyciu kodu niestandardowego

Domyślny kod modułu odbiera komunikaty w kolejce wejściowej i przekazuje je przez kolejkę wyjściową. Dodajmy dodatkowy kod, aby moduł przetwarzał komunikaty na brzegu przed przekazaniem ich do centrum IoT. Zaktualizuj moduł, aby analizować dane temperatury w każdym komunikacie i wysyłać komunikat do centrum IoT tylko wtedy, gdy temperatura przekroczy określony próg.

  1. W programie Visual Studio wybierz pozycję CSharpModule>Program.cs.

  2. Na początku przestrzeni nazw CSharpModule dodaj trzy instrukcje using dla typów, które będą używane później:

    using System.Collections.Generic;     // For KeyValuePair<>
    using Microsoft.Azure.Devices.Shared; // For TwinCollection
    using Newtonsoft.Json;                // For JsonConvert
    
  3. Dodaj zmienną temperatureThreshold do klasy Program po zmiennej licznika. Zmienna temperatureThreshold ustawia wartość, którą mierzona temperatura musi przekraczać, aby dane zostały wysłane do centrum IoT.

    static int temperatureThreshold { get; set; } = 25;
    
  4. Dodaj klasy MessageBody, Machine i Ambient do klasy Program po deklaracjach zmiennych. Te klasy definiują oczekiwany schemat treści komunikatów przychodzących.

    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. Wyszukaj metodę Init . Ta metoda tworzy i konfiguruje obiekt ModuleClient, który umożliwia modułowi łączenie się z lokalnym środowiskiem uruchomieniowym usługi Azure IoT Edge w celu wysyłania i odbierania komunikatów. Kod rejestruje również wywołanie zwrotne w celu odbierania komunikatów z centrum IoT Edge za pośrednictwem punktu końcowego input1.

    Zastąp całą metodę Init następującym kodem:

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

    Ta zaktualizowana metoda Init nadal konfiguruje połączenie ze środowiskiem uruchomieniowym IoT Edge za pomocą klasy ModuleClient, ale dodaje również nowe funkcje. Odczytuje żądane właściwości bliźniaczej reprezentacji modułu, aby pobrać wartość temperatureThreshold . Następnie tworzy wywołanie zwrotne, które nasłuchuje wszelkich przyszłych aktualizacji żądanych właściwości bliźniaczej reprezentacji modułu. Dzięki temu wywołaniu zwrotne można zdalnie zaktualizować próg temperatury w bliźniaczej reprezentacji modułu, a zmiany zostaną włączone do modułu.

    Zaktualizowana metoda Init zmienia również istniejącą metodę SetInputMessageHandlerAsync . W przykładowym kodzie komunikaty przychodzące na input1 są przetwarzane za pomocą funkcji PipeMessage , ale chcemy zmienić tę funkcję, aby użyć funkcji FilterMessages , którą utworzymy w poniższych krokach.

  6. Dodaj nową metodę onDesiredPropertiesUpdate do klasy Program . Ta metoda odbiera aktualizacje żądanych właściwości z bliźniaczej reprezentacji modułu i aktualizuje zmienną temperatureThreshold w celu dopasowania. Wszystkie moduły mają swoje bliźniacze reprezentacje, dzięki czemu można skonfigurować kod działający wewnątrz modułu bezpośrednio z poziomu chmury.

    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. Usuń przykładową metodę PipeMessage i zastąp ją nową metodą FilterMessages . Ta metoda jest wywoływana za każdym razem, gdy moduł odbiera komunikat z centrum usługi IoT Edge. Filtruje komunikaty, które zgłaszają temperatury poniżej progu temperatury ustawionego za pośrednictwem bliźniaczej reprezentacji modułu. Metoda dodaje również właściwość MessageType do komunikatu z wartością ustawioną na 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. Zapisz plik Program.cs.

  9. Otwórz plik deployment.template.json w rozwiązaniu IoT Edge. Ten plik informuje agenta IoT Edge o tym, które moduły mają zostać wdrożone, i informuje centrum IoT Edge, jak kierować komunikaty między nimi. W tym miejscu moduły do wdrożenia to SimulatedTemperatureSensor i CSharpModule.

  10. Dodaj bliźniaczą reprezentację modułu CSharpModule do manifestu wdrożenia. Wstaw następującą zawartość JSON w dolnej części modulesContent sekcji po bliźniaczej reprezentacji modułu $edgeHub :

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

    Zrzut ekranu przedstawiający bliźniaczą reprezentację modułu dodaną do szablonu wdrożenia.

  11. Zapisz plik deployment.template.json.

Kompilowanie i wypychanie modułu

W poprzedniej sekcji utworzono rozwiązanie IoT Edge i dodano kod do modułu CSharpModule, aby odfiltrować komunikaty, w których zgłoszona temperatura maszyny jest poniżej akceptowalnego progu. Teraz należy skompilować to rozwiązanie jako obraz kontenera i wypchnąć go do rejestru kontenerów.

Logowanie do platformy Docker

  1. Użyj następującego polecenia, aby zalogować się do platformy Docker na maszynie dewelopera. Użyj nazwy użytkownika, hasła i serwera logowania z rejestru kontenerów platformy Azure. Te wartości można pobrać z sekcji Klucze dostępu rejestru w Azure Portal.

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

    Może zostać wyświetlone ostrzeżenie o zabezpieczeniach, które zaleca użycie elementu --password-stdin. Mimo że zalecamy to jako najlepsze rozwiązanie dla scenariuszy produkcyjnych, wykracza poza zakres tego samouczka. Aby uzyskać więcej informacji, zobacz dokumentację logowania platformy Docker.

Kompilowanie i wypychanie

  1. W programie Visual Studio Eksplorator rozwiązań kliknij prawym przyciskiem myszy nazwę projektu, który chcesz skompilować. Domyślną nazwą jest AzureIotEdgeApp1 i, ponieważ tworzysz moduł systemu Windows, rozszerzenie powinno mieć wartość Windows.Amd64.

  2. Wybierz pozycję Kompiluj i wypychaj moduły IoT Edge.

    Polecenie kompilacji i wypychania uruchamia trzy operacje:

    • Najpierw tworzy nowy folder w rozwiązaniu o nazwie config, który zawiera pełny manifest wdrożenia. Jest on tworzony na podstawie informacji w szablonie wdrożenia i innych plikach rozwiązań.
    • Po drugie uruchamia docker build polecenie w celu skompilowania obrazu kontenera na podstawie odpowiedniego pliku Dockerfile dla architektury docelowej.
    • Na koniec zostanie uruchomione polecenie docker push , aby wypchnąć repozytorium obrazów do rejestru kontenerów.

    Ten proces może potrwać kilka minut po raz pierwszy, ale będzie działać szybciej przy następnym uruchomieniu poleceń.

Wdrażanie modułów na urządzeniu

Użyj programu Visual Studio Cloud Explorer i rozszerzenia Azure IoT Edge Tools, aby wdrożyć projekt modułu na urządzeniu IoT Edge. Masz już przygotowany manifest wdrożenia dla danego scenariusza— plik deployment.windows-amd64.json w folderze config . Teraz wystarczy wybrać urządzenie, które ma otrzymać wdrożenie.

Upewnij się, że urządzenie IoT Edge jest uruchomione.

  1. W programie Visual Studio Cloud Explorer rozwiń zasoby, aby wyświetlić listę urządzeń IoT.

  2. Kliknij prawym przyciskiem myszy nazwę urządzenia IoT Edge, które chcesz odebrać wdrożenie.

  3. Wybierz pozycję Utwórz wdrożenie.

  4. W programie Visual Studio Eksplorator plików wybierz plik deployment.windows-amd64.json w folderze config rozwiązania.

  5. Odśwież program Cloud Explorer, aby wyświetlić wdrożone moduły, które są wyświetlane na urządzeniu.

Wyświetlanie wygenerowanych danych

Po zastosowaniu manifestu wdrożenia na urządzeniu IoT Edge środowisko uruchomieniowe IoT Edge na urządzeniu zbiera nowe informacje o wdrożeniu i rozpoczyna jego wykonywanie. Wszystkie moduły uruchomione na urządzeniu, ale nieuwzględnione w manifeście wdrożenia, zostaną zatrzymane. Wszystkie moduły, których brakuje na urządzeniu, są uruchamiane.

Możesz użyć rozszerzenia IoT Edge Tools do wyświetlania komunikatów po nadejściu do centrum IoT.

  1. W eksploratorze chmury programu Visual Studio wybierz nazwę urządzenia IoT Edge.

  2. Na liście Akcje wybierz pozycję Rozpocznij monitorowanie wbudowanego punktu końcowego zdarzeń.

  3. Wyświetlanie komunikatów przychodzących do centrum IoT Hub. Odebranie komunikatów może zająć trochę czasu, ponieważ urządzenie IoT Edge musi odebrać nowe wdrożenie i uruchomić wszystkie moduły. Zmiany w kodzie CSharpModule muszą czekać, aż temperatura maszyny osiągnie 25 stopni przed wysłaniem komunikatów. Kod dodaje również typ komunikatu Alert do wszystkich komunikatów, które osiągną ten próg temperatury.

    Zrzut ekranu przedstawiający okno Dane wyjściowe z komunikatami przychodzącymi do centrum IoT Hub.

Edytowanie bliźniaczej reprezentacji modułu

Użyto bliźniaczej reprezentacji modułu CSharpModule, aby ustawić próg temperatury na poziomie 25 stopni. Możesz użyć bliźniaczej reprezentacji modułu, aby zmienić funkcjonalność bez konieczności aktualizowania kodu modułu.

  1. W programie Visual Studio otwórz plik deployment.windows-amd64.json .

    Nie otwieraj pliku deployment.template. Jeśli manifest wdrożenia nie jest widoczny w pliku konfiguracji w Eksplorator rozwiązań, wybierz ikonę Pokaż wszystkie pliki na pasku narzędzi Eksplorator rozwiązań.

  2. Poszukaj bliźniaczej reprezentacji CSharpModule i zmień wartość parametru temperatureThreshold na nową temperaturę, która jest 5 do 10 stopni wyższa niż najnowsza zgłoszona temperatura.

  3. Zapisz plik deployment.windows-amd64.json .

  4. Ponownie postępuj zgodnie z instrukcjami wdrażania, aby zastosować zaktualizowany manifest wdrożenia do urządzenia.

  5. Monitoruj przychodzące komunikaty z urządzenia do chmury. Komunikaty powinny zostać zatrzymane do momentu osiągnięcia nowego progu temperatury.

Czyszczenie zasobów

Jeśli planujesz przejść do następnego zalecanego artykułu, możesz zachować i ponownie użyć zasobów i konfiguracji utworzonych w tym samouczku. Możesz także nadal używać tego samego urządzenia usługi IoT Edge jako urządzenia testowego.

W przeciwnym razie, aby uniknąć naliczania opłat, możesz usunąć konfiguracje lokalne i zasoby platformy Azure użyte w tym miejscu.

Usuwanie zasobów platformy Azure

Usuwanie zasobów i grup zasobów platformy Azure jest nieodwracalne. Uważaj, aby nie usunąć przypadkowo niewłaściwych zasobów lub niewłaściwej grupy zasobów. Jeśli centrum IoT zostało utworzone w istniejącej grupie zasobów zawierającej zasoby, które chcesz zachować, usuń tylko sam zasób centrum IoT, a nie grupę zasobów.

Aby usunąć zasoby:

  1. Zaloguj się do witryny Azure Portal, a następnie wybierz pozycję Grupy zasobów.

  2. Wybierz nazwę grupy zasobów, która zawiera zasoby testowe usługi IoT Edge.

  3. Przejrzyj listę zasobów, które znajdują się w grupie zasobów. Jeśli chcesz usunąć je wszystkie, możesz wybrać pozycję Usuń grupę zasobów. Jeśli chcesz usunąć tylko niektóre z nich, możesz kliknąć poszczególne zasoby, aby usunąć je pojedynczo.

Następne kroki

W tym samouczku został utworzony moduł usługi IoT Edge zawierający kod służący do filtrowania nieprzetworzonych danych wygenerowanych przez urządzenie usługi IoT Edge.

Aby dowiedzieć się, jak usługa Azure IoT Edge może ułatwić wdrażanie usług w chmurze platformy Azure w celu przetwarzania i analizowania danych na urządzeniach brzegowych, przejdź do następnych samouczków.