Set up twin-to-twin event handling
This article shows how to send events from twin to twin, so that when one digital twin in the graph is updated, related twins in the graph that are affected by this information can also update. This event handling will help you create a fully connected Azure Digital Twins graph, where data that arrives into Azure Digital Twins from external sources like IoT Hub is propagated through the entire graph.
To set up this twin-to-twin event handling, you'll create an Azure function that watches for twin life-cycle events. The function recognizes which events should affect other twins in the graph, and uses the event data to update the affected twins accordingly.
To set up twin-to-twin handling, you'll need an Azure Digital Twins instance to work with. For instructions on how to create an instance, see Set up an Azure Digital Twins instance and authentication. The instance should contain at least two twins that you want to send data between.
Optionally, you may want to set up automatic telemetry ingestion through IoT Hub for your twins as well. This process isn't required to send data from twin to twin, but it's an important piece of a complete solution where the twin graph is driven by live telemetry.
Send twin events to an endpoint
To set up twin-to-twin event handling, start by creating an endpoint in Azure Digital Twins and a route to that endpoint. Twins undergoing an update will use the route to send information about their update events to the endpoint (where Event Grid can pick them up later and pass them to an Azure function for processing).
Create the Event Grid topic
Event Grid is an Azure service that helps route and deliver events from Azure services to other places within Azure. You can create an Event Grid topic to collect certain events from a source, and then subscribers can listen on the topic to receive the events as they come through.
In the Azure CLI, run the following command to create an Event Grid topic:
az eventgrid topic create --resource-group <your-resource-group> --name <name-for-your-event-grid-topic> --location <region>
The output from this command is information about the Event Grid topic you've created. Save the name that you gave to your Event Grid topic, because you'll use it later.
Create the endpoint
Next, create an Event Grid endpoint in Azure Digital Twins, which will connect your instance to your Event Grid topic. Use the command below, filling in the name of your Event Grid topic from the previous step and the other placeholder fields as needed.
az dt endpoint create eventgrid --dt-name <Azure-Digital-Twins-instance> --eventgrid-resource-group <your-resource-group> --eventgrid-topic <your-event-grid-topic> --endpoint-name <name-for-your-Azure-Digital-Twins-endpoint>
The output from this command is information about the endpoint you've created.
Look for the
provisioningState field in the output, and check that the value is "Succeeded."
It may also say "Provisioning", meaning that the endpoint is still being created. If so, wait a few seconds and run the following command to check the status of the endpoint. Repeat until the
provisioningState shows "Succeeded."
az dt endpoint show --dt-name <your-Azure-Digital-Twins-instance> --endpoint-name <your-Azure-Digital-Twins-endpoint>
Save the name of your endpoint, because you'll use it later.
Create the route
Next, create an Azure Digital Twins route that sends events to the Event Grid endpoint you created.
Use the following CLI command, filling in the name of your endpoint from the previous step and the other placeholder fields as needed. This command forwards all events that occur in the twin graph.
You can limit the events to only specific ones if you want, by using filters.
az dt route create --dt-name <your-Azure-Digital-Twins-instance> --endpoint-name <your-Azure-Digital-Twins-endpoint> --route-name <name-for-your-Azure-Digital-Twins-route>
The output from this command is some information about the route you've created.
Endpoints (from the previous step) must be finished provisioning before you can set up an event route that uses them. If the route creation fails because the endpoints aren't ready, wait a few minutes and then try again.
Create Azure function to update twins
Next, create an Azure function that will listen on the endpoint and receive twin events that are sent there via the route. The logic of the function should use the information in the events to determine what other twins need to be updated and then perform the updates.
First, create a new Azure Functions project.
You can do this using Visual Studio (for instructions, see Develop Azure Functions using Visual Studio), Visual Studio Code (for instructions, see Create a C# function in Azure using Visual Studio Code), or the Azure CLI (for instructions, see Create a C# function in Azure from the command line).
Add the following packages to your project (you can use the Visual Studio NuGet package manager, or the dotnet add package command in a command-line tool).
Fill in the logic of your function. You can view sample function code for several scenarios in the azure-digital-twins-getting-started repository to help you get started.
Publish the function to Azure, using your preferred method.
For instructions on how to publish the function using Visual Studio, see Develop Azure Functions using Visual Studio. For instructions on how to publish the function using Visual Studio Code, see Create a C# function in Azure using Visual Studio Code. For instructions on how to publish the function using the Azure CLI, see Create a C# function in Azure from the command line.
Once the process of publishing the function completes, you can use this Azure CLI command to verify the publish was successful. There are placeholders for your resource group, the name of your function app, and the name of your specific function. The command will print information about your function.
az functionapp function show --resource-group <your-resource-group> --name <your-function-app> --function-name <your-function>
Configure the function app
Before your function can access Azure Digital Twins, it needs some information about the instance and permission to access it. In this section, you'll assign an access role for the function and configure the application settings so that it can find and access the instance.
This section must be completed by an Azure user who has permissions to manage user access to Azure resources, including granting and delegating permissions. Common roles that meet this requirement are Owner, Account admin, or the combination of User Access Administrator and Contributor. For more information about permission requirements for Azure Digital Twins roles, see Set up an instance and authentication.
Assign an access role
The Azure function requires a bearer token to be passed to it. To make sure the bearer token is passed, grant the function app the Azure Digital Twins Data Owner role for your Azure Digital Twins instance, which will give the function app permission to perform data plane activities on the instance.
Use the following command to create a system-managed identity for your function (if the function already has one, this command will print its details). Take note of the
principalIdfield in the output. You'll use this ID to refer to the function so that you can grant it permissions in the next step.
az functionapp identity assign --resource-group <your-resource-group> --name <your-function-app-name>
principalIdvalue in the following command to give the function the Azure Digital Twins Data Owner role for your Azure Digital Twins instance.
az dt role-assignment create --dt-name <your-Azure-Digital-Twins-instance> --assignee "<principal-ID>" --role "Azure Digital Twins Data Owner"
Configure application settings
Next, make the URL of your Azure Digital Twins instance accessible to your function by setting an environment variable for it.
The Azure Digital Twins instance's URL is made by adding https:// to the beginning of your instance's host name. To see the host name, along with all the properties of your instance, run
az dt show --dt-name <your-Azure-Digital-Twins-instance>.
The following command sets an environment variable for your instance's URL that your function will use whenever it needs to access the instance.
az functionapp config appsettings set --resource-group <your-resource-group> --name <your-function-app-name> --settings "ADT_SERVICE_URL=https://<your-Azure-Digital-Twins-instance-host-name>"
Connect the function to the endpoint
Next, subscribe your Azure function to the Event Grid endpoint you created earlier. Doing so will ensure that data can flow from an updated twin through the Event Grid topic to the function, which can use the event information to update other twins as needed.
To subscribe your Azure function, you'll create an Event Grid subscription that sends data from the Event Grid topic that you created earlier to your Azure function.
Use the following CLI command, filling in placeholders for your subscription ID, resource group, function app, and function name.
az eventgrid event-subscription create --name <name-for-your-event-subscription> --source-resource-id /subscriptions/<subscription-ID>/resourceGroups/<your-resource-group>/providers/Microsoft.EventGrid/topics/<your-event-grid-topic> --endpoint-type azurefunction --endpoint /subscriptions/<subscription-ID>/resourceGroups/<your-resource-group>/providers/Microsoft.Web/sites/<your-function-app-name>/functions/<function-name>
Now, your function can receive events through your Event Grid topic. The data flow setup is complete.
Test and verify results
The last step is to verify that the flow is working, by updating a twin and checking that related twins are updated according to the logic in your Azure function.
Next, query your Azure Digital Twins instance for the related twin. You can use the Azure CLI, or the Azure Digital Twins REST APIs and SDK. Verify that the twin received the data and updated as expected.
In this article, you set up twin-to-twin event handling in Azure Digital Twins. Next, set up an Azure function to trigger this flow automatically based on incoming telemetry from IoT Hub devices: Ingest telemetry from IoT Hub.