✨ feat(*): 更新 PLC 相关功能与配置

- 在 appConfig.json 中添加 EndianFormat 配置项并更新相关输入输出地址
- 修改 ResultCode 类型为 short,确保与 PLC 通信一致
- 新增 DesignTimePlcService 以支持设计时的 PLC 测试写入功能
- 更新 SystemSettingViewModel 和 DashboardPage 以支持手动测试写入
- 调整多个视图模型和服务以适应新的 PLC 写入逻辑
- 更新相关单元测试以验证新功能的正确性
This commit is contained in:
2026-06-02 17:26:24 +08:00
parent ce356bffff
commit 27e2c9d5d0
31 changed files with 812 additions and 110 deletions

View File

@@ -148,12 +148,12 @@ public sealed class WorkflowHostedServiceTests
Assert.True(scannerService.TriggerCount > 0);
Assert.Contains(plcService.WrittenStates, state => state.ReleasePermit);
Assert.Contains(plcService.WrittenStates, state => state.ResultCode == (ushort)WorkflowResultCode.Passed);
Assert.Contains(plcService.WrittenStates, state => state.ResultCode == (short)WorkflowResultCode.Passed);
RuntimeSnapshot snapshot = stateStore.GetSnapshot();
Assert.Contains(snapshot.PlcMonitorItems, item => item.Name == "PcbArrived" && item.CurrentValue == "False");
Assert.Contains(snapshot.PlcMonitorItems, item => item.Name == "PcBusy" && item.CurrentValue == "False");
Assert.Contains(snapshot.PlcMonitorItems, item => item.Name == "ResultCode" && item.CurrentValue == ((ushort)WorkflowResultCode.Passed).ToString());
Assert.Contains(snapshot.PlcMonitorItems, item => item.Name == "ResultCode" && item.CurrentValue == ((short)WorkflowResultCode.Passed).ToString());
Assert.All(snapshot.PlcMonitorItems, item => Assert.NotEqual(default, item.LastUpdatedAt));
}
@@ -217,7 +217,7 @@ public sealed class WorkflowHostedServiceTests
Assert.Equal(1, scannerService.TriggerCount);
Assert.Equal("PCB-MERGED", fileCheckService.LastBarcode);
Assert.Contains(plcService.WrittenStates, state => state.ResultCode == (ushort)WorkflowResultCode.Passed);
Assert.Contains(plcService.WrittenStates, state => state.ResultCode == (short)WorkflowResultCode.Passed);
}
/// <summary>
@@ -304,7 +304,7 @@ public sealed class WorkflowHostedServiceTests
Barcode = "PCB-RESTORED",
ScanTryCount = 1,
SftpTryCount = 1,
ResultCode = (ushort)WorkflowResultCode.Passed,
ResultCode = (short)WorkflowResultCode.Passed,
ResultDescription = "OK",
ReleaseSent = true
}
@@ -409,7 +409,7 @@ public sealed class WorkflowHostedServiceTests
RuntimeSnapshot snapshot = stateStore.GetSnapshot();
Assert.NotEqual(WorkflowState.Faulted, snapshot.WorkflowState);
Assert.Equal((ushort)WorkflowResultCode.Passed, snapshot.ResultCode);
Assert.Equal((short)WorkflowResultCode.Passed, snapshot.ResultCode);
}
private sealed class FakePlcService : IPlcService
@@ -418,6 +418,7 @@ public sealed class WorkflowHostedServiceTests
public Task<PlcMonitorSnapshot> ReadMonitorSnapshotAsync(CancellationToken cancellationToken) => Task.FromResult(new PlcMonitorSnapshot());
public Task<PlcSignalSnapshot> ReadSignalsAsync(CancellationToken cancellationToken) => Task.FromResult(new PlcSignalSnapshot());
public Task WriteStateAsync(PlcProcessState state, CancellationToken cancellationToken) => Task.CompletedTask;
public Task<PlcWriteResult> WriteRawValueAsync(string address, PlcWriteType type, string value, CancellationToken cancellationToken) => Task.FromResult(PlcWriteResult.Success(address, type, value));
}
private sealed class ProbingPlcService : IPlcService
@@ -460,6 +461,11 @@ public sealed class WorkflowHostedServiceTests
{
return Task.CompletedTask;
}
public Task<PlcWriteResult> WriteRawValueAsync(string address, PlcWriteType type, string value, CancellationToken cancellationToken)
{
return Task.FromResult(PlcWriteResult.Success(address, type, value));
}
}
private sealed class FailingPlcService : IPlcService
@@ -483,6 +489,11 @@ public sealed class WorkflowHostedServiceTests
{
return Task.CompletedTask;
}
public Task<PlcWriteResult> WriteRawValueAsync(string address, PlcWriteType type, string value, CancellationToken cancellationToken)
{
throw new InvalidOperationException("PLC unreachable");
}
}
private sealed class SequencedPlcService : IPlcService
@@ -529,6 +540,11 @@ public sealed class WorkflowHostedServiceTests
WrittenStates.Add(state.Clone());
return Task.CompletedTask;
}
public Task<PlcWriteResult> WriteRawValueAsync(string address, PlcWriteType type, string value, CancellationToken cancellationToken)
{
return Task.FromResult(PlcWriteResult.Success(address, type, value));
}
}
private sealed class FakeScannerService : IScannerService