Scenario: Sending Structured Data in a Custom Format using HTTPs
Use this scenario to send and monitor structured data from a device in a custom format. If a device sends data in a custom format, that means the device cannot be programmed to change its output.
In this case, define the custom digital twin adapter mapping, to translate the incoming data into a format recognized by the IoT Platform.
An administrator must add a policy to your tenancy and the compartments you want to use. For policy examples and prerequisites, see Policy Details for the Internet of Things (IoT) Platform and IoT Prerequisites.
Step 1: Create an IoT Domain Group and an IoT Domain
Use an existing IoT domain group and IoT domain or create an IoT domain group and create an IoT domain to use for this scenario.
After you have the IoT domain group and IoT domain you want to work, follow these steps to set up digital twin resources to receive structured data in a custom format from a device. All IoT resources must be in the same region.
To get the <domain-short-id-from-device-host>
for the IoT domain or to get the IoT domain OCID, you can get the details for the IoT domain you want to work with.
Step 2: Create a Digital Twin Model
- Create specifications using the Digital Twins Definition Language (DTDL) for your digital twin model similar to this example with the data you want to collect.
To use this example, save this code snippet as a
digital-twin-model.json
file and then reference this file in the next step when you create a digital twin model.A digital twin model requires a Digital Twin Model Identifier (DTMI) as a unique identifier. For example:
dtmi:com:oracle:example:hvac;1
{ "@context": [ "dtmi:dtdl:context;3" ], "@id": "dtmi:com:oracle:example:hvac;1", "@type": "Interface", "displayName": "HVAC", "description": "A digital twin model for HVAC", "contents": [ { "@type": "Telemetry", "name": "temperature", "schema": "integer" }, { "@type": "Telemetry", "name": "humidity", "schema": "integer" }, { "@type": "Property", "name": "power", "schema": "boolean" }, { "@type": "Property", "name": "batteryLevel", "schema": "integer" } ] }
- Use the
oci iot digital-twin-model create
command with the required parameter to create a digital twin model. Replace the<iot-domain-OCID>
with the OCID for the IoT domain you want to associate to this digital twin model. Reference thedigital-twin-model.json
file created in the previous step or a specifications file for your specific scenario. For more information about referencing files, see Using a JSON File for Complex Input:
Example response using theoci iot digital-twin-model create --iot-domain-id <iot-domain-OCID> --spec file://digital-twin-model.json
digital-twin-model.json
file from the previous step. This example response shows the DTMI URI and the IoT digital twin model OCID:{ "data": { "defined-tags": { "Oracle-Tags": { "CreatedBy": "default/user@oracle.com", "CreatedOn": "2025-09-11T05:56:50.514Z" } }, "description": "A digital twin model for HVAC", "display-name": "HVAC", "freeform-tags": {}, "id": "<iot-digital-twin-model-OCID>", "iot-domain-id": "<iot-domain-OCID>", "lifecycle-state": "ACTIVE", "spec-uri": "dtmi:com:oracle:example:hvac;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 3: Create a Digital Twin Adapter for a Custom Format
If a device sends data in a custom format, that means the device cannot be programmed to change its output. In this case, define the custom format in the digital twin adapter mapping,
To do that, define the inbound-envelope
and inbound-routes
in a JSON
format to convert the data to a format you want to work with in Oracle services and applications so you can connect to view your IoT data in different systems.
Using the CLI
- Define an inbound envelope
file://inbound-envelope.json
to specify how to extract metadata from the device's payload. To extract the value at$.time
from the incoming JSON and map it totimeObserved
field in the digital twin model. These mappings allow you to extract specific metadata such as timestamps using JQ expressions.This example shows the device endpoint, a sample payload, and an inbound envelope mapping that applies JQ expressions to extract or reshape the data.
{ "reference-endpoint": "telemetry/health", "reference-payload": { "dataFormat": "JSON", "data": { "time": "<timestamp>", "data": { "temp": 0, "hum": 0, "power": false, "batteryLevel": 0 } } }, "envelope-mapping": { "timeObserved": "$.time" } }
- Create a
file://inbound-routes.json
file to define how specific payload data from device messages is mapped and routed to your digital twin instance.Each route includes a condition matching the endpoint, a reference payload structure, and mapping instructions for transferring or transforming values.
This example shows 2 payload conditions defined.Note
The maximum inbound routes allowed is 128.[ { "condition": "${endpoint(2) == \"heartbeat\"}", "reference-payload": { "data": { "temp": 75, "hum": 62 } }, "payload-mapping": { "$.temperature": "$.data.temp", "$.humidity": "${.data.hum - 5}" } }, { "condition": "${endpoint(2) == \"health\"}", "reference-payload": { "data": { "power": false, "batteryLevel": 60 } }, "payload-mapping": { "$.power": "$.data.power", "$.batteryLevel": "${.data.batteryLevel - 5}" } } ]
- Use the
oci iot digital-twin-adapter create
command to create a digital twin adapter. Replace the<iot-domain-OCID>
with the OCID for your IoT domain, and replace the<dtmi:com:oracle:example:hvac>
with the DTMI URI with the DTMI URI for the digital twin model you want to associate to this digital twin adapter.The following example uses the DTMI URI parameter to associate the digital twin model. Alternatively, you can use the
Reference the files--digital-twin-model-id
parameter with the<digital-twin-model-OCID>
for the digital twin model you want to associate to this digital twin adapter.file://inbound-enevelop.json
andfile://inbound-enevelop.json
created in the previous step.
This example response shows a custom payload mapping defined in theoci iot digital-twin-adapter create --iot-domain-id <iot-domain-OCID> --digital-twin-model-spec-uri 'dtmi:com:oracle:example:hvac;1' --inbound-envelope <file://inbound-enevelop.json> --inbound-routes <file://inbound-routes.json>
--inbound-envelope
and the--inbound-routes
options, by referencingjson
files, and a specific digital twin adapter OCID that's associated with a specific digital twin model with a unique DTMI URI and digital twin model OCID:dtmi:com:oracle:example:core:hvac: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:hvac;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": "telemetry/health", "reference-payload": { "data": { "time": "2025-09-11T06:09:27.878106Z" }, "data-format": "JSON" } }, "inbound-routes": [ { "condition": "${endpoint(2) == \"heartbeat\"}", "description": null, "payload-mapping": { "$.humidity": "${.hum-1}", "$.temperature": "$.temp" }, "reference-payload": { "data": { "hum": 62, "temp": 75 }, "data-format": "JSON" } }, { "condition": "${endpoint(2) == \"health\"}", "description": null, "payload-mapping": {}, "reference-payload": { "data": { "batteryPercentage": 60, "on": false }, "data-format": "JSON" } } ], "iot-domain-id": "<iot-domain-OCID>", "lifecycle-state": "ACTIVE", "system-tags": {}, "time-created": "2025-09-30T19:55:36.293000+00:00", "time-updated": "2025-09-30T19:55:36.293000+00:00" }, "etag": "<unique-id>" }
Step 4: Create a Digital Twin Instance with the Adapter
Using the CLI
Use the oci iot digital-twin-instance create
and the <iot-domain-OCID>
and the <certificate-or-secret-OCID>
required parameters to create a digital twin instance. Replace the <certificate-or-secret-OCID>
with the vault secret OCID you want use and replace <iot-domain-OCID>
with the OCID for the IoT domain for your environment.
If the digital twin instance is set up to receive device data, then you must use the authentication ID parameter with a vault secret or certificate OCID, so the digital twin can authenticate. To do that create a secret or create a certificate in the same region and tenancy as any other related IoT resources.
This example uses the --display-name
option, replace <your-digital-twin-instance-name>
with a user-friendly name for your digital twin instance.
<digital-twin-adapter-OCID>
with the digital twin adapter created in the previous step. oci iot digital-twin-instance create --iot-domain-id <iot-domain-OCID> --display-name <your-digital-twin-instance-name> --auth-id <certificate-or-secret-OCID> --digital-twin-adapter-id <digital-twin-adapter-OCID>
This example response shows the digital twin adapter and DTMI URI defined for the digital twin model associated with this digital twin instance.dtmi:com:oracle:example:hvac;1
{
"data": {
"auth-id": "<vault-secret-OCID>",
"defined-tags": {
"Oracle-Tags": {
"CreatedBy": "default/user@oracle.com",
"CreatedOn": "2025-08-14T17:41:11.973Z"
}
},
"description": null,
"digital-twin-adapter-id": "<iot-digital-twin-adapter-OCID>",
"digital-twin-model-id": "<digital-twin-model-OCID>",
"digital-twin-model-spec-uri": "dtmi:com:oracle:example:hvac;1",
"display-name": "<your-digital-twin-instance-name>",
"external-key": "<digital-twin-instance-external-key>",
"freeform-tags": {},
"id": "<digital-twin-instance-OCID>",
"iot-domain-id": "<iot-domain-OCID>",
"lifecycle-state": "ACTIVE",
"system-tags": {},
"time-created": "2025-08-14T17:41:13.638000+00:00",
"time-updated": "2025-08-14T17:41:13.638000+00:00"
},
"etag": "<unique-id>"
}
Step 5: Send Telemetry Data
Use the following curl
command and the <digital-twin-instance-external-key>
to send or post data. For more information, see Using cURL.
curl -u 'digital-twin-instance-external-key:device-password' -H "content-type: application/json" https://<domain-short-id-from-device-host>.device.iot.<region>.oci.oraclecloud.com/telemetry/heartbeat -d '{"temp": 70, "hum": 55}'
Accepted%
curl -i -X POST \
-u "<digital-twin-instance-external-key>:<device-password>" \
-H "Content-Type: application/json" \
"https://<domain-short-id-from-device-host>.device.iot.<region>.oci.oraclecloud.com/telemetry/heartbeat" \
-d '{
"digital_twin_instance_id": "<iot-digital-twin-instance-OCID>",
"received_at": "2024-08-14T06:01:30.432829Z",
"endpoint": "telemetry/heartbeat",
"content_type": "application/json",
"content": {
"time": "<time>",
"data": {
"temp": 70,
"hum": 65
}
}
}'
Step 6: View Telemetry Data
Use the Internet of Things Data API to Get the Data
This example uses HTTPs. Alternatively, you can use MQTT and MQTT over WebSockets. For specific examples, see Scenarios.
curl -H "Authorization: Bearer <token>" \
-X GET "https://<domain-group-short-id>.data.iot.<region>.oci.oraclecloud.com/ords/<domain-short-id>/20250531/rawData?q={\"$and\":[{\"digital_twin_instance_id\":\"<iot-digital-twin-OCID>\"}]}"
Use SQL statements to View your Data
raw
telemetry data:select * from <domain-short-id-from-device-host>__IOT.RAW_DATA where digital_twin_instance_id = '<iot-digital-twin-OCID>';
Notice the schema name contain two underscores: __IOT
Or use this SQL statement to view the rejected
telemetry data. Replace the <domain-short-id-from-device-host>
with the domain short ID for your IoT domain and the <iot-digital-twin-OCID>
with the digital twin's OCID that you want to view rejected data from:
select * from <domain-short-id-from-device-host>__IOT.REJECTED_DATA where digital_twin_instance_id = '<iot-digital-twin-OCID>';
Or use this SQL statement to view the historized telemetry data. Replace the <domain-short-id-from-device-host>
with the domain short ID for your IoT domain and the <iot-digital-twin-OCID>
with the OCID for the digital twin you want to view rejected data from:select * from <domain-short-id>__IOT.DIGITAL_TWIN_HISTORIZED_DATA where digital_twin_id = '<digital-twin-OCID>';