Kurz: Vytvoření a připojení klientské aplikace k aplikaci Azure IoT Central
Důležité
Tento článek obsahuje postup připojení zařízení pomocí sdíleného přístupového podpisu, označovaného také jako ověřování symetrického klíče. Tato metoda ověřování je vhodná pro testování a vyhodnocení, ale ověřování zařízení pomocí certifikátů X.509 je bezpečnější přístup. Další informace najdete v tématu Zabezpečení osvědčených postupů > zabezpečení připojení.
V tomto kurzu se dozvíte, jak připojit klientskou aplikaci k aplikaci Azure IoT Central. Aplikace simuluje chování zařízení řadiče teploty. Když se aplikace připojí ke službě IoT Central, odešle ID modelu zařízení kontroleru teploty. IoT Central používá ID modelu k načtení modelu zařízení a vytvoření šablony zařízení za vás. Do šablony zařízení přidáte zobrazení, abyste operátorovi umožnili interakci se zařízením.
V tomto kurzu se naučíte:
- Vytvořte a spusťte kód zařízení a podívejte se na něj, jak se připojí k aplikaci IoT Central.
- Zobrazte simulovaná telemetrická data odeslaná ze zařízení.
- Přidání vlastních zobrazení do šablony zařízení
- Publikujte šablonu zařízení.
- Pomocí zobrazení můžete spravovat vlastnosti zařízení.
- Zavolejte příkaz pro řízení zařízení.
Důležité
Tento článek obsahuje postup připojení zařízení pomocí sdíleného přístupového podpisu, označovaného také jako ověřování symetrického klíče. Tato metoda ověřování je vhodná pro testování a vyhodnocení, ale ověřování zařízení pomocí certifikátů X.509 je bezpečnější přístup. Další informace najdete v tématu Zabezpečení osvědčených postupů > zabezpečení připojení.
Požadavky
K dokončení kroků v tomto kurzu potřebujete:
Aktivní předplatné Azure. Pokud ještě nemáte předplatné Azure, vytvořte si napřed bezplatný účet.
Aplikace IoT Central vytvořená ze šablony vlastní aplikace Další informace najdete v tématu Vytvoření aplikace IoT Central a Informace o vaší aplikaci.
Tento kurz můžete spustit v Linuxu nebo Windows. Příkazy prostředí v tomto kurzu se řídí konvencí Linuxu pro oddělovače/
cest, pokud postupujete společně s Windows, nezapomeňte tyto oddělovače prohodit za "\
".
Požadavky se liší podle operačního systému:
Linux
V tomto kurzu se předpokládá, že používáte Ubuntu Linux. Kroky v tomto kurzu byly testovány pomocí Ubuntu 18.04.
Pokud chcete tento kurz dokončit v Linuxu, nainstalujte do místního linuxového prostředí následující software:
Pomocí příkazu nainstalujte GCC, Git, cmake a všechny požadované závislosti apt-get
:
sudo apt-get update
sudo apt-get install -y git cmake build-essential curl libcurl4-openssl-dev libssl-dev uuid-dev
Ověřte, že je verze cmake
větší než 2.8.12 a verze GCC je větší než 4.4.7.
cmake --version
gcc --version
Windows
Chcete-li dokončit tento kurz ve Windows, nainstalujte do místního prostředí Windows následující software:
- Visual Studio (Community, Professional nebo Enterprise) – při instalaci sady Visual Studio nezapomeňte zahrnout vývoj desktopových aplikací pomocí úlohy C++.
- Git
- CMake.
Stáhněte si kód
V tomto kurzu připravíte vývojové prostředí, které můžete použít ke klonování a sestavení sady AZURE IoT Hub Device C SDK.
Otevřete příkazový řádek v adresáři podle vašeho výběru. Spuštěním následujícího příkazu naklonujte úložiště GitHub sdk a knihoven Azure IoT C do tohoto umístění:
git clone https://github.com/Azure/azure-iot-sdk-c.git
cd azure-iot-sdk-c
git submodule update --init
Očekáváme, že dokončení této operace bude trvat několik minut.
Kontrola kódu
V kopii sady Microsoft Azure IoT SDK pro jazyk C, kterou jste si stáhli dříve, otevřete soubory azure-iot-sdk-c/iothub_client/samples/pnp/pnp_temperature_controller/pnp_temperature_controller.c a azure-iot-sdk-c/iothub_client/samples/pnp/pnp_temperature_controller/pnp_thermostat_component.c v textovém editoru.
Ukázka implementuje model více komponent Temperature Controller Digital Twin Definition Language.
Když spustíte ukázku pro připojení k IoT Central, zaregistruje zařízení pomocí služby Device Provisioning Service (DPS) a vygeneruje připojovací řetězec. Ukázka načte informace o připojení DPS, které potřebuje, z prostředí příkazového řádku.
V pnp_temperature_controller.cmain
funkce nejprve voláCreateDeviceClientAndAllocateComponents
:
-
dtmi:com:example:Thermostat;1
Nastavte ID modelu. IoT Central používá ID modelu k identifikaci nebo vygenerování šablony zařízení pro toto zařízení. Další informace najdete v tématu Přiřazení zařízení k šabloně zařízení. - Pomocí DPS zřiďte a zaregistrujte zařízení.
- Vytvořte popisovač klienta zařízení a připojte se k aplikaci IoT Central.
- Vytvoří obslužnou rutinu pro příkazy v komponentě kontroleru teploty.
- Vytvoří obslužnou rutinu pro aktualizace vlastností v komponentě kontroleru teploty.
- Vytvoří dvě součásti termostatu.
Další main
funkce:
- Hlásí některé počáteční hodnoty vlastností pro všechny komponenty.
- Spustí smyčku pro odesílání telemetrie ze všech komponent.
Funkce main
pak spustí vlákno, které bude pravidelně odesílat telemetrii.
int main(void)
{
IOTHUB_DEVICE_CLIENT_LL_HANDLE deviceClient = NULL;
g_pnpDeviceConfiguration.modelId = g_temperatureControllerModelId;
g_pnpDeviceConfiguration.enableTracing = g_hubClientTraceEnabled;
// First determine the IoT Hub / credentials / device to use.
if (GetConnectionSettingsFromEnvironment(&g_pnpDeviceConfiguration) == false)
{
LogError("Cannot read required environment variable(s)");
}
// Creates the thermostat subcomponents defined by this model. Since everything
// is simulated, this setup stage just creates simulated objects in memory.
else if (AllocateThermostatComponents() == false)
{
LogError("Failure allocating thermostat components");
}
// Create a handle to device client handle. Note that this call may block
// for extended periods of time when using DPS.
else if ((deviceClient = CreateAndConfigureDeviceClientHandleForPnP()) == NULL)
{
LogError("Failure creating Iot Hub device client");
PnP_ThermostatComponent_Destroy(g_thermostatHandle1);
PnP_ThermostatComponent_Destroy(g_thermostatHandle2);
}
else
{
LogInfo("Successfully created device client. Hit Control-C to exit program\n");
int numberOfIterations = 0;
// During startup, send what DTDLv2 calls "read-only properties" to indicate initial device state.
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_SendCurrentTemperature(g_thermostatHandle1, deviceClient);
PnP_ThermostatComponent_SendCurrentTemperature(g_thermostatHandle2, deviceClient);
}
IoTHubDeviceClient_LL_DoWork(deviceClient);
ThreadAPI_Sleep(g_sleepBetweenPollsMs);
numberOfIterations++;
}
// The remainder of the code is used for cleaning up our allocated resources. It won't be executed in this
// sample (because the loop above is infinite and is only broken out of by Control-C of the program), but
// it is included for reference.
// Free the memory allocated to track simulated thermostat.
PnP_ThermostatComponent_Destroy(g_thermostatHandle1);
PnP_ThermostatComponent_Destroy(g_thermostatHandle2);
// Clean up the IoT Hub SDK handle.
IoTHubDeviceClient_LL_Destroy(deviceClient);
// Free all IoT Hub subsystem.
IoTHub_Deinit();
}
return 0;
}
Funkce ukazujepnp_thermostat_component.c
PnP_ThermostatComponent_SendCurrentTemperature
, jak zařízení odesílá telemetrii teploty ze komponenty do IoT Central:
void PnP_ThermostatComponent_SendCurrentTemperature(PNP_THERMOSTAT_COMPONENT_HANDLE pnpThermostatComponentHandle, IOTHUB_DEVICE_CLIENT_LL_HANDLE deviceClient)
{
PNP_THERMOSTAT_COMPONENT* pnpThermostatComponent = (PNP_THERMOSTAT_COMPONENT*)pnpThermostatComponentHandle;
IOTHUB_MESSAGE_HANDLE messageHandle = NULL;
IOTHUB_MESSAGE_RESULT messageResult;
IOTHUB_CLIENT_RESULT iothubClientResult;
char temperatureStringBuffer[CURRENT_TEMPERATURE_BUFFER_SIZE];
// Create the telemetry message body to send.
if (snprintf(temperatureStringBuffer, sizeof(temperatureStringBuffer), g_temperatureTelemetryBodyFormat, pnpThermostatComponent->currentTemperature) < 0)
{
LogError("snprintf of current temperature telemetry failed");
}
// Create the message handle and specify its metadata.
else if ((messageHandle = IoTHubMessage_CreateFromString(temperatureStringBuffer)) == NULL)
{
LogError("IoTHubMessage_PnP_CreateFromString failed");
}
else if ((messageResult = IoTHubMessage_SetContentTypeSystemProperty(messageHandle, g_jsonContentType)) != IOTHUB_MESSAGE_OK)
{
LogError("IoTHubMessage_SetContentTypeSystemProperty failed, error=%d", messageResult);
}
else if ((messageResult = IoTHubMessage_SetContentEncodingSystemProperty(messageHandle, g_utf8EncodingType)) != IOTHUB_MESSAGE_OK)
{
LogError("IoTHubMessage_SetContentEncodingSystemProperty failed, error=%d", messageResult);
}
else if ((messageResult = IoTHubMessage_SetComponentName(messageHandle, pnpThermostatComponent->componentName)) != IOTHUB_MESSAGE_OK)
{
LogError("IoTHubMessage_SetContentEncodingSystemProperty failed, error=%d", messageResult);
}
// Send the telemetry message.
else if ((iothubClientResult = IoTHubDeviceClient_LL_SendTelemetryAsync(deviceClient, messageHandle, NULL, NULL)) != IOTHUB_CLIENT_OK)
{
LogError("Unable to send telemetry message, error=%d", iothubClientResult);
}
IoTHubMessage_Destroy(messageHandle);
}
Funkce pnp_thermostat_component.c
odešle PnP_TempControlComponent_Report_MaxTempSinceLastReboot_Property
maxTempSinceLastReboot
aktualizaci vlastnosti ze komponenty do IoT Central:
void PnP_TempControlComponent_Report_MaxTempSinceLastReboot_Property(PNP_THERMOSTAT_COMPONENT_HANDLE pnpThermostatComponentHandle, IOTHUB_DEVICE_CLIENT_LL_HANDLE deviceClient)
{
PNP_THERMOSTAT_COMPONENT* pnpThermostatComponent = (PNP_THERMOSTAT_COMPONENT*)pnpThermostatComponentHandle;
char maximumTemperatureAsString[MAX_TEMPERATURE_SINCE_REBOOT_BUFFER_SIZE];
IOTHUB_CLIENT_RESULT iothubClientResult;
if (snprintf(maximumTemperatureAsString, sizeof(maximumTemperatureAsString), g_maxTempSinceLastRebootPropertyFormat, pnpThermostatComponent->maxTemperature) < 0)
{
LogError("Unable to create max temp since last reboot string for reporting result");
}
else
{
IOTHUB_CLIENT_PROPERTY_REPORTED maxTempProperty;
maxTempProperty.structVersion = IOTHUB_CLIENT_PROPERTY_REPORTED_STRUCT_VERSION_1;
maxTempProperty.name = g_maxTempSinceLastRebootPropertyName;
maxTempProperty.value = maximumTemperatureAsString;
unsigned char* propertySerialized = NULL;
size_t propertySerializedLength;
// The first step of reporting properties is to serialize IOTHUB_CLIENT_PROPERTY_WRITABLE_RESPONSE into JSON for sending.
if ((iothubClientResult = IoTHubClient_Properties_Serializer_CreateReported(&maxTempProperty, 1, pnpThermostatComponent->componentName, &propertySerialized, &propertySerializedLength)) != IOTHUB_CLIENT_OK)
{
LogError("Unable to serialize reported state, error=%d", iothubClientResult);
}
// The output of IoTHubClient_Properties_Serializer_CreateReported is sent to IoTHubDeviceClient_LL_SendPropertiesAsync to perform network I/O.
else if ((iothubClientResult = IoTHubDeviceClient_LL_SendPropertiesAsync(deviceClient, propertySerialized, propertySerializedLength, NULL, NULL)) != IOTHUB_CLIENT_OK)
{
LogError("Unable to send reported state, error=%d", iothubClientResult);
}
else
{
LogInfo("Sending %s property to IoTHub for component %s", g_maxTempSinceLastRebootPropertyName, pnpThermostatComponent->componentName);
}
IoTHubClient_Properties_Serializer_Destroy(propertySerialized);
}
}
PnP_ThermostatComponent_ProcessPropertyUpdate
Funkce pnp_thermostat_component.c
zpracovává aktualizace zapisovatelných vlastností z IoT Central:
void PnP_ThermostatComponent_ProcessPropertyUpdate(PNP_THERMOSTAT_COMPONENT_HANDLE pnpThermostatComponentHandle, IOTHUB_DEVICE_CLIENT_LL_HANDLE deviceClient, const char* propertyName, const char* 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
{
char* next;
double targetTemperature = strtod(propertyValue, &next);
if ((propertyValue == next) || (targetTemperature == HUGE_VAL) || (targetTemperature == (-1*HUGE_VAL)))
{
LogError("Property %s is not a valid number", propertyValue);
SendTargetTemperatureResponse(pnpThermostatComponent, deviceClient, propertyValue, PNP_STATUS_BAD_FORMAT, version, g_temperaturePropertyResponseDescriptionNotInt);
}
else
{
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, deviceClient, propertyValue, PNP_STATUS_SUCCESS, version, NULL);
if (maxTempUpdated)
{
// If the maximum temperature has been updated, we also report this as a property.
PnP_TempControlComponent_Report_MaxTempSinceLastReboot_Property(pnpThermostatComponent, deviceClient);
}
}
}
}
PnP_ThermostatComponent_ProcessCommand
Funkce pnp_thermostat_component.c
zpracovává příkazy volané z IoT Central:
void PnP_ThermostatComponent_ProcessCommand(PNP_THERMOSTAT_COMPONENT_HANDLE pnpThermostatComponentHandle, const char *pnpCommandName, JSON_Value* commandJsonValue, IOTHUB_CLIENT_COMMAND_RESPONSE* commandResponse)
{
PNP_THERMOSTAT_COMPONENT* pnpThermostatComponent = (PNP_THERMOSTAT_COMPONENT*)pnpThermostatComponentHandle;
const char* sinceStr;
if (strcmp(pnpCommandName, g_getMaxMinReportCommandName) != 0)
{
LogError("Command %s is not supported on thermostat component", pnpCommandName);
commandResponse->statusCode = 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");
commandResponse->statusCode = PNP_STATUS_BAD_FORMAT;
}
else if (BuildMaxMinCommandResponse(pnpThermostatComponent, commandResponse) == false)
{
LogError("Unable to build response for component %s", pnpThermostatComponent->componentName);
commandResponse->statusCode = PNP_STATUS_INTERNAL_ERROR;
}
else
{
LogInfo("Returning success from command request for component %s", pnpThermostatComponent->componentName);
commandResponse->statusCode = PNP_STATUS_SUCCESS;
}
}
Sestavení kódu
Sadu SDK zařízení použijete k sestavení zahrnutého ukázkového kódu:
Vytvořte podadresář cmake v kořenové složce sady SDK zařízení a přejděte do této složky:
cd azure-iot-sdk-c mkdir cmake cd cmake
Spuštěním následujících příkazů sestavte sadu SDK a ukázky:
cmake -Duse_prov_client=ON -Dhsm_type_symm_key=ON -Drun_e2e_tests=OFF .. cmake --build .
Získání informací o připojení
Když později v tomto kurzu spustíte ukázkovou aplikaci zařízení, budete potřebovat následující konfigurační hodnoty:
- Rozsah ID: V aplikaci IoT Central přejděte do skupin připojení zařízení oprávnění>. Poznamenejte si hodnotu oboru ID.
- Primární klíč skupiny: V aplikaci IoT Central přejděte na Skupiny > připojení zařízení OPRÁVNĚNÍ > SAS-IoT-Devices. Poznamenejte si hodnotu primárního klíče sdíleného přístupového podpisu.
Pomocí Azure Cloud Shellu vygenerujte klíč zařízení z primárního klíče skupiny, který jste získali:
az extension add --name azure-iot
az iot central device compute-device-key --device-id sample-device-01 --pk <the group primary key value>
Poznamenejte si vygenerovaný klíč zařízení, který použijete později v tomto kurzu.
Poznámka:
Pokud chcete tuto ukázku spustit, nemusíte zařízení předem zaregistrovat ve své aplikaci IoT Central. Ukázka používá funkci IoT Central k automatické registraci zařízení při prvním připojení.
Spuštění kódu
Pokud chcete spustit ukázkovou aplikaci, otevřete prostředí příkazového řádku a přejděte do složky azure-iot-sdk-c\cmake.
Nastavte proměnné prostředí pro konfiguraci ukázky. Následující fragment kódu ukazuje, jak nastavit proměnné prostředí na příkazovém řádku Windows. Pokud používáte prostředí Bash , nahraďte set
příkazy export
příkazy:
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
Spuštění ukázky:
# 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
Následující výstup ukazuje registraci zařízení a připojení k IoT Central. Ukázka začne odesílat telemetrii:
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
Jako operátor ve vaší aplikaci Azure IoT Central můžete:
Zobrazte telemetrii odesílanou dvěma komponentami termostatu na stránce Přehled :
Zobrazte vlastnosti zařízení na stránce O produktu. Tato stránka zobrazuje vlastnosti ze komponenty informací o zařízení a dvě komponenty termostatu:
Přizpůsobení šablony zařízení
Jako vývojář řešení můžete přizpůsobit šablonu zařízení, kterou Služba IoT Central vytvořila automaticky při připojení zařízení kontroleru teploty.
Přidání cloudové vlastnosti pro uložení jména zákazníka přidruženého k zařízení:
V aplikaci IoT Central přejděte na šablonu zařízení Teplotní kontroler na stránce Šablony zařízení.
V modelu Teplotní kontroler vyberte +Přidat schopnost.
Jako zobrazovaný název zadejte jméno zákazníka, jako typ schopnosti vyberte vlastnost Cloud, rozbalte položku a zvolte Řetězec jako schéma. Pak vyberte Uložit.
Přizpůsobení zobrazení příkazů sestavy Get Max-Min v aplikaci IoT Central:
Na stránce Šablony zařízení přejděte na šablonu zařízení Temperature Controller.
V případě getMaxMinReport (termostat1) nahraďte sestavu Get Max-Min.Získáte termostat1 stavovou zprávu.
V případě getMaxMinReport (termostat2) nahraďte sestavu Get Max-Min.Získáte zprávu o stavu termostat2.
Zvolte Uložit.
Přizpůsobení způsobu zobrazení zapisovatelných vlastností cílové teploty v aplikaci IoT Central:
Na stránce Šablony zařízení přejděte na šablonu zařízení Temperature Controller.
Pro targetTemperature (termostat1) nahraďte cílovou teplotu cílovou teplotou(1).
Pro targetTemperature (termostat2) nahraďte cílovou teplotu cílovou teplotou(2).
Zvolte Uložit.
Součástí termostatu v modelu kontroleru teploty je vlastnost Zapisovatelná cílová teplota , šablona zařízení obsahuje cloudovou vlastnost Customer Name . Vytvořte zobrazení, které může operátor použít k úpravě těchto vlastností:
Vyberte Zobrazení a pak vyberte dlaždici Pro úpravy zařízení a cloudových dat .
Jako název formuláře zadejte Vlastnosti .
Vyberte vlastnosti Cílová teplota (1), Cílová teplota (2) a Jméno zákazníka. Pak vyberte Přidat oddíl.
Uložte provedené změny.
Publikování šablony zařízení
Než operátor uvidí a použije vlastní nastavení, které jste provedli, musíte šablonu zařízení publikovat.
V šabloně termostatu vyberte Publikovat. Na panelu aplikace vyberte Publikovat tuto šablonu zařízení.
Operátor teď může pomocí zobrazení Vlastnosti aktualizovat hodnoty vlastností a volat příkazy s názvem Get termostat1 status report and Get termostat2 status report on the device commands page:
Aktualizujte zapisovatelné hodnoty vlastností na stránce Vlastnosti :
Volání příkazů ze stránky Příkazy Pokud spustíte příkaz zprávy o stavu, vyberte před spuštěním parametru Since datum a čas:
Uvidíte, jak zařízení reaguje na příkazy a aktualizace vlastností:
<- 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
Důležité
Tento článek obsahuje postup připojení zařízení pomocí sdíleného přístupového podpisu, označovaného také jako ověřování symetrického klíče. Tato metoda ověřování je vhodná pro testování a vyhodnocení, ale ověřování zařízení pomocí certifikátů X.509 je bezpečnější přístup. Další informace najdete v tématu Zabezpečení osvědčených postupů > zabezpečení připojení.
Požadavky
K dokončení kroků v tomto článku potřebujete následující zdroje informací:
Aktivní předplatné Azure. Pokud ještě nemáte předplatné Azure, vytvořte si napřed bezplatný účet.
Aplikace IoT Central vytvořená ze šablony vlastní aplikace Další informace najdete v tématu Vytvoření aplikace IoT Central a Informace o vaší aplikaci.
Vývojový počítač se sadou Visual Studio (Community, Professional nebo Enterprise)
Místní kopie úložiště GitHub sdk Microsoft Azure IoT pro C# (.NET), které obsahuje ukázkový kód. Pomocí tohoto odkazu si můžete stáhnout kopii úložiště: Stáhnout soubor ZIP. Potom soubor rozbalte do vhodného umístění na místním počítači.
Kontrola kódu
V kopii úložiště Microsoft Azure IoT SDK pro jazyk C#, které jste si stáhli dříve, otevřete soubor řešení azure-iot-sdk-csharp-main\azureiot.sln v sadě Visual Studio. V Průzkumník řešení rozbalte složku PnpDeviceSamples > TemperatureController a otevřete Program.cs a TemperatureControllerSample.cs soubory, abyste zobrazili kód pro tuto ukázku.
Ukázka implementuje model více komponent Temperature Controller Digital Twin Definition Language.
Když spustíte ukázku pro připojení k IoT Central, zaregistruje zařízení pomocí služby Device Provisioning Service (DPS) a vygeneruje připojovací řetězec. Ukázka načte informace o připojení DPS, které potřebuje, z prostředí.
V Program.csMain
metoda voláSetupDeviceClientAsync
:
- ID modelu
dtmi:com:example:TemperatureController;2
použijte, když zřídí zařízení s DPS. IoT Central používá ID modelu k identifikaci nebo vygenerování šablony zařízení pro toto zařízení. Další informace najdete v tématu Přiřazení zařízení k šabloně zařízení. - Vytvořte instanci DeviceClient pro připojení k IoT Central.
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;
}
Hlavní metoda pak vytvoří TemperatureControllerSample instance a zavolá metodu PerformOperationsAsync
pro zpracování interakcí s IoT Central.
V TemperatureControllerSample.csPerformOperationsAsync
metoda:
- Nastaví obslužnou rutinu pro příkaz reboot ve výchozí komponentě.
- Nastaví obslužné rutiny pro příkazy getMaxMinReport na dvou komponentách termostatu.
- Nastaví obslužné rutiny pro příjem aktualizací vlastností cílové teploty na dvou komponentách termostatu.
- Odesílá počáteční aktualizace vlastností informací o zařízení.
- Pravidelně odesílá telemetrii teploty ze dvou komponent termostatu.
- Pravidelně odesílá telemetrii pracovní sady z výchozí komponenty.
- Odešle maximální teplotu od posledního restartování při každém dosažení nové maximální teploty ve dvou komponentách termostatu.
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);
}
}
Tato SendTemperatureAsync
metoda ukazuje, jak zařízení odesílá telemetrii teploty ze komponenty do IoT Central. Metoda SendTemperatureTelemetryAsync
používá PnpConvention
třídu k sestavení zprávy:
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 },
});
}
}
Metoda UpdateMaxTemperatureSinceLastRebootAsync
odešle maxTempSinceLastReboot
aktualizaci vlastnosti do IoT Central. Tato metoda používá PnpConvention
třídu k vytvoření opravy:
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);
}
Metoda TargetTemperatureUpdateCallbackAsync
zpracovává zapisovatelnou aktualizaci vlastnosti cílové teploty z IoT Central. Tato metoda používá PnpConvention
třídu ke čtení zprávy aktualizace vlastnosti a sestavení odpovědi:
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);
}
Metoda HandleMaxMinReportCommand
zpracovává příkazy pro komponenty volané z 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)
{
// ...
}
}
Získání informací o připojení
Když později v tomto kurzu spustíte ukázkovou aplikaci zařízení, budete potřebovat následující konfigurační hodnoty:
- Rozsah ID: V aplikaci IoT Central přejděte do skupin připojení zařízení oprávnění>. Poznamenejte si hodnotu oboru ID.
- Primární klíč skupiny: V aplikaci IoT Central přejděte na Skupiny > připojení zařízení OPRÁVNĚNÍ > SAS-IoT-Devices. Poznamenejte si hodnotu primárního klíče sdíleného přístupového podpisu.
Pomocí Azure Cloud Shellu vygenerujte klíč zařízení z primárního klíče skupiny, který jste získali:
az extension add --name azure-iot
az iot central device compute-device-key --device-id sample-device-01 --pk <the group primary key value>
Poznamenejte si vygenerovaný klíč zařízení, který použijete později v tomto kurzu.
Poznámka:
Pokud chcete tuto ukázku spustit, nemusíte zařízení předem zaregistrovat ve své aplikaci IoT Central. Ukázka používá funkci IoT Central k automatické registraci zařízení při prvním připojení.
Spuštění kódu
Poznámka:
Před spuštěním kódu nastavte TemperatureController jako spouštěný projekt.
Spuštění ukázkové aplikace v sadě Visual Studio:
V Průzkumník řešení vyberte soubor projektu PnpDeviceSamples > TemperatureController.
Přejděte do programu Project > TemperatureController – ladění vlastností>. Pak do projektu přidejte následující proměnné prostředí:
Jméno Hodnota IOTHUB_DEVICE_SECURITY_TYPE DPS IOTHUB_DEVICE_DPS_ENDPOINT global.azure-devices-provisioning.net IOTHUB_DEVICE_DPS_ID_SCOPE Hodnota oboru ID, kterou jste si poznamenali dříve. IOTHUB_DEVICE_DPS_DEVICE_ID sample-device-01 IOTHUB_DEVICE_DPS_DEVICE_KEY Vygenerovaná hodnota klíče zařízení, kterou jste si předtím poznamenali.
Ukázku teď můžete spustit a ladit v sadě Visual Studio.
Následující výstup ukazuje registraci zařízení a připojení k IoT Central. Ukázka začne odesílat telemetrii:
[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.
Jako operátor ve vaší aplikaci Azure IoT Central můžete:
Zobrazte telemetrii odesílanou dvěma komponentami termostatu na stránce Přehled :
Zobrazte vlastnosti zařízení na stránce O produktu. Tato stránka zobrazuje vlastnosti ze komponenty informací o zařízení a dvě komponenty termostatu:
Přizpůsobení šablony zařízení
Jako vývojář řešení můžete přizpůsobit šablonu zařízení, kterou Služba IoT Central vytvořila automaticky při připojení zařízení kontroleru teploty.
Přidání cloudové vlastnosti pro uložení jména zákazníka přidruženého k zařízení:
V aplikaci IoT Central přejděte na šablonu zařízení Teplotní kontroler na stránce Šablony zařízení.
V modelu Teplotní kontroler vyberte +Přidat schopnost.
Jako zobrazovaný název zadejte jméno zákazníka, jako typ schopnosti vyberte vlastnost Cloud, rozbalte položku a zvolte Řetězec jako schéma. Pak vyberte Uložit.
Přizpůsobení zobrazení příkazů sestavy Get Max-Min v aplikaci IoT Central:
Na stránce Šablony zařízení přejděte na šablonu zařízení Temperature Controller.
V případě getMaxMinReport (termostat1) nahraďte sestavu Get Max-Min.Získáte termostat1 stavovou zprávu.
V případě getMaxMinReport (termostat2) nahraďte sestavu Get Max-Min.Získáte zprávu o stavu termostat2.
Zvolte Uložit.
Přizpůsobení způsobu zobrazení zapisovatelných vlastností cílové teploty v aplikaci IoT Central:
Na stránce Šablony zařízení přejděte na šablonu zařízení Temperature Controller.
Pro targetTemperature (termostat1) nahraďte cílovou teplotu cílovou teplotou(1).
Pro targetTemperature (termostat2) nahraďte cílovou teplotu cílovou teplotou(2).
Zvolte Uložit.
Součástí termostatu v modelu kontroleru teploty je vlastnost Zapisovatelná cílová teplota , šablona zařízení obsahuje cloudovou vlastnost Customer Name . Vytvořte zobrazení, které může operátor použít k úpravě těchto vlastností:
Vyberte Zobrazení a pak vyberte dlaždici Pro úpravy zařízení a cloudových dat .
Jako název formuláře zadejte Vlastnosti .
Vyberte vlastnosti Cílová teplota (1), Cílová teplota (2) a Jméno zákazníka. Pak vyberte Přidat oddíl.
Uložte provedené změny.
Publikování šablony zařízení
Než operátor uvidí a použije vlastní nastavení, které jste provedli, musíte šablonu zařízení publikovat.
V šabloně termostatu vyberte Publikovat. Na panelu aplikace vyberte Publikovat tuto šablonu zařízení.
Operátor teď může pomocí zobrazení Vlastnosti aktualizovat hodnoty vlastností a volat příkazy s názvem Get termostat1 status report and Get termostat2 status report on the device commands page:
Aktualizujte zapisovatelné hodnoty vlastností na stránce Vlastnosti :
Volání příkazů ze stránky Příkazy Pokud spustíte příkaz zprávy o stavu, vyberte před spuštěním parametru Since datum a čas:
Uvidíte, jak zařízení reaguje na příkazy a aktualizace vlastností:
[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.
Důležité
Tento článek obsahuje postup připojení zařízení pomocí sdíleného přístupového podpisu, označovaného také jako ověřování symetrického klíče. Tato metoda ověřování je vhodná pro testování a vyhodnocení, ale ověřování zařízení pomocí certifikátů X.509 je bezpečnější přístup. Další informace najdete v tématu Zabezpečení osvědčených postupů > zabezpečení připojení.
Požadavky
K dokončení kroků v tomto článku potřebujete následující zdroje informací:
Aktivní předplatné Azure. Pokud ještě nemáte předplatné Azure, vytvořte si napřed bezplatný účet.
Aplikace IoT Central vytvořená ze šablony vlastní aplikace Další informace najdete v tématu Vytvoření aplikace IoT Central a Informace o vaší aplikaci.
Vývojový počítač se sadou Java SE Development Kit 8 nebo novější. Další informace naleznete v tématu Instalace sady JDK.
Místní kopie úložiště Microsoft Azure IoT SDK pro GitHub v Javě , která obsahuje ukázkový kód. Pomocí tohoto odkazu si můžete stáhnout kopii úložiště: Stáhnout soubor ZIP. Potom soubor rozbalte do vhodného umístění na místním počítači.
Kontrola kódu
V kopii sady Microsoft Azure IoT SDK pro Javu, kterou jste si stáhli dříve, otevřete azure-iot-sdk-java/iothub/device/iot-device-samples/pnp-device-sample/temperature-controller-device-sample/src/main/java/samples/com/microsoft/azure/sdk/iot/device/TemperatureController.java soubor v textovém editoru.
Ukázka implementuje model více komponent Temperature Controller Digital Twin Definition Language.
Když spustíte ukázku pro připojení k IoT Central, zaregistruje zařízení pomocí služby Device Provisioning Service (DPS) a vygeneruje připojovací řetězec. Ukázka načte informace o připojení DPS, které potřebuje, z prostředí příkazového řádku.
Metoda main
:
- Volání
initializeAndProvisionDevice
k nastavenídtmi:com:example:TemperatureController;2
ID modelu, zřízení a registrace zařízení pomocí DPS, vytvoření instance DeviceClient a připojení k aplikaci IoT Central. IoT Central používá ID modelu k identifikaci nebo vygenerování šablony zařízení pro toto zařízení. Další informace najdete v tématu Přiřazení zařízení k šabloně zařízení. - Vytvoří obslužné rutiny příkazů pro příkazy
getMaxMinReport
areboot
příkazy. - Vytvoří obslužné rutiny aktualizace vlastností pro zapisovatelné
targetTemperature
vlastnosti. - Odešle počáteční hodnoty vlastností v rozhraní Informace o zařízení a vlastnosti Paměť zařízení a Sériové číslo .
- Spustí vlákno, které odešle telemetrii teploty ze dvou termostatů a aktualizuje
maxTempSinceLastReboot
vlastnost každých pět sekund.
public static void main(String[] args) throws Exception {
// ...
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.subscribeToMethods(new MethodCallback(), null);
deviceClient.subscribeToDesiredPropertiesAsync(
{
(twin, context) ->
TwinCollection desiredProperties = twin.getDesiredProperties();
for (String desiredPropertyKey : desiredProperties.keySet())
{
TargetTemperatureUpdateCallback.onPropertyChanged(new Property(desiredPropertyKey, desiredProperties.get(desiredPropertyKey)), null);
}
},
null,
(exception, context) ->
{
if (exception == null)
{
log.info("Successfully subscribed to desired properties. Getting initial state");
deviceClient.getTwinAsync(
(twin, getTwinException, getTwinContext) ->
{
log.info("Initial twin state received");
log.info(twin.toString());
},
null);
}
else
{
log.info("Failed to subscribe to desired properties. Error code {}", exception.getStatusCode());
System.exit(-1);
}
},
null);
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();
}
Tato initializeAndProvisionDevice
metoda ukazuje, jak zařízení používá DPS k registraci a připojení k IoT Central. Datová část obsahuje ID modelu, které IoT Central používá k přiřazení zařízení k šabloně zařízení:
private static void initializeAndProvisionDevice() throws Exception {
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));
ProvisioningDeviceClientRegistrationResult registrationResult = provisioningDeviceClient.registerDeviceSync(additionalData);
ClientOptions options = ClientOptions.builder().modelId(MODEL_ID).build();
if (registrationResult.getProvisioningDeviceClientStatus() == ProvisioningDeviceClientStatus.PROVISIONING_DEVICE_STATUS_ASSIGNED) {
System.out.println("IotHUb Uri : " + registrationResult.getIothubUri());
System.out.println("Device ID : " + registrationResult.getDeviceId());
String iotHubUri = registrationResult.getIothubUri();
String deviceId = registrationResult.getDeviceId();
log.debug("Opening the device client.");
deviceClient = new DeviceClient(iotHubUri, deviceId, securityClientSymmetricKey, IotHubClientProtocol.MQTT, options);
deviceClient.open(true);
}
}
Tato sendTemperatureTelemetry
metoda ukazuje, jak zařízení odesílá telemetrii teploty ze komponenty do IoT Central. Tato metoda používá PnpConvention
třídu k vytvoření zprávy:
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);
}
Metoda updateMaxTemperatureSinceLastReboot
odešle maxTempSinceLastReboot
aktualizaci vlastnosti ze komponenty do IoT Central. Tato metoda používá PnpConvention
třídu k vytvoření opravy:
private static void updateMaxTemperatureSinceLastReboot(String componentName) throws IOException {
String propertyName = "maxTempSinceLastReboot";
double maxTemp = maxTemperature.get(componentName);
TwinCollection reportedProperty = PnpConvention.createComponentPropertyPatch(propertyName, maxTemp, componentName);
deviceClient.updateReportedPropertiesAsync(reportedProperty, sendReportedPropertiesResponseCallback, null);
log.debug("Property: Update - {\"{}\": {}°C} is {}.", propertyName, maxTemp, StatusCode.COMPLETED);
}
Třída TargetTemperatureUpdateCallback
obsahuje metodu onPropertyChanged
pro zpracování zapisovatelných vlastností aktualizace komponenty z IoT Central. Tato metoda používá PnpConvention
třídu k vytvoření odpovědi:
private static class TargetTemperatureUpdateCallback
{
final static String propertyName = "targetTemperature";
@SneakyThrows(InterruptedException.class)
public static void onPropertyChanged(Property property, Object context) {
String componentName = (String) context;
if (property.getKey().equalsIgnoreCase(componentName)) {
double targetTemperature = (double) ((TwinCollection) property.getValue()).get(propertyName);
log.debug("Property: Received - component=\"{}\", {\"{}\": {}°C}.", componentName, propertyName, targetTemperature);
TwinCollection pendingPropertyPatch = PnpConvention.createComponentWritablePropertyResponse(
propertyName,
targetTemperature,
componentName,
StatusCode.IN_PROGRESS.value,
property.getVersion().longValue(),
null);
deviceClient.updateReportedPropertiesAsync(pendingPropertyPatch, sendReportedPropertiesResponseCallback, null);
log.debug("Property: Update - component=\"{}\", {\"{}\": {}°C} is {}", componentName, propertyName, targetTemperature, StatusCode.IN_PROGRESS);
// 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);
}
TwinCollection completedPropertyPatch = PnpConvention.createComponentWritablePropertyResponse(
propertyName,
temperature.get(componentName),
componentName,
StatusCode.COMPLETED.value,
property.getVersion().longValue(),
"Successfully updated target temperature.");
deviceClient.updateReportedPropertiesAsync(completedPropertyPatch, sendReportedPropertiesResponseCallback, null);
log.debug("Property: Update - {\"{}\": {}°C} is {}", propertyName, temperature.get(componentName), StatusCode.COMPLETED);
} else {
log.debug("Property: Received an unrecognized property update from service.");
}
}
}
Třída MethodCallback
obsahuje metodu onMethodInvoked
pro zpracování příkazů komponent volané z IoT Central:
private static class MethodCallback implements com.microsoft.azure.sdk.iot.device.twin.MethodCallback
{
final String reboot = "reboot";
final String getMaxMinReport1 = "thermostat1*getMaxMinReport";
final String getMaxMinReport2 = "thermostat2*getMaxMinReport";
@SneakyThrows(InterruptedException.class)
@Override
public DirectMethodResponse onMethodInvoked(String methodName, DirectMethodPayload methodData, Object context) {
String jsonRequest = methodData.getPayload(String.class);
switch (methodName) {
case reboot:
int delay = getCommandRequestValue(jsonRequest, Integer.class);
log.debug("Command: Received - Rebooting thermostat (resetting temperature reading to 0°C after {} seconds).", delay);
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 DirectMethodResponse(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);
log.debug("Command: Received - component=\"{}\", generating min, max, avg temperature report since {}", componentName, since);
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);
log.debug("Command: MaxMinReport since {}: \"maxTemp\": {}°C, \"minTemp\": {}°C, \"avgTemp\": {}°C, \"startTime\": {}, \"endTime\": {}",
since,
maxTemp,
minTemp,
avgTemp,
startTime,
endTime);
return new DirectMethodResponse(StatusCode.COMPLETED.value, responsePayload);
}
log.debug("Command: component=\"{}\", no relevant readings found since {}, cannot generate any report.", componentName, since);
return new DirectMethodResponse(StatusCode.NOT_FOUND.value, null);
}
log.debug("Command: component=\"{}\", no temperature readings sent yet, cannot generate any report.", componentName);
return new DirectMethodResponse(StatusCode.NOT_FOUND.value, null);
default:
log.debug("Command: command=\"{}\" is not implemented, no action taken.", methodName);
return new DirectMethodResponse(StatusCode.NOT_FOUND.value, null);
}
}
}
Získání informací o připojení
Když později v tomto kurzu spustíte ukázkovou aplikaci zařízení, budete potřebovat následující konfigurační hodnoty:
- Rozsah ID: V aplikaci IoT Central přejděte do skupin připojení zařízení oprávnění>. Poznamenejte si hodnotu oboru ID.
- Primární klíč skupiny: V aplikaci IoT Central přejděte na Skupiny > připojení zařízení OPRÁVNĚNÍ > SAS-IoT-Devices. Poznamenejte si hodnotu primárního klíče sdíleného přístupového podpisu.
Pomocí Azure Cloud Shellu vygenerujte klíč zařízení z primárního klíče skupiny, který jste získali:
az extension add --name azure-iot
az iot central device compute-device-key --device-id sample-device-01 --pk <the group primary key value>
Poznamenejte si vygenerovaný klíč zařízení, který použijete později v tomto kurzu.
Poznámka:
Pokud chcete tuto ukázku spustit, nemusíte zařízení předem zaregistrovat ve své aplikaci IoT Central. Ukázka používá funkci IoT Central k automatické registraci zařízení při prvním připojení.
Ve Windows přejděte do kořenové složky úložiště Azure IoT SDK pro Javu, které jste stáhli.
Spuštěním následujícího příkazu sestavte ukázkovou aplikaci:
mvn install -T 2C -DskipTests
Spuštění kódu
Pokud chcete spustit ukázkovou aplikaci, otevřete prostředí příkazového řádku a přejděte do složky azure-iot-sdk-java/iothub/device/iot-device-samples/pnp-device-sample/temperature-controller-device-sample , která obsahuje složku src s ukázkovým souborem TemperatureController.java .
Nastavte proměnné prostředí pro konfiguraci ukázky. Následující fragment kódu ukazuje, jak nastavit proměnné prostředí na příkazovém řádku Windows. Pokud používáte prostředí Bash , nahraďte set
příkazy export
příkazy:
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
Spusťte ukázku:
mvn exec:java -Dexec.mainClass="samples.com.microsoft.azure.sdk.iot.device.TemperatureController"
Následující výstup ukazuje registraci zařízení a připojení k IoT Central. Ukázka začne odesílat telemetrii:
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 [aaaa0000-bb11-2222-33cc-444444dddddd] Message Id [bbbb1111-cc22-3333-44dd-555555eeeeee] 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 [aaaa0000-bb11-2222-33cc-444444dddddd] Message Id [bbbb1111-cc22-3333-44dd-555555eeeeee] 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 [cccc2222-dd33-4444-55ee-666666ffffff] Message Id [dddd3333-ee44-5555-66ff-777777aaaaaa] 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 [eeee4444-ff55-6666-77aa-888888bbbbbb] Message Id [ffff5555-aa66-7777-88bb-999999cccccc] 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 [aaaa6666-bb77-8888-99cc-000000dddddd] Message Id [aaaa0000-bb11-2222-33cc-444444dddddd] 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 [cccc2222-dd33-4444-55ee-666666ffffff] Message Id [dddd3333-ee44-5555-66ff-777777aaaaaa] 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 [bbbb1111-cc22-3333-44dd-555555eeeeee] Message Id [cccc2222-dd33-4444-55ee-666666ffffff] 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 [dddd3333-ee44-5555-66ff-777777aaaaaa] Message Id [eeee4444-ff55-6666-77aa-888888bbbbbb] )
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 [ffff5555-aa66-7777-88bb-999999cccccc] Message Id [aaaa6666-bb77-8888-99cc-000000dddddd] 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 [aaaa0000-bb11-2222-33cc-444444dddddd] Message Id [bbbb1111-cc22-3333-44dd-555555eeeeee] )
2021-03-30 15:33:44.927 DEBUG TemperatureController:461 - Telemetry: Sent - {"temperature": 5.8°C} with message Id bbbb1111-cc22-3333-44dd-555555eeeeee.
Jako operátor ve vaší aplikaci Azure IoT Central můžete:
Zobrazte telemetrii odesílanou dvěma komponentami termostatu na stránce Přehled :
Zobrazte vlastnosti zařízení na stránce O produktu. Tato stránka zobrazuje vlastnosti ze komponenty informací o zařízení a dvě komponenty termostatu:
Přizpůsobení šablony zařízení
Jako vývojář řešení můžete přizpůsobit šablonu zařízení, kterou Služba IoT Central vytvořila automaticky při připojení zařízení kontroleru teploty.
Přidání cloudové vlastnosti pro uložení jména zákazníka přidruženého k zařízení:
V aplikaci IoT Central přejděte na šablonu zařízení Teplotní kontroler na stránce Šablony zařízení.
V modelu Teplotní kontroler vyberte +Přidat schopnost.
Jako zobrazovaný název zadejte jméno zákazníka, jako typ schopnosti vyberte vlastnost Cloud, rozbalte položku a zvolte Řetězec jako schéma. Pak vyberte Uložit.
Přizpůsobení zobrazení příkazů sestavy Get Max-Min v aplikaci IoT Central:
Na stránce Šablony zařízení přejděte na šablonu zařízení Temperature Controller.
V případě getMaxMinReport (termostat1) nahraďte sestavu Get Max-Min.Získáte termostat1 stavovou zprávu.
V případě getMaxMinReport (termostat2) nahraďte sestavu Get Max-Min.Získáte zprávu o stavu termostat2.
Zvolte Uložit.
Přizpůsobení způsobu zobrazení zapisovatelných vlastností cílové teploty v aplikaci IoT Central:
Na stránce Šablony zařízení přejděte na šablonu zařízení Temperature Controller.
Pro targetTemperature (termostat1) nahraďte cílovou teplotu cílovou teplotou(1).
Pro targetTemperature (termostat2) nahraďte cílovou teplotu cílovou teplotou(2).
Zvolte Uložit.
Součástí termostatu v modelu kontroleru teploty je vlastnost Zapisovatelná cílová teplota , šablona zařízení obsahuje cloudovou vlastnost Customer Name . Vytvořte zobrazení, které může operátor použít k úpravě těchto vlastností:
Vyberte Zobrazení a pak vyberte dlaždici Pro úpravy zařízení a cloudových dat .
Jako název formuláře zadejte Vlastnosti .
Vyberte vlastnosti Cílová teplota (1), Cílová teplota (2) a Jméno zákazníka. Pak vyberte Přidat oddíl.
Uložte provedené změny.
Publikování šablony zařízení
Než operátor uvidí a použije vlastní nastavení, které jste provedli, musíte šablonu zařízení publikovat.
V šabloně termostatu vyberte Publikovat. Na panelu aplikace vyberte Publikovat tuto šablonu zařízení.
Operátor teď může pomocí zobrazení Vlastnosti aktualizovat hodnoty vlastností a volat příkazy s názvem Get termostat1 status report and Get termostat2 status report on the device commands page:
Aktualizujte zapisovatelné hodnoty vlastností na stránce Vlastnosti :
Volání příkazů ze stránky Příkazy Pokud spustíte příkaz zprávy o stavu, vyberte před spuštěním parametru Since datum a čas:
Uvidíte, jak zařízení reaguje na příkazy a aktualizace vlastností:
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
Důležité
Tento článek obsahuje postup připojení zařízení pomocí sdíleného přístupového podpisu, označovaného také jako ověřování symetrického klíče. Tato metoda ověřování je vhodná pro testování a vyhodnocení, ale ověřování zařízení pomocí certifikátů X.509 je bezpečnější přístup. Další informace najdete v tématu Zabezpečení osvědčených postupů > zabezpečení připojení.
Požadavky
K dokončení kroků v tomto článku potřebujete následující zdroje informací:
Aktivní předplatné Azure. Pokud ještě nemáte předplatné Azure, vytvořte si napřed bezplatný účet.
Aplikace IoT Central vytvořená ze šablony vlastní aplikace Další informace najdete v tématu Vytvoření aplikace IoT Central a Informace o vaší aplikaci.
Vývojový počítač s nainstalovaným Node.js verze 6 nebo novější. Verzi můžete zkontrolovat spuštěním
node --version
na příkazovém řádku. Pokyny v tomto kurzu předpokládají, že spouštíte příkaz node na příkazovém řádku Windows. Můžete ale použít Node.js v mnoha dalších operačních systémech.Místní kopie sady Microsoft Azure IoT SDK pro Node.js úložiště GitHub, která obsahuje ukázkový kód. Pomocí tohoto odkazu si můžete stáhnout kopii úložiště: Stáhnout soubor ZIP. Potom soubor rozbalte do vhodného umístění na místním počítači.
Kontrola kódu
V kopii sady Microsoft Azure IoT SDK pro Node.js, kterou jste si stáhli dříve, otevřete soubor azure-iot-sdk-node/device/samples/javascript/pnp_temperature_controller.js v textovém editoru.
Ukázka implementuje model více komponent Temperature Controller Digital Twin Definition Language.
Když spustíte ukázku pro připojení k IoT Central, zaregistruje zařízení pomocí služby Device Provisioning Service (DPS) a vygeneruje připojovací řetězec. Ukázka načte informace o připojení DPS, které potřebuje, z prostředí příkazového řádku.
Metoda main
:
-
client
Vytvoří objekt a nastavídtmi:com:example:TemperatureController;2
ID modelu před otevřením připojení. IoT Central používá ID modelu k identifikaci nebo vygenerování šablony zařízení pro toto zařízení. Další informace najdete v tématu Přiřazení zařízení k šabloně zařízení. - Vytvoří obslužné rutiny příkazů pro tři příkazy.
- Spustí smyčku pro každou termostatovou komponentu, která každých 5 sekund odesílá telemetrii teploty.
- Spustí smyčku pro výchozí komponentu pro odesílání telemetrie velikosti pracovní sady každých 6 sekund.
-
maxTempSinceLastReboot
Odešle vlastnost pro každou termostatovou komponentu. - Odešle vlastnosti informací o zařízení.
- Vytvoří obslužné rutiny zapisovatelných vlastností pro tři komponenty.
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());
}
}
Funkce provisionDevice
ukazuje, jak zařízení používá DPS k registraci a připojení k IoT Central. Datová část obsahuje ID modelu, které IoT Central používá k přiřazení zařízení k šabloně zařízení:
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());
}
}
Funkce sendTelemetry
ukazuje, jak zařízení odesílá telemetrii teploty do IoT Central. Pro telemetrii ze součástí přidá vlastnost volanou $.sub
s názvem komponenty:
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);
}
Metoda main
používá pomocnou metodu volanou helperCreateReportedPropertiesPatch
k vytvoření zpráv aktualizace vlastností. Tato metoda přebírá volitelný parametr k určení komponenty odesílající vlastnost:
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;
};
Metoda main
používá následující metodu ke zpracování aktualizací zapisovatelných vlastností z IoT Central. Všimněte si, jak metoda sestaví odpověď pomocí verze a stavového kódu:
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);
}
});
});
};
Metoda main
používá k zpracování příkazů z IoT Central následující metody:
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 occurred when sending a method response:\n' + err.toString());
}
};
Získání informací o připojení
Když později v tomto kurzu spustíte ukázkovou aplikaci zařízení, budete potřebovat následující konfigurační hodnoty:
- Rozsah ID: V aplikaci IoT Central přejděte do skupin připojení zařízení oprávnění>. Poznamenejte si hodnotu oboru ID.
- Primární klíč skupiny: V aplikaci IoT Central přejděte na Skupiny > připojení zařízení OPRÁVNĚNÍ > SAS-IoT-Devices. Poznamenejte si hodnotu primárního klíče sdíleného přístupového podpisu.
Pomocí Azure Cloud Shellu vygenerujte klíč zařízení z primárního klíče skupiny, který jste získali:
az extension add --name azure-iot
az iot central device compute-device-key --device-id sample-device-01 --pk <the group primary key value>
Poznamenejte si vygenerovaný klíč zařízení, který použijete později v tomto kurzu.
Poznámka:
Pokud chcete tuto ukázku spustit, nemusíte zařízení předem zaregistrovat ve své aplikaci IoT Central. Ukázka používá funkci IoT Central k automatické registraci zařízení při prvním připojení.
Spuštění kódu
Pokud chcete spustit ukázkovou aplikaci, otevřete prostředí příkazového řádku a přejděte do složky azure-iot-sdk-node/device/samples/javascriptová složka, která obsahuje ukázkový soubor pnp_temperature_controller.js .
Nastavte proměnné prostředí pro konfiguraci ukázky. Následující fragment kódu ukazuje, jak nastavit proměnné prostředí na příkazovém řádku Windows. Pokud používáte prostředí Bash , nahraďte set
příkazy export
příkazy:
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
Nainstalujte požadované balíčky:
npm install
Spusťte ukázku:
node pnp_temperature_controller.js
Následující výstup ukazuje registraci zařízení a připojení k IoT Central. Ukázka pak odešle maxTempSinceLastReboot
vlastnost ze dvou termostatických komponent předtím, než začne odesílat telemetrii:
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
Jako operátor ve vaší aplikaci Azure IoT Central můžete:
Zobrazte telemetrii odesílanou dvěma komponentami termostatu na stránce Přehled :
Zobrazte vlastnosti zařízení na stránce O produktu. Tato stránka zobrazuje vlastnosti ze komponenty informací o zařízení a dvě komponenty termostatu:
Přizpůsobení šablony zařízení
Jako vývojář řešení můžete přizpůsobit šablonu zařízení, kterou Služba IoT Central vytvořila automaticky při připojení zařízení kontroleru teploty.
Přidání cloudové vlastnosti pro uložení jména zákazníka přidruženého k zařízení:
V aplikaci IoT Central přejděte na šablonu zařízení Teplotní kontroler na stránce Šablony zařízení.
V modelu Teplotní kontroler vyberte +Přidat schopnost.
Jako zobrazovaný název zadejte jméno zákazníka, jako typ schopnosti vyberte vlastnost Cloud, rozbalte položku a zvolte Řetězec jako schéma. Pak vyberte Uložit.
Přizpůsobení zobrazení příkazů sestavy Get Max-Min v aplikaci IoT Central:
Na stránce Šablony zařízení přejděte na šablonu zařízení Temperature Controller.
V případě getMaxMinReport (termostat1) nahraďte sestavu Get Max-Min.Získáte termostat1 stavovou zprávu.
V případě getMaxMinReport (termostat2) nahraďte sestavu Get Max-Min.Získáte zprávu o stavu termostat2.
Zvolte Uložit.
Přizpůsobení způsobu zobrazení zapisovatelných vlastností cílové teploty v aplikaci IoT Central:
Na stránce Šablony zařízení přejděte na šablonu zařízení Temperature Controller.
Pro targetTemperature (termostat1) nahraďte cílovou teplotu cílovou teplotou(1).
Pro targetTemperature (termostat2) nahraďte cílovou teplotu cílovou teplotou(2).
Zvolte Uložit.
Součástí termostatu v modelu kontroleru teploty je vlastnost Zapisovatelná cílová teplota , šablona zařízení obsahuje cloudovou vlastnost Customer Name . Vytvořte zobrazení, které může operátor použít k úpravě těchto vlastností:
Vyberte Zobrazení a pak vyberte dlaždici Pro úpravy zařízení a cloudových dat .
Jako název formuláře zadejte Vlastnosti .
Vyberte vlastnosti Cílová teplota (1), Cílová teplota (2) a Jméno zákazníka. Pak vyberte Přidat oddíl.
Uložte provedené změny.
Publikování šablony zařízení
Než operátor uvidí a použije vlastní nastavení, které jste provedli, musíte šablonu zařízení publikovat.
V šabloně termostatu vyberte Publikovat. Na panelu aplikace vyberte Publikovat tuto šablonu zařízení.
Operátor teď může pomocí zobrazení Vlastnosti aktualizovat hodnoty vlastností a volat příkazy s názvem Get termostat1 status report and Get termostat2 status report on the device commands page:
Aktualizujte zapisovatelné hodnoty vlastností na stránce Vlastnosti :
Volání příkazů ze stránky Příkazy Pokud spustíte příkaz zprávy o stavu, vyberte před spuštěním parametru Since datum a čas:
Uvidíte, jak zařízení reaguje na příkazy a aktualizace vlastností. Příkaz getMaxMinReport
je v komponentě thermostat2
, reboot
příkaz je ve výchozí komponentě. Zapisovatelná targetTemperature
vlastnost byla nastavena pro komponentu thermostat2
:
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
Důležité
Tento článek obsahuje postup připojení zařízení pomocí sdíleného přístupového podpisu, označovaného také jako ověřování symetrického klíče. Tato metoda ověřování je vhodná pro testování a vyhodnocení, ale ověřování zařízení pomocí certifikátů X.509 je bezpečnější přístup. Další informace najdete v tématu Zabezpečení osvědčených postupů > zabezpečení připojení.
Požadavky
K dokončení kroků v tomto článku potřebujete následující zdroje informací:
Aktivní předplatné Azure. Pokud ještě nemáte předplatné Azure, vytvořte si napřed bezplatný účet.
Aplikace IoT Central vytvořená ze šablony vlastní aplikace Další informace najdete v tématu Vytvoření aplikace IoT Central a Informace o vaší aplikaci.
Vývojový počítač s nainstalovaným Pythonem Zkontrolujte aktuální požadavky na verzi Pythonu v sadě Azure IoT Python SDK. Verzi můžete zkontrolovat spuštěním
python --version
na příkazovém řádku. Python je k dispozici pro širokou škálu operačních systémů. Pokyny v tomto kurzu předpokládají, že spouštíte příkaz Pythonu na příkazovém řádku Windows.Místní kopie úložiště Microsoft Azure IoT SDK pro GitHub v Pythonu , která obsahuje ukázkový kód. Pomocí tohoto odkazu si můžete stáhnout kopii úložiště: Stáhnout soubor ZIP. Potom soubor rozbalte do vhodného umístění na místním počítači.
Kontrola kódu
V kopii sady Microsoft Azure IoT SDK pro Python, kterou jste si stáhli dříve, otevřete soubor azure-iot-sdk-python/samples/pnp/temp_controller_with_thermostats.py v textovém editoru.
Ukázka implementuje model více komponent Temperature Controller Digital Twin Definition Language.
Když spustíte ukázku pro připojení k IoT Central, zaregistruje zařízení pomocí služby Device Provisioning Service (DPS) a vygeneruje připojovací řetězec. Ukázka načte informace o připojení DPS, které potřebuje, z prostředí příkazového řádku.
Funkce main
:
- Používá službu DPS ke zřízení zařízení. Informace o zřizování zahrnují ID modelu. IoT Central používá ID modelu k identifikaci nebo vygenerování šablony zařízení pro toto zařízení. Další informace najdete v tématu Přiřazení zařízení k šabloně zařízení.
-
Device_client
Vytvoří objekt a nastavídtmi:com:example:TemperatureController;2
ID modelu před otevřením připojení. - Odešle počáteční hodnoty vlastností do IoT Central. Používá
pnp_helper
k vytvoření oprav. - Vytvoří naslouchací procesy pro příkazy
getMaxMinReport
areboot
příkazy. Každá komponenta termostatu má svůj vlastnígetMaxMinReport
příkaz. - Vytvoří naslouchací proces vlastností pro naslouchání aktualizacím zapisovatelných vlastností.
- Spustí smyčku pro odesílání telemetrie teploty ze dvou komponent termostatu a funkční nastavení telemetrie z výchozí komponenty každých 8 sekund.
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())
# ...
Tato provision_device
funkce pomocí DPS zřídí zařízení a zaregistruje ho ve službě IoT Central. Tato funkce zahrnuje ID modelu zařízení, které IoT Central používá k přiřazení zařízení k šabloně zařízení, v datové části zřizování:
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()
Funkce execute_command_listener
zpracovává požadavky na příkazy, spustí max_min_handler
funkci, když zařízení přijme getMaxMinReport
příkaz pro součásti termostatu reboot_handler
a funkci, když zařízení obdrží reboot
příkaz. Pomocí pnp_helper
modulu sestaví odpověď:
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))
Zpracovává async def execute_property_listener
aktualizace zapisovatelných vlastností, například targetTemperature
pro komponenty termostatu, a generuje odpověď JSON. Pomocí pnp_helper
modulu sestaví odpověď:
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)
Funkce send_telemetry_from_temp_controller
odesílá telemetrické zprávy ze komponent termostatu do IoT Central. Modul používá pnp_helper
k sestavení zpráv:
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)
Získání informací o připojení
Když později v tomto kurzu spustíte ukázkovou aplikaci zařízení, budete potřebovat následující konfigurační hodnoty:
- Rozsah ID: V aplikaci IoT Central přejděte do skupin připojení zařízení oprávnění>. Poznamenejte si hodnotu oboru ID.
- Primární klíč skupiny: V aplikaci IoT Central přejděte na Skupiny > připojení zařízení OPRÁVNĚNÍ > SAS-IoT-Devices. Poznamenejte si hodnotu primárního klíče sdíleného přístupového podpisu.
Pomocí Azure Cloud Shellu vygenerujte klíč zařízení z primárního klíče skupiny, který jste získali:
az extension add --name azure-iot
az iot central device compute-device-key --device-id sample-device-01 --pk <the group primary key value>
Poznamenejte si vygenerovaný klíč zařízení, který použijete později v tomto kurzu.
Poznámka:
Pokud chcete tuto ukázku spustit, nemusíte zařízení předem zaregistrovat ve své aplikaci IoT Central. Ukázka používá funkci IoT Central k automatické registraci zařízení při prvním připojení.
Spuštění kódu
Pokud chcete spustit ukázkovou aplikaci, otevřete prostředí příkazového řádku a přejděte do složky azure-iot-sdk-python-2/samples/pnp , která obsahuje ukázkový soubor temp_controller_with_thermostats.py .
Nastavte proměnné prostředí pro konfiguraci ukázky. Následující fragment kódu ukazuje, jak nastavit proměnné prostředí na příkazovém řádku Windows. Pokud používáte prostředí Bash , nahraďte set
příkazy export
příkazy:
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
Nainstalujte požadované balíčky:
pip install azure-iot-device
Spusťte ukázku:
python temp_controller_with_thermostats.py
Následující výstup ukazuje registraci zařízení a připojení k IoT Central. Ukázka odešle maxTempSinceLastReboot
vlastnosti ze dvou komponent termostatu před tím, než začne odesílat telemetrii:
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}
Jako operátor ve vaší aplikaci Azure IoT Central můžete:
Zobrazte telemetrii odesílanou dvěma komponentami termostatu na stránce Přehled :
Zobrazte vlastnosti zařízení na stránce O produktu. Tato stránka zobrazuje vlastnosti ze komponenty informací o zařízení a dvě komponenty termostatu:
Přizpůsobení šablony zařízení
Jako vývojář řešení můžete přizpůsobit šablonu zařízení, kterou Služba IoT Central vytvořila automaticky při připojení zařízení kontroleru teploty.
Přidání cloudové vlastnosti pro uložení jména zákazníka přidruženého k zařízení:
V aplikaci IoT Central přejděte na šablonu zařízení Teplotní kontroler na stránce Šablony zařízení.
V modelu Teplotní kontroler vyberte +Přidat schopnost.
Jako zobrazovaný název zadejte jméno zákazníka, jako typ schopnosti vyberte vlastnost Cloud, rozbalte položku a zvolte Řetězec jako schéma. Pak vyberte Uložit.
Přizpůsobení zobrazení příkazů sestavy Get Max-Min v aplikaci IoT Central:
Na stránce Šablony zařízení přejděte na šablonu zařízení Temperature Controller.
V případě getMaxMinReport (termostat1) nahraďte sestavu Get Max-Min.Získáte termostat1 stavovou zprávu.
V případě getMaxMinReport (termostat2) nahraďte sestavu Get Max-Min.Získáte zprávu o stavu termostat2.
Zvolte Uložit.
Přizpůsobení způsobu zobrazení zapisovatelných vlastností cílové teploty v aplikaci IoT Central:
Na stránce Šablony zařízení přejděte na šablonu zařízení Temperature Controller.
Pro targetTemperature (termostat1) nahraďte cílovou teplotu cílovou teplotou(1).
Pro targetTemperature (termostat2) nahraďte cílovou teplotu cílovou teplotou(2).
Zvolte Uložit.
Součástí termostatu v modelu kontroleru teploty je vlastnost Zapisovatelná cílová teplota , šablona zařízení obsahuje cloudovou vlastnost Customer Name . Vytvořte zobrazení, které může operátor použít k úpravě těchto vlastností:
Vyberte Zobrazení a pak vyberte dlaždici Pro úpravy zařízení a cloudových dat .
Jako název formuláře zadejte Vlastnosti .
Vyberte vlastnosti Cílová teplota (1), Cílová teplota (2) a Jméno zákazníka. Pak vyberte Přidat oddíl.
Uložte provedené změny.
Publikování šablony zařízení
Než operátor uvidí a použije vlastní nastavení, které jste provedli, musíte šablonu zařízení publikovat.
V šabloně termostatu vyberte Publikovat. Na panelu aplikace vyberte Publikovat tuto šablonu zařízení.
Operátor teď může pomocí zobrazení Vlastnosti aktualizovat hodnoty vlastností a volat příkazy s názvem Get termostat1 status report and Get termostat2 status report on the device commands page:
Aktualizujte zapisovatelné hodnoty vlastností na stránce Vlastnosti :
Volání příkazů ze stránky Příkazy Pokud spustíte příkaz zprávy o stavu, vyberte před spuštěním parametru Since datum a čas:
Uvidíte, jak zařízení reaguje na příkazy a aktualizace vlastností:
{'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"}
Zobrazení nezpracovaných dat
Pomocí zobrazení nezpracovaných dat můžete zkoumat nezpracovaná data, která vaše zařízení odesílá do IoT Central:
V tomto zobrazení můžete vybrat sloupce, které chcete zobrazit, a nastavit časový rozsah pro zobrazení. Nevymodelovaný datový sloupec zobrazuje data zařízení, která neodpovídají žádné definici vlastností nebo telemetrie v šabloně zařízení.
Vyčištění prostředků
Pokud nemáte v úmyslu dokončit žádné další rychlé starty nebo kurzy IoT Central, můžete aplikaci IoT Central odstranit:
- V aplikaci IoT Central přejděte do správy aplikací>.
- Vyberte Odstranit a potvrďte akci.
Další kroky
Pokud chcete pokračovat v sadě kurzů IoT Central a získat další informace o vytváření řešení IoT Central, přečtěte si téma: