Samouczek: konfigurowanie urządzeń z poziomu usługi zaplecza

W ramach cyklu życia urządzenia może być konieczne skonfigurowanie urządzeń IoT z poziomu usługi zaplecza. Po wysłaniu żądanej konfiguracji do urządzeń chcesz również otrzymywać aktualizacje stanu i zgodności z tych urządzeń. Możesz na przykład ustawić docelowy zakres temperatur działania urządzenia lub zbierać informacje o wersji oprogramowania układowego z urządzeń.

Aby synchronizować informacje o stanie między urządzeniem i centrum IoT Hub, należy użyć bliźniaczych reprezentacji urządzenia. Bliźniacza reprezentacja urządzenia to dokument JSON skojarzony z określonym urządzeniem i przechowywany przez usługę IoT Hub w chmurze, w której można wykonywać zapytania dotyczące tego urządzenia. Bliźniacza reprezentacja urządzenia zawiera żądane właściwości, zgłaszane właściwości i tagi.

  • Żądana właściwość jest ustawiana przez aplikację zaplecza i odczytywana przez urządzenie.
  • Zgłoszona właściwość jest ustawiana przez urządzenie i odczytywana przez aplikację zaplecza.
  • Tag jest ustawiany przez aplikację zaplecza i nigdy nie jest wysyłany do urządzenia. Tagi są używane do organizowania urządzeń.

W tym samouczku pokazano, jak używać żądanych i zgłoszonych właściwości do synchronizowania informacji o stanie.

Diagram of device twins on the device and in the cloud.

Ten samouczek obejmuje wykonanie następujących zadań:

  • Utworzenie centrum IoT Hub i dodanie urządzenia testowego do rejestru tożsamości.
  • Użycie żądanych właściwości do wysyłania informacji o stanie do urządzenia symulowanego.
  • Użycie zgłaszanych właściwości do odbierania informacji o stanie z urządzenia symulowanego.

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

Wymagania wstępne

  • W tym samouczku do tworzenia zasobów w chmurze jest używany interfejs wiersza polecenia platformy Azure. Jeśli masz już centrum IoT z zarejestrowanym w nim urządzeniem, możesz pominąć te kroki. Istnieją dwa sposoby uruchamiania poleceń interfejsu wiersza polecenia:

  • Dwie przykładowe aplikacje uruchamiane w tym samouczku zostały napisane przy użyciu Node.js. Potrzebujesz Node.js wersji 10.x.x lub nowszej na komputerze deweloperskim.

    • Możesz pobrać środowisko Node.js dla wielu platform ze strony nodejs.org.

    • Możesz sprawdzić bieżącą wersję środowiska Node.js na komputerze deweloperskim przy użyciu następującego polecenia:

      node --version
      
  • Sklonuj lub pobierz przykładowy projekt Node.js z przykładów usługi Azure IoT dla Node.js.

  • Upewnij się, że port 8883 jest otwarty w zaporze. Przykład urządzenia w tym samouczku używa protokołu MQTT, który komunikuje się za pośrednictwem portu 8883. Ten port może zostać zablokowany w niektórych środowiskach sieci firmowych i edukacyjnych. Aby uzyskać więcej informacji i sposobów obejścia tego problemu, zobacz Połączenie do usługi IoT Hub (MQTT).

Konfigurowanie zasobów platformy Azure

Do ukończenia czynności z tego samouczka niezbędna jest subskrypcja platformy Azure zawierająca centrum IoT Hub z urządzeniem dodanym do rejestru tożsamości urządzeń. Wpis w rejestrze tożsamości urządzeń umożliwia łączenie urządzenia symulowanego uruchamianego w tym samouczku z centrum.

Jeśli nie masz jeszcze skonfigurowanego centrum IoT w ramach subskrypcji, możesz skonfigurować go za pomocą następującego skryptu interfejsu wiersza polecenia. Ten skrypt używa nazwy tutorial-iot-hub z numerem losowym dołączonym do nazwy centrum IoT. Możesz zastąpić tę nazwę własną globalnie unikatową nazwą podczas jej uruchamiania. Skrypt tworzy grupę zasobów i centrum w regionie Środkowe stany USA, który można zmienić na bliższy. Skrypt pobiera parametry połączenia usługi IoT Hub używane w przykładowym zapleczu w celi połączenia z centrum IoT Hub:

let "randomIdentifier=$RANDOM*$RANDOM"  
hubname="tutorial-iot-hub-$randomIdentifier"
location=centralus

# Install the IoT extension if it's not already installed:
az extension add --name azure-iot

# Create a resource group:
az group create --name tutorial-iot-hub-rg --location $location

# Create your free-tier IoT hub. You can only have one free IoT hub per subscription.
# Change the sku to S1 to create a standard-tier hub if necessary.
az iot hub create --name $hubname --location $location --resource-group tutorial-iot-hub-rg --partition-count 2 --sku F1

# Make a note of the service connection string, you need it later:
az iot hub connection-string show --hub-name $hubname --policy-name service -o table

W tym samouczku jest używane urządzenie symulowane o nazwie MyTwinDevice. Poniższy skrypt dodaje to urządzenie do rejestru tożsamości i pobiera odpowiednie parametry połączenia:

# Create the device in the identity registry:
az iot hub device-identity create --device-id MyTwinDevice --hub-name $hubname --resource-group tutorial-iot-hub-rg

# Retrieve the device connection string, you need this later:
az iot hub device-identity connection-string show --device-id MyTwinDevice --hub-name $hubname --resource-group tutorial-iot-hub-rg -o table

Wysyłanie informacji o stanie do urządzenia

Żądane właściwości służą do wysyłania informacji o stanie z aplikacji zaplecza do urządzenia. W tej sekcji zobaczysz, jak:

  • Skonfiguruj urządzenie do odbierania i przetwarzania żądanych właściwości.
  • Wysyłanie żądanych właściwości z aplikacji zaplecza do urządzenia.

Przykładowe żądane właściwości

Strukturę żądanych właściwości można definiować w dowolny sposób wygodny dla aplikacji. W tym przykładzie jest używana jedna właściwość najwyższego poziomu o nazwie fanOn, która grupuje pozostałe właściwości w postaci oddzielnych elementów components. Poniższy fragment kodu JSON przedstawia strukturę żądanych właściwości używanych w tym samouczku. Plik JSON znajduje się w pliku desired.json.

{
  "fanOn": "true",
  "components": {
    "system": {
      "id": "17",
      "units": "farenheit",
      "firmwareVersion": "9.75"
    },
    "wifi" : { 
      "channel" : "6",
      "ssid": "my_network"
    },
    "climate" : {
      "minTemperature": "68",
      "maxTemperature": "76"
    }
  }
}

Odbieranie żądanych właściwości w aplikacji urządzenia

Aby zobaczyć przykładowy kod urządzenia symulowanego, który umożliwia odbieranie żądanych właściwości, przejdź do folderu iot-hub/Tutorials/DeviceTwins pobranego przykładowego projektu platformy Node.js. Następnie otwórz plik SimulatedDevice.js w edytorze tekstów.

W poniższych sekcjach opisano kod uruchamiany na symulowanym urządzeniu, który odpowiada na żądane zmiany właściwości wysyłane z aplikacji zaplecza.

Pobieranie obiektu bliźniaczej reprezentacji urządzenia

Po zarejestrowaniu urządzenia w centrum IoT otrzymasz urządzenie parametry połączenia jako dane wyjściowe. Urządzenie parametry połączenia jest używane przez urządzenie do uwierzytelniania przy użyciu jego zarejestrowanej tożsamości w chmurze. Poniższy kod łączy się z centrum IoT Hub przy użyciu parametrów połączenia urządzenia:

// Get the device connection string from a command line argument
var connectionString = process.argv[2];

Poniższy kod pobiera bliźniaczą reprezentację z obiektu klienta:

// Get the device twin
client.getTwin(function(err, twin) {
  if (err) {
    console.error(chalk.red('Could not get device twin'));
  } else {
    console.log(chalk.green('Device twin created'));

Tworzenie procedur obsługi

Procedury obsługi można tworzyć w przypadku aktualizacji żądanych właściwości, które odpowiadają na aktualizacje na różnych poziomach hierarchii JSON. Na przykład ta procedura obsługi widzi wszystkie zmiany żądanych właściwości wysyłane do urządzenia z poziomu aplikacji zaplecza. Zmienna delta zawiera żądane właściwości wysyłane z zaplecza rozwiązania:

// Handle all desired property updates
twin.on('properties.desired', function(delta) {
    console.log(chalk.yellow('\nNew desired properties received in patch:'));

Poniższa procedura obsługi reaguje tylko na zmiany wprowadzone w żądanej właściwości fanOn:

// Handle changes to the fanOn desired property
twin.on('properties.desired.fanOn', function(fanOn) {
    console.log(chalk.green('\nSetting fan state to ' + fanOn));

    // Update the reported property after processing the desired property
    reportedPropertiesPatch.fanOn = fanOn ? fanOn : '{unknown}';
});

Procedury obsługi dla wielu właściwości

W przykładowym żądanym pliku JSON właściwości dla tego samouczka węzeł klimat w obszarze składniki zawiera dwie właściwości: minTemperature i maxTemperature.

Lokalny obiekt twin urządzenia przechowuje kompletny zestaw właściwości żądanych i zgłaszanych. Zmienna delta wysłana z zaplecza może zaktualizować tylko podzestaw żądanych właściwości. W poniższym fragmencie kodu, gdy urządzenie symulowane odbiera aktualizację tylko z jednej wartości: minTemperature lub maxTemperature, używa wartości w lokalnym obiekcie twin dla innej wartości w celu skonfigurowania urządzenia:

// Handle desired properties updates to the climate component
twin.on('properties.desired.components.climate', function(delta) {
    if (delta.minTemperature || delta.maxTemperature) {
      console.log(chalk.green('\nUpdating desired tempertures in climate component:'));
      console.log('Configuring minimum temperature: ' + twin.properties.desired.components.climate.minTemperature);
      console.log('Configuring maximum temperture: ' + twin.properties.desired.components.climate.maxTemperature);

      // Update the reported properties and send them to the hub
      reportedPropertiesPatch.minTemperature = twin.properties.desired.components.climate.minTemperature;
      reportedPropertiesPatch.maxTemperature = twin.properties.desired.components.climate.maxTemperature;
      sendReportedProperties();
    }
});

Obsługa operacji wstawiania, aktualizowania i usuwania

Żądane właściwości wysyłane z zaplecza nie wskazują, jaka operacja jest wykonywana na określonej żądanej właściwości. Operacja wykonywana przez kod musi pochodzić z bieżącego zestawu żądanych właściwości przechowywanych lokalnie i zmian wysyłanych z centrum.

Poniższy fragment kodu pokazuje, jak urządzenie symulowane obsługuje operacje wstawiania, aktualizowania i usuwania na liście elementów components w żądanych właściwościach. Możesz sprawdzić, jak używać wartości null, aby wskazać, że składnik powinien zostać usunięty:

// Keep track of all the components the device knows about
var componentList = {};

// Use this componentList list and compare it to the delta to infer
// if anything was added, deleted, or updated.
twin.on('properties.desired.components', function(delta) {
  if (delta === null) {
    componentList = {};
  }
  else {
    Object.keys(delta).forEach(function(key) {

      if (delta[key] === null && componentList[key]) {
        // The delta contains a null value, and the
        // device has a record of this component.
        // Must be a delete operation.
        console.log(chalk.green('\nDeleting component ' + key));
        delete componentList[key];

      } else if (delta[key]) {
        if (componentList[key]) {
          // The delta contains a component, and the
          // device has a record of it.
          // Must be an update operation.
          console.log(chalk.green('\nUpdating component ' + key + ':'));
          console.log(JSON.stringify(delta[key]));
          // Store the complete object instead of just the delta
          componentList[key] = twin.properties.desired.components[key];

        } else {
          // The delta contains a component, and the
          // device has no record of it.
          // Must be an add operation.
          console.log(chalk.green('\nAdding component ' + key + ':'));
          console.log(JSON.stringify(delta[key]));
          // Store the complete object instead of just the delta
          componentList[key] = twin.properties.desired.components[key];
        }
      }
    });
  }
});

Wysyłanie żądanych właściwości z aplikacji zaplecza

Wiadomo już, jak urządzenie implementuje procedury obsługi w celu odbierania aktualizacji żądanej właściwości. W tej sekcji przedstawiono sposób wysyłania zmian żądanej właściwości do urządzenia z poziomu aplikacji zaplecza.

Aby zobaczyć przykładowy kod urządzenia symulowanego, który umożliwia odbieranie żądanych właściwości, przejdź do folderu iot-hub/Tutorials/DeviceTwins pobranego przykładowego projektu platformy Node.js. Następnie otwórz plik ServiceClient.js w edytorze tekstów.

Poniższy fragment kodu przedstawia sposób łączenia się z rejestrem tożsamości urządzeń i uzyskiwania dostępu do bliźniaczej reprezentacji określonego urządzenia:

// Create a device identity registry object
var registry = Registry.fromConnectionString(connectionString);

// Get the device twin and send desired property update patches at intervals.
// Print the reported properties after some of the desired property updates.
registry.getTwin(deviceId, async (err, twin) => {
  if (err) {
    console.error(err.message);
  } else {
    console.log('Got device twin');

Poniższy fragment kodu przedstawia różne poprawki żądanej właściwości, które aplikacja zaplecza wysyła do urządzenia:

// Turn the fan on
var twinPatchFanOn = {
  properties: {
    desired: {
      patchId: "Switch fan on",
      fanOn: "false",
    }
  }
};

// Set the maximum temperature for the climate component
var twinPatchSetMaxTemperature = {
  properties: {
    desired: {
      patchId: "Set maximum temperature",
      components: {
        climate: {
          maxTemperature: "92"
        }
      }
    }
  }
};

// Add a new component
var twinPatchAddWifiComponent = {
  properties: {
    desired: {
      patchId: "Add WiFi component",
      components: {
        wifi: { 
          channel: "6",
          ssid: "my_network"
        }
      }
    }
  }
};

// Update the WiFi component
var twinPatchUpdateWifiComponent = {
  properties: {
    desired: {
      patchId: "Update WiFi component",
      components: {
        wifi: { 
          channel: "13",
          ssid: "my_other_network"
        }
      }
    }
  }
};

// Delete the WiFi component
var twinPatchDeleteWifiComponent = {
  properties: {
    desired: {
      patchId: "Delete WiFi component",
      components: {
        wifi: null
      }
    }
  }
};

Poniższy fragment kodu przedstawia sposób wysyłania aktualizacji żądanej właściwości z aplikacji zaplecza do urządzenia:

// Send a desired property update patch
async function sendDesiredProperties(twin, patch) {
  twin.update(patch, (err, twin) => {
    if (err) {
      console.error(err.message);
    } else {
      console.log(chalk.green(`\nSent ${twin.properties.desired.patchId} patch:`));
      console.log(JSON.stringify(patch, null, 2));
    }
  });
}

Odbieranie informacji o stanie z urządzenia

Aplikacja zaplecza otrzymuje informacje o stanie z urządzenia jako zgłaszane właściwości. Urządzenie ustawia zgłaszane właściwości, a następnie wysyła je do centrum. Aplikacja zaplecza może odczytywać bieżące wartości zgłaszanych właściwości bliźniaczej reprezentacji urządzenia przechowywanej w centrum.

Wysyłanie zgłaszanych właściwości z urządzenia

Aktualizacje można wysłać do wartości zgłaszanych właściwości jako poprawki. Poniższy fragment kodu przedstawia szablon poprawki wysyłanej przez urządzenie symulowane. Urządzenie symulowane aktualizuje pola poprawki przed wysłaniem jej do centrum:

// Create a patch to send to the hub
var reportedPropertiesPatch = {
  firmwareVersion:'1.2.1',
  lastPatchReceivedId: '',
  fanOn:'',
  minTemperature:'',
  maxTemperature:''
};

Urządzenie symulowane używa następującej funkcji do wysyłania poprawki, która zawiera zgłaszane właściwości centrum:

// Send the reported properties patch to the hub
function sendReportedProperties() {
  twin.properties.reported.update(reportedPropertiesPatch, function(err) {
    if (err) throw err;
    console.log(chalk.blue('\nTwin state reported'));
    console.log(JSON.stringify(reportedPropertiesPatch, null, 2));
  });
}

Przetwarzanie zgłaszanych właściwości

Aplikacja zaplecza uzyskuje dostęp do bieżących wartości zgłaszanej właściwości urządzenia za pośrednictwem bliźniaczej reprezentacji urządzenia. Poniższy fragment kodu pokazuje, jak aplikacja zaplecza odczytuje wartości zgłaszanych właściwości urządzenia symulowanego:

// Display the reported properties from the device
function printReportedProperties(twin) {
  console.log("Last received patch: " + twin.properties.reported.lastPatchReceivedId);
  console.log("Firmware version: " + twin.properties.reported.firmwareVersion);
  console.log("Fan status: " + twin.properties.reported.fanOn);
  console.log("Min temperature set: " + twin.properties.reported.minTemperature);
  console.log("Max temperature set: " + twin.properties.reported.maxTemperature);
}

Uruchamianie aplikacji

W tej sekcji uruchomisz dwie przykładowe aplikacje, aby obserwować, jak aplikacja zaplecza wysyła żądane aktualizacje właściwości do aplikacji symulowanego urządzenia.

Aby uruchomić urządzenie symulowane i aplikacje zaplecza, potrzebujesz parametrów połączenia usługi i urządzenia. Parametry połączenia zostały zapisane podczas tworzenia zasobu na początku tego samouczka.

Aby uruchomić aplikację urządzenia symulowanego, otwórz powłokę lub okno wiersza polecenia i przejdź do folderu iot-hub/Tutorials/DeviceTwins w pobranym projekcie platformy Node.js. Następnie uruchom następujące polecenia:

npm install
node SimulatedDevice.js "{your device connection string}"

Aby uruchomić aplikację zaplecza, otwórz inną powłokę lub okno wiersza polecenia. Następnie przejdź do folderu iot-hub/Tutorials/DeviceTwins w pobranym projekcie platformy Node.js. Następnie uruchom następujące polecenia:

npm install
node ServiceClient.js "{your service connection string}"

Obserwowanie aktualizacji żądanych właściwości

Poniższy zrzut ekranu przedstawia dane wyjściowe z aplikacji urządzenia symulowanego i prezentuje sposób obsługi aktualizacji żądanej właściwości maxTemperature. Możesz zapoznać się ze sposobem uruchamiania procedury obsługi najwyższego poziomu oraz procedur obsługi składnika climate:

Screenshot that shows how both the top-level handler and the climate component handlers run.

Poniższy zrzut ekranu przedstawia dane wyjściowe z aplikacji zaplecza i prezentuje sposób wysłania aktualizacji do żądanej właściwości maxTemperature:

Screenshot that shows the output from the back-end application and highlights how it sends an update.

Obserwowanie zgłoszonych aktualizacji właściwości

Poniższy zrzut ekranu przedstawia dane wyjściowe z aplikacji urządzenia symulowanego i prezentuje sposób wysyłania aktualizacji zgłaszanej właściwości do centrum:

Screenshot that shows the simulated device updating its twin state.

Poniższy zrzut ekranu przedstawia dane wyjściowe z aplikacji zaplecza i wyróżnia sposób, w jaki odbiera i przetwarza zgłoszoną aktualizację właściwości z urządzenia:

Screenshot that shows the back-end application receiving the device reported properties.

Czyszczenie zasobów

Jeśli planujesz ukończyć następny samouczek, pozostaw grupę zasobów i centrum IoT, aby użyć ich później.

Jeśli nie potrzebujesz już tego centrum IoT, usuń je oraz grupę zasobów z poziomu portalu. W tym celu wybierz grupę zasobów tutorial-iot-hub-rg zawierającą centrum IoT, a następnie wybierz pozycję Usuń.

Alternatywnie możesz użyć interfejsu wiersza polecenia:

# Delete your resource group and its contents
az group delete --name tutorial-iot-hub-rg

Następne kroki

W tym samouczku przedstawiono sposób synchronizacji informacji o stanie między urządzeniami i centrum IoT Hub. Przejdź do następnego samouczka, aby dowiedzieć się, jak za pomocą bliźniaczych reprezentacji urządzeń zaimplementować proces aktualizacji urządzenia.