diff --git a/src/Controllers/StateController.cs b/src/Controllers/StateController.cs index 8733fd74..4c431b35 100644 --- a/src/Controllers/StateController.cs +++ b/src/Controllers/StateController.cs @@ -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; diff --git a/src/Models/NodeSettings.cs b/src/Models/NodeSettings.cs index a7dceb02..4b101b97 100644 --- a/src/Models/NodeSettings.cs +++ b/src/Models/NodeSettings.cs @@ -11,28 +11,62 @@ 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; } + public UpdatingSettings Updating { get; set; } = new UpdatingSettings(); + public ScanningSettings Scanning { get; set; } = new ScanningSettings(); + public CountingSettings Counting { get; set; } = new CountingSettings(); + public FilteringSettings Filtering { get; set; } = new FilteringSettings(); + public CalibrationSettings Calibration { get; set; } = new CalibrationSettings(); - [JsonPropertyName("rx_adj_rssi")] - [JsonProperty("rx_adj_rssi")] - [Range(-127, 128)] - public int? RxAdjRssi { get; set; } + public NodeSettings Clone() + { + return new NodeSettings(id) + { + Updating = Updating.Clone(), + Scanning = Scanning.Clone(), + Counting = Counting.Clone(), + Filtering = Filtering.Clone(), + Calibration = Calibration.Clone() + }; + } +} - [JsonPropertyName("tx_ref_rssi")] - [JsonProperty("tx_ref_rssi")] - [Range(-127, 128)] - public int? TxRefRssi { get; set; } +public class UpdatingSettings +{ + public bool? AutoUpdate { get; set; } + public bool? PreRelease { get; set; } + public UpdatingSettings Clone() => (UpdatingSettings)MemberwiseClone(); +} - [JsonPropertyName("max_distance")] - [JsonProperty("max_distance")] - [Range(0, 100)] +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 NodeSettings Clone() - { - return (NodeSettings)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(); } \ No newline at end of file diff --git a/src/Models/OptimizationResults.cs b/src/Models/OptimizationResults.cs index 8dffa723..0308901c 100644 --- a/src/Models/OptimizationResults.cs +++ b/src/Models/OptimizationResults.cs @@ -20,9 +20,9 @@ public double Evaluate(List 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); diff --git a/src/Optimizers/OptimizationRunner.cs b/src/Optimizers/OptimizationRunner.cs index 87b25fc7..e20bfc07 100644 --- a/src/Optimizers/OptimizationRunner.cs +++ b/src/Optimizers/OptimizationRunner.cs @@ -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); } diff --git a/src/Services/NodeSettingsStore.cs b/src/Services/NodeSettingsStore.cs index cebd9337..86639b7d 100644 --- a/src/Services/NodeSettingsStore.cs +++ b/src/Services/NodeSettingsStore.cs @@ -15,12 +15,12 @@ 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}"); + if (ds.Absorption == null || ds.Calibration.Absorption != old.Calibration.Absorption) + await mqtt.EnqueueAsync($"espresense/rooms/{id}/absorption/set", $"{ds.Calibration.Absorption:0.00}"); + if (ds.RxAdjRssi == null || ds.Calibration.RxAdjRssi != old.Calibration.RxAdjRssi) + await mqtt.EnqueueAsync($"espresense/rooms/{id}/rx_adj_rssi/set", $"{ds.Calibration.RxAdjRssi}"); + if (ds.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) diff --git a/src/ui/src/lib/GlobalSettings.svelte b/src/ui/src/lib/GlobalSettings.svelte new file mode 100644 index 00000000..8e3aecb1 --- /dev/null +++ b/src/ui/src/lib/GlobalSettings.svelte @@ -0,0 +1,155 @@ + + +{#if loading} +
+
+ +

Loading settings...

+
+
+{:else if error} +
+

Error: {error}

+
+{:else if $settings} +
+
+

Updating

+
+
+ + +
+
+ + +
+
+
+ +
+

Scanning

+
+ +
+
+ +
+

Counting

+
+ + + + + + + +
+
+ +
+

Filtering

+
+ + + + + + + + + +
+
+ +
+

Calibration

+
+ + + + + + + +
+
+ +
+ +
+
+{:else} +
+

No settings available.

+
+{/if} \ No newline at end of file diff --git a/src/ui/src/lib/TriStateCheckbox.svelte b/src/ui/src/lib/TriStateCheckbox.svelte new file mode 100644 index 00000000..b96b7480 --- /dev/null +++ b/src/ui/src/lib/TriStateCheckbox.svelte @@ -0,0 +1,38 @@ + + + + + \ No newline at end of file diff --git a/src/ui/src/routes/+layout.svelte b/src/ui/src/routes/+layout.svelte index 3a0fe504..8a8061e6 100644 --- a/src/ui/src/routes/+layout.svelte +++ b/src/ui/src/routes/+layout.svelte @@ -25,6 +25,7 @@ { href: '/devices', name: 'devices', icon: devices, alt: 'Devices' }, { href: '/nodes', name: 'nodes', icon: nodes, alt: 'Nodes' }, { href: '/calibration', name: 'calibration', icon: calibration, alt: 'Calibration' }, + { href: '/settings', name: 'settings', icon: settings, alt: 'Settings' } ]; diff --git a/src/ui/src/routes/settings/+page.svelte b/src/ui/src/routes/settings/+page.svelte new file mode 100644 index 00000000..a77dcab0 --- /dev/null +++ b/src/ui/src/routes/settings/+page.svelte @@ -0,0 +1,14 @@ + + + + ESPresense Companion: Settings + + +
+

Settings

+

These settings will be applied to every node, including new nodes.

+ + +