From cfa02e6873fad29f453a954f04f9849cb3155f6c Mon Sep 17 00:00:00 2001 From: garath001 <62758265+garath001@users.noreply.github.com> Date: Thu, 30 Jul 2026 08:45:20 -0400 Subject: [PATCH 1/5] Quick fix for multidrop alicat serial connection --- .../Connection/MassFlowControllerConnection.cs | 11 ++++++++++- AlicatMFCRemastered/MassFlowController.cs | 18 ++++++++++++------ 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/AlicatMFCRemastered/Connection/MassFlowControllerConnection.cs b/AlicatMFCRemastered/Connection/MassFlowControllerConnection.cs index 55d31d0..47a5b87 100644 --- a/AlicatMFCRemastered/Connection/MassFlowControllerConnection.cs +++ b/AlicatMFCRemastered/Connection/MassFlowControllerConnection.cs @@ -6,7 +6,16 @@ namespace AlicatMFCRemastered; public class MassFlowControllerConnection : AresHardwareConnection, IMfcConnection { - private readonly List _unusedIds; + static Dictionary _connections = new Dictionary(); + public static MassFlowControllerConnection GetMassFlowControllerConnection(string portName) + { + if (!_connections.ContainsKey(portName)) + _connections[portName] = new MassFlowControllerConnection(portName); + + return _connections[portName]; + } + + private readonly List _unusedIds; public MassFlowControllerConnection(string portName) : base(new SerialPortConnectionInfo(19200, Parity.None, 8, StopBits.One), portName, new SerialConnectionOptions diff --git a/AlicatMFCRemastered/MassFlowController.cs b/AlicatMFCRemastered/MassFlowController.cs index 74b3a6e..fa0c33c 100644 --- a/AlicatMFCRemastered/MassFlowController.cs +++ b/AlicatMFCRemastered/MassFlowController.cs @@ -57,12 +57,13 @@ public MassFlowController(DeviceConnectionInfo connectionInfo, ILogger logger) : } else - _serialConnection = new MassFlowControllerConnection(serialInfo.PortName); + _serialConnection = MassFlowControllerConnection.GetMassFlowControllerConnection(serialInfo.PortName); - _stateWatchers = new CompositeDisposable - { - _serialConnection.GetTransactionStream().Select(transaction => transaction.Response).Subscribe(UpdateLiveData) - }; + /// replaced with transactional update. Could restore if we add an id check to verify correct MFC, but given potential 26 MFCs on a single connection, most traffic on bus could be ignored + //_stateWatchers = new CompositeDisposable + //{ + // _serialConnection.GetTransactionStream().Select(transaction => transaction.Response).Subscribe(UpdateLiveData) + //}; _expectedDataFormatEntryCount = _mfcType == MfcTypeEnum.Normal ? 12 : 7; @@ -655,7 +656,9 @@ public async Task StartUpdateLoop(TimeSpan interval) try { var liveData = await GetLiveData(); - } + /// explicit call required here if statewatchers is not used to subscribe to the live data stream, otherwise the state will not update + UpdateLiveData(liveData); + } catch(TimeoutException) { Status = new DeviceOperationalStatus { OperationalState = OperationalState.Active, Message = $"Get Live Data timed out at {DateTime.Now}" }; @@ -728,6 +731,9 @@ private async Task GetResponseWithRetry(TRequest req private void UpdateLiveData(LiveDataResponse liveResponse) { _liveData = liveResponse; + /// check on id is required if _statewatcher is used in order to avoid updating the state with a response from a different MFC than the one that is being watched + /// if (liveResponse.Id != this.AssumedId) return; + var next = AresStateBuilder .From(_stateSubject.Value) .AddStruct("LiveData", b => From 518da295cd3dedba544afaf2d0b66441b485f57f Mon Sep 17 00:00:00 2001 From: garath001 <62758265+garath001@users.noreply.github.com> Date: Thu, 30 Jul 2026 08:48:48 -0400 Subject: [PATCH 2/5] comments on mfcflowcontrollerconnection --- AlicatBusMFC/AlicatBusMFC.csproj | 9 +++++++++ .../Connection/MassFlowControllerConnection.cs | 2 ++ 2 files changed, 11 insertions(+) create mode 100644 AlicatBusMFC/AlicatBusMFC.csproj diff --git a/AlicatBusMFC/AlicatBusMFC.csproj b/AlicatBusMFC/AlicatBusMFC.csproj new file mode 100644 index 0000000..a3a34b6 --- /dev/null +++ b/AlicatBusMFC/AlicatBusMFC.csproj @@ -0,0 +1,9 @@ + + + + net10.0 + enable + enable + + + diff --git a/AlicatMFCRemastered/Connection/MassFlowControllerConnection.cs b/AlicatMFCRemastered/Connection/MassFlowControllerConnection.cs index 47a5b87..1f28660 100644 --- a/AlicatMFCRemastered/Connection/MassFlowControllerConnection.cs +++ b/AlicatMFCRemastered/Connection/MassFlowControllerConnection.cs @@ -6,6 +6,7 @@ namespace AlicatMFCRemastered; public class MassFlowControllerConnection : AresHardwareConnection, IMfcConnection { + //simple registry to manage instances of seriaport resources across multiple mfcs static Dictionary _connections = new Dictionary(); public static MassFlowControllerConnection GetMassFlowControllerConnection(string portName) { @@ -15,6 +16,7 @@ public static MassFlowControllerConnection GetMassFlowControllerConnection(strin return _connections[portName]; } + private readonly List _unusedIds; public MassFlowControllerConnection(string portName) : base(new SerialPortConnectionInfo(19200, Parity.None, 8, StopBits.One), portName, From fb65d85015f9be858afe95a0a302670a2ec4135f Mon Sep 17 00:00:00 2001 From: garath001 <62758265+garath001@users.noreply.github.com> Date: Mon, 10 Aug 2026 14:02:47 -0400 Subject: [PATCH 3/5] Added units to parser Removed unit from display until dynamic units are implemented --- AlicatMFCRemastered/Parsers/MfcUnitParser.cs | 4 +++- AlicatMFCRemastered/UI/MfcUnitControl.razor | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/AlicatMFCRemastered/Parsers/MfcUnitParser.cs b/AlicatMFCRemastered/Parsers/MfcUnitParser.cs index c420c1c..a4c0c83 100644 --- a/AlicatMFCRemastered/Parsers/MfcUnitParser.cs +++ b/AlicatMFCRemastered/Parsers/MfcUnitParser.cs @@ -16,8 +16,10 @@ static MfcUnitParser() // PSIA should just be absolute PSI, so I believe the unit can just be PSI mfcUnitCache.MapUnitToAbbreviation(PressureUnit.PoundForcePerSquareInch, "PSIA"); mfcUnitCache.MapUnitToAbbreviation(VolumeFlowUnit.CubicCentimeterPerMinute, "CCM"); + mfcUnitCache.MapUnitToAbbreviation(VolumeFlowUnit.LiterPerMinute, "LPM"); mfcUnitCache.MapUnitToAbbreviation(StandardVolumeFlowUnit.StandardLiterPerMinute, "SLPM"); - Parser = new MfcUnitParser(new UnitParser(mfcUnitCache)); + mfcUnitCache.MapUnitToAbbreviation(StandardVolumeFlowUnit.StandardCubicCentimeterPerMinute, "SCCM"); + Parser = new MfcUnitParser(new UnitParser(mfcUnitCache)); } public MfcUnitParser(UnitParser parser) diff --git a/AlicatMFCRemastered/UI/MfcUnitControl.razor b/AlicatMFCRemastered/UI/MfcUnitControl.razor index bdfccc0..adf1241 100644 --- a/AlicatMFCRemastered/UI/MfcUnitControl.razor +++ b/AlicatMFCRemastered/UI/MfcUnitControl.razor @@ -37,7 +37,7 @@ }
-
Mass Flow (SCCM)
+
Mass Flow
@($"{ViewModel!.AlicatState.LiveData.MassFlow}")
@@ -48,7 +48,7 @@
} -
Setpoint (SCCM)
+
Setpoint
@($"{ViewModel!.AlicatState.LiveData.Setpoint}")
New Setpoint
Date: Tue, 11 Aug 2026 09:14:14 -0400 Subject: [PATCH 4/5] Unified setpoint units and maxvalue units --- AlicatMFCRemastered/MassFlowController.cs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/AlicatMFCRemastered/MassFlowController.cs b/AlicatMFCRemastered/MassFlowController.cs index fa0c33c..e272885 100644 --- a/AlicatMFCRemastered/MassFlowController.cs +++ b/AlicatMFCRemastered/MassFlowController.cs @@ -25,7 +25,7 @@ namespace AlicatMFCRemastered; public class MassFlowController : AresDevice, IMassFlowController { - private readonly int _expectedDataFormatEntryCount; + private readonly int _expectedDataFormatEntryCount; private readonly BehaviorSubject _stateSubject = new(new AresStruct()); private CancellationTokenSource _stateGetterLoopTokenSource = new(); private CompositeDisposable _stateWatchers = new(); @@ -171,9 +171,12 @@ private void UpdatePotentialMaxValue(ManufacturerInfoEntry entry) _logger.LogWarning($"Failed to get max value for MFC {Name} as we couldn't get the numeric max value from model number {entry.Data}"); return; } - var flowVal = StandardVolumeFlow.From(numericNum, unit); - dataFrameFormat.MaxVal = flowVal.StandardLitersPerMinute.ToString(); - } + _logger.LogInformation($"Found a potential max value of {numericNum} {unit} for MFC {Name} from model number {entry.Data}"); + var flowVal = StandardVolumeFlow.From(numericNum, unit); +// must be converted to match setpoint units, otherwise may cause issues when calculating newsetpoint + // dataFrameFormat.MaxVal = flowVal.StandardLitersPerMinute.ToString(); + dataFrameFormat.MaxVal = flowVal.As((StandardVolumeFlowUnit)dataFrameFormat.Unit).ToString(); + } } } } @@ -462,9 +465,10 @@ public Task NewComposerMix(MfcGasComposition composerMix) public async Task NewSetpoint(StandardVolumeFlow setpoint) { if(_mfcType == MfcTypeEnum.Normal) - { + { var newSetpointCommand = new NewSetpointCommand(AssumedId, setpoint, GetFormatEntries(), FirmwareVersion); - try + _logger.LogInformation($"DEBUG_UNITCONVERSION: Calculating ratio of {newSetpointCommand.SetPoint.Value} {newSetpointCommand.SetPoint.Unit} to {newSetpointCommand.MaxSetPoint.Value} {newSetpointCommand.MaxSetPoint.Unit} = { newSetpointCommand.SetPoint / newSetpointCommand.MaxSetPoint }"); + try { var response = await Send(newSetpointCommand, TimeSpan.FromSeconds(10)); } @@ -969,7 +973,8 @@ public override async Task ExecuteCommand(string command, List Date: Tue, 11 Aug 2026 09:19:13 -0400 Subject: [PATCH 5/5] removed lines added for debugging --- AlicatMFCRemastered/MassFlowController.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/AlicatMFCRemastered/MassFlowController.cs b/AlicatMFCRemastered/MassFlowController.cs index e272885..8d0131d 100644 --- a/AlicatMFCRemastered/MassFlowController.cs +++ b/AlicatMFCRemastered/MassFlowController.cs @@ -467,7 +467,6 @@ public async Task NewSetpoint(StandardVolumeFlow setpoint) if(_mfcType == MfcTypeEnum.Normal) { var newSetpointCommand = new NewSetpointCommand(AssumedId, setpoint, GetFormatEntries(), FirmwareVersion); - _logger.LogInformation($"DEBUG_UNITCONVERSION: Calculating ratio of {newSetpointCommand.SetPoint.Value} {newSetpointCommand.SetPoint.Unit} to {newSetpointCommand.MaxSetPoint.Value} {newSetpointCommand.MaxSetPoint.Unit} = { newSetpointCommand.SetPoint / newSetpointCommand.MaxSetPoint }"); try { var response = await Send(newSetpointCommand, TimeSpan.FromSeconds(10));