FAT P2: embed production FAT workspace in Engineering tab - #290
FAT P2: embed production FAT workspace in Engineering tab#290masarray wants to merge 34 commits into
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2d5a962c93
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| public bool CaptureValue(int slot) | ||
| { | ||
| if (!CanCapture || slot is < 1 or > 2) | ||
| return false; | ||
|
|
||
| var capture = CaptureCurrent(); |
There was a problem hiding this comment.
Require a live sample before capturing FAT evidence
When the selected IED comes from an offline SCL or cached project, a SignalDefinition exists with its default value/quality ("-" and "Unknown") even though there is no active live point. Because CanCapture only checks for the existence of either source object, CaptureValue records that placeholder as commissioning evidence and the row can subsequently be marked PASS. Require an active, initialized, sufficiently fresh live observation rather than merely an engineering-model source.
Useful? React with 👍 / 👎.
| File.Move(tempPath, path, overwrite: true); | ||
| state.StoragePath = path; |
There was a problem hiding this comment.
Keep unreadable state files from being overwritten
When the preferred JSON is damaged, TryReadAsync returns null and LoadAsync creates a new state whose StoragePath is that same file; the automatic save queued after reconciliation then replaces it here. This contradicts the recovery behavior promised by TryReadAsync and permanently destroys the old commissioning evidence before an operator can recover it. Quarantine the damaged file or choose a different path for the replacement state.
Useful? React with 👍 / 👎.
| private string GetPreferredPath(string? iedName) | ||
| => Path.Combine(_rootDirectory, SanitizeFileStem(iedName) + ".json"); |
There was a problem hiding this comment.
Include device identity in each state filename
When two active devices have the same display name, or names that sanitize to the same stem, both states resolve to the same JSON path even though their DeviceId values differ. Saving the second state uses overwrite mode and destroys the first device's FAT evidence; duplicate IED names are possible across separate SCL sources and endpoints. Derive the path from a collision-resistant device identity in addition to the display name.
Useful? React with 👍 / 👎.
| if (!string.IsNullOrWhiteSpace(state.DeviceId) && | ||
| state.DeviceId.Equals(device.DeviceId, StringComparison.OrdinalIgnoreCase)) | ||
| return true; | ||
|
|
||
| return string.IsNullOrWhiteSpace(state.DeviceId) && | ||
| state.IedName.Equals(device.Name, StringComparison.OrdinalIgnoreCase); |
There was a problem hiding this comment.
Use an identity that survives reopening an endpoint
When an operator re-adds the same endpoint in a later application launch without reopening a saved project, Iec61850MonitorDevice.DeviceId is a new random GUID. This check therefore rejects the prior JSON even when the discovered IED name and preferred path are identical, after which a blank reconciled state overwrites that file. Base persisted matching on a durable endpoint/SCL/device identity, or persist the generated ID independently of project files, so the advertised resumable state works across ordinary launches.
Useful? React with 👍 / 👎.
| _nativeFatInstallRetry?.Stop(); | ||
| _nativeFatReconcileTimer?.Stop(); | ||
| _nativeFatSaveTimer?.Stop(); | ||
| _nativeFatLoadCts?.Cancel(); |
There was a problem hiding this comment.
Flush pending FAT edits during shutdown
When the user closes the application within the 350 ms autosave debounce after a capture or result change, shutdown has already cancelled _applicationCancellation and this handler simply stops the pending timer without saving its state. The last commissioning action is therefore lost permanently despite the UI saying autosave was queued. Flush the pending state before cancellation/closure and await that save before disposing the gate.
Useful? React with 👍 / 👎.
| private async void NativeFatSaveTimer_Tick(object? sender, EventArgs e) | ||
| { | ||
| _nativeFatSaveTimer?.Stop(); | ||
| if (_nativeFatCurrentState != null) | ||
| await SaveNativeFatStateAsync(_nativeFatCurrentState); |
There was a problem hiding this comment.
Bind each queued save to the state that was edited
When an operator edits FAT data and selects another IED before the debounce expires, loading the new IED replaces _nativeFatCurrentState; the timer then dereferences that field and saves the new state instead of the departing edited state. The old edits remain only in the cache and are lost if that IED is not revisited before exit. Capture the state when scheduling the save or maintain independent pending saves per device.
Useful? React with 👍 / 👎.
| if (!forceReconcile && _nativeFatCurrentState != null && | ||
| _nativeFatCurrentState.DeviceId.Equals(device.DeviceId, StringComparison.OrdinalIgnoreCase)) | ||
| { | ||
| UpdateNativeFatSummary(); | ||
| return; |
There was a problem hiding this comment.
Reconcile after Explorer selection changes
When Explorer signal selections change while FAT is not selected, the FAT collection-change handler ignores any resulting point changes and does not observe SignalDefinition.IsSelected changes at all. Re-entering FAT with the same device then returns here without reconciliation, so added selections remain absent and removed selections remain current until the user manually clicks Refresh. Track selection changes or force reconciliation whenever the workspace is entered.
Useful? React with 👍 / 👎.
Merge the validated P0/P1 Engineering shell: persistent IED Explorer, shared resizable Command Dock, observation scope refinements, panel geometry, loading feedback, and safer RCB export guidance. Native FAT tab work remains isolated in PR #290.
Milestone
Move the proven production FAT workspace into the persistent Engineering
FATtab and make Engineering/Explorer the single SCL/static-DataSet/live-value authority.Production FAT tab pivot
mainIoListTestingWindowproduction central workspace into the FAT tabIoTestProject,IoTestMultiSessionCoordinator,IoTestSessionController, persistence, auto-capture and FAT result lifecycle instead of implementing a second FAT state machineEngineering-owned automatic FAT bootstrap
FATno longer requires a secondOpen SCL for FATSclIedWorkspacewith static DataSet members, FAT automatically builds the production project from those exact in-memory ARIEC workspacesIoFatEngineeringWorkspaceProjectionServiceconsumes the existing EngineeringSclIedWorkspaceobjects andFatSclWorkspaceImportServicestatic-DataSet projection; it does not invokeSclWorkspaceService.OpenAsyncor parse XML againARSAS-FAT-SCL-1.0persistence path, so saved FAT progress can continue using the same source identityP0 field fixes
MainWindow.Hide()/ child-WindowShow()hand-off to blank the already-visible Engineering shell; the compatibility hide path still delegates to WPF outside that narrowly-scoped embedded bootstrapscl-manual-*workspace overlays are retired from activeWorkspaceSelectedscope when authoritative static DataSet rows existTestEnabled, FAT disposition or captured evidence; saved audit/evidence continuity is preservedFAT workflow
Capture V1,Capture V2,PASS,REVIEW,FAIL,Reset currentworkflow is retired from the visible FAT tabReport Preview
IoListTestingWindow.PrintPreviewimplementationPrint Previewswitches the entire FAT center between signal/testing view and the native paged report previewNavigation / visual language
Engineering selection bridge
Excel intentionally deferred
Safety boundary
No Select/SBO/Operate sequencing, ctlModel, confirmation, interlock/synchrocheck/Test, CommandTermination, RCB runtime behavior, GOOSE capture, MMS acquisition, live-monitor acquisition, or production FAT evidence semantics are changed.
Regression coverage
device.SclWorkspaceand must not call an SCL/XML open/parser pathValidation
Latest head
4dfc8344f0838f489b735d3045ae71ec2abec89e:PR remains unmerged pending physical-IED field verification of the P0 transition/preflight fixes and the separate P1 FAT navigation visual cleanup.