Upsert Twins

Upsert Twin combines both Create Twin and Update Twin, in order to streamline the process and reduce the number of API calls.

This page covers:


Introduction to Upsert Digital Twins

Upsert Twin unites Create Twin and Update Twin, therefore combining the following basic functions in a single call:

🚧

Upsert Twin can be used once a Digital Twin has been created with control delegation and its Twin DID has been retrieved. See further details on this prerequisite here.

The body parameters required to use the Upsert Twin API are the same as for Update Twin API in addition with the ones described in the table below.

Key

Description

Twin DID

The DID of the Twin that you want to update.

Mandatory

Feeds

The list of Feeds you want to add to the Twin including:

  • the Feed(s) metadata;
  • the Value(s) metadata.

Optional

Upsert a Twin with the IOTICS API

Click to see the prerequisites

  1. Create your user credentials (guide);
  2. Delegate the agent so it can work on behalf of the user (guide);
  3. Create your token to interact with your Host (guide);
  4. Create headers to be added alongside the API request (guide);
1. Create Twin with control delegation and get a new "twin_registered_id" (DID)
2. Use the Upsert Twin API call
from requests import request

response = request(
    method="PUT",
    url=f"{HOST}/qapi/twins",  # Replace with URL of the Host
    headers=headers,  # It includes the token
    json={
        "twinId": twin_id,  # The ID of the Twin to update
        "visibility": "PRIVATE",
        "location": {"lat": 51.5, "lon": -0.1},
        "properties": [
            {
                "key": "http://www.w3.org/2000/01/rdf-schema#label",
                "langLiteralValue": {"value": "Temperature Sensor", "lang": "en"},
            },
            {
                "key": "http://www.w3.org/2000/01/rdf-schema#comment",
                "langLiteralValue": {
                    "value": "A temperature sensor that shares temperature data",
                    "lang": "en",
                },
            },
        ],
        "feeds": [
            {
                "id": "currentTemp",
                "storeLast": True,
                "properties": [
                    {
                        "key": "http://www.w3.org/2000/01/rdf-schema#label",
                        "langLiteralValue": {"value": "currentTemp", "lang": "en"},
                    }
                ],
                "values": [
                    {
                        "comment": "Temperature in degrees Celsius",
                        "dataType": "decimal",
                        "label": "reading",
                        "unit": "http://purl.obolibrary.org/obo/UO_0000027",
                    }
                ],
            }
        ],
    },
)

response.raise_for_status()

Tutorial of the Upsert Twin section

🚧

Please note that the following snippets provides exactly the same result as the final Tutorial of the Update Twin section.

Click to see the entire code on how to upsert a Twin

from typing import List

from iotics.lib.identity.api.high_level_api import get_rest_high_level_identity_api
from requests import request

RESOLVER_URL = "resolver_url"
HOST = "host_url"

USER_KEY_NAME = "user_key_name"
AGENT_KEY_NAME = "agent_key_name"
USER_SEED = bytes.fromhex("user_seed")
AGENT_SEED = bytes.fromhex("agent_seed")


def make_api_call(method: str, url: str, json: dict):
    response = request(method=method, url=url, headers=headers, json=json)
    response.raise_for_status()

    return response.json()


def create_twin(twin_key_name: str):
    twin_registered_id = api.create_twin_with_control_delegation(
        twin_seed=AGENT_SEED,
        twin_key_name=twin_key_name,
        agent_registered_identity=agent_registered_id,
        delegation_name="#ControlDeleg",
    )

    return twin_registered_id.did


def upsert_twin(
    twin_id: str,
    visibility: str = "PRIVATE",
    feeds: List[dict] = None,
    location: dict = None,
    properties: List[dict] = None,
):
    payload = {"twinId": twin_id, "visibility": visibility}

    if location:
        payload["location"] = location
    if feeds:
        payload["feeds"] = feeds
    if properties:
        payload["properties"] = properties

    make_api_call(method="PUT", url=f"{HOST}/qapi/twins", json=payload)


# Set Up API, token and headers
api = get_rest_high_level_identity_api(resolver_url=RESOLVER_URL)
(
    user_registered_id,
    agent_registered_id,
) = api.create_user_and_agent_with_auth_delegation(
    user_seed=USER_SEED,
    user_key_name=USER_KEY_NAME,
    agent_seed=AGENT_SEED,
    agent_key_name=AGENT_KEY_NAME,
    delegation_name="#AuthDeleg",
)

token = api.create_agent_auth_token(
    agent_registered_identity=agent_registered_id,
    user_did=user_registered_id.did,
    duration=600,
)

headers = {
    "accept": "application/json",
    "Iotics-ClientAppId": "example",
    "Authorization": f"Bearer {token}",
    "Content-Type": "application/json",
}

twin_did = create_twin(twin_key_name="SensorTwin")

print(f"Twin {twin_did} created succesfully")

# Add Metadata, Feed and Value
upsert_twin(
    twin_id=twin_did,
    properties=[
        {
            "key": "http://www.w3.org/2000/01/rdf-schema#label",
            "langLiteralValue": {"value": "Temperature Sensor", "lang": "en"},
        },
        {
            "key": "http://www.w3.org/2000/01/rdf-schema#comment",
            "langLiteralValue": {
                "value": "A temperature sensor that shares temperature data",
                "lang": "en",
            },
        },
    ],
    feeds=[
        {
            "id": "currentTemp",
            "storeLast": True,
            "properties": [
                {
                    "key": "http://www.w3.org/2000/01/rdf-schema#label",
                    "langLiteralValue": {"value": "currentTemp", "lang": "en"},
                }
            ],
            "values": [
                {
                    "comment": "Temperature in degrees Celsius",
                    "dataType": "decimal",
                    "label": "reading",
                    "unit": "http://purl.obolibrary.org/obo/UO_0000027",
                }
            ],
        }
    ],
    location={"lat": 51.5, "lon": -0.1},
)

print("Metadata, Feed and Value added to the Twin")

Did this page help you?