diff --git a/src/AxiOmron.PcbCheck/Converters/ResultCodeToTagTextConverter.cs b/src/AxiOmron.PcbCheck/Converters/ResultCodeToTagTextConverter.cs
index 28cf4f1..723f293 100644
--- a/src/AxiOmron.PcbCheck/Converters/ResultCodeToTagTextConverter.cs
+++ b/src/AxiOmron.PcbCheck/Converters/ResultCodeToTagTextConverter.cs
@@ -5,7 +5,7 @@ using AxiOmron.PcbCheck.Models;
namespace AxiOmron.PcbCheck.Converters;
///
-/// 将 (以 存储)映射为简短 Tag 文本。
+/// 将 (以 存储)映射为简短 Tag 文本。
///
///
/// 映射规则:Passed → "OK";Processing → "处理中";None → "-";其余视为 "NG"。
@@ -22,19 +22,20 @@ public sealed class ResultCodeToTagTextConverter : IValueConverter
/// 简短标签文本。
public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
- short code = value switch
+ ushort code = value switch
{
- short s => s,
- int i => (short)i,
- WorkflowResultCode rc => (short)rc,
+ ushort s => s,
+ short s when s >= 0 => (ushort)s,
+ int i when i >= 0 && i <= ushort.MaxValue => (ushort)i,
+ WorkflowResultCode rc => (ushort)rc,
_ => 0
};
return code switch
{
- (short)WorkflowResultCode.Passed => "OK",
- (short)WorkflowResultCode.Processing => "处理中",
- (short)WorkflowResultCode.None => "-",
+ (ushort)WorkflowResultCode.Passed => "OK",
+ (ushort)WorkflowResultCode.Processing => "处理中",
+ (ushort)WorkflowResultCode.None => "-",
_ => "NG"
};
}
diff --git a/src/AxiOmron.PcbCheck/DesignTime/DesignTimeAppStateStore.cs b/src/AxiOmron.PcbCheck/DesignTime/DesignTimeAppStateStore.cs
index fac8ace..063cb9d 100644
--- a/src/AxiOmron.PcbCheck/DesignTime/DesignTimeAppStateStore.cs
+++ b/src/AxiOmron.PcbCheck/DesignTime/DesignTimeAppStateStore.cs
@@ -32,7 +32,7 @@ public sealed class DesignTimeAppStateStore : IAppStateStore
CurrentBarcode = "PCB240417000128",
ResultDescription = "已扫码,等待 SFTP 文件确认",
FaultMessage = string.Empty,
- ResultCode = (short)WorkflowResultCode.Processing,
+ ResultCode = (ushort)WorkflowResultCode.Processing,
LastTriggeredAt = now.AddSeconds(-18),
LastCompletedAt = now.AddMinutes(-2),
IsBusy = true,
@@ -44,7 +44,7 @@ public sealed class DesignTimeAppStateStore : IAppStateStore
_snapshot.PlcMonitorItems.Add(new PlcMonitorItem { GroupName = "Inputs", Name = "PlcAckRelease", Address = "10003", CurrentValue = "False", LastUpdatedAt = now.AddSeconds(-1) });
_snapshot.PlcMonitorItems.Add(new PlcMonitorItem { GroupName = "Outputs", Name = "PcBusy", Address = "51", CurrentValue = "True", LastUpdatedAt = now.AddSeconds(-1) });
_snapshot.PlcMonitorItems.Add(new PlcMonitorItem { GroupName = "Outputs", Name = "ReleasePermit", Address = "52", CurrentValue = "False", LastUpdatedAt = now.AddSeconds(-1) });
- _snapshot.PlcMonitorItems.Add(new PlcMonitorItem { GroupName = "Registers", Name = "ResultCode", Address = "40001", CurrentValue = ((short)WorkflowResultCode.Processing).ToString(), LastUpdatedAt = now.AddSeconds(-1) });
+ _snapshot.PlcMonitorItems.Add(new PlcMonitorItem { GroupName = "Registers", Name = "ResultCode", Address = "40001", CurrentValue = ((ushort)WorkflowResultCode.Processing).ToString(), LastUpdatedAt = now.AddSeconds(-1) });
_logs = new List
{
@@ -64,7 +64,7 @@ public sealed class DesignTimeAppStateStore : IAppStateStore
Barcode = "PCB240417000125",
ScanTryCount = 1,
SftpTryCount = 1,
- ResultCode = (short)WorkflowResultCode.Passed,
+ ResultCode = (ushort)WorkflowResultCode.Passed,
ResultDescription = "OK 放行",
ReleaseSent = true,
ExceptionSummary = string.Empty
@@ -76,7 +76,7 @@ public sealed class DesignTimeAppStateStore : IAppStateStore
Barcode = "PCB240417000126",
ScanTryCount = 3,
SftpTryCount = 0,
- ResultCode = (short)WorkflowResultCode.NgReleased,
+ ResultCode = (ushort)WorkflowResultCode.NgReleased,
ResultDescription = "扫码失败后放行",
ReleaseSent = true,
ExceptionSummary = "扫码连续失败三次"
@@ -88,7 +88,7 @@ public sealed class DesignTimeAppStateStore : IAppStateStore
Barcode = "PCB240417000127",
ScanTryCount = 1,
SftpTryCount = 3,
- ResultCode = (short)WorkflowResultCode.NgReleased,
+ ResultCode = (ushort)WorkflowResultCode.NgReleased,
ResultDescription = "处理结果 NG,随后放行",
ReleaseSent = true,
ExceptionSummary = "SFTP 文件查询超时"
@@ -97,8 +97,8 @@ public sealed class DesignTimeAppStateStore : IAppStateStore
_snapshot.RecordStatisticDate = DateOnly.FromDateTime(now.LocalDateTime.Date);
_snapshot.TodayProcessCount = _records.Count;
- _snapshot.TodayOkCount = _records.Count(record => record.ResultCode == (short)WorkflowResultCode.Passed);
- _snapshot.TodayNgCount = _records.Count(record => record.ResultCode != (short)WorkflowResultCode.Passed);
+ _snapshot.TodayOkCount = _records.Count(record => record.ResultCode == (ushort)WorkflowResultCode.Passed);
+ _snapshot.TodayNgCount = _records.Count(record => record.ResultCode != (ushort)WorkflowResultCode.Passed);
_snapshot.RecordsLastUpdatedAt = now;
foreach (BoardProcessRecord record in _records)
{
diff --git a/src/AxiOmron.PcbCheck/Models/RuntimeSnapshot.cs b/src/AxiOmron.PcbCheck/Models/RuntimeSnapshot.cs
index 1911f6f..3b1c1f5 100644
--- a/src/AxiOmron.PcbCheck/Models/RuntimeSnapshot.cs
+++ b/src/AxiOmron.PcbCheck/Models/RuntimeSnapshot.cs
@@ -63,7 +63,7 @@ public sealed class RuntimeSnapshot
///
/// 获取或设置结果代码。
///
- public short ResultCode { get; set; }
+ public ushort ResultCode { get; set; }
///
/// 获取或设置上次触发时间。
diff --git a/src/AxiOmron.PcbCheck/Models/WorkflowModels.cs b/src/AxiOmron.PcbCheck/Models/WorkflowModels.cs
index 06e9128..a4fb15a 100644
--- a/src/AxiOmron.PcbCheck/Models/WorkflowModels.cs
+++ b/src/AxiOmron.PcbCheck/Models/WorkflowModels.cs
@@ -69,7 +69,7 @@ public enum WorkflowState
///
/// 表示最终结果代码定义。
///
-public enum WorkflowResultCode : short
+public enum WorkflowResultCode : ushort
{
///
/// 无结果。
@@ -182,7 +182,7 @@ public sealed class PlcProcessState
///
/// 获取或设置结果代码寄存器值。
///
- public short ResultCode { get; set; }
+ public ushort ResultCode { get; set; }
///
/// 创建当前状态对象的浅拷贝。
@@ -496,7 +496,7 @@ public sealed class BoardProcessRecord
///
/// 获取或设置结果代码。
///
- public short ResultCode { get; set; }
+ public ushort ResultCode { get; set; }
///
/// 获取或设置结果描述。
diff --git a/src/AxiOmron.PcbCheck/Options/AppConfig.cs b/src/AxiOmron.PcbCheck/Options/AppConfig.cs
index 87713c7..1ef4701 100644
--- a/src/AxiOmron.PcbCheck/Options/AppConfig.cs
+++ b/src/AxiOmron.PcbCheck/Options/AppConfig.cs
@@ -130,9 +130,9 @@ public sealed class PlcOptions
public byte SourceNodeAddress { get; set; } = 25;
///
- /// 获取或设置 PLC 寄存器字节序,默认使用 BADC 以匹配现场 D 区 Int16 高低字节顺序。
+ /// 获取或设置 PLC 寄存器字节序,默认使用 ABCD 以避免 UInt16 结果代码发生高低字节交换。
///
- public string? EndianFormat { get; set; } = "BADC";
+ public string? EndianFormat { get; set; } = "ABCD";
///
/// 获取或设置轮询周期,单位为毫秒。
diff --git a/src/AxiOmron.PcbCheck/Services/Implementations/CsvBoardRecordRepository.cs b/src/AxiOmron.PcbCheck/Services/Implementations/CsvBoardRecordRepository.cs
index ea680eb..1f786de 100644
--- a/src/AxiOmron.PcbCheck/Services/Implementations/CsvBoardRecordRepository.cs
+++ b/src/AxiOmron.PcbCheck/Services/Implementations/CsvBoardRecordRepository.cs
@@ -247,10 +247,10 @@ public sealed class CsvBoardRecordRepository : IBoardRecordRepository
{
StatisticDate = date,
TotalCount = records.Count,
- OkCount = records.Count(record => record.ResultCode == (short)WorkflowResultCode.Passed),
- NgCount = records.Count(record => record.ResultCode != (short)WorkflowResultCode.Passed
- && record.ResultCode != (short)WorkflowResultCode.Processing
- && record.ResultCode != (short)WorkflowResultCode.None),
+ OkCount = records.Count(record => record.ResultCode == (ushort)WorkflowResultCode.Passed),
+ NgCount = records.Count(record => record.ResultCode != (ushort)WorkflowResultCode.Passed
+ && record.ResultCode != (ushort)WorkflowResultCode.Processing
+ && record.ResultCode != (ushort)WorkflowResultCode.None),
LastUpdatedAt = _timeProvider.GetLocalNow()
};
@@ -400,7 +400,7 @@ public sealed class CsvBoardRecordRepository : IBoardRecordRepository
|| !DateTimeOffset.TryParse(fields[1], out DateTimeOffset completedAt)
|| !int.TryParse(fields[3], out int scanTryCount)
|| !int.TryParse(fields[4], out int sftpTryCount)
- || !short.TryParse(fields[5], out short resultCode)
+ || !ushort.TryParse(fields[5], out ushort resultCode)
|| !bool.TryParse(fields[7], out bool releaseSent)
|| !bool.TryParse(fields[8], out bool alarmRaised))
{
diff --git a/src/AxiOmron.PcbCheck/Services/Implementations/OmronFinsPlcService.cs b/src/AxiOmron.PcbCheck/Services/Implementations/OmronFinsPlcService.cs
index 4e50ea2..e5630fa 100644
--- a/src/AxiOmron.PcbCheck/Services/Implementations/OmronFinsPlcService.cs
+++ b/src/AxiOmron.PcbCheck/Services/Implementations/OmronFinsPlcService.cs
@@ -89,7 +89,7 @@ public sealed class OmronFinsPlcService : IPlcService, IDisposable
{
PcBusy = ReadBoolean(ToDataMemoryAddress(_options.Outputs.PcBusy)),
ReleasePermit = ReadBoolean(ToDataMemoryAddress(_options.Outputs.ReleasePermit)),
- ResultCode = ReadInt16(ToDataMemoryAddress(_options.Registers.ResultCode))
+ ResultCode = ReadUInt16(ToDataMemoryAddress(_options.Registers.ResultCode))
},
CapturedAt = capturedAt
};
@@ -276,15 +276,15 @@ public sealed class OmronFinsPlcService : IPlcService, IDisposable
}
///
- /// 读取单个 D 区有符号 16 位整数。
+ /// 读取单个 D 区无符号 16 位整数。
///
/// FINS 地址。
/// 读取到的寄存器值。
- private short ReadInt16(string address)
+ private ushort ReadUInt16(string address)
{
var client = _client ?? throw new InvalidOperationException("PLC 客户端尚未初始化。");
- var result = client.ReadInt16(address);
- EnsureSuccess(result.IsSucceed, result.Err, $"读取 FINS Int16 失败,地址={address}");
+ var result = client.ReadUInt16(address);
+ EnsureSuccess(result.IsSucceed, result.Err, $"读取 FINS UInt16 失败,地址={address}");
return result.Value;
}
@@ -295,10 +295,10 @@ public sealed class OmronFinsPlcService : IPlcService, IDisposable
private void WriteChangedState(PlcProcessState state)
{
var previous = _lastWrittenState;
- short? previousResultCode = previous is null ? null : previous.ResultCode;
+ ushort? previousResultCode = previous is null ? null : previous.ResultCode;
WriteBooleanIfChanged(previous?.PcBusy, state.PcBusy, ToDataMemoryAddress(_options.Outputs.PcBusy));
WriteBooleanIfChanged(previous?.ReleasePermit, state.ReleasePermit, ToDataMemoryAddress(_options.Outputs.ReleasePermit));
- WriteInt16IfChanged(previousResultCode, state.ResultCode, ToDataMemoryAddress(_options.Registers.ResultCode));
+ WriteUInt16IfChanged(previousResultCode, state.ResultCode, ToDataMemoryAddress(_options.Registers.ResultCode));
}
///
@@ -320,12 +320,12 @@ public sealed class OmronFinsPlcService : IPlcService, IDisposable
}
///
- /// 仅当值发生变化时写入单个 D 区有符号 16 位整数。
+ /// 仅当值发生变化时写入单个 D 区无符号 16 位整数。
///
/// 上一值。
/// 当前值。
/// FINS 地址。
- private void WriteInt16IfChanged(short? previous, short current, string address)
+ private void WriteUInt16IfChanged(ushort? previous, ushort current, string address)
{
if (previous.HasValue && previous.Value == current)
{
@@ -334,7 +334,7 @@ public sealed class OmronFinsPlcService : IPlcService, IDisposable
var client = _client ?? throw new InvalidOperationException("PLC 客户端尚未初始化。");
var result = client.Write(address, current);
- EnsureSuccess(result.IsSucceed, result.Err, $"写入 FINS Int16 失败,地址={address},值={current}");
+ EnsureSuccess(result.IsSucceed, result.Err, $"写入 FINS UInt16 失败,地址={address},值={current}");
}
///
diff --git a/src/AxiOmron.PcbCheck/Services/Implementations/WorkflowHostedService.cs b/src/AxiOmron.PcbCheck/Services/Implementations/WorkflowHostedService.cs
index 25c8d8f..f34f8a7 100644
--- a/src/AxiOmron.PcbCheck/Services/Implementations/WorkflowHostedService.cs
+++ b/src/AxiOmron.PcbCheck/Services/Implementations/WorkflowHostedService.cs
@@ -848,7 +848,7 @@ public sealed class WorkflowHostedService : BackgroundService, IWorkflowControlS
Barcode = _currentBarcode,
ScanTryCount = _scanTryCount,
SftpTryCount = _sftpTryCount,
- ResultCode = (short)_resultCode,
+ ResultCode = (ushort)_resultCode,
ResultDescription = GetResultDescription(_resultCode),
ReleaseSent = _releaseSent,
AlarmRaised = false,
@@ -1082,7 +1082,7 @@ public sealed class WorkflowHostedService : BackgroundService, IWorkflowControlS
lock (_stateSyncRoot)
{
updateAction(_plcState);
- _plcState.ResultCode = (short)_resultCode;
+ _plcState.ResultCode = (ushort)_resultCode;
snapshot = _plcState.Clone();
}
@@ -1103,7 +1103,7 @@ public sealed class WorkflowHostedService : BackgroundService, IWorkflowControlS
{
DateTimeOffset? startedAt;
string barcode;
- short resultCode;
+ ushort resultCode;
bool isBusy;
string faultMessage;
@@ -1111,7 +1111,7 @@ public sealed class WorkflowHostedService : BackgroundService, IWorkflowControlS
{
startedAt = _currentBoardStartedAt;
barcode = _currentBarcode;
- resultCode = (short)_resultCode;
+ resultCode = (ushort)_resultCode;
isBusy = _plcState.PcBusy;
faultMessage = _faultLatched ? description : string.Empty;
}
diff --git a/src/AxiOmron.PcbCheck/ViewModels/MainWindowViewModel.cs b/src/AxiOmron.PcbCheck/ViewModels/MainWindowViewModel.cs
index 1102cf1..bdb5393 100644
--- a/src/AxiOmron.PcbCheck/ViewModels/MainWindowViewModel.cs
+++ b/src/AxiOmron.PcbCheck/ViewModels/MainWindowViewModel.cs
@@ -150,7 +150,7 @@ public partial class MainWindowViewModel : ObservableObject
/// 获取或设置结果代码。
///
[ObservableProperty]
- private short _resultCode;
+ private ushort _resultCode;
///
/// 获取或设置最近触发时间。
@@ -557,6 +557,7 @@ public partial class MainWindowViewModel : ObservableObject
await AppendLogOnUiAsync(entry).ConfigureAwait(false);
}
+ ///
/// 处理管理员解锁倒计时,超时后自动恢复锁定。
///
/// 事件源。
diff --git a/src/AxiOmron.PcbCheck/appConfig.json b/src/AxiOmron.PcbCheck/appConfig.json
index 6eab135..65c240b 100644
--- a/src/AxiOmron.PcbCheck/appConfig.json
+++ b/src/AxiOmron.PcbCheck/appConfig.json
@@ -1,92 +1,92 @@
-{
- "Plc": {
- "Host": "127.0.0.1",
- "Port": 9600,
- "UnitAddress": 0,
- "SourceNodeAddress": 25,
- "EndianFormat": "BADC",
- "PollIntervalMs": 200,
- "ConnectTimeoutMs": 3000,
- "ReleasePulseMs": 500,
- "ReleaseAckTimeoutMs": 2000,
- "Inputs": {
- "PcbArrived": 101,
- "PlcReset": 102,
- "PlcAckRelease": 103
- },
- "Outputs": {
- "PcBusy": 51,
- "ReleasePermit": 52
- },
- "Registers": {
- "ResultCode": 401
- }
- },
- "Scanner": {
- "Scanner1": {
- "Name": "扫码枪1",
- "Host": "127.0.0.1",
- "Port": 2001
- },
- "Scanner2": {
- "Name": "扫码枪2",
- "Host": "127.0.0.1",
- "Port": 2001
- },
- "ConnectTimeoutMs": 3000,
- "ReadTimeoutMs": 3000,
- "TriggerCommand": "T",
- "ResponseTerminator": "\\r",
- "TriggerInParallel": true
- },
- "FileCheck": {
- "Provider": "Local",
- "FileNamePattern": "${barcode}.txt",
- "RetryIntervalSeconds": 2,
- "MaxRetryCount": 3,
- "Local": {
- "RootPath": "D:\\PcbCheck\\Files"
- }
- },
- "Sftp": {
- "Host": "127.0.0.1",
- "Port": 22,
- "Username": "uaesadmin",
- "Password": "uaes,123",
- "PrivateKeyPath": "",
- "PrivateKeyPassphrase": "",
- "RootPath": "/home/uaesadmin/",
- "FileNamePattern": "${barcode}.txt",
- "RetryIntervalSeconds": 2,
- "MaxRetryCount": 3,
- "ConnectTimeoutMs": 3000
- },
- "Andon": {
- "Enable": false,
- "Url": "https://shp.prod.aliyun.mit.uaes.com/api/mit/MAE/Station/Status/alarm",
- "Method": "POST",
- "TimeoutMs": 3000,
- "AndonTheme": "SS7_Auto_Andon",
- "Eid": "PR1965269806334783488",
- "FromSign": "IOT",
- "ServiceId": "4dccd822-86b2-47dd-89bd-ca472ba0d14d",
- "EnableScanFailAlarm": true,
- "EnableFileNotFoundAlarm": false,
- "Headers": {
- "Accept": "application/json"
- }
- },
- "Workflow": {
- "RequireManualResetAfterFault": true,
- "MaxUiLogEntries": 200,
- "MaxBoardRecords": 100
- },
- "RecordPersistence": {
- "DirectoryPath": "Data\\Records",
- "DayChangeCheckIntervalSeconds": 30
- },
- "Security": {
- "AdminPassword": "AxiOmron@123",
- "AdminSessionTimeoutMinutes": 15
- }
+{
+ "Plc": {
+ "Host": "192.168.2.100",
+ "Port": 9600,
+ "UnitAddress": 0,
+ "SourceNodeAddress": 0,
+ "EndianFormat": "ABCD",
+ "PollIntervalMs": 200,
+ "ConnectTimeoutMs": 3000,
+ "ReleasePulseMs": 500,
+ "ReleaseAckTimeoutMs": 2000,
+ "Inputs": {
+ "PcbArrived": 101,
+ "PlcReset": 102,
+ "PlcAckRelease": 103
+ },
+ "Outputs": {
+ "PcBusy": 51,
+ "ReleasePermit": 52
+ },
+ "Registers": {
+ "ResultCode": 401
+ }
+ },
+ "Scanner": {
+ "Scanner1": {
+ "Name": "\u626B\u7801\u67AA1",
+ "Host": "192.168.2.13",
+ "Port": 2001
+ },
+ "Scanner2": {
+ "Name": "\u626B\u7801\u67AA2",
+ "Host": "192.168.2.14",
+ "Port": 2001
+ },
+ "ConnectTimeoutMs": 3000,
+ "TriggerCommand": "T",
+ "ResponseTerminator": "",
+ "TriggerInParallel": true,
+ "ReadTimeoutMs": 5000
+ },
+ "FileCheck": {
+ "Provider": "Local",
+ "FileNamePattern": "${barcode}.txt",
+ "RetryIntervalSeconds": 2,
+ "MaxRetryCount": 3,
+ "Local": {
+ "RootPath": "D:\\test"
+ }
+ },
+ "Sftp": {
+ "Host": "127.0.0.1",
+ "Port": 22,
+ "Username": "uaesadmin",
+ "Password": "uaes,123",
+ "PrivateKeyPath": "",
+ "PrivateKeyPassphrase": "",
+ "RootPath": "/home/uaesadmin/",
+ "FileNamePattern": "${barcode}.txt",
+ "RetryIntervalSeconds": 2,
+ "MaxRetryCount": 3,
+ "ConnectTimeoutMs": 3000
+ },
+ "Andon": {
+ "Enable": false,
+ "Url": "https://shp.prod.aliyun.mit.uaes.com/api/mit/MAE/Station/Status/alarm",
+ "Method": "POST",
+ "TimeoutMs": 3000,
+ "AndonTheme": "SS7_Auto_Andon",
+ "Eid": "PR1965269806334783488",
+ "FromSign": "IOT",
+ "ServiceId": "4dccd822-86b2-47dd-89bd-ca472ba0d14d",
+ "EnableScanFailAlarm": false,
+ "EnableFileNotFoundAlarm": false,
+ "Headers": {
+ "Accept": "application/json"
+ }
+ },
+ "Workflow": {
+ "RequireManualResetAfterFault": true,
+ "MaxUiLogEntries": 200,
+ "MaxBoardRecords": 100
+ },
+ "RecordPersistence": {
+ "DirectoryPath": "Data\\Records",
+ "DayChangeCheckIntervalSeconds": 30
+ },
+ "Security": {
+ "AdminPassword": "AxiOmron@123",
+ "AdminSessionTimeoutMinutes": 15
+ }
}
\ No newline at end of file
diff --git a/tests/AxiOmron.PcbCheck.Tests/CsvBoardRecordRepositoryTests.cs b/tests/AxiOmron.PcbCheck.Tests/CsvBoardRecordRepositoryTests.cs
index c109899..94a1a49 100644
--- a/tests/AxiOmron.PcbCheck.Tests/CsvBoardRecordRepositoryTests.cs
+++ b/tests/AxiOmron.PcbCheck.Tests/CsvBoardRecordRepositoryTests.cs
@@ -37,10 +37,10 @@ public sealed class CsvBoardRecordRepositoryTests : IDisposable
timeProvider);
await repository.AppendAsync(
- CreateRecord("PCB-001", new DateTimeOffset(2026, 4, 19, 8, 0, 0, TimeSpan.FromHours(8)), (short)WorkflowResultCode.Passed),
+ CreateRecord("PCB-001", new DateTimeOffset(2026, 4, 19, 8, 0, 0, TimeSpan.FromHours(8)), (ushort)WorkflowResultCode.Passed),
CancellationToken.None);
await repository.AppendAsync(
- CreateRecord("PCB-002", new DateTimeOffset(2026, 4, 19, 8, 5, 0, TimeSpan.FromHours(8)), (short)WorkflowResultCode.NgReleased),
+ CreateRecord("PCB-002", new DateTimeOffset(2026, 4, 19, 8, 5, 0, TimeSpan.FromHours(8)), (ushort)WorkflowResultCode.NgReleased),
CancellationToken.None);
BoardRecordLoadResult result = await repository.LoadCurrentDayAsync(CancellationToken.None);
@@ -100,7 +100,7 @@ public sealed class CsvBoardRecordRepositoryTests : IDisposable
timeProvider);
await repository.AppendAsync(
- CreateRecord("PCB-OLD", new DateTimeOffset(2026, 4, 19, 23, 59, 55, TimeSpan.FromHours(8)), (short)WorkflowResultCode.Passed),
+ CreateRecord("PCB-OLD", new DateTimeOffset(2026, 4, 19, 23, 59, 55, TimeSpan.FromHours(8)), (ushort)WorkflowResultCode.Passed),
CancellationToken.None);
timeProvider.SetLocalNow(new DateTimeOffset(2026, 4, 20, 0, 0, 10, TimeSpan.FromHours(8)));
@@ -131,7 +131,7 @@ public sealed class CsvBoardRecordRepositoryTests : IDisposable
/// 完成时间。
/// 结果代码。
/// 测试记录。
- private static BoardProcessRecord CreateRecord(string barcode, DateTimeOffset completedAt, short resultCode)
+ private static BoardProcessRecord CreateRecord(string barcode, DateTimeOffset completedAt, ushort resultCode)
{
return new BoardProcessRecord
{
@@ -141,7 +141,7 @@ public sealed class CsvBoardRecordRepositoryTests : IDisposable
ScanTryCount = 1,
SftpTryCount = 1,
ResultCode = resultCode,
- ResultDescription = resultCode == (short)WorkflowResultCode.Passed ? "OK" : "NG",
+ ResultDescription = resultCode == (ushort)WorkflowResultCode.Passed ? "OK" : "NG",
ReleaseSent = true,
AlarmRaised = false,
ExceptionSummary = string.Empty
diff --git a/tests/AxiOmron.PcbCheck.Tests/MainWindowViewModelTests.cs b/tests/AxiOmron.PcbCheck.Tests/MainWindowViewModelTests.cs
index 85eecdf..c08f786 100644
--- a/tests/AxiOmron.PcbCheck.Tests/MainWindowViewModelTests.cs
+++ b/tests/AxiOmron.PcbCheck.Tests/MainWindowViewModelTests.cs
@@ -50,7 +50,7 @@ public sealed class MainWindowViewModelTests
Barcode = $"PCB-{index:D3}",
ScanTryCount = 1,
SftpTryCount = 1,
- ResultCode = index % 2 == 0 ? (short)WorkflowResultCode.Passed : (short)WorkflowResultCode.NgReleased,
+ ResultCode = index % 2 == 0 ? (ushort)WorkflowResultCode.Passed : (ushort)WorkflowResultCode.NgReleased,
ResultDescription = index % 2 == 0 ? "OK" : "NG",
ReleaseSent = true,
AlarmRaised = false
diff --git a/tests/AxiOmron.PcbCheck.Tests/OmronFinsPlcServiceTests.cs b/tests/AxiOmron.PcbCheck.Tests/OmronFinsPlcServiceTests.cs
index 5016fc4..79eee1a 100644
--- a/tests/AxiOmron.PcbCheck.Tests/OmronFinsPlcServiceTests.cs
+++ b/tests/AxiOmron.PcbCheck.Tests/OmronFinsPlcServiceTests.cs
@@ -11,16 +11,16 @@ namespace AxiOmron.PcbCheck.Tests;
public sealed class OmronFinsPlcServiceTests
{
///
- /// 默认字节序应使用 BADC,以匹配现场 D 区 Int16 的高低字节顺序。
+ /// 默认字节序应使用 ABCD,避免 UInt16 结果代码发生高低字节交换。
///
[Fact]
- public void ResolveEndianFormat_ShouldUseBadc_WhenConfigurationIsDefault()
+ public void ResolveEndianFormat_ShouldUseAbcd_WhenConfigurationIsDefault()
{
var options = new PlcOptions();
EndianFormat result = OmronFinsPlcService.ResolveEndianFormat(options);
- Assert.Equal(EndianFormat.BADC, result);
+ Assert.Equal(EndianFormat.ABCD, result);
}
///
diff --git a/tests/AxiOmron.PcbCheck.Tests/ResultCodeTypeTests.cs b/tests/AxiOmron.PcbCheck.Tests/ResultCodeTypeTests.cs
index ca67826..3cc880d 100644
--- a/tests/AxiOmron.PcbCheck.Tests/ResultCodeTypeTests.cs
+++ b/tests/AxiOmron.PcbCheck.Tests/ResultCodeTypeTests.cs
@@ -5,29 +5,29 @@ using Xunit;
namespace AxiOmron.PcbCheck.Tests;
///
-/// 验证结果代码在模型与界面层统一使用 16 位有符号整数。
+/// 验证结果代码在模型与界面层统一使用 16 位无符号整数。
///
public sealed class ResultCodeTypeTests
{
///
- /// 结果代码枚举应以 Int16 作为底层类型,匹配 PLC 的 ResultCode 定义。
+ /// 结果代码枚举应以 UInt16 作为底层类型,匹配 PLC 的 ResultCode 定义。
///
[Fact]
- public void WorkflowResultCode_ShouldUseInt16UnderlyingType()
+ public void WorkflowResultCode_ShouldUseUInt16UnderlyingType()
{
- Assert.Equal(typeof(short), Enum.GetUnderlyingType(typeof(WorkflowResultCode)));
+ Assert.Equal(typeof(ushort), Enum.GetUnderlyingType(typeof(WorkflowResultCode)));
}
///
- /// 结果代码属性应统一使用 Int16,避免经过界面或快照时被误建模为 UInt16 或 Int32。
+ /// 结果代码属性应统一使用 UInt16,避免经过界面或快照时被误建模为 Int16 或 Int32。
///
[Theory]
[InlineData(typeof(RuntimeSnapshot))]
[InlineData(typeof(PlcProcessState))]
[InlineData(typeof(BoardProcessRecord))]
[InlineData(typeof(MainWindowViewModel))]
- public void ResultCodeProperties_ShouldUseInt16(Type ownerType)
+ public void ResultCodeProperties_ShouldUseUInt16(Type ownerType)
{
- Assert.Equal(typeof(short), ownerType.GetProperty("ResultCode")?.PropertyType);
+ Assert.Equal(typeof(ushort), ownerType.GetProperty("ResultCode")?.PropertyType);
}
}
diff --git a/tests/AxiOmron.PcbCheck.Tests/WorkflowHostedServiceTests.cs b/tests/AxiOmron.PcbCheck.Tests/WorkflowHostedServiceTests.cs
index e88a761..05b7c8f 100644
--- a/tests/AxiOmron.PcbCheck.Tests/WorkflowHostedServiceTests.cs
+++ b/tests/AxiOmron.PcbCheck.Tests/WorkflowHostedServiceTests.cs
@@ -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 == (short)WorkflowResultCode.Passed);
+ Assert.Contains(plcService.WrittenStates, state => state.ResultCode == (ushort)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 == ((short)WorkflowResultCode.Passed).ToString());
+ Assert.Contains(snapshot.PlcMonitorItems, item => item.Name == "ResultCode" && item.CurrentValue == ((ushort)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 == (short)WorkflowResultCode.Passed);
+ Assert.Contains(plcService.WrittenStates, state => state.ResultCode == (ushort)WorkflowResultCode.Passed);
}
///
@@ -304,7 +304,7 @@ public sealed class WorkflowHostedServiceTests
Barcode = "PCB-RESTORED",
ScanTryCount = 1,
SftpTryCount = 1,
- ResultCode = (short)WorkflowResultCode.Passed,
+ ResultCode = (ushort)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((short)WorkflowResultCode.Passed, snapshot.ResultCode);
+ Assert.Equal((ushort)WorkflowResultCode.Passed, snapshot.ResultCode);
}
private sealed class FakePlcService : IPlcService