Skip to main content

Tutorial: Configure Single Device

This tutorial will show you how to:

  • Propagate your custom configuration to a Device
  • Report the current configuration and status of the Device to the Platform


Imagine a robotic arm with two properties that you want to access from the Platform:

  • Speed: You need to read it and adjust it remotely.
  • Last maintenance date: Changing it requires a technician to visit the Device. You need to read it remotely to plan the next visit.

You'll use two JSON documents that the Platform stores for each Device:

  • Desired Properties: You can update them, while the Device can only read them. The Platform propagates all the updates to the Device.
  • Reported Properties: The Device can update them, while you can only read them.

The Device SDK also stores copies of these documents on the Device to handle Internet connection outages. The schema shows how you'll use the Desired and Reported Properties to configure the Device:

Scenario schema

  1. You'll update the Desired Properties in the Platform.
  2. The Device SDK will read the updated Desired Properties and publish them to your program running on the Device.
  3. Your program will process the changes and update the Reported Properties using the Device SDK. The new version of the Reported Properties will contain the updated current speed and the last maintenance date.
  4. You'll verify that the Device has updated its configuration and state by checking the Reported Properties in the Platform.


1. Start Device

The program running on the Device will connect to the Platform and periodically synchronize its configuration and status.

If you haven't installed the Device SDK yet, run the following command:

pip install --upgrade spotflow-device

Paste the following code into a new file, or download it. Replace the placeholder <Your Provisioning Token> with your Provisioning Token and run the program.


If you don't have a Provisioning Token, see Create Provisioning Token for instructions on creating it.
import time
from spotflow_device import DesiredProperties, DeviceClient


properties = {
"settings": {
"status": {
"lastMaintenance": "2024-02-04"

# Immediately print all changes of Desired Properties
def desired_properties_updated_callback(desired_properties: DesiredProperties):
print(f"[Callback] Received Desired Properties (version {desired_properties.version}): {desired_properties.values}")

# Connect to the Platform
client = DeviceClient.start(device_id="robo-arm", provisioning_token="<Your Provisioning Token>",
db="spotf_robo-arm.db", desired_properties_updated_callback=desired_properties_updated_callback)

# Synchronize the configuration and status

desired_properties_version = None

print("Setting Reported Properties to initial state")

while True:
desired_properties = client.get_desired_properties_if_newer(desired_properties_version)
if desired_properties is not None:
print(f"Received Desired Properties of version {desired_properties.version}")

if 'settings' in desired_properties.values and 'speed' in desired_properties.values['settings']:
print("Updating the speed to {}".format(desired_properties.values['settings']['speed']))
properties['settings']['speed'] = desired_properties.values['settings']['speed']

desired_properties_version = desired_properties.version

print("Updating Reported Properties")

print("Current speed: {}".format(properties['settings']['speed']))


The program connects to the Platform using DeviceClient.start. Then, it uses the following methods of the DeviceClient class:

  • get_desired_properties_if_newer enables the program to poll for changes of the Desired Properties. Whenever you update the Desired Properties in the Platform, the Platform assigns a new version number to them. If the argument to the function is None, the function always returns the current version of the Desired Properties. If the argument is a version number, the function returns the current version only if it's newer than the specified one. As a result, the program processes the Desired Properties in the first iteration of the loop and then whenever they change.
  • update_reported_properties updates the Reported Properties of the Device in the Platform. If the Device is currently disconnected, the Device SDK will store the update and send it when the connection is restored.

If you don't want to use the polling, you can process the Desired Properties entirely using the callback provided to DeviceClientOptions.desired_properties_updated_callback. The Device SDK calls this callback right after DeviceClient.start and then whenever the Desired Properties change.

Because the callback is called from a separate thread, you'll most likely need to use synchronization primitives when accessing data shared with the main thread. See the code example:

When you run the program for the first time, it will show the details of the Provisioning Operation:

Provisioning operation initialized, waiting for approval.
Operation ID: fceb289b-33a2-42b0-92ed-785a377748f7
Verification Code: 9yreu8sy

After you approve the Device to the Platform (see Approve Device), the program will start writing the current speed every 5 seconds:

[Callback] Received Desired Properties (version 1): {}
Setting Reported Properties to initial state
Received Desired Properties of version 1
Updating Reported Properties
Current speed: 10
Current speed: 10

A newly registered Device has empty Desired Properties. Therefore, the program shouldn't depend on any of the Desired Properties being present.

Keep the program running and proceed to the next step.

2. Set Desired Properties

You'll now change the speed of the robotic arm using the Platform. Choose one of the following ways:

Login to the Spotflow IoT Platform Portal and follow the instructions:

  1. Open the link Devices in the left sidebar.

  2. Click the Device ID robo-arm to open its details. If the Device is not on the list, make sure that you have approved it earlier (see Approve Device).

  3. Scroll the page down to see Desired Properties and click Edit.

  4. Update Content to {"settings": {"speed": 20}} and click Update.

  5. A box with the title Updated confirms that you've successfully updated the Desired Properties.

After a few seconds, the program running on the Device will update its speed from the Desired Properties. The program will also update the Reported Properties to confirm the change:

Current speed: 10
[Callback] Received Desired Properties (version 2): {'settings': {'speed': 20}}
Received Desired Properties of version 2
Updating the speed to 20
Updating Reported Properties
Current speed: 20
Current speed: 20

You won't need to use the program anymore, so you can close it using Ctrl+C.

3. Inspect Reported Properties

You can now verify that the Device has updated its configuration from the Platform:

You should have the Device Details page open because of your previous interaction with the Portal. If not, navigate to the page by following the instructions in the previous step. Then:

  1. Click the Refetch icon of the Reported Properties.

  2. You should now see the updated Reported Properties.


Congratulations on finishing the tutorial! It has shown you how to configure a Device and obtain its status. Because the Platform and the Device SDK handle the synchronization of Desired and Reported Properties in the background, you don't have to deal with it in your application.

In the scenario, the section settings in the Reported Properties has the same structure as in the Desired Properties. However, you might want to use a different approach in your application. For example:

  • The Device can't update its speed based on your request because the value is out of allowed bounds. In this case, the Device can report this problem in the respective part of the Reported Properties.
  • If you don't need to check that the Device has updated its configuration, you don't need to use the Reported Properties at all.

Desired and Reported Properties are designed for working with the current state of the Device. To store the history of the Device's operations, we instead recommend to send relevant logs, metrics, and traces to the Platform and route them to an OpenTelemetry observability backend.

What's Next