private HashSet <string> GetDevicesInQuery(string hubQuery, string deploymentId, string tenantId)
        {
            var query         = string.Format(hubQuery, deploymentId);
            var queryResponse = TenantConnectionHelper.GetRegistry(tenantId).CreateQuery(query);
            var deviceIds     = new HashSet <string>();

            try
            {
                while (queryResponse.HasMoreResults)
                {
                    // TODO: Add pagination with queryOptions
                    var resultSet = queryResponse.GetNextAsJsonAsync();
                    foreach (var result in resultSet.Result)
                    {
                        var deviceId = JToken.Parse(result)[DeviceIdKey];
                        deviceIds.Add(deviceId.ToString());
                    }
                }
            }
            catch (Exception)
            {
                // this.logger.LogError(ex, "Error getting status of devices in query {query}", query);
            }

            return(deviceIds);
        }
        private async Task <ResultWithContinuationToken <List <Twin> > > GetTwinByQueryAsync(
            string tenantId,
            string queryPrefix,
            string query,
            string continuationToken,
            int numberOfResult)
        {
            query = string.IsNullOrEmpty(query) ? queryPrefix : $"{queryPrefix} where {query}";

            var twins = new List <Twin>();

            var twinQuery = TenantConnectionHelper.GetRegistry(tenantId).CreateQuery(query);

            QueryOptions options = new QueryOptions();

            options.ContinuationToken = continuationToken;

            while (twinQuery.HasMoreResults && twins.Count < numberOfResult)
            {
                var response = await twinQuery.GetNextAsTwinAsync(options);

                options.ContinuationToken = response.ContinuationToken;
                twins.AddRange(response);
            }

            return(new ResultWithContinuationToken <List <Twin> >(twins, options.ContinuationToken));
        }
예제 #3
0
 public DeviceGroupMigration(TableStorageHelper tableStorageClient, TenantConnectionHelper tenantConnectionHelper, ILogger logger, AppConfig appConfig)
 {
     this.tableStorageClient     = tableStorageClient;
     this.tenantConnectionHelper = tenantConnectionHelper;
     this.logger    = logger;
     this.appConfig = appConfig;
 }
예제 #4
0
        private static async Task Main(string[] args)
        {
            var     appConfig = InitializeAppConfig();
            ILogger logger    = LoggerSetup();

            try
            {
                AppConfigHelper        appConfigHelper        = new AppConfigHelper(appConfig.AppConfigurationConnectionString);
                TableStorageHelper     tableStorageHelper     = new TableStorageHelper(appConfig);
                TenantConnectionHelper tenantConnectionHelper = new TenantConnectionHelper(appConfigHelper);
                DeviceGroupMigration   deviceGroupMigration   = new DeviceGroupMigration(tableStorageHelper, tenantConnectionHelper, logger, appConfig);
                logger.LogInformation("Device Group Migration Started");
                await deviceGroupMigration.Start();

                logger.LogInformation("Device Group Migration Completed");

                DeviceTwinMigration deviceTwinMigration = new DeviceTwinMigration(tableStorageHelper, tenantConnectionHelper, logger);
                logger.LogInformation("Device Twin Migration Started");
                await deviceTwinMigration.Start();

                logger.LogInformation("Device Twin Migration Completed");
            }
            catch (System.Exception ex)
            {
                logger.LogError(ex, "Migration Failed");
            }
        }
예제 #5
0
        public async Task ProcessDeviceTwin(EventData[] source, ILogger log, string tenant, string deviceId)
        {
            foreach (EventData message in source)
            {
                try
                {
                    if (tenant != null)
                    {
                        var            connectionString = TenantConnectionHelper.GetEventHubConnectionString(Convert.ToString(tenant));
                        EventHubHelper eventHubHelper   = new EventHubHelper(connectionString);

                        string eventData = Encoding.UTF8.GetString(message.Body.Array);
                        message.Properties.TryGetValue("opType", out object operationType);
                        message.SystemProperties.TryGetValue(DeviceTelemetryKeyConstants.IotHubEnqueuedTime, out object dateTimeReceived);

                        var           timeStamp     = new TelemetryTimestamp(Convert.ToDateTime(dateTimeReceived));
                        DeviceService deviceService = new DeviceService();
                        await deviceService.SaveDeviceTwinOperationAsync(eventData, log, Convert.ToString(tenant), deviceId.ToString(), operationType.ToString(), timeStamp, eventHubHelper);
                    }
                }
                catch (Exception ex)
                {
                    log.LogError($"Error occurrred in for loop: {ex.Message} StackTrace: {ex.StackTrace}  Inner Exception: {(string.IsNullOrEmpty(ex.StackTrace) ? string.Empty : ex.StackTrace)}");
                }
            }
        }
        public static async Task Run([EventHubTrigger(eventHubName: "twin-change", Connection = "TwinChangeEventHubConnectionString", ConsumerGroup = "%DeviceDeploymentHistoryConsumerGroup%")] EventData[] events, ILogger log)
        {
            bool        exceptionOccurred = false;
            List <Task> list = new List <Task>();

            foreach (EventData message in events)
            {
                try
                {
                    message.Properties.TryGetValue("tenant", out object tenant);

                    if (tenant != null)
                    {
                        string                      eventData          = Encoding.UTF8.GetString(message.Body.Array);
                        Twin                        twin               = JsonConvert.DeserializeObject <Twin>(eventData);
                        TwinServiceModel            twinServiceModel   = new TwinServiceModel(twin);
                        Dictionary <string, JToken> reportedProperties = twinServiceModel.ReportedProperties;
                        var  json             = JToken.Parse(JsonConvert.SerializeObject(reportedProperties));
                        var  fieldsCollector  = new JsonFieldsCollector(json);
                        var  fields           = fieldsCollector.GetAllFields();
                        bool isFirmWareUpdate = false;
                        foreach (var field in fields)
                        {
                            isFirmWareUpdate = field.Key.Contains(FIRMWARE, StringComparison.OrdinalIgnoreCase);
                            if (isFirmWareUpdate)
                            {
                                break;
                            }
                        }

                        if (isFirmWareUpdate)
                        {
                            message.SystemProperties.TryGetValue("iothub-connection-device-id", out object deviceId);
                            var newTwin = await TenantConnectionHelper.GetRegistry(Convert.ToString(tenant)).GetTwinAsync(deviceId.ToString());

                            var appliedConfigurations = newTwin.Configurations.Where(c => c.Value.Status.Equals(ConfigurationStatus.Applied));
                            if (appliedConfigurations != null && appliedConfigurations.Count() > 0)
                            {
                                DeploymentSyncService service    = new DeploymentSyncService();
                                var appliedDeploymentFromStorage = service.GetDeploymentsByIdFromStorage(Convert.ToString(tenant), appliedConfigurations.Select(ac => ac.Key).ToArray()).Result.FirstOrDefault();
                                await service.SaveDeploymentHistory(Convert.ToString(tenant), appliedDeploymentFromStorage, newTwin);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    log.LogError($"Error occurrred : {ex.Message} StackTrace: {ex.StackTrace}  Inner Exception: {(string.IsNullOrEmpty(ex.StackTrace) ? string.Empty : ex.StackTrace)}");
                    exceptionOccurred = true;
                }
            }

            if (exceptionOccurred)
            {
                throw new Exception("Function Failed with exception");
            }
        }
예제 #7
0
        public static async Task Run([QueueTrigger("tenantstosync", Connection = "AzureStorageConnectionString")] string myQueueItem, ILogger log)
        {
            log.LogInformation($"C# Queue trigger function processed: {myQueueItem}");

            if (!string.IsNullOrEmpty(myQueueItem))
            {
                TenantQueueItem tenant = JsonConvert.DeserializeObject <TenantQueueItem>(myQueueItem);

                if (tenant != null && !string.IsNullOrWhiteSpace(tenant.TenantId))
                {
                    List <DeploymentServiceModel> deploymentsToSync  = new List <DeploymentServiceModel>();
                    IEnumerable <Configuration>   deploymentsFromHub = null;
                    try
                    {
                        deploymentsFromHub = await TenantConnectionHelper.GetRegistry(tenant.TenantId).GetConfigurationsAsync(100);

                        DeploymentSyncService service = new DeploymentSyncService();

                        deploymentsToSync.AddRange(await service.GetDeploymentsToSync(tenant.TenantId, deploymentsFromHub));
                    }
                    catch (Exception)
                    {
                        log.LogError($"Error occurrred while fetching deployments");
                        throw;
                    }

                    if (deploymentsToSync != null && deploymentsToSync.Count > 0)
                    {
                        // Get the connection string from app settings
                        string connectionString = Environment.GetEnvironmentVariable("AzureStorageConnectionString", EnvironmentVariableTarget.Process);

                        // Instantiate a QueueClient which will be used to create and manipulate the queue
                        QueueClient queueClient = new QueueClient(connectionString, "deploymentstosync");

                        await queueClient.CreateIfNotExistsAsync();

                        if (queueClient.Exists())
                        {
                            foreach (var deploymentToSync in deploymentsToSync)
                            {
                                DeploymentModel deployment = new DeploymentModel();
                                deployment.TenantId      = tenant.TenantId;
                                deployment.Deployment    = deploymentToSync;
                                deployment.Configuration = deploymentsFromHub.FirstOrDefault(d => d.Id == deploymentToSync.Id);

                                var deploymentToSyncString = JsonConvert.SerializeObject(deployment);

                                queueClient.SendMessage(Base64Encode(deploymentToSyncString));
                            }
                        }
                    }
                }
            }
        }
예제 #8
0
 public Storage(
     IStorageAdapterClient client,
     IAsaManagerClient asaManager,
     AppConfig config,
     IPackageEventLog packageLog,
     ILogger <Storage> logger,
     IHttpContextAccessor httpContextAccessor,
     IAppConfigurationClient appConfigurationClient)
 {
     this.client                 = client;
     this.asaManager             = asaManager;
     this.config                 = config;
     this.packageLog             = packageLog;
     this.logger                 = logger;
     this.tenantConnectionHelper = new TenantConnectionHelper(appConfigurationClient);
     this.httpContextAccessor    = httpContextAccessor;
 }
예제 #9
0
 public DeviceTwinMigration(TableStorageHelper tableStorageClient, TenantConnectionHelper tenantConnectionHelper, ILogger logger)
 {
     this.tableStorageClient     = tableStorageClient;
     this.tenantConnectionHelper = tenantConnectionHelper;
     this.logger = logger;
 }
예제 #10
0
        public async Task SaveDeviceTwinOperationAsync(string eventData, ILogger log, string tenant, string deviceId, string operationType, TelemetryTimestamp timeStamp, EventHubHelper eventHubHelper)
        {
            try
            {
                string  deviceTwin     = eventData;
                Twin    twin           = null;
                JObject deviceTwinJson = new JObject();
                deviceTwinJson.Add(DeviceTelemetryKeyConstants.DeviceId, deviceId.ToString());
                deviceTwinJson.Add(DeviceTelemetryKeyConstants.TimeStamp, timeStamp.DateTime);
                deviceTwinJson.Add(DeviceTelemetryKeyConstants.TimeReceived, timeStamp.EpochTimestamp);
                deviceTwinJson.Add(DeviceTelemetryKeyConstants.EventOpType, operationType);
                deviceTwinJson.Add(DeviceTelemetryKeyConstants.IsDeleted, false);

                if (operationType.ToString().Equals("createDeviceIdentity"))
                {
                    deviceTwinJson.Add(DeviceTelemetryKeyConstants.DeviceCreatedDate, timeStamp.DateTime);

                    try
                    {
                        twin = await TenantConnectionHelper.GetRegistry(Convert.ToString(tenant)).GetTwinAsync(deviceId.ToString());

                        deviceTwin = twin.ToJson();
                    }
                    catch (Exception e)
                    {
                        log.LogError($"Unable to fetch DeviceId: {deviceId} device twin from iothub of tenant: {tenant}.", e);
                    }
                }
                else
                {
                    JObject         previousTwin = null;
                    KustoOperations kustoClient  = await KustoOperations.GetClientAsync();

                    string kustoQuery     = $"DeviceTwin | where DeviceId == \"{deviceId}\" | summarize arg_max(TimeStamp, *) by DeviceId | where IsDeleted == false";
                    var    deviceTwinList = await kustoClient.QueryAsync <DeviceTwinModel>($"IoT-{tenant}", kustoQuery, null);

                    DeviceTwinModel preDeviceTwin = deviceTwinList.FirstOrDefault();

                    if (preDeviceTwin != null)
                    {
                        previousTwin = preDeviceTwin.Twin;
                        deviceTwinJson.Add(DeviceTelemetryKeyConstants.DeviceCreatedDate, preDeviceTwin.DeviceCreatedDate);
                    }
                    else
                    {
                        deviceTwinJson.Add(DeviceTelemetryKeyConstants.DeviceCreatedDate, default(DateTime)); // Set Device Created Date to Default if twin is not present in storage.

                        try
                        {
                            twin = await TenantConnectionHelper.GetRegistry(Convert.ToString(tenant)).GetTwinAsync(deviceId.ToString());

                            if (twin != null)
                            {
                                previousTwin = JObject.Parse(twin.ToJson());
                            }
                        }
                        catch (Exception e)
                        {
                            log.LogError($"Unable to fetch DeviceId: {deviceId} device twin from iothub of tenant: {tenant}.", e);
                        }
                    }

                    switch (operationType)
                    {
                    case "deviceConnected":
                        if (preDeviceTwin != null)
                        {
                            previousTwin["connectionState"]  = "Connected";
                            previousTwin["lastActivityTime"] = timeStamp.DateTime;
                        }

                        break;

                    case "deviceDisconnected":
                        if (preDeviceTwin != null)
                        {
                            previousTwin["connectionState"]  = "Disconnected";
                            previousTwin["lastActivityTime"] = timeStamp.DateTime;
                        }

                        break;

                    case "updateTwin":
                        if (preDeviceTwin != null)
                        {
                            JObject twinFragment = JObject.Parse(eventData);
                            previousTwin = previousTwin.UpdateJson(twinFragment);
                        }
                        else
                        {
                            previousTwin = JObject.Parse(eventData);
                        }

                        break;

                    case "deleteDeviceIdentity":
                        deviceTwinJson[DeviceTelemetryKeyConstants.IsDeleted] = true;
                        break;

                    default:
                        break;
                    }

                    deviceTwin = previousTwin?.ToString();
                }

                deviceTwinJson.Add(DeviceTelemetryKeyConstants.Data, deviceTwin);

                // Save the Device Twin Data to EventHub for further processing
                var byteMessage         = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(deviceTwinJson));
                var eventDeviceTwinData = new Azure.Messaging.EventHubs.EventData(byteMessage);
                eventDeviceTwinData.Properties.Add("deviceid", deviceId.ToString());

                await eventHubHelper.SendMessageToEventHub($"{tenant}-devicetwin", new Azure.Messaging.EventHubs.EventData[] { eventDeviceTwinData });
            }
            catch (Exception exception)
            {
                throw new ApplicationException($"Save Device Twin operation failed: {exception}, operation type: {operationType}, tenant: {tenant}, deviceId {deviceId}");
            }
        }