private void UpdateDeviceGroupDefinitionDictionary(DeviceGroupListApiModel deviceGroupList) { this.deviceGroupDefinitionDictionary.Clear(); foreach (DeviceGroupApiModel deviceGroup in deviceGroupList.Items) { this.deviceGroupDefinitionDictionary[deviceGroup.Id] = deviceGroup.ETag; } }
/** * Given list of device groups, query for device group -> device(s) mapping. * If this mapping is different from previous known mapping, or have no previous * known mapping, write mapping to reference data */ private async Task GetAndWriteDeviceGroupsMapping(DeviceGroupListApiModel deviceGroupList) { var deviceGroupMapping = await this.deviceGroupsClient.GetGroupToDevicesMappingAsync(deviceGroupList); if (this.mostRecentMapping == null || !this.AreDictionariesTheSame(this.mostRecentMapping, deviceGroupMapping)) { await this.deviceGroupsWriter.ExportMapToReferenceDataAsync(deviceGroupMapping, DateTimeOffset.UtcNow); this.mostRecentMapping = deviceGroupMapping; } }
public async Task RunAsync(CancellationToken runState) { this.log.Info("Device Groups Agent running", () => { }); // ensure will do initial write even if there are no device group definitions bool forceWrite = true; // IotHub has some latency between reporting a device is created/updated and when // the API returns the updates. This flag will tell the service to write // again a minute after changes have been seen, // to ensures if there are updates they are not missed. bool previousEventHubSeenChanges = this.eventHubStatus.SeenChanges; await this.SetupEventHub(runState); this.mostRecentMapping = null; while (!runState.IsCancellationRequested) { try { // check device groups DeviceGroupListApiModel deviceGroupList = await this.deviceGroupsClient.GetDeviceGroupsAsync(); bool deviceGroupsChanged = this.DidDeviceGroupDefinitionsChange(deviceGroupList); if (forceWrite || deviceGroupsChanged || this.eventHubStatus.SeenChanges || previousEventHubSeenChanges) { previousEventHubSeenChanges = this.eventHubStatus.SeenChanges; // set status before update so if message is received during update, will update again in a minute this.eventHubStatus.SeenChanges = false; // update device group definition dictionary this.UpdateDeviceGroupDefinitionDictionary(deviceGroupList, deviceGroupsChanged); // get device group -> devices mapping and write to file if it has changed await this.GetAndWriteDeviceGroupsMapping(deviceGroupList); forceWrite = false; } } catch (Exception e) { this.log.Error("Received error updating device to device group mapping", () => new { e }); forceWrite = true; } this.thread.Sleep(CHECK_INTERVAL_MSECS); } }
// Create fake device group list with one group definition with no conditions public static DeviceGroupListApiModel CreateDeviceGroupListApiModel(string etag, string groupId) { var returnObj = new DeviceGroupListApiModel(); var itemsList = new List <DeviceGroupApiModel> { new DeviceGroupApiModel() { Id = groupId, Conditions = new DeviceGroupConditionApiModel[0], DisplayName = "display", ETag = etag } }; returnObj.Items = itemsList; return(returnObj); }
private bool DidDeviceGroupDefinitionsChange(DeviceGroupListApiModel newDeviceGroupList) { if (newDeviceGroupList.Items.Count() != this.deviceGroupDefinitionDictionary.Keys.Count) { return(true); } foreach (DeviceGroupApiModel deviceGroup in newDeviceGroupList.Items) { if (!this.deviceGroupDefinitionDictionary.ContainsKey(deviceGroup.Id)) { return(true); } } return(false); }
// Set up device group client to return dummy device group list that will not change private void SetupDeviceGroupsClientMock() { this.deviceGroupListApiModel = TestHelperFunctions.CreateDeviceGroupListApiModel("etag1", "groupid"); this.deviceGroupsClientMock.Setup(x => x.GetDeviceGroupsAsync()).Returns(Task.FromResult(this.deviceGroupListApiModel)); }
/** * Given a list of device group definitions, queries for the list of devices * for each group and returns a dictionary of group id -> device ids */ public async Task <Dictionary <string, IEnumerable <string> > > GetGroupToDevicesMappingAsync(DeviceGroupListApiModel deviceGroupList) { var groupToDeviceMapping = new Dictionary <string, IEnumerable <string> >(); if (deviceGroupList?.Items != null) { // TODO: Add retry if this call fails // https://github.com/Azure/asa-manager-dotnet/issues/7 foreach (DeviceGroupApiModel group in deviceGroupList.Items) { groupToDeviceMapping.Add(group.Id, await this.GetDevicesAsync(group)); } } return(groupToDeviceMapping); }
/** * Given a list of device group definitions, queries for the list of devices * for each group and returns a dictionary of group id -> device ids */ public async Task <Dictionary <string, IEnumerable <string> > > GetGroupToDevicesMappingAsync(DeviceGroupListApiModel deviceGroupList) { var groupToDeviceMapping = new Dictionary <string, IEnumerable <string> >(); if (deviceGroupList?.Items != null) { foreach (DeviceGroupApiModel group in deviceGroupList.Items) { // TODO: await these calls after starting all of them instead of individually // https://github.com/Azure/asa-manager-dotnet/issues/22 var deviceList = (await this.GetDevicesAsync(group)).ToList(); // If device group has no devices in it, do not add to dictionary if (deviceList.Count > 0) { groupToDeviceMapping.Add(group.Id, deviceList); } } } return(groupToDeviceMapping); }
public async Task RunAsync(CancellationToken runState) { this.log.Info("Device Groups Agent running", () => { }); // ensure will do initial write even if there are no device group definitions bool forceWrite = true; // IotHub has some latency between reporting a device is created/updated and when // the API returns the updates. This flag will tell the service to write // again a minute after changes have been seen, // to ensures if there are updates they are not missed. bool previousEventHubSeenChanges = this.eventHubStatus.SeenChanges; if (!runState.IsCancellationRequested) { try { await this.SetupEventHub(); } catch (Exception e) { this.log.Error("Received error setting up event hub. Will not receive updates from devices", () => new { e }); } } while (!runState.IsCancellationRequested) { try { // check device groups DeviceGroupListApiModel deviceGroupList = await this.deviceGroupsClient.GetDeviceGroupsAsync(); bool deviceGroupsChanged = this.DidDeviceGroupDefinitionsChange(deviceGroupList); if (forceWrite || deviceGroupsChanged || this.eventHubStatus.SeenChanges || previousEventHubSeenChanges) { previousEventHubSeenChanges = this.eventHubStatus.SeenChanges; // set status before update so if message is received during update, will update again in a minute this.eventHubStatus.SeenChanges = false; // update if (deviceGroupsChanged) { this.UpdateDeviceGroupDefinitionDictionary(deviceGroupList); } var deviceGroupMapping = await this.deviceGroupsClient.GetGroupToDevicesMappingAsync(deviceGroupList); await this.deviceGroupsWriter.ExportMapToReferenceDataAsync(deviceGroupMapping, DateTimeOffset.UtcNow); forceWrite = false; } } catch (Exception e) { this.log.Error("Received error updating device to device group mapping", () => new { e }); forceWrite = true; } this.thread.Sleep(CHECK_INTERVAL_MSECS); } }