using WIDESEAWCS_S7Simulator.Application.Protocol; using WIDESEAWCS_S7Simulator.Core.Entities; using WIDESEAWCS_S7Simulator.Core.Memory; using WIDESEAWCS_S7Simulator.Core.Protocol; namespace WIDESEAWCS_S7Simulator.UnitTests.Protocol; public class MirrorAckProtocolHandlerTests { [Fact] public void Process_WhenAckIsOne_MirrorsConfiguredFieldsAndResetsStb() { var memory = BuildMemory(); var template = BuildTemplate(); var state = new ProtocolRuntimeState(); var rule = BuildRule(); var handler = new MirrorAckProtocolHandler(); memory.Write("DB1.DBB0", 1); // WCS 确认位 memory.Write("DB1.DBD2", 123456); // WCS 任务号 memory.Write("DB1.DBW6", 88); // WCS 目标位 memory.Write("DB1.DBB10", 1); // PLC 状态位 var changed = handler.Process(memory, template, state, rule); Assert.True(changed); Assert.Equal(123456, memory.Read("DB1.DBD20")); Assert.Equal((short)88, memory.Read("DB1.DBW24")); Assert.Equal((byte)0, memory.Read("DB1.DBB10")); } [Fact] public void Process_WhenAckIsTwo_ClearsConfiguredFields() { var memory = BuildMemory(); var template = BuildTemplate(); var state = new ProtocolRuntimeState(); var rule = BuildRule(); var handler = new MirrorAckProtocolHandler(); memory.Write("DB1.DBB0", 2); // WCS 确认位 memory.Write("DB1.DBD20", 1); // PLC 任务号 memory.Write("DB1.DBW24", 2); // PLC 目标位 memory.Write("DB1.DBB30", 3); // 托盘号 memory.Write("DB1.DBB10", 1); // PLC 状态位 var changed = handler.Process(memory, template, state, rule); Assert.True(changed); Assert.Equal(0, memory.Read("DB1.DBD20")); Assert.Equal((short)0, memory.Read("DB1.DBW24")); Assert.Equal((byte)0, memory.Read("DB1.DBB30")); Assert.Equal((byte)0, memory.Read("DB1.DBB10")); } [Fact] public void Process_不同段状态键_相同Ack也可分别处理() { var memory = BuildMemory(); var template = BuildTemplate(); var state = new ProtocolRuntimeState(); var rule = BuildRule(); var handler = new MirrorAckProtocolHandler(); memory.Write("DB1.DBB0", 1); // WCS 确认位 memory.Write("DB1.DBD2", 1001); // WCS 任务号 memory.Write("DB1.DBW6", 11); // WCS 目标位 memory.Write("DB1.DBB10", 1); // PLC 状态位 var changedSeg1 = handler.Process(memory, template, state, rule, "WcsLineProtocol:SEG1"); // 保持 ACK 不变,改写目标值,模拟另一段线体处理。 memory.Write("DB1.DBD2", 2002); memory.Write("DB1.DBW6", 22); var changedSeg2 = handler.Process(memory, template, state, rule, "WcsLineProtocol:SEG2"); Assert.True(changedSeg1); Assert.True(changedSeg2); Assert.Equal(2002, memory.Read("DB1.DBD20")); Assert.Equal((short)22, memory.Read("DB1.DBW24")); } private static MemoryStore BuildMemory() { return new MemoryStore(new MemoryRegionConfig { DBBlockCount = 2, DBBlockSize = 256 }); } private static ProtocolTemplate BuildTemplate() { return new ProtocolTemplate { Id = "wcs-line-v1", Name = "WCS_LINE_V1", Fields = new List { new() { FieldKey = "WCS_ACK", DbNumber = 1, Offset = 0, DataType = ProtocolDataType.Byte }, new() { FieldKey = "WCS_TASK_ID", DbNumber = 1, Offset = 2, DataType = ProtocolDataType.DInt }, new() { FieldKey = "WCS_TARGET_ID", DbNumber = 1, Offset = 6, DataType = ProtocolDataType.Int }, new() { FieldKey = "PLC_STB", DbNumber = 1, Offset = 10, DataType = ProtocolDataType.Byte }, new() { FieldKey = "PLC_TASK_ID", DbNumber = 1, Offset = 20, DataType = ProtocolDataType.DInt }, new() { FieldKey = "PLC_TARGET_ID", DbNumber = 1, Offset = 24, DataType = ProtocolDataType.Int }, new() { FieldKey = "PALLET_CODE", DbNumber = 1, Offset = 30, DataType = ProtocolDataType.Byte } } }; } private static MirrorAckRuleOptions BuildRule() { return new MirrorAckRuleOptions { RuleId = "line-default", WcsAckFieldKey = "WCS_ACK", PlcStbFieldKey = "PLC_STB", WcsTaskIdFieldKey = "WCS_TASK_ID", PlcTaskIdFieldKey = "PLC_TASK_ID", WcsTargetIdFieldKey = "WCS_TARGET_ID", PlcTargetIdFieldKey = "PLC_TARGET_ID", ClearFieldKeysOnAck0 = new List { "PLC_TASK_ID", "PLC_TARGET_ID", "PALLET_CODE" }, ClearFieldKeysOnAck2 = new List { "PLC_TASK_ID", "PLC_TARGET_ID", "PALLET_CODE" } }; } }