Tutorial: Interact with an IoT Plug and Play device that's connected to your solution

IoT Plug and Play simplifies IoT by enabling you to interact with a device's capabilities without knowledge of the underlying device implementation. This tutorial shows you how to use C# to connect to and control an IoT Plug and Play device that's connected to your solution.

Prerequisites

Before you continue, make sure you've set up your environment, including your IoT hub.

You can run this tutorial on Linux or Windows. The shell commands in this tutorial follow the Linux convention for path separators '/', if you're following along on Windows be sure to swap these separators for '\'.

Clone the SDK repository with the sample code

If you completed Tutorial: Connect a sample IoT Plug and Play device application running on Windows to IoT Hub (C#), you've already cloned the repository.

Clone the samples from the Azure IoT SDK for C# GitHub repository. Open a command prompt in a folder of your choice. Run the following command to clone the Microsoft Azure IoT SDK for .NET GitHub repository:

git clone https://github.com/Azure/azure-iot-sdk-csharp.git

Build the device code

You can now build the device sample and run it. Run the following commands to build the sample:

cd azure-iot-sdk-csharp/iothub/device/samples/solutions/PnpDeviceSamples/Thermostat
dotnet build

Run the device sample

To run the sample, run the following command:

dotnet run

The device is now ready to receive commands and property updates, and has started sending telemetry data to the hub. Keep the sample running as you complete the next steps.

Run the sample solution

In Set up your environment for the IoT Plug and Play quickstarts and tutorials you created two environment variables to configure the sample to connect to your IoT hub:

  • IOTHUB_CONNECTION_STRING: the IoT hub connection string you made a note of previously.
  • IOTHUB_DEVICE_ID: "my-pnp-device".

In this tutorial, you use a sample IoT solution written in C# to interact with the sample device you just set up and ran.

  1. In another terminal window, navigate to the azure-iot-sdk-csharp/iothub/service/samples/solutions/PnpServiceSamples/Thermostat folder.

  2. Run the following command to build the service sample:

    dotnet build
    
  3. Run the following command to run the service sample:

    dotnet run
    

Get device twin

The following code snippet shows how the service application retrieves the device twin:

// Get a Twin and retrieves model Id set by Device client
Twin twin = await s_registryManager.GetTwinAsync(s_deviceId);
s_logger.LogDebug($"Model Id of this Twin is: {twin.ModelId}");

Note

This sample uses the Microsoft.Azure.Devices.Client namespace from the IoT Hub service client. To learn more about the APIs, including the digital twins API, see the service developer guide.

This code generates the following output:

[09/21/2020 11:26:04]dbug: Thermostat.Program[0]
      Model Id of this Twin is: dtmi:com:example:Thermostat;1

The following code snippet shows how to use a patch to update properties through the device twin:

// Update the twin
var twinPatch = new Twin();
twinPatch.Properties.Desired[PropertyName] = PropertyValue;
await s_registryManager.UpdateTwinAsync(s_deviceId, twinPatch, twin.ETag);

This code generates the following output from the device when the service updates the targetTemperature property:

[09/21/2020 11:26:05]dbug: Thermostat.ThermostatSample[0]
      Property: Received - { "targetTemperature": 60°C }.
[09/21/2020 11:26:05]dbug: Thermostat.ThermostatSample[0]
      Property: Update - {"targetTemperature": 60°C } is InProgress.

...

[09/21/2020 11:26:17]dbug: Thermostat.ThermostatSample[0]
      Property: Update - {"targetTemperature": 60°C } is Completed.

Invoke a command

The following code snippet shows how to call a command:

private static async Task InvokeCommandAsync()
{
    var commandInvocation = new CloudToDeviceMethod(CommandName) { ResponseTimeout = TimeSpan.FromSeconds(30) };

    // Set command payload
    string componentCommandPayload = JsonConvert.SerializeObject(s_dateTime);
    commandInvocation.SetPayloadJson(componentCommandPayload);

    CloudToDeviceMethodResult result = await s_serviceClient.InvokeDeviceMethodAsync(s_deviceId, commandInvocation);

    if (result == null)
    {
        throw new Exception($"Command {CommandName} invocation returned null");
    }

    s_logger.LogDebug($"Command {CommandName} invocation result status is: {result.Status}");
}

This code generates the following output from the device when the service calls the getMaxMinReport command:

[09/21/2020 11:26:05]dbug: Thermostat.ThermostatSample[0]
      Command: Received - Generating max, min and avg temperature report since 21/09/2020 11:25:58.
[09/21/2020 11:26:05]dbug: Thermostat.ThermostatSample[0]
      Command: MaxMinReport since 21/09/2020 11:25:58: maxTemp=32, minTemp=32, avgTemp=32, startTime=21/09/2020 11:25:59, endTime=21/09/2020 11:26:04

IoT Plug and Play simplifies IoT by enabling you to interact with a device's capabilities without knowledge of the underlying device implementation. This tutorial shows you how to use Java to connect to and control an IoT Plug and Play device that's connected to your solution.

Prerequisites

Before you continue, make sure you've set up your environment, including your IoT hub.

You can run this tutorial on Linux or Windows. The shell commands in this tutorial follow the Linux convention for path separators '/', if you're following along on Windows be sure to swap these separators for '\'.

To complete this tutorial, install the following software in your local development environment:

Clone the SDK repository with the sample code

If you completed Tutorial: Connect a sample IoT Plug and Play device application running on Windows to IoT Hub (Java), you've already cloned the repository.

Open a command prompt in the directory of your choice. Execute the following command to clone the Microsoft Azure IoT SDKs for Java GitHub repository into this location:

git clone https://github.com/Azure/azure-iot-sdk-java.git

Build and run the sample device

Navigate to the root folder of the thermostat sample in the cloned Java SDK repository and build it:

cd azure-iot-sdk-java/device/iot-device-samples/pnp-device-sample/thermostat-device-sample
mvn clean package

In Set up your environment, you created four environment variables to configure the sample to use the Device Provisioning Service (DPS) to connect to your IoT hub:

  • IOTHUB_DEVICE_SECURITY_TYPE with the value DPS
  • IOTHUB_DEVICE_DPS_ID_SCOPE with the DPS ID scope.
  • IOTHUB_DEVICE_DPS_DEVICE_ID with the value my-pnp-device.
  • IOTHUB_DEVICE_DPS_DEVICE_KEY with the enrollment primary key.
  • IOTHUB_DEVICE_DPS_ENDPOINT with the value global.azure-devices-provisioning.net.

To learn more about the sample configuration, see the sample readme.

From the /device/iot-device-samples/pnp-device-sample/thermostat-device-sample folder, run the application:

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

The device is now ready to receive commands and property updates, and has started sending telemetry data to the hub. Keep the sample running as you complete the next steps.

Run the sample solution

In Set up your environment for the IoT Plug and Play quickstarts and tutorials you created two environment variables to configure the sample to connect to your IoT hub:

  • IOTHUB_CONNECTION_STRING: the IoT hub connection string you made a note of previously.
  • IOTHUB_DEVICE_ID: "my-pnp-device".

In this tutorial, you use a sample IoT solution written in Java to interact with the sample device you just set up.

Note

This sample uses the com.microsoft.azure.sdk.iot.service namespace from the IoT Hub service client. To learn more about the APIs, including the digital twins API, see the service developer guide.

  1. Open another terminal window to use as your service terminal.

  2. In the cloned Java SDK repository, navigate to the service/iot-service-samples/pnp-service-sample/thermostat-service-sample folder.

  3. To build and run the sample service application, run the following commands:

    mvn clean package
    mvn exec:java -Dexec.mainClass="samples.com.microsoft.azure.sdk.iot.service.Thermostat"
    

Get device twin

The following code snippet shows how to retrieve the device twin in the service:

 // Get the twin and retrieve model Id set by Device client.
DeviceTwinDevice twin = new DeviceTwinDevice(deviceId);
twinClient.getTwin(twin);
System.out.println("Model Id of this Twin is: " + twin.getModelId());

Update a device twin

The following code snippet shows you how to use a patch to update properties through the device twin:

String propertyName = "targetTemperature";
double propertyValue = 60.2;
twin.setDesiredProperties(Collections.singleton(new Pair(propertyName, propertyValue)));
twinClient.updateTwin(twin);

The device output shows how the device responds to this property update.

Invoke a command

The following code snippet shows you call a command on the device:

// The method to invoke for a device without components should be "methodName" as defined in the DTDL.
String methodToInvoke = "getMaxMinReport";
System.out.println("Invoking method: " + methodToInvoke);

Long responseTimeout = TimeUnit.SECONDS.toSeconds(200);
Long connectTimeout = TimeUnit.SECONDS.toSeconds(5);

// Invoke the command.
String commandInput = ZonedDateTime.now(ZoneOffset.UTC).minusMinutes(5).format(DateTimeFormatter.ISO_DATE_TIME);
MethodResult result = methodClient.invoke(deviceId, methodToInvoke, responseTimeout, connectTimeout, commandInput);
if(result == null)
{
    throw new IOException("Method result is null");
}

System.out.println("Method result status is: " + result.getStatus());

The device output shows how the device responds to this command.

IoT Plug and Play simplifies IoT by enabling you to interact with a device's capabilities without knowledge of the underlying device implementation. This tutorial shows you how to use Node.js to connect to and control an IoT Plug and Play device that's connected to your solution.

Prerequisites

Before you continue, make sure you've set up your environment, including your IoT hub.

To complete this tutorial, you need Node.js on your development machine. You can download the latest recommended version for multiple platforms from nodejs.org.

You can verify the current version of Node.js on your development machine using the following command:

node --version

Clone the SDK repository with the sample code

Clone the samples from a the Node SDK repository. Open a terminal window in a folder of your choice. Run the following command to clone the Microsoft Azure IoT SDK for Node.js GitHub repository:

git clone https://github.com/Azure/azure-iot-sdk-node

Run the sample device

In Set up your environment, you created four environment variables to configure the sample to use the Device Provisioning Service (DPS) to connect to your IoT hub:

  • IOTHUB_DEVICE_SECURITY_TYPE with the value DPS
  • IOTHUB_DEVICE_DPS_ID_SCOPE with the DPS ID scope.
  • IOTHUB_DEVICE_DPS_DEVICE_ID with the value my-pnp-device.
  • IOTHUB_DEVICE_DPS_DEVICE_KEY with the enrollment primary key.
  • IOTHUB_DEVICE_DPS_ENDPOINT with the value global.azure-devices-provisioning.net.

To learn more about the sample configuration, see the sample readme.

In this tutorial, you use a sample thermostat device that's written in Node.js as the IoT Plug and Play device. To run the sample device:

  1. Open a terminal window and navigate to the local folder that contains the Microsoft Azure IoT SDK for Node.js repository you cloned from GitHub.

  2. This terminal window is used as your device terminal. Go to the folder of your cloned repository, and navigate to the /azure-iot-sdk-node/device/samples/javascript folder. Install all the dependencies by running the following command:

    npm install
    
  3. Run the sample thermostat device with the following command:

    node pnp_simple_thermostat.js
    
  4. You see messages saying that the device has sent some information and reported itself online. These messages indicate that the device has begun sending telemetry data to the hub, and is now ready to receive commands and property updates. Don't close this terminal, you need it to confirm the service sample is working.

Run the sample solution

In Set up your environment for the IoT Plug and Play quickstarts and tutorials you created two environment variables to configure the sample to connect to your IoT hub:

  • IOTHUB_CONNECTION_STRING: the IoT hub connection string you made a note of previously.
  • IOTHUB_DEVICE_ID: "my-pnp-device".

In this tutorial, you use a sample Node.js IoT solution to interact with the sample device you just set up and ran.

  1. Open another terminal window to use as your service terminal.

  2. In the cloned Node SDK repository, navigate to the azure-iot-sdk-node/service/samples/javascript folder. Install all the dependencies by running the following command:

    npm install
    

Read a property

  1. When you ran the sample thermostat device in the device terminal, you saw the following messages indicating its online status:

    properties have been reported for component
    sending telemetry message 0...
    
  2. Go to the service terminal and use the following command to run the sample for reading device information:

    node twin.js
    
  3. In the service terminal output, notice the response of the device twin. You see the device's model ID and associated properties reported:

    Model Id: dtmi:com:example:Thermostat;1
    {
      "deviceId": "my-pnp-device",
      "etag": "AAAAAAAAAAE=",
      "deviceEtag": "Njc3MDMxNDcy",
      "status": "enabled",
      "statusUpdateTime": "0001-01-01T00:00:00Z",
      "connectionState": "Connected",
      "lastActivityTime": "0001-01-01T00:00:00Z",
      "cloudToDeviceMessageCount": 0,
      "authenticationType": "sas",
      "x509Thumbprint": {
        "primaryThumbprint": null,
        "secondaryThumbprint": null
      },
      "modelId": "dtmi:com:example:Thermostat;1",
      "version": 4,
      "properties": {
        "desired": {
          "$metadata": {
            "$lastUpdated": "2020-10-05T11:35:19.4574755Z"
          },
          "$version": 1
        },
        "reported": {
          "maxTempSinceLastReboot": 31.343640523762232,
          "serialNumber": "123abc",
          "$metadata": {
            "$lastUpdated": "2020-10-05T11:35:23.7339042Z",
            "maxTempSinceLastReboot": {
              "$lastUpdated": "2020-10-05T11:35:23.7339042Z"
            },
            "serialNumber": {
              "$lastUpdated": "2020-10-05T11:35:23.7339042Z"
            }
          },
          "$version": 3
        }
      },
      "capabilities": {
        "iotEdge": false
      },
      "tags": {}
    }
    
  4. The following snippet shows the code in twin.js that retrieves the device twin's model ID:

    var registry = Registry.fromConnectionString(connectionString);
    registry.getTwin(deviceId, function(err, twin) {
      if (err) {
        console.error(err.message);
      } else {
        console.log('Model Id: ' + twin.modelId);
        //...
      }
      //...
    }
    

In this scenario, it outputs Model Id: dtmi:com:example:Thermostat;1.

Note

These service samples use the Registry class from the IoT Hub service client. To learn more about the APIs, including the digital twins API, see the service developer guide.

Update a writable property

  1. Open the file twin.js in a code editor.

  2. Review the sample code, it shows you two ways to update the device twin. To use the first way, modify the twinPatch variable as follows:

    var twinPatch = {
      tags: {
        city: "Redmond"
      },
      properties: {
        desired: {
          targetTemperature: 42
        }
      }
    };
    

    The targetTemperature property is defined as a writable property in the Thermostat device model.

  3. In the service terminal, use the following command to run the sample for updating the property:

    node twin.js
    
  4. In your device terminal, you see the device has received the update:

    The following properties will be updated for the default component:
    {
      targetTemperature: {
        value: 42,
        ac: 200,
        ad: 'Successfully executed patch for targetTemperature',
        av: 2
      }
    }
    updated the property
    
  5. In your service terminal, run the following command to confirm the property is updated:

    node twin.js
    
  6. In the service terminal output, in the reported properties section, you see the updated target temperature reported. It might take a while for the device to finish the update. Repeat this step until the device has processed the property update:

    "reported": {
      //...
      "targetTemperature": {
        "value": 42,
        "ac": 200,
        "ad": "Successfully executed patch for targetTemperature",
        "av": 4
      },
      //...
    }
    

Invoke a command

  1. Open the file device_method.js and review the code.

  2. Go to the service terminal. Use the following command to run the sample for invoking the command:

    set IOTHUB_METHOD_NAME=getMaxMinReport
    set IOTHUB_METHOD_PAYLOAD=commandpayload
    node device_method.js
    
  3. Output in the service terminal shows the following confirmation:

    getMaxMinReport on my-pnp-device:
    {
      "status": 200,
      "payload": {
        "maxTemp": 23.460596940801928,
        "minTemp": 23.460596940801928,
        "avgTemp": 23.460596940801928,
        "endTime": "2020-10-05T12:48:08.562Z",
        "startTime": "2020-10-05T12:47:54.450Z"
      }
    }
    
  4. In the device terminal, you see the command is acknowledged:

    MaxMinReport commandpayload
    Response to method 'getMaxMinReport' sent successfully.
    

IoT Plug and Play simplifies IoT by enabling you to interact with a device's model without knowledge of the underlying device implementation. This tutorial shows you how to use Python to connect to and control an IoT Plug and Play device that's connected to your solution.

Prerequisites

Before you continue, make sure you've set up your environment, including your IoT hub.

To complete this tutorial, you need Python installed on your development machine. Check the Azure IoT Python SDK for current Python version requirements. You can check your Python version with the following command:

python --version

You can download the latest recommended version for multiple platforms from python.org.

In your local Python environment, install the azure-iot-device package as follows:

pip install azure-iot-device

Install the azure-iot-hub package by running the following command:

pip install azure-iot-hub

Run the sample device

In Set up your environment, you created four environment variables to configure the sample to use the Device Provisioning Service (DPS) to connect to your IoT hub:

  • IOTHUB_DEVICE_SECURITY_TYPE with the value DPS
  • IOTHUB_DEVICE_DPS_ID_SCOPE with the DPS ID scope.
  • IOTHUB_DEVICE_DPS_DEVICE_ID with the value my-pnp-device.
  • IOTHUB_DEVICE_DPS_DEVICE_KEY with the enrollment primary key.
  • IOTHUB_DEVICE_DPS_ENDPOINT with the value global.azure-devices-provisioning.net.

To learn more about the sample configuration, see the sample readme.

In this tutorial, you use a sample thermostat device, written in Python, as the IoT Plug and Play device. To run the sample device:

  1. Open a terminal window in a folder of your choice. Run the following command to clone the Azure IoT Device Python SDK GitHub repository into this location:

    git clone --branch v2 https://github.com/Azure/azure-iot-sdk-python
    
  2. This terminal window is used as your device terminal. Go to the folder of your cloned repository, and navigate to the azure-iot-sdk-python/samples/pnp folder.

  3. Run the sample thermostat device with the following command:

    python simple_thermostat.py
    
  4. You see messages saying that the device has sent some information and reported itself online. These messages indicate that the device has begun sending telemetry data to the hub, and is now ready to receive commands and property updates. Don't close this terminal, you need it to confirm the service sample is working.

Run the sample solution

In this tutorial, you use a sample IoT solution in Python to interact with the sample device you just set up.

  1. Open another terminal window to use as your service terminal. Run the following command to clone the Azure IoT Hub Python SDK GitHub repository into this location:

    git clone https://github.com/Azure/azure-iot-hub-python
    
  2. Install the

  3. Navigate to the /azure-iot-hub-python/samples folder of the cloned Python SDK repository.

  4. Open the registry_manager_pnp_sample.py file and review the code. This sample shows how to use the IoTHubRegistryManager class to interact with your IoT Plug and Play device.

Note

These service samples use the IoTHubRegistryManager class from the IoT Hub service client. To learn more about the APIs, including the digital twins API, see the service developer guide.

Get the device twin

In Set up your environment for the IoT Plug and Play quickstarts and tutorials you created two environment variables to configure the sample to connect to your IoT hub:

  • IOTHUB_CONNECTION_STRING: the IoT hub connection string you made a note of previously.
  • IOTHUB_DEVICE_ID: "my-pnp-device".

Use the following command in the service terminal to run this sample:

set IOTHUB_METHOD_NAME="getMaxMinReport"
set IOTHUB_METHOD_PAYLOAD="hello world"
python registry_manager_pnp_sample.py

Note

If you're running this sample on Linux, use export in place of set.

The output shows the device twin and prints its model ID:

The Model ID for this device is:
dtmi:com:example:Thermostat;1

The following snippet shows the sample code from registry_manager_pnp_sample.py:

    # Create IoTHubRegistryManager
    iothub_registry_manager = IoTHubRegistryManager(iothub_connection_str)

    # Get device twin
    twin = iothub_registry_manager.get_twin(device_id)
    print("The device twin is: ")
    print("")
    print(twin)
    print("")

    # Print the device's model ID
    additional_props = twin.additional_properties
    if "modelId" in additional_props:
        print("The Model ID for this device is:")
        print(additional_props["modelId"])
        print("")

Update a device twin

This sample shows you how to update the targetTemperature writable property in the device:

    # Update twin
    twin_patch = Twin()
    twin_patch.properties = TwinProperties(
        desired={"targetTemperature": 42}
    )  # this is relevant for the thermostat device sample
    updated_twin = iothub_registry_manager.update_twin(device_id, twin_patch, twin.etag)
    print("The twin patch has been successfully applied")
    print("")

You can verify that the update is applied in the device terminal that shows the following output:

the data in the desired properties patch was: {'targetTemperature': 42, '$version': 2}

The service terminal confirms that the patch was successful:

The twin patch has been successfully applied

Invoke a command

The sample then invokes a command:

The service terminal shows a confirmation message from the device:

The device method has been successfully invoked

In the device terminal, you see the device receives the command:

Command request received with payload
hello world
Will return the max, min and average temperature from the specified time hello to the current time
Done generating
{"tempReport": {"avgTemp": 34.2, "endTime": "09/07/2020 09:58:11", "maxTemp": 49, "minTemp": 10, "startTime": "09/07/2020 09:56:51"}}

Clean up resources

If you've finished with the quickstarts and tutorials, see Clean up resources.

Next steps

In this tutorial, you learned how to connect an IoT Plug and Play device to a IoT solution. To learn more about IoT Plug and Play device models, see: