Scenario: Query a Digital Twin Relationship

A digital twin instance can use digital twin models, digital twin adapters, hierarchies, and relationships to create a virtual model that represent a real environment.

This scenario explains how you can query a digital twin relationship to answer questions about a device, capabilities, data, and connectivity, to monitor a physical space and its devices. In this scenario, a space is a physical area, for example a conference room. That's served by an Env-III sensor which is a device located in the space that measures environmental characteristics including temperature and humidity. This hierarchy and the servedBy relationship allows applications to query:
  • Which sensors serve a specific space?
  • What telemetry is reported by these sensors?
  • How the devices are connected, using wi-fi?

Tasks

Step 1: Create a Digital Twin Model with a Capability Base Model

  1. Save this code snippet as a model_capability.json file. Reference this file in the next step when you create a digital twin model. This model specification defines the capability and acts as a base model.

    For more information about referencing files, see Using a JSON File for Complex Input and create a digital twin model.

    {
      "@context": [
        "dtmi:dtdl:context;3"
      ],
      "@id": "dtmi:com:oracle:example:core:Capability:cap;1",
      "@type": "Interface",
      "displayName": "Capability",
      "description": "A Capability indicates capacity to produce and ingest data.",
      "contents": [
        {
          "@type": "Property",
          "name": "lastValueTime",
          "schema": "dateTime"
        }
      ]
    }
  2. Use the oci iot digital-twin-model create command and parameters to create a digital twin model with a capability base model.

    oci iot digital-twin-model create --iot-domain-id <iot-domain-OCID> --spec file://model_capability.json

    This example response shows the digital twin model is active and references the DTMI URI defined in the model_capability.json file:

    dtmi:com:oracle:example:core:Capability:cap;1

    {
      "data": {
        "defined-tags": {
          "Oracle-Tags": {
            "CreatedBy": "default/user@oracle.com",
            "CreatedOn": "2025-09-11T05:56:50.514Z"
          }
        },
        "description": "A aapability indicates capacity to produce and ingest data.",
        "display-name": "Capability",
        "freeform-tags": {},
        "id": "<iot-digital-twin-model-OCID>",
        "iot-domain-id": "<iot-domain-OCID>",
        "lifecycle-state": "ACTIVE",
        "spec-uri": "dtmi:com:oracle:example:core:Capability:cap;1",
        "system-tags": {},
        "time-created": "2025-09-11T05:56:50.587000+00:00",
        "time-updated": "2025-09-11T05:56:50.587000+00:00"
      },
      "etag": "<unique-id>"
    }
    

Step 2: Create a Digital Twin Model for a Sensor

  1. Save this code snippet as a model_sensor.json file. Reference this file in the next step to create another digital twin model. This is a sensor definition that inherits the properties from and extends the capability base model.
    {
      "@context": [
        "dtmi:dtdl:context;3"
      ],
      "@id": "dtmi:com:oracle:example:core:Sensor:sen;1",
      "@type": "Interface",
      "extends": "dtmi:com:oracle:example:core:Capability:cap;1",
      "displayName": "Sensor",
      "description": "Capability to detect or measure properties of the physical world.",
      "contents": [
        {
          "@type": "Relationship",
          "displayName": "observes",
          "name": "observes",
          "target": "dtmi:com:oracle:example:core:Space:ex;1"
        }
      ]
    }
    
  2. Use this command and parameters to define the specifications to create a digital twin model.
    oci iot digital-twin-model create --iot-domain-id <iot-domain-OCID> --spec file://model_sensor.json

    This example response shows the digital twin model is active and references the specific DTMI URI defined in the model_sensor.json file:

    dtmi:com:oracle:example:core:sensor:sen;1

    {
      "data": {
        "defined-tags": {
          "Oracle-Tags": {
            "CreatedBy": "default/user@oracle.com",
            "CreatedOn": "2025-09-11T06:03:25.687Z"
          }
        },
        "description": "Capability to detect or measure properties of the physical world.",
        "display-name": "Sensor",
        "freeform-tags": {},
        "id": "<iot-digital-twin-model-OCID>",
        "iot-domain-id": "<iot-domain-OCID>",
        "lifecycle-state": "ACTIVE",
        "spec-uri": "dtmi:com:oracle:example:core:Sensor:sen;1",
        "system-tags": {},
        "time-created": "2025-09-11T06:03:25.753000+00:00",
        "time-updated": "2025-09-11T06:03:25.753000+00:00"
      },
      "etag": "<unique-id>"
    }
    

Step 3: Create a Digital Twin Model for the Env-III Sensor

  1. Save this code snippet as a model_env.json file. Reference this file in the next step when you create another digital twin model.
    {
      "@context": [
        "dtmi:dtdl:context;3",
        "dtmi:dtdl:extension:quantitativeTypes;1",
        "dtmi:dtdl:extension:historization;1",
        "dtmi:com:oracle:dtdl:extension:validation;1"
      ],
      "@id": "dtmi:com:oracle:example:stack:enviii:ev;2",
      "@type": "Interface",
      "extends": [
        "dtmi:com:oracle:example:core:sensor:sen;1"
      ],
      "displayName": "M5 with EnvIII sensors",
      "description": "Model envIII",
      "contents": [
        {
          "@type": [
            "Telemetry",
            "Historized",
            "Temperature"
          ],
          "name": "room_temp",
          "schema": "double",
          "unit": "degreeCelsius"
        }
      ]
    }
  2. Use this command and parameters to define the specifications to create another digital twin model.
    oci iot digital-twin-model create --iot-domain-id <iot-domain-OCID> --spec file://model_env.json

    This example shows the digital twin model is active and references the specific DTMI URI defined in the model_env.json file:

    dtmi:com:oracle:example:stack:enviii:ev;2
    {
      "data": {
        "defined-tags": {
          "Oracle-Tags": {
            "CreatedBy": "default/user@oracle.com",
            "CreatedOn": "2025-09-11T06:07:30.882Z"
          }
        },
        "description": "Model envIII",
        "display-name": "M5 with EnvIII sensors",
        "freeform-tags": {},
        "id": "<iot-digital-twin-model-OCID>",
        "iot-domain-id": "<iot-domain-OCID>",
        "lifecycle-state": "ACTIVE",
        "spec-uri": "dtmi:com:oracle:example:stack:enviii:ev;2",
        "system-tags": {},
        "time-created": "2025-09-11T06:07:30.944000+00:00",
        "time-updated": "2025-09-11T06:07:30.944000+00:00"
      },
      "etag": "<unique-id>"
    }
    

Step 4: Create a Digital Twin Model for the Space

  1. Save this code snippet as a model_space.json file and reference this file in the next step when you create a digital twin model for the space. The space is servedBy the sensor model.
    {
      "@context": [
        "dtmi:dtdl:context;3"
      ],
      "@id": "dtmi:com:oracle:example:core:Space:sp;1",
      "@type": "Interface",
      "displayName": "Space",
      "description": "Model Space",
      "contents": [
        {
          "@type": "Relationship",
          "displayName": "served by",
          "name": "servedBy",
          "target": "dtmi:com:oracle:example:core:sensor:sen;1"
        }
      ]
    }
  2. Use the following command to create a digital twin model referencing the file://model_space.json to apply the specifications defined in the file to this digital twin model.
    oci iot digital-twin-model create --iot-domain-id <iot-domain-OCID> --spec file://model_space.json

    This example response shows the digital twin model is active and references this specific DTMI URI defined in the model_space.json file:

    dtmi:com:oracle:example:core:Space:sp;1
    {
      "data": {
        "defined-tags": {
          "Oracle-Tags": {
            "CreatedBy": "default/user@oracle.com",
            "CreatedOn": "2025-09-11T06:06:45.538Z"
          }
        },
        "description": "Model Space",
        "display-name": "Space",
        "freeform-tags": {},
        "id": "<iot-digital-twin-model-OCID>",
        "iot-domain-id": "<iot-domain-OCID>",
        "lifecycle-state": "ACTIVE",
        "spec-uri": "dtmi:com:oracle:example:core:Space:sp;1",
        "system-tags": {},
        "time-created": "2025-09-11T06:06:45.574000+00:00",
        "time-updated": "2025-09-11T06:06:45.574000+00:00"
      },
      "etag": "<unique-id>"
    }
    

Step 5: Create a Digital Twin Adapter for the Space

Use this command to create a digital twin adapter and to associate the digital twin model specification with the DTMI URI for the space.

When you create a digital twin adapter, you can force the system to create a default payload and mappings by not specifying the inbound-envelope or the inbound-routes options.

If the envelope mapping is not specified and contains a timeObserved then receivedTime is used as timeObserved value.

oci iot digital-twin-adapter create --iot-domain-id <iot-domain-OCID> --digital-twin-model-spec-uri "dtmi:com:oracle:example:core:space:sp;1"
This example response shows a specific digital twin adapter OCID and that it's associated with a specific digital twin model and DTMI URI.

dtmi:com:oracle:example:core:Space:sp;1

{
  "data": {
    "defined-tags": {
      "Oracle-Tags": {
        "CreatedBy": "default/user@oracle.com",
        "CreatedOn": "2025-09-11T06:09:27.323Z"
      }
    },
    "description": null,
    "digital-twin-model-id": "<iot-digital-twin-model-OCID>",
    "digital-twin-model-spec-uri": "dtmi:com:oracle:example:core:Space:sp;1",
    "display-name": "<digital-twin-adapter-display-name>",
    "freeform-tags": {},
    "id": "<iot-digital-twin-adapter-OCID>",
    "inbound-envelope": {
      "envelope-mapping": {
        "time-observed": "$.time"
      },
      "reference-endpoint": "/",
      "reference-payload": {
        "data": {
          "time": "2025-09-11T06:09:27.878106Z"
        },
        "data-format": "JSON"
      }
    },
    "inbound-routes": [
      {
        "condition": "*",
        "description": "default condition",
        "payload-mapping": {},
        "reference-payload": null
      }
    ],
    "iot-domain-id": "<iot-domain-OCID>",
    "lifecycle-state": "ACTIVE",
    "system-tags": {},
    "time-created": "2025-09-11T06:09:27.879000+00:00",
    "time-updated": "2025-09-11T06:09:27.879000+00:00"
  },
  "etag": "<unique-id>"
}

Step 6: Create a Digital Twin Adapter for the Env-III Sensor

Use this command to create a digital twin adapter and associate the digital twin model specification with the DTMI URI for the Env-III sensor.
oci iot digital-twin-adapter create --iot-domain-id <iot-domain-OCID> --digital-twin-model-spec-uri "dtmi:com:oracle:room:m5stack:enviii:ev;2"
This example response shows a specific digital twin adapter OCID and it's associated with a specific digital twin model and DTMI.

dtmi:com:oracle:example:stack:enviii:ev;2

{
  "data": {
    "defined-tags": {
      "Oracle-Tags": {
        "CreatedBy": "default/user@oracle.com",
        "CreatedOn": "2025-09-11T06:10:23.303Z"
      }
    },
    "description": null,
    "digital-twin-model-id": "<iot-digital-twin-model-OCID>",
    "digital-twin-model-spec-uri": "dtmi:com:oracle:example:stack:enviii:ev;2",
    "display-name": "<digital-twin-adapter-display-name>",
    "freeform-tags": {},
    "id": "<iot-digital-twin-adapter-OCID>",
    "inbound-envelope": {
      "envelope-mapping": {
        "time-observed": "$.time"
      },
      "reference-endpoint": "/",
      "reference-payload": {
        "data": {
          "sht_temp": 0.0,
          "time": "2025-09-11T06:10:26.127416Z"
        },
        "data-format": "JSON"
      }
    },
    "inbound-routes": [
      {
        "condition": "*",
        "description": "Default condition",
        "payload-mapping": {
          "$.sht_temp": "$.sht_temp"
        },
        "reference-payload": null
      }
    ],
    "iot-domain-id": "<iot-domain-OCID>",
    "lifecycle-state": "ACTIVE",
    "system-tags": {},
    "time-created": "2025-09-11T06:10:27.204000+00:00",
    "time-updated": "2025-09-11T06:10:27.204000+00:00"
  },
  "etag": "<unique-id>"
}

Step 7: Create a Digital Twin Instance with an Adapter for a Space

Use this command to create a digital twin instance with a display name that uses a secret to authenticate, and is associated with a specific digital twin model and digital twin adapter. For information on how to create a vault secret, see Creating a Secret.
oci iot digital-twin-instance create --auth-id <vault-secret-OCID> --iot-domain-id <iot-domain-OCID> --digital-twin-adapter-id <iot-digital-twin-adapter-OCID> --display-name <your-display-name>
This example response shows the specific digital twin instance OCID and it's associated digital twin adapter, digital twin model, the external key ID, and includes the specific DTMI URI defined for the space:

dtmi:com:oracle:example:core:Space:sp;1

{
  "data": {
    "auth-id": "<vault-secret-OCID>",
    "defined-tags": {
      "Oracle-Tags": {
        "CreatedBy": "default/user@oracle.com",
        "CreatedOn": "2025-09-11T06:12:43.393Z"
      }
    },
    "description": null,
    "digital-twin-adapter-id": "<iot-digital-twin-adapter-OCID>",
    "digital-twin-model-id": "<iot-digital-twin-model-OCID>",
    "digital-twin-model-spec-uri": "dtmi:com:oracle:example:core:Space:sp;1",
    "display-name": "device for conference room 103",
    "external-key": "<unique-id>",
    "freeform-tags": {},
    "id": "<iot-digital-twin-instance-OCID>",
    "iot-domain-id": "<iot-domain-OCID>",
    "lifecycle-state": "ACTIVE",
    "system-tags": {},
    "time-created": "2025-09-11T06:12:44.178000+00:00",
    "time-updated": "2025-09-11T06:12:44.178000+00:00"
  },
  "etag": "<unique-id>"
}

Step 8: Create a Digital Twin Instance with an Adapter for an Env-III Sensor

Use this command to create a digital twin instance with a display name that uses a secret to authenticate and is associated with a specific digital twin model, digital twin adapter, and IoT domain. Replace the OCID's with the related IoT resources for your environment.

oci iot digital-twin-instance create --auth-id <vault-secret-OCID> --iot-domain-id <iot-domain-OCID> --digital-twin-adapter-id <iot-digital-twin-adapter-OCID> --display-name "<your-display-name>"
This example response shows the digital twin instance is active and contains the related digital twin model and digital twin adapter.
{
  "data": {
    "auth-id": "<vault-secret-OCID>",
    "defined-tags": {
      "Oracle-Tags": {
        "CreatedBy": "default/user@oracle.com",
        "CreatedOn": "2025-09-11T06:14:33.493Z"
      }
    },
    "description": null,
    "digital-twin-adapter-id": "<iot-digital-twin-adapter-OCID>",
    "digital-twin-model-id": "<iot-digital-twin-model-OCID>",
    "digital-twin-model-spec-uri": "dtmi:com:oracle:example:stack:enviii:ev;2",
    "display-name": "Envii device 2",
    "external-key": "<unique-id>",
    "freeform-tags": {},
    "id": "<iot-digital-twin-instance-OCID>",
    "iot-domain-id": "<iot-domain-OCID>",
    "lifecycle-state": "ACTIVE",
    "system-tags": {},
    "time-created": "2025-09-11T06:14:34.821000+00:00",
    "time-updated": "2025-09-11T06:14:34.821000+00:00"
  },
  "etag": "<unique-id>"
}

Step 9: Create a Digital Twin Relationship to Connect two Digital Twin Instances

Use this command to create a digital twin relationship between two digital twin instances and to define the content path as servedBy, the connection type as wi-fi, and the display name for this digital twin relationship.
oci iot digital-twin-relationship create --iot-domain-id <iot-domain-OCID> --target-digital-twin-instance-id <iot-digital-twin-instance-OCID> --source-digital-twin-instance-id <iot-digital-twin-instance-OCID> --content-path "servedBy" --content '{"connectionType": "wi-fi"}' --display-name "Env and sensor relationship"
This example response shows the content path and the related digital twin instances for this digital twin relationship:
{
  "data": {
    "content": {
      "connectionType": "wi-fi"
    },
    "content-path": "servedBy",
    "defined-tags": {
      "Oracle-Tags": {
        "CreatedBy": "default/user@oracle.com",
        "CreatedOn": "2025-09-11T07:40:08.926Z"
      }
    },
    "description": null,
    "display-name": "Env and sensor relationship",
    "freeform-tags": {},
    "id": "<iot-digital-twin-relationship-OCID>",
    "iot-domain-id": "<iot-domain-OCID>",
    "lifecycle-state": "ACTIVE",
    "source-digital-twin-instance-id": "<iot-digital-twin-instance-OCID>",
    "system-tags": {},
    "target-digital-twin-instance-id": "<iot-digital-twin-instance-OCID>",
    "time-created": "2025-09-11T07:40:09.755000+00:00",
    "time-updated": "2025-09-11T07:40:09.755000+00:00"
  },
  "etag": "<unique-id>"
}

Step 10: Query the Digital Twin Relationship Graph using SQL

If you want to use SQL queries to view your IoT data in APEX or directly in the database that requires configuring a connection to APEX or configuring a direct database connection.

In APEX or directly in the database, use the following SQL statements to find the digital twin relationship details for a specific digital twin instance. Replace the <domain-short-id-from-device-host> with the domain short id from the device host. Replace the <digital-twin-instance-OCID> with the digital twin instance OCID you want to work with:

Note

Notice two underscores in __IOT.
<domain-short-id-from-device-host>__IOT.DIGITAL_TWINS
SELECT * FROM GRAPH_TABLE(
    <domain-short-id-from-device-host>__IOT.DIGITAL_TWINS
    MATCH (a IS digitalTwinInstance) -[e IS digitalTwinRelationship]-> (b IS digitalTwinInstance)
    WHERE a.id = '<digital-twin-instance-OCID>'
    COLUMNS (a.id as src, e.content_path as rel, b.id as tgt)
);

To find the relationships between two digital twin instances use the following query. Replace the FROM_DIGITAL-TWIN-INSTANCE-OCID with the source digital twin instance OCID and TO_DIGITAL-TWIN-INSTANCE-OCID with the target digital twin instance OCID you want to find the content path for:

SELECT * FROM GRAPH_TABLE(
    <domain-short-id-from-device-host>__IOT.DIGITAL_TWINS
    MATCH (a IS digitalTwinInstance) -[e IS digitalTwinRelationship]-> (b IS digitalTwinInstance)
    WHERE a.id = 'FROM_DIGITAL-TWIN-INSTANCE-OCID'AND b.id = 'TO_DIGITAL-TWIN-INSTANCE-OCID'
    COLUMNS (a.id as src, e.content_path as rel, b.id as tgt)
);