Getting started

This document covers getting a basic setup started in combination with Drogue Cloud. You will learn how to:

  • Create a device in Drogue Cloud and have its reported state synchronized to Drogue Doppelgänger.

  • Configuring a desired state of the device in Drogue Doppelgänger and have it reconcile this with the device.

Prerequisites

The Drogue Dopplegänger is assumed to run locally, but you can also use a remote instance as long as you replace the hostnames and ports accordingly.

Configuration

Configuring the system involves several commands that interact with Drogue Cloud and Drogue Doppelgänger. In this section we will:

  • Create an application and a device in Drogue Cloud

  • Create a thing in Drogue Doppelgänger for that device

Configuring Drogue Cloud

Follow the Drogue Cloud User Guide for creating an application and a device in Drogue Cloud.

The rest of this guide will assume you have an application named example-app and a device named device1. Replace any occurrences of these with the names you have selected.

Configuring Drogue Doppelgänger

Procedure
  1. Get a fresh OAuth token:

    TOKEN=$(http --form POST localhost:8081/realms/doppelgaenger/protocol/openid-connect/token grant_type=client_credentials client_id=services client_secret=bfa33cd2-18bd-11ed-a9f9-d45d6455d2cc | jq -r .access_token)
    HTTP_OPTS="-A bearer -a $TOKEN"
    bfa33cd2-18bd-11ed-a9f9-d45d6455d2cc is a hardcoded default client secret in server/src/keycloak.rs. It will only work if run with Keycloak and the server binary.
  2. Create a thing:

    http $HTTP_OPTS POST localhost:8080/api/v1alpha1/things metadata:='{"name": "device1/sensor", "application": "example-app", "annotations": {"drogue.io/device", "device1"}}'

Subscribe to the digital twin state

To subscribe to the digital twin state, we will use the websocat utility demonstrating the WebSocket capabilities.

Procedure
  1. Open a terminal and observe the device state:

    websocat -H="Authorization: Bearer $TOKEN" ws://localhost:8080/api/v1alpha1/things/example-app/things/device1%2Fsensor/notifications

    The state will not change until you are sending data from your device.

    If you get authorization denied, make sure to refresh your token again (see the first step).

Simulating a device

  1. Open another terminal and simulate telemetry data from your device;

    echo '{"temperature": 42}' | http --auth 'device1@example-app:hey-rodney' POST http://localhost:8088/v1/sensor?ct=30
    The command will wait for 30 seconds before returning, in case the twin has a command for it

    The event from the "device" should now be appearing in the other terminal.

Setting the desired state

Setting the desired state is a way for the digital twin to send commands to a device until the device actual state matches the desired state. This is useful in control applications, where you need to continuously monitor the device and adjust.

Procedure
  1. Create a command reconciled desired state:

    echo '{"method": {"command": {"period":"5s"}}}'| http $HTTP_OPTS PUT localhost:8080/api/v1alpha1/things/example-app/things/device1%2Fsensor/desiredStates/temperature
  2. Set the desired value (ensure it is currently not already 23):

    http $HTTP_OPTS PUT localhost:8080/api/v1alpha1/things/example-app/things/device1%2Fsensor/desiredStates/temperature?value:=23

    Now check the state with a GET. You should see that the reconciliation state is reconciling and it is waiting for the report of the state to match the desired value:

    {
        "desiredState": {
            "temperature": {
                "lastUpdate": "2022-07-29T08:14:45.072140510Z",
                "method": "external",
                "reconciliation": {
                    "state": "reconciling"
                },
                "value": 23
            }
        }
    }

    If you have a device running or is running the simulated device, it will receive the command with the desired state payload.

  3. Simulate the device reporting back the desired temperature value:

    echo '{"temperature": 23}' | http --auth 'device1@example-app:hey-rodney' POST http://localhost:8088/v1/sensor?ct=30
  4. Perform the GET operation again (try it multiple times in case the device has not been processed yet):

    {
        "desiredState": {
            "temperature": {
                "lastUpdate": "2022-07-29T08:14:45.072140510Z",
                "method": "external",
                "reconciliation": {
                    "state": "succeeded",
                    "when": "2022-07-29T08:14:59.579334005Z"
                },
                "value": 23
            }
        }
    }

    By default, the mode is Sync, which means that the system expects the state to stay with the desired state. If the device deviates from this state, the command will again be sent to the device.

    It will try to reconcile only for as long as the desired value is valid. Once it expired, it no longer tries.