public async static void Run([EventGridTrigger] EventGridEvent eventGridEvent, ILogger log) { log.LogInformation(eventGridEvent.Data.ToString()); if (adtInstanceUrl == null) { log.LogError("Application setting \"ADT_SERVICE_URL\" not set"); return; } try { // INSERT authentication code below here ManagedIdentityCredential cred = new ManagedIdentityCredential("https://digitaltwins.azure.net"); DigitalTwinsClient client = new DigitalTwinsClient(new Uri(adtInstanceUrl), cred, new DigitalTwinsClientOptions { Transport = new HttpClientTransport(httpClient) }); log.LogInformation($"Azure digital twins service client connection created."); // INSERT event processing code below here if (eventGridEvent != null && eventGridEvent.Data != null) { // Read deviceId and temperature for IoT Hub JSON. JObject deviceMessage = (JObject)JsonConvert.DeserializeObject(eventGridEvent.Data.ToString()); string deviceId = (string)deviceMessage["systemProperties"]["iothub-connection-device-id"]; var fanAlert = (bool)deviceMessage["properties"]["fanAlert"]; // cast directly to a bool var temperatureAlert = deviceMessage["properties"].SelectToken("temperatureAlert") ?? false; // JToken object var humidityAlert = deviceMessage["properties"].SelectToken("humidityAlert") ?? false; // JToken object log.LogInformation($"Device:{deviceId} fanAlert is:{fanAlert}"); log.LogInformation($"Device:{deviceId} temperatureAlert is:{temperatureAlert}"); log.LogInformation($"Device:{deviceId} humidityAlert is:{humidityAlert}"); var bodyJson = Encoding.ASCII.GetString((byte[])deviceMessage["body"]); JObject body = (JObject)JsonConvert.DeserializeObject(bodyJson); log.LogInformation($"Device:{deviceId} Temperature is:{body["temperature"]}"); log.LogInformation($"Device:{deviceId} Humidity is:{body["humidity"]}"); // INSERT ADT update code below here // Update twin properties var patch = new Azure.JsonPatchDocument(); patch.AppendReplace <bool>("/fanAlert", fanAlert); // already a bool patch.AppendReplace <bool>("/temperatureAlert", temperatureAlert.Value <bool>()); // convert the JToken value to bool patch.AppendReplace <bool>("/humidityAlert", humidityAlert.Value <bool>()); // convert the JToken value to bool await client.UpdateDigitalTwinAsync(deviceId, patch); // publish telemetry await client.PublishTelemetryAsync(deviceId, null, bodyJson); } } catch (Exception e) { log.LogError(e.Message); } }
public async void Run([EventGridTrigger] EventGridEvent eventGridEvent, ILogger log) { //log.LogInformation("Starting function"); //log.LogInformation(eventGridEvent.Data.ToString()); if (adtInstanceUrl == null) { log.LogError("Application setting \"ADT_SERVICE_URL\" not set"); } try { //Authenticate with Digital Twins. //log.LogInformation("Starting ManagedIdentityCredential"); ManagedIdentityCredential cred = new ManagedIdentityCredential("https://digitaltwins.azure.net"); //log.LogInformation("Starting DigitalTwinsClient to: " + adtInstanceUrl.ToString()); DigitalTwinsClient client = new DigitalTwinsClient(new Uri(adtInstanceUrl), cred, new DigitalTwinsClientOptions { Transport = new HttpClientTransport(httpClient) }); log.LogInformation($"Azure digital twins service client connection created."); if (eventGridEvent != null && eventGridEvent.Data != null) { //log.LogInformation(eventGridEvent.Data.ToString()); // Read deviceId and temperature for IoT Hub JSON. JObject deviceMessage = (JObject)JsonConvert.DeserializeObject(eventGridEvent.Data.ToString()); String body = Base64StringDecode(deviceMessage["body"].ToString()); JObject deviceMessageBody = (JObject)JsonConvert.DeserializeObject(body); //log.LogInformation(body); string deviceId = (string)deviceMessage["systemProperties"]["iothub-connection-device-id"]; var temperature = deviceMessageBody["Temperature"]; log.LogInformation($"Device:{deviceId} Temperature is:{temperature}"); //Update twin by using device temperature. var patch = new Azure.JsonPatchDocument(); patch.AppendReplace <double>("/Temperature", temperature.Value <double>()); await client.UpdateDigitalTwinAsync(deviceId, patch); } } catch (Exception e) { log.LogError(e.Message); } }
public async static Task Run( [EventGridTrigger] EventGridEvent eventGridEvent, ILogger log) { // The ILogger interface is defined in the // Microsoft.Extensions.Logging namespace and aggregates most // logging patterns to a single method call. In this case, a log // entry is created at the Information level - other methods // exists for various levels including critical, error. etc. As the // Azure Function is running in the cloud, logging is essential // during development and production. log.LogInformation(eventGridEvent.Data.ToString()); // This code checks if the adtInstanceUrl environment variable // has been set - if not, the error is logged and the function exits. // This demonstrates the value of logging to capture the fact that // the function has been incorrectly configured. if (adtInstanceUrl == null) { log.LogError("Application setting \"ADT_SERVICE_URL\" not set"); return; } try { // REVIEW authentication code below here // Notice the use of the ManagedIdentityCredential class. // This class attempts authentication using the managed identity // that has been assigned to the deployment environment earlier. // Once the credential is returned, it is used to construct an // instance of the DigitalTwinsClient. The client contains // methods to retrieve and update digital twin information, like // models, components, properties and relationships. ManagedIdentityCredential cred = new ManagedIdentityCredential("https://digitaltwins.azure.net"); DigitalTwinsClient client = new DigitalTwinsClient( new Uri(adtInstanceUrl), cred, new DigitalTwinsClientOptions { Transport = new HttpClientTransport(httpClient) }); log.LogInformation($"Azure digital twins service client connection created."); // REVIEW event processing code below here if (eventGridEvent != null && eventGridEvent.Data != null) { // Read deviceId and temperature for IoT Hub JSON. // Notice the use of JSON deserialization to access the event data. // The message properties and systemProperties are // easily accessible using an indexer approach. JObject deviceMessage = (JObject)JsonConvert.DeserializeObject(eventGridEvent.Data.ToString()); string deviceId = (string)deviceMessage["systemProperties"]["iothub-connection-device-id"]; var fanAlert = (bool)deviceMessage["properties"]["fanAlert"]; // cast directly to a bool // However where properties are optional, such as temperatureAlert // and humidityAlert, the use of `SelectToken` and a // null-coalescing operation is required to prevent an // exception being thrown. var temperatureAlert = deviceMessage["properties"].SelectToken("temperatureAlert") ?? false; // JToken object var humidityAlert = deviceMessage["properties"].SelectToken("humidityAlert") ?? false; // JToken object log.LogInformation($"Device:{deviceId} fanAlert is:{fanAlert}"); log.LogInformation($"Device:{deviceId} temperatureAlert is:{temperatureAlert}"); log.LogInformation($"Device:{deviceId} humidityAlert is:{humidityAlert}"); // The message body contains the telemetry payload and is // ASCII encoded JSON. Therefore, it must first be decoded and // then deserialized before the telemetry properties can be accessed. var bodyJson = Encoding.ASCII.GetString((byte[])deviceMessage["body"]); JObject body = (JObject)JsonConvert.DeserializeObject(bodyJson); log.LogInformation($"Device:{deviceId} Temperature is:{body["temperature"]}"); log.LogInformation($"Device:{deviceId} Humidity is:{body["humidity"]}"); // REVIEW ADT update code below here // There are two approaches being used to apply data to the // digital twin - the first via property updates using a JSON // patch, the second via the publishing of telemetry data. // The ADT client utilizes a JSON Patch document to add or // update digital twin properties. The JSON Patch defines a // JSON document structure for expressing a sequence of // operations to apply to a JSON document. The various values // are added to the patch as append or replace operations, // and the ADT is then updated asynchronously. var patch = new Azure.JsonPatchDocument(); patch.AppendReplace <bool>("/fanAlert", fanAlert); // already a bool patch.AppendReplace <bool>("/temperatureAlert", temperatureAlert.Value <bool>()); // convert the JToken value to bool patch.AppendReplace <bool>("/humidityAlert", humidityAlert.Value <bool>()); // convert the JToken value to bool await client.UpdateDigitalTwinAsync(deviceId, patch); // publish telemetry // Notice that the telemetry data is handled differently than // the properties - rather than being used to set digital twin // properties, it is instead being published as telemetry // events. This mechanism ensures that the telemetry is // available to be consumed by any downstream subscribers to // the digital twins event route. await client.PublishTelemetryAsync(deviceId, null, bodyJson); } } catch (Exception e) { log.LogError(e.Message); } }