-
Notifications
You must be signed in to change notification settings - Fork 1
Feat/fix alicat multidrop #2
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
base: Develop
Are you sure you want to change the base?
Changes from all commits
cfa02e6
518da29
fb65d85
75b65a2
4e3827a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk.Web"> | ||
|
|
||
| <PropertyGroup> | ||
| <TargetFramework>net10.0</TargetFramework> | ||
| <Nullable>enable</Nullable> | ||
| <ImplicitUsings>enable</ImplicitUsings> | ||
| </PropertyGroup> | ||
|
|
||
| </Project> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -25,7 +25,7 @@ namespace AlicatMFCRemastered; | |
|
|
||
| public class MassFlowController : AresDevice, IMassFlowController | ||
| { | ||
| private readonly int _expectedDataFormatEntryCount; | ||
| private readonly int _expectedDataFormatEntryCount; | ||
| private readonly BehaviorSubject<AresStruct> _stateSubject = new(new AresStruct()); | ||
| private CancellationTokenSource _stateGetterLoopTokenSource = new(); | ||
| private CompositeDisposable _stateWatchers = new(); | ||
|
|
@@ -57,12 +57,13 @@ public MassFlowController(DeviceConnectionInfo connectionInfo, ILogger logger) : | |
| } | ||
|
|
||
| else | ||
| _serialConnection = new MassFlowControllerConnection(serialInfo.PortName); | ||
| _serialConnection = MassFlowControllerConnection.GetMassFlowControllerConnection(serialInfo.PortName); | ||
|
|
||
| _stateWatchers = new CompositeDisposable | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see the motivation here, but this should theoretically not be an issue on the current system. When receiving data that needs to be parsed, we have dedicated response parser classes that handle breaking down the serialized data. In the case of this stream, we're only going to get this processed response (the "LiveDataResponse" class) in the event that parser deemed it a valid response to parse. You can find that logic under "Commands/Responses/Parsers/LiveDataParser.cs". Based on that, I don't think this change is necessary, you shouldn't see the system processing any additional data from MFC's other than the one you told the driver to care about. If you are, then perhaps there's another bug happening under the hood we can dig out. |
||
| { | ||
| _serialConnection.GetTransactionStream<LiveDataResponse>().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<LiveDataResponse>().Select(transaction => transaction.Response).Subscribe(UpdateLiveData) | ||
| //}; | ||
|
|
||
| _expectedDataFormatEntryCount = _mfcType == MfcTypeEnum.Normal ? 12 : 7; | ||
|
|
||
|
|
@@ -170,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(); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just curious, was this change inspired by an issue you saw in lab? |
||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -461,9 +465,9 @@ public Task NewComposerMix(MfcGasComposition composerMix) | |
| public async Task NewSetpoint(StandardVolumeFlow setpoint) | ||
| { | ||
| if(_mfcType == MfcTypeEnum.Normal) | ||
| { | ||
| { | ||
| var newSetpointCommand = new NewSetpointCommand(AssumedId, setpoint, GetFormatEntries(), FirmwareVersion); | ||
| try | ||
| try | ||
| { | ||
| var response = await Send(newSetpointCommand, TimeSpan.FromSeconds(10)); | ||
| } | ||
|
|
@@ -655,7 +659,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 +734,9 @@ private async Task<TResult> GetResponseWithRetry<TResult, TRequest>(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 | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My comment above talks about this point I believe |
||
| /// if (liveResponse.Id != this.AssumedId) return; | ||
|
|
||
| var next = AresStateBuilder | ||
| .From(_stateSubject.Value) | ||
| .AddStruct("LiveData", b => | ||
|
|
@@ -963,7 +972,8 @@ public override async Task<CommandResult> ExecuteCommand(string command, List<De | |
| if(!setpointFound) | ||
| return ArgumentError("NewSetpoint", "Setpoint", "number"); | ||
|
|
||
| await NewSetpoint(StandardVolumeFlow.FromStandardCubicCentimetersPerMinute(setpoint)); | ||
| _logger.LogInformation($"Attempting to set new setpoint for MFC {Name} to {setpoint} sccm"); | ||
| await NewSetpoint(StandardVolumeFlow.FromStandardCubicCentimetersPerMinute(setpoint)); | ||
| break; | ||
|
|
||
| case MassFlowControllerCommand.GetSetpoint: | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm curious if you could elaborate on what you wanted to implement this to address. Typically we don't expect the driver to care about it's connection in relation to any others (maintaining the idea that the driver itself would only really care about it's own connection). It's true that the MFC's can share a serial connection, and we account for that in ARES by allowing devices of the same class (i.e. Alicat MFC's) to share the same resource with a unique identifier. For the MFC's this is the Id list that use a single capital letter (A, B, C...). Unless there's something critical this provides, I would say this is best left at the ARES level rather than the driver level itself.