public async void Run([EventGridTrigger] EventGridEvent eventGridEvent, ILogger log) { // After this is deployed, you need to turn the Managed Identity Status to "On", // Grab Object Id of the function and assigned "Azure Digital Twins Owner (Preview)" role to this function identity // in order for this function to be authorized on ADT APIs. log.LogInformation(eventGridEvent.Data.ToString()); try { // Authenticate on ADT APIs var cred = new ManagedIdentityCredential(adtAppId); var client = new DigitalTwinsClient(new Uri(adtInstanceUrl), cred, new DigitalTwinsClientOptions { Transport = new HttpClientTransport(httpClient) }); log.LogInformation($"ADT service client connection created."); if (client != null) { if (eventGridEvent != null && eventGridEvent.Data != null) { #region Open this region for message format information // Telemetry message format //{ // "properties": { }, // "systemProperties": // { // "iothub-connection-device-id": "thermostat1", // "iothub-connection-auth-method": "{\"scope\":\"device\",\"type\":\"sas\",\"issuer\":\"iothub\",\"acceptingIpFilterRule\":null}", // "iothub-connection-auth-generation-id": "637199981642612179", // "iothub-enqueuedtime": "2020-03-18T18:35:08.269Z", // "iothub-message-source": "Telemetry" // }, // "body": "eyJUZW1wZXJhdHVyZSI6NzAuOTI3MjM0MDg3MTA1NDg5fQ==" //} #endregion // Reading deviceId from message headers log.LogInformation(eventGridEvent.Data.ToString()); JObject job = (JObject)JsonConvert.DeserializeObject(eventGridEvent.Data.ToString()); string deviceId = (string)job["systemProperties"]["iothub-connection-device-id"]; log.LogInformation($"Found device: {deviceId}"); // Extracting temperature from device telemetry byte[] body = Convert.FromBase64String(job["body"].ToString()); var value = Encoding.ASCII.GetString(body); var bodyProperty = (JObject)JsonConvert.DeserializeObject(value); JToken temperature = bodyProperty["Temperature"]; log.LogInformation($"Device Temperature is ({temperature.Type}): {temperature}"); // Update device Temperature property await AdtUtilities.UpdateTwinPropertyAsync(client, deviceId, "/Temperature", temperature.Value <float>(), log); } } } catch (Exception e) { log.LogError($"Error: {e.Message}"); } }
public static async Task Run([EventGridTrigger] EventGridEvent eventGridEvent, ILogger log) { log.LogInformation("Start execution"); // After this is deployed, you'll need to turn the Azure Function Identity Status "On", // grab Object ID of the function, and assign "Azure Digital Twins Owner (Preview)" role to this function identity // in order for this function to be authorized on ADT APIs. // // If you are following "Tutorial: Connect an end-to-end solution" in the Azure Digital Twins documentation, // you have done this already with an equivalent CLI step in the "Assign permissions to the function app" section. DigitalTwinsClient client; // Authenticate on ADT APIs try { var credentials = new DefaultAzureCredential(); client = new DigitalTwinsClient(new Uri(adtServiceUrl), credentials, new DigitalTwinsClientOptions { Transport = new HttpClientTransport(httpClient) }); log.LogInformation("ADT service client connection created."); } catch (Exception e) { log.LogError($"ADT service client connection failed. {e}"); return; } if (client != null) { if (eventGridEvent != null && eventGridEvent.Data != null) { string twinId = eventGridEvent.Subject.ToString(); JObject message = (JObject)JsonConvert.DeserializeObject(eventGridEvent.Data.ToString()); log.LogInformation($"Reading event from {twinId}: {eventGridEvent.EventType}: {message["data"]}"); //Find and update parent Twin string parentId = await AdtUtilities.FindParentAsync(client, twinId, "contains", log); if (parentId != null) { // Read properties which values have been changed in each operation foreach (var operation in message["data"]["patch"]) { string opValue = (string)operation["op"]; if (opValue.Equals("replace")) { string propertyPath = ((string)operation["path"]); if (propertyPath.Equals("/Temperature")) { await AdtUtilities.UpdateTwinPropertyAsync(client, parentId, propertyPath, operation["value"].Value <float>(), log); } } } } } } }
public static async Task Run([EventGridTrigger] EventGridEvent eventGridEvent, ILogger log) { log.LogInformation("Start execution"); // After this is deployed, you need to turn the Identity Status "On", // Grab Object Id of the function and assigned "Azure Digital Twins Owner (Preview)" role to this function identity // in order for this function to be authorize on ADT APIs. DigitalTwinsClient client; // Authenticate on ADT APIs try { ManagedIdentityCredential cred = new ManagedIdentityCredential(adtAppId); client = new DigitalTwinsClient(new Uri(adtInstanceUrl), cred, new DigitalTwinsClientOptions { Transport = new HttpClientTransport(httpClient) }); log.LogInformation("ADT service client connection created."); } catch (Exception e) { log.LogError($"ADT service client connection failed. {e}"); return; } if (client != null) { try { if (eventGridEvent != null && eventGridEvent.Data != null) { string twinId = eventGridEvent.Subject.ToString(); JObject message = (JObject)JsonConvert.DeserializeObject(eventGridEvent.Data.ToString()); log.LogInformation($"Reading event from {twinId}: {eventGridEvent.EventType}: {message["data"]}"); //Find and update parent Twin string parentId = await AdtUtilities.FindParentAsync(client, twinId, "contains", log); if (parentId != null) { // Read properties which values have been changed in each operation foreach (var operation in message["data"]["patch"]) { string opValue = (string)operation["op"]; if (opValue.Equals("replace")) { string propertyPath = ((string)operation["path"]); object propertyValue = (object)operation["value"]; if (propertyPath.Equals("/Temperature")) { await AdtUtilities.UpdateTwinPropertyAsync(client, parentId, propertyPath, propertyValue, log); } } } } } } catch (Exception e) { log.LogError(e.ToString()); } } }
public static async Task Run([EventGridTrigger] EventGridEvent eventGridEvent, ILogger log) { // After this is deployed, you need to turn the Identity Status "On", // Grab Object Id of the function and assigned "Azure Digital Twins Owner (Preview)" role to this function identity // in order for this function to be authorize on ADT APIs. DigitalTwinsClient client = null; log.LogInformation("start execution"); // Authenticate on ADT APIs try { ManagedIdentityCredential cred = new ManagedIdentityCredential(adtAppId); client = new DigitalTwinsClient(new Uri(adtInstanceUrl), cred, new DigitalTwinsClientOptions { Transport = new HttpClientTransport(httpClient) }); log.LogInformation($"ADT service client connection created."); } catch (Exception e) { log.LogError($"ADT service client connection failed. " + e.ToString()); return; } if (client != null) { try { if (eventGridEvent != null && eventGridEvent.Data != null) { #region Open this region for message format information // Known Issue: you cannot read the header event type in telemetry or notifications, // you cannot read notification properties for now until CE format it's implemented // Therefore you have to parse the notification for "Operations" (for now) // Read property change events, format looks like this //{ // "data": // { // "TwinId": "room1", // "Operations": // [ // {"op": "replace", "path": "/Temperature", "value": 70}, // {"op": "replace", "path": "/Humidity","value": 49 } // ] // } // } // Device Telemetry message //{ // "properties": { }, // "systemProperties": // { // "iothub-connection-device-id": "thermostat1", // "iothub-connection-auth-method": "{\"scope\":\"device\",\"type\":\"sas\",\"issuer\":\"iothub\",\"acceptingIpFilterRule\":null}", // "iothub-connection-auth-generation-id": "637199981642612179", // "iothub-enqueuedtime": "2020-03-18T18:35:08.269Z", // "iothub-message-source": "Telemetry" // }, // "body": "eyJUZW1wZXJhdHVyZSI6NzAuOTI3MjM0MDg3MTA1NDg5fQ==" //} #endregion string evt = eventGridEvent.Data.ToString(); log.LogInformation(evt); JObject message = (JObject)JsonConvert.DeserializeObject(evt); // Read twin id string twinId = (string)message["TwinId"]; log.LogInformation($"Found updates on twin: {twinId}"); // Validate "Operations" and TwinId if ((message["Operations"] == null || message["Operations"].Count() == 0) && String.IsNullOrEmpty(twinId)) { log.LogInformation($"No twin property change events"); } //string parent = await FindParent(twinId, "contains", log); string parentId = await AdtUtilities.FindParentByQuery(client, twinId, log); if (parentId != null) { // Read properties which values have been changed in each operation foreach (var operation in message["Operations"]) { string opValue = (string)operation["op"]; if (opValue.Equals("replace")) { string propertyPath = ((string)operation["path"]); string propertyValue = (string)operation["value"]; if (propertyPath.Equals("/Temperature")) { await AdtUtilities.UpdateTwinProperty(client, parentId, "replace", propertyPath, "double", propertyValue, log); } } } } } } catch (Exception e) { log.LogError($"*** Unable to create client connection {e}"); } } }