Skip to content

Commit

Permalink
Add Global Settings / Improve Node Settings
Browse files Browse the repository at this point in the history
  • Loading branch information
DTTerastar committed Dec 31, 2024
1 parent ed4ff3b commit c762a74
Show file tree
Hide file tree
Showing 11 changed files with 466 additions and 62 deletions.
12 changes: 6 additions & 6 deletions src/Controllers/StateController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ public Calibration GetCalibration()
{
var rxNs = _nsd.Get(rxId);
var rxM = txM.GetOrAdd(rx.Rx?.Name ?? rxId);
if (txNs.TxRefRssi is not null) rxM["tx_ref_rssi"] = txNs.TxRefRssi.Value;
if (rxNs.RxAdjRssi is not null) rxM["rx_adj_rssi"] = rxNs.RxAdjRssi.Value;
if (rxNs.Absorption is not null) rxM["absorption"] = rxNs.Absorption.Value;
if (txNs.Calibration.TxRefRssi is not null) rxM["tx_ref_rssi"] = txNs.Calibration.TxRefRssi.Value;
if (rxNs.Calibration.RxAdjRssi is not null) rxM["rx_adj_rssi"] = rxNs.Calibration.RxAdjRssi.Value;
if (rxNs.Calibration.Absorption is not null) rxM["absorption"] = rxNs.Calibration.Absorption.Value;
rxM["expected"] = rx.Expected;
rxM["actual"] = rx.Distance;
rxM["rssi"] = rx.Rssi;
Expand Down Expand Up @@ -145,9 +145,9 @@ public async Task<IActionResult> ResetCalibration()
foreach (var node in _state.Nodes.Values)
{
var nodeSettings = _nsd.Get(node.Id);
nodeSettings.TxRefRssi = null;
nodeSettings.RxAdjRssi = null;
nodeSettings.Absorption = null;
nodeSettings.Calibration.TxRefRssi = null;
nodeSettings.Calibration.RxAdjRssi = null;
nodeSettings.Calibration.Absorption = null;
await _nsd.Set(node.Id, nodeSettings);
}

Expand Down
84 changes: 66 additions & 18 deletions src/Models/NodeSettings.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
using Newtonsoft.Json;

Expand All @@ -11,28 +11,76 @@ public class NodeSettings(string id)
[StringLength(64)]
public string? Id { get; set; } = id;

[JsonPropertyName("absorption")]
[JsonProperty("absorption")]
[Range(1, 10)]
public double? Absorption { get; set; }
[JsonPropertyName("updating")]
[JsonProperty("updating")]
public UpdatingSettings Updating { get; set; } = new UpdatingSettings();

[JsonPropertyName("rx_adj_rssi")]
[JsonProperty("rx_adj_rssi")]
[Range(-127, 128)]
public int? RxAdjRssi { get; set; }
[JsonPropertyName("scanning")]
[JsonProperty("scanning")]
public ScanningSettings Scanning { get; set; } = new ScanningSettings();

[JsonPropertyName("tx_ref_rssi")]
[JsonProperty("tx_ref_rssi")]
[Range(-127, 128)]
public int? TxRefRssi { get; set; }
[JsonPropertyName("counting")]
[JsonProperty("counting")]
public CountingSettings Counting { get; set; } = new CountingSettings();

[JsonPropertyName("max_distance")]
[JsonProperty("max_distance")]
[Range(0, 100)]
public double? MaxDistance { get; set; }
[JsonPropertyName("filtering")]
[JsonProperty("filtering")]
public FilteringSettings Filtering { get; set; } = new FilteringSettings();

[JsonPropertyName("calibration")]
[JsonProperty("calibration")]
public CalibrationSettings Calibration { get; set; } = new CalibrationSettings();

public NodeSettings Clone()
{
return (NodeSettings)MemberwiseClone();
return new NodeSettings(id)
{
Updating = Updating.Clone(),
Scanning = Scanning.Clone(),
Counting = Counting.Clone(),
Filtering = Filtering.Clone(),
Calibration = Calibration.Clone()
};
}
}

public class UpdatingSettings
{
public bool? AutoUpdate { get; set; }
public bool? PreRelease { get; set; }
public UpdatingSettings Clone() => (UpdatingSettings)MemberwiseClone();
}

public class ScanningSettings
{
public int? ForgetAfterMs { get; set; }
public ScanningSettings Clone() => (ScanningSettings)MemberwiseClone();
}

public class CountingSettings
{
public string? IdPrefixes { get; set; }
public double? StartCountingDistance { get; set; }
public double? StopCountingDistance { get; set; }
public int? IncludeDevicesAge { get; set; }
public CountingSettings Clone() => (CountingSettings)MemberwiseClone();
}

public class FilteringSettings
{
public string? IncludeIds { get; set; }
public string? ExcludeIds { get; set; }
public double? MaxDistance { get; set; }
public double? EarlyReportDistance { get; set; }
public int? SkipReportAge { get; set; }
public FilteringSettings Clone() => (FilteringSettings)MemberwiseClone();
}

public class CalibrationSettings
{
public int? RssiAt1m { get; set; }
public int? RxAdjRssi { get; set; }
public double? Absorption { get; set; }
public int? TxRefRssi { get; set; }
public CalibrationSettings Clone() => (CalibrationSettings)MemberwiseClone();
}
6 changes: 3 additions & 3 deletions src/Models/OptimizationResults.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ public double Evaluate(List<OptimizationSnapshot> oss, NodeSettingsStore nss)
var rx = nss.Get(m.Rx.Id);

RxNodes.TryGetValue(m.Rx.Id, out var pv);
double rxAdjRssi = pv?.RxAdjRssi ?? rx.RxAdjRssi ?? 0;
double txPower = tx.TxRefRssi ?? -59;
double pathLossExponent = pv?.Absorption ?? rx.Absorption ?? 3;
double rxAdjRssi = pv?.RxAdjRssi ?? rx.Calibration.RxAdjRssi ?? 0;
double txPower = tx.Calibration.TxRefRssi ?? -59;
double pathLossExponent = pv?.Absorption ?? rx.Calibration.Absorption ?? 3;
double distance = m.Rx.Location.DistanceTo(m.Tx.Location);
double predictedRssi = txPower + rxAdjRssi - 10 * pathLossExponent * Math.Log10(distance);

Expand Down
4 changes: 2 additions & 2 deletions src/Optimizers/OptimizationRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
Log.Information("Optimizer set {0,-20} to Absorption: {1:0.00} RxAdj: {2:00} Error: {3}", id, result.Absorption, result.RxAdjRssi, result.Error);
var a = _nsd.Get(id);
if (optimization == null) continue;
if (result.Absorption != null && result.Absorption > optimization.AbsorptionMin && result.Absorption < optimization.AbsorptionMax) a.Absorption = result.Absorption;
if (result.RxAdjRssi != null && result.RxAdjRssi > optimization.RxAdjRssiMin && result.RxAdjRssi < optimization.RxAdjRssiMax) a.RxAdjRssi = result.RxAdjRssi == null ? 0 : (int?)Math.Round(result.RxAdjRssi.Value);
if (result.Absorption != null && result.Absorption > optimization.AbsorptionMin && result.Absorption < optimization.AbsorptionMax) a.Calibration.Absorption = result.Absorption;
if (result.RxAdjRssi != null && result.RxAdjRssi > optimization.RxAdjRssiMin && result.RxAdjRssi < optimization.RxAdjRssiMax) a.Calibration.RxAdjRssi = result.RxAdjRssi == null ? 0 : (int?)Math.Round(result.RxAdjRssi.Value);
await _nsd.Set(id, a);
}

Expand Down
103 changes: 90 additions & 13 deletions src/Services/NodeSettingsStore.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Collections.Concurrent;
using System.Collections.Concurrent;
using ESPresense.Models;

namespace ESPresense.Services
Expand All @@ -15,12 +15,46 @@ public NodeSettings Get(string id)
public async Task Set(string id, NodeSettings ds)
{
var old = Get(id);
if (ds.Absorption == null || ds.Absorption != old.Absorption)
await mqtt.EnqueueAsync($"espresense/rooms/{id}/absorption/set", $"{ds.Absorption:0.00}");
if (ds.RxAdjRssi == null || ds.RxAdjRssi != old.RxAdjRssi)
await mqtt.EnqueueAsync($"espresense/rooms/{id}/rx_adj_rssi/set", $"{ds.RxAdjRssi}");
if (ds.TxRefRssi == null || ds.TxRefRssi != old.TxRefRssi)
await mqtt.EnqueueAsync($"espresense/rooms/{id}/tx_ref_rssi/set", $"{ds.TxRefRssi}");

// Updating settings
if (ds.Updating.AutoUpdate == null || ds.Updating.AutoUpdate != old.Updating.AutoUpdate)
await mqtt.EnqueueAsync($"espresense/rooms/{id}/auto_update/set", $"{ds.Updating.AutoUpdate}");
if (ds.Updating.PreRelease == null || ds.Updating.PreRelease != old.Updating.PreRelease)
await mqtt.EnqueueAsync($"espresense/rooms/{id}/pre_release/set", $"{ds.Updating.PreRelease}");

// Scanning settings
if (ds.Scanning.ForgetAfterMs == null || ds.Scanning.ForgetAfterMs != old.Scanning.ForgetAfterMs)
await mqtt.EnqueueAsync($"espresense/rooms/{id}/forget_after_ms/set", $"{ds.Scanning.ForgetAfterMs}");

// Counting settings
if (ds.Counting.IdPrefixes == null || ds.Counting.IdPrefixes != old.Counting.IdPrefixes)
await mqtt.EnqueueAsync($"espresense/rooms/{id}/count_ids/set", $"{ds.Counting.IdPrefixes}");
if (ds.Counting.StartCountingDistance == null || ds.Counting.StartCountingDistance != old.Counting.StartCountingDistance)
await mqtt.EnqueueAsync($"espresense/rooms/{id}/count_min_dist/set", $"{ds.Counting.StartCountingDistance:0.00}");
if (ds.Counting.StopCountingDistance == null || ds.Counting.StopCountingDistance != old.Counting.StopCountingDistance)
await mqtt.EnqueueAsync($"espresense/rooms/{id}/count_max_dist/set", $"{ds.Counting.StopCountingDistance:0.00}");
if (ds.Counting.IncludeDevicesAge == null || ds.Counting.IncludeDevicesAge != old.Counting.IncludeDevicesAge)
await mqtt.EnqueueAsync($"espresense/rooms/{id}/include_devices_age/set", $"{ds.Counting.IncludeDevicesAge}");

// Filtering settings
if (ds.Filtering.IncludeIds == null || ds.Filtering.IncludeIds != old.Filtering.IncludeIds)
await mqtt.EnqueueAsync($"espresense/rooms/{id}/include_ids/set", $"{ds.Filtering.IncludeIds}");
if (ds.Filtering.ExcludeIds == null || ds.Filtering.ExcludeIds != old.Filtering.ExcludeIds)
await mqtt.EnqueueAsync($"espresense/rooms/{id}/exclude_ids/set", $"{ds.Filtering.ExcludeIds}");
if (ds.Filtering.MaxDistance == null || ds.Filtering.MaxDistance != old.Filtering.MaxDistance)
await mqtt.EnqueueAsync($"espresense/rooms/{id}/max_distance/set", $"{ds.Filtering.MaxDistance:0.00}");
if (ds.Filtering.EarlyReportDistance == null || ds.Filtering.EarlyReportDistance != old.Filtering.EarlyReportDistance)
await mqtt.EnqueueAsync($"espresense/rooms/{id}/early_report_distance/set", $"{ds.Filtering.EarlyReportDistance:0.00}");
if (ds.Filtering.SkipReportAge == null || ds.Filtering.SkipReportAge != old.Filtering.SkipReportAge)
await mqtt.EnqueueAsync($"espresense/rooms/{id}/skip_report_age/set", $"{ds.Filtering.SkipReportAge}");

// Calibration settings
if (ds.Calibration.Absorption == null || ds.Calibration.Absorption != old.Calibration.Absorption)
await mqtt.EnqueueAsync($"espresense/rooms/{id}/absorption/set", $"{ds.Calibration.Absorption:0.00}");
if (ds.Calibration.RxAdjRssi == null || ds.Calibration.RxAdjRssi != old.Calibration.RxAdjRssi)
await mqtt.EnqueueAsync($"espresense/rooms/{id}/rx_adj_rssi/set", $"{ds.Calibration.RxAdjRssi}");
if (ds.Calibration.TxRefRssi == null || ds.Calibration.TxRefRssi != old.Calibration.TxRefRssi)
await mqtt.EnqueueAsync($"espresense/rooms/{id}/tx_ref_rssi/set", $"{ds.Calibration.TxRefRssi}");
}

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
Expand All @@ -32,18 +66,61 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
var ns = Get(arg.NodeId);

Check warning on line 66 in src/Services/NodeSettingsStore.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference argument for parameter 'id' in 'NodeSettings NodeSettingsStore.Get(string id)'.
switch (arg.Setting)
{
// Updating settings
case "auto_update":
ns.Updating.AutoUpdate = bool.Parse(arg.Payload);
break;
case "pre_release":
ns.Updating.PreRelease = bool.Parse(arg.Payload);
break;

// Scanning settings
case "forget_after_ms":
ns.Scanning.ForgetAfterMs = int.Parse(arg.Payload);
break;

// Counting settings
case "count_ids":
ns.Counting.IdPrefixes = arg.Payload;
break;
case "count_min_dist":
ns.Counting.StartCountingDistance = double.Parse(arg.Payload);
break;
case "count_max_dist":
ns.Counting.StopCountingDistance = double.Parse(arg.Payload);
break;
case "include_devices_age":
ns.Counting.IncludeDevicesAge = int.Parse(arg.Payload);
break;

// Filtering settings
case "include_ids":
ns.Filtering.IncludeIds = arg.Payload;
break;
case "exclude_ids":
ns.Filtering.ExcludeIds = arg.Payload;
break;
case "max_distance":
ns.Filtering.MaxDistance = double.Parse(arg.Payload);
break;
case "early_report_distance":
ns.Filtering.EarlyReportDistance = double.Parse(arg.Payload);
break;
case "skip_report_age":
ns.Filtering.SkipReportAge = int.Parse(arg.Payload);
break;

// Calibration settings
case "absorption":
ns.Absorption = double.Parse(arg.Payload);
ns.Calibration.Absorption = double.Parse(arg.Payload);
break;
case "rx_adj_rssi":
ns.RxAdjRssi = int.Parse(arg.Payload);
ns.Calibration.RxAdjRssi = int.Parse(arg.Payload);
break;
case "tx_ref_rssi":
ns.TxRefRssi = int.Parse(arg.Payload);
break;
case "max_distance":
ns.MaxDistance = double.Parse(arg.Payload);
ns.Calibration.TxRefRssi = int.Parse(arg.Payload);
break;

default:
return Task.CompletedTask;
}
Expand Down
Loading

0 comments on commit c762a74

Please sign in to comment.