Skip to content

Commit

Permalink
add dke:ping (#138)
Browse files Browse the repository at this point in the history
* add dke:ping

* fix mistake

* cleanup

* 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.

* 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.

* 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.

* 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.

* 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.

* 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.

---------

Co-authored-by: Sascha Doemer <[email protected]>
  • Loading branch information
oliverrahner and saschadoemer authored Aug 20, 2024
1 parent c4147ed commit b3c2183
Show file tree
Hide file tree
Showing 5 changed files with 221 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ public static class TechnicalMessageTypes
/// </summary>
public static string DkeSubscription => "dke:subscription";

/// <summary>
/// Type 'dke:ping'.
/// </summary>
public static string DkePing => "dke:ping";

/// <summary>
/// Type 'dke:cloud_onboard_endpoints'.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Agrirouter.Api.Service.Parameters;

namespace Agrirouter.Api.Service.Messaging
{
/// <summary>
/// Send a ping message to check if the endpoint still exists.
/// </summary>
public interface IPingService : IMessagingService<PingParameters>, IEncodeMessageService<PingParameters>
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Agrirouter.Api.Service.Parameters
{
public class PingParameters : MessageParameters
{
// no additional fields, but more verbosity with explicit class definition
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
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.Impl.Service.Common;
using Agrirouter.Request;
using Google.Protobuf;

namespace Agrirouter.Impl.Service.Messaging
{
/// <summary>
/// Service to list the endpoints connected to an endpoint.
/// </summary>
public class PingService: IPingService
{
private readonly IMessagingService<MessagingParameters> _messagingService;

/// <summary>
/// Constructor.
/// </summary>
/// <param name="messagingService"></param>
public PingService(IMessagingService<MessagingParameters> messagingService)
{
_messagingService = messagingService;
}

/// <summary>
/// Please see base class declaration for documentation.
/// </summary>
/// <param name="pingParameters">-</param>
/// <returns>-</returns>
public MessagingResult Send(PingParameters pingParameters)
{
var encodedMessages = new List<string> {Encode(pingParameters).Content};
var messagingParameters = pingParameters.BuildMessagingParameter(encodedMessages);
return _messagingService.Send(messagingParameters);
}

/// <summary>
/// Please see base class declaration for documentation.
/// </summary>
/// <param name="pingParameters">-</param>
/// <returns>-</returns>
public Task<MessagingResult> SendAsync(PingParameters pingParameters)
{
var encodedMessages = new List<string> {Encode(pingParameters).Content};
var messagingParameters = pingParameters.BuildMessagingParameter(encodedMessages);
return _messagingService.SendAsync(messagingParameters);
}

/// <summary>
/// Please see <seealso cref="IEncodeMessageService{T}.Encode" /> for documentation.
/// </summary>
/// <param name="pingParameters">-</param>
/// <returns>-</returns>
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 = "",
Value = ByteString.Empty
};

var encodedMessage = new EncodedMessage
{
Id = Guid.NewGuid().ToString(),
Content = EncodeMessageService.Encode(messageHeaderParameters, messagePayloadParameters)
};

return encodedMessage;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
using System;
using System.Text;
using System.Threading.Tasks;
using Agrirouter.Api.Dto.Messaging;
using Agrirouter.Api.Dto.Onboard;
using Agrirouter.Api.Service.Parameters;
using Agrirouter.Impl.Service.Common;
using Agrirouter.Impl.Service.Messaging;
using Agrirouter.Test.Data;
using Agrirouter.Test.Helper;
using MQTTnet;
using MQTTnet.Client;
using Newtonsoft.Json;
using Xunit;

namespace Agrirouter.Test.Service.Messaging.Mqtt
{
[Collection("Integrationtest")]
public class PingServiceTest : AbstractIntegrationTestForCommunicationUnits
{
[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;
var msg = JsonConvert.DeserializeObject<MessageResponse>(
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: A deleted endpoint can not be tested automatically and requires some manual actions.")]
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;
var msg = JsonConvert.DeserializeObject<MessageResponse>(
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);
}
}
}

0 comments on commit b3c2183

Please sign in to comment.