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
18 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
12 changes: 6 additions & 6 deletions .github/workflows/continuous_integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ jobs:
build_jdk17:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4.2.2
- name: Set up JDK 17
uses: actions/setup-java@v3
uses: actions/setup-java@v4.5.0
with:
java-version: 17
distribution: zulu
Expand All @@ -25,9 +25,9 @@ jobs:
build_jdk21:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4.2.2
- name: Set up JDK 21
uses: actions/setup-java@v3
uses: actions/setup-java@v4.5.0
with:
java-version: 21
distribution: zulu
Expand All @@ -38,9 +38,9 @@ jobs:
integration_test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4.2.2
- name: Set up JDK 17
uses: actions/setup-java@v3
uses: actions/setup-java@v4.5.0
with:
java-version: 17
distribution: zulu
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,8 @@ buildNumber.properties
# GENERATED #
src/main/generated

# LOCAL SETTINGS #
ci/local-settings.xml

# LCK #
*.lck
10 changes: 9 additions & 1 deletion agrirouter-sdk-java-api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>com.agrirouter.api</groupId>
<artifactId>agrirouter-sdk-java</artifactId>
<version>3.2.2</version>
<version>3.3.0</version>
</parent>
<name>AGRIROUTER SDK JAVA - API</name>
<artifactId>agrirouter-sdk-java-api</artifactId>
Expand Down Expand Up @@ -48,6 +48,14 @@
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
</dependency>
<dependency>
<groupId>com.hivemq</groupId>
<artifactId>hivemq-mqtt-client</artifactId>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.dke.data.agrirouter.api.mqtt;

import com.hivemq.client.mqtt.mqtt3.Mqtt3AsyncClient;

/**
* A wrapper around HiveMQ's Mqtt3AsyncClient that implements the MqttClientWrapper interface.
* This class is responsible for publishing messages to a specified MQTT topic using the
* provided Mqtt3AsyncClient.
*/
public class HiveMqttClientWrapper implements MqttClientWrapper {

private final Mqtt3AsyncClient mqttClient;

public HiveMqttClientWrapper(Mqtt3AsyncClient mqttClient) {
this.mqttClient = mqttClient;
}

@Override
public void publish(String measures, byte[] payload) {
this.mqttClient.publishWith().topic(measures).payload(payload).send();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.dke.data.agrirouter.api.mqtt;

/**
* Interface representing an MQTT client wrapper for publishing messages.
* Implementations of this interface should define how to publish messages
* to a specific topic with a given payload.
*/
public interface MqttClientWrapper {

/**
* Publishes a message to a specific topic with a given payload.
*
* @param measures the topic to which the message should be published
* @param payload the byte array representing the content of the message
*/
void publish(String measures, byte[] payload);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.dke.data.agrirouter.api.mqtt;

import com.dke.data.agrirouter.api.exception.CouldNotSendMqttMessageException;
import org.eclipse.paho.client.mqttv3.IMqttClient;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;

/**
* PahoMqttClientWrapper is an implementation of the MqttClientWrapper interface,
* providing a wrapper around an instance of IMqttClient from the Paho MQTT library.
* This class handles the publishing of MQTT messages to specified topics with a given payload.
*/
public class PahoMqttClientWrapper implements MqttClientWrapper {

private final IMqttClient mqttClient;

public PahoMqttClientWrapper(IMqttClient mqttClient) {
this.mqttClient = mqttClient;
}

@Override
public void publish(String measures, byte[] payload) {
try {
this.mqttClient.publish(measures, new MqttMessage(payload));
} catch (MqttException e) {
throw new CouldNotSendMqttMessageException(e);
}
}

}
2 changes: 1 addition & 1 deletion agrirouter-sdk-java-convenience/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>com.agrirouter.api</groupId>
<artifactId>agrirouter-sdk-java</artifactId>
<version>3.2.2</version>
<version>3.3.0</version>
</parent>
<name>AGRIROUTER SDK JAVA - CONVENIENCE</name>
<artifactId>agrirouter-sdk-java-convenience</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package com.dke.data.agrirouter.convenience.mqtt.hive;

import com.dke.data.agrirouter.api.dto.onboard.OnboardingResponse;
import com.dke.data.agrirouter.api.dto.onboard.RouterDevice;
import com.dke.data.agrirouter.api.env.Environment;
import com.dke.data.agrirouter.api.exception.CouldNotCreateMqttClientException;
import com.dke.data.agrirouter.impl.EnvironmentalService;
import com.hivemq.client.mqtt.MqttClient;
import com.hivemq.client.mqtt.mqtt3.Mqtt3AsyncClient;
import org.apache.commons.lang3.StringUtils;

import java.util.Objects;

/**
* Service to create a MQTT client using the given onboarding response.
*/
@SuppressWarnings("unused")
public class HiveMqttClientService extends EnvironmentalService {

/**
* Constructor for an environmental service.
*
* @param environment -
*/
public HiveMqttClientService(Environment environment) {
super(environment);
}

/**
* Creates a MQTT client using the given onboarding response. Communication relies on given root
* certificates in an external keystore. The keystore with the root certificates is not created
* locally.
*
* @param onboardingResponse -
* @return -
*/
public Mqtt3AsyncClient create(OnboardingResponse onboardingResponse) {
return this.createMqttClient(
onboardingResponse.getConnectionCriteria().getHost(),
onboardingResponse.getConnectionCriteria().getPort(),
onboardingResponse.getConnectionCriteria().getClientId());
}

/**
* Creates a MQTT client using the given router Device. Communication relies on given root
* certificates in an external keystore. The keystore with the root certificates is not created
* locally.
*
* @param routerDevice -
* @return -
*/
public Mqtt3AsyncClient create(RouterDevice routerDevice) {
return this.createMqttClient(
routerDevice.getConnectionCriteria().getHost(),
String.valueOf(routerDevice.getConnectionCriteria().getPort()),
routerDevice.getConnectionCriteria().getClientId());
}

private Mqtt3AsyncClient createMqttClient(String host, String port, String clientId) {
if (StringUtils.isAnyBlank(host, port, clientId)) {
throw new CouldNotCreateMqttClientException(
"Currently there are parameters missing. Did you onboard correctly - host, port or client id are missing.");
}
return MqttClient.builder()
.useMqttVersion3()
.identifier(Objects.requireNonNull(clientId))
.serverHost(host)
.serverPort(Integer.parseInt(port))
.buildAsync();
}
}
2 changes: 1 addition & 1 deletion agrirouter-sdk-java-impl/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>com.agrirouter.api</groupId>
<artifactId>agrirouter-sdk-java</artifactId>
<version>3.2.2</version>
<version>3.3.0</version>
</parent>
<name>AGRIROUTER SDK JAVA - IMPL</name>
<artifactId>agrirouter-sdk-java-impl</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
package com.dke.data.agrirouter.impl.messaging;

import org.eclipse.paho.client.mqttv3.IMqttClient;
import com.dke.data.agrirouter.api.mqtt.MqttClientWrapper;

/**
* Base class which holds the MQTT client with the connection provided by the provider.
*/
public class MqttService {

private final IMqttClient mqttClient;
private final MqttClientWrapper mqttClientWrapper;

public MqttService(IMqttClient mqttClient) {
this.mqttClient = mqttClient;
public MqttService(MqttClientWrapper mqttClientWrapper) {
this.mqttClientWrapper = mqttClientWrapper;
}

protected IMqttClient getMqttClient() {
return mqttClient;
protected MqttClientWrapper getMqttClient() {
return mqttClientWrapper;
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
package com.dke.data.agrirouter.impl.messaging.helper.mqtt;

import com.dke.data.agrirouter.api.enums.TechnicalMessageType;
import com.dke.data.agrirouter.api.exception.CouldNotSendMqttMessageException;
import com.dke.data.agrirouter.api.mqtt.HiveMqttClientWrapper;
import com.dke.data.agrirouter.api.mqtt.PahoMqttClientWrapper;
import com.dke.data.agrirouter.api.service.messaging.encoding.EncodeMessageService;
import com.dke.data.agrirouter.api.service.parameters.MessageQueryParameters;
import com.dke.data.agrirouter.api.service.parameters.SendMessageParameters;
import com.dke.data.agrirouter.impl.messaging.MessageEncoder;
import com.dke.data.agrirouter.impl.messaging.MqttService;
import com.dke.data.agrirouter.impl.messaging.helper.QueryAllMessagesParameterCreator;
import com.dke.data.agrirouter.impl.messaging.rest.MessageSender;
import com.hivemq.client.mqtt.mqtt3.Mqtt3AsyncClient;
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;
Expand All @@ -26,41 +26,44 @@ public MessageQueryHelperService(
IMqttClient mqttClient,
EncodeMessageService encodeMessageService,
TechnicalMessageType technicalMessageType) {
super(mqttClient);
this.logMethodBegin();
super(new PahoMqttClientWrapper(mqttClient));
this.encodeMessageService = encodeMessageService;
this.technicalMessageType = technicalMessageType;
}

public MessageQueryHelperService(
Mqtt3AsyncClient mqttClient,
EncodeMessageService encodeMessageService,
TechnicalMessageType technicalMessageType) {
super(new HiveMqttClientWrapper(mqttClient));
this.encodeMessageService = encodeMessageService;
this.technicalMessageType = technicalMessageType;
this.logMethodEnd();
}

public String send(MessageQueryParameters parameters) {
this.logMethodBegin(parameters);

this.getNativeLogger().trace("Validate parameters.");
parameters.validate();
try {
this.getNativeLogger().trace("Encode message.");
var encodedMessage = this.encode(this.technicalMessageType, parameters);
this.getNativeLogger().trace("Encode message.");
var encodedMessage = this.encode(this.technicalMessageType, parameters);

this.getNativeLogger().trace("Build message parameters.");
var sendMessageParameters = new SendMessageParameters();
sendMessageParameters.setOnboardingResponse(parameters.getOnboardingResponse());
sendMessageParameters.setEncodedMessages(
Collections.singletonList(encodedMessage.getEncodedMessage()));
this.getNativeLogger().trace("Build message parameters.");
var sendMessageParameters = new SendMessageParameters();
sendMessageParameters.setOnboardingResponse(parameters.getOnboardingResponse());
sendMessageParameters.setEncodedMessages(
Collections.singletonList(encodedMessage.getEncodedMessage()));

this.getNativeLogger().trace("Send and fetch message response.");
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);
}
this.getNativeLogger().trace("Send and fetch message response.");
var messageAsJson = this.createMessageBody(sendMessageParameters);
var payload = messageAsJson.getBytes();
this.getMqttClient()
.publish(
Objects.requireNonNull(parameters.getOnboardingResponse())
.getConnectionCriteria()
.getMeasures(),
payload);
return encodedMessage.getApplicationMessageID();
}

@Override
Expand Down
Loading