From 3aca6729a5cb047d93688e4718404087fd052b1e Mon Sep 17 00:00:00 2001 From: Mads Mogensen Date: Mon, 4 Dec 2023 15:28:58 +0100 Subject: [PATCH] Fix Measurements with multiple trackers --- .../Measurements/AggregatedMeasurements.cs | 72 ++------- .../GetAggregatedMeasurementsResponse.cs | 6 +- .../MeasurementControllerTests.cs | 41 ++---- CentralHub.Api.Tests/ServiceTests.cs | 44 +----- .../Controllers/MeasurementController.cs | 72 ++++----- .../Dtos/AggregatedMeasurementDto.cs | 22 +-- .../Services/LocalizationService.cs | 92 +----------- CentralHub.WebUI/Data/MeasurementService.cs | 6 +- CentralHub.WebUI/Pages/Charts.razor | 138 +++--------------- 9 files changed, 103 insertions(+), 390 deletions(-) diff --git a/CentralHub.Api.Model/Responses/Measurements/AggregatedMeasurements.cs b/CentralHub.Api.Model/Responses/Measurements/AggregatedMeasurements.cs index 1e80904..6a56b9e 100644 --- a/CentralHub.Api.Model/Responses/Measurements/AggregatedMeasurements.cs +++ b/CentralHub.Api.Model/Responses/Measurements/AggregatedMeasurements.cs @@ -1,67 +1,21 @@ using System.Text.Json.Serialization; -namespace CentralHub.Api.Model.Responses.AggregatedMeasurements; - -public sealed class AggregatedMeasurements +namespace CentralHub.Api.Model.Responses.Measurements; + +[method: JsonConstructor] +public sealed class AggregatedMeasurements(int aggregatedMeasurementsId, + DateTime startTime, + DateTime endTime, + int bluetoothCount, + int wifiCount) { - [JsonConstructor] - public AggregatedMeasurements( - int aggregatedMeasurementDtoId, - DateTime startTime, - DateTime endTime, - int measurementGroupCount, - int bluetoothMedian, - double bluetoothMean, - int bluetoothMin, - int bluetoothMax, - int totalBluetoothDeviceCount, - int wifiMedian, - double wifiMean, - int wifiMin, - int wifiMax, - int totalWifiDeviceCount) - { - AggregatedMeasurementDtoId = aggregatedMeasurementDtoId; - StartTime = startTime; - EndTime = endTime; - MeasurementGroupCount = measurementGroupCount; - BluetoothMedian = bluetoothMedian; - BluetoothMean = bluetoothMean; - BluetoothMin = bluetoothMin; - BluetoothMax = bluetoothMax; - TotalBluetoothDeviceCount = totalBluetoothDeviceCount; - WifiMedian = wifiMedian; - WifiMean = wifiMean; - WifiMin = wifiMin; - WifiMax = wifiMax; - TotalWifiDeviceCount = totalWifiDeviceCount; - } - - public int AggregatedMeasurementDtoId { get; } - - public DateTime StartTime { get; } - - public DateTime EndTime { get; } - - public int MeasurementGroupCount { get; } - - public int BluetoothMedian { get; } - - public double BluetoothMean { get; } - - public int BluetoothMin { get; } - - public int BluetoothMax { get; } - - public int TotalBluetoothDeviceCount { get; } - - public int WifiMedian { get; } + public int AggregatedMeasurementId { get; } = aggregatedMeasurementsId; - public double WifiMean { get; } + public DateTime StartTime { get; } = startTime; - public int WifiMin { get; } + public DateTime EndTime { get; } = endTime; - public int WifiMax { get; } + public int BluetoothCount { get; } = bluetoothCount; - public int TotalWifiDeviceCount { get; } + public int WifiCount { get; } = wifiCount; } \ No newline at end of file diff --git a/CentralHub.Api.Model/Responses/Measurements/GetAggregatedMeasurementsResponse.cs b/CentralHub.Api.Model/Responses/Measurements/GetAggregatedMeasurementsResponse.cs index 942f126..a5a5027 100644 --- a/CentralHub.Api.Model/Responses/Measurements/GetAggregatedMeasurementsResponse.cs +++ b/CentralHub.Api.Model/Responses/Measurements/GetAggregatedMeasurementsResponse.cs @@ -5,7 +5,7 @@ namespace CentralHub.Api.Model.Responses.Measurements; public sealed class GetAggregatedMeasurementsResponse { [JsonConstructor] - public GetAggregatedMeasurementsResponse(bool success, IReadOnlyCollection? aggregatedMeasurements) + public GetAggregatedMeasurementsResponse(bool success, IReadOnlyCollection? aggregatedMeasurements) { Success = success; AggregatedMeasurements = aggregatedMeasurements; @@ -14,14 +14,14 @@ public GetAggregatedMeasurementsResponse(bool success, IReadOnlyCollection? AggregatedMeasurements { get; } + public IReadOnlyCollection? AggregatedMeasurements { get; } public static GetAggregatedMeasurementsResponse CreateUnsuccessful() { return new GetAggregatedMeasurementsResponse(false, null); } - public static GetAggregatedMeasurementsResponse CreateSuccessful(IReadOnlyCollection aggregatedMeasurements) + public static GetAggregatedMeasurementsResponse CreateSuccessful(IReadOnlyCollection aggregatedMeasurements) { return new GetAggregatedMeasurementsResponse(true, aggregatedMeasurements); } diff --git a/CentralHub.Api.Tests/MeasurementControllerTests.cs b/CentralHub.Api.Tests/MeasurementControllerTests.cs index 3b546c0..e3c9616 100644 --- a/CentralHub.Api.Tests/MeasurementControllerTests.cs +++ b/CentralHub.Api.Tests/MeasurementControllerTests.cs @@ -13,7 +13,7 @@ public class MeasurementControllerTests private MeasurementController _measurementController; private IRoomRepository _roomRepository; private ITrackerRepository _trackerRepository; - private IMeasurementRepository _aggregatedMeasurementRepository; + private IMeasurementRepository _measurementRepository; private LocalizationService _localizationService; @@ -45,15 +45,17 @@ public void Setup() _trackerRepository = new MockTrackerRepository(roomDto); _trackerId = _trackerRepository.AddTrackerAsync(trackerDto, default).GetAwaiter().GetResult(); - _aggregatedMeasurementRepository = new MockAggregatedMeasurementRepository(); + _measurementRepository = new MockAggregatedMeasurementRepository(); _measurementController = new MeasurementController( NullLogger.Instance, - _aggregatedMeasurementRepository, - _trackerRepository); + _roomRepository, + _trackerRepository, + _measurementRepository + ); _localizationService = new LocalizationService( NullLogger.Instance, - _aggregatedMeasurementRepository, + _measurementRepository, _roomRepository ); } @@ -61,10 +63,10 @@ public void Setup() [TearDown] public void TearDown() { - var aggregatedMeasurements = _aggregatedMeasurementRepository.GetAggregatedMeasurementsAsync(_roomId, default).GetAwaiter().GetResult(); + var aggregatedMeasurements = _measurementRepository.GetAggregatedMeasurementsAsync(_roomId, default).GetAwaiter().GetResult(); foreach (var measurement in aggregatedMeasurements) { - _aggregatedMeasurementRepository.RemoveAggregatedMeasurementAsync(measurement, default).GetAwaiter().GetResult(); + _measurementRepository.RemoveAggregatedMeasurementAsync(measurement, default).GetAwaiter().GetResult(); } } @@ -78,7 +80,7 @@ public async Task TestAddMeasurements() var addMeasurementsRequest = new AddMeasurementsRequest(_trackerId, measurements); await _measurementController.AddMeasurements(addMeasurementsRequest, default); - var addedMeasurements = (await _aggregatedMeasurementRepository.GetRoomMeasurementGroupsAsync(default))[_roomId][0].Measurements; + var addedMeasurements = (await _measurementRepository.GetRoomMeasurementGroupsAsync(default))[_roomId][0].Measurements; Assert.That(addedMeasurements, Has.Count.EqualTo(measurements.Length)); Assert.That(addedMeasurements, Does.Contain(measurements[0])); @@ -95,7 +97,7 @@ public async Task TrackersFilteredFromMeasurements() var addMeasurementsRequest = new AddMeasurementsRequest(_trackerId, measurements); await _measurementController.AddMeasurements(addMeasurementsRequest, default); - var addedMeasurements = (await _aggregatedMeasurementRepository.GetRoomMeasurementGroupsAsync(default))[_roomId][0].Measurements; + var addedMeasurements = (await _measurementRepository.GetRoomMeasurementGroupsAsync(default))[_roomId][0].Measurements; Assert.That(addedMeasurements, Has.Count.EqualTo(0)); } @@ -111,15 +113,6 @@ public async Task CalibrateMeasurements() var addMeasurementsRequest = new AddMeasurementsRequest(_trackerId, measurements); await _measurementController.AddMeasurements(addMeasurementsRequest, default); - var measurements2 = new Measurement[] { - new Measurement("13:22:33:44:55:66", Measurement.Protocol.Bluetooth, 10), - new Measurement("ac:bb:cc:dd:ee:ff", Measurement.Protocol.Wifi, 20), - new Measurement("14:22:33:44:55:66", Measurement.Protocol.Bluetooth, 10), - new Measurement("ab:bb:cc:dd:ee:ff", Measurement.Protocol.Wifi, 20) - }; - - var addMeasurementsRequest2 = new AddMeasurementsRequest(_trackerId, measurements2); - await _measurementController.AddMeasurements(addMeasurementsRequest2, default); await _localizationService.AggregateMeasurementsAsync(default); var measurements3 = new Measurement[] { @@ -135,15 +128,7 @@ public async Task CalibrateMeasurements() var lastAggregatedMeasurements = (await _measurementController.GetAggregateMeasurements(_roomId, default)).AggregatedMeasurements.Last(); - Assert.That(lastAggregatedMeasurements.BluetoothMedian, Is.EqualTo(1)); - Assert.That(lastAggregatedMeasurements.WifiMedian, Is.EqualTo(1)); - Assert.That(lastAggregatedMeasurements.BluetoothMean, Is.EqualTo(1f)); - Assert.That(lastAggregatedMeasurements.WifiMean, Is.EqualTo(1f)); - Assert.That(lastAggregatedMeasurements.BluetoothMax, Is.EqualTo(1)); - Assert.That(lastAggregatedMeasurements.WifiMax, Is.EqualTo(1)); - Assert.That(lastAggregatedMeasurements.BluetoothMin, Is.EqualTo(1)); - Assert.That(lastAggregatedMeasurements.WifiMin, Is.EqualTo(1)); - Assert.That(lastAggregatedMeasurements.TotalBluetoothDeviceCount, Is.EqualTo(1)); - Assert.That(lastAggregatedMeasurements.TotalWifiDeviceCount, Is.EqualTo(1)); + Assert.That(lastAggregatedMeasurements.BluetoothCount, Is.EqualTo(1)); + Assert.That(lastAggregatedMeasurements.WifiCount, Is.EqualTo(1)); } } \ No newline at end of file diff --git a/CentralHub.Api.Tests/ServiceTests.cs b/CentralHub.Api.Tests/ServiceTests.cs index b4f3ea9..eb92395 100644 --- a/CentralHub.Api.Tests/ServiceTests.cs +++ b/CentralHub.Api.Tests/ServiceTests.cs @@ -75,17 +75,8 @@ public async Task TestAggregateSingleGroupMeasurements() var aggregatedMeasurement = aggregatedMeasurements.First(); - Assert.That(aggregatedMeasurement.MeasurementGroupCount, Is.EqualTo(1)); - Assert.That(aggregatedMeasurement.BluetoothMedianDeviceCount, Is.EqualTo(1)); - Assert.That(aggregatedMeasurement.WifiMedianDeviceCount, Is.EqualTo(1)); - Assert.That(aggregatedMeasurement.BluetoothMeanDeviceCount, Is.EqualTo(1f)); - Assert.That(aggregatedMeasurement.WifiMeanDeviceCount, Is.EqualTo(1f)); - Assert.That(aggregatedMeasurement.BluetoothMaxDeviceCount, Is.EqualTo(1)); - Assert.That(aggregatedMeasurement.WifiMaxDeviceCount, Is.EqualTo(1)); - Assert.That(aggregatedMeasurement.BluetoothMinDeviceCount, Is.EqualTo(1)); - Assert.That(aggregatedMeasurement.WifiMinDeviceCount, Is.EqualTo(1)); - Assert.That(aggregatedMeasurement.TotalBluetoothDeviceCount, Is.EqualTo(1)); - Assert.That(aggregatedMeasurement.TotalWifiDeviceCount, Is.EqualTo(1)); + Assert.That(aggregatedMeasurement.BluetoothCount, Is.EqualTo(1)); + Assert.That(aggregatedMeasurement.WifiCount, Is.EqualTo(1)); } [Test] @@ -116,17 +107,8 @@ public async Task TestAggregateMultipleGroupsOfMeasurements() var aggregatedMeasurement = aggregatedMeasurements.First(); - Assert.That(aggregatedMeasurement.MeasurementGroupCount, Is.EqualTo(2)); - Assert.That(aggregatedMeasurement.BluetoothMedianDeviceCount, Is.EqualTo(3)); - Assert.That(aggregatedMeasurement.WifiMedianDeviceCount, Is.EqualTo(3)); - Assert.That(aggregatedMeasurement.BluetoothMeanDeviceCount, Is.EqualTo(2.5f)); - Assert.That(aggregatedMeasurement.WifiMeanDeviceCount, Is.EqualTo(2.5f)); - Assert.That(aggregatedMeasurement.BluetoothMaxDeviceCount, Is.EqualTo(3)); - Assert.That(aggregatedMeasurement.WifiMaxDeviceCount, Is.EqualTo(3)); - Assert.That(aggregatedMeasurement.BluetoothMinDeviceCount, Is.EqualTo(2)); - Assert.That(aggregatedMeasurement.WifiMinDeviceCount, Is.EqualTo(2)); - Assert.That(aggregatedMeasurement.TotalBluetoothDeviceCount, Is.EqualTo(5)); - Assert.That(aggregatedMeasurement.TotalWifiDeviceCount, Is.EqualTo(5)); + Assert.That(aggregatedMeasurement.BluetoothCount, Is.EqualTo(5)); + Assert.That(aggregatedMeasurement.WifiCount, Is.EqualTo(5)); } [Test] @@ -148,9 +130,8 @@ public async Task TestAggregateDuplicateMeasurements() var aggregatedMeasurement = aggregatedMeasurements.First(); - Assert.That(aggregatedMeasurement.MeasurementGroupCount, Is.EqualTo(1)); - Assert.That(aggregatedMeasurement.TotalBluetoothDeviceCount, Is.EqualTo(1)); - Assert.That(aggregatedMeasurement.TotalWifiDeviceCount, Is.EqualTo(1)); + Assert.That(aggregatedMeasurement.BluetoothCount, Is.EqualTo(1)); + Assert.That(aggregatedMeasurement.WifiCount, Is.EqualTo(1)); } [Test] @@ -165,16 +146,7 @@ public async Task TestNoMeasurements() var aggregatedMeasurement = aggregatedMeasurements.First(); - Assert.That(aggregatedMeasurement.MeasurementGroupCount, Is.EqualTo(1)); - Assert.That(aggregatedMeasurement.BluetoothMedianDeviceCount, Is.EqualTo(0)); - Assert.That(aggregatedMeasurement.WifiMedianDeviceCount, Is.EqualTo(0)); - Assert.That(aggregatedMeasurement.BluetoothMeanDeviceCount, Is.EqualTo(0)); - Assert.That(aggregatedMeasurement.WifiMeanDeviceCount, Is.EqualTo(0)); - Assert.That(aggregatedMeasurement.BluetoothMaxDeviceCount, Is.EqualTo(0)); - Assert.That(aggregatedMeasurement.WifiMaxDeviceCount, Is.EqualTo(0)); - Assert.That(aggregatedMeasurement.BluetoothMinDeviceCount, Is.EqualTo(0)); - Assert.That(aggregatedMeasurement.WifiMinDeviceCount, Is.EqualTo(0)); - Assert.That(aggregatedMeasurement.TotalBluetoothDeviceCount, Is.EqualTo(0)); - Assert.That(aggregatedMeasurement.TotalWifiDeviceCount, Is.EqualTo(0)); + Assert.That(aggregatedMeasurement.BluetoothCount, Is.EqualTo(0)); + Assert.That(aggregatedMeasurement.WifiCount, Is.EqualTo(0)); } } \ No newline at end of file diff --git a/CentralHub.Api/Controllers/MeasurementController.cs b/CentralHub.Api/Controllers/MeasurementController.cs index 2e7b069..9f0e1e6 100644 --- a/CentralHub.Api/Controllers/MeasurementController.cs +++ b/CentralHub.Api/Controllers/MeasurementController.cs @@ -1,6 +1,5 @@ using System.Collections.Immutable; using CentralHub.Api.Dtos; -using CentralHub.Api.Model; using CentralHub.Api.Model.Requests.Localization; using CentralHub.Api.Model.Responses.AggregatedMeasurements; using CentralHub.Api.Model.Responses.Measurements; @@ -11,29 +10,18 @@ namespace CentralHub.Api.Controllers; [ApiController] [Route("/measurements")] -public sealed class MeasurementController : ControllerBase +public sealed class MeasurementController(ILogger logger, + IRoomRepository roomRepository, + ITrackerRepository trackerRepository, + IMeasurementRepository measurementRepository) + : ControllerBase { - private readonly ILogger _logger; - - private readonly IMeasurementRepository _measurementRepository; - - private readonly ITrackerRepository _trackerRepository; - - public MeasurementController( - ILogger logger, - IMeasurementRepository measurementRepository, - ITrackerRepository trackerRepository) - { - _logger = logger; - _measurementRepository = measurementRepository; - _trackerRepository = trackerRepository; - } - [HttpPost("add")] public async Task AddMeasurements(AddMeasurementsRequest addMeasurementsRequest, CancellationToken token) { - var registeredTrackers = await _trackerRepository.GetRegisteredTrackers(token); - var unregisteredTrackers = await _trackerRepository.GetUnregisteredTrackers(token); + var registeredTrackers = (await trackerRepository.GetRegisteredTrackers(token)) + .ToImmutableArray(); + var unregisteredTrackers = await trackerRepository.GetUnregisteredTrackers(token); var tracker = registeredTrackers.SingleOrDefault(t => t.TrackerDtoId == addMeasurementsRequest.TrackerId); @@ -42,7 +30,7 @@ public async Task AddMeasurements(AddMeasurementsReques return AddMeasurementsResponse.CreateUnsuccessful(); } - await _measurementRepository.AddMeasurementsAsync( + await measurementRepository.AddMeasurementsAsync( tracker.RoomDtoId, addMeasurementsRequest.Measurements .Where(m => !registeredTrackers.Any(t => t.WifiMacAddress == m.MacAddress || t.BluetoothMacAddress == m.MacAddress)) @@ -55,13 +43,15 @@ await _measurementRepository.AddMeasurementsAsync( [HttpGet("all")] public async Task GetAggregateMeasurements(int roomId, CancellationToken token) { - var aggregatedMeasurements = await _measurementRepository.GetAggregatedMeasurementsAsync(roomId, token); - - if (aggregatedMeasurements == null) + var possibleRoom = await roomRepository.GetRoomByIdAsync(roomId, token); + if (possibleRoom == null) { return GetAggregatedMeasurementsResponse.CreateUnsuccessful(); } + var aggregatedMeasurements = (await measurementRepository.GetAggregatedMeasurementsAsync(roomId, token)) + .ToImmutableArray(); + return GetAggregatedMeasurementsResponse .CreateSuccessful(CreateMeasurements(aggregatedMeasurements)); } @@ -69,13 +59,15 @@ public async Task GetAggregateMeasurements(in [HttpGet("range")] public async Task GetAggregateMeasurements(int roomId, DateTime timeStart, DateTime timeEnd, CancellationToken token) { - var aggregatedMeasurements = await _measurementRepository.GetAggregatedMeasurementsAsync(roomId, timeStart, timeEnd, token); - - if (aggregatedMeasurements == null) + var possibleRoom = await roomRepository.GetRoomByIdAsync(roomId, token); + if (possibleRoom == null) { return GetAggregatedMeasurementsResponse.CreateUnsuccessful(); } + var aggregatedMeasurements = (await measurementRepository.GetAggregatedMeasurementsAsync(roomId, timeStart, timeEnd, token)) + .ToImmutableArray(); + return GetAggregatedMeasurementsResponse .CreateSuccessful(CreateMeasurements(aggregatedMeasurements)); } @@ -85,7 +77,7 @@ public async Task GetFirstAggreg CancellationToken cancellationToken) { var possibleFirstDateTime = - await _measurementRepository.GetFirstAggregatedMeasurementsDateTimeAsync(roomId, cancellationToken); + await measurementRepository.GetFirstAggregatedMeasurementsDateTimeAsync(roomId, cancellationToken); if (possibleFirstDateTime == null) { @@ -95,27 +87,21 @@ public async Task GetFirstAggreg return GetFirstAggregatedMeasurementsDateTimeResponse.CreateSuccessful(possibleFirstDateTime.Value); } - private static IReadOnlyList CreateMeasurements(IEnumerable aggregatedMeasurements) + private static IReadOnlyList CreateMeasurements(IReadOnlyCollection aggregatedMeasurements) { - var recentAggregatedMeasurements = aggregatedMeasurements.Where(am => am.EndTime > (DateTime.UtcNow - TimeSpan.FromDays(1))); - var wifiCalibrationNumber = recentAggregatedMeasurements.Min(am => am.WifiMinDeviceCount); - var bluetoothCalibrationNumber = recentAggregatedMeasurements.Min(am => am.BluetoothMinDeviceCount); + var recentAggregatedMeasurements = aggregatedMeasurements + .Where(am => am.EndTime > (DateTime.UtcNow - TimeSpan.FromDays(1))) + .ToImmutableArray(); + + var bluetoothCalibrationNumber = recentAggregatedMeasurements.Min(am => am.BluetoothCount); + var wifiCalibrationNumber = recentAggregatedMeasurements.Min(am => am.WifiCount); return aggregatedMeasurements.Select(am => new AggregatedMeasurements( am.AggregatedMeasurementDtoId, am.StartTime, am.EndTime, - am.MeasurementGroupCount, - am.BluetoothMedianDeviceCount - bluetoothCalibrationNumber, - am.BluetoothMeanDeviceCount - bluetoothCalibrationNumber, - am.BluetoothMinDeviceCount - bluetoothCalibrationNumber, - am.BluetoothMaxDeviceCount - bluetoothCalibrationNumber, - am.TotalBluetoothDeviceCount - bluetoothCalibrationNumber, - am.WifiMedianDeviceCount - wifiCalibrationNumber, - am.WifiMeanDeviceCount - wifiCalibrationNumber, - am.WifiMinDeviceCount - wifiCalibrationNumber, - am.WifiMaxDeviceCount - wifiCalibrationNumber, - am.TotalWifiDeviceCount - wifiCalibrationNumber) + am.BluetoothCount - bluetoothCalibrationNumber, + am.WifiCount - wifiCalibrationNumber) ).ToImmutableArray(); } } diff --git a/CentralHub.Api/Dtos/AggregatedMeasurementDto.cs b/CentralHub.Api/Dtos/AggregatedMeasurementDto.cs index 6c50992..528d7ee 100644 --- a/CentralHub.Api/Dtos/AggregatedMeasurementDto.cs +++ b/CentralHub.Api/Dtos/AggregatedMeasurementDto.cs @@ -8,27 +8,9 @@ public sealed class AggregatedMeasurementDto public required DateTime EndTime { get; set; } - public required int MeasurementGroupCount { get; set; } + public required int BluetoothCount { get; set; } - public required int BluetoothMedianDeviceCount { get; set; } - - public required double BluetoothMeanDeviceCount { get; set; } - - public required int BluetoothMinDeviceCount { get; set; } - - public required int BluetoothMaxDeviceCount { get; set; } - - public required int TotalBluetoothDeviceCount { get; set; } - - public required int WifiMedianDeviceCount { get; set; } - - public required double WifiMeanDeviceCount { get; set; } - - public required int WifiMinDeviceCount { get; set; } - - public required int WifiMaxDeviceCount { get; set; } - - public required int TotalWifiDeviceCount { get; set; } + public required int WifiCount { get; set; } public required int RoomDtoId { get; set; } diff --git a/CentralHub.Api/Services/LocalizationService.cs b/CentralHub.Api/Services/LocalizationService.cs index 7b257db..33223d6 100644 --- a/CentralHub.Api/Services/LocalizationService.cs +++ b/CentralHub.Api/Services/LocalizationService.cs @@ -8,7 +8,7 @@ namespace CentralHub.Api.Services; public class LocalizationService : IScopedProcessingService { - private static readonly TimeSpan _sleepTime = TimeSpan.FromMinutes(2); + private static readonly TimeSpan SleepTime = TimeSpan.FromMinutes(2); private readonly ILogger _logger; private readonly IMeasurementRepository _aggregatorRepository; @@ -30,7 +30,7 @@ public async Task DoWorkAsync(CancellationToken stoppingToken) while (!stoppingToken.IsCancellationRequested) { await AggregateMeasurementsAsync(stoppingToken); - await Task.Delay(_sleepTime, stoppingToken); + await Task.Delay(SleepTime, stoppingToken); } } @@ -70,40 +70,14 @@ await _aggregatorRepository.AddAggregatedMeasurementAsync( private static AggregatedMeasurementDto CreateAggregatedMeasurement(RoomDto room, IReadOnlyCollection measurementGroups) { var measurements = measurementGroups.SelectMany(mg => mg.Measurements); - var bluetooth = measurements.Where(m => m.Type == Measurement.Protocol.Bluetooth); - var wifi = measurements.Where(m => m.Type == Measurement.Protocol.Wifi); + var filteredMeasurements = FilterMeasurements(measurements).ToImmutableArray(); + var bluetoothCount = filteredMeasurements.Count(m => m.Type == Measurement.Protocol.Bluetooth); + var wifiCount = filteredMeasurements.Count(m => m.Type == Measurement.Protocol.Wifi); var now = DateTime.UtcNow; - var startMeasurementTime = measurementGroups.Count != 0 ? measurementGroups.Min(mg => mg.Timestamp) : now - _sleepTime; + var startMeasurementTime = measurementGroups.Count != 0 ? measurementGroups.Min(mg => mg.Timestamp) : now - SleepTime; var endMeasurementTime = measurementGroups.Count != 0 ? measurementGroups.Max(mg => mg.Timestamp) : now; - var filteredMeasurementsGroups = measurementGroups.Select(mg => FilterMeasurements(mg.Measurements)).ToImmutableArray(); - var numBluetoothPerGroup = filteredMeasurementsGroups.Select(m => m.Count(m => m.Type == Measurement.Protocol.Bluetooth)).ToImmutableArray(); - var numWifiPerGroup = filteredMeasurementsGroups.Select(m => m.Count(m => m.Type == Measurement.Protocol.Wifi)).ToImmutableArray(); - - - var measurementGroupCount = measurementGroups.Count != 0 ? measurementGroups.Count : 1; - - var bluetoothMax = MaxDevices(numBluetoothPerGroup); - - var bluetoothMedian = MedianDevices(numBluetoothPerGroup); - - var bluetoothMean = MeanDevices(numBluetoothPerGroup); - - var bluetoothMin = MinDevices(numBluetoothPerGroup); - - var bluetoothCount = FilterMeasurements(bluetooth).Count(); - - var wifiMax = MaxDevices(numWifiPerGroup); - - var wifiMedian = MedianDevices(numWifiPerGroup); - - var wifiMean = MeanDevices(numWifiPerGroup); - - var wifiMin = MinDevices(numWifiPerGroup); - - var wifiCount = FilterMeasurements(wifi).Count(); - var roomDtoId = room.RoomDtoId; var roomDto = room; @@ -112,17 +86,8 @@ private static AggregatedMeasurementDto CreateAggregatedMeasurement(RoomDto room { StartTime = startMeasurementTime, EndTime = endMeasurementTime, - MeasurementGroupCount = measurementGroupCount, - BluetoothMaxDeviceCount = bluetoothMax, - BluetoothMedianDeviceCount = bluetoothMedian, - BluetoothMeanDeviceCount = bluetoothMean, - BluetoothMinDeviceCount = bluetoothMin, - TotalBluetoothDeviceCount = bluetoothCount, - WifiMaxDeviceCount = wifiMax, - WifiMedianDeviceCount = wifiMedian, - WifiMeanDeviceCount = wifiMean, - WifiMinDeviceCount = wifiMin, - TotalWifiDeviceCount = wifiCount, + BluetoothCount = bluetoothCount, + WifiCount = wifiCount, RoomDtoId = roomDtoId, RoomDto = roomDto }; @@ -147,47 +112,6 @@ private static IEnumerable FilterMeasurements(IEnumerable numMatchingProtocolPerGroup) - { - if (!numMatchingProtocolPerGroup.Any()) - { - return 0; - } - - return numMatchingProtocolPerGroup.Max(); - } - - private static int MinDevices(IEnumerable numMatchingProtocolPerGroup) - { - if (!numMatchingProtocolPerGroup.Any()) - { - return 0; - } - - return numMatchingProtocolPerGroup.Min(); - } - - private static int MedianDevices(IEnumerable numMatchingProtocolPerGroup) - { - if (!numMatchingProtocolPerGroup.Any()) - { - return 0; - } - - return numMatchingProtocolPerGroup - .Order() - .ElementAt((int)Math.Floor(numMatchingProtocolPerGroup.Count() / 2f)); - } - - private static double MeanDevices(IEnumerable numMatchingProtocolPerGroup) - { - if (!numMatchingProtocolPerGroup.Any()) - { - return 0; - } - - return numMatchingProtocolPerGroup.Average(); - } private readonly struct FilterCriteria { public string MacAddress { get; } diff --git a/CentralHub.WebUI/Data/MeasurementService.cs b/CentralHub.WebUI/Data/MeasurementService.cs index 4d2511a..a2c7569 100644 --- a/CentralHub.WebUI/Data/MeasurementService.cs +++ b/CentralHub.WebUI/Data/MeasurementService.cs @@ -47,7 +47,7 @@ public async Task> GetAggregatedMeas return getAggregatedMeasurementsResponse.AggregatedMeasurements!; } - public async Task GetFirstAggregatedMeasurementsDateTime(int roomId, CancellationToken cancellationToken) + public async Task GetFirstAggregatedMeasurementsDateTime(int roomId, CancellationToken cancellationToken) { var request = new HttpRequestMessage( HttpMethod.Get, @@ -68,9 +68,9 @@ public async Task GetFirstAggregatedMeasurementsDateTime(int roomId, C if (getFirstAggregatedMeasurementsDateTimeResponse == null || !getFirstAggregatedMeasurementsDateTimeResponse.Success) { - throw new InvalidOperationException("Unsuccessful!"); + return null; } - return getFirstAggregatedMeasurementsDateTimeResponse.FirstDateTime.Value; + return getFirstAggregatedMeasurementsDateTimeResponse.FirstDateTime; } } \ No newline at end of file diff --git a/CentralHub.WebUI/Pages/Charts.razor b/CentralHub.WebUI/Pages/Charts.razor index 8cc5b20..7f3c491 100644 --- a/CentralHub.WebUI/Pages/Charts.razor +++ b/CentralHub.WebUI/Pages/Charts.razor @@ -1,9 +1,8 @@ @page "/charts/{roomId:int}" @using ApexCharts -@using CentralHub.Api.Model.Responses.AggregatedMeasurements @using CentralHub.WebUI.Data -@using System.Collections.Immutable @using System.Globalization +@using CentralHub.Api.Model.Responses.Measurements @implements IDisposable @inject MeasurementService MeasurementService @@ -29,64 +28,24 @@
-
- - - - - -
-
- - +
+ @@ -101,11 +60,9 @@ private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource(); - private IReadOnlyCollection? _data1; - private IReadOnlyCollection? _data2; + private IReadOnlyCollection? _aggregatedMeasurements; - private readonly ApexChartOptions _options1 = new(); - private readonly ApexChartOptions _options2 = new(); + private readonly ApexChartOptions _chartOptions = new(); private DateTime _firstDateTime; @@ -122,8 +79,7 @@ { await UpdateAggregatedMeasurements(); StateHasChanged(); - await _wifiChart!.RenderAsync(); - await _bluetoothChart!.RenderAsync(); + await _chart!.RenderAsync(); }); } } @@ -136,86 +92,40 @@ { await UpdateAggregatedMeasurements(); StateHasChanged(); - await _wifiChart!.RenderAsync(); - await _bluetoothChart!.RenderAsync(); + await _chart!.RenderAsync(); }); } } - private ApexChart? _wifiChart; - private ApexChart? _bluetoothChart; + private ApexChart? _chart; private async Task UpdateAggregatedMeasurements() { - _data1 = await MeasurementService.GetAggregatedMeasurements(RoomId, MinDateTime.ToUniversalTime(), MaxDateTime.ToUniversalTime(), _cancellationTokenSource.Token); + _aggregatedMeasurements = await MeasurementService.GetAggregatedMeasurements(RoomId, MinDateTime.ToUniversalTime(), MaxDateTime.ToUniversalTime(), _cancellationTokenSource.Token); // HACK!: Add dummy data because the charts crash if there is no data and a page reload is necessary to get it back - if (!_data1.Any()) + if (!_aggregatedMeasurements.Any()) { - _data1 = new[] {new AggregatedMeasurements(0, MinDateTime.ToUniversalTime(), MaxDateTime.ToUniversalTime(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)}; + _aggregatedMeasurements = new[] {new AggregatedMeasurements(0, MinDateTime.ToUniversalTime(), MaxDateTime.ToUniversalTime(), 0, 0)}; } - _data2 = _data1.ToImmutableArray(); } protected override async Task OnInitializedAsync() { - _firstDateTime = await MeasurementService.GetFirstAggregatedMeasurementsDateTime(RoomId, _cancellationTokenSource.Token); + _firstDateTime = (await MeasurementService.GetFirstAggregatedMeasurementsDateTime(RoomId, _cancellationTokenSource.Token)).GetValueOrDefault(); await UpdateAggregatedMeasurements(); - _options1.Chart = new Chart() - { - Type = ChartType.RangeArea - }; - - _options1.Colors = new List { "#d4526e", "#ff3300", "#0033ff" }; - _options1.Fill = new Fill - { - Opacity = new List { 0.24, 1, 1 } - }; - - _options1.Yaxis = new List() - { - new YAxis() - { - Labels = new () - { - Formatter = @" - function (val) { - return val.toFixed(0); - } - ", - }, - }, - }; - - _options1.Tooltip = new Tooltip() - { - Y = new TooltipY() - { - Formatter = @" - function (val) { - return val.toString(); - } - ", - }, - }; - - _options1.Xaxis = new XAxis() - { - Type = XAxisType.Datetime, - }; - - _options2.Chart = new Chart() + _chartOptions.Chart = new Chart() { Type = ChartType.RangeArea }; - _options2.Colors = new List { "#d4526e", "#ff3300", "#0033ff" }; - _options2.Fill = new Fill + _chartOptions.Colors = new List { "#d4526e", "#ff3300", "#0033ff" }; + _chartOptions.Fill = new Fill { Opacity = new List { 0.24, 1, 1 } }; - _options2.Yaxis = new List() + _chartOptions.Yaxis = new List() { new YAxis() { @@ -230,7 +140,7 @@ }, }; - _options2.Tooltip = new Tooltip() + _chartOptions.Tooltip = new Tooltip() { Y = new TooltipY() { @@ -242,7 +152,7 @@ }, }; - _options2.Xaxis = new XAxis() + _chartOptions.Xaxis = new XAxis() { Type = XAxisType.Datetime, };