Digital twins and their twin graph
This article describes what digital twins are in the context of Azure Digital Twins, and how relationships between them can form a twin graph. In an Azure Digital Twins solution, the entities in your environment are represented by digital twins. A digital twin is an instance of one of your custom-defined models. It can be connected to other digital twins via relationships to form a twin graph: this twin graph is the representation of your entire environment.
Tips
"Azure Digital Twins" refers to this Azure service as a whole. "Digital twin(s)" or just "twin(s)" refers to individual twin nodes inside your instance of the service.
Before you can create a digital twin in your Azure Digital Twins instance, you need to have a model uploaded to the service. A model describes the set of properties and relationships that a particular twin can have, among other things. For the types of information that are defined in a model, see Custom models.
After creating and uploading a model, your client app can create an instance of the type. This instance is a digital twin. For example, after creating a model of Floor, you may create one or several digital twins that use this type (like a Floor-type twin called GroundFloor, another called Floor2, and so on).
Obs!
Digital twins in Azure Digital Twins are different from device twins in IoT Hub. IoT Hub device twins often focus on describing the aspects and capabilities of a device itself, while twins in Azure Digital Twins are more conceptual representations that can store user-defined insights about a device or many related devices.
Devices in IoT Hub can be connected to Azure Digital Twins as part of an end-to-end solution that represents your device across services.
Twins are connected into a twin graph by their relationships. The relationships that a twin can have are defined as part of its model.
For example, the model Floor might define a contains
relationship that targets twins of type Room. With this definition, Azure Digital Twins will allow you to create contains
relationships from any Floor twin to any Room twin (including twins that are of Room subtypes).
The result of this process is a set of nodes (the digital twins) connected via edges (their relationships) in a graph.
Azure Digital Twins Explorer is a visual tool for exploring the data in your Azure Digital Twins graph. You can use the explorer to view, query, and edit your models, twins, and relationships.
To read about the Azure Digital Twins Explorer tool, see Azure Digital Twins Explorer. For detailed steps on how to use its features, see Use Azure Digital Twins Explorer.
Here's what the visualization looks like:
This section shows what it looks like to create digital twins and relationships from a client application. It contains .NET SDK examples that use the DigitalTwins APIs, to provide more context on what goes on inside each of these concepts.
Below is a snippet of client code that uses the DigitalTwins APIs to instantiate a twin of type Room with a twinId
that's defined during the instantiation.
You can initialize the properties of a twin when it's created, or set them later. To create a twin with initialized properties, create a JSON document that provides the necessary initialization values.
// Define a custom model type for the twin to be created
internal class CustomDigitalTwin
{
[JsonPropertyName(DigitalTwinsJsonPropertyNames.DigitalTwinId)]
public string Id { get; set; }
[JsonPropertyName(DigitalTwinsJsonPropertyNames.DigitalTwinETag)]
public string ETag { get; set; }
[JsonPropertyName("temperature")]
public double Temperature { get; set; }
[JsonPropertyName("humidity")]
public double Humidity{ get; set; }
}
// Initialize properties and create the twin
public class TwinOperationsCreateTwin
{
public async Task CreateTwinAsync(DigitalTwinsClient client)
{
// Initialize the twin properties
var myTwin = new CustomDigitalTwin
{
Temperature = 25.0,
Humidity = 50.0,
};
// Create the twin
const string twinId = "<twin-ID>";
Response<CustomDigitalTwin> response = await client.CreateOrReplaceDigitalTwinAsync(twinId, myTwin);
Console.WriteLine($"Temperature value: {response.Value.Temperature}");
}
}
You can also use a helper class called BasicDigitalTwin
to store property fields in a "twin" object more directly, as an alternative to using a dictionary. For more information about the helper class and examples of its use, see Create a digital twin.
Obs!
While twin properties are treated as optional and thus don't have to be initialized, any components on the twin need to be set when the twin is created. They can be empty objects, but the components themselves must exist.
Here's some example client code that uses the DigitalTwins APIs to build a relationship from one digital twin (the "source" twin) to another digital twin (the "target" twin).
public async Task CreateRelationship(DigitalTwinsClient client)
{
var rel = new BasicRelationship
{
TargetId = "myTargetTwin",
Name = "contains", // a relationship with this name must be defined in the model
// Initialize properties
Properties =
{
{ "active", true },
},
};
await client.CreateOrReplaceRelationshipAsync("mySourceTwin", "rel001", rel);
}
You can upload many twins and relationships in a single API call using the Import Jobs API. Twins and relationships created with this API can optionally include initialization of their properties. For detailed instructions and examples that use this API, see bulk import instructions for twins and relationships.
To delete specific twins and relationships, use the DigitalTwins Delete and DigitalTwins DeleteRelationship APIs (also available in as CLI commands and SDK calls).
To delete all models, twins, and relationships in an instance at once, use the Delete Jobs API.
Digital twin data and relationship data are both stored in JSON format, which means that when you query the twin graph in your Azure Digital Twins instance, the result will be a JSON representation of digital twins and relationships you've created.
When represented as a JSON object, a digital twin will display the following fields:
Field name | Description |
---|---|
$dtId |
A user-provided string representing the ID of the digital twin |
$etag |
Standard HTTP field assigned by the web server |
$metadata.$model |
The ID of the model interface that characterizes this digital twin |
$metadata.<property-name> |
Other metadata information about properties of the digital twin |
$metadata.<property-name>.lastUpdateTime |
The date/time the property update message was processed by Azure Digital Twins |
$metadata.<property-name>.sourceTime |
An optional, writable property representing the timestamp when the property update was observed in the real world. This property can only be written using the 2022-05-31 version of the Azure Digital Twins APIs/SDKs and the value must comply to ISO 8601 date and time format. For more information about how to update this property, see Update a property's sourceTime. |
<property-name> |
The value of a property in JSON (string , number type, or object) |
$relationships |
The URL of the path to the relationships collection. This field is absent if the digital twin has no outgoing relationship edges. |
<component-name> |
A JSON object containing the component's property values and metadata, similar to those of the root object. This object exists even if the component has no properties. |
<component-name>.$metadata |
The metadata information for the component, similar to the root-level $metadata |
<component-name>.<property-name> |
The value of the component's property in JSON (string , number type, or object) |
Here's an example of a digital twin formatted as a JSON object. This twin has two properties, Humidity and Temperature, and a component called Thermostat.
{
"$dtId": "myRoomID",
"$etag": "W/\"8e6d3e89-1166-4a1d-9a99-8accd8fef43f\"",
"$metadata": {
"$model": "dtmi:example:Room23;1",
"Humidity": {
"lastUpdateTime": "2021-11-30T18:47:53.7648958Z"
},
"Temperature": {
"lastUpdateTime": "2021-11-30T18:47:53.7648958Z"
}
},
"Humidity": 55,
"Temperature": 35,
"Thermostat": {
"$metadata": {}
}
When represented as a JSON object, a relationship from a digital twin will display the following fields:
Field name | Description |
---|---|
$relationshipId |
A user-provided string representing the ID of this relationship. This string is unique in the context of the source digital twin, which also means that sourceId + relationshipId is unique in the context of the Azure Digital Twins instance. |
$etag |
Standard HTTP field assigned by the web server |
$sourceId |
The ID of the source digital twin |
$targetId |
The ID of the target digital twin |
$relationshipName |
The name of the relationship |
<property-name> |
[Optional] The value of a property of this relationship, in JSON (string , number type, or object) |
Here's an example of a relationship formatted as a JSON object:
{
"$relationshipId": "relationship-01",
"$etag": "W/\"506e8391-2b21-4ac9-bca3-53e6620f6a90\"",
"$sourceId": "GroundFloor",
"$targetId": "Cafe",
"$relationshipName": "contains",
"startDate": "2020-02-04"
}
See how to manage graph elements with Azure Digital Twin APIs:
Or, learn about querying the Azure Digital Twins twin graph for information: