Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(sparkplug): added Sparkplug B Protobuf Payload support and utility classes #5072

Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/target
/bin
/lib
.vscode
generated-sources/
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ Bundle-Name: Sparkplug MQTT Cloud Connection Provider
Bundle-SymbolicName: org.eclipse.kura.cloudconnection.sparkplug.mqtt.provider
Bundle-Version: 1.0.0.qualifier
Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.8))"
Import-Package: org.eclipse.kura;version="[1.0,2.0)",
org.eclipse.kura.configuration;version="[1.1,2.0)",
Import-Package: com.google.protobuf;version="[3.0,4.0]",
org.eclipse.kura;version="[1.0,2.0)",
org.eclipse.kura.cloud;version="[1.1,2.0)",
org.eclipse.kura.cloudconnection;version="[1.0,1.1)",
org.eclipse.kura.cloudconnection.factory;version="[1.0,1.1)",
Expand All @@ -14,9 +14,11 @@ Import-Package: org.eclipse.kura;version="[1.0,2.0)",
org.eclipse.kura.cloudconnection.publisher;version="[1.0,1.1)",
org.eclipse.kura.cloudconnection.subscriber;version="[1.0,1.1)",
org.eclipse.kura.cloudconnection.subscriber.listener;version="[1.0,2.0)",
org.eclipse.kura.configuration;version="[1.1,2.0)",
org.eclipse.kura.data;version="[1.0,2.0)",
org.eclipse.kura.data.listener;version="[1.0,2.0)",
org.eclipse.kura.data.transport.listener;version="[1.0,2.0)",
org.eclipse.kura.type;version="[1.1,2.0)",
org.osgi.framework;version="1.8.0",
org.osgi.service.component;version="1.2.0",
org.osgi.service.event;version="1.3.1",
Expand All @@ -25,3 +27,4 @@ Bundle-ActivationPolicy: lazy
Service-Component: OSGI-INF/*.xml
Bundle-Vendor: Eclipse Kura
Bundle-License: Eclipse Public License v2.0
Bundle-ClassPath: .
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
source.. = src/main/java
source.. = src/main/java/,\
generated-sources/src/main/java/
output.. = target/
bin.includes = META-INF/,\
.,\
OSGI-INF/,\
about.html,
about.html
106 changes: 100 additions & 6 deletions kura/org.eclipse.kura.cloudconnection.sparkplug.mqtt.provider/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
Eurotech

-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
Expand All @@ -21,15 +23,107 @@
<version>5.5.0-SNAPSHOT</version>
</parent>

<artifactId>org.eclipse.kura.cloudconnection.sparkplug.mqtt.provider</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>

<properties>
<kura.basedir>${project.basedir}/..</kura.basedir>
<sonar.coverage.jacoco.xmlReportPaths>
${project.basedir}/../test/org.eclipse.kura.cloudconnection.sparkplug.mqtt.provider.test/target/site/jacoco-aggregate/jacoco.xml
</sonar.coverage.jacoco.xmlReportPaths>
<sonar.coverage.exclusions>${project.basedir}/generated-sources/**/*</sonar.coverage.exclusions>
<sonar.exclusions>${project.basedir}/generated-sources/**/*</sonar.exclusions>
<protoc.version>3.21.12</protoc.version>
</properties>

</project>
<artifactId>org.eclipse.kura.cloudconnection.sparkplug.mqtt.provider</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>

<build>
<plugins>

<plugin>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.7.1</version>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>detect</goal>
</goals>
</execution>
</executions>
</plugin>

<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<configuration>
<protocArtifact>
com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}
</protocArtifact>
</configuration>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.5.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<!--<source>${project.build.directory}/generated-sources/protobuf/java</source>-->
marcellorinaldo marked this conversation as resolved.
Show resolved Hide resolved
<source>${project.basedir}/generated-sources/src/main/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>

<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
<executions>
<execution>
<id>copy-protobuf-resource</id>
<phase>generate-sources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.basedir}/generated-sources/src/main</outputDirectory>
<resources>
<resource>
<directory>${project.build.directory}/generated-sources/protobuf/</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<configuration>
<excludes>${project.basedir}/generated-sources/**/*</excludes>
</configuration>
</plugin>

</plugins>
</build>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
/*******************************************************************************
* Copyright (c) 2023 Eurotech and/or its affiliates and others
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Eurotech
*******************************************************************************/
package org.eclipse.kura.cloudconnection.sparkplug.mqtt.message;

import java.math.BigInteger;
import java.util.Date;

import org.eclipse.kura.type.TypedValue;
import org.eclipse.tahu.protobuf.SparkplugBProto.DataType;
import org.eclipse.tahu.protobuf.SparkplugBProto.Payload;

import com.google.protobuf.ByteString;

public class SparkplugBProtobufPayloadBuilder {

public static final String BDSEQ_METRIC_NAME = "bdSeq";

private Payload.Builder payloadBuilder = Payload.newBuilder();

public SparkplugBProtobufPayloadBuilder withMetric(String name, Object value, DataType dataType, long timestamp) {
Payload.Metric.Builder metricBuilder = Payload.Metric.newBuilder();
metricBuilder.setName(name);
metricBuilder.setDatatype(dataType.getNumber());
metricBuilder.setTimestamp(timestamp);

switch (dataType) {
case Boolean:
metricBuilder.setBooleanValue((Boolean) value);
break;
case Bytes:
metricBuilder.setBytesValue(ByteString.copyFrom((byte[]) value));
break;
case Double:
metricBuilder.setDoubleValue((Double) value);
break;
case Float:
metricBuilder.setFloatValue((Float) value);
break;
case Int8:
metricBuilder.setIntValue((Byte) value);
break;
case Int16:
metricBuilder.setIntValue((Short) value);
break;
case Int32:
metricBuilder.setIntValue((Integer) value);
break;
case Int64:
metricBuilder.setLongValue((Long) value);
break;
case String:
case Text:
case UUID:
metricBuilder.setStringValue((String) value);
break;
case DateTime:
metricBuilder.setLongValue(((Date) value).getTime());
break;
case UInt8:
metricBuilder.setIntValue(Short.toUnsignedInt((Short) value));
break;
case UInt16:
metricBuilder.setIntValue((int) Integer.toUnsignedLong((Integer) value));
break;
case UInt32:
metricBuilder.setLongValue(Long.parseUnsignedLong(Long.toUnsignedString((Long) value)));
break;
case UInt64:
metricBuilder.setLongValue(((BigInteger) value).longValue());
break;
case DataSet:
case Template:
case PropertySet:
case PropertySetList:
case File:
case BooleanArray:
case DateTimeArray:
case UInt8Array:
case UInt64Array:
case UInt32Array:
case UInt16Array:
case StringArray:
case Int8Array:
case Int64Array:
case Int32Array:
case Int16Array:
case FloatArray:
case DoubleArray:
case Unknown:
default:
throw new UnsupportedOperationException("DataType " + dataType.toString() + " not implemented");
}

this.payloadBuilder.addMetrics(metricBuilder.build());

return this;
}

public <T> SparkplugBProtobufPayloadBuilder withMetric(String name, TypedValue<T> value, long timestamp) {
DataType sparkplugDataType;

switch (value.getType()) {
case BOOLEAN:
sparkplugDataType = DataType.Boolean;
break;
case BYTE_ARRAY:
sparkplugDataType = DataType.Bytes;
break;
case DOUBLE:
sparkplugDataType = DataType.Double;
break;
case FLOAT:
sparkplugDataType = DataType.Float;
break;
case INTEGER:
sparkplugDataType = DataType.Int32;
break;
case LONG:
sparkplugDataType = DataType.Int64;
break;
case STRING:
sparkplugDataType = DataType.String;
break;
default:
sparkplugDataType = DataType.Unknown;
break;
}

return this.withMetric(name, value.getValue(), sparkplugDataType, timestamp);
}

public <T> SparkplugBProtobufPayloadBuilder withMetric(String name, TypedValue<T> value) {
return this.withMetric(name, value, new Date().getTime());
}
marcellorinaldo marked this conversation as resolved.
Show resolved Hide resolved

public SparkplugBProtobufPayloadBuilder withBdSeq(long bdSeq, long timestamp) {
Payload.Metric.Builder bdSeqMetric = Payload.Metric.newBuilder();
bdSeqMetric.setName(BDSEQ_METRIC_NAME);
bdSeqMetric.setLongValue(bdSeq);
bdSeqMetric.setDatatype(DataType.Int64.getNumber());
bdSeqMetric.setTimestamp(timestamp);

this.payloadBuilder.addMetrics(bdSeqMetric.build());
return this;
}

public SparkplugBProtobufPayloadBuilder withSeq(long seq) {
this.payloadBuilder.setSeq(seq);
return this;
}

public SparkplugBProtobufPayloadBuilder withTimestamp(long timestamp) {
this.payloadBuilder.setTimestamp(timestamp);
return this;
}

public Payload buildPayload() {
return this.payloadBuilder.build();
}

public byte[] build() {
return this.buildPayload().toByteArray();
}

}
Loading