public static async Task <VerifyDeviceTwinResult> VerifyDeviceTwinActivity([ActivityTrigger] DeviceCreateOrchestrationInput req, TraceWriter log) { var iotHubConnectionString = Environment.GetEnvironmentVariable($"iothub_{req.IoTHubName}"); if (string.IsNullOrEmpty(iotHubConnectionString)) { iotHubConnectionString = Settings.Instance.IoTHubConnectionString; } if (string.IsNullOrEmpty(iotHubConnectionString)) { throw new Exception($"Could not find connection string for IoT Hub '{req.IoTHubName}'"); } RegistryManager rm = RegistryManager.CreateFromConnectionString(iotHubConnectionString); try { var deviceTwin = await rm.GetTwinAsync(req.DeviceId); if (deviceTwin == null) { throw new Exception($"Could not retrieve twin from device {req.DeviceId} in iothub {req.IoTHubName}"); } var externalDeviceRegistry = Utils.ResolveExternalDeviceRegistry(); foreach (var prop in externalDeviceRegistry.GetRequiredTwinProperties()) { if (!deviceTwin.Tags.Contains(prop)) { Utils.TelemetryClient?.TrackEvent(Utils.Event_DeviceTwinCheckFail, new Dictionary <string, string>() { { "deviceId", req.DeviceId }, { "iothubname", req.IoTHubName }, { "missingProperty", prop } }); log.Warning($"Missing property {prop} in device {req.DeviceId}"); throw new Exception($"Missing property {prop} in device {req.DeviceId}"); } } // all properties are there, create the succeeded response var properties = new Dictionary <string, string>(); foreach (var prop in externalDeviceRegistry.GetRequiredTwinProperties()) { properties[prop] = deviceTwin.Tags[prop]; } externalDeviceRegistry.ValidateTwinProperties(properties); return(new VerifyDeviceTwinResult { Properties = properties, }); } catch (Exception ex) { log.Error($"Error checking device twin properties in device {req.DeviceId}", ex); throw; } }
public static async Task <HttpResponseMessage> ExternalRegistrySynchronizer_EventGridListener( [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestMessage req, [OrchestrationClient] DurableOrchestrationClient starter, TraceWriter log) { var eventGridResponse = await Utils.HandleEventGridRequest(req); if (eventGridResponse != null) { return(eventGridResponse); } var orchestrationInstances = new List <string>(); var payload = await req.Content.ReadAsStringAsync(); var events = JsonConvert.DeserializeObject <List <JObject> >(payload); if (events != null) { var externalDeviceRegistry = Utils.ResolveExternalDeviceRegistry(); foreach (var gridEvent in events) { var data = gridEvent["data"]; var deviceId = data["deviceId"].ToString(); var iotHubName = data["hubName"].ToString(); var operationType = data["opType"].ToString(); switch (operationType.ToLowerInvariant()) { case "devicecreated": { var twinProperties = new Dictionary <string, string>(); if (data["twin"]?["tags"] != null) { var deviceTwinTags = data["twin"]["tags"]; foreach (var requiredProperty in externalDeviceRegistry.GetRequiredTwinProperties()) { if (deviceTwinTags[requiredProperty] != null) { twinProperties.Add(requiredProperty, deviceTwinTags[requiredProperty].ToString()); } else { twinProperties.Clear(); break; } } } // create device if all properties are there if (twinProperties.Count > 0) { try { externalDeviceRegistry.ValidateTwinProperties(twinProperties); // Create the device if all properties are there await CreateExternalDeviceActivity(new CreateExternalDeviceInput() { DeviceId = deviceId, IotHubName = iotHubName, Properties = twinProperties }, log); } catch (Exception ex) { log.Warning($"Direct device creation for device {deviceId} in iothub {iotHubName} failed, starting an orchestration. {ex.ToString()}"); // failed to create the device immediately, starts an orchestration to retry more times var deviceForwarderRequest = new DeviceCreateOrchestrationInput(deviceId, iotHubName); var instanceId = await starter.StartNewAsync(nameof(ExternalRegistrySynchronizer_CreateDeviceOrchestration), deviceForwarderRequest); orchestrationInstances.Add(instanceId); } } else { // Otherwise start orchestration to wait until the device twin properties exist var deviceForwarderRequest = new DeviceCreateOrchestrationInput(deviceId, iotHubName); var instanceId = await starter.StartNewAsync(nameof(ExternalRegistrySynchronizer_CreateDeviceOrchestration), deviceForwarderRequest); orchestrationInstances.Add(instanceId); } break; } case "devicedeleted": { var deleteDeviceInput = new DeviceDeleteOrchestrationInput(data, iotHubName); try { await DeleteDeviceInExternalSystemActivity(deleteDeviceInput, log); } catch (Exception ex) { log.Warning($"Direct device delete for device {deviceId} in iothub {iotHubName} failed, starting an orchestration. {ex.ToString()}"); // failed to delete the device, starts an orchestration to retry more times var instanceId = await starter.StartNewAsync(nameof(ExternalRegistrySynchronizer_DeleteDeviceOrchestration), deleteDeviceInput); orchestrationInstances.Add(instanceId); } break; } } } } if (orchestrationInstances.Count == 1) { return(starter.CreateCheckStatusResponse(req, orchestrationInstances.First())); } var res = new HttpResponseMessage(System.Net.HttpStatusCode.OK); return(res); }