Skip to content
This repository was archived by the owner on May 8, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,7 @@ buildNumber.properties
.settings

# GENERATED #
src/main/generated
src/main/generated

# LCK #
*.lck

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,13 @@

/**
* Abstraction of the QA environment, currently no overrides because the default is QA already.
*
* @deprecated This class is deprecated and will be removed in future versions.
* The new agrirouter environment will be the default to use
*/
@Deprecated(since = "3.2.0", forRemoval = true)
public abstract class QA implements Environment {

private static final String ENV_BASE_URL = "https://agrirouter-qa.cfapps.eu10.hana.ondemand.com";
private static final String ENV_BASE_URL = "https://app.qa.agrirouter.farm";
private static final String API_PREFIX = "/api/v1.0";
private static final String REGISTRATION_SERVICE_URL =
"https://agrirouter-registration-service-hubqa-eu10.cfapps.eu10.hana.ondemand.com";
"https://endpoint-service.qa.agrirouter.farm";

@Override
public String getEnvironmentBaseUrl() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.dke.data.agrirouter.api.service.messaging.mqtt;

import com.dke.data.agrirouter.api.service.parameters.PingParameters;

/**
* Service interface for pinging the health interface.
*/
public interface PingService extends MessagingService<PingParameters> {
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ enum class SystemMessageType(private val key: String, private val typeUrl: Strin
DKE_FEED_CONFIRM("dke:feed_confirm", FeedRequests.MessageConfirm.getDescriptor().fullName),
DKE_FEED_DELETE("dke:feed_delete", FeedRequests.MessageDelete.getDescriptor().fullName),
DKE_FEED_MESSAGE_QUERY("dke:feed_message_query", FeedRequests.MessageQuery.getDescriptor().fullName),
DKE_FEED_HEADER_QUERY("dke:feed_header_query", FeedRequests.MessageQuery.getDescriptor().fullName);
DKE_FEED_HEADER_QUERY("dke:feed_header_query", FeedRequests.MessageQuery.getDescriptor().fullName),
DKE_PING("dke:ping", "");

override fun getKey(): String {
return key
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.dke.data.agrirouter.api.service.parameters

import com.dke.data.agrirouter.api.dto.onboard.OnboardingResponse
import com.dke.data.agrirouter.api.service.ParameterValidation
import com.dke.data.agrirouter.api.service.parameters.base.AbstractParameterBase

/**
* Parameters class. Encapsulation for the services.
*/
class PingParameters : AbstractParameterBase(), ParameterValidation {

var onboardingResponse: OnboardingResponse? = null

override fun technicalValidation() {
nullCheck("onboardingResponse", onboardingResponse)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.dke.data.agrirouter.api.service.parameters.*;
import com.dke.data.agrirouter.api.util.TimestampUtil;
import com.dke.data.agrirouter.impl.common.MessageIdService;
import com.google.protobuf.ByteString;

import java.util.Objects;

Expand Down Expand Up @@ -450,10 +451,45 @@ default EncodedMessage encode(CloudOffboardingParameters parameters) {
return new EncodedMessage(applicationMessageID, encodedMessage);
}

/**
* Encode a message to send a message.
*
* @param parameters -
* @return -
*/
default EncodedMessage encode(PingParameters parameters) {
final var applicationMessageID =
parameters.getApplicationMessageId() == null
? MessageIdService.generateMessageId()
: parameters.getApplicationMessageId();

var messageContent = ""; // No content for ping messages.

var messageHeaderParameters = new MessageHeaderParameters();
messageHeaderParameters.setApplicationMessageId(applicationMessageID);
messageHeaderParameters.setTechnicalMessageType(SystemMessageType.DKE_PING);
messageHeaderParameters.setMode(Request.RequestEnvelope.Mode.DIRECT);
messageHeaderParameters.setMetadata(MessageOuterClass.Metadata.newBuilder().build());

setSequenceNumber(
messageHeaderParameters,
parameters.getSequenceNumber(),
parameters.getOnboardingResponse());
var payloadParameters = new PayloadParameters();
payloadParameters.setTypeUrl(SystemMessageType.DKE_PING.getTypeUrl());

payloadParameters.setValue(ByteString.copyFrom(messageContent.getBytes()));

var encodedMessage =
this.getEncodeMessageService().encode(messageHeaderParameters, payloadParameters);
return new EncodedMessage(applicationMessageID, encodedMessage);
}

/**
* Get the service to encode messages.
*
* @return -
*/
EncodeMessageService getEncodeMessageService();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package com.dke.data.agrirouter.impl.messaging.mqtt;

import com.dke.data.agrirouter.api.exception.CouldNotSendMqttMessageException;
import com.dke.data.agrirouter.api.messaging.MqttAsyncMessageSendingResult;
import com.dke.data.agrirouter.api.service.messaging.encoding.EncodeMessageService;
import com.dke.data.agrirouter.api.service.messaging.mqtt.PingService;
import com.dke.data.agrirouter.api.service.parameters.PingParameters;
import com.dke.data.agrirouter.api.service.parameters.SendMessageParameters;
import com.dke.data.agrirouter.impl.messaging.MessageBodyCreator;
import com.dke.data.agrirouter.impl.messaging.MessageEncoder;
import com.dke.data.agrirouter.impl.messaging.MqttService;
import com.dke.data.agrirouter.impl.messaging.encoding.EncodeMessageServiceImpl;
import org.eclipse.paho.client.mqttv3.IMqttClient;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;

import java.util.Collections;
import java.util.Objects;

/**
* Service implementation.
*/
public class PingServiceImpl extends MqttService
implements PingService, MessageBodyCreator, MessageEncoder {

private final EncodeMessageService encodeMessageService;

public PingServiceImpl(IMqttClient mqttClient) {
super(mqttClient);
this.encodeMessageService = new EncodeMessageServiceImpl();
}

@Override
public String send(PingParameters parameters) {
try {
var encodedMessage = this.encode(parameters);
var sendMessageParameters = new SendMessageParameters();
sendMessageParameters.setOnboardingResponse(parameters.getOnboardingResponse());
sendMessageParameters.setEncodedMessages(
Collections.singletonList(encodedMessage.getEncodedMessage()));
var messageAsJson = this.createMessageBody(sendMessageParameters);
var payload = messageAsJson.getBytes();
this.getMqttClient()
.publish(
Objects.requireNonNull(parameters.getOnboardingResponse())
.getConnectionCriteria()
.getMeasures(),
new MqttMessage(payload));
return encodedMessage.getApplicationMessageID();
} catch (MqttException e) {
throw new CouldNotSendMqttMessageException(e);
}
}

@Override
public MqttAsyncMessageSendingResult sendAsync(PingParameters parameters) {
throw new RuntimeException("Not implemented, please use the synchronous send method.");
}

@Override
public EncodeMessageService getEncodeMessageService() {
return encodeMessageService;
}
}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"deviceAlternateId":"cdee8e0c-05b8-4252-9da3-977239e54adc","capabilityAlternateId":"3035ec70-dca1-4d71-a000-e79eb5891f81","sensorAlternateId":"f658fa1a-fef3-43bc-87e7-4499858ac609","connectionCriteria":{"gatewayId":"3","measures":"https://dke-qa.eu10.cp.iot.sap/iot/gateway/rest/measures/cdee8e0c-05b8-4252-9da3-977239e54adc","commands":"https://dke-qa.eu10.cp.iot.sap/iot/gateway/rest/commands/cdee8e0c-05b8-4252-9da3-977239e54adc"},"authentication":{"type":"P12","secret":"FNG3X?X4gJwZlut!ebZ3rigVfQCyOrOqhCj7","certificate":"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"}}
{"deviceAlternateId":"5dade5c9-dcca-4bf1-be22-f7f61ed90ea7","capabilityAlternateId":"5dade5c9-dcca-4bf1-be22-f7f61ed90ea7","sensorAlternateId":"5dade5c9-dcca-4bf1-be22-f7f61ed90ea7","connectionCriteria":{"gatewayId":"3","measures":"https://gateway-service.qa.agrirouter.farm/inbox/5dade5c9-dcca-4bf1-be22-f7f61ed90ea7","commands":"https://gateway-service.qa.agrirouter.farm/outbox/5dade5c9-dcca-4bf1-be22-f7f61ed90ea7"},"authentication":{"type":"P12","secret":"Ga4OM1C4tgWGILrF","certificate":"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\u003d"}}
Loading