diff --git a/src/FieldElementSubsystems.Test/Connection/Baseline4R1/PointToInterlockingConnectionTest.cs b/src/FieldElementSubsystems.Test/Connection/Baseline4R1/PointToInterlockingConnectionTest.cs index f4a0c1f..b159c89 100644 --- a/src/FieldElementSubsystems.Test/Connection/Baseline4R1/PointToInterlockingConnectionTest.cs +++ b/src/FieldElementSubsystems.Test/Connection/Baseline4R1/PointToInterlockingConnectionTest.cs @@ -32,7 +32,7 @@ private static Mock CreateDefaultMockConnection() {"PointSettings:AllPointMachinesCrucial", "false" }, {"PointSettings:ObserveAbilityToMove", "true" }, {"PointSettings:PDIVersion", "1" }, - {"PointSettings:PDIChecksum", "0x0000" } + {"PointSettings:PDIChecksum", "0x00" } }; private readonly IConfiguration _configuration = new ConfigurationBuilder() @@ -44,13 +44,13 @@ public void Test_Connect() { // Arrange var mockConnection = new Mock(); - var connection = new PointToInterlockingConnection(Mock.Of>(), _configuration, CancellationToken.None); + var builder = new PointToInterlockingConnectionBuilder(Mock.Of>(), _configuration, CancellationToken.None); // Act - connection.Connect(mockConnection.Object); + var connection = builder.Connect(mockConnection.Object); // Assert - Assert.Equal(connection.CurrentConnection, mockConnection.Object); + Assert.Equal(((PointToInterlockingConnection)connection).CurrentConnection, mockConnection.Object); } [Fact] @@ -62,16 +62,16 @@ public async Task Test_Initialization() mockConnection.Setup(x => x.SendAsync(Capture.In(receivedMessages))) .Returns(Task.FromResult(0)); - var connection = new PointToInterlockingConnection(Mock.Of>(), _configuration, CancellationToken.None); + var builder = new PointToInterlockingConnectionBuilder(Mock.Of>(), _configuration, CancellationToken.None); // Act - connection.Connect(mockConnection.Object); + var connection = builder.Connect(mockConnection.Object); await connection.InitializeConnection(new GenericPointState(LastCommandedPointPosition: null, PointPosition: GenericPointPosition.Left, DegradedPointPosition: GenericDegradedPointPosition.NotDegraded, AbilityToMove: GenericAbilityToMove.AbleToMove), true, false, CancellationToken.None); // Assert mockConnection.Verify(v => v.ReceiveAsync(It.IsAny()), Times.Exactly(2)); mockConnection.Verify(v => v.SendAsync(It.IsAny()), Times.Exactly(5)); - Assert.Equal(new PointPdiVersionCheckMessage("99W1________________", "INTERLOCKING________", PointPdiVersionCheckMessageResultPdiVersionCheck.PDIVersionsFromReceiverAndSenderDoMatch, 1, 2, new byte[] { 0x00, 0x00 }).ToByteArray(), receivedMessages[0]); + Assert.Equal(new PointPdiVersionCheckMessage("99W1________________", "INTERLOCKING________", PointPdiVersionCheckMessageResultPdiVersionCheck.PDIVersionsFromReceiverAndSenderDoMatch, 1,1, new byte[] { 0x00 }).ToByteArray(), receivedMessages[0]); Assert.Equal(new PointStartInitialisationMessage("99W1________________", "INTERLOCKING________").ToByteArray(), receivedMessages[1]); Assert.Equal(new PointPointPositionMessage("99W1________________", "INTERLOCKING________", PointPointPositionMessageReportedPointPosition.PointIsInALeftHandPositionDefinedEndPosition, PointPointPositionMessageReportedDegradedPointPosition.PointIsNotInADegradedPosition).ToByteArray(), receivedMessages[2]); Assert.Equal(new PointAbilityToMovePointMessage("99W1________________", "INTERLOCKING________", PointAbilityToMovePointMessageReportedAbilityToMovePointStatus.PointIsAbleToMove).ToByteArray(), receivedMessages[3]); @@ -89,16 +89,16 @@ public async Task Test_Initialization_Timeout(){ mockConnection.Setup(x => x.SendAsync(Capture.In(receivedMessages))) .Returns(Task.FromResult(0)); - var connection = new PointToInterlockingConnection(Mock.Of>(), _configuration, CancellationToken.None); + var builder = new PointToInterlockingConnectionBuilder(Mock.Of>(), _configuration, CancellationToken.None); // Act - connection.Connect(mockConnection.Object); + var connection = builder.Connect(mockConnection.Object); await connection.InitializeConnection(new GenericPointState(LastCommandedPointPosition: null, PointPosition: GenericPointPosition.Left, DegradedPointPosition: GenericDegradedPointPosition.NotDegraded, AbilityToMove: GenericAbilityToMove.AbleToMove), true, true, CancellationToken.None); // Assert + // Should not send/receive any more messages after version check as timeout is simulated mockConnection.Verify(v => v.ReceiveAsync(It.IsAny()), Times.Exactly(1)); mockConnection.Verify(v => v.SendAsync(It.IsAny()), Times.Exactly(1)); - Assert.Equal(new PointPdiVersionCheckMessage("99W1________________", "INTERLOCKING________", PointPdiVersionCheckMessageResultPdiVersionCheck.PDIVersionsFromReceiverAndSenderDoMatch, 1, 2, new byte[] { 0x00, 0x00 }).ToByteArray(), receivedMessages[0]); } /// @@ -115,10 +115,10 @@ public async Task Test_Initialization_Version_Mismatch(){ mockConnection.Setup(x => x.SendAsync(Capture.In(receivedMessages))) .Returns(Task.FromResult(0)); - var connection = new PointToInterlockingConnection(Mock.Of>(), _configuration, CancellationToken.None); + var builder = new PointToInterlockingConnectionBuilder(Mock.Of>(), _configuration, CancellationToken.None); // Act - connection.Connect(mockConnection.Object); + var connection = builder.Connect(mockConnection.Object); await connection.InitializeConnection(new GenericPointState(LastCommandedPointPosition: null, PointPosition: GenericPointPosition.Left, DegradedPointPosition: GenericDegradedPointPosition.NotDegraded, AbilityToMove: GenericAbilityToMove.AbleToMove), true, true, CancellationToken.None); // Assert @@ -136,10 +136,10 @@ public async Task Test_Send_Position() mockConnection.Setup(x => x.SendAsync(Capture.In(args))) .Returns(Task.FromResult(0)); - var connection = new PointToInterlockingConnection(Mock.Of>(), _configuration, CancellationToken.None); + var builder = new PointToInterlockingConnectionBuilder(Mock.Of>(), _configuration, CancellationToken.None); // Act - connection.Connect(mockConnection.Object); + var connection = builder.Connect(mockConnection.Object); await connection.InitializeConnection(new GenericPointState(LastCommandedPointPosition: null, PointPosition: GenericPointPosition.Left, DegradedPointPosition: GenericDegradedPointPosition.NotDegraded, AbilityToMove: GenericAbilityToMove.AbleToMove), true, false, CancellationToken.None); foreach (var position in new List() { GenericPointPosition.Left, GenericPointPosition.Right, GenericPointPosition.UnintendedPosition, GenericPointPosition.NoEndPosition }) { @@ -165,10 +165,10 @@ public async Task Test_Receive_Position() .ReturnsAsync(new PointMovePointCommand("99W1", "100", PointMovePointCommandCommandedPointPosition.SubsystemElectronicInterlockingRequestsALeftHandPointMoving).ToByteArray()) .ReturnsAsync(new PointMovePointCommand("99W1", "100", PointMovePointCommandCommandedPointPosition.SubsystemElectronicInterlockingRequestsARightHandPointMoving).ToByteArray()); - var connection = new PointToInterlockingConnection(Mock.Of>(), _configuration, CancellationToken.None); + var builder = new PointToInterlockingConnectionBuilder(Mock.Of>(), _configuration, CancellationToken.None); // Act - connection.Connect(mockConnection.Object); + var connection = builder.Connect(mockConnection.Object); await connection.InitializeConnection(new GenericPointState(LastCommandedPointPosition: null, PointPosition: GenericPointPosition.Left, DegradedPointPosition: GenericDegradedPointPosition.NotDegraded, AbilityToMove: GenericAbilityToMove.AbleToMove), true, false, CancellationToken.None); var position1 = await connection.ReceiveMovePointCommand(CancellationToken.None); var position2 = await connection.ReceiveMovePointCommand(CancellationToken.None); @@ -188,10 +188,10 @@ public async Task Test_TimeoutMessage() mockConnection.Setup(x => x.SendAsync(Capture.In(args))) .Returns(Task.FromResult(0)); - var connection = new PointToInterlockingConnection(Mock.Of>(), _configuration, CancellationToken.None); + var builder = new PointToInterlockingConnectionBuilder(Mock.Of>(), _configuration, CancellationToken.None); // Act - connection.Connect(mockConnection.Object); + var connection = builder.Connect(mockConnection.Object); await connection.InitializeConnection(new GenericPointState(LastCommandedPointPosition: null, PointPosition: GenericPointPosition.Left, DegradedPointPosition: GenericDegradedPointPosition.NotDegraded, AbilityToMove: GenericAbilityToMove.AbleToMove), true, false, CancellationToken.None); await connection.SendTimeoutMessage(); diff --git a/src/FieldElementSubsystems.Test/Connection/Baseline4R2/PointToInterlockingConnectionTest.cs b/src/FieldElementSubsystems.Test/Connection/Baseline4R2/PointToInterlockingConnectionTest.cs index 3e78eb1..855091e 100644 --- a/src/FieldElementSubsystems.Test/Connection/Baseline4R2/PointToInterlockingConnectionTest.cs +++ b/src/FieldElementSubsystems.Test/Connection/Baseline4R2/PointToInterlockingConnectionTest.cs @@ -23,7 +23,7 @@ public class PointToInterlockingConnectionTest {"PointSettings:AllPointMachinesCrucial", "false" }, {"PointSettings:ObserveAbilityToMove", "true" }, {"PointSettings:PDIVersion", "1" }, - {"PointSettings:PDIChecksum", "0x0000" } + {"PointSettings:PDIChecksum", "0x00" } }; private readonly IConfiguration _configuration = new ConfigurationBuilder() @@ -35,13 +35,13 @@ public void Test_Connect() { // Arrange var mockConnection = new Mock(); - var connection = new PointToInterlockingConnection(Mock.Of>(), _configuration, CancellationToken.None); + var builder = new PointToInterlockingConnectionBuilder(Mock.Of>(), _configuration, CancellationToken.None); // Act - connection.Connect(mockConnection.Object); + var connection = builder.Connect(mockConnection.Object); // Assert - Assert.Equal(connection.CurrentConnection, mockConnection.Object); + Assert.Equal(((PointToInterlockingConnection)connection).CurrentConnection, mockConnection.Object); } [Fact] @@ -56,16 +56,15 @@ public async Task Test_Initialization() mockConnection.Setup(x => x.SendAsync(Capture.In(receivedMessages))) .Returns(Task.FromResult(0)); - var connection = new PointToInterlockingConnection(Mock.Of>(), _configuration, CancellationToken.None); + var builder = new PointToInterlockingConnectionBuilder(Mock.Of>(), _configuration, CancellationToken.None); // Act - connection.Connect(mockConnection.Object); + var connection = builder.Connect(mockConnection.Object); await connection.InitializeConnection(new GenericPointState(LastCommandedPointPosition: null, PointPosition: GenericPointPosition.Left, DegradedPointPosition: GenericDegradedPointPosition.NotDegraded, AbilityToMove: GenericAbilityToMove.AbleToMove), true, false, CancellationToken.None); - // Assert mockConnection.Verify(v => v.ReceiveAsync(It.IsAny()), Times.Exactly(2)); mockConnection.Verify(v => v.SendAsync(It.IsAny()), Times.Exactly(5)); - Assert.Equal(new PointPdiVersionCheckMessage("99W1________________", "INTERLOCKING________", PointPdiVersionCheckMessageResultPdiVersionCheck.PDIVersionsFromReceiverAndSenderDoMatch, 1, 2, new byte[] { 0x00, 0x00 }).ToByteArray(), receivedMessages[0]); + Assert.Equal(new PointPdiVersionCheckMessage("99W1________________", "INTERLOCKING________", PointPdiVersionCheckMessageResultPdiVersionCheck.PDIVersionsFromReceiverAndSenderDoMatch, 1,1, new byte[] { 0x00 }).ToByteArray(), receivedMessages[0]); Assert.Equal(new PointStartInitialisationMessage("99W1________________", "INTERLOCKING________").ToByteArray(), receivedMessages[1]); Assert.Equal(new PointPointPositionMessage("99W1________________", "INTERLOCKING________", PointPointPositionMessageReportedPointPosition.PointIsInALeftHandPositionDefinedEndPosition, PointPointPositionMessageReportedDegradedPointPosition.PointIsNotInADegradedPosition).ToByteArray(), receivedMessages[2]); Assert.Equal(new PointAbilityToMovePointMessage("99W1________________", "INTERLOCKING________", PointAbilityToMovePointMessageReportedAbilityToMovePointStatus.PointIsAbleToMove).ToByteArray(), receivedMessages[3]); @@ -83,16 +82,16 @@ public async Task Test_Initialization_Timeout(){ mockConnection.Setup(x => x.SendAsync(Capture.In(receivedMessages))) .Returns(Task.FromResult(0)); - var connection = new PointToInterlockingConnection(Mock.Of>(), _configuration, CancellationToken.None); + var builder = new PointToInterlockingConnectionBuilder(Mock.Of>(), _configuration, CancellationToken.None); // Act - connection.Connect(mockConnection.Object); + var connection = builder.Connect(mockConnection.Object); await connection.InitializeConnection(new GenericPointState(LastCommandedPointPosition: null, PointPosition: GenericPointPosition.Left, DegradedPointPosition: GenericDegradedPointPosition.NotDegraded, AbilityToMove: GenericAbilityToMove.AbleToMove), true, true, CancellationToken.None); // Assert + // Should not send/receive any more messages after version check as timeout is simulated mockConnection.Verify(v => v.ReceiveAsync(It.IsAny()), Times.Exactly(1)); mockConnection.Verify(v => v.SendAsync(It.IsAny()), Times.Exactly(1)); - Assert.Equal(new PointPdiVersionCheckMessage("99W1________________", "INTERLOCKING________", PointPdiVersionCheckMessageResultPdiVersionCheck.PDIVersionsFromReceiverAndSenderDoMatch, 1, 2, new byte[] { 0x00, 0x00 }).ToByteArray(), receivedMessages[0]); } /// @@ -109,10 +108,10 @@ public async Task Test_Initialization_Version_Mismatch(){ mockConnection.Setup(x => x.SendAsync(Capture.In(receivedMessages))) .Returns(Task.FromResult(0)); - var connection = new PointToInterlockingConnection(Mock.Of>(), _configuration, CancellationToken.None); + var builder = new PointToInterlockingConnectionBuilder(Mock.Of>(), _configuration, CancellationToken.None); // Act - connection.Connect(mockConnection.Object); + var connection = builder.Connect(mockConnection.Object); await connection.InitializeConnection(new GenericPointState(LastCommandedPointPosition: null, PointPosition: GenericPointPosition.Left, DegradedPointPosition: GenericDegradedPointPosition.NotDegraded, AbilityToMove: GenericAbilityToMove.AbleToMove), true, true, CancellationToken.None); // Assert @@ -133,10 +132,10 @@ public async Task Test_Send_Position() mockConnection.Setup(x => x.SendAsync(Capture.In(args))) .Returns(Task.FromResult(0)); - var connection = new PointToInterlockingConnection(Mock.Of>(), _configuration, CancellationToken.None); + var builder = new PointToInterlockingConnectionBuilder(Mock.Of>(), _configuration, CancellationToken.None); // Act - connection.Connect(mockConnection.Object); + var connection = builder.Connect(mockConnection.Object); await connection.InitializeConnection(new GenericPointState(LastCommandedPointPosition: null, PointPosition: GenericPointPosition.Left, DegradedPointPosition: GenericDegradedPointPosition.NotDegraded, AbilityToMove: GenericAbilityToMove.AbleToMove), true, false, CancellationToken.None); await connection.SendPointPosition(new GenericPointState(LastCommandedPointPosition: null, PointPosition: GenericPointPosition.Right, DegradedPointPosition: GenericDegradedPointPosition.NotDegraded, AbilityToMove: GenericAbilityToMove.AbleToMove)); await connection.SendPointPosition(new GenericPointState(LastCommandedPointPosition: null, PointPosition: GenericPointPosition.Left, DegradedPointPosition: GenericDegradedPointPosition.NotDegraded, AbilityToMove: GenericAbilityToMove.AbleToMove)); @@ -162,10 +161,10 @@ public async Task Test_Receive_Position() .ReturnsAsync(new PointMovePointCommand("99W1", "100", PointMovePointCommandCommandedPointPosition.SubsystemElectronicInterlockingRequestsALeftHandPointMoving).ToByteArray()) .ReturnsAsync(new PointMovePointCommand("99W1", "100", PointMovePointCommandCommandedPointPosition.SubsystemElectronicInterlockingRequestsARightHandPointMoving).ToByteArray()); - var connection = new PointToInterlockingConnection(Mock.Of>(), _configuration, CancellationToken.None); + var builder = new PointToInterlockingConnectionBuilder(Mock.Of>(), _configuration, CancellationToken.None); // Act - connection.Connect(mockConnection.Object); + var connection = builder.Connect(mockConnection.Object); await connection.InitializeConnection(new GenericPointState(LastCommandedPointPosition: null, PointPosition: GenericPointPosition.Left, DegradedPointPosition: GenericDegradedPointPosition.NotDegraded, AbilityToMove: GenericAbilityToMove.AbleToMove), true, false, CancellationToken.None); var position1 = await connection.ReceiveMovePointCommand(CancellationToken.None); var position2 = await connection.ReceiveMovePointCommand(CancellationToken.None); @@ -188,10 +187,10 @@ public async Task Test_TimeoutMessage() mockConnection.Setup(x => x.SendAsync(Capture.In(args))) .Returns(Task.FromResult(0)); - var connection = new PointToInterlockingConnection(Mock.Of>(), _configuration, CancellationToken.None); + var builder = new PointToInterlockingConnectionBuilder(Mock.Of>(), _configuration, CancellationToken.None); // Act - connection.Connect(mockConnection.Object); + var connection = builder.Connect(mockConnection.Object); await connection.InitializeConnection(new GenericPointState(LastCommandedPointPosition: null, PointPosition: GenericPointPosition.Left, DegradedPointPosition: GenericDegradedPointPosition.NotDegraded, AbilityToMove: GenericAbilityToMove.AbleToMove), true, false, CancellationToken.None); await connection.SendTimeoutMessage(); diff --git a/src/FieldElementSubsystems.Test/Point/Baseline4R2/CommandingAndReversingTests.cs b/src/FieldElementSubsystems.Test/Point/Baseline4R2/CommandingAndReversingTests.cs index 3da96c9..403748f 100644 --- a/src/FieldElementSubsystems.Test/Point/Baseline4R2/CommandingAndReversingTests.cs +++ b/src/FieldElementSubsystems.Test/Point/Baseline4R2/CommandingAndReversingTests.cs @@ -30,7 +30,7 @@ private static (EulynxLive.Point.Point point, Task pointTask, List recei {"PointSettings:InitialDegradedPointPosition", initialPointState.DegradedPointPosition.ToString() }, {"PointSettings:InitialAbilityToMove", initialPointState.AbilityToMove.ToString() }, {"PointSettings:PDIVersion", "1" }, - {"PointSettings:PDIChecksum", "0x0000" } + {"PointSettings:PDIChecksum", "0x00" } }; var configuration = new ConfigurationBuilder() @@ -72,11 +72,11 @@ private static (EulynxLive.Point.Point point, Task pointTask, List recei .Setup(x => x.Connect(It.IsAny(), It.IsAny())) .Returns(mockConnection.Object); - var connection = new PointToInterlockingConnection(Mock.Of>(), configuration, CancellationToken.None); + var builder = new PointToInterlockingConnectionBuilder(Mock.Of>(), configuration, CancellationToken.None); var mockHubContext = new Mock>(); mockHubContext.Setup(x => x.Clients.All.SendCoreAsync(It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.CompletedTask); - var point = new EulynxLive.Point.Point(Mock.Of>(), configuration, connection, connectionProvider.Object, mockHubContext.Object); + var point = new EulynxLive.Point.Point(Mock.Of>(), configuration, builder, connectionProvider.Object, mockHubContext.Object); if (simulateTimeouts) { point.EnableTimeoutLeft(true); point.EnableTimeoutRight(true); diff --git a/src/FieldElementSubsystems.Test/Point/Baseline4R2/ReportStatusTests.cs b/src/FieldElementSubsystems.Test/Point/Baseline4R2/ReportStatusTests.cs index 35677b1..c34e9b5 100644 --- a/src/FieldElementSubsystems.Test/Point/Baseline4R2/ReportStatusTests.cs +++ b/src/FieldElementSubsystems.Test/Point/Baseline4R2/ReportStatusTests.cs @@ -30,7 +30,7 @@ private static (EulynxLive.Point.Point point, Task, List receivedBytes) {"PointSettings:InitialDegradedPointPosition", initialPointState.DegradedPointPosition.ToString() }, {"PointSettings:InitialAbilityToMove", initialPointState.AbilityToMove.ToString() }, {"PointSettings:PDIVersion", "1" }, - {"PointSettings:PDIChecksum", "0x0000" } + {"PointSettings:PDIChecksum", "0x00" } }; var configuration = new ConfigurationBuilder() @@ -58,12 +58,11 @@ private static (EulynxLive.Point.Point point, Task, List receivedBytes) .Setup(x => x.Connect(It.IsAny(), It.IsAny())) .Returns(mockConnection.Object); - var connection = new PointToInterlockingConnection(Mock.Of>(), configuration, CancellationToken.None); - connection.Connect(mockConnection.Object); + var builder = new PointToInterlockingConnectionBuilder(Mock.Of>(), configuration, CancellationToken.None); var mockHubContext = new Mock>(); mockHubContext.Setup(x => x.Clients.All.SendCoreAsync(It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.CompletedTask); - var point = new EulynxLive.Point.Point(Mock.Of>(), configuration, connection, connectionProvider.Object, mockHubContext.Object); + var point = new EulynxLive.Point.Point(Mock.Of>(), configuration, builder, connectionProvider.Object, mockHubContext.Object); async Task SimulatePoint() { diff --git a/src/FieldElementSubsystems.Test/Point/PointTest.cs b/src/FieldElementSubsystems.Test/Point/PointTest.cs index 14fbaf0..4afab1a 100644 --- a/src/FieldElementSubsystems.Test/Point/PointTest.cs +++ b/src/FieldElementSubsystems.Test/Point/PointTest.cs @@ -29,7 +29,7 @@ private static (EulynxLive.Point.Point, Func simulatePoint, Mock simulatePoint, Mock()!; - var mockConnection = CreateDefaultMockConnection(config); + var (mockConnection, mockConnectionBuilder) = CreateDefaultMockConnection(config); var mockHubContext = new Mock>(); mockHubContext.Setup(x => x.Clients.All.SendCoreAsync(It.IsAny(), It.IsAny(), It.IsAny())).Returns(Task.CompletedTask); - var point = new EulynxLive.Point.Point(Mock.Of>(), configuration, mockConnection.Object, Mock.Of(), mockHubContext.Object); + var point = new EulynxLive.Point.Point(Mock.Of>(), configuration, mockConnectionBuilder.Object, Mock.Of(), mockHubContext.Object); async Task SimulatePoint() { @@ -56,9 +56,10 @@ async Task SimulatePoint() return (point, SimulatePoint, mockConnection, cancel); } - private static Mock CreateDefaultMockConnection(PointConfiguration configuration) + private static (Mock, Mock) CreateDefaultMockConnection(PointConfiguration configuration) { var mockConnection = new Mock(); + var mockConnectionBuilder = new Mock(); mockConnection.Setup(x => x.Configuration).Returns(() => configuration); mockConnection .Setup(m => m.SendPointPosition( @@ -66,13 +67,13 @@ private static Mock CreateDefaultMockConnection( .Returns(Task.FromResult(0)); mockConnection .Setup(m => m.InitializeConnection( - It.IsAny(), It.IsAny(), It.IsAny(),It.IsAny())) + It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Returns(Task.FromResult(true)); - mockConnection + mockConnectionBuilder .Setup(m => m.Connect( It.IsAny())) .Returns(mockConnection.Object); - return mockConnection; + return (mockConnection, mockConnectionBuilder); } private readonly ILogger _logger = Mock.Of>(); @@ -116,7 +117,7 @@ public async Task Test_Reset() await pointTask(); // Assert - connection.Verify(v => v.InitializeConnection(It.IsAny(), It.IsAny(), It.IsAny(),It.IsAny()), Times.Exactly(2)); + connection.Verify(v => v.InitializeConnection(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(2)); } [Fact] diff --git a/src/FieldElementSubsystems.Test/UtilsTest.cs b/src/FieldElementSubsystems.Test/UtilsTest.cs index 7aa4405..4393437 100644 --- a/src/FieldElementSubsystems.Test/UtilsTest.cs +++ b/src/FieldElementSubsystems.Test/UtilsTest.cs @@ -7,13 +7,21 @@ public static void TestHexToByteArray() { string hexString = "0A0B0C0D0E0F"; byte[] byteArray = hexString.HexToByteArray(); - Assert.Equal(byteArray, new byte[] { 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }); + Assert.Equal(byteArray, [0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F]); + } + + [Fact] + public static void TestHexToByteArray0x() + { + string hexString = "0x0A0B0C0D0E0F"; + byte[] byteArray = hexString.HexToByteArray(); + Assert.Equal(byteArray, [0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F]); } [Fact] public static void TestHexToByteArrayUneven() { string hexString = "F"; - Assert.Throws(() => hexString.HexToByteArray()); + Assert.Throws(hexString.HexToByteArray); } } diff --git a/src/FieldElementSubsystems/Connections/EulynxBaseline4R1/PointToInterlockingConnection.cs b/src/FieldElementSubsystems/Connections/EulynxBaseline4R1/PointToInterlockingConnection.cs index 7051e59..8382c6b 100644 --- a/src/FieldElementSubsystems/Connections/EulynxBaseline4R1/PointToInterlockingConnection.cs +++ b/src/FieldElementSubsystems/Connections/EulynxBaseline4R1/PointToInterlockingConnection.cs @@ -9,6 +9,29 @@ namespace EulynxLive.FieldElementSubsystems.Connections.EulynxBaseline4R1; + +public class PointToInterlockingConnectionBuilder : IPointToInterlockingConnectionBuilder +{ + private readonly ILogger _logger; + private readonly CancellationToken _stoppingToken; + private readonly IConfiguration _configuration; + + public PointToInterlockingConnectionBuilder( + ILogger logger, + IConfiguration configuration, + CancellationToken stoppingToken) + { + _logger = logger; + _stoppingToken = stoppingToken; + _configuration = configuration; + } + + public IPointToInterlockingConnection Connect(IConnection conn) + { + return new PointToInterlockingConnection(_logger, _configuration, _stoppingToken, conn); + } +} + public class PointToInterlockingConnection : IPointToInterlockingConnection { private readonly ILogger _logger; @@ -27,28 +50,21 @@ public class PointToInterlockingConnection : IPointToInterlockingConnection public PointToInterlockingConnection( ILogger logger, IConfiguration configuration, - CancellationToken stoppingToken) + CancellationToken stoppingToken, IConnection connection) { _stoppingToken = stoppingToken; _logger = logger; - CurrentConnection = null; + CurrentConnection = connection; var config = configuration.GetSection("PointSettings").Get() ?? throw new Exception("No configuration provided"); _localId = config.LocalId; _remoteId = config.RemoteId; _pdiVersion = config.PDIVersion; _checksum = config.PDIChecksum.HexToByteArray(); - if (_checksum.Length != 2) throw new InvalidOperationException($"Invalid checksum length. Expected 2 bytes was ${_checksum.Length}."); Configuration = config; _overrideMessages = Channel.CreateUnbounded(); } - public IPointToInterlockingConnection Connect(IConnection connection) - { - CurrentConnection = connection; - return this; - } - public async Task InitializeConnection(GenericPointState state, bool observeAbilityToMove, bool simulateTimeout, CancellationToken cancellationToken) { var versionCheckReceived = await ReceiveMessage(cancellationToken); @@ -63,6 +79,8 @@ public async Task InitializeConnection(GenericPointState state, bool obser { // Eu.Gen-SCI.445 // Eu.SCI-XX.PDI.91 - Eu.SCI-XX.PDI.94 + // If byte 43 is set to 0x01, byte 45 shall be set to zero. + // The bytes 46 ... 46+n-1 shall not be allocated, if PDI-Version from Receiver and Sender does not match _logger.LogError("Version check failed."); var versionCheckFailedResponse = new PointPdiVersionCheckMessage(_localId, _remoteId, PointPdiVersionCheckMessageResultPdiVersionCheck.PDIVersionsFromReceiverAndSenderDoNotMatch, _pdiVersion, 0, []); await SendMessage(versionCheckFailedResponse); @@ -76,7 +94,7 @@ public async Task InitializeConnection(GenericPointState state, bool obser if (simulateTimeout) { // Never send the missing initialization messages - return false; + return true; } if (await ReceiveMessage(cancellationToken) == null) diff --git a/src/FieldElementSubsystems/Connections/EulynxBaseline4R2/PointToInterlockingConnection.cs b/src/FieldElementSubsystems/Connections/EulynxBaseline4R2/PointToInterlockingConnection.cs index e4c8579..920454d 100644 --- a/src/FieldElementSubsystems/Connections/EulynxBaseline4R2/PointToInterlockingConnection.cs +++ b/src/FieldElementSubsystems/Connections/EulynxBaseline4R2/PointToInterlockingConnection.cs @@ -10,6 +10,28 @@ namespace EulynxLive.FieldElementSubsystems.Connections.EulynxBaseline4R2; +public class PointToInterlockingConnectionBuilder : IPointToInterlockingConnectionBuilder +{ + private readonly ILogger _logger; + private readonly CancellationToken _stoppingToken; + private readonly IConfiguration _configuration; + + public PointToInterlockingConnectionBuilder( + ILogger logger, + IConfiguration configuration, + CancellationToken stoppingToken) + { + _logger = logger; + _stoppingToken = stoppingToken; + _configuration = configuration; + } + + public IPointToInterlockingConnection Connect(IConnection conn) + { + return new PointToInterlockingConnection(_logger, _configuration, _stoppingToken, conn); + } +} + public class PointToInterlockingConnection : IPointToInterlockingConnection { private readonly ILogger _logger; @@ -28,29 +50,21 @@ public class PointToInterlockingConnection : IPointToInterlockingConnection public PointToInterlockingConnection( ILogger logger, IConfiguration configuration, - CancellationToken stoppingToken) + CancellationToken stoppingToken, IConnection connection) { _stoppingToken = stoppingToken; _logger = logger; - CurrentConnection = null; + CurrentConnection = connection; var config = configuration.GetSection("PointSettings").Get() ?? throw new Exception("No configuration provided"); _localId = config.LocalId; _remoteId = config.RemoteId; _pdiVersion = config.PDIVersion; _checksum = config.PDIChecksum.HexToByteArray(); - if (_checksum.Length != 2) throw new InvalidOperationException($"Invalid checksum length. Expected 2 bytes was ${_checksum.Length}."); - Configuration = config; _overrideMessages = Channel.CreateUnbounded(); } - public IPointToInterlockingConnection Connect(IConnection connection) - { - CurrentConnection = connection; - return this; - } - public async Task InitializeConnection(GenericPointState state, bool observeAbilityToMove, bool simulateTimeout, CancellationToken cancellationToken) { var versionCheckReceived = await ReceiveMessage(cancellationToken); @@ -65,6 +79,8 @@ public async Task InitializeConnection(GenericPointState state, bool obser { // Eu.Gen-SCI.445 // Eu.SCI-XX.PDI.91 - Eu.SCI-XX.PDI.94 + // If byte 43 is set to 0x01, byte 45 shall be set to zero. + // The bytes 46 ... 46+n-1 shall not be allocated, if PDI-Version from Receiver and Sender does not match _logger.LogError("Version check failed."); var versionCheckFailedResponse = new PointPdiVersionCheckMessage(_localId, _remoteId, PointPdiVersionCheckMessageResultPdiVersionCheck.PDIVersionsFromReceiverAndSenderDoNotMatch, _pdiVersion, 0, []); await SendMessage(versionCheckFailedResponse); @@ -78,15 +94,13 @@ public async Task InitializeConnection(GenericPointState state, bool obser if (simulateTimeout) { // Never send the missing initialization messages - return false; + return true; } - if (await ReceiveMessage(cancellationToken) == null) { _logger.LogError("Unexpected message."); return false; } - var startInitialization = new PointStartInitialisationMessage(_localId, _remoteId); await SendMessage(startInitialization); diff --git a/src/FieldElementSubsystems/Interfaces/IPointToInterlockingConnection.cs b/src/FieldElementSubsystems/Interfaces/IPointToInterlockingConnection.cs index 135186d..8a5f6d3 100644 --- a/src/FieldElementSubsystems/Interfaces/IPointToInterlockingConnection.cs +++ b/src/FieldElementSubsystems/Interfaces/IPointToInterlockingConnection.cs @@ -2,11 +2,13 @@ namespace EulynxLive.FieldElementSubsystems.Interfaces; +public interface IPointToInterlockingConnectionBuilder { + IPointToInterlockingConnection Connect(IConnection conn); +} + public interface IPointToInterlockingConnection : IDisposable { PointConfiguration Configuration { get; } - IPointToInterlockingConnection Connect(IConnection connection); - Task SendPointPosition(GenericPointState state); Task SendSciMessage(byte[] message); Task OverrideNextSciMessage(byte[] message); diff --git a/src/Point/Connections/ConnectionFactory.cs b/src/Point/Connections/ConnectionFactory.cs index b787939..befd994 100644 --- a/src/Point/Connections/ConnectionFactory.cs +++ b/src/Point/Connections/ConnectionFactory.cs @@ -15,16 +15,16 @@ public ConnectionFactory(ILogger logger, IConfiguration confi _configuration = configuration; } - public IPointToInterlockingConnection CreateConnection(IServiceProvider x) { + public IPointToInterlockingConnectionBuilder CreateConnection(IServiceProvider x) { var connectionProtocol = _configuration.GetSection("PointSettings").Get()?.ConnectionProtocol; switch (connectionProtocol){ case ConnectionProtocol.EulynxBaseline4R1: - return ActivatorUtilities.CreateInstance(x, _configuration, CancellationToken.None); + return ActivatorUtilities.CreateInstance(x, _configuration, CancellationToken.None); case ConnectionProtocol.EulynxBaseline4R2: - return ActivatorUtilities.CreateInstance(x, _configuration, CancellationToken.None); + return ActivatorUtilities.CreateInstance(x, _configuration, CancellationToken.None); case null: _logger.LogWarning($"No connection protocol specified. Using EulynxBaseline4R2."); - return ActivatorUtilities.CreateInstance(x, _configuration, CancellationToken.None); + return ActivatorUtilities.CreateInstance(x, _configuration, CancellationToken.None); default: throw new NotImplementedException($"Unknown connection protocol {connectionProtocol}."); } diff --git a/src/Point/IPoint.cs b/src/Point/IPoint.cs index 6b36b09..c5cbed2 100644 --- a/src/Point/IPoint.cs +++ b/src/Point/IPoint.cs @@ -6,7 +6,7 @@ namespace EulynxLive.Point { public interface IPoint { ConnectionProtocol? ConnectionProtocol { get; } - IPointToInterlockingConnection Connection { get; } + IPointToInterlockingConnection? Connection { get; } GenericPointState PointState { get; } void EnableTimeoutLeft(bool enableMovementFailed); diff --git a/src/Point/Point.cs b/src/Point/Point.cs index ce5d6ac..89923e8 100644 --- a/src/Point/Point.cs +++ b/src/Point/Point.cs @@ -19,7 +19,9 @@ namespace EulynxLive.Point { public partial class Point : BackgroundService, IPoint { - public IPointToInterlockingConnection Connection { get; set; } + public IPointToInterlockingConnectionBuilder? ConnectionBuilder { get; } + + public IPointToInterlockingConnection? Connection { get; private set; } public bool AllPointMachinesCrucial { get; } public bool ObserveAbilityToMove { get; } @@ -33,13 +35,14 @@ public partial class Point : BackgroundService, IPoint private bool _initialized; private readonly ILogger _logger; + private readonly IPointToInterlockingConnectionBuilder _connectionBuilder; private readonly IConnectionProvider _connectionProvider; private readonly PointConfiguration _config; private CancellationTokenSource _resetTokenSource = CancellationTokenSource.CreateLinkedTokenSource(CancellationToken.None); - public Point(ILogger logger, IConfiguration configuration, IPointToInterlockingConnection connection, IConnectionProvider connectionProvider, IHubContext statusHub) + public Point(ILogger logger, IConfiguration configuration, IPointToInterlockingConnectionBuilder connectionBuilder, IConnectionProvider connectionProvider, IHubContext statusHub) { - Connection = connection; + _connectionBuilder = connectionBuilder; _connectionProvider = connectionProvider; _logger = logger; @@ -95,6 +98,7 @@ public Point(ILogger logger, IConfiguration configuration, IPointToInterl public async Task SendSciMessage(SciMessage message) { + if (Connection == null) throw new InvalidOperationException("Connection is null. Did you call Connect()?"); _logger.LogInformation("Sending SCI message: {}", message.Message); await Connection.SendSciMessage(message.Message.ToByteArray()); } @@ -102,12 +106,13 @@ public async Task SendSciMessage(SciMessage message) /// /// Sets the sets the initialization timeout flag for the next initialization. /// - public void EnableInitializationTimeout(bool enableInitialisationTimeout) + public void EnableInitializationTimeout(bool enableInitializationTimeout) { - _logger.LogInformation("Reset and Timeout on next initialisation handshake enabled."); + if (Connection == null) throw new InvalidOperationException("Connection is null. Did you call Connect()?"); + _logger.LogInformation("Reset and Timeout on next initialization handshake enabled."); _simulatedPointState = _simulatedPointState with { - SimulateInitializationTimeout = enableInitialisationTimeout + SimulateInitializationTimeout = enableInitializationTimeout }; } @@ -158,6 +163,7 @@ public async Task SetAbilityToMove(AbilityToMoveMessage abilityToMoveMessage) if (_initialized) { + if (Connection == null) throw new InvalidOperationException("Connection is null. Did you call Connect()?"); await Connection.SendAbilityToMove(PointState); } } @@ -184,6 +190,7 @@ public async Task PutIntoUnintendedPosition(DegradedPositionMessage simulatedPos if (_initialized) { + if (Connection == null) throw new InvalidOperationException("Connection is null. Did you call Connect()?"); await Connection.SendPointPosition(PointState); } } @@ -260,8 +267,8 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) while (!stoppingToken.IsCancellationRequested) { _logger.LogTrace("Connecting..."); - var conn = _connectionProvider.Connect(Connection.Configuration, stoppingToken); - using (Connection = Connection.Connect(conn)) + var conn = _connectionProvider.Connect(_config, stoppingToken); + using (Connection = _connectionBuilder.Connect(conn)) { _resetTokenSource = CancellationTokenSource.CreateLinkedTokenSource(stoppingToken); @@ -303,6 +310,7 @@ await AllMovePointCommands(_resetTokenSource.Token) private async IAsyncEnumerable AllMovePointCommands([EnumeratorCancellation] CancellationToken stoppingToken) { + if (Connection == null) throw new InvalidOperationException("Connection is null. Did you call Connect()?"); while (!stoppingToken.IsCancellationRequested) { var commandedPointPosition = await Connection.ReceiveMovePointCommand(stoppingToken); @@ -332,6 +340,7 @@ private async Task HandleCommandedPointPosition(GenericPointPosition commandedPo return; } + if (Connection == null) throw new InvalidOperationException("Connection is null. Did you call Connect()?"); _logger.LogDebug("Moving to {}.", commandedPointPosition); if (PointState.PointPosition != GenericPointPosition.NoEndPosition) diff --git a/src/Point/Program.cs b/src/Point/Program.cs index 270219c..52a7a84 100644 --- a/src/Point/Program.cs +++ b/src/Point/Program.cs @@ -34,6 +34,8 @@ public static IHostBuilder CreateHostBuilder(string[] args) => { "--initial-point-position", "PointSettings:InitialPointPosition" }, { "--initial-degraded-point-position", "PointSettings:InitialDegradedPointPosition" }, { "--initial-ability-to-move", "PointSettings:InitialAbilityToMove" }, + { "--pdi-version", "PointSettings:PDIVersion"}, + { "--pdi-checksum", "PointSettings:PDIChecksum"} }; webBuilder .ConfigureAppConfiguration((hostingContext, config) => diff --git a/src/Point/Services/PointService.cs b/src/Point/Services/PointService.cs index 0ab5d2a..44ee377 100644 --- a/src/Point/Services/PointService.cs +++ b/src/Point/Services/PointService.cs @@ -18,7 +18,6 @@ public PointService(IPoint point) public override Task Reset(Empty request, ServerCallContext context) { - // TODO: We have to disconnect here! _point.Reset(); return Task.FromResult(new Empty()); } @@ -49,11 +48,12 @@ public override async Task SendSciMessage(SciMessage request, ServerCallC public override async Task OverrideSciMessage(SciMessage request, ServerCallContext context) { + if (_point.Connection == null) throw new InvalidOperationException("Connection is null. Did you call Connect()?"); await _point.Connection.OverrideNextSciMessage(request.Message.ToByteArray()); return new Empty(); } - public override Task ScheduleInitializationTimeout(EnableInitializationFailedMessage request, ServerCallContext context) + public override Task ScheduleInitializationFailed(EnableInitializationFailedMessage request, ServerCallContext context) { _point.EnableInitializationTimeout(request.EnableInitializationFailed); return Task.FromResult(new Empty()); diff --git a/src/Point/appsettings.json b/src/Point/appsettings.json index 9148003..5cf049d 100644 --- a/src/Point/appsettings.json +++ b/src/Point/appsettings.json @@ -17,7 +17,7 @@ "InitialAbilityToMove": "AbleToMove", "ConnectionProtocol": "EulynxBaseline4R1", "PDIVersion": "1", - "PDIChecksum": "0x0000" + "PDIChecksum": "0x00" }, "Kestrel": { "EndPoints": { diff --git a/src/Point/rasta-point-web/src/App.tsx b/src/Point/rasta-point-web/src/App.tsx index dab3b63..47ddb5f 100644 --- a/src/Point/rasta-point-web/src/App.tsx +++ b/src/Point/rasta-point-web/src/App.tsx @@ -34,6 +34,8 @@ export type SimulatorConfiguration = { initialDegradedPointPosition: string, initialAbilityToMove: string, connectionProtocol: 'EulynxBaseline4R1' | 'EulynxBaseline4R2', + pdiVersion: string, + pdiChecksum: string, }; function App() { diff --git a/src/Point/rasta-point-web/src/Point.tsx b/src/Point/rasta-point-web/src/Point.tsx index 1fd1f0c..1413088 100644 --- a/src/Point/rasta-point-web/src/Point.tsx +++ b/src/Point/rasta-point-web/src/Point.tsx @@ -55,7 +55,7 @@ function ButtonGroup({ items }: { items: { active: boolean, label: string, disab return (
-
+
{items.map((item, index) => ( ))} @@ -136,6 +136,20 @@ function Point({ {' '} s +
+ + PDI Version + + + {simulatorConfiguration?.pdiVersion} + + + PDI Checksum + + + {simulatorConfiguration?.pdiChecksum} + +
@@ -360,7 +374,7 @@ function Point({ label="Enable Initialization Timeout" active={simulatedPointState?.simulateInitializationTimeout || false} onChange={ - (enable) => sendCommand((client) => client.scheduleInitializationTimeout(new EnableInitializationFailedMessage().setEnableinitializationfailed(enable), null)) + (enable) => sendCommand((client) => client.scheduleInitializationFailed(new EnableInitializationFailedMessage().setEnableinitializationfailed(enable), null)) } />
diff --git a/src/Point/rasta-point-web/src/proto/PointServiceClientPb.ts b/src/Point/rasta-point-web/src/proto/PointServiceClientPb.ts index 5124741..15d8fac 100644 --- a/src/Point/rasta-point-web/src/proto/PointServiceClientPb.ts +++ b/src/Point/rasta-point-web/src/proto/PointServiceClientPb.ts @@ -513,8 +513,8 @@ export class PointClient { this.methodDescriptorScheduleTimeoutLeft); } - methodDescriptorScheduleInitializationTimeout = new grpcWeb.MethodDescriptor( - '/point.Point/ScheduleInitializationTimeout', + methodDescriptorScheduleInitializationFailed = new grpcWeb.MethodDescriptor( + '/point.Point/ScheduleInitializationFailed', grpcWeb.MethodType.UNARY, point_pb.EnableInitializationFailedMessage, google_protobuf_empty_pb.Empty, @@ -524,17 +524,17 @@ export class PointClient { google_protobuf_empty_pb.Empty.deserializeBinary ); - scheduleInitializationTimeout( + scheduleInitializationFailed( request: point_pb.EnableInitializationFailedMessage, metadata: grpcWeb.Metadata | null): Promise; - scheduleInitializationTimeout( + scheduleInitializationFailed( request: point_pb.EnableInitializationFailedMessage, metadata: grpcWeb.Metadata | null, callback: (err: grpcWeb.RpcError, response: google_protobuf_empty_pb.Empty) => void): grpcWeb.ClientReadableStream; - scheduleInitializationTimeout( + scheduleInitializationFailed( request: point_pb.EnableInitializationFailedMessage, metadata: grpcWeb.Metadata | null, callback?: (err: grpcWeb.RpcError, @@ -542,18 +542,18 @@ export class PointClient { if (callback !== undefined) { return this.client_.rpcCall( this.hostname_ + - '/point.Point/ScheduleInitializationTimeout', + '/point.Point/ScheduleInitializationFailed', request, metadata || {}, - this.methodDescriptorScheduleInitializationTimeout, + this.methodDescriptorScheduleInitializationFailed, callback); } return this.client_.unaryCall( this.hostname_ + - '/point.Point/ScheduleInitializationTimeout', + '/point.Point/ScheduleInitializationFailed', request, metadata || {}, - this.methodDescriptorScheduleInitializationTimeout); + this.methodDescriptorScheduleInitializationFailed); } methodDescriptorReset = new grpcWeb.MethodDescriptor( diff --git a/src/ProtobufInterfaces/proto/point.proto b/src/ProtobufInterfaces/proto/point.proto index 979a6b7..b8f662b 100644 --- a/src/ProtobufInterfaces/proto/point.proto +++ b/src/ProtobufInterfaces/proto/point.proto @@ -41,7 +41,7 @@ service Point { rpc ScheduleTimeoutRight (EnableMovementFailedMessage) returns (google.protobuf.Empty) {} rpc ScheduleTimeoutLeft (EnableMovementFailedMessage) returns (google.protobuf.Empty) {} - rpc ScheduleInitializationTimeout (EnableInitializationFailedMessage) returns (google.protobuf.Empty) {} + rpc ScheduleInitializationFailed (EnableInitializationFailedMessage) returns (google.protobuf.Empty) {} rpc Reset (google.protobuf.Empty) returns (google.protobuf.Empty) {} }