From 55ae67632384f9067d48e3607f56e1adc15da23c Mon Sep 17 00:00:00 2001 From: garath001 <62758265+garath001@users.noreply.github.com> Date: Fri, 31 Jul 2026 07:47:29 -0400 Subject: [PATCH 1/3] Reusable helper class to handle basic stats on streaming data --- Ares.Device.Drivers.slnx | 1 + StreamHelper/SimpleStreamingStats.cs | 431 +++++++++++++++++++++++++++ StreamHelper/StreamHelper.csproj | 10 + 3 files changed, 442 insertions(+) create mode 100644 StreamHelper/SimpleStreamingStats.cs create mode 100644 StreamHelper/StreamHelper.csproj diff --git a/Ares.Device.Drivers.slnx b/Ares.Device.Drivers.slnx index 9afe033..231764a 100644 --- a/Ares.Device.Drivers.slnx +++ b/Ares.Device.Drivers.slnx @@ -4,6 +4,7 @@ + diff --git a/StreamHelper/SimpleStreamingStats.cs b/StreamHelper/SimpleStreamingStats.cs new file mode 100644 index 0000000..851a7de --- /dev/null +++ b/StreamHelper/SimpleStreamingStats.cs @@ -0,0 +1,431 @@ +using System; + +namespace StreamHelper +{ + /// + /// Calculates descriptive statistics incrementally without buffering + /// individual samples. + /// + /// Regression is performed against the zero-based sample index: + /// x = 0, 1, 2, ... + /// + /// This class uses constant memory regardless of the number of samples. + /// + public class SimpleStreamingStats + { + private readonly object _syncRoot = new(); + + private long _count; + + // Online central moments. + private double _mean; + private double _m2; + private double _m3; + private double _m4; + + // Sum of squares of raw values, used for RMS. + private double _sumSquares; + + private double _minimum; + private double _maximum; + + // Running regression values. + private double _meanX; + private double _meanY; + private double _sxx; + private double _syy; + private double _sxy; + + /// + /// Adds one sample to the running statistics. + /// + public void AddValue(double value) + { + if (!double.IsFinite(value)) + throw new ArgumentOutOfRangeException( + nameof(value), + "The sample must be a finite number."); + + lock (_syncRoot) + { + long previousCount = _count; + _count++; + + if (_count == 1) + { + _minimum = value; + _maximum = value; + } + else + { + if (value < _minimum) + _minimum = value; + + if (value > _maximum) + _maximum = value; + } + + _sumSquares += value * value; + + UpdateMoments(value, previousCount); + UpdateRegression(value, previousCount); + } + } + + /// + /// Clears all accumulated statistics. + /// + public void ResetStats() + { + lock (_syncRoot) + { + _count = 0; + + _mean = 0.0; + _m2 = 0.0; + _m3 = 0.0; + _m4 = 0.0; + + _sumSquares = 0.0; + + _minimum = 0.0; + _maximum = 0.0; + + _meanX = 0.0; + _meanY = 0.0; + _sxx = 0.0; + _syy = 0.0; + _sxy = 0.0; + } + } + + public long GetCount() + { + lock (_syncRoot) + return _count; + } + + public double GetMean() + { + lock (_syncRoot) + return _count > 0 ? _mean : double.NaN; + } + + /// + /// Returns variance using N as the denominator. + /// + public double GetPopulationVariance() + { + lock (_syncRoot) + return _count > 0 + ? _m2 / _count + : double.NaN; + } + + /// + /// Returns variance using N - 1 as the denominator. + /// + public double GetSampleVariance() + { + lock (_syncRoot) + return _count > 1 + ? _m2 / (_count - 1) + : double.NaN; + } + + public double GetPopulationStandardDeviation() + { + lock (_syncRoot) + { + return _count > 0 + ? Math.Sqrt(Math.Max(0.0, _m2 / _count)) + : double.NaN; + } + } + + public double GetSampleStandardDeviation() + { + lock (_syncRoot) + { + return _count > 1 + ? Math.Sqrt(Math.Max(0.0, _m2 / (_count - 1))) + : double.NaN; + } + } + + public double GetMinimum() + { + lock (_syncRoot) + return _count > 0 ? _minimum : double.NaN; + } + + public double GetMaximum() + { + lock (_syncRoot) + return _count > 0 ? _maximum : double.NaN; + } + + public double GetRange() + { + lock (_syncRoot) + return _count > 0 + ? _maximum - _minimum + : double.NaN; + } + + public double GetRootMeanSquare() + { + lock (_syncRoot) + { + return _count > 0 + ? Math.Sqrt(_sumSquares / _count) + : double.NaN; + } + } + + /// + /// Returns adjusted sample skewness. + /// Requires at least three samples. + /// + public double GetSkewness() + { + lock (_syncRoot) + { + if (_count < 3 || _m2 <= 0.0) + return double.NaN; + + double n = _count; + + return Math.Sqrt(n * (n - 1.0)) + / (n - 2.0) + * (_m3 / Math.Pow(_m2, 1.5)); + } + } + + /// + /// Returns bias-corrected excess kurtosis. + /// + /// A normal distribution has an excess kurtosis near zero. + /// Requires at least four samples. + /// + public double GetExcessKurtosis() + { + lock (_syncRoot) + { + if (_count < 4 || _m2 <= 0.0) + return double.NaN; + + double n = _count; + + double rawKurtosis = + n * _m4 / (_m2 * _m2); + + return ((n - 1.0) / + ((n - 2.0) * (n - 3.0))) + * + ((n + 1.0) * (rawKurtosis - 3.0) + 6.0); + } + } + + /// + /// Returns the slope per sample interval. + /// + /// For example, if samples are one second apart, this is the slope + /// per second. + /// + public double GetSlope() + { + lock (_syncRoot) + { + return _count > 1 && _sxx > 0.0 + ? _sxy / _sxx + : double.NaN; + } + } + + /// + /// Returns the slope converted to a specified time unit. + /// + /// Example: + /// sampleIntervalSeconds = 0.1 + /// returns units per second. + /// + public double GetSlopePerTime(double sampleInterval) + { + if (!double.IsFinite(sampleInterval) || sampleInterval <= 0.0) + throw new ArgumentOutOfRangeException( + nameof(sampleInterval), + "Sample interval must be finite and greater than zero."); + + lock (_syncRoot) + { + return _count > 1 && _sxx > 0.0 + ? (_sxy / _sxx) / sampleInterval + : double.NaN; + } + } + + public double GetIntercept() + { + lock (_syncRoot) + { + if (_count < 2 || _sxx <= 0.0) + return double.NaN; + + double slope = _sxy / _sxx; + + return _meanY - slope * _meanX; + } + } + + public double GetCorrelation() + { + lock (_syncRoot) + { + if (_count < 2 || _sxx <= 0.0 || _syy <= 0.0) + return double.NaN; + + double denominator = Math.Sqrt(_sxx * _syy); + + if (denominator <= 0.0) + return double.NaN; + + return Math.Clamp( + _sxy / denominator, + -1.0, + 1.0); + } + } + + public double GetRSquared() + { + lock (_syncRoot) + { + if (_count < 2 || _sxx <= 0.0 || _syy <= 0.0) + return double.NaN; + + double denominator = _sxx * _syy; + + if (denominator <= 0.0) + return double.NaN; + + double rSquared = + (_sxy * _sxy) / denominator; + + return Math.Clamp(rSquared, 0.0, 1.0); + } + } + + /// + /// Returns the residual standard error around the linear fit. + /// Requires at least three samples. + /// + public double GetRegressionStandardError() + { + lock (_syncRoot) + { + if (_count < 3 || _sxx <= 0.0) + return double.NaN; + + double explainedSumSquares = + (_sxy * _sxy) / _sxx; + + double residualSumSquares = + Math.Max(0.0, _syy - explainedSumSquares); + + return Math.Sqrt( + residualSumSquares / (_count - 2)); + } + } + + /// + /// Predicts the value at a zero-based sample index. + /// + public double GetPredictedValue(double sampleIndex) + { + if (!double.IsFinite(sampleIndex)) + throw new ArgumentOutOfRangeException( + nameof(sampleIndex)); + + lock (_syncRoot) + { + if (_count < 2 || _sxx <= 0.0) + return double.NaN; + + double slope = _sxy / _sxx; + double intercept = _meanY - slope * _meanX; + + return intercept + slope * sampleIndex; + } + } + + private void UpdateMoments( + double value, + long previousCount) + { + /* + * Online update of the first four central moments. + * + * This is an extension of Welford's algorithm and avoids + * subtracting two large, nearly equal raw sums. + */ + double n = _count; + double delta = value - _mean; + double deltaOverN = delta / n; + double deltaOverNSquared = + deltaOverN * deltaOverN; + + double term1 = + delta * deltaOverN * previousCount; + + _mean += deltaOverN; + + _m4 += + term1 + * deltaOverNSquared + * (n * n - 3.0 * n + 3.0) + + + 6.0 + * deltaOverNSquared + * _m2 + - + 4.0 + * deltaOverN + * _m3; + + _m3 += + term1 + * deltaOverN + * (n - 2.0) + - + 3.0 + * deltaOverN + * _m2; + + _m2 += term1; + } + + private void UpdateRegression( + double value, + long sampleIndex) + { + double x = sampleIndex; + double y = value; + double n = _count; + + double deltaX = x - _meanX; + double deltaY = y - _meanY; + + _meanX += deltaX / n; + _meanY += deltaY / n; + + /* + * Use the updated means for the second part of the online + * covariance update. + */ + _sxx += deltaX * (x - _meanX); + _syy += deltaY * (y - _meanY); + _sxy += deltaX * (y - _meanY); + } + } +} \ No newline at end of file diff --git a/StreamHelper/StreamHelper.csproj b/StreamHelper/StreamHelper.csproj new file mode 100644 index 0000000..a0bed63 --- /dev/null +++ b/StreamHelper/StreamHelper.csproj @@ -0,0 +1,10 @@ + + + + net10.0 + enable + enable + Library + + + From f72fbbed8e68ef006b4aa0b310f554057e0523c2 Mon Sep 17 00:00:00 2001 From: garath001 <62758265+garath001@users.noreply.github.com> Date: Fri, 31 Jul 2026 15:47:06 -0400 Subject: [PATCH 2/3] Template of SerialStreamingDevice. Missing realtime hooks --- .../DelimitedStreamSensor.cs | 324 ++++++++++++++++++ .../IDelimitedSteamSensor.cs | 15 + .../Models/StreamingField.cs | 28 ++ .../SerialStreamingSensor.csproj | 65 ++++ .../UI/DelimitedStreamSensorControl.razor | 154 +++++++++ .../UI/DelimitedStreamSensorControl.razor.css | 1 + .../DelimitedStreamSensorControlViewModel.cs | 119 +++++++ .../UI/State/DelimitedStreamSensorState.cs | 20 ++ .../State/DelimitedStreamSensorStateMapper.cs | 47 +++ SerialStreamingSensor/manifest.yaml | 23 ++ 10 files changed, 796 insertions(+) create mode 100644 SerialStreamingSensor/DelimitedStreamSensor.cs create mode 100644 SerialStreamingSensor/IDelimitedSteamSensor.cs create mode 100644 SerialStreamingSensor/Models/StreamingField.cs create mode 100644 SerialStreamingSensor/SerialStreamingSensor.csproj create mode 100644 SerialStreamingSensor/UI/DelimitedStreamSensorControl.razor create mode 100644 SerialStreamingSensor/UI/DelimitedStreamSensorControl.razor.css create mode 100644 SerialStreamingSensor/UI/DelimitedStreamSensorControlViewModel.cs create mode 100644 SerialStreamingSensor/UI/State/DelimitedStreamSensorState.cs create mode 100644 SerialStreamingSensor/UI/State/DelimitedStreamSensorStateMapper.cs create mode 100644 SerialStreamingSensor/manifest.yaml diff --git a/SerialStreamingSensor/DelimitedStreamSensor.cs b/SerialStreamingSensor/DelimitedStreamSensor.cs new file mode 100644 index 0000000..36599d5 --- /dev/null +++ b/SerialStreamingSensor/DelimitedStreamSensor.cs @@ -0,0 +1,324 @@ +using Ares.Datamodel; +using Ares.Datamodel.Device; +using Ares.Datamodel.Extensions; +using Ares.Datamodel.Factories; +using Ares.Device; +using Microsoft.AspNetCore.Components.Web; +using SerialStreamingSensor.Models; +using StreamHelper; +using System.Linq.Expressions; +using System.Reactive.Linq; +using System.Reactive.Subjects; + +namespace SerialStreamingSensor +{ + public class DelimitedStreamSensor : AresDevice, IDelimitedSteamSensor + { + private readonly DeviceConnectionInfo _connectionInfo; + private readonly ILogger _logger; + private readonly string _dataFormat; + private readonly string[] _fields; + private readonly StreamingField[] _streamingFields; + private readonly IReadOnlyDictionary _streamingFieldsByName; + + private readonly BehaviorSubject _stateSubject = new(new AresStruct()); + + public DelimitedStreamSensor(DeviceConnectionInfo info, ILogger logger) : base(info) + { + + _connectionInfo = info; + _logger = logger; + _dataFormat = info.DeviceSettings.Fields["DataFormat"].StringValue; + StateStream = _stateSubject.AsObservable(); + + _logger.LogInformation($"Parsing data format '{_dataFormat}'"); + + _fields = _dataFormat.Split(":,\t".ToCharArray(), StringSplitOptions.None).Select(field => field.Trim()).ToArray(); + + _streamingFields = _fields + .Select((fieldName, dataIndex) => new + { + FieldName = fieldName, + DataIndex = dataIndex + }) + .Where(field => !string.IsNullOrWhiteSpace(field.FieldName)) + .Select(field => new StreamingField + { + Name = field.FieldName, + DataIndex = field.DataIndex, + StatsActive = false, + Value = null + }) + .ToArray(); + + _logger.LogInformation($"{_streamingFields.Length} fields parsed"); + + _streamingFieldsByName = _streamingFields.ToDictionary(field => field.Name, field => field, StringComparer.OrdinalIgnoreCase); + + StateSchema = AresSchemaBuilder.Empty() + .AddEntry("Name", AresSchemaBuilder.StringEntry().Build()) + .AddEntry("DataFormat", AresSchemaBuilder.StringEntry().Build()) + .AddEntry("LiveData", AresSchemaBuilder.Entry(AresDataType.Struct) + .WithStructSchema(liveData => + { + foreach (var field in _streamingFields) + { + liveData.Fields.Add(field.Name, AresSchemaBuilder.NumberEntry().AsOptional().Build()); + } + }) + .Build()) + .Build(); + } + + private AresStruct BuildInitialState() + { + return AresStateBuilder.Create() + .Add("Name", Name) + .Add("DataFormat", _dataFormat) + .AddStruct("LiveData", liveData => + { + foreach (var field in _streamingFields) + { + /* + * If AresStateBuilder does not support null numeric values, + * use 0 initially and distinguish validity separately. + */ + liveData.Add(field.Name, field.Value ?? 0.0); + } + }) + .Build(); + } + + + public override IObservable StateStream { get; } + + + public override Task Activate(CancellationToken ct) + { + _stateSubject.OnNext(BuildInitialState()); + + return Task.FromResult(true); + } + + public Task BeginCollectingStats(string fieldName) + { + var field = getStreamingField(fieldName); + field.Stats.ResetStats(); + field.StatsActive = true; + return Task.CompletedTask; + } + + public async ValueTask DisposeAsync() + { + //_stateWatchers.Dispose(); + //await _stateGetterLoopTokenSource.CancelAsync(); + //await _stateUpdater; + //_stateGetterLoopTokenSource.Dispose(); + _stateSubject.OnCompleted(); + } + + public Task EndCollectingStats(string fieldName) + { + var field = getStreamingField(fieldName); + field.StatsActive = false; + return Task.CompletedTask; + } + + public override Task EnterSafeMode(CancellationToken ct) + { + // passive device. No action required + return Task.CompletedTask; + } + + public async override Task ExecuteCommand(string command, List arguments, CancellationToken token) + { + var result = new CommandResult { Success = true }; + string? fieldName = null; + + try + { + switch (command) + { + case nameof(BeginCollectingStats): + fieldName = arguments.FirstOrDefault(a => a.ArgName == "fieldName")?.ArgValue.StringValue; + if (fieldName == null) return ArgumentError(nameof(BeginCollectingStats), "fieldName", "string"); + await BeginCollectingStats(fieldName); + break; + + case nameof(EndCollectingStats): + fieldName = arguments.FirstOrDefault(a => a.ArgName == "fieldName")?.ArgValue.StringValue; + if (fieldName == null) return ArgumentError(nameof(EndCollectingStats), "fieldName", "string"); + await EndCollectingStats(fieldName); + break; + + case nameof(ResetStatistics): + fieldName = arguments.FirstOrDefault(a => a.ArgName == "fieldName")?.ArgValue.StringValue; + if (fieldName == null) return ArgumentError(nameof(ResetStatistics), "fieldName", "string"); + await ResetStatistics(fieldName); + break; + + case nameof(getCollectionCount): + fieldName = arguments.FirstOrDefault(a => a.ArgName == "fieldName")?.ArgValue.StringValue; + if (fieldName == null) return ArgumentError(nameof(getCollectionCount), "fieldName", "string"); + var collectionCount = await getCollectionCount(fieldName); + result.Result=AresValueHelper.CreateNumber(collectionCount); + break; + + case nameof(getVariance): + fieldName = arguments.FirstOrDefault(a => a.ArgName == "fieldName")?.ArgValue.StringValue; + if (fieldName == null) return ArgumentError(nameof(getVariance), "fieldName", "string"); + var variance = await getVariance(fieldName); + result.Result = AresValueHelper.CreateNumber(variance); + break; + + case nameof(getMean): + fieldName = arguments.FirstOrDefault(a => a.ArgName == "fieldName")?.ArgValue.StringValue; + if (fieldName == null) return ArgumentError(nameof(getMean), "fieldName", "string"); + var mean = await getMean(fieldName) ; + result.Result = AresValueHelper.CreateNumber(mean); + break; + + default: + result.Success = false; + result.Error = $"Unrecognized command '{command}'"; + break; + } + } + catch (Exception err) + { + result.Success = false; + result.Error = err.Message; + } + + return result; + } + + private static CommandResult ArgumentError(string commandName, string paramName, string expectedType) + { + return new CommandResult + { + Success = false, + Error = $"The {commandName} command requires a valid {expectedType} for '{paramName}', but none was provided or the type was incorrect." + }; + } + + public Task getCollectionCount(string fieldName) + { + var field = getStreamingField(fieldName); + var count = field.Stats.GetCount(); + return Task.FromResult(count); + } + + public Task getMean(string fieldName) + { + var field = getStreamingField(fieldName); + var mean = field.Stats.GetMean(); + return Task.FromResult(mean); + } + + public override Task GetSettings() + { + var response = new AresStruct().AddString("Mode", "Streaming senor"); + return Task.FromResult(response); + } + + public override Task GetState() => Task.FromResult(_stateSubject.Value); + + public Task getVariance(string fieldName) + { + var field = getStreamingField(fieldName); + var variance = field.Stats.GetSampleVariance(); + return Task.FromResult(variance); + } + + public Task ResetStatistics(string fieldName) + { + var field = getStreamingField(fieldName); + field.Stats.ResetStats(); + return Task.CompletedTask; + } + + StreamingField getStreamingField(string fieldName) + { + if (!_streamingFieldsByName.ContainsKey(fieldName)) + { + throw new ArgumentOutOfRangeException($"'{fieldName}' not a recognized data field"); + } + return _streamingFieldsByName[fieldName]; + } + + + public override Task UpdateSettings(AresStruct settings) + { + return Task.CompletedTask; + } + + protected override Task> BuildCommandDescriptorsAsync() + { + + var descriptors = new List + { + new() + { + Name = nameof(BeginCollectingStats), + Description = "Starts calculating stats on streaming data", + InputSchema = AresSchemaBuilder.Empty() + .AddEntry("fieldName", AresSchemaBuilder.StringEntry().Build()) + .Build() + }, + new() + { + Name = nameof(EndCollectingStats), + Description = "Ends calculating stats on streaming data", + InputSchema = AresSchemaBuilder.Empty() + .AddEntry("fieldName", AresSchemaBuilder.StringEntry().Build()) + .Build() + }, + new() + { + Name = nameof(getVariance), + Description = "gets the calculated variance", + InputSchema = AresSchemaBuilder.Empty() + .AddEntry("fieldName", AresSchemaBuilder.StringEntry().Build()) + .Build(), + OutputSchema = AresSchemaBuilder.NumberEntry() + .WithDescription("variance") + .Build() + }, + new() + { + Name = nameof(getMean), + Description = "gets the calculated mean", + InputSchema = AresSchemaBuilder.Empty() + .AddEntry("fieldName", AresSchemaBuilder.StringEntry().Build()) + .Build(), + OutputSchema = AresSchemaBuilder.NumberEntry() + .WithDescription("mean") + .Build() + }, + new() + { + Name = nameof(getCollectionCount), + Description = "gets the number of samples in stats calculation", + InputSchema = AresSchemaBuilder.Empty() + .AddEntry("fieldName", AresSchemaBuilder.StringEntry().Build()) + .Build(), + OutputSchema = AresSchemaBuilder.NumberEntry() + .WithDescription("count") + .Build() + }, + new() + { + Name = nameof(ResetStatistics), + Description = "clears current stats data", + InputSchema = AresSchemaBuilder.Empty() + .AddEntry("fieldName", AresSchemaBuilder.StringEntry().Build()) + .Build() + }, + }; + + return Task.FromResult(descriptors); + + } + } +} diff --git a/SerialStreamingSensor/IDelimitedSteamSensor.cs b/SerialStreamingSensor/IDelimitedSteamSensor.cs new file mode 100644 index 0000000..bd3120e --- /dev/null +++ b/SerialStreamingSensor/IDelimitedSteamSensor.cs @@ -0,0 +1,15 @@ +namespace SerialStreamingSensor +{ + public interface IDelimitedSteamSensor: IAsyncDisposable + { + + + Task BeginCollectingStats(string fieldName); + Task EndCollectingStats(string fieldName); + Task getCollectionCount(string fieldName); + Task getMean(string fieldName); + Task getVariance(string fieldName); + Task ResetStatistics(string fieldName); + + } +} diff --git a/SerialStreamingSensor/Models/StreamingField.cs b/SerialStreamingSensor/Models/StreamingField.cs new file mode 100644 index 0000000..add5fcf --- /dev/null +++ b/SerialStreamingSensor/Models/StreamingField.cs @@ -0,0 +1,28 @@ +using StreamHelper; + +namespace SerialStreamingSensor.Models +{ + public sealed class StreamingField + { + public required string Name { get; init; } + + /// + /// Position of this field in the incoming delimited data line. + /// Empty entries in the data format are counted when assigning + /// this index, even though they are not represented as fields. + /// + public int DataIndex { get; init; } + + /// + /// Most recently parsed value. + /// + public double? Value { get; set; } + + /// + /// Determines whether incoming values are added to Stats. + /// + public bool StatsActive { get; set; } + + public SimpleStreamingStats Stats { get; } = new(); + } +} \ No newline at end of file diff --git a/SerialStreamingSensor/SerialStreamingSensor.csproj b/SerialStreamingSensor/SerialStreamingSensor.csproj new file mode 100644 index 0000000..4cf115b --- /dev/null +++ b/SerialStreamingSensor/SerialStreamingSensor.csproj @@ -0,0 +1,65 @@ + + + + net10.0 + enable + enable + Library + + + + + + + + + Always + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + True + False + + + + + + $(ProjectDir)obj\AresStaging\ + $(ProjectDir)..\plugins\$(AssemblyName).ares + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/SerialStreamingSensor/UI/DelimitedStreamSensorControl.razor b/SerialStreamingSensor/UI/DelimitedStreamSensorControl.razor new file mode 100644 index 0000000..8fdd81d --- /dev/null +++ b/SerialStreamingSensor/UI/DelimitedStreamSensorControl.razor @@ -0,0 +1,154 @@ +@using ReactiveUI +@using SerialStreamingSensor.UI.State +@implements IDisposable + +@if (ViewModel is null) +{ +
+ No sensor view model is available. +
+} +else +{ +
+
+ @GetDisplayName() +
+ +
+ @GetStatusText() +
+
+ + @if (ViewModel.SensorState.LiveData.Count == 0) + { +
+ No live-data fields are defined. +
+ } + else + { +
+ @foreach (var entry in ViewModel.SensorState.LiveData) + { +
+ + + @FormatName(entry.Name) + + + + @FormatValue(entry.Value) + +
+ } +
+ } +} + +@code { + private IDisposable? _viewModelSubscription; + + [Parameter] + public DelimitedStreamSensorControlViewModel? ViewModel + { + get; + set; + } + + protected override void OnParametersSet() + { + _viewModelSubscription?.Dispose(); + _viewModelSubscription = null; + + if (ViewModel is null) + return; + + _viewModelSubscription = ViewModel + .Changed + .Subscribe( + _ => InvokeAsync(StateHasChanged)); + } + + private string GetDisplayName() + { + if (ViewModel is null) + return "Delimited Stream Sensor"; + + if (!string.IsNullOrWhiteSpace( + ViewModel.SensorState.Name)) + { + return ViewModel.SensorState.Name; + } + + return ViewModel.DeviceName; + } + + private string GetStatusText() + { + if (ViewModel?.CapturingLiveData == true) + return "Live"; + + if (ViewModel?.HasValidData == true) + return "Connected"; + + return "Waiting for data"; + } + + private string GetStatusClass() + { + return ViewModel?.CapturingLiveData == true + ? "streaming-sensor-status active" + : "streaming-sensor-status waiting"; + } + + private static string GetValueClass( + DelimitedStreamSensorLiveDataEntry entry) + { + return entry.Value.HasValue + ? "streaming-sensor-value" + : "streaming-sensor-value unavailable"; + } + + private static string FormatValue(double? value) + { + return value.HasValue + ? value.Value.ToString("G6") + : "—"; + } + + private static string FormatName(string name) + { + if (string.IsNullOrWhiteSpace(name)) + return "Value"; + + var result = + new System.Text.StringBuilder( + name.Length + 8); + + for (var index = 0; + index < name.Length; + index++) + { + var current = name[index]; + + if (index > 0 && + char.IsUpper(current) && + !char.IsUpper(name[index - 1])) + { + result.Append(' '); + } + + result.Append(current); + } + + return result.ToString(); + } + + public void Dispose() + { + _viewModelSubscription?.Dispose(); + _viewModelSubscription = null; + } +} \ No newline at end of file diff --git a/SerialStreamingSensor/UI/DelimitedStreamSensorControl.razor.css b/SerialStreamingSensor/UI/DelimitedStreamSensorControl.razor.css new file mode 100644 index 0000000..5f28270 --- /dev/null +++ b/SerialStreamingSensor/UI/DelimitedStreamSensorControl.razor.css @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/SerialStreamingSensor/UI/DelimitedStreamSensorControlViewModel.cs b/SerialStreamingSensor/UI/DelimitedStreamSensorControlViewModel.cs new file mode 100644 index 0000000..3ff034f --- /dev/null +++ b/SerialStreamingSensor/UI/DelimitedStreamSensorControlViewModel.cs @@ -0,0 +1,119 @@ +using Ares.Toolkit.Device.UI; +using Microsoft.Extensions.Logging; +using ReactiveUI; +using SerialStreamingSensor.UI.State; +using System.Reactive.Linq; + +namespace SerialStreamingSensor.UI +{ + public sealed class DelimitedStreamSensorControlViewModel + : DeviceUnitControlViewModel, + IAsyncDisposable + { + private readonly ILogger< + DelimitedStreamSensorControlViewModel> _logger; + + private IDisposable? _stateSubscription; + + private DelimitedStreamSensorState _sensorState = new(); + private bool _hasValidData; + private bool _capturingLiveData; + private bool _disposed; + + public DelimitedStreamSensorControlViewModel( + DelimitedStreamSensor sensor, + ILogger logger) + : base(sensor) + { + _logger = logger; + + ViewType = typeof(DelimitedStreamSensorControl); + DefaultWidth = 19; + + _stateSubscription = sensor.StateStream + .Select( + DelimitedStreamSensorStateMapper.FromAresStruct) + .Subscribe( + UpdateState, + HandleStateStreamError, + HandleStateStreamCompleted); + } + + public DelimitedStreamSensorState SensorState + { + get => _sensorState; + + private set => + this.RaiseAndSetIfChanged( + ref _sensorState, + value); + } + + public bool HasValidData + { + get => _hasValidData; + + private set => + this.RaiseAndSetIfChanged( + ref _hasValidData, + value); + } + + public bool CapturingLiveData + { + get => _capturingLiveData; + + private set => + this.RaiseAndSetIfChanged( + ref _capturingLiveData, + value); + } + + private void UpdateState( + DelimitedStreamSensorState? state) + { + if (state is null) + { + HasValidData = false; + CapturingLiveData = false; + return; + } + + SensorState = state; + HasValidData = true; + CapturingLiveData = true; + } + + private void HandleStateStreamError( + Exception exception) + { + _logger.LogError( + exception, + "State stream failed for {Name}", + DeviceName); + + HasValidData = false; + CapturingLiveData = false; + } + + private void HandleStateStreamCompleted() + { + CapturingLiveData = false; + } + + public ValueTask DisposeAsync() + { + if (_disposed) + return ValueTask.CompletedTask; + + _disposed = true; + + _stateSubscription?.Dispose(); + _stateSubscription = null; + + GC.SuppressFinalize(this); + + return ValueTask.CompletedTask; + } + } +} \ No newline at end of file diff --git a/SerialStreamingSensor/UI/State/DelimitedStreamSensorState.cs b/SerialStreamingSensor/UI/State/DelimitedStreamSensorState.cs new file mode 100644 index 0000000..3b1d93a --- /dev/null +++ b/SerialStreamingSensor/UI/State/DelimitedStreamSensorState.cs @@ -0,0 +1,20 @@ +namespace SerialStreamingSensor.UI.State +{ + public sealed class DelimitedStreamSensorState + { + public string Name { get; init; } = string.Empty; + + public IReadOnlyList LiveData + { + get; + init; + } = Array.Empty(); + } + + public sealed class DelimitedStreamSensorLiveDataEntry + { + public string Name { get; init; } = string.Empty; + + public double? Value { get; init; } + } +} \ No newline at end of file diff --git a/SerialStreamingSensor/UI/State/DelimitedStreamSensorStateMapper.cs b/SerialStreamingSensor/UI/State/DelimitedStreamSensorStateMapper.cs new file mode 100644 index 0000000..9e38949 --- /dev/null +++ b/SerialStreamingSensor/UI/State/DelimitedStreamSensorStateMapper.cs @@ -0,0 +1,47 @@ +using Ares.Datamodel; +using Ares.Datamodel.Extensions; + +namespace SerialStreamingSensor.UI.State +{ + public static class DelimitedStreamSensorStateMapper + { + public static DelimitedStreamSensorState FromAresStruct( + AresStruct state) + { + var model = new DelimitedStreamSensorState + { + + Name = state.Fields + .GetValueOrDefault("Name")? + .StringValue ?? string.Empty + }; + + if (state.Fields.TryGetValue( + "LiveData", + out var liveDataValue) && + liveDataValue.StructValue is not null) + { + model = new DelimitedStreamSensorState + { + Name = model.Name, + + LiveData = liveDataValue.StructValue.Fields + .Where(field => + !string.IsNullOrWhiteSpace(field.Key)) + .Select(field => + new DelimitedStreamSensorLiveDataEntry + { + Name = field.Key, + + Value = field.Value.HasNumberValue + ? field.Value.NumberValue + : null + }) + .ToArray() + }; + } + + return model; + } + } +} \ No newline at end of file diff --git a/SerialStreamingSensor/manifest.yaml b/SerialStreamingSensor/manifest.yaml new file mode 100644 index 0000000..5bd464b --- /dev/null +++ b/SerialStreamingSensor/manifest.yaml @@ -0,0 +1,23 @@ +# ARES Device Driver Manifest +# Target: Steaming Serial Sensor + +# Basic Metadata +device_type_name: "Delimited Stream Sensor" +driver_id: "delimited_stream_sensor_v1" +connection_type: "Serial" + +# The DLL that contains the MassFlowController and ViewModel classes +assembly_name: "SerialStreamingSensor.dll" + +# Serial connection specifics (Parsed only if connection_type is "Serial") +serial_settings: + variable_baud_rate: true + allowed_baud_rates: [9600, 19200, 38400, 57600, 115200] + default_baud_rate: 115200 # Keeps the UI friendly by pre-filling + +# Settings required when adding the device through the ARES UI +settings: + - key: "DataFormat" + display_name: "Data Format" + type: "string" + description: "streaming data line format." From 9b41cb71c2b916f9c5731ac37d91efd4bcdbf3a3 Mon Sep 17 00:00:00 2001 From: garath001 <62758265+garath001@users.noreply.github.com> Date: Mon, 3 Aug 2026 17:25:29 -0400 Subject: [PATCH 3/3] Library for sensor streaming delimited data over dedicated serial port. Validated function! --- Ares.Device.Drivers.slnx | 1 + .../Connection/ISerialSteramingConnection.cs | 9 + .../Connection/SerialStreamingConnection.cs | 19 +++ .../DelimitedStreamSensor.cs | 154 +++++++++++++++++- .../SerialStreamingSensor.csproj | 1 + .../UI/DelimitedStreamSensorControl.razor | 88 +++++----- .../UI/DelimitedStreamSensorControl.razor.css | 69 +++++++- plugins/SerialStreamingSensor.ares.archive | Bin 0 -> 74000 bytes 8 files changed, 293 insertions(+), 48 deletions(-) create mode 100644 SerialStreamingSensor/Connection/ISerialSteramingConnection.cs create mode 100644 SerialStreamingSensor/Connection/SerialStreamingConnection.cs create mode 100644 plugins/SerialStreamingSensor.ares.archive diff --git a/Ares.Device.Drivers.slnx b/Ares.Device.Drivers.slnx index 231764a..67386e3 100644 --- a/Ares.Device.Drivers.slnx +++ b/Ares.Device.Drivers.slnx @@ -4,6 +4,7 @@ + diff --git a/SerialStreamingSensor/Connection/ISerialSteramingConnection.cs b/SerialStreamingSensor/Connection/ISerialSteramingConnection.cs new file mode 100644 index 0000000..5ac1265 --- /dev/null +++ b/SerialStreamingSensor/Connection/ISerialSteramingConnection.cs @@ -0,0 +1,9 @@ +using Ares.Toolkit.Serial; + +namespace SerialStreamingSensor.Connection +{ + public interface ISerialSteramingConnection: IAresSerialConnection + { + + } +} diff --git a/SerialStreamingSensor/Connection/SerialStreamingConnection.cs b/SerialStreamingSensor/Connection/SerialStreamingConnection.cs new file mode 100644 index 0000000..251a591 --- /dev/null +++ b/SerialStreamingSensor/Connection/SerialStreamingConnection.cs @@ -0,0 +1,19 @@ +using Ares.Toolkit.Serial; +using Ares.Toolkit.Serial.Commands; +using System.IO.Ports; + +namespace SerialStreamingSensor.Connection +{ + public class SerialStreamingConnection : AresHardwareConnection, ISerialSteramingConnection + { + public SerialStreamingConnection(SerialPortConnectionInfo connectionInfo, string portName, SerialConnectionOptions? connectionOptions = null) : base(connectionInfo, portName, connectionOptions) + { + } + + public SerialStreamingConnection(string portName, int baudRate = 115200, Parity parity = Parity.None, int dataBits = 8, StopBits stopBits = StopBits.One, SerialConnectionOptions? options = null) : base(portName, baudRate, parity, dataBits, stopBits, options) + { + + } + + } +} diff --git a/SerialStreamingSensor/DelimitedStreamSensor.cs b/SerialStreamingSensor/DelimitedStreamSensor.cs index 36599d5..18d65f0 100644 --- a/SerialStreamingSensor/DelimitedStreamSensor.cs +++ b/SerialStreamingSensor/DelimitedStreamSensor.cs @@ -4,9 +4,12 @@ using Ares.Datamodel.Factories; using Ares.Device; using Microsoft.AspNetCore.Components.Web; +using Microsoft.AspNetCore.Mvc.Diagnostics; +using SerialStreamingSensor.Connection; using SerialStreamingSensor.Models; using StreamHelper; using System.Linq.Expressions; +using System.Reactive.Disposables; using System.Reactive.Linq; using System.Reactive.Subjects; @@ -20,6 +23,10 @@ public class DelimitedStreamSensor : AresDevice, IDelimitedSteamSensor private readonly string[] _fields; private readonly StreamingField[] _streamingFields; private readonly IReadOnlyDictionary _streamingFieldsByName; + private readonly System.IO.Ports.SerialPort _serialConnection; + private CancellationTokenSource _stateGetterLoopTokenSource = new(); + //private CompositeDisposable _stateWatchers = new(); + private Task _stateUpdater = Task.CompletedTask; private readonly BehaviorSubject _stateSubject = new(new AresStruct()); @@ -32,6 +39,19 @@ public DelimitedStreamSensor(DeviceConnectionInfo info, ILogger logger) : base(i StateStream = _stateSubject.AsObservable(); _logger.LogInformation($"Parsing data format '{_dataFormat}'"); + _serialConnection = new System.IO.Ports.SerialPort() + { + PortName = info.SerialConnectionInfo.PortName, + BaudRate = 115200, + Parity = System.IO.Ports.Parity.None, + StopBits = System.IO.Ports.StopBits.One, + DataBits = 8, + DtrEnable = true, + RtsEnable = true, + ReadTimeout=1000, + }; + + _fields = _dataFormat.Split(":,\t".ToCharArray(), StringSplitOptions.None).Select(field => field.Trim()).ToArray(); @@ -68,6 +88,46 @@ public DelimitedStreamSensor(DeviceConnectionInfo info, ILogger logger) : base(i }) .Build()) .Build(); + + //_stateWatchers = new CompositeDisposable + // { + // _serialConnection.GetTransactionStream().Select(transaction => transaction.Response).Subscribe(UpdateLiveData) + // }; + + _logger.LogInformation($" Streaming device {Name} initialization completed"); + } + + private void UpdateLiveData(string response) + { + // TODO: move parsing into parser class (deliver key-value pairs instead of raw line) + //_logger.LogInformation($"Received line: {response}"); + var fields = response.Split(":,\t".ToCharArray(), StringSplitOptions.None).Select(field => field.Trim()).ToArray(); + foreach (var field in _streamingFields) + { + double value; + if (double.TryParse(fields[field.DataIndex], out value)) + { + field.Value = value; + if (field.StatsActive) field.Stats.AddValue(value); + } + else + { + field.Value = null; + } + } + + var next = AresStateBuilder + .From(_stateSubject.Value) + .AddStruct("LiveData", b => + { + foreach (var field in _streamingFields) + { + b.Add(field.Name, field.Value ?? 0.0); + } + }) + .Build(); + + _stateSubject.OnNext(next); } private AresStruct BuildInitialState() @@ -89,15 +149,97 @@ private AresStruct BuildInitialState() .Build(); } - public override IObservable StateStream { get; } - public override Task Activate(CancellationToken ct) + public async override Task Activate(CancellationToken ct) + { + bool activated = false; + _logger.LogInformation($"Activating streaming device {Name}..."); + try + { + await Initialize(); + activated = true; + Status = new DeviceOperationalStatus { OperationalState = OperationalState.Active, Message = $"Streaming device {Name} is active!" }; + _logger.LogInformation($"Device {Name} activated"); + } + catch (Exception e) + { + Status = new DeviceOperationalStatus { OperationalState = OperationalState.Error, Message = $"Failed to initialize: {e.Message}" }; + _logger.LogError(e, $"Device {Name} activation failed"); + } + + return activated; + } + + private async Task Initialize() { + if (_serialConnection is null) + { + _logger.LogError($"Serial device {Name}: Initialize was called, but connection was not set!"); + return; + } + + await StopUpdateLoop(); + _stateSubject.OnNext(BuildInitialState()); - return Task.FromResult(true); + _ = Start(); + + } + + public async Task Start() + { + await StopUpdateLoop(); + await StartUpdateLoop(TimeSpan.FromMilliseconds(500)); + } + + public async Task StartUpdateLoop(TimeSpan interval) + { + await StopUpdateLoop(); + await Task.Delay(150); + _stateGetterLoopTokenSource = new CancellationTokenSource(); + _stateUpdater = Task.Factory.StartNew(async _ => + { + Thread.CurrentThread.Name = $"Serial Device {Name} State Update Loop Thread"; + try + { + while (!_stateGetterLoopTokenSource.IsCancellationRequested) + { + try + { + if (!_serialConnection.IsOpen) _serialConnection.Open(); + //_logger.LogInformation($"Requesting live data at {DateTime.Now}"); + var liveData = _serialConnection.ReadLine(); + UpdateLiveData(liveData); + } + catch (TimeoutException) + { + _logger.LogError($"Get Live Data timed out at {DateTime.Now}"); + Status = new DeviceOperationalStatus { OperationalState = OperationalState.Active, Message = $"Get Live Data timed out at {DateTime.Now}" }; + } + catch (Exception e) + { + _logger.LogError(e, $"Get Live Data failed at {DateTime.Now}"); + await Task.Delay(150); + } + } + } + catch (ObjectDisposedException) + { + } + catch (Exception e) + { + Status = new DeviceOperationalStatus { OperationalState = OperationalState.Error, Message = $"{e.Message}" }; + } + }, + _stateGetterLoopTokenSource.Token); + } + + private async Task StopUpdateLoop() + { + _stateGetterLoopTokenSource?.Cancel(); + await _stateUpdater; } public Task BeginCollectingStats(string fieldName) @@ -111,9 +253,9 @@ public Task BeginCollectingStats(string fieldName) public async ValueTask DisposeAsync() { //_stateWatchers.Dispose(); - //await _stateGetterLoopTokenSource.CancelAsync(); - //await _stateUpdater; - //_stateGetterLoopTokenSource.Dispose(); + await _stateGetterLoopTokenSource.CancelAsync(); + await _stateUpdater; + _stateGetterLoopTokenSource.Dispose(); _stateSubject.OnCompleted(); } diff --git a/SerialStreamingSensor/SerialStreamingSensor.csproj b/SerialStreamingSensor/SerialStreamingSensor.csproj index 4cf115b..3ee1c0e 100644 --- a/SerialStreamingSensor/SerialStreamingSensor.csproj +++ b/SerialStreamingSensor/SerialStreamingSensor.csproj @@ -19,6 +19,7 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/SerialStreamingSensor/UI/DelimitedStreamSensorControl.razor b/SerialStreamingSensor/UI/DelimitedStreamSensorControl.razor index 8fdd81d..9b3c3eb 100644 --- a/SerialStreamingSensor/UI/DelimitedStreamSensorControl.razor +++ b/SerialStreamingSensor/UI/DelimitedStreamSensorControl.razor @@ -10,41 +10,43 @@ } else { -
-
- @GetDisplayName() +
+
+
+ @GetDisplayName() +
+ +
+ @GetStatusText() +
-
- @GetStatusText() -
+ @if (ViewModel.SensorState.LiveData.Count == 0) + { +
+ No live-data fields are defined. +
+ } + else + { + + + @foreach (var entry in ViewModel.SensorState.LiveData) + { + + + + + + } + +
+ @FormatName(entry.Name) + + @FormatValue(entry.Value) +
+ }
- - @if (ViewModel.SensorState.LiveData.Count == 0) - { -
- No live-data fields are defined. -
- } - else - { -
- @foreach (var entry in ViewModel.SensorState.LiveData) - { -
- - - @FormatName(entry.Name) - - - - @FormatValue(entry.Value) - -
- } -
- } } @code { @@ -88,27 +90,31 @@ else private string GetStatusText() { if (ViewModel?.CapturingLiveData == true) - return "Live"; + return "LIVE"; if (ViewModel?.HasValidData == true) - return "Connected"; + return "CONNECTED"; - return "Waiting for data"; + return "INITIALIZING"; } private string GetStatusClass() { - return ViewModel?.CapturingLiveData == true - ? "streaming-sensor-status active" - : "streaming-sensor-status waiting"; + if (ViewModel?.CapturingLiveData == true) + return "device-state connected"; + + if (ViewModel?.HasValidData == true) + return "device-state connected"; + + return "device-state initializing"; } private static string GetValueClass( DelimitedStreamSensorLiveDataEntry entry) { return entry.Value.HasValue - ? "streaming-sensor-value" - : "streaming-sensor-value unavailable"; + ? "parameter-value" + : "parameter-value unavailable"; } private static string FormatValue(double? value) @@ -151,4 +157,4 @@ else _viewModelSubscription?.Dispose(); _viewModelSubscription = null; } -} \ No newline at end of file +} diff --git a/SerialStreamingSensor/UI/DelimitedStreamSensorControl.razor.css b/SerialStreamingSensor/UI/DelimitedStreamSensorControl.razor.css index 5f28270..17971f2 100644 --- a/SerialStreamingSensor/UI/DelimitedStreamSensorControl.razor.css +++ b/SerialStreamingSensor/UI/DelimitedStreamSensorControl.razor.css @@ -1 +1,68 @@ - \ No newline at end of file +.device-container { + display: grid; + grid-template: + "header" + "state" + / minmax(0, 1fr); + justify-content: center; +} + +.title-row { + grid-area: header; + display: flex; + justify-content: space-between; + align-items: center; + width: 100%; + min-width: 0; + padding: 8px 10px; + gap: 10px; + border-radius: 6px; + box-sizing: border-box; +} + +.device-name { + flex: 1 1 auto; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-size:larger; +} + +.device-state { + flex: 0 0 auto; +} + +.status-connected { + background-color: #28a745; +} + +.status-initializing { + background-color: #f0ad4e; +} + +.status-error { + background-color: #dc3545; +} + +.parameter-table { + grid-area: state; + width: 95%; + min-width: 0; + border-collapse: collapse; + table-layout: auto; +} + +.parameter-name { + min-width: 80px; + white-space: normal; + overflow-wrap: anywhere; + font-size: smaller; +} + +.parameter-value { + width: 120px; + min-width: 90px; + white-space: nowrap; + font-size: smaller; +} diff --git a/plugins/SerialStreamingSensor.ares.archive b/plugins/SerialStreamingSensor.ares.archive new file mode 100644 index 0000000000000000000000000000000000000000..bf966ba962611ce5ddc5b0a2b4fe4b6de1035740 GIT binary patch literal 74000 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