Deriving real-time intelligence about the physical world with Azure Percept and Azure Digital Twins

Published Jul 27 2021 08:00 AM 1,918 Views
Microsoft

Imagine that you represent a company that manages facilities for various conferences and exhibitions. Part of your job is to ensure that products exhibited by participants (or customers) are being displayed at the right location assigned to the participant. Not only would you need a view of the facilities, but you would also require real-time intelligence about the displayed products and their locations. Now this is possible through the real-time intelligence of Azure Percept and real-world view of Azure Digital Twins.

 

Azure Percept is a comprehensive platform for creating edge AI solutions. It is great at running AI at the edge and communicating back to Azure IoT Hub.

Azure Digital Twins is a comprehensive platform for creating digital representation of real-world things. It is an amazing technology for creating a digital representation of the physical world.

 

When you combine the real-time intelligence of Azure Percept with real-world view of Azure Digital Twins, you get an intelligent digital representation of the real world.

 

In this post we will see how we can collect real-time AI on the edge through Azure Percept and send it to Azure Digital Twins, adding real-time intelligence to the digital representation of real-world entities such as places, devices, and people.

 

The following figure shows how real-time AI on the Edge can be combined with Azure Digital Twins to yield real-time data visualization:

 

mnabeel_48-1626935892048.png

The goal of this post is to show how to build an end-to-end solution that leverages Azure Percept and Azure Digital Twins to build a real-time intelligent data visualization.

 

Architecture

 

mnabeel_0-1626942360023.png

The main components for the architecture are:

  • The Azure Percept DK that is configured to run AI on the Edge.
  • Azure IoT Hub that is configured to receive messages from the Azure Percept device.
  • An Azure Digital Twins instance deployed with DTDL models representing the physical entities monitored by the solution.
  • Azure Event Hub setup to receive events/updates from the Azure Digital Twins instance. Azure Event Hub allows telemetry and event data to be made available to various stream-processing infrastructures and can receive millions of events per second which is exactly what we need to process a constant stream of events from the Azure Percept DK.
  • Two Azure Functions, one which serves as a bridge between Azure Percept and the Azure Digital Twins instance, and another one that listens to the Azure Event Hubs to receive updates from the Azure Digital Twins instance.
  • A front-end Dashboard application to receive the updates from Azure Digital Twins through EventHub. Any front-end platform can be used to receive these updates and provide data visualization. In our example, we are using a SignalR based Dashboard application.

 

Setup

 

Azure Percept DK Setup

If you do not have Azure Percept DK, you can use any IoT device (edge or leaf) that sends inference data to Azure IoT Hub.

To learn more about how to configure Azure Percept devices running AI visit Create a no-code vision solution in Azure Percept

The Azure Percept device’s job is to look for objects of interest using an AI model that detects various objects such as people, bottle etc. For this post we are using an example with two use cases:

  • Detect objects that are compliant: the presence of “bottle” is expected.
  • Detect objects that are not compliant: the presence of a “person” is not expected as this would raise safety concerns.

The Azure Percept DK is constantly looking for compliant objects (example: bottle) and non-compliant objects (example: person).

Here is how Azure Percept is detecting a “bottle”:

mnabeel_51-1626936536300.png

Azure Percept is constantly sending the inference data (information about detected objects such as bottle, erson) to Azure IoT Hub as device-to-cloud messages.

Here is an example of data sent from the Azure Percept DK to Azure IoT Hub:

Data coming from Azure Percept

 

 

 

{ 
  "body": { 
    "NEURAL_NETWORK": [ 
      { 
        "bbox": [ 
          0.32, 
          0.084, 
          0.636, 
          1 
        ], 
        "label": "person", 
        "confidence": "0.889648", 
        "timestamp": "1622658821393258467" 
      } 
    ] 
  }, 
  "enqueuedTime": "2021-06-02T18:33:41.866Z" 
}

 

 

 

This data will be paired up with Azure Digital Twins to yield real-time AI data visualization of real-world digital representation.

 

Azure Digital Twins Setup

Azure Digital Twins setup is divided into two distinct parts.

  • The first part deals with the setup of a model for Azure Digital Twins. The Digital Twins Definition Language (DTDL) models are used to define the digital representation of real-world entities indicating their properties and relationships. The digital entities can represent people, places, and things. For more details on DTDL models visit the Azure Digital Twins documentation.
  • The second part is the provisioning of the Azure Digital Twins instance.

In our example scenario we developed a model that has two components. One component of the model will be the site (mentioned as “PerceptSite” in the model) where the exhibition is taking place. The second component is the model for the floor (“PerceptSiteFloor”) which is assigned to a particular exhibition participant.

 

Azure Digital Twins Instance Setup

In the following steps, we are using the CLI to setup the Azure Digital Twins instance. You can find details for this at: Set up an instance and authentication (CLI) - Azure Digital Twins | Microsoft Docs.

For steps using the Azure Portal visit Set up an instance and authentication (portal) - Azure Digital Twins | Microsoft Docs

 

 

 

$rgname = "<your-prefix>" 
$random = "<your-prefix>" + $(get-random -maximum 10000) 
$dtname = $random + "-digitaltwin" 
$location = "westus2" 
$username = "<your-username>@<your-domain>" 
$functionstorage = $random + "storage" 
$telemetryfunctionname = $random + "-telemetryfunction" 
$twinupdatefunctionname = $random + "-twinupdatefunction" 

# Create resource group 
az group create -n $rgname -l $location 

# Create Azure Digital Twins instance 
az dt create --dt-name $dtname -g $rgname -l $location 

# Create role assignment for user needed to access Azure Digital Twins instance 
az dt role-assignment create -n $dtname -g $rgname --role "Azure Digital Twins Data Owner" --assignee $username -o json 

 

 

 

Model Setup

 

 

 

$sitemodelid = "dtmi:percept:DigitalTwins:Site;1" 

# Creating Azure Digital Twins model for Site 
az dt model delete --dt-name $dtname --dtmi $sitemodelid 
$sitemodelid = $(az dt model create -n $dtname --models .\SiteInterface.json --query [].id -o tsv) 
$sitefloormodelid = "dtmi:percept:DigitalTwins:SiteFloor;1" 

# Creating Azure Digital Twins model for Site floor 
$sitefloormodelid = $(az dt model create -n $dtname --models .\SiteFloorInterface.json --query [].id -o tsv) 

# Creating twin: PerceptSite 
az dt twin create -n $dtname --dtmi $sitemodelid --twin-id "PerceptSite" 

# Creating twin: PerceptSiteFloor 
az dt twin create -n $dtname --dtmi $sitefloormodelid --twin-id "PerceptSiteFloor" 
$relname = "rel_has_floors"

# Creating relationships" 
az dt twin relationship create -n $dtname --relationship $relname --twin-id "PerceptSite" --target "PerceptSiteFloor" --relationship-id "Site has floors"

 

 

 

Here is how this basic model looks like once it is created on Azure Digital Twins:

mnabeel_0-1626939036437.png

 

The above screenshot is taken from Azure Digital Twins Explorer view. Azure Digital Twins Explorer is a developer tool for the Azure Digital Twins service. It lets you connect to an Azure Digital Twins instance to understand, visualize, and modify your digital twin data.

Functions Apps Setup

 

Azure Digital Twins Ingestion App

mnabeel_1-1626939132912.png

 

The Azure Digital Twins Ingestion Function app will receive updates from Azure IoT Hub and forward those updates to Azure Digital Twins. The functions use in the code can be found in the Azure.DigitalTwins.Core library.

 

Here is the source code for the Azure Digital Twins Ingestion App:

 

 

 

namespace TwinIngestionFunctionApp 
{ 
    using Azure; 
    using Azure.Core.Pipeline; 
    using Azure.DigitalTwins.Core; 
    using Azure.Identity; 
    using Microsoft.Azure.EventHubs; 
    using Microsoft.Azure.WebJobs; 
    using Microsoft.Extensions.Logging; 
    using Newtonsoft.Json; 
    using Newtonsoft.Json.Linq; 
    using System; 
    using System.Net.Http; 
    using System.Text; 
    using IoTHubTrigger = Microsoft.Azure.WebJobs.EventHubTriggerAttribute; 

 
    public class TwinsFunction 
    { 
        private static readonly string adtInstanceUrl = Environment.GetEnvironmentVariable("ADT_SERVICE_URL"); 
        private static HttpClient httpClient = new HttpClient(); 

 
        [FunctionName("TwinsFunction")] 
        public async void Run([IoTHubTrigger("messages/events", Connection = "EventHubConnectionString")] EventData message, ILogger log) 
        { 

 
            if (adtInstanceUrl == null) log.LogError("Application setting \"ADT_SERVICE_URL\" not set"); 
            { 
                try 
                { 
                    //Authenticate with Digital Twins 
                    ManagedIdentityCredential cred = new ManagedIdentityCredential("https://digitaltwins.azure.net"); 
                    DigitalTwinsClient client = new DigitalTwinsClient(new Uri(adtInstanceUrl), cred, new DigitalTwinsClientOptions { Transport = new HttpClientTransport(httpClient) }); 
                    if (message != null && message.Body != null) 
                    { 

                       log.LogInformation(Encoding.UTF8.GetString(message.Body.Array)); 

 
                        // Reading AI data for IoT Hub JSON 
                        JObject deviceMessage = (JObject)JsonConvert.DeserializeObject(Encoding.UTF8.GetString(message.Body.Array)); 
                        string label = deviceMessage["NEURAL_NETWORK"][0]["label"].ToString(); 
                        string confidence = deviceMessage["NEURAL_NETWORK"][0]["confidence"].ToString(); 
                        string timestamp = deviceMessage["NEURAL_NETWORK"][0]["timestamp"].ToString(); 
                        if(!(string.IsNullOrEmpty(label) && string.IsNullOrEmpty(confidence) && string.IsNullOrEmpty(timestamp))) 
                        { 
                            var updateTwinData = new JsonPatchDocument(); 
                            updateTwinData.AppendAdd("/Label", label); 
                            updateTwinData.AppendAdd("/Confidence", confidence); 
                            updateTwinData.AppendAdd("/timestamp", timestamp); 
                            await client.UpdateDigitalTwinAsync("PerceptSiteFloor", updateTwinData); 
                            log.LogInformation($"Updated Device: PerceptSiteFloor with { updateTwinData} at: {DateTime.Now.ToString()}"); 
                        } 
                    } 
                } 
                catch (Exception e) 
                { 
                    log.LogError(e.Message); 
                } 

 
            } 
        } 
    } 
} 

 

 

 

Here is the video that shows how the inference data from Azure Percept is being received by Azure Digital Twins instance:

 

 

Publishing messages from Azure Digital Twins to Event Hub

 

In the previous sections we have seen how the messages from Azure Percept are forwarded to Azure Digital Twins through Azure IoT Hub using an Azure Function. In this section we will see how to prepare the Azure Digital Twins instance to send messages to Event Hub. This involves the following:

  • Setting up Event Hub
  • Setting up Azure Digital Twins to send messages to Event Hub.

Setting up Event Hub

The setting up of the Event Hub involves creating an Event Hub Namespace and creating an Event Hub.

To create Event Hub Namespace refer to details mentioned at Azure Quickstart - Create an event hub using the Azure portal - Azure Event Hubs | Microsoft Docs

To create Event Hub refer to details mentioned at Azure Quickstart - Create an event hub using the Azure portal - Azure Event Hubs | Microsoft Docs

Once the Event Hub is created, we can proceed to set up the route from Azure Digital Twins.

 

Setting up Azure Digital Twins to send messages to Event Hub

Use the following steps to setup Azure Digital Twins to send messages to Event Hub:

  1. Create Azure Digital Twins Endpoint
  2. Create Azure Digital Twins Event Route

 

Create Azure Digital Twins Endpoint

For this step will be using the Event Hub Namespace and Event Hub that was created in previous steps.

Following image illustrates the details of creating an Azure Digital Twins Endpoint:

mnabeel_2-1626939490703.png

 

Create Azure Digital Twins Event Route

The following image illustrates the details of creating an Azure Digital Twins Event Route:

mnabeel_3-1626939550331.png

The above steps will result in our Azure Digital Twins instance routing messages to our Event hub.

 

Azure Digital Twins Update App

 

The previous sections explained the steps to receive messages from Azure Percept to Event Hub using Azure IoT Hub and Azure Digital Twins. In this section we focus on the Azure function that will be receiving events from Event Hub. These events are showing the updates that Azure Digital Twins instance is receiving.

mnabeel_4-1626939622770.png

The purpose of Azure Function for receiving Azure Digital Twins updates through Event Hub is to create a source for any further processing. For example, this can be a source for 3d modeling platform or an API backend.

 

Here is the source code for the Azure Function that processes the Event Hub events coming from Azure Digital Twins:

 

 

 

namespace TwinsUpdateFunctionApp 
{ 
    using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Net.Http; 
    using System.Text; 
    using System.Threading.Tasks; 
    using Microsoft.Azure.EventHubs; 
    using Microsoft.Azure.WebJobs; 
    using Microsoft.Extensions.Logging; 
    using Newtonsoft.Json; 
    using Newtonsoft.Json.Linq; 
    using TwinsUpdateFunctionApp.model; 
 
    public static class TwinsUpdateFunction 
    { 
        private static readonly string twinReceiverUrl = Environment.GetEnvironmentVariable("TWINS_RECEIVER_URL"); 

        [FunctionName("TwinsUpdateFunction")] 
        public static async Task Run([EventHubTrigger("[your-digitaltwin-eventhub]", Connection = "EventHubConnectionString")] EventData[] events, ILogger log) 
        { 
            var exceptions = new List<Exception>(); 
            List<TwinUpdate> twinUpdates = new List<TwinUpdate>(); 
            foreach (EventData eventData in events) 
            { 
                try 
                { 
                    string messageBody = Encoding.UTF8.GetString(eventData.Body.Array, eventData.Body.Offset, eventData.Body.Count); 
                    JObject twinMessage = (JObject)JsonConvert.DeserializeObject(messageBody); 
                    if (twinMessage["patch"] != null) 
                    { 
                        TwinUpdate twinUpdate = new TwinUpdate(); 
                        twinUpdate.ModelId = twinMessage["modelId"].ToString(); 
                        foreach (JToken jToken in twinMessage["patch"]) 
                        { 
                            if (jToken["path"].ToString().Equals("/FloorId", StringComparison.InvariantCultureIgnoreCase)) 
                            { 
                                twinUpdate.Floor = jToken["value"].ToString(); 
                            } 
                            if (jToken["path"].ToString().Equals("/FloorName", StringComparison.InvariantCultureIgnoreCase)) 
                            { 
                                twinUpdate.FloorName = jToken["value"].ToString(); 
                            } 
                            if (jToken["path"].ToString().Equals("/Label", StringComparison.InvariantCultureIgnoreCase)) 
                            { 
                                twinUpdate.Label = jToken["value"].ToString(); 
                            } 
                            if (jToken["path"].ToString().Equals("/Confidence", StringComparison.InvariantCultureIgnoreCase)) 
                            { 
                                twinUpdate.Confidence = jToken["value"].ToString(); 
                            } 
                            if (jToken["path"].ToString().Equals("/timestamp", StringComparison.InvariantCultureIgnoreCase)) 
                            { 
                                twinUpdate.Timestamp = jToken["value"].ToString(); 
                            } 
                        } 
 
                        using (HttpClient httpClient = new HttpClient()) 
                        { 
                            var requestURl = new Uri($"{twinReceiverUrl}?label={twinUpdate.Label}&confidence={twinUpdate.Confidence}&timestamp={twinUpdate.Timestamp}&floorId={twinUpdate.Floor}&floorName={twinUpdate.FloorName}"); 
                            StringContent queryString = new StringContent(messageBody); 
                            var response = httpClient.PostAsync(requestURl, queryString).Result; 
                        } 
 
                        twinUpdates.Add(twinUpdate); 
                    } 
                     
                    await Task.Yield(); 
                } 
                catch (Exception e) 
                { 
                    exceptions.Add(e); 
                } 
            } 
 
            if (exceptions.Count > 1) 
                throw new AggregateException(exceptions); 

 
            if (exceptions.Count == 1) 
                throw exceptions.Single(); 
        } 
    } 
} 

 

 

 

The above-mentioned code represents an Azure Function that is triggered by EventHubTrigger. After deserializing the data received from the Digital Twins update, the Azure function posts update to a SignalR front-end application using the following code:

 

 

 

                        using (HttpClient httpClient = new HttpClient()) 
                        { 
                            var requestURl = new Uri($"{twinReceiverUrl}?label={twinUpdate.Label}&confidence={twinUpdate.Confidence}&timestamp={twinUpdate.Timestamp}&floorId={twinUpdate.Floor}&floorName={twinUpdate.FloorName}"); 
                            StringContent queryString = new StringContent(messageBody); 
                            var response = httpClient.PostAsync(requestURl, queryString).Result; 
                        } 

 

 

 

Front-end Dashboard App

 

The last and the most important piece of our architecture is the front-end Dashboard app that will be used to visualize the Azure Data Twins updates. This is where the value of combing Azure Percept and Azure Digital Twins is revealed. Any front-end platforms can be used for this part depending on the requirements and constraints. To demonstrate the Front-end Dashboard App, we are using a SignalR based application with a single page. SignalR allows to make Web pages more dynamic, offering an eventing mecanism from server to client. Here is a link to a great tutorial on SignalR: Get started with ASP.NET Core SignalR | Microsoft Docs

 

Once the Dashboard App receives the data it automatically updates its view. The view contains a top section showing the “Data visualization through Azure Digital Twins updates and a bottom section showing the “Raw Azure Digital Twins updates”. The top section is an example of how you can present the data visualization on a view using the raw data mentioned on the bottom section.

 

mnabeel_0-1626940171467.png

 

For our example we had two use cases representing compliant and non-compliant objects detection. Here is how the data visualization on the front-end app will look like for compliant and non-compliant objects:

 

Compliant object detection:

mnabeel_1-1626940252929.png

 

Non-compliant object detection:

mnabeel_2-1626940316304.png

The source code for the example that we have used for data visualization can be found at: https://aka.ms/AAd96fy

 

Conclusion

Azure Percept and Azure Digital Twins are two distinct Azure services that are built to provide unique values. In this post we have seen how real-time AI with Azure Percept can be combined with the real-word digital representations of Azure Digital Twins to derive pertinent data visualization using real-time intelligence. This post has shown how simple it is to combine both technologies to achieve data visualization that we need.

Here is what the final application looks like:

Compliant use case

mnabeel_3-1626940471402.png

 

Non-compliant use case

mnabeel_4-1626940546176.png

Following video shows how Azure Percept is running AI on edge to identify objects and then how the Front-end Dashboard App displays the update flowing from Azure Digital Twins:

 

 

Let us know what you think commenting below and to stay informed, subscribe to our post here and follow us on Twitter @MicrosoftIoT .

%3CLINGO-SUB%20id%3D%22lingo-sub-2574104%22%20slang%3D%22en-US%22%3EDeriving%20real-time%20intelligence%20about%20the%20physical%20world%20with%20Azure%20Percept%20and%20Azure%20Digital%20Twins%3C%2FLINGO-SUB%3E%3CLINGO-BODY%20id%3D%22lingo-body-2574104%22%20slang%3D%22en-US%22%3E%3CP%3EImagine%20that%20you%20represent%20a%20company%20that%20manages%20facilities%20for%20various%20conferences%20and%20exhibitions.%20Part%20of%20your%20job%20is%20to%20ensure%20that%20products%20exhibited%20by%20participants%20(or%20customers)%20are%20being%20displayed%20at%20the%20right%20location%20assigned%20to%20the%20participant.%20Not%20only%20would%20you%20need%20a%20view%20of%20the%20facilities%2C%20but%20you%20would%20also%20require%20real-time%20intelligence%20about%20the%20displayed%20products%20and%20their%20locations.%20Now%20this%20is%20possible%20through%20the%20real-time%20intelligence%20of%20Azure%20Percept%20and%20real-world%20view%20of%20Azure%20Digital%20Twins.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CA%20href%3D%22https%3A%2F%2Fazure.microsoft.com%2Fservices%2Fazure-percept%2F%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%22%3EAzure%20Percept%3C%2FA%3E%20is%20a%20comprehensive%20platform%20for%20creating%20edge%20AI%20solutions.%20It%20is%20great%20at%20running%20AI%20at%20the%20edge%20and%20communicating%20back%20to%20Azure%20IoT%20Hub.%3C%2FP%3E%0A%3CP%3E%3CA%20href%3D%22https%3A%2F%2Fazure.microsoft.com%2Fservices%2Fdigital-twins%2F%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%22%3EAzure%20Digital%20Twins%3C%2FA%3E%20is%20a%20comprehensive%20platform%20for%20creating%20digital%20representation%20of%20real-world%20things.%20It%20is%20an%20amazing%20technology%20for%20creating%20a%20digital%20representation%20of%20the%20physical%20world.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EWhen%20you%20combine%20the%20real-time%20intelligence%20of%20Azure%20Percept%20with%20real-world%20view%20of%20Azure%20Digital%20Twins%2C%20you%20get%20an%20intelligent%20digital%20representation%20of%20the%20real%20world.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EIn%20this%20post%20we%20will%20see%20how%20we%20can%20collect%20real-time%20AI%20on%20the%20edge%20through%20Azure%20Percept%20and%20send%20it%20to%20Azure%20Digital%20Twins%2C%20adding%20real-time%20intelligence%20to%20the%20digital%20representation%20of%20real-world%20entities%20such%20as%20places%2C%20devices%2C%20and%20people.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EThe%20following%20figure%20shows%20how%20real-time%20AI%20on%20the%20Edge%20can%20be%20combined%20with%20Azure%20Digital%20Twins%20to%20yield%20real-time%20data%20visualization%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%20align%3D%22center%22%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%22mnabeel_48-1626935892048.png%22%20style%3D%22width%3A%20999px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F297571iACF257528777AB5B%2Fimage-size%2Flarge%3Fv%3Dv2%26amp%3Bpx%3D999%22%20role%3D%22button%22%20title%3D%22mnabeel_48-1626935892048.png%22%20alt%3D%22mnabeel_48-1626935892048.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3EThe%20goal%20of%20this%20post%20is%20to%20show%20how%20to%20build%20an%20end-to-end%20solution%20that%20leverages%20Azure%20Percept%20and%20Azure%20Digital%20Twins%20to%20build%20a%20real-time%20intelligent%20data%20visualization.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH2%20id%3D%22toc-hId--406099622%22%20id%3D%22toc-hId--406099620%22%3EArchitecture%3C%2FH2%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%20align%3D%22center%22%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%22mnabeel_0-1626942360023.png%22%20style%3D%22width%3A%20999px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F297601i9AE5735A7F42C48E%2Fimage-size%2Flarge%3Fv%3Dv2%26amp%3Bpx%3D999%22%20role%3D%22button%22%20title%3D%22mnabeel_0-1626942360023.png%22%20alt%3D%22mnabeel_0-1626942360023.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3EThe%20main%20components%20for%20the%20architecture%20are%3A%3C%2FP%3E%0A%3CUL%3E%0A%3CLI%3EThe%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fazure-percept%2Foverview-azure-percept%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%22%3EAzure%20Percept%3C%2FA%3E%20DK%20that%20is%20configured%20to%20run%20AI%20on%20the%20Edge.%3C%2FLI%3E%0A%3CLI%3E%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fiot-hub%2Fabout-iot-hub%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%22%3EAzure%20IoT%20Hub%3C%2FA%3E%20that%20is%20configured%20to%20receive%20messages%20from%20the%20Azure%20Percept%20device.%3C%2FLI%3E%0A%3CLI%3EAn%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fdigital-twins%2Foverview%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%22%3EAzure%20Digital%20Twins%3C%2FA%3E%20instance%20deployed%20with%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fdigital-twins%2Fconcepts-models%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%22%3EDTDL%20models%3C%2FA%3E%20representing%20the%20physical%20entities%20monitored%20by%20the%20solution.%3C%2FLI%3E%0A%3CLI%3E%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fevent-hubs%2Fevent-hubs-about%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%22%3EAzure%20Event%20Hub%3C%2FA%3E%20setup%20to%20receive%20events%2Fupdates%20from%20the%20Azure%20Digital%20Twins%20instance.%20Azure%20Event%20Hub%20allows%20telemetry%20and%20event%20data%20to%20be%20made%20available%20to%20various%20stream-processing%20infrastructures%20and%20can%20receive%20millions%20of%20events%20per%20second%20which%20is%20exactly%20what%20we%20need%20to%20process%20a%20constant%20stream%20of%20events%20from%20the%20Azure%20Percept%20DK.%3C%2FLI%3E%0A%3CLI%3ETwo%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fazure-functions%2Ffunctions-overview%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%22%3EAzure%20Functions%3C%2FA%3E%2C%20one%20which%20serves%20as%20a%20bridge%20between%20Azure%20Percept%20and%20the%20Azure%20Digital%20Twins%20instance%2C%20and%20another%20one%20that%20listens%20to%20the%20Azure%20Event%20Hubs%20to%20receive%20updates%20from%20the%20Azure%20Digital%20Twins%20instance.%3C%2FLI%3E%0A%3CLI%3EA%20front-end%20Dashboard%20application%20to%20receive%20the%20updates%20from%20Azure%20Digital%20Twins%20through%20EventHub.%20Any%20front-end%20platform%20can%20be%20used%20to%20receive%20these%20updates%20and%20provide%20data%20visualization.%20In%20our%20example%2C%20we%20are%20using%20a%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Faspnet%2Fsignalr%2Foverview%2Fgetting-started%2Fintroduction-to-signalr%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%22%3ESignalR%3C%2FA%3E%20based%20Dashboard%20application.%3C%2FLI%3E%0A%3C%2FUL%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH2%20id%3D%22toc-hId-2081413211%22%20id%3D%22toc-hId-2081413213%22%3ESetup%3C%2FH2%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH3%20id%3D%22toc-hId--1522992611%22%20id%3D%22toc-hId--1522992609%22%3EAzure%20Percept%20DK%20Setup%3C%2FH3%3E%0A%3CP%3EIf%20you%20do%20not%20have%20Azure%20Percept%20DK%2C%20you%20can%20use%20any%20IoT%20device%20(edge%20or%20leaf)%20that%20sends%20inference%20data%20to%20Azure%20IoT%20Hub.%3C%2FP%3E%0A%3CP%3ETo%20learn%20more%20about%20how%20to%20configure%20Azure%20Percept%20devices%20running%20AI%20visit%E2%80%AF%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fazure-percept%2Ftutorial-nocode-vision%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%22%3ECreate%20a%20no-code%20vision%20solution%20in%20Azure%20Percept%3C%2FA%3E%3C%2FP%3E%0A%3CP%3EThe%20Azure%20Percept%20device%E2%80%99s%20job%20is%20to%20look%20for%20objects%20of%20interest%20using%20an%20AI%20model%20that%20detects%20various%20objects%20such%20as%20people%2C%20bottle%20etc.%20For%20this%20post%20we%20are%20using%20an%20example%20with%20two%20use%20cases%3A%3C%2FP%3E%0A%3CUL%3E%0A%3CLI%3EDetect%20objects%20that%20are%20compliant%3A%20the%20presence%20of%20%E2%80%9Cbottle%E2%80%9D%20is%20expected.%3C%2FLI%3E%0A%3CLI%3EDetect%20objects%20that%20are%20not%20compliant%3A%20the%20presence%20of%20a%20%E2%80%9Cperson%E2%80%9D%20is%20not%20expected%20as%20this%20would%20raise%20safety%20concerns.%3C%2FLI%3E%0A%3C%2FUL%3E%0A%3CP%3EThe%20Azure%20Percept%20DK%20is%20constantly%20looking%20for%20compliant%20objects%20(example%3A%20bottle)%20and%20non-compliant%20objects%20(example%3A%20person).%3C%2FP%3E%0A%3CP%3EHere%20is%20how%20Azure%20Percept%20is%20detecting%20a%20%E2%80%9Cbottle%E2%80%9D%3A%3C%2FP%3E%0A%3CP%20align%3D%22center%22%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%22mnabeel_51-1626936536300.png%22%20style%3D%22width%3A%20999px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F297574i9CFA3F04C0D130B8%2Fimage-size%2Flarge%3Fv%3Dv2%26amp%3Bpx%3D999%22%20role%3D%22button%22%20title%3D%22mnabeel_51-1626936536300.png%22%20alt%3D%22mnabeel_51-1626936536300.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3EAzure%20Percept%20is%20constantly%20sending%20the%20inference%20data%20(information%20about%20detected%20objects%20such%20as%20bottle%2C%20erson)%20to%20Azure%20IoT%20Hub%20as%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fazure%2Fiot-hub%2Fiot-hub-devguide-messages-d2c%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%22%3Edevice-to-cloud%3C%2FA%3E%20messages.%3C%2FP%3E%0A%3CP%3EHere%20is%20an%20example%20of%20data%20sent%20from%20the%20Azure%20Percept%20DK%20to%20Azure%20IoT%20Hub%3A%3C%2FP%3E%0A%3CP%3EData%20coming%20from%20Azure%20Percept%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CPRE%20class%3D%22lia-code-sample%20language-json%22%3E%3CCODE%3E%7B%20%0A%20%20%22body%22%3A%20%7B%20%0A%20%20%20%20%22NEURAL_NETWORK%22%3A%20%5B%20%0A%20%20%20%20%20%20%7B%20%0A%20%20%20%20%20%20%20%20%22bbox%22%3A%20%5B%20%0A%20%20%20%20%20%20%20%20%20%200.32%2C%20%0A%20%20%20%20%20%20%20%20%20%200.084%2C%20%0A%20%20%20%20%20%20%20%20%20%200.636%2C%20%0A%20%20%20%20%20%20%20%20%20%201%20%0A%20%20%20%20%20%20%20%20%5D%2C%20%0A%20%20%20%20%20%20%20%20%22label%22%3A%20%22person%22%2C%20%0A%20%20%20%20%20%20%20%20%22confidence%22%3A%20%220.889648%22%2C%20%0A%20%20%20%20%20%20%20%20%22timestamp%22%3A%20%221622658821393258467%22%20%0A%20%20%20%20%20%20%7D%20%0A%20%20%20%20%5D%20%0A%20%20%7D%2C%20%0A%20%20%22enqueuedTime%22%3A%20%222021-06-02T18%3A33%3A41.866Z%22%20%0A%7D%3C%2FCODE%3E%3C%2FPRE%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EThis%20data%20will%20be%20paired%20up%20with%20Azure%20Digital%20Twins%20to%20yield%20real-time%20AI%20data%20visualization%20of%20real-world%20digital%20representation.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH3%20id%3D%22toc-hId-964520222%22%20id%3D%22toc-hId-964520224%22%3EAzure%20Digital%20Twins%20Setup%3C%2FH3%3E%0A%3CP%3EAzure%20Digital%20Twins%20setup%20is%20divided%20into%20two%20distinct%20parts.%3C%2FP%3E%0A%3CUL%3E%0A%3CLI%3EThe%20first%20part%20deals%20with%20the%20setup%20of%20a%20model%20for%20Azure%20Digital%20Twins.%20The%20Digital%20Twins%20Definition%20Language%20(DTDL)%20models%20are%20used%20to%20define%20the%20digital%20representation%20of%20real-world%20entities%20indicating%20their%20properties%20and%20relationships.%20The%20digital%20entities%20can%20represent%20people%2C%20places%2C%20and%20things.%20For%20more%20details%20on%20DTDL%20models%20visit%20the%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fdigital-twins%2Foverview%23open-modeling-language%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%22%3EAzure%20Digital%20Twins%20documentation.%3C%2FA%3E%3C%2FLI%3E%0A%3CLI%3EThe%20second%20part%20is%20the%20provisioning%20of%20the%20Azure%20Digital%20Twins%20instance.%3C%2FLI%3E%0A%3C%2FUL%3E%0A%3CP%3EIn%20our%20example%20scenario%20we%20developed%20a%20model%20that%20has%20two%20components.%20One%20component%20of%20the%20model%20will%20be%20the%20site%20(mentioned%20as%20%E2%80%9CPerceptSite%E2%80%9D%20in%20the%20model)%20where%20the%20exhibition%20is%20taking%20place.%20The%20second%20component%20is%20the%20model%20for%20the%20floor%20(%E2%80%9CPerceptSiteFloor%E2%80%9D)%20which%20is%20assigned%20to%20a%20particular%20exhibition%20participant.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH3%20id%3D%22toc-hId--842934241%22%20id%3D%22toc-hId--842934239%22%3EAzure%20Digital%20Twins%20Instance%20Setup%3C%2FH3%3E%0A%3CP%3EIn%20the%20following%20steps%2C%20we%20are%20using%20the%20CLI%20to%20setup%20the%20Azure%20Digital%20Twins%20instance.%20You%20can%20find%20details%20for%20this%20at%3A%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fdigital-twins%2Fhow-to-set-up-instance-cli%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%22%3ESet%20up%20an%20instance%20and%20authentication%20(CLI)%20-%20Azure%20Digital%20Twins%20%7C%20Microsoft%20Docs.%3C%2FA%3E%3C%2FP%3E%0A%3CP%3EFor%20steps%20using%20the%20Azure%20Portal%20visit%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fdigital-twins%2Fhow-to-set-up-instance-portal%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%22%3ESet%20up%20an%20instance%20and%20authentication%20(portal)%20-%20Azure%20Digital%20Twins%20%7C%20Microsoft%20Docs%3C%2FA%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CPRE%20class%3D%22lia-code-sample%20language-powershell%22%3E%3CCODE%3E%24rgname%20%3D%20%22%3CYOUR-PREFIX%3E%22%20%0A%24random%20%3D%20%22%3CYOUR-PREFIX%3E%22%20%2B%20%24(get-random%20-maximum%2010000)%20%0A%24dtname%20%3D%20%24random%20%2B%20%22-digitaltwin%22%20%0A%24location%20%3D%20%22westus2%22%20%0A%24username%20%3D%20%22%3CYOUR-USERNAME%3E%40%3CYOUR-DOMAIN%3E%22%20%0A%24functionstorage%20%3D%20%24random%20%2B%20%22storage%22%20%0A%24telemetryfunctionname%20%3D%20%24random%20%2B%20%22-telemetryfunction%22%20%0A%24twinupdatefunctionname%20%3D%20%24random%20%2B%20%22-twinupdatefunction%22%20%0A%0A%23%20Create%20resource%20group%20%0Aaz%20group%20create%20-n%20%24rgname%20-l%20%24location%20%0A%0A%23%20Create%20Azure%20Digital%20Twins%20instance%20%0Aaz%20dt%20create%20--dt-name%20%24dtname%20-g%20%24rgname%20-l%20%24location%20%0A%0A%23%20Create%20role%20assignment%20for%20user%20needed%20to%20access%20Azure%20Digital%20Twins%20instance%20%0Aaz%20dt%20role-assignment%20create%20-n%20%24dtname%20-g%20%24rgname%20--role%20%22Azure%20Digital%20Twins%20Data%20Owner%22%20--assignee%20%24username%20-o%20json%20%3C%2FYOUR-DOMAIN%3E%3C%2FYOUR-USERNAME%3E%3C%2FYOUR-PREFIX%3E%3C%2FYOUR-PREFIX%3E%3C%2FCODE%3E%3C%2FPRE%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CEM%3EModel%20Setup%20%3C%2FEM%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CPRE%20class%3D%22lia-code-sample%20language-powershell%22%3E%3CCODE%3E%24sitemodelid%20%3D%20%22dtmi%3Apercept%3ADigitalTwins%3ASite%3B1%22%20%0A%0A%23%20Creating%20Azure%20Digital%20Twins%20model%20for%20Site%20%0Aaz%20dt%20model%20delete%20--dt-name%20%24dtname%20--dtmi%20%24sitemodelid%20%0A%24sitemodelid%20%3D%20%24(az%20dt%20model%20create%20-n%20%24dtname%20--models%20.%5CSiteInterface.json%20--query%20%5B%5D.id%20-o%20tsv)%20%0A%24sitefloormodelid%20%3D%20%22dtmi%3Apercept%3ADigitalTwins%3ASiteFloor%3B1%22%20%0A%0A%23%20Creating%20Azure%20Digital%20Twins%20model%20for%20Site%20floor%20%0A%24sitefloormodelid%20%3D%20%24(az%20dt%20model%20create%20-n%20%24dtname%20--models%20.%5CSiteFloorInterface.json%20--query%20%5B%5D.id%20-o%20tsv)%20%0A%0A%23%20Creating%20twin%3A%20PerceptSite%20%0Aaz%20dt%20twin%20create%20-n%20%24dtname%20--dtmi%20%24sitemodelid%20--twin-id%20%22PerceptSite%22%20%0A%0A%23%20Creating%20twin%3A%20PerceptSiteFloor%20%0Aaz%20dt%20twin%20create%20-n%20%24dtname%20--dtmi%20%24sitefloormodelid%20--twin-id%20%22PerceptSiteFloor%22%20%0A%24relname%20%3D%20%22rel_has_floors%22%0A%0A%23%20Creating%20relationships%22%20%0Aaz%20dt%20twin%20relationship%20create%20-n%20%24dtname%20--relationship%20%24relname%20--twin-id%20%22PerceptSite%22%20--target%20%22PerceptSiteFloor%22%20--relationship-id%20%22Site%20has%20floors%22%3C%2FCODE%3E%3C%2FPRE%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EHere%20is%20how%20this%20basic%20model%20looks%20like%20once%20it%20is%20created%20on%20Azure%20Digital%20Twins%3A%3C%2FP%3E%0A%3CP%20align%3D%22center%22%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%22mnabeel_0-1626939036437.png%22%20style%3D%22width%3A%20999px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F297587i34AAB34945235363%2Fimage-size%2Flarge%3Fv%3Dv2%26amp%3Bpx%3D999%22%20role%3D%22button%22%20title%3D%22mnabeel_0-1626939036437.png%22%20alt%3D%22mnabeel_0-1626939036437.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EThe%20above%20screenshot%20is%20taken%20from%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fsamples%2Fazure-samples%2Fdigital-twins-explorer%2Fdigital-twins-explorer%2F%22%20target%3D%22_blank%22%20rel%3D%22noreferrer%20noopener%22%3EAzure%20Digital%20Twins%20Explorer%3C%2FA%3E%20view.%20Azure%20Digital%20Twins%20Explorer%20is%20a%20developer%20tool%20for%20the%20Azure%20Digital%20Twins%20service.%20It%20lets%20you%20connect%20to%20an%20Azure%20Digital%20Twins%20instance%20to%20understand%2C%20visualize%2C%20and%20modify%20your%20digital%20twin%20data.%3C%2FP%3E%0A%3CH2%20id%3D%22toc-hId--853437345%22%20id%3D%22toc-hId--853437343%22%3EFunctions%20Apps%20Setup%3C%2FH2%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH3%20id%3D%22toc-hId--162875871%22%20id%3D%22toc-hId--162875869%22%3EAzure%20Digital%20Twins%20Ingestion%20App%3C%2FH3%3E%0A%3CP%20align%3D%22center%22%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%22mnabeel_1-1626939132912.png%22%20style%3D%22width%3A%20999px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F297588i1460142833BB13FB%2Fimage-size%2Flarge%3Fv%3Dv2%26amp%3Bpx%3D999%22%20role%3D%22button%22%20title%3D%22mnabeel_1-1626939132912.png%22%20alt%3D%22mnabeel_1-1626939132912.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EThe%20Azure%20Digital%20Twins%20Ingestion%20Function%20app%20will%20receive%20updates%20from%20Azure%20IoT%20Hub%20and%20forward%20those%20updates%20to%20Azure%20Digital%20Twins.%20The%20functions%20use%20in%20the%20code%20can%20be%20found%20in%20the%20Azure.DigitalTwins.Core%20library.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EHere%20is%20the%20source%20code%20for%20the%20Azure%20Digital%20Twins%20Ingestion%20App%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CPRE%20class%3D%22lia-code-sample%20language-csharp%22%3E%3CCODE%3Enamespace%20TwinIngestionFunctionApp%20%0A%7B%20%0A%20%20%20%20using%20Azure%3B%20%0A%20%20%20%20using%20Azure.Core.Pipeline%3B%20%0A%20%20%20%20using%20Azure.DigitalTwins.Core%3B%20%0A%20%20%20%20using%20Azure.Identity%3B%20%0A%20%20%20%20using%20Microsoft.Azure.EventHubs%3B%20%0A%20%20%20%20using%20Microsoft.Azure.WebJobs%3B%20%0A%20%20%20%20using%20Microsoft.Extensions.Logging%3B%20%0A%20%20%20%20using%20Newtonsoft.Json%3B%20%0A%20%20%20%20using%20Newtonsoft.Json.Linq%3B%20%0A%20%20%20%20using%20System%3B%20%0A%20%20%20%20using%20System.Net.Http%3B%20%0A%20%20%20%20using%20System.Text%3B%20%0A%20%20%20%20using%20IoTHubTrigger%20%3D%20Microsoft.Azure.WebJobs.EventHubTriggerAttribute%3B%20%0A%0A%20%0A%20%20%20%20public%20class%20TwinsFunction%20%0A%20%20%20%20%7B%20%0A%20%20%20%20%20%20%20%20private%20static%20readonly%20string%20adtInstanceUrl%20%3D%20Environment.GetEnvironmentVariable(%22ADT_SERVICE_URL%22)%3B%20%0A%20%20%20%20%20%20%20%20private%20static%20HttpClient%20httpClient%20%3D%20new%20HttpClient()%3B%20%0A%0A%20%0A%20%20%20%20%20%20%20%20%5BFunctionName(%22TwinsFunction%22)%5D%20%0A%20%20%20%20%20%20%20%20public%20async%20void%20Run(%5BIoTHubTrigger(%22messages%2Fevents%22%2C%20Connection%20%3D%20%22EventHubConnectionString%22)%5D%20EventData%20message%2C%20ILogger%20log)%20%0A%20%20%20%20%20%20%20%20%7B%20%0A%0A%20%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(adtInstanceUrl%20%3D%3D%20null)%20log.LogError(%22Application%20setting%20%5C%22ADT_SERVICE_URL%5C%22%20not%20set%22)%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2FAuthenticate%20with%20Digital%20Twins%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20ManagedIdentityCredential%20cred%20%3D%20new%20ManagedIdentityCredential(%22https%3A%2F%2Fdigitaltwins.azure.net%22)%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20DigitalTwinsClient%20client%20%3D%20new%20DigitalTwinsClient(new%20Uri(adtInstanceUrl)%2C%20cred%2C%20new%20DigitalTwinsClientOptions%20%7B%20Transport%20%3D%20new%20HttpClientTransport(httpClient)%20%7D)%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(message%20!%3D%20null%20%26amp%3B%26amp%3B%20message.Body%20!%3D%20null)%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%20%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20log.LogInformation(Encoding.UTF8.GetString(message.Body.Array))%3B%20%0A%0A%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%2F%20Reading%20AI%20data%20for%20IoT%20Hub%20JSON%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20JObject%20deviceMessage%20%3D%20(JObject)JsonConvert.DeserializeObject(Encoding.UTF8.GetString(message.Body.Array))%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20string%20label%20%3D%20deviceMessage%5B%22NEURAL_NETWORK%22%5D%5B0%5D%5B%22label%22%5D.ToString()%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20string%20confidence%20%3D%20deviceMessage%5B%22NEURAL_NETWORK%22%5D%5B0%5D%5B%22confidence%22%5D.ToString()%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20string%20timestamp%20%3D%20deviceMessage%5B%22NEURAL_NETWORK%22%5D%5B0%5D%5B%22timestamp%22%5D.ToString()%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if(!(string.IsNullOrEmpty(label)%20%26amp%3B%26amp%3B%20string.IsNullOrEmpty(confidence)%20%26amp%3B%26amp%3B%20string.IsNullOrEmpty(timestamp)))%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20var%20updateTwinData%20%3D%20new%20JsonPatchDocument()%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20updateTwinData.AppendAdd(%22%2FLabel%22%2C%20label)%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20updateTwinData.AppendAdd(%22%2FConfidence%22%2C%20confidence)%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20updateTwinData.AppendAdd(%22%2Ftimestamp%22%2C%20timestamp)%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20await%20client.UpdateDigitalTwinAsync(%22PerceptSiteFloor%22%2C%20updateTwinData)%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20log.LogInformation(%24%22Updated%20Device%3A%20PerceptSiteFloor%20with%20%7B%20updateTwinData%7D%20at%3A%20%7BDateTime.Now.ToString()%7D%22)%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20catch%20(Exception%20e)%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20log.LogError(e.Message)%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20%0A%0A%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20%0A%20%20%20%20%20%20%20%20%7D%20%0A%20%20%20%20%7D%20%0A%7D%20%3C%2FCODE%3E%3C%2FPRE%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EHere%20is%20the%20video%20that%20shows%20how%20the%20inference%20data%20from%20Azure%20Percept%20is%20being%20received%20by%20Azure%20Digital%20Twins%20instance%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CDIV%20style%3D%22position%3A%20relative%3B%20left%3A%2012.5%25%3B%20padding-bottom%3A%2042.3%25%3B%20padding-top%3A%200px%3B%20height%3A%200%3B%20overflow%3A%20hidden%3B%20min-width%3A%20320px%3B%20max-width%3A%2075%25%3B%22%3E%3CIFRAME%20src%3D%22https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FxCfVnBlp9uE%3Fcontrols%3D0%26amp%3Bautoplay%3Dfalse%26amp%3BWT.mc_id%3Diot-c9-niner%22%20frameborder%3D%220%22%20allowfullscreen%3D%22allowfullscreen%22%20style%3D%22position%3A%20absolute%3B%20top%3A%200%3B%20left%3A%200%3B%20width%3A%20100%25%3B%20height%3A%20100%25%3B%22%20class%3D%22video-iframe%22%20title%3D%22Video%20showing%20how%20the%20inference%20data%20from%20Azure%20Percept%20is%20being%20received%20by%20Azure%20Digital%20Twins%22%3E%3C%2FIFRAME%3E%3C%2FDIV%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH2%20id%3D%22toc-hId--173378975%22%20id%3D%22toc-hId--173378973%22%3EPublishing%20messages%20from%20Azure%20Digital%20Twins%20to%20Event%20Hub%3C%2FH2%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EIn%20the%20previous%20sections%20we%20have%20seen%20how%20the%20messages%20from%20Azure%20Percept%20are%20forwarded%20to%20Azure%20Digital%20Twins%20through%20Azure%20IoT%20Hub%20using%20an%20Azure%20Function.%20In%20this%20section%20we%20will%20see%20how%20to%20prepare%20the%20Azure%20Digital%20Twins%20instance%20to%20send%20messages%20to%20Event%20Hub.%20This%20involves%20the%20following%3A%3C%2FP%3E%0A%3CUL%3E%0A%3CLI%3ESetting%20up%20Event%20Hub%3C%2FLI%3E%0A%3CLI%3ESetting%20up%20Azure%20Digital%20Twins%20to%20send%20messages%20to%20Event%20Hub.%3C%2FLI%3E%0A%3C%2FUL%3E%0A%3CH3%20id%3D%22toc-hId-517182499%22%20id%3D%22toc-hId-517182501%22%3ESetting%20up%20Event%20Hub%3C%2FH3%3E%0A%3CP%3EThe%20setting%20up%20of%20the%20Event%20Hub%20involves%20creating%20an%20Event%20Hub%20Namespace%20and%20creating%20an%20Event%20Hub.%3C%2FP%3E%0A%3CP%3ETo%20create%20Event%20Hub%20Namespace%20refer%20to%20details%20mentioned%20at%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fevent-hubs%2Fevent-hubs-create%23create-an-event-hubs-namespace%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%22%3EAzure%20Quickstart%20-%20Create%20an%20event%20hub%20using%20the%20Azure%20portal%20-%20Azure%20Event%20Hubs%20%7C%20Microsoft%20Docs%3C%2FA%3E%3C%2FP%3E%0A%3CP%3ETo%20create%20Event%20Hub%20refer%20to%20details%20mentioned%20at%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fevent-hubs%2Fevent-hubs-create%23create-an-event-hubs-namespace%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%22%3EAzure%20Quickstart%20-%20Create%20an%20event%20hub%20using%20the%20Azure%20portal%20-%20Azure%20Event%20Hubs%20%7C%20Microsoft%20Docs%3C%2FA%3E%3C%2FP%3E%0A%3CP%3EOnce%20the%20Event%20Hub%20is%20created%2C%20we%20can%20proceed%20to%20set%20up%20the%20route%20from%20Azure%20Digital%20Twins.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH3%20id%3D%22toc-hId--1290271964%22%20id%3D%22toc-hId--1290271962%22%3ESetting%20up%20Azure%20Digital%20Twins%20to%20send%20messages%20to%20Event%20Hub%3C%2FH3%3E%0A%3CP%3EUse%20the%20following%20steps%20to%20setup%20Azure%20Digital%20Twins%20to%20send%20messages%20to%20Event%20Hub%3A%3C%2FP%3E%0A%3COL%3E%0A%3CLI%3ECreate%20Azure%20Digital%20Twins%20Endpoint%3C%2FLI%3E%0A%3CLI%3ECreate%20Azure%20Digital%20Twins%20Event%20Route%3C%2FLI%3E%0A%3C%2FOL%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CI%3ECreate%20Azure%20Digital%20Twins%20Endpoint%3C%2FI%3E%3C%2FP%3E%0A%3CP%3EFor%20this%20step%20will%20be%20using%20the%20Event%20Hub%20Namespace%20and%20Event%20Hub%20that%20was%20created%20in%20previous%20steps.%3C%2FP%3E%0A%3CP%3EFollowing%20image%20illustrates%20the%20details%20of%20creating%20an%20Azure%20Digital%20Twins%20Endpoint%3A%3C%2FP%3E%0A%3CP%20align%3D%22center%22%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%22mnabeel_2-1626939490703.png%22%20style%3D%22width%3A%20999px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F297589i7FE5E91D43DA71E5%2Fimage-size%2Flarge%3Fv%3Dv2%26amp%3Bpx%3D999%22%20role%3D%22button%22%20title%3D%22mnabeel_2-1626939490703.png%22%20alt%3D%22mnabeel_2-1626939490703.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CI%3ECreate%20Azure%20Digital%20Twins%20Event%20Route%3C%2FI%3E%3C%2FP%3E%0A%3CP%3EThe%20following%20image%20illustrates%20the%20details%20of%20creating%20an%20Azure%20Digital%20Twins%20Event%20Route%3A%3C%2FP%3E%0A%3CP%20align%3D%22center%22%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%22mnabeel_3-1626939550331.png%22%20style%3D%22width%3A%20999px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F297591iED1A28CA64F5A986%2Fimage-size%2Flarge%3Fv%3Dv2%26amp%3Bpx%3D999%22%20role%3D%22button%22%20title%3D%22mnabeel_3-1626939550331.png%22%20alt%3D%22mnabeel_3-1626939550331.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3EThe%20above%20steps%20will%20result%20in%20our%20Azure%20Digital%20Twins%20instance%20routing%20messages%20to%20our%20Event%20hub.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH2%20id%3D%22toc-hId-372994671%22%20id%3D%22toc-hId-372994673%22%3EAzure%20Digital%20Twins%20Update%20App%3C%2FH2%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EThe%20previous%20sections%20explained%20the%20steps%20to%20receive%20messages%20from%20Azure%20Percept%20to%20Event%20Hub%20using%20Azure%20IoT%20Hub%20and%20Azure%20Digital%20Twins.%20In%20this%20section%20we%20focus%20on%20the%20Azure%20function%20that%20will%20be%20receiving%20events%20from%20Event%20Hub.%20These%20events%20are%20showing%20the%20updates%20that%20Azure%20Digital%20Twins%20instance%20is%20receiving.%3C%2FP%3E%0A%3CP%20align%3D%22center%22%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%22mnabeel_4-1626939622770.png%22%20style%3D%22width%3A%20999px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F297592i4E71AB672EE0FCCA%2Fimage-size%2Flarge%3Fv%3Dv2%26amp%3Bpx%3D999%22%20role%3D%22button%22%20title%3D%22mnabeel_4-1626939622770.png%22%20alt%3D%22mnabeel_4-1626939622770.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3EThe%20purpose%20of%20Azure%20Function%20for%20receiving%20Azure%20Digital%20Twins%20updates%20through%20Event%20Hub%20is%20to%20create%20a%20source%20for%20any%20further%20processing.%20For%20example%2C%20this%20can%20be%20a%20source%20for%203d%20modeling%20platform%20or%20an%20API%20backend.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EHere%20is%20the%20source%20code%20for%20the%20Azure%20Function%20that%20processes%20the%20Event%20Hub%20events%20coming%20from%20Azure%20Digital%20Twins%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CPRE%20class%3D%22lia-code-sample%20language-csharp%22%3E%3CCODE%3Enamespace%20TwinsUpdateFunctionApp%20%0A%7B%20%0A%20%20%20%20using%20System%3B%20%0A%20%20%20%20using%20System.Collections.Generic%3B%20%0A%20%20%20%20using%20System.Linq%3B%20%0A%20%20%20%20using%20System.Net.Http%3B%20%0A%20%20%20%20using%20System.Text%3B%20%0A%20%20%20%20using%20System.Threading.Tasks%3B%20%0A%20%20%20%20using%20Microsoft.Azure.EventHubs%3B%20%0A%20%20%20%20using%20Microsoft.Azure.WebJobs%3B%20%0A%20%20%20%20using%20Microsoft.Extensions.Logging%3B%20%0A%20%20%20%20using%20Newtonsoft.Json%3B%20%0A%20%20%20%20using%20Newtonsoft.Json.Linq%3B%20%0A%20%20%20%20using%20TwinsUpdateFunctionApp.model%3B%20%0A%20%0A%20%20%20%20public%20static%20class%20TwinsUpdateFunction%20%0A%20%20%20%20%7B%20%0A%20%20%20%20%20%20%20%20private%20static%20readonly%20string%20twinReceiverUrl%20%3D%20Environment.GetEnvironmentVariable(%22TWINS_RECEIVER_URL%22)%3B%20%0A%0A%20%20%20%20%20%20%20%20%5BFunctionName(%22TwinsUpdateFunction%22)%5D%20%0A%20%20%20%20%20%20%20%20public%20static%20async%20Task%20Run(%5BEventHubTrigger(%22%5Byour-digitaltwin-eventhub%5D%22%2C%20Connection%20%3D%20%22EventHubConnectionString%22)%5D%20EventData%5B%5D%20events%2C%20ILogger%20log)%20%0A%20%20%20%20%20%20%20%20%7B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20exceptions%20%3D%20new%20List%3CEXCEPTION%3E()%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20List%3CTWINUPDATE%3E%20twinUpdates%20%3D%20new%20List%3CTWINUPDATE%3E()%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20foreach%20(EventData%20eventData%20in%20events)%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%7B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20string%20messageBody%20%3D%20Encoding.UTF8.GetString(eventData.Body.Array%2C%20eventData.Body.Offset%2C%20eventData.Body.Count)%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20JObject%20twinMessage%20%3D%20(JObject)JsonConvert.DeserializeObject(messageBody)%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(twinMessage%5B%22patch%22%5D%20!%3D%20null)%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20TwinUpdate%20twinUpdate%20%3D%20new%20TwinUpdate()%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20twinUpdate.ModelId%20%3D%20twinMessage%5B%22modelId%22%5D.ToString()%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20foreach%20(JToken%20jToken%20in%20twinMessage%5B%22patch%22%5D)%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(jToken%5B%22path%22%5D.ToString().Equals(%22%2FFloorId%22%2C%20StringComparison.InvariantCultureIgnoreCase))%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20twinUpdate.Floor%20%3D%20jToken%5B%22value%22%5D.ToString()%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(jToken%5B%22path%22%5D.ToString().Equals(%22%2FFloorName%22%2C%20StringComparison.InvariantCultureIgnoreCase))%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20twinUpdate.FloorName%20%3D%20jToken%5B%22value%22%5D.ToString()%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(jToken%5B%22path%22%5D.ToString().Equals(%22%2FLabel%22%2C%20StringComparison.InvariantCultureIgnoreCase))%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20twinUpdate.Label%20%3D%20jToken%5B%22value%22%5D.ToString()%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(jToken%5B%22path%22%5D.ToString().Equals(%22%2FConfidence%22%2C%20StringComparison.InvariantCultureIgnoreCase))%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20twinUpdate.Confidence%20%3D%20jToken%5B%22value%22%5D.ToString()%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20(jToken%5B%22path%22%5D.ToString().Equals(%22%2Ftimestamp%22%2C%20StringComparison.InvariantCultureIgnoreCase))%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20twinUpdate.Timestamp%20%3D%20jToken%5B%22value%22%5D.ToString()%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20%0A%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20using%20(HttpClient%20httpClient%20%3D%20new%20HttpClient())%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20var%20requestURl%20%3D%20new%20Uri(%24%22%7BtwinReceiverUrl%7D%3Flabel%3D%7BtwinUpdate.Label%7D%26amp%3Bconfidence%3D%7BtwinUpdate.Confidence%7D%26amp%3Btimestamp%3D%7BtwinUpdate.Timestamp%7D%26amp%3BfloorId%3D%7BtwinUpdate.Floor%7D%26amp%3BfloorName%3D%7BtwinUpdate.FloorName%7D%22)%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20StringContent%20queryString%20%3D%20new%20StringContent(messageBody)%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20var%20response%20%3D%20httpClient.PostAsync(requestURl%2C%20queryString).Result%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20%0A%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20twinUpdates.Add(twinUpdate)%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20await%20Task.Yield()%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20catch%20(Exception%20e)%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20exceptions.Add(e)%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20%0A%20%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(exceptions.Count%20%26gt%3B%201)%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20throw%20new%20AggregateException(exceptions)%3B%20%0A%0A%20%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20(exceptions.Count%20%3D%3D%201)%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20throw%20exceptions.Single()%3B%20%0A%20%20%20%20%20%20%20%20%7D%20%0A%20%20%20%20%7D%20%0A%7D%20%3C%2FTWINUPDATE%3E%3C%2FTWINUPDATE%3E%3C%2FEXCEPTION%3E%3C%2FCODE%3E%3C%2FPRE%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EThe%20above-mentioned%20code%20represents%20an%20Azure%20Function%20that%20is%20triggered%20by%20EventHubTrigger.%20After%20deserializing%20the%20data%20received%20from%20the%20Digital%20Twins%20update%2C%20the%20Azure%20function%20posts%20update%20to%20a%20%3CA%20class%3D%22Hyperlink%20SCXW203015753%20BCX8%22%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Faspnet%2Fsignalr%2Foverview%2Fgetting-started%2Fintroduction-to-signalr%22%20target%3D%22_blank%22%20rel%3D%22noreferrer%20noopener%22%3ESignalR%3C%2FA%3E%20front-end%20application%20using%20the%20following%20code%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CPRE%20class%3D%22lia-code-sample%20language-csharp%22%3E%3CCODE%3E%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20using%20(HttpClient%20httpClient%20%3D%20new%20HttpClient())%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20var%20requestURl%20%3D%20new%20Uri(%24%22%7BtwinReceiverUrl%7D%3Flabel%3D%7BtwinUpdate.Label%7D%26amp%3Bconfidence%3D%7BtwinUpdate.Confidence%7D%26amp%3Btimestamp%3D%7BtwinUpdate.Timestamp%7D%26amp%3BfloorId%3D%7BtwinUpdate.Floor%7D%26amp%3BfloorName%3D%7BtwinUpdate.FloorName%7D%22)%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20StringContent%20queryString%20%3D%20new%20StringContent(messageBody)%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20var%20response%20%3D%20httpClient.PostAsync(requestURl%2C%20queryString).Result%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%20%3C%2FCODE%3E%3C%2FPRE%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH2%20id%3D%22toc-hId--1434459792%22%20id%3D%22toc-hId--1434459790%22%3EFront-end%20Dashboard%20App%3C%2FH2%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EThe%20last%20and%20the%20most%20important%20piece%20of%20our%20architecture%20is%20the%20front-end%20Dashboard%20app%20that%20will%20be%20used%20to%20visualize%20the%20Azure%20Data%20Twins%20updates.%20This%20is%20where%20the%20value%20of%20combing%20Azure%20Percept%20and%20Azure%20Digital%20Twins%20is%20revealed.%20Any%20front-end%20platforms%20can%20be%20used%20for%20this%20part%20depending%20on%20the%20requirements%20and%20constraints.%20To%20demonstrate%20the%20Front-end%20Dashboard%20App%2C%20we%20are%20using%20a%20SignalR%20based%20application%20with%20a%20single%20page.%20SignalR%20allows%20to%20make%20Web%20pages%20more%20dynamic%2C%20offering%20an%20eventing%20mecanism%20from%20server%20to%20client.%20Here%20is%20a%20link%20to%20a%20great%20tutorial%20on%20SignalR%3A%20%3CA%20href%3D%22https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Faspnet%2Fcore%2Ftutorials%2Fsignalr%3Fview%3Daspnetcore-5.0%26amp%3Btabs%3Dvisual-studio%22%20target%3D%22_blank%22%20rel%3D%22noopener%20noreferrer%22%3EGet%20started%20with%20ASP.NET%20Core%20SignalR%20%7C%20Microsoft%20Docs%3C%2FA%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EOnce%20the%20Dashboard%20App%20receives%20the%20data%20it%20automatically%20updates%20its%20view.%20The%20view%20contains%20a%20top%20section%20showing%20the%20%E2%80%9CData%20visualization%20through%20Azure%20Digital%20Twins%20updates%20and%20a%20bottom%20section%20showing%20the%20%E2%80%9CRaw%20Azure%20Digital%20Twins%20updates%E2%80%9D.%20The%20top%20section%20is%20an%20example%20of%20how%20you%20can%20present%20the%20data%20visualization%20on%20a%20view%20using%20the%20raw%20data%20mentioned%20on%20the%20bottom%20section.%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%20align%3D%22center%22%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%22mnabeel_0-1626940171467.png%22%20style%3D%22width%3A%20999px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F297593iB1C61A2948A6F4FC%2Fimage-size%2Flarge%3Fv%3Dv2%26amp%3Bpx%3D999%22%20role%3D%22button%22%20title%3D%22mnabeel_0-1626940171467.png%22%20alt%3D%22mnabeel_0-1626940171467.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3EFor%20our%20example%20we%20had%20two%20use%20cases%20representing%20compliant%20and%20non-compliant%20objects%20detection.%20Here%20is%20how%20the%20data%20visualization%20on%20the%20front-end%20app%20will%20look%20like%20for%20compliant%20and%20non-compliant%20objects%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH3%20id%3D%22toc-hId-1182135760%22%20id%3D%22toc-hId-1182135762%22%3ECompliant%20object%20detection%3A%3C%2FH3%3E%0A%3CP%20align%3D%22center%22%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%22mnabeel_1-1626940252929.png%22%20style%3D%22width%3A%20999px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F297594i3B919436115E1E88%2Fimage-size%2Flarge%3Fv%3Dv2%26amp%3Bpx%3D999%22%20role%3D%22button%22%20title%3D%22mnabeel_1-1626940252929.png%22%20alt%3D%22mnabeel_1-1626940252929.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH3%20id%3D%22toc-hId--625318703%22%20id%3D%22toc-hId--625318701%22%3ENon-compliant%20object%20detection%3A%3C%2FH3%3E%0A%3CP%20align%3D%22center%22%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%22mnabeel_2-1626940316304.png%22%20style%3D%22width%3A%20999px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F297595i11CED0517433CF10%2Fimage-size%2Flarge%3Fv%3Dv2%26amp%3Bpx%3D999%22%20role%3D%22button%22%20title%3D%22mnabeel_2-1626940316304.png%22%20alt%3D%22mnabeel_2-1626940316304.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3EThe%20source%20code%20for%20the%20example%20that%20we%20have%20used%20for%20data%20visualization%20can%20be%20found%20at%3A%20%3CA%20class%3D%22Hyperlink%20SCXW105434683%20BCX8%22%20href%3D%22https%3A%2F%2Faka.ms%2FAAd96fy%22%20target%3D%22_blank%22%20rel%3D%22noreferrer%20noopener%22%3Ehttps%3A%2F%2Faka.ms%2FAAd96fy%3C%2FA%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH2%20id%3D%22toc-hId-1733111411%22%20id%3D%22toc-hId-1733111413%22%3EConclusion%3C%2FH2%3E%0A%3CP%3EAzure%20Percept%20and%20Azure%20Digital%20Twins%20are%20two%20distinct%20Azure%20services%20that%20are%20built%20to%20provide%20unique%20values.%20In%20this%20post%20we%20have%20seen%20how%20real-time%20AI%20with%20Azure%20Percept%20can%20be%20combined%20with%20the%20real-word%20digital%20representations%20of%20Azure%20Digital%20Twins%20to%20derive%20pertinent%20data%20visualization%20using%20real-time%20intelligence.%20This%20post%20has%20shown%20how%20simple%20it%20is%20to%20combine%20both%20technologies%20to%20achieve%20data%20visualization%20that%20we%20need.%3C%2FP%3E%0A%3CP%3EHere%20is%20what%20the%20final%20application%20looks%20like%3A%3C%2FP%3E%0A%3CH3%20id%3D%22toc-hId-54739667%22%20id%3D%22toc-hId-54739669%22%3ECompliant%20use%20case%3C%2FH3%3E%0A%3CP%20align%3D%22center%22%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%22mnabeel_3-1626940471402.png%22%20style%3D%22width%3A%20999px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F297596i81D8AEC953009B65%2Fimage-size%2Flarge%3Fv%3Dv2%26amp%3Bpx%3D999%22%20role%3D%22button%22%20title%3D%22mnabeel_3-1626940471402.png%22%20alt%3D%22mnabeel_3-1626940471402.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CH3%20id%3D%22toc-hId--1752714796%22%20id%3D%22toc-hId--1752714794%22%3ENon-compliant%20use%20case%3C%2FH3%3E%0A%3CP%20align%3D%22center%22%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%22mnabeel_4-1626940546176.png%22%20style%3D%22width%3A%20999px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F297597i36820FBB9F6B7920%2Fimage-size%2Flarge%3Fv%3Dv2%26amp%3Bpx%3D999%22%20role%3D%22button%22%20title%3D%22mnabeel_4-1626940546176.png%22%20alt%3D%22mnabeel_4-1626940546176.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3EFollowing%20video%20shows%20how%20Azure%20Percept%20is%20running%20AI%20on%20edge%20to%20identify%20objects%20and%20then%20how%20the%20Front-end%20Dashboard%20App%20displays%20the%20update%20flowing%20from%20Azure%20Digital%20Twins%3A%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CDIV%20style%3D%22position%3A%20relative%3B%20left%3A%2012.5%25%3B%20padding-bottom%3A%2042.3%25%3B%20padding-top%3A%200px%3B%20height%3A%200%3B%20overflow%3A%20hidden%3B%20min-width%3A%20320px%3B%20max-width%3A%2075%25%3B%22%3E%3CIFRAME%20src%3D%22https%3A%2F%2Fwww.youtube-nocookie.com%2Fembed%2FdPw9xI35AA0%3Fcontrols%3D0%26amp%3Bautoplay%3Dfalse%26amp%3BWT.mc_id%3Diot-c9-niner%22%20frameborder%3D%220%22%20allowfullscreen%3D%22allowfullscreen%22%20style%3D%22position%3A%20absolute%3B%20top%3A%200%3B%20left%3A%200%3B%20width%3A%20100%25%3B%20height%3A%20100%25%3B%22%20class%3D%22video-iframe%22%20title%3D%22Video%20showing%20how%20Azure%20Percept%20is%20running%20AI%20on%20the%20edge%20to%20identify%20objects%20and%20then%20how%20the%20Front-end%20Dashboard%20App%20displays%20the%20update%20flowing%20from%20Azure%20Digital%20Twins%22%3E%3C%2FIFRAME%3E%3C%2FDIV%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3ELet%20us%20know%20what%20you%20think%20commenting%20below%20and%20to%20stay%20informed%2C%20subscribe%20to%20our%20post%20here%20and%20follow%20us%20on%20Twitter%20%3CA%20href%3D%22https%3A%2F%2Ftwitter.com%2Fmicrosoftiot%22%20target%3D%22_blank%22%20rel%3D%22noopener%20nofollow%20noreferrer%22%3E%40MicrosoftIoT%3C%2FA%3E%20.%3C%2FP%3E%3C%2FLINGO-BODY%3E%3CLINGO-TEASER%20id%3D%22lingo-teaser-2574104%22%20slang%3D%22en-US%22%3E%3CP%3E%3CSPAN%20class%3D%22lia-inline-image-display-wrapper%20lia-image-align-inline%22%20image-alt%3D%22mnabeel_34-1626934435585.png%22%20style%3D%22width%3A%20999px%3B%22%3E%3CIMG%20src%3D%22https%3A%2F%2Ftechcommunity.microsoft.com%2Ft5%2Fimage%2Fserverpage%2Fimage-id%2F297567iD2C0CCE1BACCA3C6%2Fimage-size%2Flarge%3Fv%3Dv2%26amp%3Bpx%3D999%22%20role%3D%22button%22%20title%3D%22mnabeel_34-1626934435585.png%22%20alt%3D%22mnabeel_34-1626934435585.png%22%20%2F%3E%3C%2FSPAN%3E%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%26nbsp%3B%3C%2FP%3E%0A%3CP%3E%3CSPAN%20class%3D%22NormalTextRun%20CommentStart%20%20BCX8%20SCXW3198432%22%3EDeriving%3C%2FSPAN%3E%3CSPAN%20class%3D%22NormalTextRun%20CommentStart%20%20BCX8%20SCXW3198432%22%3E%3CSPAN%3E%26nbsp%3B%3C%2FSPAN%3E%3C%2FSPAN%3E%3CSPAN%20class%3D%22NormalTextRun%20%20BCX8%20SCXW3198432%22%3Ereal-time%3CSPAN%3E%26nbsp%3B%3C%2FSPAN%3E%3C%2FSPAN%3E%3CSPAN%20class%3D%22NormalTextRun%20%20BCX8%20SCXW3198432%22%3Eintelligence%3CSPAN%3E%26nbsp%3B%3C%2FSPAN%3E%3C%2FSPAN%3E%3CSPAN%20class%3D%22NormalTextRun%20%20BCX8%20SCXW3198432%22%3Eabout%20the%20physical%20world%3CSPAN%3E%26nbsp%3B%3C%2FSPAN%3E%3C%2FSPAN%3E%3CSPAN%20class%3D%22NormalTextRun%20%20BCX8%20SCXW3198432%22%3Ewith%3C%2FSPAN%3E%3CSPAN%20class%3D%22NormalTextRun%20%20BCX8%20SCXW3198432%22%3E%3CSPAN%3E%26nbsp%3B%3C%2FSPAN%3EAzure%20Percept%3C%2FSPAN%3E%3CSPAN%20class%3D%22NormalTextRun%20%20BCX8%20SCXW3198432%22%3E%3CSPAN%3E%26nbsp%3B%3C%2FSPAN%3Ean%3C%2FSPAN%3E%3CSPAN%20class%3D%22NormalTextRun%20%20BCX8%20SCXW3198432%22%3Ed%3C%2FSPAN%3E%3CSPAN%20class%3D%22NormalTextRun%20%20BCX8%20SCXW3198432%22%3E%3CSPAN%3E%26nbsp%3B%3C%2FSPAN%3EAzure%20Digital%20Twins.%3C%2FSPAN%3E%3C%2FP%3E%3C%2FLINGO-TEASER%3E%3CLINGO-LABS%20id%3D%22lingo-labs-2574104%22%20slang%3D%22en-US%22%3E%3CLINGO-LABEL%3EAzure%20Digital%20Twins%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3EAzure%20IoT%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3EAzure%20IoT%20Edge%3C%2FLINGO-LABEL%3E%3CLINGO-LABEL%3EAzure%20Percept%3C%2FLINGO-LABEL%3E%3C%2FLINGO-LABS%3E
Co-Authors
Version history
Last update:
‎Jul 26 2021 10:25 AM