From 74eefa456296a65383b739fea3ce3fbc9be23fee Mon Sep 17 00:00:00 2001 From: Oliver Rahner Date: Mon, 19 Aug 2024 13:52:24 +0200 Subject: [PATCH 1/9] add dke:ping --- .../TechnicalMessageTypeDefinitions.cs | 5 + .../Service/Messaging/IPingService.cs | 33 +++++ .../Service/Parameters/PingParameters.cs | 7 + .../Service/Messaging/PingService.cs | 85 ++++++++++++ .../Service/Messaging/Mqtt/PingServiceTest.cs | 127 ++++++++++++++++++ 5 files changed, 257 insertions(+) create mode 100644 agrirouter-sdk-dotnet-standard-api/Service/Messaging/IPingService.cs create mode 100644 agrirouter-sdk-dotnet-standard-api/Service/Parameters/PingParameters.cs create mode 100644 agrirouter-sdk-dotnet-standard-impl/Service/Messaging/PingService.cs create mode 100644 agrirouter-sdk-dotnet-standard-test/Service/Messaging/Mqtt/PingServiceTest.cs diff --git a/agrirouter-sdk-dotnet-standard-api/Definitions/TechnicalMessageTypeDefinitions.cs b/agrirouter-sdk-dotnet-standard-api/Definitions/TechnicalMessageTypeDefinitions.cs index 5df9207..ccb8abf 100644 --- a/agrirouter-sdk-dotnet-standard-api/Definitions/TechnicalMessageTypeDefinitions.cs +++ b/agrirouter-sdk-dotnet-standard-api/Definitions/TechnicalMessageTypeDefinitions.cs @@ -52,6 +52,11 @@ public static class TechnicalMessageTypes /// public static string DkeSubscription => "dke:subscription"; + /// + /// Type 'dke:ping'. + /// + public static string DkePing => "dke:ping"; + /// /// Type 'dke:cloud_onboard_endpoints'. /// diff --git a/agrirouter-sdk-dotnet-standard-api/Service/Messaging/IPingService.cs b/agrirouter-sdk-dotnet-standard-api/Service/Messaging/IPingService.cs new file mode 100644 index 0000000..351d681 --- /dev/null +++ b/agrirouter-sdk-dotnet-standard-api/Service/Messaging/IPingService.cs @@ -0,0 +1,33 @@ +using System.Threading.Tasks; +using Agrirouter.Api.Dto.Messaging; +using Agrirouter.Api.Service.Parameters; + +namespace Agrirouter.Api.Service.Messaging +{ + /// + /// Send a ping message to check if the endpoint still exists. + /// + public interface IPingService : IMessagingService + { + /// + /// Please see base class declaration for documentation. + /// + /// - + /// - + MessagingResult Send(PingParameters pingParameters); + + /// + /// Please see base class declaration for documentation. + /// + /// - + /// - + Task SendAsync(PingParameters pingParameters); + + /// + /// Please see for documentation. + /// + /// - + /// - + EncodedMessage Encode(PingParameters pingParameters); + } +} \ No newline at end of file diff --git a/agrirouter-sdk-dotnet-standard-api/Service/Parameters/PingParameters.cs b/agrirouter-sdk-dotnet-standard-api/Service/Parameters/PingParameters.cs new file mode 100644 index 0000000..9ed7748 --- /dev/null +++ b/agrirouter-sdk-dotnet-standard-api/Service/Parameters/PingParameters.cs @@ -0,0 +1,7 @@ +namespace Agrirouter.Api.Service.Parameters +{ + public class PingParameters : MessageParameters + { + // no additional fields, but more verbosity with explicit class definition + } +} \ No newline at end of file diff --git a/agrirouter-sdk-dotnet-standard-impl/Service/Messaging/PingService.cs b/agrirouter-sdk-dotnet-standard-impl/Service/Messaging/PingService.cs new file mode 100644 index 0000000..08d1170 --- /dev/null +++ b/agrirouter-sdk-dotnet-standard-impl/Service/Messaging/PingService.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Agrirouter.Api.Definitions; +using Agrirouter.Api.Dto.Messaging; +using Agrirouter.Api.Service.Messaging; +using Agrirouter.Api.Service.Parameters; +using Agrirouter.Feed.Request; +using Agrirouter.Impl.Service.Common; +using Agrirouter.Request; +using Google.Protobuf; + +namespace Agrirouter.Impl.Service.Messaging +{ + /// + /// Service to list the endpoints connected to an endpoint. + /// + public class PingService + { + private IMessagingService _messagingService; + + /// + /// Constructor. + /// + /// + public PingService(IMessagingService messagingService) + { + _messagingService = messagingService; + } + + /// + /// Please see base class declaration for documentation. + /// + /// - + /// - + public MessagingResult Send(PingParameters pingParameters) + { + var encodedMessages = new List {Encode(pingParameters).Content}; + var messagingParameters = pingParameters.BuildMessagingParameter(encodedMessages); + return _messagingService.Send(messagingParameters); + } + + /// + /// Please see base class declaration for documentation. + /// + /// - + /// - + public Task SendAsync(PingParameters pingParameters) + { + var encodedMessages = new List {Encode(pingParameters).Content}; + var messagingParameters = pingParameters.BuildMessagingParameter(encodedMessages); + return _messagingService.SendAsync(messagingParameters); + } + + /// + /// Please see for documentation. + /// + /// - + /// - + public EncodedMessage Encode(PingParameters pingParameters) + { + var messageHeaderParameters = new MessageHeaderParameters + { + ApplicationMessageId = pingParameters.ApplicationMessageId, + TeamSetContextId = pingParameters.TeamsetContextId ?? "", + TechnicalMessageType = TechnicalMessageTypes.DkePing, + Mode = RequestEnvelope.Types.Mode.Direct + }; + + var messagePayloadParameters = new MessagePayloadParameters + { + TypeUrl = MessageQuery.Descriptor.FullName, + Value = ByteString.Empty + }; + + var encodedMessage = new EncodedMessage + { + Id = Guid.NewGuid().ToString(), + Content = EncodeMessageService.Encode(messageHeaderParameters, messagePayloadParameters) + }; + + return encodedMessage; + } + } +} \ No newline at end of file diff --git a/agrirouter-sdk-dotnet-standard-test/Service/Messaging/Mqtt/PingServiceTest.cs b/agrirouter-sdk-dotnet-standard-test/Service/Messaging/Mqtt/PingServiceTest.cs new file mode 100644 index 0000000..df6a562 --- /dev/null +++ b/agrirouter-sdk-dotnet-standard-test/Service/Messaging/Mqtt/PingServiceTest.cs @@ -0,0 +1,127 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading.Tasks; +using Agrirouter.Request.Payload.Endpoint; +using Agrirouter.Api.Definitions; +using Agrirouter.Api.Dto.Onboard; +using Agrirouter.Api.Service.Parameters; +using Agrirouter.Api.Service.Parameters.Inner; +using Agrirouter.Impl.Service.Common; +using Agrirouter.Impl.Service.Messaging; +using Agrirouter.Test.Data; +using Agrirouter.Test.Helper; +using MQTTnet; +using MQTTnet.Client; +using Xunit; +using Agrirouter.Api.Dto.Messaging; +using Newtonsoft.Json; +using Xunit.Abstractions; + +namespace Agrirouter.Test.Service.Messaging.Mqtt +{ + [Collection("Integrationtest")] + public class PingServiceTest : AbstractIntegrationTestForCommunicationUnits + { + private readonly ITestOutputHelper _testOutputHelper; + + public PingServiceTest(ITestOutputHelper testOutputHelper) + { + _testOutputHelper = testOutputHelper; + } + + [Fact] + public async void + GivenExistingEndpointWhenSendingPingThenShouldBeSuccessful() + { + var mqttClient = new MqttFactory().CreateMqttClient(); + + await MqttConnectionHelper.ConnectMqttClient(mqttClient, OnboardResponse); + await MqttConnectionHelper.SubscribeToTopics(mqttClient, OnboardResponse); + + var pingService = new PingService(new MqttMessagingService(mqttClient)); + var pingParameters = new PingParameters() + { + OnboardResponse = OnboardResponse + }; + + pingService.Send(pingParameters); + + var messageReceived = false; + var counter = 0; + + mqttClient.UseApplicationMessageReceivedHandler(e => + { + messageReceived = true; + + MessageResponse msg = + JsonConvert.DeserializeObject( + Encoding.UTF8.GetString(e.ApplicationMessage.Payload)); + var decodedMessage = DecodeMessageService.Decode(msg.Command.Message); + + Assert.Equal(200, decodedMessage.ResponseEnvelope.ResponseCode); + }); + + while (!messageReceived && counter < 5) + { + await Task.Delay(TimeSpan.FromSeconds(5)); + counter++; + } + + Assert.True(messageReceived); + } + + private static OnboardResponse OnboardResponse => + OnboardResponseIntegrationService.Read(Identifier.Mqtt.CommunicationUnit.SingleEndpointWithP12Certificate); + + + [Fact(Skip="Concept only")] + public async void + GivenRecentlyDeletedEndpointWhenSendingPingThenShouldReturn400() + { + // This test case can not run. We have no Router Device based tests currently, and this command only + // makes sense with a Router Device. + // It is only intended to show the concept of the test case. + + var mqttClient = new MqttFactory().CreateMqttClient(); + + await MqttConnectionHelper.ConnectMqttClient(mqttClient, OnboardResponse); + await MqttConnectionHelper.SubscribeToTopics(mqttClient, OnboardResponse); + + // Endpoint would need to be deleted here + // if it was deleted earlier, the connection wouldn't be possible + + var pingService = new PingService(new MqttMessagingService(mqttClient)); + var pingParameters = new PingParameters() + { + OnboardResponse = OnboardResponse + }; + + pingService.Send(pingParameters); + + var messageReceived = false; + var counter = 0; + + mqttClient.UseApplicationMessageReceivedHandler(e => + { + messageReceived = true; + + MessageResponse msg = + JsonConvert.DeserializeObject( + Encoding.UTF8.GetString(e.ApplicationMessage.Payload)); + var decodedMessage = DecodeMessageService.Decode(msg.Command.Message); + + // your own application should remove the endpoint from your endpoint list/registry now! + Assert.Equal(400, decodedMessage.ResponseEnvelope.ResponseCode); + }); + + while (!messageReceived && counter < 5) + { + await Task.Delay(TimeSpan.FromSeconds(5)); + counter++; + } + + Assert.True(messageReceived); + } + } +} \ No newline at end of file From 15c02f4cb0747e724d2853290c34e3f13092360f Mon Sep 17 00:00:00 2001 From: Oliver Rahner Date: Mon, 19 Aug 2024 13:53:37 +0200 Subject: [PATCH 2/9] fix mistake --- .../Service/Messaging/PingService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agrirouter-sdk-dotnet-standard-impl/Service/Messaging/PingService.cs b/agrirouter-sdk-dotnet-standard-impl/Service/Messaging/PingService.cs index 08d1170..22b4ac8 100644 --- a/agrirouter-sdk-dotnet-standard-impl/Service/Messaging/PingService.cs +++ b/agrirouter-sdk-dotnet-standard-impl/Service/Messaging/PingService.cs @@ -69,7 +69,7 @@ public EncodedMessage Encode(PingParameters pingParameters) var messagePayloadParameters = new MessagePayloadParameters { - TypeUrl = MessageQuery.Descriptor.FullName, + TypeUrl = "", Value = ByteString.Empty }; From bec47fc0e0bf80e4b4a65b77fec5ac0cf63bcd69 Mon Sep 17 00:00:00 2001 From: Oliver Rahner Date: Mon, 19 Aug 2024 14:02:52 +0200 Subject: [PATCH 3/9] cleanup --- .../Service/Messaging/IPingService.cs | 24 +------------------ .../Service/Messaging/PingService.cs | 4 ++-- 2 files changed, 3 insertions(+), 25 deletions(-) diff --git a/agrirouter-sdk-dotnet-standard-api/Service/Messaging/IPingService.cs b/agrirouter-sdk-dotnet-standard-api/Service/Messaging/IPingService.cs index 351d681..dcb6d5b 100644 --- a/agrirouter-sdk-dotnet-standard-api/Service/Messaging/IPingService.cs +++ b/agrirouter-sdk-dotnet-standard-api/Service/Messaging/IPingService.cs @@ -1,5 +1,3 @@ -using System.Threading.Tasks; -using Agrirouter.Api.Dto.Messaging; using Agrirouter.Api.Service.Parameters; namespace Agrirouter.Api.Service.Messaging @@ -7,27 +5,7 @@ namespace Agrirouter.Api.Service.Messaging /// /// Send a ping message to check if the endpoint still exists. /// - public interface IPingService : IMessagingService + public interface IPingService : IMessagingService, IEncodeMessageService { - /// - /// Please see base class declaration for documentation. - /// - /// - - /// - - MessagingResult Send(PingParameters pingParameters); - - /// - /// Please see base class declaration for documentation. - /// - /// - - /// - - Task SendAsync(PingParameters pingParameters); - - /// - /// Please see for documentation. - /// - /// - - /// - - EncodedMessage Encode(PingParameters pingParameters); } } \ No newline at end of file diff --git a/agrirouter-sdk-dotnet-standard-impl/Service/Messaging/PingService.cs b/agrirouter-sdk-dotnet-standard-impl/Service/Messaging/PingService.cs index 22b4ac8..7978a9c 100644 --- a/agrirouter-sdk-dotnet-standard-impl/Service/Messaging/PingService.cs +++ b/agrirouter-sdk-dotnet-standard-impl/Service/Messaging/PingService.cs @@ -15,9 +15,9 @@ namespace Agrirouter.Impl.Service.Messaging /// /// Service to list the endpoints connected to an endpoint. /// - public class PingService + public class PingService: IPingService { - private IMessagingService _messagingService; + private readonly IMessagingService _messagingService; /// /// Constructor. From 2c3735d60cce900d1ffb3e2faf25ba394e3b9aff Mon Sep 17 00:00:00 2001 From: Sascha Doemer Date: Mon, 19 Aug 2024 14:18:18 +0200 Subject: [PATCH 4/9] Remove unused test output helper from PingServiceTest The test output helper was not being utilized in the PingServiceTest class and has been removed to clean up the code. Additionally, a minor spacing adjustment was made in the existing Fact attribute for consistency. --- .../Service/Messaging/Mqtt/PingServiceTest.cs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/agrirouter-sdk-dotnet-standard-test/Service/Messaging/Mqtt/PingServiceTest.cs b/agrirouter-sdk-dotnet-standard-test/Service/Messaging/Mqtt/PingServiceTest.cs index df6a562..bf9ac5e 100644 --- a/agrirouter-sdk-dotnet-standard-test/Service/Messaging/Mqtt/PingServiceTest.cs +++ b/agrirouter-sdk-dotnet-standard-test/Service/Messaging/Mqtt/PingServiceTest.cs @@ -23,13 +23,6 @@ namespace Agrirouter.Test.Service.Messaging.Mqtt [Collection("Integrationtest")] public class PingServiceTest : AbstractIntegrationTestForCommunicationUnits { - private readonly ITestOutputHelper _testOutputHelper; - - public PingServiceTest(ITestOutputHelper testOutputHelper) - { - _testOutputHelper = testOutputHelper; - } - [Fact] public async void GivenExistingEndpointWhenSendingPingThenShouldBeSuccessful() @@ -75,7 +68,7 @@ public async void OnboardResponseIntegrationService.Read(Identifier.Mqtt.CommunicationUnit.SingleEndpointWithP12Certificate); - [Fact(Skip="Concept only")] + [Fact(Skip = "Concept only")] public async void GivenRecentlyDeletedEndpointWhenSendingPingThenShouldReturn400() { From ec04eb8e65bbc8f3a22e9d735de75950812dd9ed Mon Sep 17 00:00:00 2001 From: Sascha Doemer Date: Mon, 19 Aug 2024 14:18:55 +0200 Subject: [PATCH 5/9] Refactor variable declaration in PingServiceTest Simplify variable declaration from explicit type to 'var' in PingServiceTest. This change promotes readability and adheres to modern C# coding conventions. --- .../Service/Messaging/Mqtt/PingServiceTest.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/agrirouter-sdk-dotnet-standard-test/Service/Messaging/Mqtt/PingServiceTest.cs b/agrirouter-sdk-dotnet-standard-test/Service/Messaging/Mqtt/PingServiceTest.cs index bf9ac5e..c377935 100644 --- a/agrirouter-sdk-dotnet-standard-test/Service/Messaging/Mqtt/PingServiceTest.cs +++ b/agrirouter-sdk-dotnet-standard-test/Service/Messaging/Mqtt/PingServiceTest.cs @@ -47,9 +47,8 @@ public async void { messageReceived = true; - MessageResponse msg = - JsonConvert.DeserializeObject( - Encoding.UTF8.GetString(e.ApplicationMessage.Payload)); + var msg = JsonConvert.DeserializeObject( + Encoding.UTF8.GetString(e.ApplicationMessage.Payload)); var decodedMessage = DecodeMessageService.Decode(msg.Command.Message); Assert.Equal(200, decodedMessage.ResponseEnvelope.ResponseCode); From 379c04dd897ecdd78332b2477d9d892ac3d5f490 Mon Sep 17 00:00:00 2001 From: Sascha Doemer Date: Mon, 19 Aug 2024 14:19:51 +0200 Subject: [PATCH 6/9] Update skip reason for PingServiceTest Clarify the reason for skipping the PingServiceTest fact. The updated message highlights that a deleted endpoint cannot be automatically tested and requires manual actions. --- .../Service/Messaging/Mqtt/PingServiceTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agrirouter-sdk-dotnet-standard-test/Service/Messaging/Mqtt/PingServiceTest.cs b/agrirouter-sdk-dotnet-standard-test/Service/Messaging/Mqtt/PingServiceTest.cs index c377935..251c8a7 100644 --- a/agrirouter-sdk-dotnet-standard-test/Service/Messaging/Mqtt/PingServiceTest.cs +++ b/agrirouter-sdk-dotnet-standard-test/Service/Messaging/Mqtt/PingServiceTest.cs @@ -67,7 +67,7 @@ public async void OnboardResponseIntegrationService.Read(Identifier.Mqtt.CommunicationUnit.SingleEndpointWithP12Certificate); - [Fact(Skip = "Concept only")] + [Fact(Skip = "Concept only: A deleted endpoint can not be tested automatically and requires some manual actions.")] public async void GivenRecentlyDeletedEndpointWhenSendingPingThenShouldReturn400() { From 85d7789f9b27006f59e2c81467ff8c1ec110bce2 Mon Sep 17 00:00:00 2001 From: Sascha Doemer Date: Mon, 19 Aug 2024 14:20:19 +0200 Subject: [PATCH 7/9] Refactor test method for deleted endpoint handling Updated PingServiceTest.cs to refactor a test method for better readability. Changed variable declaration and initialization style for consistency. Kept skip attribute message format consistent across tests. --- .../Service/Messaging/Mqtt/PingServiceTest.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/agrirouter-sdk-dotnet-standard-test/Service/Messaging/Mqtt/PingServiceTest.cs b/agrirouter-sdk-dotnet-standard-test/Service/Messaging/Mqtt/PingServiceTest.cs index 251c8a7..f4ee642 100644 --- a/agrirouter-sdk-dotnet-standard-test/Service/Messaging/Mqtt/PingServiceTest.cs +++ b/agrirouter-sdk-dotnet-standard-test/Service/Messaging/Mqtt/PingServiceTest.cs @@ -67,7 +67,8 @@ public async void OnboardResponseIntegrationService.Read(Identifier.Mqtt.CommunicationUnit.SingleEndpointWithP12Certificate); - [Fact(Skip = "Concept only: A deleted endpoint can not be tested automatically and requires some manual actions.")] + [Fact(Skip = + "Concept only: A deleted endpoint can not be tested automatically and requires some manual actions.")] public async void GivenRecentlyDeletedEndpointWhenSendingPingThenShouldReturn400() { @@ -98,9 +99,8 @@ public async void { messageReceived = true; - MessageResponse msg = - JsonConvert.DeserializeObject( - Encoding.UTF8.GetString(e.ApplicationMessage.Payload)); + var msg = JsonConvert.DeserializeObject( + Encoding.UTF8.GetString(e.ApplicationMessage.Payload)); var decodedMessage = DecodeMessageService.Decode(msg.Command.Message); // your own application should remove the endpoint from your endpoint list/registry now! From 7c6ea047f2370348690f7321f76060910689b214 Mon Sep 17 00:00:00 2001 From: Sascha Doemer Date: Mon, 19 Aug 2024 14:20:47 +0200 Subject: [PATCH 8/9] Simplify imports in PingServiceTest.cs Removed unused using directives in PingServiceTest.cs to clean up the code. This helps improve readability and maintainability by excluding unnecessary dependencies. --- .../Service/Messaging/Mqtt/PingServiceTest.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/agrirouter-sdk-dotnet-standard-test/Service/Messaging/Mqtt/PingServiceTest.cs b/agrirouter-sdk-dotnet-standard-test/Service/Messaging/Mqtt/PingServiceTest.cs index f4ee642..3f6d2b3 100644 --- a/agrirouter-sdk-dotnet-standard-test/Service/Messaging/Mqtt/PingServiceTest.cs +++ b/agrirouter-sdk-dotnet-standard-test/Service/Messaging/Mqtt/PingServiceTest.cs @@ -1,22 +1,17 @@ using System; -using System.Collections.Generic; using System.Text; using System.Threading.Tasks; -using Agrirouter.Request.Payload.Endpoint; -using Agrirouter.Api.Definitions; +using Agrirouter.Api.Dto.Messaging; using Agrirouter.Api.Dto.Onboard; using Agrirouter.Api.Service.Parameters; -using Agrirouter.Api.Service.Parameters.Inner; using Agrirouter.Impl.Service.Common; using Agrirouter.Impl.Service.Messaging; using Agrirouter.Test.Data; using Agrirouter.Test.Helper; using MQTTnet; using MQTTnet.Client; -using Xunit; -using Agrirouter.Api.Dto.Messaging; using Newtonsoft.Json; -using Xunit.Abstractions; +using Xunit; namespace Agrirouter.Test.Service.Messaging.Mqtt { From 8d23e234565348c8d1a1587c5a6dd311c4b68379 Mon Sep 17 00:00:00 2001 From: Sascha Doemer Date: Mon, 19 Aug 2024 14:21:25 +0200 Subject: [PATCH 9/9] Remove unused import in PingService.cs Eliminated an unnecessary import statement for `Agrirouter.Feed.Request` in PingService.cs to clean up the code. This change helps in maintaining clarity and avoiding potential confusion with unused references. --- .../Service/Messaging/PingService.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/agrirouter-sdk-dotnet-standard-impl/Service/Messaging/PingService.cs b/agrirouter-sdk-dotnet-standard-impl/Service/Messaging/PingService.cs index 7978a9c..26dca44 100644 --- a/agrirouter-sdk-dotnet-standard-impl/Service/Messaging/PingService.cs +++ b/agrirouter-sdk-dotnet-standard-impl/Service/Messaging/PingService.cs @@ -5,7 +5,6 @@ using Agrirouter.Api.Dto.Messaging; using Agrirouter.Api.Service.Messaging; using Agrirouter.Api.Service.Parameters; -using Agrirouter.Feed.Request; using Agrirouter.Impl.Service.Common; using Agrirouter.Request; using Google.Protobuf;