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;
            }
        }
Пример #2
0
        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);
        }