Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calbrate measurements #39

Merged
merged 3 commits into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 57 additions & 2 deletions CentralHub.Api.Tests/MeasurementControllerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ public class MeasurementControllerTests
private ITrackerRepository _trackerRepository;
private IMeasurementRepository _aggregatedMeasurementRepository;

private LocalizationService _localizationService;

private int _roomId = 0;

private int _trackerId = 0;
Expand Down Expand Up @@ -48,6 +50,12 @@ public void Setup()
NullLogger<MeasurementController>.Instance,
_aggregatedMeasurementRepository,
_trackerRepository);

_localizationService = new LocalizationService(
NullLogger<LocalizationService>.Instance,
_aggregatedMeasurementRepository,
_roomRepository
);
}

[TearDown]
Expand All @@ -70,7 +78,7 @@ public async Task TestAddMeasurements()

var addMeasurementsRequest = new AddMeasurementsRequest(_trackerId, measurements);
await _measurementController.AddMeasurements(addMeasurementsRequest, default);
var addedMeasurements = (await _aggregatedMeasurementRepository.GetRoomMeasurementGroupsAsync(default))[_trackerId][0].Measurements;
var addedMeasurements = (await _aggregatedMeasurementRepository.GetRoomMeasurementGroupsAsync(default))[_roomId][0].Measurements;

Assert.That(addedMeasurements, Has.Count.EqualTo(measurements.Length));
Assert.That(addedMeasurements, Does.Contain(measurements[0]));
Expand All @@ -87,8 +95,55 @@ public async Task TrackersFilteredFromMeasurements()

var addMeasurementsRequest = new AddMeasurementsRequest(_trackerId, measurements);
await _measurementController.AddMeasurements(addMeasurementsRequest, default);
var addedMeasurements = (await _aggregatedMeasurementRepository.GetRoomMeasurementGroupsAsync(default))[_trackerId][0].Measurements;
var addedMeasurements = (await _aggregatedMeasurementRepository.GetRoomMeasurementGroupsAsync(default))[_roomId][0].Measurements;

Assert.That(addedMeasurements, Has.Count.EqualTo(0));
}

[Test]
public async Task CalibrateMeasurements()
{
var measurements = new Measurement[] {
new Measurement("12:22:33:44:55:66", Measurement.Protocol.Bluetooth, 10),
new Measurement("ab:bb:cc:dd:ee:ff", Measurement.Protocol.Wifi, 20)
};

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[] {
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 addMeasurementsRequest3 = new AddMeasurementsRequest(_trackerId, measurements3);
await _measurementController.AddMeasurements(addMeasurementsRequest3, default);
await _localizationService.AggregateMeasurementsAsync(default);

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));
}
}
2 changes: 1 addition & 1 deletion CentralHub.Api.Tests/MockTrackerRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,6 @@ public Task AddUnregisteredTracker(string wifiMacAddress, string bluetoothMacAdd

public Task<IEnumerable<TrackerDto>> GetRegisteredTrackers(CancellationToken cancellationToken)
{
return Task.FromResult(RoomDto.Trackers.ToList().AsEnumerable());
return Task.FromResult(RoomDto.Trackers.ToArray().AsEnumerable());
}
}
51 changes: 30 additions & 21 deletions CentralHub.Api/Controllers/MeasurementController.cs
Original file line number Diff line number Diff line change
@@ -1,4 +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;
Expand Down Expand Up @@ -61,38 +62,22 @@ public async Task<GetAggregatedMeasurementsResponse> GetAggregateMeasurements(in
return GetAggregatedMeasurementsResponse.CreateUnsuccessful();
}

return GetAggregatedMeasurementsResponse.CreateSuccessful(
aggregatedMeasurements.Select(am => new AggregatedMeasurements(
am.AggregatedMeasurementDtoId,
am.StartTime,
am.EndTime,
am.MeasurementGroupCount,
am.BluetoothMedianDeviceCount,
am.BluetoothMeanDeviceCount,
am.BluetoothMaxDeviceCount,
am.BluetoothMinDeviceCount,
am.TotalBluetoothDeviceCount,
am.WifiMedianDeviceCount,
am.WifiMeanDeviceCount,
am.WifiMaxDeviceCount,
am.WifiMinDeviceCount,
am.TotalWifiDeviceCount)).ToImmutableArray());
return GetAggregatedMeasurementsResponse
.CreateSuccessful(CreateMeasurements(aggregatedMeasurements));
}

[HttpGet("range")]
public async Task<GetAggregatedMeasurementsResponse> GetAggregateMeasurements(int roomId, DateTime timeStart, DateTime timeEnd, CancellationToken token)
{
var aggregatedMeasurements = await GetAggregateMeasurements(roomId, token);
var aggregatedMeasurements = await _measurementRepository.GetAggregatedMeasurementsAsync(roomId, timeStart, timeEnd, token);

if (!aggregatedMeasurements.Success)
if (aggregatedMeasurements == null)
{
return GetAggregatedMeasurementsResponse.CreateUnsuccessful();
}

return GetAggregatedMeasurementsResponse
.CreateSuccessful(aggregatedMeasurements.AggregatedMeasurements!
.Where(am => am.StartTime >= timeStart && am.EndTime <= timeEnd)
.ToImmutableArray());
.CreateSuccessful(CreateMeasurements(aggregatedMeasurements));
}

[HttpGet("first")]
Expand All @@ -109,4 +94,28 @@ public async Task<GetFirstAggregatedMeasurementsDateTimeResponse> GetFirstAggreg

return GetFirstAggregatedMeasurementsDateTimeResponse.CreateSuccessful(possibleFirstDateTime.Value);
}

private static IReadOnlyList<AggregatedMeasurements> CreateMeasurements(IEnumerable<AggregatedMeasurementDto> 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);

return aggregatedMeasurements.Select(am => new AggregatedMeasurements(
am.AggregatedMeasurementDtoId,
am.StartTime,
am.EndTime,
am.MeasurementGroupCount,
am.BluetoothMedianDeviceCount - bluetoothCalibrationNumber,
am.BluetoothMeanDeviceCount - bluetoothCalibrationNumber,
am.BluetoothMaxDeviceCount - bluetoothCalibrationNumber,
am.BluetoothMinDeviceCount - bluetoothCalibrationNumber,
am.TotalBluetoothDeviceCount - bluetoothCalibrationNumber,
am.WifiMedianDeviceCount - wifiCalibrationNumber,
am.WifiMeanDeviceCount - wifiCalibrationNumber,
am.WifiMaxDeviceCount - wifiCalibrationNumber,
am.WifiMinDeviceCount - wifiCalibrationNumber,
am.TotalWifiDeviceCount - wifiCalibrationNumber)
).ToImmutableArray();
}
}
2 changes: 1 addition & 1 deletion CentralHub.Api/MeasurementGroup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ public class MeasurementGroup
{
public MeasurementGroup(IEnumerable<Measurement> measurements)
{
Timestamp = DateTime.Now;
Timestamp = DateTime.UtcNow;
Measurements = measurements.ToImmutableArray();
}
public DateTime Timestamp { get; }
Expand Down
4 changes: 2 additions & 2 deletions CentralHub.Api/Services/LocalizationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
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 now = DateTime.Now;
var now = DateTime.UtcNow;

var startMeasurementTime = measurementGroups.Count != 0 ? measurementGroups.Min(mg => mg.Timestamp) : now - _sleepTime;
var endMeasurementTime = measurementGroups.Count != 0 ? measurementGroups.Max(mg => mg.Timestamp) : now;
Expand Down Expand Up @@ -133,7 +133,7 @@
/// </summary>
/// <param name="measurements">An enumerable collection of the measurements</param>
/// <returns>An enumerable collection of measurements with only unique macAddresses.</returns>
private static IEnumerable<Measurement> FilterMeasurements(IEnumerable<Measurement> measurements)

Check warning on line 136 in CentralHub.Api/Services/LocalizationService.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

Change return type of method 'FilterMeasurements' from 'System.Collections.Generic.IEnumerable<CentralHub.Api.Model.Measurement>' to 'System.Collections.Generic.Dictionary<CentralHub.Api.Services.LocalizationService.FilterCriteria, CentralHub.Api.Model.Measurement>.ValueCollection' for improved performance (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1859)

Check warning on line 136 in CentralHub.Api/Services/LocalizationService.cs

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest)

Change return type of method 'FilterMeasurements' from 'System.Collections.Generic.IEnumerable<CentralHub.Api.Model.Measurement>' to 'System.Collections.Generic.Dictionary<CentralHub.Api.Services.LocalizationService.FilterCriteria, CentralHub.Api.Model.Measurement>.ValueCollection' for improved performance (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1859)

Check warning on line 136 in CentralHub.Api/Services/LocalizationService.cs

View workflow job for this annotation

GitHub Actions / build (macos-latest)

Change return type of method 'FilterMeasurements' from 'System.Collections.Generic.IEnumerable<CentralHub.Api.Model.Measurement>' to 'System.Collections.Generic.Dictionary<CentralHub.Api.Services.LocalizationService.FilterCriteria, CentralHub.Api.Model.Measurement>.ValueCollection' for improved performance (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1859)

Check warning on line 136 in CentralHub.Api/Services/LocalizationService.cs

View workflow job for this annotation

GitHub Actions / build (macos-latest)

Change return type of method 'FilterMeasurements' from 'System.Collections.Generic.IEnumerable<CentralHub.Api.Model.Measurement>' to 'System.Collections.Generic.Dictionary<CentralHub.Api.Services.LocalizationService.FilterCriteria, CentralHub.Api.Model.Measurement>.ValueCollection' for improved performance (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1859)

Check warning on line 136 in CentralHub.Api/Services/LocalizationService.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest)

Change return type of method 'FilterMeasurements' from 'System.Collections.Generic.IEnumerable<CentralHub.Api.Model.Measurement>' to 'System.Collections.Generic.Dictionary<CentralHub.Api.Services.LocalizationService.FilterCriteria, CentralHub.Api.Model.Measurement>.ValueCollection' for improved performance (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1859)

Check warning on line 136 in CentralHub.Api/Services/LocalizationService.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest)

Change return type of method 'FilterMeasurements' from 'System.Collections.Generic.IEnumerable<CentralHub.Api.Model.Measurement>' to 'System.Collections.Generic.Dictionary<CentralHub.Api.Services.LocalizationService.FilterCriteria, CentralHub.Api.Model.Measurement>.ValueCollection' for improved performance (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1859)
{
var filteredMeasurements = new Dictionary<FilterCriteria, Measurement>();
foreach (var (filterCriteria, measurement) in measurements.Select(m => (new FilterCriteria(m.MacAddress, m.Type), m)))
Expand All @@ -144,7 +144,7 @@
}
}

return filteredMeasurements.Values.Where(m => m.Rssi >= -75);
return filteredMeasurements.Values;
}

private static int MaxDevices(IEnumerable<int> numMatchingProtocolPerGroup)
Expand Down
Loading