Sorry, you need to enable JavaScript to visit this website.

You are here

“Code First” Digital Twins

BY Michelle Telstra 29 October 2021

Azure Digital Twins is a platform as a service offering that enables you to create live digital twin graphs that represent entities and their relationships.

In today’s world where your IDE automatically detects your coding style and makes recommendations using machine learning, creating a digital twin might seem like more work than you’re accustomed.

First, you’d need to create a document using the Digital Twin Definition Language (DTDL). Then you’d need to add it to Azure Digital Twins using a Restful API call. You then need to repeat this process as changes are required.

A more familiar way might be to use Plain Old Class Objects or simply POCO. You may  already be familiar with it if you’ve used Entity Framework Core. Using POCO, you may find it easier to create and manage your digital twins using a code first approach.

 

Figure 1: Twin model vs twin with a buildings example

Creating Digital Twins using DTDL

Currently, digital twins are defined in a variety of ways. In Azure Digital Twins, developers define digital entities that represent people, places, or things by creating a digital twin model. For clarity, hereafter we will refer to digital twin models as simply models and digital twins as simply twins.

As Microsoft describes it, models are defined in a JSON-like language called Digital Twins Definition Language (DTDL) and they describe twins in terms of their state properties, telemetry events, commands, components, and relationships.

These models are then used to create twins that represents specific entities according to their defined model. Let’s take a look at an example.

Creating a Building Twin Model using DTDL

Let’s say we want to create a digital twin model of a Telstra building in Sydney located at 400 George Street. The DTDL to create the building model is shown below.

 

{

  "@id": "dtmi:com:telstra:building;1",

  "@type": "Interface",

  "displayName": "Building",

  "contents": [

    {

      "@type": "Property",

      "name": "name",

      "schema": "string",

      "writable": true

    },

    {

      "@type": "Property",

      "name": "address",

      "schema": "string",

      "writable": true

    },

    {

      "@type": "Property",

      "name": "city",

      "schema": "string",

      "writable": true

    },

    {

      "@type": "Property",

      "name": "state",

      "schema": "string",

      "writable": true

    },

    {

      "@type": "Property",

      "name": "zipcode",

      "schema": "string",

      "writable": true

    },

    {

      "@type": "Relationship",

      "name": "contains",

      "target": "dtmi:com:telstra:Floor;1"

    }

  ],

  "@context": "dtmi:dtdl:context;2"

}

Note that the @id is "dtmi:com:telstra:building;1". Where the identifier is made up of two parts, the id, "dtmi:com:telstra:building", and the model version, "1".

After creating a model for a building, a developer could create a twin for the Telstra building at 400 George Street, Sydney, Australia.

Writing this in DTDL provides the most flexibility but does require developers to learn DTDL and write the code necessary in their solutions to read and write data in DTDL for both twin models and twins.

Although deployment using DTDL is straightforward, it can be more difficult than developers are accustomed to. As model changes are required, updates must be made to the DTDL and then deployed, preferably using a CI/CD automated process. In Azure Digital Twins, an API must be called for each model that needs to be created or updated. The same is true for the creation of each twin.

Introducing Code First Digital Twins

Telstra has developed a “code-first” approach which sees it leverage common developer Plain Old Class Objects (POCO) together with Azure Digital Twins and a new Digital Twins library that may be preferred to working with DTDL directly.

Figure 2: Automated generation of DTDL can save time.

This approach enables developers to define digital twin models in code and then serialize them to create the twin models in Azure Digital Twins. This process can be automated in Azure DevOps using a simple pipeline step.

To date this has drastically reduced the time it takes for developers to create, read, write, and deploy digital twins, as well as reducing the ongoing maintenance required.

Figure 4: Continuous deployment, including the separation of device twin models from ontology specific twin models to increase quality and separate concerns.

A Building Twin Model using Code-First

Now, how would we create a building digital twin using code first? First, let’s take a look at how we might do it using Entity Framework Core.

public class Building

{

    public string Name { get; set; }

    public string Address { get; set; }


    public string City { get; set; }


    public string State { get; set; }


    public string ZipCode { get; set; }

}

This class could then be used by Entity Framework Core to create a database table for storing buildings. To provide additional information to Entity Framework Core about the class we use attributes such as ColumnAttribute, KeyAttribute, and MaxLengthAttribute.

Code first digital twins work in a similar way but require different attributes.

First, we need to indicate that the class represents a digital twin. To do this we use the DigitalTwinAttribute. Here we specify the version and the display name for the digital twin model.

[DigitalTwin(Version = 1, DisplayName = "Building")]

public class Building

{

    …

}

Next, we need to indicate which properties will be included in the digital twin model. We do this by adding the TwinPropertyAttribute to the relevant class properties.

[DigitalTwin(Version = 1, DisplayName = "Building")]

public class Building

{

    [TwinProperty]

    public string Name { get; set; }

    [TwinProperty]

    public string Address { get; set; }

    [TwinProperty]

    public string City { get; set; }

    [TwinProperty]

    public string State { get; set; }

    [TwinProperty]

    public string ZipCode { get; set; }

    [TwinRelationship]

    public List<Floor> Floors { get; } = new List<Floor>();

}

An instance of the above class would result in the following digital twin DTDL.

{

  "$dtId": "buildingTwin1",

  "$etag": "686897696a7c876b7e",

  "$metadata": {

    "$model": "dtmi:telstra:examples:building;1",

    "PropertyMetadata": {}

  },

  "name": "Telstra Building",

  "address": "400 George Street",

  "city": "Sydney",

  "state": "NSW",

  "zipCode": "2000"

}

For more information

To learn more about code first digital twins and the Telstra Twins library, reach out to the Daniel Simpson of the Telstra Digital Twins team at daniel.simpson@team.telstra.com. You can also visit the GitHub repository at https://github.com/telstra/DigitalTwins-CodeFirst-dotnet.