Öğretici: İstemci uygulamasını oluşturma ve uygulamanıza Azure IoT Central bağlama

Bu öğreticide, bir istemci uygulamasını uygulamanıza nasıl Azure IoT Central gösterir. Uygulama, bir sıcaklık denetleyicisi cihazın davranışının benzetimini sağlar. Uygulama IoT Central cihaz modelinin model kimliğini gönderir. IoT Central modeli almak ve sizin için bir cihaz şablonu oluşturmak için model kimliğini kullanır. Bir operatörün cihazla etkileşim kurması için cihaz şablonuna özelleştirmeler ve görünümler eklersiniz.

Bu öğreticide şunların nasıl yapıldığını öğreneceksiniz:

  • Cihaz kodunu oluşturun ve çalıştırın ve uygulamanıza bağlanarak IoT Central bakın.
  • Cihazdan gönderilen simülasyon telemetrisini görüntüleme.
  • Bir cihaz şablonuna özel görünümler ekleyin.
  • Cihaz şablonunu yayımlama.
  • Cihaz özelliklerini yönetmek için bir görünüm kullanın.
  • Cihazı kontrol etmek için bir komut çağırma.

Koda göz atın

Önkoşullar

Bu öğreticideki adımları tamamlayabilmeniz için şunlar gerekir:

Bu öğreticiyi Linux veya Windows üzerinde çalıştırabilirsiniz. bu öğreticideki kabuk komutları ' ' yol ayırıcıları için Linux kuralını izler / . Windows üzerinde takip ediyorsanız, bu ayırıcıları ' ' için değiştirmeyi unutmayın \ .

Önkoşullar işletim sistemine göre farklılık gösterir:

Linux

Bu öğretici Ubuntu Linux kullandığınızı varsayar. Bu öğreticideki adımlar Ubuntu 18,04 kullanılarak test edilmiştir.

Linux 'ta bu öğreticiyi tamamlayabilmeniz için, yerel Linux ortamınıza aşağıdaki yazılımı yüklersiniz:

şu komutu kullanarak GCC, Git, cmake ve tüm gerekli bağımlılıkları yükler apt-get :

sudo apt-get update
sudo apt-get install -y git cmake build-essential curl libcurl4-openssl-dev libssl-dev uuid-dev

öğesinin sürümünün cmake 2.8.12 üzerinde olduğunu ve GCC sürümünün 4.4.7'in üzerinde olduğunu doğrulayın.

cmake --version
gcc --version

Windows

bu öğreticiyi Windows gerçekleştirmek için yerel Windows ortamınıza aşağıdaki yazılımları yüklersiniz:

Kodu indirme

Bu öğreticide, Azure IoT Hub cihaz C SDK 'sını klonlamak ve derlemek için kullanabileceğiniz bir geliştirme ortamı hazırlarsınız.

Seçtiğiniz dizinde bir komut istemi açın. Azure ıot C sdk 'ları ve kitaplıkları GitHub deposunu bu konuma kopyalamak için aşağıdaki komutu yürütün:

git clone https://github.com/Azure/azure-iot-sdk-c.git
cd azure-iot-sdk-c
git submodule update --init

Bu işlemin tamamlanması birkaç dakika sürer.

Kodu gözden geçirin

daha önce indirdiğiniz C için ıot SDK Microsoft Azure kopyasında, Azure-ıot-SDK-c/iothub_client/samples/pnp/pnp_temperature_controller/pnp_temperature_controller. C ve Azure-ıot-SDK-c/iothub_client/samples/pnp/pnp_temperature_controller/pnp_thermostat_component. c dosyalarını bir metin düzenleyicisinde açın.

IoT Central bağlanmak için örneği çalıştırdığınızda, cihazı kaydetmek ve bir bağlantı dizesi oluşturmak için cihaz sağlama hizmeti 'ni (DPS) kullanır. Örnek, gereken DPS bağlantı bilgilerini komut satırı ortamından alır.

Pnp_temperature_controller. c' de, main önce işlevi şunu çağırır CreateDeviceClientAndAllocateComponents :

  • dtmi:com:example:Thermostat;1Model kimliğini ayarlayın. IoT Central, bu cihazın cihaz şablonunu tanımlamak veya oluşturmak için model KIMLIĞINI kullanır. Daha fazla bilgi için bkz. cihaz şablonuyla bir cihazı ilişkilendirme.
  • Cihaz sağlamak ve kaydetmek için DPS kullanın.
  • Bir cihaz istemci tutamacı oluşturun ve IoT Central uygulamanıza bağlanın.
  • Sıcaklık denetleyicisi bileşenindeki komutlar için bir işleyici oluşturur.
  • Sıcaklık denetleyicisi bileşenindeki özellik güncelleştirmeleri için bir işleyici oluşturur.
  • İki termostat bileşeni oluşturur.

mainSonraki işlev:

  • Tüm bileşenler için bazı ilk özellik değerlerini raporlar.
  • Tüm bileşenlerden telemetri göndermek için bir döngü başlatır.

mainİşlev daha sonra telemetrileri aralıklarla göndermek için bir iş parçacığı başlatır.

int main(void)
{
  IOTHUB_DEVICE_CLIENT_LL_HANDLE deviceClient = NULL;

  if ((deviceClient = CreateDeviceClientAndAllocateComponents()) == NULL)
  {
    LogError("Failure creating IotHub device client");
  }
  else
  {
    LogInfo("Successfully created device client.  Hit Control-C to exit program\n");

    int numberOfIterations = 0;

    // During startup, send the non-"writable" properties.
    PnP_TempControlComponent_ReportSerialNumber_Property(deviceClient);
    PnP_DeviceInfoComponent_Report_All_Properties(g_deviceInfoComponentName, deviceClient);
    PnP_TempControlComponent_Report_MaxTempSinceLastReboot_Property(g_thermostatHandle1, deviceClient);
    PnP_TempControlComponent_Report_MaxTempSinceLastReboot_Property(g_thermostatHandle2, deviceClient);

    while (true)
    {
      // Wake up periodically to poll.  Even if we do not plan on sending telemetry, we still need to poll periodically in order to process
      // incoming requests from the server and to do connection keep alives.
      if ((numberOfIterations % g_sendTelemetryPollInterval) == 0)
      {
          PnP_TempControlComponent_SendWorkingSet(deviceClient);
          PnP_ThermostatComponent_SendTelemetry(g_thermostatHandle1, deviceClient);
          PnP_ThermostatComponent_SendTelemetry(g_thermostatHandle2, deviceClient);
      }

      IoTHubDeviceClient_LL_DoWork(deviceClient);
      ThreadAPI_Sleep(g_sleepBetweenPollsMs);
      numberOfIterations++;
    }

    // Free the memory allocated to track simulated thermostat.
    PnP_ThermostatComponent_Destroy(g_thermostatHandle2);
    PnP_ThermostatComponent_Destroy(g_thermostatHandle1);

    // Clean up the iothub sdk handle
    IoTHubDeviceClient_LL_Destroy(deviceClient);
    // Free all the sdk subsystem
    IoTHub_Deinit();
  }

  return 0;
}

' De pnp_thermostat_component.c , PnP_ThermostatComponent_SendTelemetry işlevi cihazın bir bileşenden IoT Central sıcaklık telemetrisini nasıl göndereceğini gösterir:

void PnP_ThermostatComponent_SendTelemetry(PNP_THERMOSTAT_COMPONENT_HANDLE pnpThermostatComponentHandle, IOTHUB_DEVICE_CLIENT_LL_HANDLE deviceClientLL)
{
  PNP_THERMOSTAT_COMPONENT* pnpThermostatComponent = (PNP_THERMOSTAT_COMPONENT*)pnpThermostatComponentHandle;
  IOTHUB_MESSAGE_HANDLE messageHandle = NULL;
  IOTHUB_CLIENT_RESULT iothubResult;

  char temperatureStringBuffer[32];

  if (snprintf(temperatureStringBuffer, sizeof(temperatureStringBuffer), g_temperatureTelemetryBodyFormat, pnpThermostatComponent->currentTemperature) < 0)
  {
    LogError("snprintf of current temperature telemetry failed");
  }
  else if ((messageHandle = PnP_CreateTelemetryMessageHandle(pnpThermostatComponent->componentName, temperatureStringBuffer)) == NULL)
  {
    LogError("Unable to create telemetry message");
  }
  else if ((iothubResult = IoTHubDeviceClient_LL_SendEventAsync(deviceClientLL, messageHandle, NULL, NULL)) != IOTHUB_CLIENT_OK)
  {
    LogError("Unable to send telemetry message, error=%d", iothubResult);
  }

  IoTHubMessage_Destroy(messageHandle);
}

pnp_thermostat_component.c' De, PnP_TempControlComponent_Report_MaxTempSinceLastReboot_Property işlevi maxTempSinceLastReboot bileşenden IoT Central bir özellik güncelleştirmesi gönderir:

void PnP_TempControlComponent_Report_MaxTempSinceLastReboot_Property(PNP_THERMOSTAT_COMPONENT_HANDLE pnpThermostatComponentHandle, IOTHUB_DEVICE_CLIENT_LL_HANDLE deviceClientLL)
{
  PNP_THERMOSTAT_COMPONENT* pnpThermostatComponent = (PNP_THERMOSTAT_COMPONENT*)pnpThermostatComponentHandle;
  char maximumTemperatureAsString[32];
  IOTHUB_CLIENT_RESULT iothubClientResult;
  STRING_HANDLE jsonToSend = NULL;

  if (snprintf(maximumTemperatureAsString, sizeof(maximumTemperatureAsString), g_maxTempSinceLastRebootPropertyFormat, pnpThermostatComponent->maxTemperature) < 0)
  {
    LogError("Unable to create max temp since last reboot string for reporting result");
  }
  else if ((jsonToSend = PnP_CreateReportedProperty(pnpThermostatComponent->componentName, g_maxTempSinceLastRebootPropertyName, maximumTemperatureAsString)) == NULL)
  {
    LogError("Unable to build max temp since last reboot property");
  }
  else
  {
    const char* jsonToSendStr = STRING_c_str(jsonToSend);
    size_t jsonToSendStrLen = strlen(jsonToSendStr);

    if ((iothubClientResult = IoTHubDeviceClient_LL_SendReportedState(deviceClientLL, (const unsigned char*)jsonToSendStr, jsonToSendStrLen, NULL, NULL)) != IOTHUB_CLIENT_OK)
    {
      LogError("Unable to send reported state, error=%d", iothubClientResult);
    }
    else
    {
      LogInfo("Sending maximumTemperatureSinceLastReboot property to IoTHub for component=%s", pnpThermostatComponent->componentName);
    }
  }

  STRING_delete(jsonToSend);
}

pnp_thermostat_component.c' De, PnP_ThermostatComponent_ProcessPropertyUpdate işlevi IoT Central 'dan yazılabilir Özellik güncelleştirmelerini işler:

void PnP_ThermostatComponent_ProcessPropertyUpdate(PNP_THERMOSTAT_COMPONENT_HANDLE pnpThermostatComponentHandle, IOTHUB_DEVICE_CLIENT_LL_HANDLE deviceClientLL, const char* propertyName, JSON_Value* propertyValue, int version)
{
  PNP_THERMOSTAT_COMPONENT* pnpThermostatComponent = (PNP_THERMOSTAT_COMPONENT*)pnpThermostatComponentHandle;

  if (strcmp(propertyName, g_targetTemperaturePropertyName) != 0)
  {
    LogError("Property=%s was requested to be changed but is not part of the thermostat interface definition", propertyName);
  }
  else if (json_value_get_type(propertyValue) != JSONNumber)
  {
    LogError("JSON field %s is not a number", g_targetTemperaturePropertyName);
  }
  else
  {
    double targetTemperature = json_value_get_number(propertyValue);

    LogInfo("Received targetTemperature=%f for component=%s", targetTemperature, pnpThermostatComponent->componentName);
    
    bool maxTempUpdated = false;
    UpdateTemperatureAndStatistics(pnpThermostatComponent, targetTemperature, &maxTempUpdated);

    // The device needs to let the service know that it has received the targetTemperature desired property.
    SendTargetTemperatureResponse(pnpThermostatComponent, deviceClientLL, version);
    
    if (maxTempUpdated)
    {
      // If the Maximum temperature has been updated, we also report this as a property.
        PnP_TempControlComponent_Report_MaxTempSinceLastReboot_Property(pnpThermostatComponent, deviceClientLL);
    }
  }
}

pnp_thermostat_component.c' De PnP_ThermostatComponent_ProcessCommand işlev, IoT Central çağrılan komutları işler:

int PnP_ThermostatComponent_ProcessCommand(PNP_THERMOSTAT_COMPONENT_HANDLE pnpThermostatComponentHandle, const char *pnpCommandName, JSON_Value* commandJsonValue, unsigned char** response, size_t* responseSize)
{
  PNP_THERMOSTAT_COMPONENT* pnpThermostatComponent = (PNP_THERMOSTAT_COMPONENT*)pnpThermostatComponentHandle;
  const char* sinceStr;
  int result;

  if (strcmp(pnpCommandName, g_getMaxMinReport) != 0)
  {
    LogError("PnP command=%s is not supported on thermostat component", pnpCommandName);
    result = PNP_STATUS_NOT_FOUND;
  }
  // See caveats section in ../readme.md; we don't actually respect this sinceStr to keep the sample simple,
  // but want to demonstrate how to parse out in any case.
  else if ((sinceStr = json_value_get_string(commandJsonValue)) == NULL)
  {
    LogError("Cannot retrieve JSON string for command");
    result = PNP_STATUS_BAD_FORMAT;
  }
  else if (BuildMaxMinCommandResponse(pnpThermostatComponent, response, responseSize) == false)
  {
    LogError("Unable to build response for component=%s", pnpThermostatComponent->componentName);
    result = PNP_STATUS_INTERNAL_ERROR;
  }
  else
  {
    LogInfo("Returning success from command request for component=%s", pnpThermostatComponent->componentName);
    result = PNP_STATUS_SUCCESS;
  }

  return result;
}

Kodu oluşturma

Dahil edilen örnek kodu oluşturmak için cihaz SDK 'sını kullanın:

  1. Cihaz SDK 'sının kök klasöründe bir CMake alt dizini oluşturun ve bu klasöre gidin:

    cd azure-iot-sdk-c
    mkdir cmake
    cd cmake
    
  2. SDK 'Yı ve örnekleri derlemek için aşağıdaki komutları çalıştırın:

    cmake -Duse_prov_client=ON -Dhsm_type_symm_key=ON -Drun_e2e_tests=OFF ..
    cmake --build .
    

Bağlantı bilgilerini alma

Bu öğreticide daha sonra örnek cihaz uygulamasını çalıştırdığınızda aşağıdaki yapılandırma değerleri gerekir:

  • KIMLIK kapsamı: IoT Central uygulamanızda yönetim > cihaz bağlantısı' na gidin. Kimlik kapsamı değerini bir yere getirin.
  • Birincil anahtarı grupla: IoT Central uygulamanızda yönetim > cihaz bağlantısı > SAS-IoT-cihazlar' a gidin. Paylaşılan erişim imzası birincil anahtar değerini bir yere getirin.

Aldığınız grup birincil anahtarından bir cihaz anahtarı oluşturmak için Cloud Shell kullanın:

az extension add --name azure-iot
az iot central device compute-device-key --device-id sample-device-01 --pk <the group primary key value>

Oluşturulan Cihaz anahtarını bir yere getirin, bu öğreticide daha sonra kullanın.

Kodu çalıştırma

Örnek uygulamayı çalıştırmak için bir komut satırı ortamı açın ve Azure-iot-SDK-c\cmake klasörüne gidin.

Örneği yapılandırmak için ortam değişkenlerini ayarlayın. Aşağıdaki kod parçacığında, Windows komut isteminde ortam değişkenlerinin nasıl ayarlanacağı gösterilmektedir. Bash kabuğu kullanıyorsanız, komutları komutlarla değiştirin set export :

set IOTHUB_DEVICE_SECURITY_TYPE=DPS
set IOTHUB_DEVICE_DPS_ID_SCOPE=<The ID scope you made a note of previously>
set IOTHUB_DEVICE_DPS_DEVICE_ID=sample-device-01
set IOTHUB_DEVICE_DPS_DEVICE_KEY=<The generated device key you made a note of previously>
set IOTHUB_DEVICE_DPS_ENDPOINT=global.azure-devices-provisioning.net

Örneği çalıştırmak için:

# Bash
cd iothub_client/samples/pnp/pnp_temperature_controller/
./pnp_temperature_controller
REM Windows
cd iothub_client\samples\pnp\pnp_temperature_controller\Debug
.\pnp_temperature_controller.exe

Aşağıdaki çıktı, IoT Central kaydetme ve bağlanma için cihazı gösterir. Örnek, telemetri göndermeye başlar:

Info: Initiating DPS client to retrieve IoT Hub connection information
-> 09:43:27 CONNECT | VER: 4 | KEEPALIVE: 0 | FLAGS: 194 | USERNAME: 0ne0026656D/registrations/sample-device-01/api-version=2019-03-31&ClientVersion=1.6.0 | PWD: XXXX | CLEAN: 1
<- 09:43:28 CONNACK | SESSION_PRESENT: false | RETURN_CODE: 0x0
-> 09:43:29 SUBSCRIBE | PACKET_ID: 1 | TOPIC_NAME: $dps/registrations/res/# | QOS: 1
<- 09:43:30 SUBACK | PACKET_ID: 1 | RETURN_CODE: 1
-> 09:43:30 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_MOST_ONCE | TOPIC_NAME: $dps/registrations/PUT/iotdps-register/?$rid=1 | PAYLOAD_LEN: 102
<- 09:43:31 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_LEAST_ONCE | TOPIC_NAME: $dps/registrations/res/202/?$rid=1&retry-after=3 | PACKET_ID: 2 | PAYLOAD_LEN: 94
-> 09:43:31 PUBACK | PACKET_ID: 2
-> 09:43:33 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_MOST_ONCE | TOPIC_NAME: $dps/registrations/GET/iotdps-get-operationstatus/?$rid=2&operationId=4.2f792ade0a5c3e68.baf0e879-d88a-4153-afef-71aff51fd847 | PAYLOAD_LEN: 102
<- 09:43:34 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_LEAST_ONCE | TOPIC_NAME: $dps/registrations/res/202/?$rid=2&retry-after=3 | PACKET_ID: 2 | PAYLOAD_LEN: 173
-> 09:43:34 PUBACK | PACKET_ID: 2
-> 09:43:36 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_MOST_ONCE | TOPIC_NAME: $dps/registrations/GET/iotdps-get-operationstatus/?$rid=3&operationId=4.2f792ade0a5c3e68.baf0e879-d88a-4153-afef-71aff51fd847 | PAYLOAD_LEN: 102
<- 09:43:37 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_LEAST_ONCE | TOPIC_NAME: $dps/registrations/res/200/?$rid=3 | PACKET_ID: 2 | PAYLOAD_LEN: 478
-> 09:43:37 PUBACK | PACKET_ID: 2
Info: Provisioning callback indicates success.  iothubUri=iotc-60a....azure-devices.net, deviceId=sample-device-01
-> 09:43:37 DISCONNECT
Info: DPS successfully registered.  Continuing on to creation of IoTHub device client handle.
Info: Successfully created device client.  Hit Control-C to exit program

Info: Sending serialNumber property to IoTHub
Info: Sending device information property to IoTHub.  propertyName=swVersion, propertyValue="1.0.0.0"
Info: Sending device information property to IoTHub.  propertyName=manufacturer, propertyValue="Sample-Manufacturer"
Info: Sending device information property to IoTHub.  propertyName=model, propertyValue="sample-Model-123"
Info: Sending device information property to IoTHub.  propertyName=osName, propertyValue="sample-OperatingSystem-name"
Info: Sending device information property to IoTHub.  propertyName=processorArchitecture, propertyValue="Contoso-Arch-64bit"
Info: Sending device information property to IoTHub.  propertyName=processorManufacturer, propertyValue="Processor Manufacturer(TM)"
Info: Sending device information property to IoTHub.  propertyName=totalStorage, propertyValue=10000
Info: Sending device information property to IoTHub.  propertyName=totalMemory, propertyValue=200
Info: Sending maximumTemperatureSinceLastReboot property to IoTHub for component=thermostat1
Info: Sending maximumTemperatureSinceLastReboot property to IoTHub for component=thermostat2
-> 09:43:44 CONNECT | VER: 4 | KEEPALIVE: 240 | FLAGS: 192 | USERNAME: iotc-60a576a2-eec7-48e2-9306-9e7089a79995.azure-devices.net/sample-device-01/?api-version=2020-09-30&DeviceClientType=iothubclient%2f1.6.0%20(native%3b%20Linux%3b%20x86_64)&model-id=dtmi%3acom%3aexample%3aTemperatureController%3b1 | PWD: XXXX | CLEAN: 0
<- 09:43:44 CONNACK | SESSION_PRESENT: false | RETURN_CODE: 0x0
-> 09:43:44 SUBSCRIBE | PACKET_ID: 2 | TOPIC_NAME: $iothub/twin/res/# | QOS: 0 | TOPIC_NAME: $iothub/methods/POST/# | QOS: 0
-> 09:43:44 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_LEAST_ONCE | TOPIC_NAME: devices/sample-device-01/messages/events/ | PACKET_ID: 3 | PAYLOAD_LEN: 19
-> 09:43:44 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_LEAST_ONCE | TOPIC_NAME: devices/sample-device-01/messages/events/%24.sub=thermostat1 | PACKET_ID: 4 | PAYLOAD_LEN: 21
-> 09:43:44 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_LEAST_ONCE | TOPIC_NAME: devices/sample-device-01/messages/events/%24.sub=thermostat2 | PACKET_ID: 5 | PAYLOAD_LEN: 21

Uygulamanıza işleç olarak Azure IoT Central şunları gerçekleştirebilirsiniz:

  • Genel Bakış sayfasında iki termostat bileşeni tarafından gönderilen telemetrisini görüntüleyebilirsiniz:

    Cihaz telemetrisini görüntüleme

  • Hakkında sayfasında cihaz özelliklerini görüntüleme. Bu sayfada cihaz bilgileri bileşeni ve iki termostat bileşeninden özellikler görüntülenir:

    Cihaz özelliklerini görüntüleme

Cihaz şablonunu özelleştirme

Çözüm geliştiricisi olarak, sıcaklık denetleyicisi cihazı bağlandığında otomatik IoT Central oluşturulan cihaz şablonunu özelleştirebilirsiniz.

Cihazla ilişkili müşteri adını depolamak için bir bulut özelliği eklemek için:

  1. Uygulama IoT Central Cihaz şablonları sayfasında Temperature Controller cihaz şablonuna gidin.

  2. Sıcaklık Denetleyicisi cihaz şablonunda Bulut özellikleri'ne tıklayın.

  3. Bulut özelliği ekle'yi seçin. Görünen ad olarak Müşteri adı girin, girişi genişletin ve Şema olarak Dize'yi seçin. Sonra Kaydet'i seçin.

Get Max-Min rapor komutlarının uygulamanıza nasıl görüntü IoT Central için:

  1. Cihaz şablonunda Özelleştir'i seçin.

  2. getMaxMinReport (thermostat1) için Get Max-Min değiştirin. termostat1 durum raporunu al ile.

  3. getMaxMinReport (termostat2) için Get Max-Min değiştirin. termostat2 durum raporunu al ile.

  4. Kaydet’i seçin.

Hedef Sıcaklık yazılabilir özelliklerinin uygulamanıza nasıl görüntü IoT Central için:

  1. Cihaz şablonunda Özelleştir'i seçin.

  2. targetTemperature (termostat1) için Hedef Sıcaklığı Hedef Sıcaklık (1) ile değiştirin.

  3. targetTemperature (termostat2) için Hedef Sıcaklığı Hedef Sıcaklık (2) ile değiştirin.

  4. Kaydet’i seçin.

Sıcaklık Denetleyicisi modelinde termostat bileşenleri Hedef Sıcaklık yazılabilir özelliğini, cihaz şablonu ise Müşteri Adı bulut özelliğini içerir. Bir operatörün şu özellikleri düzenlemek için kullanabileceği bir görünüm oluşturun:

  1. Görünümler'i ve ardından Cihaz ve bulut verilerini düzenleme kutucuğunu seçin.

  2. Form adı olarak Özellikler girin.

  3. Hedef Sıcaklık (1), Hedef Sıcaklık (2) ve Müşteri Adı özelliklerini seçin. Ardından Bölüm ekle'yi seçin.

  4. Yaptığınız değişiklikleri kaydedin.

Özellik değerlerini güncelleştirmek için görüntüleme

Cihaz şablonunu yayımlama

Operatör, sizin yapmış olduğunu özelleştirmeleri görene ve kullanamadan önce cihaz şablonunu yayımlamanız gerekir.

Thermostat cihaz şablonundan Yayımla'yı seçin. Bu cihazı yayımla şablonunu uygulama panelinde Yayımla'yı seçin.

Operatör artık özellik değerlerini güncelleştirmek için Özellikler görünümünü kullanabilir ve cihaz komutları sayfasındaKi Termostat1 durum raporunu al ve Termostat2 durum raporunu al adlı komutları çağırabilirsiniz:

  • Özellikler sayfasında yazılabilir özellik değerlerini güncelleştirin:

    Cihaz özelliklerini güncelleştirme

  • Komutlar sayfasından komutları çağırma. Durum raporu komutunu çalıştırmadan önce Since parametresi için bir tarih ve saat seçin:

    komutunu çağırma

    Komut yanıtını görüntüleme

Aygıtın komutlara ve özellik güncelleştirmelerine nasıl yanıt verdiğini görebilirsiniz:

<- 09:49:03 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_MOST_ONCE | TOPIC_NAME: $iothub/methods/POST/thermostat1*getMaxMinReport/?$rid=1 | PAYLOAD_LEN: 26
Info: Received PnP command for component=thermostat1, command=getMaxMinReport
Info: Returning success from command request for component=thermostat1
-> 09:49:03 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_MOST_ONCE | TOPIC_NAME: $iothub/methods/res/200/?$rid=1 | PAYLOAD_LEN: 117

...

<- 09:50:04 PUBLISH | IS_DUP: false | RETAIN: 0 | QOS: DELIVER_AT_MOST_ONCE | TOPIC_NAME: $iothub/twin/PATCH/properties/desired/?$version=2 | PAYLOAD_LEN: 63
Info: Received targetTemperature=67.000000 for component=thermostat2
Info: Sending acknowledgement of property to IoTHub for component=thermostat2

Koda göz atın

Önkoşullar

Bu makaledeki adımları tamamlamak için aşağıdaki kaynaklar gereklidir:

Kodu gözden geçirin

Daha önce indirdiğiniz C# için Microsoft Azure IoT Örnekleri deposunun kopyasında azure-iot-samples-csharp-main\iot-hub\Samples\device\IoTHubDeviceSamples.sln" çözüm dosyasını Visual Studio. Bu Çözüm Gezgini için PnpDeviceSamples > TemperatureController klasörünü genişletin ve Program.cs ve TemperatureControllerSample.cs dosyalarını açın.

IoT Central'a bağlanmak için örneği IoT Central, cihazı kaydetmek ve bir bağlantı dizesi oluşturmak için Cihaz Sağlama Hizmeti'nin (DPS) kullanır. Örnek, ihtiyacı olan DPS bağlantı bilgilerini ortamdan almaktadır.

Program.cs'de yöntemi Main şu çağrıyı SetupDeviceClientAsync kullanır:

  • DpS ile dtmi:com:example:TemperatureController;2 cihaz sağlarken model kimliğini kullanın. IoT Central, bu cihaz için cihaz şablonunu tanımlamak veya oluşturmak için model kimliğini kullanır. Daha fazla bilgi için bkz. Cihazı cihaz şablonuyla ilişkilendirme.
  • IoT Central'a bağlanmak için bir DeviceClient örneği oluşturun.
private static async Task<DeviceClient> SetupDeviceClientAsync(Parameters parameters, CancellationToken cancellationToken)
{
  DeviceClient deviceClient;
  switch (parameters.DeviceSecurityType.ToLowerInvariant())
  {
    case "dps":
      DeviceRegistrationResult dpsRegistrationResult = await ProvisionDeviceAsync(parameters, cancellationToken);
      var authMethod = new DeviceAuthenticationWithRegistrySymmetricKey(dpsRegistrationResult.DeviceId, parameters.DeviceSymmetricKey);
      deviceClient = InitializeDeviceClient(dpsRegistrationResult.AssignedHub, authMethod);
      break;

    case "connectionstring":
      // ...

    default:
      // ...
  }
  return deviceClient;
}

Ardından main yöntemi bir TemperatureControllerSample örneği oluşturur ve bu örnekle etkileşimleri PerformOperationsAsync işlemek için IoT Central.

TemperatureControllerSample.cs içinde PerformOperationsAsync yöntemi:

  • Varsayılan bileşende reboot komutu için bir işleyici ayarlar.
  • İki termostat bileşeni üzerinde getMaxMinReport komutları için işleyicileri ayarlar.
  • İki termostat bileşeni üzerinde hedef sıcaklık özelliği güncelleştirmelerini almak için işleyicileri ayarlar.
  • İlk cihaz bilgileri özellik güncelleştirmelerini gönderir.
  • İki termostat bileşeninden düzenli aralıklarla sıcaklık telemetrisi gönderir.
  • Çalışma kümesi telemetrisini varsayılan bileşenden düzenli aralıklarla gönderir.
  • İki termostat bileşeninde yeni bir en yüksek sıcaklığa ulaşıldıktan sonra son yeniden başlatmadan bu yana en yüksek sıcaklığı gönderir.
public async Task PerformOperationsAsync(CancellationToken cancellationToken)
{
  await _deviceClient.SetMethodHandlerAsync("reboot", HandleRebootCommandAsync, _deviceClient, cancellationToken);

  // For a component-level command, the command name is in the format "<component-name>*<command-name>".
  await _deviceClient.SetMethodHandlerAsync("thermostat1*getMaxMinReport", HandleMaxMinReportCommand, Thermostat1, cancellationToken);
  await _deviceClient.SetMethodHandlerAsync("thermostat2*getMaxMinReport", HandleMaxMinReportCommand, Thermostat2, cancellationToken);

  await _deviceClient.SetDesiredPropertyUpdateCallbackAsync(SetDesiredPropertyUpdateCallback, null, cancellationToken);
  _desiredPropertyUpdateCallbacks.Add(Thermostat1, TargetTemperatureUpdateCallbackAsync);
  _desiredPropertyUpdateCallbacks.Add(Thermostat2, TargetTemperatureUpdateCallbackAsync);

  await UpdateDeviceInformationAsync(cancellationToken);
  await SendDeviceSerialNumberAsync(cancellationToken);

  bool temperatureReset = true;
  _maxTemp[Thermostat1] = 0d;
  _maxTemp[Thermostat2] = 0d;

  while (!cancellationToken.IsCancellationRequested)
  {
    if (temperatureReset)
    {
      // Generate a random value between 5.0°C and 45.0°C for the current temperature reading for each "Thermostat" component.
      _temperature[Thermostat1] = Math.Round(s_random.NextDouble() * 40.0 + 5.0, 1);
      _temperature[Thermostat2] = Math.Round(s_random.NextDouble() * 40.0 + 5.0, 1);
    }

    await SendTemperatureAsync(Thermostat1, cancellationToken);
    await SendTemperatureAsync(Thermostat2, cancellationToken);
    await SendDeviceMemoryAsync(cancellationToken);

    temperatureReset = _temperature[Thermostat1] == 0 && _temperature[Thermostat2] == 0;
    await Task.Delay(5 * 1000);
  }
}

yöntemi, SendTemperatureAsync cihazın sıcaklık telemetrisini bir bileşenden cihaza nasıl IoT Central. yöntemi, SendTemperatureTelemetryAsync PnpConvention iletiyi derlemek için sınıfını kullanır:

private async Task SendTemperatureAsync(string componentName, CancellationToken cancellationToken)
{
  await SendTemperatureTelemetryAsync(componentName, cancellationToken);

  double maxTemp = _temperatureReadingsDateTimeOffset[componentName].Values.Max<double>();
  if (maxTemp > _maxTemp[componentName])
  {
    _maxTemp[componentName] = maxTemp;
    await UpdateMaxTemperatureSinceLastRebootAsync(componentName, cancellationToken);
  }
}

private async Task SendTemperatureTelemetryAsync(string componentName, CancellationToken cancellationToken)
{
  const string telemetryName = "temperature";
  double currentTemperature = _temperature[componentName];
  using Message msg = PnpConvention.CreateMessage(telemetryName, currentTemperature, componentName);

  await _deviceClient.SendEventAsync(msg, cancellationToken);

  if (_temperatureReadingsDateTimeOffset.ContainsKey(componentName))
  {
    _temperatureReadingsDateTimeOffset[componentName].TryAdd(DateTimeOffset.UtcNow, currentTemperature);
  }
  else
  {
    _temperatureReadingsDateTimeOffset.TryAdd(
      componentName,
      new Dictionary<DateTimeOffset, double>
      {
        { DateTimeOffset.UtcNow, currentTemperature },
      });
  }
}

yöntemi, UpdateMaxTemperatureSinceLastRebootAsync bir özellik maxTempSinceLastReboot güncelleştirmesini IoT Central. Bu yöntem, düzeltme PnpConvention ekini oluşturmak için sınıfını kullanır:

private async Task UpdateMaxTemperatureSinceLastRebootAsync(string componentName, CancellationToken cancellationToken)
{
  const string propertyName = "maxTempSinceLastReboot";
  double maxTemp = _maxTemp[componentName];
  TwinCollection reportedProperties = PnpConvention.CreateComponentPropertyPatch(componentName, propertyName, maxTemp);

  await _deviceClient.UpdateReportedPropertiesAsync(reportedProperties, cancellationToken);
}

yöntemi, TargetTemperatureUpdateCallbackAsync yazılabilir hedef sıcaklık özelliği güncelleştirmesini IoT Central. Bu yöntem, PnpConvention özellik güncelleştirme iletiyi okumak ve yanıtı oluşturmak için sınıfını kullanır:

private async Task TargetTemperatureUpdateCallbackAsync(TwinCollection desiredProperties, object userContext)
{
  const string propertyName = "targetTemperature";
  string componentName = (string)userContext;

  bool targetTempUpdateReceived = PnpConvention.TryGetPropertyFromTwin(
    desiredProperties,
    propertyName,
    out double targetTemperature,
    componentName);
  if (!targetTempUpdateReceived)
  {
      return;
  }

  TwinCollection pendingReportedProperty = PnpConvention.CreateComponentWritablePropertyResponse(
      componentName,
      propertyName,
      targetTemperature,
      (int)StatusCode.InProgress,
      desiredProperties.Version);

  await _deviceClient.UpdateReportedPropertiesAsync(pendingReportedProperty);

  // Update Temperature in 2 steps
  double step = (targetTemperature - _temperature[componentName]) / 2d;
  for (int i = 1; i <= 2; i++)
  {
      _temperature[componentName] = Math.Round(_temperature[componentName] + step, 1);
      await Task.Delay(6 * 1000);
  }

  TwinCollection completedReportedProperty = PnpConvention.CreateComponentWritablePropertyResponse(
      componentName,
      propertyName,
      _temperature[componentName],
      (int)StatusCode.Completed,
      desiredProperties.Version,
      "Successfully updated target temperature");

  await _deviceClient.UpdateReportedPropertiesAsync(completedReportedProperty);
}

yöntemi, HandleMaxMinReportCommand aşağıdaki komutlardan çağrılır bileşenler için IoT Central:

private Task<MethodResponse> HandleMaxMinReportCommand(MethodRequest request, object userContext)
{
    try
    {
        string componentName = (string)userContext;
        DateTime sinceInUtc = JsonConvert.DeserializeObject<DateTime>(request.DataAsJson);
        var sinceInDateTimeOffset = new DateTimeOffset(sinceInUtc);

        if (_temperatureReadingsDateTimeOffset.ContainsKey(componentName))
        {

            Dictionary<DateTimeOffset, double> allReadings = _temperatureReadingsDateTimeOffset[componentName];
            Dictionary<DateTimeOffset, double> filteredReadings = allReadings.Where(i => i.Key > sinceInDateTimeOffset)
                .ToDictionary(i => i.Key, i => i.Value);

            if (filteredReadings != null && filteredReadings.Any())
            {
                var report = new
                {
                    maxTemp = filteredReadings.Values.Max<double>(),
                    minTemp = filteredReadings.Values.Min<double>(),
                    avgTemp = filteredReadings.Values.Average(),
                    startTime = filteredReadings.Keys.Min(),
                    endTime = filteredReadings.Keys.Max(),
                };

                byte[] responsePayload = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(report));
                return Task.FromResult(new MethodResponse(responsePayload, (int)StatusCode.Completed));
            }

            return Task.FromResult(new MethodResponse((int)StatusCode.NotFound));
        }

        return Task.FromResult(new MethodResponse((int)StatusCode.NotFound));
    }
    catch (JsonReaderException ex)
    {
        // ...
    }
}

Bağlantı bilgilerini alma

Bu öğreticide daha sonra örnek cihaz uygulamasını çalıştırdığınızda aşağıdaki yapılandırma değerleri gerekir:

  • KIMLIK kapsamı: IoT Central uygulamanızda yönetim > cihaz bağlantısı' na gidin. Kimlik kapsamı değerini bir yere getirin.
  • Birincil anahtarı grupla: IoT Central uygulamanızda yönetim > cihaz bağlantısı > SAS-IoT-cihazlar' a gidin. Paylaşılan erişim imzası birincil anahtar değerini bir yere getirin.

Aldığınız grup birincil anahtarından bir cihaz anahtarı oluşturmak için Cloud Shell kullanın:

az extension add --name azure-iot
az iot central device compute-device-key --device-id sample-device-01 --pk <the group primary key value>

Oluşturulan Cihaz anahtarını bir yere getirin, bu öğreticide daha sonra kullanın.

Kodu çalıştırma

Örnek uygulamayı Visual Studio:

  1. Bu Çözüm Gezgini, TemperatureController proje dosyası için PnpDeviceSamples > seçin.

  2. Hata Ayıklama Project > TemperatureController Özellikleri'> gidin. Ardından aşağıdaki ortam değişkenlerini projeye ekleyin:

    Name Değer
    IOTHUB_DEVICE_SECURITY_TYPE DPS
    IOTHUB_DEVICE_DPS_ENDPOINT global.azure-devices-provisioning.net
    IOTHUB_DEVICE_DPS_ID_SCOPE Daha önce not defterine not alan kimlik kapsamı değeri.
    IOTHUB_DEVICE_DPS_DEVICE_ID sample-device-01
    IOTHUB_DEVICE_DPS_DEVICE_KEY Daha önce not edinen, oluşturulan cihaz anahtarı değeri.

Artık örneği çalıştırarak hata ayıklamak için Visual Studio.

Aşağıdaki çıkışta cihaz kaydı ve cihaza bağlanma IoT Central. Örnek telemetri göndermeye başlar:

[03/31/2021 14:43:17]info: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
      Press Control+C to quit the sample.
[03/31/2021 14:43:17]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
      Set up the device client.
[03/31/2021 14:43:18]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
      Initializing via DPS
[03/31/2021 14:43:27]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
      Set handler for 'reboot' command.
[03/31/2021 14:43:27]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
      Connection status change registered - status=Connected, reason=Connection_Ok.
[03/31/2021 14:43:28]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
      Set handler for "getMaxMinReport" command.
[03/31/2021 14:43:28]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
      Set handler to receive 'targetTemperature' updates.
[03/31/2021 14:43:28]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
      Property: Update - component = 'deviceInformation', properties update is complete.
[03/31/2021 14:43:28]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
      Property: Update - { "serialNumber": "SR-123456" } is complete.
[03/31/2021 14:43:29]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
      Telemetry: Sent - component="thermostat1", { "temperature": 34.2 } in °C.
[03/31/2021 14:43:29]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
      Property: Update - component="thermostat1", { "maxTempSinceLastReboot": 34.2 } in °C is complete.
[03/31/2021 14:43:29]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
      Telemetry: Sent - component="thermostat2", { "temperature": 25.1 } in °C.
[03/31/2021 14:43:29]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
      Property: Update - component="thermostat2", { "maxTempSinceLastReboot": 25.1 } in °C is complete.
[03/31/2021 14:43:29]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
      Telemetry: Sent - {"workingSet":31412} in KB.

Uygulamanıza işleç olarak Azure IoT Central şunları gerçekleştirebilirsiniz:

  • Genel Bakış sayfasında iki termostat bileşeni tarafından gönderilen telemetrisini görüntüleyebilirsiniz:

    Cihaz telemetrisini görüntüleme

  • Hakkında sayfasında cihaz özelliklerini görüntüleme. Bu sayfada cihaz bilgileri bileşeni ve iki termostat bileşeninden özellikler görüntülenir:

    Cihaz özelliklerini görüntüleme

Cihaz şablonunu özelleştirme

Çözüm geliştiricisi olarak, sıcaklık denetleyicisi cihazı bağlandığında otomatik IoT Central oluşturulan cihaz şablonunu özelleştirebilirsiniz.

Cihazla ilişkili müşteri adını depolamak için bir bulut özelliği eklemek için:

  1. Uygulama IoT Central Cihaz şablonları sayfasında Temperature Controller cihaz şablonuna gidin.

  2. Sıcaklık Denetleyicisi cihaz şablonunda Bulut özellikleri'ne tıklayın.

  3. Bulut özelliği ekle'yi seçin. Görünen ad olarak Müşteri adı girin, girişi genişletin ve Şema olarak Dize'yi seçin. Sonra Kaydet'i seçin.

Get Max-Min rapor komutlarının uygulamanıza nasıl görüntü IoT Central için:

  1. Cihaz şablonunda Özelleştir'i seçin.

  2. getMaxMinReport (thermostat1) için Get Max-Min değiştirin. termostat1 durum raporunu al ile.

  3. getMaxMinReport (termostat2) için Get Max-Min değiştirin. termostat2 durum raporunu al ile.

  4. Kaydet’i seçin.

Hedef Sıcaklık yazılabilir özelliklerinin uygulamanıza nasıl görüntü IoT Central için:

  1. Cihaz şablonunda Özelleştir'i seçin.

  2. targetTemperature (termostat1) için Hedef Sıcaklığı Hedef Sıcaklık (1) ile değiştirin.

  3. targetTemperature (termostat2) için Hedef Sıcaklığı Hedef Sıcaklık (2) ile değiştirin.

  4. Kaydet’i seçin.

Sıcaklık Denetleyicisi modelinde termostat bileşenleri Hedef Sıcaklık yazılabilir özelliğini, cihaz şablonu ise Müşteri Adı bulut özelliğini içerir. Bir operatörün şu özellikleri düzenlemek için kullanabileceği bir görünüm oluşturun:

  1. Görünümler'i ve ardından Cihaz ve bulut verilerini düzenleme kutucuğunu seçin.

  2. Form adı olarak Özellikler girin.

  3. Hedef Sıcaklık (1), Hedef Sıcaklık (2) ve Müşteri Adı özelliklerini seçin. Ardından Bölüm ekle'yi seçin.

  4. Yaptığınız değişiklikleri kaydedin.

Özellik değerlerini güncelleştirmek için görüntüleme

Cihaz şablonunu yayımlama

Operatör, sizin yapmış olduğunu özelleştirmeleri görene ve kullanamadan önce cihaz şablonunu yayımlamanız gerekir.

Thermostat cihaz şablonundan Yayımla'yı seçin. Bu cihazı yayımla şablonunu uygulama panelinde Yayımla'yı seçin.

Operatör artık özellik değerlerini güncelleştirmek için Özellikler görünümünü kullanabilir ve cihaz komutları sayfasındaKi Termostat1 durum raporunu al ve Termostat2 durum raporunu al adlı komutları çağırabilirsiniz:

  • Özellikler sayfasında yazılabilir özellik değerlerini güncelleştirin:

    Cihaz özelliklerini güncelleştirme

  • Komutlar sayfasından komutları çağırma. Durum raporu komutunu çalıştırmadan önce Since parametresi için bir tarih ve saat seçin:

    komutunu çağırma

    Komut yanıtını görüntüleme

Cihazın komutlara ve özellik güncelleştirmelerine nasıl yanıt verir?

[03/31/2021 14:47:00]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
      Command: Received - component="thermostat2", generating max, min and avg temperature report since 31/03/2021 06:00:00.
[03/31/2021 14:47:00]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
      Command: component="thermostat2", MaxMinReport since 31/03/2021 06:00:00: maxTemp=36.4, minTemp=36.4, avgTemp=36.4, startTime=31/03/2021 14:46:33, endTime=31/03/2021 14:46:55

...

[03/31/2021 14:46:36]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
      Property: Received - component="thermostat1", { "targetTemperature": 67°C }.
[03/31/2021 14:46:36]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
      Property: Update - component="thermostat1", {"targetTemperature": 67 } in °C is InProgress.
[03/31/2021 14:46:49]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
      Property: Update - component="thermostat1", {"targetTemperature": 67 } in °C is Completed
[03/31/2021 14:46:49]dbug: Microsoft.Azure.Devices.Client.Samples.TemperatureControllerSample[0]
      Telemetry: Sent - component="thermostat1", { "temperature": 67 } in °C.

Koda göz atın

Önkoşullar

Bu makaledeki adımları tamamlamak için aşağıdaki kaynaklar gereklidir:

Kodu gözden geçirin

Daha önce indirdiğiniz Java için Microsoft Azure IoT SDK'sı kopyasında, azure-iot-sdk-java/device/iot-device-samples/pnp-device-sample/temperature-controller-device-sample/src/main/java/samples/com/microsoft/azure/sdk/iot/device/TemperatureController.java dosyasını bir metin düzenleyicisinde açın.

IoT Central'a bağlanmak için örneği IoT Central, cihazı kaydetmek ve bir bağlantı dizesi oluşturmak için Cihaz Sağlama Hizmeti'nin (DPS) kullanır. Örnek, ihtiyacı olan DPS bağlantı bilgilerini komut satırı ortamından almaktadır.

mainyöntemi:

  • Model kimliğini ayarlama, cihazı sağlama ve kaydetme, DeviceClient örneği oluşturma ve cihaz uygulamanıza bağlanmak için initializeAndProvisionDevice dtmi:com:example:TemperatureController;2 DPS'IoT Central çağrıları. IoT Central, bu cihaz için cihaz şablonunu tanımlamak veya oluşturmak için model kimliğini kullanır. Daha fazla bilgi için bkz. Cihazı cihaz şablonuyla ilişkilendirme.
  • ve komutları için komut getMaxMinReport işleyicileri reboot oluşturur.
  • Yazılabilir özellikler için özellik güncelleştirme işleyicileri targetTemperature oluşturur.
  • Cihaz Bilgileri arabirimi ve Cihaz Belleği ve Seri Numarası özellikleri için ilk değerleri gönderir.
  • İki termostattan sıcaklık telemetrisi göndermek ve beş saniyede bir özelliği güncelleştirmek maxTempSinceLastReboot için bir iş parçacığı başlatır.
public static void main(String[] args) throws IOException, URISyntaxException, ProvisioningDeviceClientException, InterruptedException {

  // ...
  
  switch (deviceSecurityType.toLowerCase())
  {
    case "dps":
    {
      if (validateArgsForDpsFlow())
      {
        initializeAndProvisionDevice();
        break;
      }
      throw new IllegalArgumentException("Required environment variables are not set for DPS flow, please recheck your environment.");
    }
    case "connectionstring":
    {
      // ...
    }
    default:
    {
      // ...
    }
  }
  
  deviceClient.subscribeToDeviceMethod(new MethodCallback(), null, new MethodIotHubEventCallback(), null);
  
  deviceClient.startDeviceTwin(new TwinIotHubEventCallback(), null, new GenericPropertyUpdateCallback(), null);
  Map<Property, Pair<TwinPropertyCallBack, Object>> desiredPropertyUpdateCallback = Stream.of(
      new AbstractMap.SimpleEntry<Property, Pair<TwinPropertyCallBack, Object>>(
          new Property(THERMOSTAT_1, null),
          new Pair<>(new TargetTemperatureUpdateCallback(), THERMOSTAT_1)),
      new AbstractMap.SimpleEntry<Property, Pair<TwinPropertyCallBack, Object>>(
          new Property(THERMOSTAT_2, null),
          new Pair<>(new TargetTemperatureUpdateCallback(), THERMOSTAT_2))
  ).collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));
  
  deviceClient.subscribeToTwinDesiredProperties(desiredPropertyUpdateCallback);
  
  updateDeviceInformation();
  sendDeviceMemory();
  sendDeviceSerialNumber();
  
  final AtomicBoolean temperatureReset = new AtomicBoolean(true);
  maxTemperature.put(THERMOSTAT_1, 0.0d);
  maxTemperature.put(THERMOSTAT_2, 0.0d);
  
  new Thread(new Runnable() {
    @SneakyThrows({InterruptedException.class, IOException.class})
    @Override
    public void run() {
      while (true) {
        if (temperatureReset.get()) {
          // Generate a random value between 5.0°C and 45.0°C for the current temperature reading for each "Thermostat" component.
          temperature.put(THERMOSTAT_1, BigDecimal.valueOf(random.nextDouble() * 40 + 5).setScale(1, RoundingMode.HALF_UP).doubleValue());
          temperature.put(THERMOSTAT_2, BigDecimal.valueOf(random.nextDouble() * 40 + 5).setScale(1, RoundingMode.HALF_UP).doubleValue());
        }

        sendTemperatureReading(THERMOSTAT_1);
        sendTemperatureReading(THERMOSTAT_2);

        temperatureReset.set(temperature.get(THERMOSTAT_1) == 0 && temperature.get(THERMOSTAT_2) == 0);
        Thread.sleep(5 * 1000);
      }
    }
  }).start();
}

yöntemi, initializeAndProvisionDevice cihazın DPS'i kullanarak nasıl kayıt olduğunu ve IoT Central. Yük, cihazı bir cihaz şablonuyla IoT Central için kullandığı model kimliğini içerir:

private static void initializeAndProvisionDevice() throws ProvisioningDeviceClientException, IOException, URISyntaxException, InterruptedException {
  SecurityProviderSymmetricKey securityClientSymmetricKey = new SecurityProviderSymmetricKey(deviceSymmetricKey.getBytes(), registrationId);
  ProvisioningDeviceClient provisioningDeviceClient;
  ProvisioningStatus provisioningStatus = new ProvisioningStatus();

  provisioningDeviceClient = ProvisioningDeviceClient.create(globalEndpoint, scopeId, provisioningProtocol, securityClientSymmetricKey);

  AdditionalData additionalData = new AdditionalData();
  additionalData.setProvisioningPayload(com.microsoft.azure.sdk.iot.provisioning.device.plugandplay.PnpHelper.createDpsPayload(MODEL_ID));

  provisioningDeviceClient.registerDevice(new ProvisioningDeviceClientRegistrationCallbackImpl(), provisioningStatus, additionalData);

  while (provisioningStatus.provisioningDeviceClientRegistrationInfoClient.getProvisioningDeviceClientStatus() != ProvisioningDeviceClientStatus.PROVISIONING_DEVICE_STATUS_ASSIGNED)
  {
    if (provisioningStatus.provisioningDeviceClientRegistrationInfoClient.getProvisioningDeviceClientStatus() == ProvisioningDeviceClientStatus.PROVISIONING_DEVICE_STATUS_ERROR ||
        provisioningStatus.provisioningDeviceClientRegistrationInfoClient.getProvisioningDeviceClientStatus() == ProvisioningDeviceClientStatus.PROVISIONING_DEVICE_STATUS_DISABLED ||
        provisioningStatus.provisioningDeviceClientRegistrationInfoClient.getProvisioningDeviceClientStatus() == ProvisioningDeviceClientStatus.PROVISIONING_DEVICE_STATUS_FAILED)
    {
      provisioningStatus.exception.printStackTrace();
      System.out.println("Registration error, bailing out");
      break;
    }
    System.out.println("Waiting for Provisioning Service to register");
    Thread.sleep(MAX_TIME_TO_WAIT_FOR_REGISTRATION);
  }

  ClientOptions options = new ClientOptions();
  options.setModelId(MODEL_ID);

  if (provisioningStatus.provisioningDeviceClientRegistrationInfoClient.getProvisioningDeviceClientStatus() == ProvisioningDeviceClientStatus.PROVISIONING_DEVICE_STATUS_ASSIGNED) {
    System.out.println("IotHUb Uri : " + provisioningStatus.provisioningDeviceClientRegistrationInfoClient.getIothubUri());
    System.out.println("Device ID : " + provisioningStatus.provisioningDeviceClientRegistrationInfoClient.getDeviceId());

    String iotHubUri = provisioningStatus.provisioningDeviceClientRegistrationInfoClient.getIothubUri();
    String deviceId = provisioningStatus.provisioningDeviceClientRegistrationInfoClient.getDeviceId();

    deviceClient = DeviceClient.createFromSecurityProvider(iotHubUri, deviceId, securityClientSymmetricKey, IotHubClientProtocol.MQTT, options);
    deviceClient.open();
  }
}

yöntemi, sendTemperatureTelemetry cihazın sıcaklık telemetrisini bir bileşenden cihaza nasıl IoT Central. Bu yöntem, PnpConvention iletiyi oluşturmak için sınıfını kullanır:

  private static void sendTemperatureTelemetry(String componentName) {
    String telemetryName = "temperature";
    double currentTemperature = temperature.get(componentName);

    Message message = PnpConvention.createIotHubMessageUtf8(telemetryName, currentTemperature, componentName);
    deviceClient.sendEventAsync(message, new MessageIotHubEventCallback(), message);

    // Add the current temperature entry to the list of temperature readings.
    Map<Date, Double> currentReadings;
    if (temperatureReadings.containsKey(componentName)) {
      currentReadings = temperatureReadings.get(componentName);
    } else {
      currentReadings = new HashMap<>();
    }
    currentReadings.put(new Date(), currentTemperature);
    temperatureReadings.put(componentName, currentReadings);
  }

yöntemi, updateMaxTemperatureSinceLastReboot bir maxTempSinceLastReboot bileşenden bir özellik güncelleştirmesini IoT Central. Bu yöntem, düzeltme PnpConvention ekini oluşturmak için sınıfını kullanır:

private static void updateMaxTemperatureSinceLastReboot(String componentName) throws IOException {
  String propertyName = "maxTempSinceLastReboot";
  double maxTemp = maxTemperature.get(componentName);

  Set<Property> reportedProperty = PnpConvention.createComponentPropertyPatch(propertyName, maxTemp, componentName);
  deviceClient.sendReportedProperties(reportedProperty);
}

sınıfı, TargetTemperatureUpdateCallback bir TwinPropertyCallBack bileşene ait yazılabilir özellik güncelleştirmelerini işlemek için IoT Central. Bu yöntem, PnpConvention yanıtı oluşturmak için sınıfını kullanır:

private static class TargetTemperatureUpdateCallback implements TwinPropertyCallBack {

  final String propertyName = "targetTemperature";

  @SneakyThrows({IOException.class, InterruptedException.class})
  @Override
  public void TwinPropertyCallBack(Property property, Object context) {
    String componentName = (String) context;

    if (property.getKey().equalsIgnoreCase(componentName)) {
      double targetTemperature = (double) ((TwinCollection) property.getValue()).get(propertyName);

      Set<Property> pendingPropertyPatch = PnpConvention.createComponentWritablePropertyResponse(
          propertyName,
          targetTemperature,
          componentName,
          StatusCode.IN_PROGRESS.value,
          property.getVersion().longValue(),
          null);
      deviceClient.sendReportedProperties(pendingPropertyPatch);

      // Update temperature in 2 steps
      double step = (targetTemperature - temperature.get(componentName)) / 2;
      for (int i = 1; i <=2; i++) {
        temperature.put(componentName, BigDecimal.valueOf(temperature.get(componentName) + step).setScale(1, RoundingMode.HALF_UP).doubleValue());
        Thread.sleep(5 * 1000);
      }

      Set<Property> completedPropertyPatch = PnpConvention.createComponentWritablePropertyResponse(
          propertyName,
          temperature.get(componentName),
          componentName,
          StatusCode.COMPLETED.value,
          property.getVersion().longValue(),
          "Successfully updated target temperature.");
      deviceClient.sendReportedProperties(completedPropertyPatch);
    } else {
        // ...
    }
  }
}

sınıfı, MethodCallback aşağıdaki call komutlardan çağrılır bileşen komutlarını işlemek için IoT Central:

private static class MethodCallback implements DeviceMethodCallback {
  final String reboot = "reboot";
  final String getMaxMinReport1 = "thermostat1*getMaxMinReport";
  final String getMaxMinReport2 = "thermostat2*getMaxMinReport";

  @SneakyThrows(InterruptedException.class)
  @Override
  public DeviceMethodData call(String methodName, Object methodData, Object context) {
    String jsonRequest = new String((byte[]) methodData, StandardCharsets.UTF_8);

    switch (methodName) {
      case reboot:
        int delay = getCommandRequestValue(jsonRequest, Integer.class);
        Thread.sleep(delay * 1000L);

        temperature.put(THERMOSTAT_1, 0.0d);
        temperature.put(THERMOSTAT_2, 0.0d);

        maxTemperature.put(THERMOSTAT_1, 0.0d);
        maxTemperature.put(THERMOSTAT_2, 0.0d);

        temperatureReadings.clear();
        return new DeviceMethodData(StatusCode.COMPLETED.value, null);

        case getMaxMinReport1:
        case getMaxMinReport2:
          String[] words = methodName.split("\\*");
          String componentName = words[0];

          if (temperatureReadings.containsKey(componentName)) {
            Date since = getCommandRequestValue(jsonRequest, Date.class);

            Map<Date, Double> allReadings = temperatureReadings.get(componentName);
            Map<Date, Double> filteredReadings = allReadings.entrySet().stream()
                .filter(map -> map.getKey().after(since))
                .collect(Collectors.toMap(Entry::getKey, Entry::getValue));

            if (!filteredReadings.isEmpty()) {
              SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
              double maxTemp = Collections.max(filteredReadings.values());
              double minTemp = Collections.min(filteredReadings.values());
              double avgTemp = filteredReadings.values().stream().mapToDouble(Double::doubleValue).average().orElse(Double.NaN);
              String startTime =  sdf.format(Collections.min(filteredReadings.keySet()));
              String endTime =  sdf.format(Collections.max(filteredReadings.keySet()));

              String responsePayload = String.format(
                  "{\"maxTemp\": %.1f, \"minTemp\": %.1f, \"avgTemp\": %.1f, \"startTime\": \"%s\", \"endTime\": \"%s\"}",
                  maxTemp,
                  minTemp,
                  avgTemp,
                  startTime,
                  endTime);

              return new DeviceMethodData(StatusCode.COMPLETED.value, responsePayload);
            }

            return new DeviceMethodData(StatusCode.NOT_FOUND.value, null);
          }

          return new DeviceMethodData(StatusCode.NOT_FOUND.value, null);

        default:
            return new DeviceMethodData(StatusCode.NOT_FOUND.value, null);
    }
  }
}

Bağlantı bilgilerini alma

Bu öğreticide daha sonra örnek cihaz uygulamasını çalıştırdığınızda aşağıdaki yapılandırma değerleri gerekir:

  • KIMLIK kapsamı: IoT Central uygulamanızda yönetim > cihaz bağlantısı' na gidin. Kimlik kapsamı değerini bir yere getirin.
  • Birincil anahtarı grupla: IoT Central uygulamanızda yönetim > cihaz bağlantısı > SAS-IoT-cihazlar' a gidin. Paylaşılan erişim imzası birincil anahtar değerini bir yere getirin.

Aldığınız grup birincil anahtarından bir cihaz anahtarı oluşturmak için Cloud Shell kullanın:

az extension add --name azure-iot
az iot central device compute-device-key --device-id sample-device-01 --pk <the group primary key value>

Oluşturulan Cihaz anahtarını bir yere getirin, bu öğreticide daha sonra kullanın.

Bu Windows, indirdiğiniz Java için Azure IoT SDK deposunun kök klasörüne gidin.

Örnek uygulamayı derlemek için aşağıdaki komutu çalıştırın:

mvn install -T 2C -DskipTests

Kodu çalıştırma

Örnek uygulamayı çalıştırmak için bir komut satırı ortamı açın ve TemperatureController.java örnek dosyası ile src klasörünü içeren azure-iot-sdk-java/device/iot-device-samples/pnp-device-sample/temperature-controller-device-sample klasörüne gidin.

Örneği yapılandırmak için ortam değişkenlerini ayarlayın. Aşağıdaki kod parçacığında, Windows komut isteminde ortam değişkenlerinin nasıl ayarlanacağı gösterilmektedir. Bash kabuğu kullanıyorsanız, komutları komutlarla değiştirin set export :

set IOTHUB_DEVICE_SECURITY_TYPE=DPS
set IOTHUB_DEVICE_DPS_ID_SCOPE=<The ID scope you made a note of previously>
set IOTHUB_DEVICE_DPS_DEVICE_ID=sample-device-01
set IOTHUB_DEVICE_DPS_DEVICE_KEY=<The generated device key you made a note of previously>
set IOTHUB_DEVICE_DPS_ENDPOINT=global.azure-devices-provisioning.net

Örneği çalıştırın:

mvn exec:java -Dexec.mainClass="samples.com.microsoft.azure.sdk.iot.device.TemperatureController"

Aşağıdaki çıkışta cihaz kaydı ve cihaza bağlanma IoT Central. Örnek telemetri göndermeye başlar:

2021-03-30 15:33:25.138 DEBUG TemperatureController:123 - Initialize the device client.
Waiting for Provisioning Service to register
Waiting for Provisioning Service to register
IotHUb Uri : iotc-60a.....azure-devices.net
Device ID : sample-device-01
2021-03-30 15:33:38.294 DEBUG TemperatureController:247 - Opening the device client.
2021-03-30 15:33:38.307 INFO  ExponentialBackoffWithJitter:98 - NOTE: A new instance of ExponentialBackoffWithJitter has been created with the following properties. Retry Count: 2147483647, Min Backoff Interval: 100, Max Backoff Interval: 10000, Max Time Between Retries: 100, Fast Retry Enabled: true
2021-03-30 15:33:38.321 INFO  ExponentialBackoffWithJitter:98 - NOTE: A new instance of ExponentialBackoffWithJitter has been created with the following properties. Retry Count: 2147483647, Min Backoff Interval: 100, Max Backoff Interval: 10000, Max Time Between Retries: 100, Fast Retry Enabled: true
2021-03-30 15:33:38.427 DEBUG MqttIotHubConnection:274 - Opening MQTT connection...
2021-03-30 15:33:38.427 DEBUG Mqtt:123 - Sending MQTT CONNECT packet...
2021-03-30 15:33:44.628 DEBUG Mqtt:126 - Sent MQTT CONNECT packet was acknowledged
2021-03-30 15:33:44.630 DEBUG Mqtt:256 - Sending MQTT SUBSCRIBE packet for topic devices/sample-device-01/messages/devicebound/#
2021-03-30 15:33:44.731 DEBUG Mqtt:261 - Sent MQTT SUBSCRIBE packet for topic devices/sample-device-01/messages/devicebound/# was acknowledged
2021-03-30 15:33:44.733 DEBUG MqttIotHubConnection:279 - MQTT connection opened successfully
2021-03-30 15:33:44.733 DEBUG IotHubTransport:302 - The connection to the IoT Hub has been established
2021-03-30 15:33:44.734 INFO  IotHubTransport:1429 - Updating transport status to new status CONNECTED with reason CONNECTION_OK
2021-03-30 15:33:44.735 DEBUG IotHubTransport:1439 - Invoking connection status callbacks with new status details
2021-03-30 15:33:44.739 DEBUG IotHubTransport:394 - Client connection opened successfully
2021-03-30 15:33:44.740 INFO  DeviceClient:438 - Device client opened successfully
2021-03-30 15:33:44.740 DEBUG TemperatureController:152 - Set handler for "reboot" command.
2021-03-30 15:33:44.742 DEBUG TemperatureController:153 - Set handler for "getMaxMinReport" command.
2021-03-30 15:33:44.774 INFO  IotHubTransport:489 - Message was queued to be sent later ( Message details: Correlation Id [029d30d4-acbd-462d-b155-82d53ce7786c] Message Id [1b2adf93-ba81-41e4-b8c7-7c90c8b0d6a1] Device Operation Type [DEVICE_OPERATION_METHOD_SUBSCRIBE_REQUEST] )
2021-03-30 15:33:44.774 DEBUG TemperatureController:156 - Set handler to receive "targetTemperature" updates.
2021-03-30 15:33:44.775 INFO  IotHubTransport:1344 - Sending message ( Message details: Correlation Id [029d30d4-acbd-462d-b155-82d53ce7786c] Message Id [1b2adf93-ba81-41e4-b8c7-7c90c8b0d6a1] Device Operation Type [DEVICE_OPERATION_METHOD_SUBSCRIBE_REQUEST] )
2021-03-30 15:33:44.779 DEBUG Mqtt:256 - Sending MQTT SUBSCRIBE packet for topic $iothub/methods/POST/#
2021-03-30 15:33:44.793 INFO  IotHubTransport:489 - Message was queued to be sent later ( Message details: Correlation Id [f2f9ed95-9778-44f2-b9ec-f60c84061251] Message Id [0d5abdb2-6460-414c-a10e-786ee24cacff] Device Operation Type [DEVICE_OPERATION_TWIN_SUBSCRIBE_DESIRED_PROPERTIES_REQUEST] )
2021-03-30 15:33:44.794 INFO  IotHubTransport:489 - Message was queued to be sent later ( Message details: Correlation Id [417d659a-7324-43fa-84eb-8a3f3d07963c] Message Id [55532cad-8a5a-489f-9aa8-8f0e5bc21541] Request Id [0] Device Operation Type [DEVICE_OPERATION_TWIN_GET_REQUEST] )
2021-03-30 15:33:44.819 INFO  IotHubTransport:489 - Message was queued to be sent later ( Message details: Correlation Id [d46a0d8a-8a18-4014-abeb-768bd9b17ad2] Message Id [780abc81-ce42-4e5f-aa80-e4785883604e] Device Operation Type [DEVICE_OPERATION_TWIN_SUBSCRIBE_DESIRED_PROPERTIES_REQUEST] )
2021-03-30 15:33:44.881 DEBUG Mqtt:261 - Sent MQTT SUBSCRIBE packet for topic $iothub/methods/POST/# was acknowledged
2021-03-30 15:33:44.882 INFO  IotHubTransport:1344 - Sending message ( Message details: Correlation Id [f2f9ed95-9778-44f2-b9ec-f60c84061251] Message Id [0d5abdb2-6460-414c-a10e-786ee24cacff] Device Operation Type [DEVICE_OPERATION_TWIN_SUBSCRIBE_DESIRED_PROPERTIES_REQUEST] )
2021-03-30 15:33:44.882 DEBUG Mqtt:256 - Sending MQTT SUBSCRIBE packet for topic $iothub/twin/res/#
2021-03-30 15:33:44.893 INFO  IotHubTransport:489 - Message was queued to be sent later ( Message details: Correlation Id [a77b1c02-f043-4477-b610-e31a774772c0] Message Id [2e2f6bee-c480-42cf-ac31-194118930846] Request Id [1] Device Operation Type [DEVICE_OPERATION_TWIN_UPDATE_REPORTED_PROPERTIES_REQUEST] )
2021-03-30 15:33:44.904 DEBUG TemperatureController:423 - Property: Update - component = "deviceInformation" is COMPLETED.
2021-03-30 15:33:44.915 INFO  IotHubTransport:489 - Message was queued to be sent later ( Message details: Correlation Id [bbb7e3cf-3550-4fdf-90f9-0787740f028a] Message Id [e06ac385-ae0d-46dd-857a-d9725707527a] )
2021-03-30 15:33:44.915 DEBUG TemperatureController:434 - Telemetry: Sent - {"workingSet": 1024.0KiB }
2021-03-30 15:33:44.915 INFO  IotHubTransport:489 - Message was queued to be sent later ( Message details: Correlation Id [6dbef765-cc9a-4e72-980a-2fe5b0cd77e1] Message Id [49bbad33-09bf-417a-9d6e-299ba7b7c562] Request Id [2] Device Operation Type [DEVICE_OPERATION_TWIN_UPDATE_REPORTED_PROPERTIES_REQUEST] )
2021-03-30 15:33:44.916 DEBUG TemperatureController:442 - Property: Update - {"serialNumber": SR-123456} is COMPLETED
2021-03-30 15:33:44.927 INFO  IotHubTransport:489 - Message was queued to be sent later ( Message details: Correlation Id [86787c32-87a5-4c49-9083-c7f2b17446a7] Message Id [0a45fa0c-a467-499d-b214-9bb5995772ba] )
2021-03-30 15:33:44.927 DEBUG TemperatureController:461 - Telemetry: Sent - {"temperature": 5.8°C} with message Id 0a45fa0c-a467-499d-b214-9bb5995772ba.

Uygulamanıza işleç olarak Azure IoT Central şunları gerçekleştirebilirsiniz:

  • Genel Bakış sayfasında iki termostat bileşeni tarafından gönderilen telemetrisini görüntüleyebilirsiniz:

    Cihaz telemetrisini görüntüleme

  • Hakkında sayfasında cihaz özelliklerini görüntüleme. Bu sayfada cihaz bilgileri bileşeni ve iki termostat bileşeninden özellikler görüntülenir:

    Cihaz özelliklerini görüntüleme

Cihaz şablonunu özelleştirme

Çözüm geliştiricisi olarak, sıcaklık denetleyicisi cihazı bağlandığında otomatik IoT Central oluşturulan cihaz şablonunu özelleştirebilirsiniz.

Cihazla ilişkili müşteri adını depolamak için bir bulut özelliği eklemek için:

  1. Uygulama IoT Central Cihaz şablonları sayfasında Temperature Controller cihaz şablonuna gidin.

  2. Sıcaklık Denetleyicisi cihaz şablonunda Bulut özellikleri'ne tıklayın.

  3. Bulut özelliği ekle'yi seçin. Görünen ad olarak Müşteri adı girin, girişi genişletin ve Şema olarak Dize'yi seçin. Sonra Kaydet'i seçin.

Get Max-Min rapor komutlarının uygulamanıza nasıl görüntü IoT Central için:

  1. Cihaz şablonunda Özelleştir'i seçin.

  2. getMaxMinReport (thermostat1) için Get Max-Min değiştirin. termostat1 durum raporunu al ile.

  3. getMaxMinReport (termostat2) için Get Max-Min değiştirin. termostat2 durum raporunu al ile.

  4. Kaydet’i seçin.

Hedef Sıcaklık yazılabilir özelliklerinin uygulamanıza nasıl görüntü IoT Central için:

  1. Cihaz şablonunda Özelleştir'i seçin.

  2. targetTemperature (termostat1) için Hedef Sıcaklığı Hedef Sıcaklık (1) ile değiştirin.

  3. targetTemperature (termostat2) için Hedef Sıcaklığı Hedef Sıcaklık (2) ile değiştirin.

  4. Kaydet’i seçin.

Sıcaklık Denetleyicisi modelinde termostat bileşenleri Hedef Sıcaklık yazılabilir özelliğini, cihaz şablonu ise Müşteri Adı bulut özelliğini içerir. Bir operatörün şu özellikleri düzenlemek için kullanabileceği bir görünüm oluşturun:

  1. Görünümler'i ve ardından Cihaz ve bulut verilerini düzenleme kutucuğunu seçin.

  2. Form adı olarak Özellikler girin.

  3. Hedef Sıcaklık (1), Hedef Sıcaklık (2) ve Müşteri Adı özelliklerini seçin. Ardından Bölüm ekle'yi seçin.

  4. Yaptığınız değişiklikleri kaydedin.

Özellik değerlerini güncelleştirmek için görüntüleme

Cihaz şablonunu yayımlama

Operatör, sizin yapmış olduğunu özelleştirmeleri görene ve kullanamadan önce cihaz şablonunu yayımlamanız gerekir.

Thermostat cihaz şablonundan Yayımla'yı seçin. Bu cihazı yayımla şablonunu uygulama panelinde Yayımla'yı seçin.

Operatör artık özellik değerlerini güncelleştirmek için Özellikler görünümünü kullanabilir ve cihaz komutları sayfasındaKi Termostat1 durum raporunu al ve Termostat2 durum raporunu al adlı komutları çağırabilirsiniz:

  • Özellikler sayfasında yazılabilir özellik değerlerini güncelleştirin:

    Cihaz özelliklerini güncelleştirme

  • Komutlar sayfasından komutları çağırma. Durum raporu komutunu çalıştırmadan önce Since parametresi için bir tarih ve saat seçin:

    komutunu çağırma

    Komut yanıtını görüntüleme

Cihazın komutlara ve özellik güncelleştirmelerine nasıl yanıt verir?

2021-03-30 15:43:57.133 DEBUG TemperatureController:309 - Command: Received - component="thermostat1", generating min, max, avg temperature report since Tue Mar 30 06:00:00 BST 2021
2021-03-30 15:43:57.153 DEBUG TemperatureController:332 - Command: MaxMinReport since Tue Mar 30 06:00:00 BST 2021: "maxTemp": 35.6°C, "minTemp": 35.6°C, "avgTemp": 35.6°C, "startTime": 2021-03-30T15:43:41Z, "endTime": 2021-03-30T15:43:56Z
2021-03-30 15:43:57.394 DEBUG TemperatureController:502 - Command - Response from IoT Hub: command name=null, status=OK_EMPTY


...

2021-03-30 15:48:47.808 DEBUG TemperatureController:372 - Property: Received - component="thermostat2", {"targetTemperature": 67.0°C}.
2021-03-30 15:48:47.837 DEBUG TemperatureController:382 - Property: Update - component="thermostat2", {"targetTemperature": 67.0°C} is IN_PROGRESS

Koda göz atın

Önkoşullar

Bu makaledeki adımları tamamlamak için aşağıdaki kaynaklar gereklidir:

  • Node.js sürüm 6 veya üzeri yüklü bir geliştirme makinesi. node --versionSürümünüzü denetlemek için komut satırında çalıştırabilirsiniz. bu öğreticideki yönergeler, Windows komut isteminde node komutunu çalıştırmakta olduğunuzu varsayar. Ancak, diğer birçok işletim sisteminde Node.js kullanabilirsiniz.

  • örnek kodu içeren Node.jsGitHub deposu için Microsoft Azure ıot SDK 'sının yerel bir kopyası. Deponun bir kopyasını indirmek için bu bağlantıyı kullanın: ZIP 'i indirin. Sonra dosyayı yerel makinenizde uygun bir konuma ayıklayın.

Kodu gözden geçirin

daha önce indirdiğiniz Node.js Microsoft Azure ıot SDK kopyasında, Azure-ıot-SDK-node/device/samples/javascript/pnp/pnpTemperatureController.js dosyasını bir metin düzenleyicisinde açın.

IoT Central bağlanmak için örneği çalıştırdığınızda, cihazı kaydetmek ve bir bağlantı dizesi oluşturmak için cihaz sağlama hizmeti 'ni (DPS) kullanır. Örnek, gereken DPS bağlantı bilgilerini komut satırı ortamından alır.

mainYöntemi:

  • Bir client nesne oluşturur ve dtmi:com:example:TemperatureController;2 bağlantıyı açmadan önce model kimliğini ayarlar. IoT Central, bu cihazın cihaz şablonunu tanımlamak veya oluşturmak için model KIMLIĞINI kullanır. Daha fazla bilgi için bkz. cihaz şablonuyla bir cihazı ilişkilendirme.
  • Üç komut için komut işleyicileri oluşturur.
  • Her bir termostat bileşeni için her 5 saniyede bir sıcaklık telemetrisi göndermek üzere bir döngü başlatır.
  • Her 6 saniyede bir çalışma kümesi boyutu telemetrisi göndermek için varsayılan bileşen için bir döngü başlatır.
  • Her bir maxTempSinceLastReboot termostat bileşeni için özelliğini gönderir.
  • Cihaz bilgileri özelliklerini gönderir.
  • Üç bileşen için yazılabilir Özellikler işleyicileri oluşturur.
async function main() {
  // ...

  // fromConnectionString must specify a transport, coming from any transport package.
  const client = Client.fromConnectionString(deviceConnectionString, Protocol);
  console.log('Connecting using connection string: ' + deviceConnectionString);
  let resultTwin;

  try {
    // Add the modelId here
    await client.setOptions(modelIdObject);
    await client.open();
    console.log('Enabling the commands on the client');
    client.onDeviceMethod(commandNameGetMaxMinReport1, commandHandler);
    client.onDeviceMethod(commandNameGetMaxMinReport2, commandHandler);
    client.onDeviceMethod(commandNameReboot, commandHandler);

    // Send Telemetry after some interval
    let index1 = 0;
    let index2 = 0;
    let index3 = 0;
    intervalToken1 = setInterval(() => {
      const data = JSON.stringify(thermostat1.updateSensor().getCurrentTemperatureObject());
      sendTelemetry(client, data, index1, thermostat1ComponentName).catch((err) => console.log('error ', err.toString()));
      index1 += 1;
    }, 5000);

    intervalToken2 = setInterval(() => {
      const data = JSON.stringify(thermostat2.updateSensor().getCurrentTemperatureObject());
      sendTelemetry(client, data, index2, thermostat2ComponentName).catch((err) => console.log('error ', err.toString()));
      index2 += 1;
    }, 5500);


    intervalToken3 = setInterval(() => {
      const data = JSON.stringify({ workingset: 1 + (Math.random() * 90) });
      sendTelemetry(client, data, index3, null).catch((err) => console.log('error ', err.toString()));
      index3 += 1;
    }, 6000);

    // attach a standard input exit listener
    exitListener(client);

    try {
      resultTwin = await client.getTwin();
      // Only report readable properties
      const patchRoot = helperCreateReportedPropertiesPatch({ serialNumber: serialNumber }, null);
      const patchThermostat1Info = helperCreateReportedPropertiesPatch({
        maxTempSinceLastReboot: thermostat1.getMaxTemperatureValue(),
      }, thermostat1ComponentName);

      const patchThermostat2Info = helperCreateReportedPropertiesPatch({
        maxTempSinceLastReboot: thermostat2.getMaxTemperatureValue(),
      }, thermostat2ComponentName);

      const patchDeviceInfo = helperCreateReportedPropertiesPatch({
        manufacturer: 'Contoso Device Corporation',
        model: 'Contoso 47-turbo',
        swVersion: '10.89',
        osName: 'Contoso_OS',
        processorArchitecture: 'Contoso_x86',
        processorManufacturer: 'Contoso Industries',
        totalStorage: 65000,
        totalMemory: 640,
      }, deviceInfoComponentName);

      // the below things can only happen once the twin is there
      updateComponentReportedProperties(resultTwin, patchRoot, null);
      updateComponentReportedProperties(resultTwin, patchThermostat1Info, thermostat1ComponentName);
      updateComponentReportedProperties(resultTwin, patchThermostat2Info, thermostat2ComponentName);
      updateComponentReportedProperties(resultTwin, patchDeviceInfo, deviceInfoComponentName);
      desiredPropertyPatchListener(resultTwin, [thermostat1ComponentName, thermostat2ComponentName, deviceInfoComponentName]);
    } catch (err) {
      console.error('could not retrieve twin or report twin properties\n' + err.toString());
    }
  } catch (err) {
    console.error('could not connect Plug and Play client or could not attach interval function for telemetry\n' + err.toString());
  }
}

provisionDeviceİşlevi, cihazın IoT Central kaydetmek ve bağlanmak IÇIN DPS nasıl kullandığını gösterir. Yük, cihazı cihaz şablonuyla ilişkilendirmekiçin IoT Central tarafından kullanılan model kimliğini içerir:

async function provisionDevice(payload) {
  var provSecurityClient = new SymmetricKeySecurityClient(registrationId, symmetricKey);
  var provisioningClient = ProvisioningDeviceClient.create(provisioningHost, idScope, new ProvProtocol(), provSecurityClient);

  if (!!(payload)) {
    provisioningClient.setProvisioningPayload(payload);
  }

  try {
    let result = await provisioningClient.register();
    deviceConnectionString = 'HostName=' + result.assignedHub + ';DeviceId=' + result.deviceId + ';SharedAccessKey=' + symmetricKey;
    console.log('registration succeeded');
    console.log('assigned hub=' + result.assignedHub);
    console.log('deviceId=' + result.deviceId);
    console.log('payload=' + JSON.stringify(result.payload));
  } catch (err) {
    console.error("error registering device: " + err.toString());
  }
}

sendTelemetryİşlevi, cihazın sıcaklık telemetrisini IoT Central nasıl göndereceğini gösterir. Bileşenlerinden telemetri için bileşen adı ile çağrılan bir özelliği ekler $.sub :

async function sendTelemetry(deviceClient, data, index, componentName) {
  if (!!(componentName)) {
    console.log('Sending telemetry message %d from component: %s ', index, componentName);
  } else {
    console.log('Sending telemetry message %d from root interface', index);
  }
  const msg = new Message(data);
  if (!!(componentName)) {
    msg.properties.add(messageSubjectProperty, componentName);
  }
  msg.contentType = 'application/json';
  msg.contentEncoding = 'utf-8';
  await deviceClient.sendEvent(msg);
}

mainYöntemi, helperCreateReportedPropertiesPatch özellik güncelleştirme iletileri oluşturmak için çağrılan bir yardımcı yöntemi kullanır. Bu yöntem, özelliği gönderen bileşeni belirtmek için isteğe bağlı bir parametre alır.:

const helperCreateReportedPropertiesPatch = (propertiesToReport, componentName) => {
  let patch;
  if (!!(componentName)) {
    patch = { };
    propertiesToReport.__t = 'c';
    patch[componentName] = propertiesToReport;
  } else {
    patch = { };
    patch = propertiesToReport;
  }
  if (!!(componentName)) {
    console.log('The following properties will be updated for component: ' + componentName);
  } else {
    console.log('The following properties will be updated for root interface.');
  }
  console.log(patch);
  return patch;
};

mainYöntemi, IoT Central yazılabilir özelliklerde yapılan güncelleştirmeleri işlemek için aşağıdaki yöntemi kullanır. Yönteminin sürümü ve durum kodu ile yanıtı nasıl oluşturduğuna dikkat edin:

const desiredPropertyPatchListener = (deviceTwin, componentNames) => {
  deviceTwin.on('properties.desired', (delta) => {
    console.log('Received an update for device with value: ' + JSON.stringify(delta));
    Object.entries(delta).forEach(([key, values]) => {
      const version = delta.$version;
      if (!!(componentNames) && componentNames.includes(key)) { // then it is a component we are expecting
        const componentName = key;
        const patchForComponents = { [componentName]: {} };
        Object.entries(values).forEach(([propertyName, propertyValue]) => {
          if (propertyName !== '__t' && propertyName !== '$version') {
            console.log('Will update property: ' + propertyName + ' to value: ' + propertyValue + ' of component: ' + componentName);
            const propertyContent = { value: propertyValue };
            propertyContent.ac = 200;
            propertyContent.ad = 'Successfully executed patch';
            propertyContent.av = version;
            patchForComponents[componentName][propertyName] = propertyContent;
          }
        });
        updateComponentReportedProperties(deviceTwin, patchForComponents, componentName);
      }
      else if  (key !== '$version') { // individual property for root
        const patchForRoot = { };
        console.log('Will update property: ' + key + ' to value: ' + values + ' for root');
        const propertyContent = { value: values };
        propertyContent.ac = 200;
        propertyContent.ad = 'Successfully executed patch';
        propertyContent.av = version;
        patchForRoot[key] = propertyContent;
        updateComponentReportedProperties(deviceTwin, patchForRoot, null);
      }
    });
  });
};

mainYöntemi, IoT Central komutları işlemek için aşağıdaki yöntemleri kullanır:

const commandHandler = async (request, response) => {
  helperLogCommandRequest(request);
  switch (request.methodName) {
  case commandNameGetMaxMinReport1: {
    await sendCommandResponse(request, response, 200, thermostat1.getMaxMinReportObject());
    break;
  }
  case commandNameGetMaxMinReport2: {
    await sendCommandResponse(request, response, 200, thermostat2.getMaxMinReportObject());
    break;
  }
  case commandNameReboot: {
    await sendCommandResponse(request, response, 200, 'reboot response');
    break;
  }
  default:
    await sendCommandResponse(request, response, 404, 'unknown method');
    break;
  }
};

const sendCommandResponse = async (request, response, status, payload) => {
  try {
    await response.send(status, payload);
    console.log('Response to method: ' + request.methodName + ' sent successfully.' );
  } catch (err) {
    console.error('An error ocurred when sending a method response:\n' + err.toString());
  }
};

Bağlantı bilgilerini alma

Bu öğreticide daha sonra örnek cihaz uygulamasını çalıştırdığınızda aşağıdaki yapılandırma değerleri gerekir:

  • KIMLIK kapsamı: IoT Central uygulamanızda yönetim > cihaz bağlantısı' na gidin. Kimlik kapsamı değerini bir yere getirin.
  • Birincil anahtarı grupla: IoT Central uygulamanızda yönetim > cihaz bağlantısı > SAS-IoT-cihazlar' a gidin. Paylaşılan erişim imzası birincil anahtar değerini bir yere getirin.

Aldığınız grup birincil anahtarından bir cihaz anahtarı oluşturmak için Cloud Shell kullanın:

az extension add --name azure-iot
az iot central device compute-device-key --device-id sample-device-01 --pk <the group primary key value>

Oluşturulan Cihaz anahtarını bir yere getirin, bu öğreticide daha sonra kullanın.

Kodu çalıştırma

Örnek uygulamayı çalıştırmak için bir komut satırı ortamı açın ve pnpTemperatureController.js örnek dosyasını içeren Azure-IoT-SDK-node/Device/Samples/PNP klasörüne gidin.

Örneği yapılandırmak için ortam değişkenlerini ayarlayın. Aşağıdaki kod parçacığında, Windows komut isteminde ortam değişkenlerinin nasıl ayarlanacağı gösterilmektedir. Bash kabuğu kullanıyorsanız, komutları komutlarla değiştirin set export :

set IOTHUB_DEVICE_SECURITY_TYPE=DPS
set IOTHUB_DEVICE_DPS_ID_SCOPE=<The ID scope you made a note of previously>
set IOTHUB_DEVICE_DPS_DEVICE_ID=sample-device-01
set IOTHUB_DEVICE_DPS_DEVICE_KEY=<The generated device key you made a note of previously>
set IOTHUB_DEVICE_DPS_ENDPOINT=global.azure-devices-provisioning.net

Gerekli paketleri yükler:

npm install

Örneği çalıştırın:

node pnpTemperatureController.js

Aşağıdaki çıktı, IoT Central kaydetme ve bağlanma için cihazı gösterir. Örnek daha sonra maxTempSinceLastReboot özelliği Telemetriyi göndermeye başlamadan önce iki termostat bileşeninden gönderir:

registration succeeded
assigned hub=iotc-....azure-devices.net
deviceId=sample-device-01
payload=undefined
Connecting using connection string: HostName=iotc-....azure-devices.net;DeviceId=sample-device-01;SharedAccessKey=qdv...IpAo=
Enabling the commands on the client
Please enter q or Q to exit sample.
The following properties will be updated for root interface.
{ serialNumber: 'alwinexlepaho8329' }
The following properties will be updated for component: thermostat1
{ thermostat1: { maxTempSinceLastReboot: 1.5902294191855972, __t: 'c' } }
The following properties will be updated for component: thermostat2
{ thermostat2: { maxTempSinceLastReboot: 16.181771928614545, __t: 'c' } }
The following properties will be updated for component: deviceInformation
{ deviceInformation:
   { manufacturer: 'Contoso Device Corporation',
     model: 'Contoso 47-turbo',
     swVersion: '10.89',
     osName: 'Contoso_OS',
     processorArchitecture: 'Contoso_x86',
     processorManufacturer: 'Contoso Industries',
     totalStorage: 65000,
     totalMemory: 640,
     __t: 'c' } }
executed sample
Received an update for device with value: {"$version":1}
Properties have been reported for component: thermostat1
Properties have been reported for component: thermostat2
Properties have been reported for component: deviceInformation
Properties have been reported for root interface.
Sending telemetry message 0 from component: thermostat1 
Sending telemetry message 0 from component: thermostat2 
Sending telemetry message 0 from root interface

Uygulamanıza işleç olarak Azure IoT Central şunları gerçekleştirebilirsiniz:

  • Genel Bakış sayfasında iki termostat bileşeni tarafından gönderilen telemetrisini görüntüleyebilirsiniz:

    Cihaz telemetrisini görüntüleme

  • Hakkında sayfasında cihaz özelliklerini görüntüleme. Bu sayfada cihaz bilgileri bileşeni ve iki termostat bileşeninden özellikler görüntülenir:

    Cihaz özelliklerini görüntüleme

Cihaz şablonunu özelleştirme

Çözüm geliştiricisi olarak, sıcaklık denetleyicisi cihazı bağlandığında otomatik IoT Central oluşturulan cihaz şablonunu özelleştirebilirsiniz.

Cihazla ilişkili müşteri adını depolamak için bir bulut özelliği eklemek için:

  1. Uygulama IoT Central Cihaz şablonları sayfasında Temperature Controller cihaz şablonuna gidin.

  2. Sıcaklık Denetleyicisi cihaz şablonunda Bulut özellikleri'ne tıklayın.

  3. Bulut özelliği ekle'yi seçin. Görünen ad olarak Müşteri adı girin, girişi genişletin ve Şema olarak Dize'yi seçin. Sonra Kaydet'i seçin.

Get Max-Min rapor komutlarının uygulamanıza nasıl görüntü IoT Central için:

  1. Cihaz şablonunda Özelleştir'i seçin.

  2. getMaxMinReport (thermostat1) için Get Max-Min değiştirin. termostat1 durum raporunu al ile.

  3. getMaxMinReport (termostat2) için Get Max-Min değiştirin. termostat2 durum raporunu al ile.

  4. Kaydet’i seçin.

Hedef Sıcaklık yazılabilir özelliklerinin uygulamanıza nasıl görüntü IoT Central için:

  1. Cihaz şablonunda Özelleştir'i seçin.

  2. targetTemperature (termostat1) için Hedef Sıcaklığı Hedef Sıcaklık (1) ile değiştirin.

  3. targetTemperature (termostat2) için Hedef Sıcaklığı Hedef Sıcaklık (2) ile değiştirin.

  4. Kaydet’i seçin.

Sıcaklık Denetleyicisi modelinde termostat bileşenleri Hedef Sıcaklık yazılabilir özelliğini, cihaz şablonu ise Müşteri Adı bulut özelliğini içerir. Bir operatörün şu özellikleri düzenlemek için kullanabileceği bir görünüm oluşturun:

  1. Görünümler'i ve ardından Cihaz ve bulut verilerini düzenleme kutucuğunu seçin.

  2. Form adı olarak Özellikler girin.

  3. Hedef Sıcaklık (1), Hedef Sıcaklık (2) ve Müşteri Adı özelliklerini seçin. Ardından Bölüm ekle'yi seçin.

  4. Yaptığınız değişiklikleri kaydedin.

Özellik değerlerini güncelleştirmek için görüntüleme

Cihaz şablonunu yayımlama

Operatör, sizin yapmış olduğunu özelleştirmeleri görene ve kullanamadan önce cihaz şablonunu yayımlamanız gerekir.

Thermostat cihaz şablonundan Yayımla'yı seçin. Bu cihazı yayımla şablonunu uygulama panelinde Yayımla'yı seçin.

Operatör artık özellik değerlerini güncelleştirmek için Özellikler görünümünü kullanabilir ve cihaz komutları sayfasındaKi Termostat1 durum raporunu al ve Termostat2 durum raporunu al adlı komutları çağırabilirsiniz:

  • Özellikler sayfasında yazılabilir özellik değerlerini güncelleştirin:

    Cihaz özelliklerini güncelleştirme

  • Komutlar sayfasından komutları çağırma. Durum raporu komutunu çalıştırmadan önce Since parametresi için bir tarih ve saat seçin:

    komutunu çağırma

    Komut yanıtını görüntüleme

Aygıtın komutlara ve özellik güncelleştirmelerine nasıl yanıt verdiğini görebilirsiniz. getMaxMinReportKomut thermostat2 bileşende, reboot komut varsayılan bileşendir. targetTemperature' Thermostat2 ' bileşeni için yazılabilir özellik ayarlandı:

Received command request for command name: thermostat2*getMaxMinReport
The command request payload is:
2021-03-26T06:00:00.000Z
Response to method: thermostat2*getMaxMinReport sent successfully.

...

Received command request for command name: reboot
The command request payload is:
10
Response to method: reboot sent successfully.

...

Received an update for device with value: {"thermostat2":{"targetTemperature":76,"__t":"c"},"$version":2}
Will update property: targetTemperature to value: 76 of component: thermostat2
Properties have been reported for component: thermostat2

Koda göz atın

Önkoşullar

Bu makaledeki adımları tamamlamak için aşağıdaki kaynaklar gereklidir:

  • Python sürüm 3,7 veya sonraki bir sürümü yüklü bir geliştirme makinesi. python --versionSürümünüzü denetlemek için komut satırından çalıştırabilirsiniz. Python, çok çeşitli işletim sistemleri için kullanılabilir. bu öğreticideki yönergeler, Windows komut isteminde python komutunu çalıştırmakta olduğunuzu varsayar.

  • örnek kodu içeren Python GitHub deposu için Microsoft Azure ıot SDK 'nın yerel bir kopyası. Deponun bir kopyasını indirmek için bu bağlantıyı kullanın: ZIP 'i indirin. Sonra dosyayı yerel makinenizde uygun bir konuma ayıklayın.

Kodu gözden geçirin

daha önce indirdiğiniz Python için Microsoft Azure ıot SDK kopyasında, Azure-ıot-SDK-Python/azure-ıot-device/samples/pnp/temp_controller_with_thermostats. kopyala dosyasını bir metin düzenleyicisinde açın.

IoT Central bağlanmak için örneği çalıştırdığınızda, cihazı kaydetmek ve bir bağlantı dizesi oluşturmak için cihaz sağlama hizmeti 'ni (DPS) kullanır. Örnek, gereken DPS bağlantı bilgilerini komut satırı ortamından alır.

mainİşlev:

  • , Cihazı sağlamak için DPS kullanır. Sağlama bilgileri, model KIMLIĞINI içerir. IoT Central, bu cihazın cihaz şablonunu tanımlamak veya oluşturmak için model KIMLIĞINI kullanır. Daha fazla bilgi için bkz. cihaz şablonuyla bir cihazı ilişkilendirme.
  • Bir Device_client nesne oluşturur ve dtmi:com:example:TemperatureController;2 bağlantıyı açmadan önce model kimliğini ayarlar.
  • IoT Central ilk özellik değerlerini gönderir. pnp_helperDüzeltme eklerini oluşturmak için öğesini kullanır.
  • Ve komutları için dinleyicileri getMaxMinReport oluşturur reboot . Her bir termostat bileşeni kendi getMaxMinReport komutuna sahiptir.
  • Yazılabilir Özellik güncelleştirmelerini dinlemek için özellik dinleyicisi oluşturur.
  • İki termostat bileşeninden ve çalışma kümesi telemetrisinden her 8 saniyede bir varsayılan bileşenden sıcaklık telemetrisi göndermek için bir döngü başlatır.
async def main():
    switch = os.getenv("IOTHUB_DEVICE_SECURITY_TYPE")
    if switch == "DPS":
        provisioning_host = (
            os.getenv("IOTHUB_DEVICE_DPS_ENDPOINT")
            if os.getenv("IOTHUB_DEVICE_DPS_ENDPOINT")
            else "global.azure-devices-provisioning.net"
        )
        id_scope = os.getenv("IOTHUB_DEVICE_DPS_ID_SCOPE")
        registration_id = os.getenv("IOTHUB_DEVICE_DPS_DEVICE_ID")
        symmetric_key = os.getenv("IOTHUB_DEVICE_DPS_DEVICE_KEY")

        registration_result = await provision_device(
            provisioning_host, id_scope, registration_id, symmetric_key, model_id
        )

        if registration_result.status == "assigned":
            print("Device was assigned")
            print(registration_result.registration_state.assigned_hub)
            print(registration_result.registration_state.device_id)
            device_client = IoTHubDeviceClient.create_from_symmetric_key(
                symmetric_key=symmetric_key,
                hostname=registration_result.registration_state.assigned_hub,
                device_id=registration_result.registration_state.device_id,
                product_info=model_id,
            )
        else:
            raise RuntimeError(
                "Could not provision device. Aborting Plug and Play device connection."
            )

    elif switch == "connectionString":
        # ...

    # Connect the client.
    await device_client.connect()

    ################################################
    # Update readable properties from various components

    properties_root = pnp_helper.create_reported_properties(serialNumber=serial_number)
    properties_thermostat1 = pnp_helper.create_reported_properties(
        thermostat_1_component_name, maxTempSinceLastReboot=98.34
    )
    properties_thermostat2 = pnp_helper.create_reported_properties(
        thermostat_2_component_name, maxTempSinceLastReboot=48.92
    )
    properties_device_info = pnp_helper.create_reported_properties(
        device_information_component_name,
        swVersion="5.5",
        manufacturer="Contoso Device Corporation",
        model="Contoso 4762B-turbo",
        osName="Mac Os",
        processorArchitecture="x86-64",
        processorManufacturer="Intel",
        totalStorage=1024,
        totalMemory=32,
    )

    property_updates = asyncio.gather(
        device_client.patch_twin_reported_properties(properties_root),
        device_client.patch_twin_reported_properties(properties_thermostat1),
        device_client.patch_twin_reported_properties(properties_thermostat2),
        device_client.patch_twin_reported_properties(properties_device_info),
    )

    ################################################
    # Get all the listeners running
    print("Listening for command requests and property updates")

    global THERMOSTAT_1
    global THERMOSTAT_2
    THERMOSTAT_1 = Thermostat(thermostat_1_component_name, 10)
    THERMOSTAT_2 = Thermostat(thermostat_2_component_name, 10)

    listeners = asyncio.gather(
        execute_command_listener(
            device_client, method_name="reboot", user_command_handler=reboot_handler
        ),
        execute_command_listener(
            device_client,
            thermostat_1_component_name,
            method_name="getMaxMinReport",
            user_command_handler=max_min_handler,
            create_user_response_handler=create_max_min_report_response,
        ),
        execute_command_listener(
            device_client,
            thermostat_2_component_name,
            method_name="getMaxMinReport",
            user_command_handler=max_min_handler,
            create_user_response_handler=create_max_min_report_response,
        ),
        execute_property_listener(device_client),
    )

    ################################################
    # Function to send telemetry every 8 seconds

    async def send_telemetry():
        print("Sending telemetry from various components")

        while True:
            curr_temp_ext = random.randrange(10, 50)
            THERMOSTAT_1.record(curr_temp_ext)

            temperature_msg1 = {"temperature": curr_temp_ext}
            await send_telemetry_from_temp_controller(
                device_client, temperature_msg1, thermostat_1_component_name
            )

            curr_temp_int = random.randrange(10, 50)  # Current temperature in Celsius
            THERMOSTAT_2.record(curr_temp_int)

            temperature_msg2 = {"temperature": curr_temp_int}

            await send_telemetry_from_temp_controller(
                device_client, temperature_msg2, thermostat_2_component_name
            )

            workingset_msg3 = {"workingSet": random.randrange(1, 100)}
            await send_telemetry_from_temp_controller(device_client, workingset_msg3)

    send_telemetry_task = asyncio.ensure_future(send_telemetry())

    # ...

provision_deviceİşlevi, cihazı sağlamak ve IoT Central kaydetmek IÇIN DPS kullanır. İşlevi, sağlama yükünde bir cihazı bir cihaz şablonuyla ilişkilendirmekiçin IoT Central kullanılan CIHAZ modeli kimliğini içerir:

async def provision_device(provisioning_host, id_scope, registration_id, symmetric_key, model_id):
    provisioning_device_client = ProvisioningDeviceClient.create_from_symmetric_key(
        provisioning_host=provisioning_host,
        registration_id=registration_id,
        id_scope=id_scope,
        symmetric_key=symmetric_key,
    )

    provisioning_device_client.provisioning_payload = {"modelId": model_id}
    return await provisioning_device_client.register()

execute_command_listenerİşlevi, komut isteklerini işler, cihaz, Ise max_min_handler getMaxMinReport stat bileşenleri için komutu aldığında ve reboot_handler cihaz reboot komutu aldığında işlevi çalıştırır. pnp_helperYanıtı oluşturmak için modülünü kullanır:

async def execute_command_listener(
    device_client,
    component_name=None,
    method_name=None,
    user_command_handler=None,
    create_user_response_handler=None,
):
    while True:
        if component_name and method_name:
            command_name = component_name + "*" + method_name
        elif method_name:
            command_name = method_name
        else:
            command_name = None

        command_request = await device_client.receive_method_request(command_name)
        print("Command request received with payload")
        values = command_request.payload
        print(values)

        if user_command_handler:
            await user_command_handler(values)
        else:
            print("No handler provided to execute")

        (response_status, response_payload) = pnp_helper.create_response_payload_with_status(
            command_request, method_name, create_user_response=create_user_response_handler
        )

        command_response = MethodResponse.create_from_method_request(
            command_request, response_status, response_payload
        )

        try:
            await device_client.send_method_response(command_response)
        except Exception:
            print("responding to the {command} command failed".format(command=method_name))

, async def execute_property_listener Termostat bileşenleri gibi yazılabilir Özellik güncelleştirmelerini işler targetTemperature ve JSON yanıtını üretir. pnp_helperYanıtı oluşturmak için modülünü kullanır:

async def execute_property_listener(device_client):
    while True:
        patch = await device_client.receive_twin_desired_properties_patch()  # blocking call
        print(patch)
        properties_dict = pnp_helper.create_reported_properties_from_desired(patch)

        await device_client.patch_twin_reported_properties(properties_dict)

send_telemetry_from_temp_controllerİşlevi, termostat bileşenlerinden telemetri iletilerini IoT Central olarak gönderir. pnp_helperİletileri oluşturmak için modülünü kullanır:

async def send_telemetry_from_temp_controller(device_client, telemetry_msg, component_name=None):
    msg = pnp_helper.create_telemetry(telemetry_msg, component_name)
    await device_client.send_message(msg)
    print("Sent message")
    print(msg)
    await asyncio.sleep(5)

Bağlantı bilgilerini alma

Bu öğreticide daha sonra örnek cihaz uygulamasını çalıştırdığınızda aşağıdaki yapılandırma değerleri gerekir:

  • KIMLIK kapsamı: IoT Central uygulamanızda yönetim > cihaz bağlantısı' na gidin. Kimlik kapsamı değerini bir yere getirin.
  • Birincil anahtarı grupla: IoT Central uygulamanızda yönetim > cihaz bağlantısı > SAS-IoT-cihazlar' a gidin. Paylaşılan erişim imzası birincil anahtar değerini bir yere getirin.

Aldığınız grup birincil anahtarından bir cihaz anahtarı oluşturmak için Cloud Shell kullanın:

az extension add --name azure-iot
az iot central device compute-device-key --device-id sample-device-01 --pk <the group primary key value>

Oluşturulan Cihaz anahtarını bir yere getirin, bu öğreticide daha sonra kullanın.

Kodu çalıştırma

Örnek uygulamayı çalıştırmak için bir komut satırı ortamı açın ve temp_controller_with_thermostats. Kopyala örnek dosyasını içeren Azure-IoT-SDK-Python/Azure-IoT-Device/Samples/PNP klasörüne gidin.

Örneği yapılandırmak için ortam değişkenlerini ayarlayın. Aşağıdaki kod parçacığında, Windows komut isteminde ortam değişkenlerinin nasıl ayarlanacağı gösterilmektedir. Bash kabuğu kullanıyorsanız, komutları komutlarla değiştirin set export :

set IOTHUB_DEVICE_SECURITY_TYPE=DPS
set IOTHUB_DEVICE_DPS_ID_SCOPE=<The ID scope you made a note of previously>
set IOTHUB_DEVICE_DPS_DEVICE_ID=sample-device-01
set IOTHUB_DEVICE_DPS_DEVICE_KEY=<The generated device key you made a note of previously>
set IOTHUB_DEVICE_DPS_ENDPOINT=global.azure-devices-provisioning.net

Gerekli paketleri yükler:

pip install azure-iot-device

Örneği çalıştırın:

python temp_controller_with_thermostats.py

Aşağıdaki çıktı, IoT Central kaydetme ve bağlanma için cihazı gösterir. Örnek, maxTempSinceLastReboot telemetri göndermeye başlamadan önce iki ıterstat bileşeninden özellikleri gönderir:

Device was assigned
iotc-60a.....azure-devices.net
sample-device-01
Updating pnp properties for root interface
{'serialNumber': 'alohomora'}
Updating pnp properties for thermostat1
{'thermostat1': {'maxTempSinceLastReboot': 98.34, '__t': 'c'}}
Updating pnp properties for thermostat2
{'thermostat2': {'maxTempSinceLastReboot': 48.92, '__t': 'c'}}
Updating pnp properties for deviceInformation
{'deviceInformation': {'swVersion': '5.5', 'manufacturer': 'Contoso Device Corporation', 'model': 'Contoso 4762B-turbo', 'osName': 'Mac Os', 'processorArchitecture': 'x86-64', 'processorManufacturer': 'Intel', 'totalStorage': 1024, 'totalMemory': 32, '__t': 'c'}}
Listening for command requests and property updates
Press Q to quit
Sending telemetry from various components
Sent message
{"temperature": 27}
Sent message
{"temperature": 17}
Sent message
{"workingSet": 13}

Uygulamanıza işleç olarak Azure IoT Central şunları gerçekleştirebilirsiniz:

  • Genel Bakış sayfasında iki termostat bileşeni tarafından gönderilen telemetrisini görüntüleyebilirsiniz:

    Cihaz telemetrisini görüntüleme

  • Hakkında sayfasında cihaz özelliklerini görüntüleme. Bu sayfada cihaz bilgileri bileşeni ve iki termostat bileşeninden özellikler görüntülenir:

    Cihaz özelliklerini görüntüleme

Cihaz şablonunu özelleştirme

Çözüm geliştiricisi olarak, sıcaklık denetleyicisi cihazı bağlandığında otomatik IoT Central oluşturulan cihaz şablonunu özelleştirebilirsiniz.

Cihazla ilişkili müşteri adını depolamak için bir bulut özelliği eklemek için:

  1. Uygulama IoT Central Cihaz şablonları sayfasında Temperature Controller cihaz şablonuna gidin.

  2. Sıcaklık Denetleyicisi cihaz şablonunda Bulut özellikleri'ne tıklayın.

  3. Bulut özelliği ekle'yi seçin. Görünen ad olarak Müşteri adı girin, girişi genişletin ve Şema olarak Dize'yi seçin. Sonra Kaydet'i seçin.

Get Max-Min rapor komutlarının uygulamanıza nasıl görüntü IoT Central için:

  1. Cihaz şablonunda Özelleştir'i seçin.

  2. getMaxMinReport (thermostat1) için Get Max-Min değiştirin. termostat1 durum raporunu al ile.

  3. getMaxMinReport (termostat2) için Get Max-Min değiştirin. termostat2 durum raporunu al ile.

  4. Kaydet’i seçin.

Hedef Sıcaklık yazılabilir özelliklerinin uygulamanıza nasıl görüntü IoT Central için:

  1. Cihaz şablonunda Özelleştir'i seçin.

  2. targetTemperature (termostat1) için Hedef Sıcaklığı Hedef Sıcaklık (1) ile değiştirin.

  3. targetTemperature (termostat2) için Hedef Sıcaklığı Hedef Sıcaklık (2) ile değiştirin.

  4. Kaydet’i seçin.

Sıcaklık Denetleyicisi modelinde termostat bileşenleri Hedef Sıcaklık yazılabilir özelliğini, cihaz şablonu ise Müşteri Adı bulut özelliğini içerir. Bir operatörün şu özellikleri düzenlemek için kullanabileceği bir görünüm oluşturun:

  1. Görünümler'i ve ardından Cihaz ve bulut verilerini düzenleme kutucuğunu seçin.

  2. Form adı olarak Özellikler girin.

  3. Hedef Sıcaklık (1), Hedef Sıcaklık (2) ve Müşteri Adı özelliklerini seçin. Ardından Bölüm ekle'yi seçin.

  4. Yaptığınız değişiklikleri kaydedin.

Özellik değerlerini güncelleştirmek için görüntüleme

Cihaz şablonunu yayımlama

Operatör, sizin yapmış olduğunu özelleştirmeleri görene ve kullanamadan önce cihaz şablonunu yayımlamanız gerekir.

Thermostat cihaz şablonundan Yayımla'yı seçin. Bu cihazı yayımla şablonunu uygulama panelinde Yayımla'yı seçin.

Operatör artık özellik değerlerini güncelleştirmek için Özellikler görünümünü kullanabilir ve cihaz komutları sayfasındaKi Termostat1 durum raporunu al ve Termostat2 durum raporunu al adlı komutları çağırabilirsiniz:

  • Özellikler sayfasında yazılabilir özellik değerlerini güncelleştirin:

    Cihaz özelliklerini güncelleştirme

  • Komutlar sayfasından komutları çağırma. Durum raporu komutunu çalıştırmadan önce Since parametresi için bir tarih ve saat seçin:

    komutunu çağırma

    Komut yanıtını görüntüleme

Aygıtın komutlara ve özellik güncelleştirmelerine nasıl yanıt verdiğini görebilirsiniz:

{'thermostat1': {'targetTemperature': 67, '__t': 'c'}, '$version': 2}
the data in the desired properties patch was: {'thermostat1': {'targetTemperature': 67, '__t': 'c'}, '$version': 2}
Values received are :-
{'targetTemperature': 67, '__t': 'c'}
Sent message

...

Command request received with payload
2021-03-31T05:00:00.000Z
Will return the max, min and average temperature from the specified time 2021-03-31T05:00:00.000Z to the current time
Done generating
{"avgTemp": 4.0, "endTime": "2021-03-31T12:29:48.322427", "maxTemp": 18, "minTemp": null, "startTime": "2021-03-31T12:28:28.322381"}

Ham verileri görüntüleme

Cihazınızın cihaza gönderdiği ham verileri incelemek için Ham veri görünümünü IoT Central:

Ham veri görünümü

Bu görünümde, görüntülemek istediğiniz sütunları seçin ve görüntülemek için bir zaman aralığı ayarlayın. Modelsiz veri sütunu, cihaz şablonunda herhangi bir özellik veya telemetri tanımıyla eşleşmemiş cihaz verilerini gösterir.

Kaynakları temizleme

Daha fazla IoT Central hızlı başlangıç veya öğreticilerle tamamlamayı planlamıyorsanız, IoT Central uygulamanızı silebilirsiniz:

  1. IoT Central uygulamanızda, uygulamanızın yönetim > gidin.
  2. Sil ' i seçin ve eyleminizi onaylayın.

Sonraki adımlar

IoT Central öğreticileri kümesiyle devam etmek ve IoT Central daha fazla bilgi edinmek isterseniz bkz: