You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@streampipes.apache.org by bo...@apache.org on 2024/03/04 15:39:14 UTC

(streampipes) branch support-hilscher-devices created (now cce9b45985)

This is an automated email from the ASF dual-hosted git repository.

bossenti pushed a change to branch support-hilscher-devices
in repository https://gitbox.apache.org/repos/asf/streampipes.git


      at cce9b45985 revert change

This branch includes the following new commits:

     new d78f6d5b60 tmp
     new eac774486a initial implementation
     new cce9b45985 revert change

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(streampipes) 02/03: initial implementation

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

bossenti pushed a commit to branch support-hilscher-devices
in repository https://gitbox.apache.org/repos/asf/streampipes.git

commit eac774486a1608cd4eb5e15330d7385109d00686
Author: bossenti <bo...@posteo.de>
AuthorDate: Mon Mar 4 16:37:51 2024 +0100

    initial implementation
---
 .../iiot/adapters/iolink/HilscherMqttAdapter.java  | 150 ++++++++++++++++++-
 .../iiot/adapters/iolink/IfmAlMqttAdapter.java     |   8 +-
 .../iolink/sensor/SensorVVB001Hilscher.java        | 131 +++++++++++++++++
 .../adapters/iolink/sensor/SensorVVB001Ifm.java    | 162 +++++++++++++++++++++
 .../documentation.md                               |  73 ++++++++++
 .../icon.png                                       | Bin 0 -> 9219 bytes
 .../strings.en                                     |  47 ++++++
 ...sorVVB001Test.java => SensorVVB001IfmTest.java} |  22 +--
 8 files changed, 575 insertions(+), 18 deletions(-)

diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/iolink/HilscherMqttAdapter.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/iolink/HilscherMqttAdapter.java
index 2f87d29cda..82fabac31c 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/iolink/HilscherMqttAdapter.java
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/iolink/HilscherMqttAdapter.java
@@ -19,18 +19,82 @@
 package org.apache.streampipes.connect.iiot.adapters.iolink;
 
 import org.apache.streampipes.commons.exceptions.connect.AdapterException;
+import org.apache.streampipes.commons.exceptions.connect.ParseException;
+import org.apache.streampipes.connect.iiot.adapters.iolink.sensor.IoLinkSensor;
+import org.apache.streampipes.connect.iiot.adapters.iolink.sensor.SensorVVB001Hilscher;
+import org.apache.streampipes.connect.iiot.adapters.iolink.sensor.SensorVVB001Ifm;
 import org.apache.streampipes.extensions.api.connect.IAdapterConfiguration;
 import org.apache.streampipes.extensions.api.connect.IEventCollector;
+import org.apache.streampipes.extensions.api.connect.IParser;
 import org.apache.streampipes.extensions.api.connect.StreamPipesAdapter;
 import org.apache.streampipes.extensions.api.connect.context.IAdapterGuessSchemaContext;
 import org.apache.streampipes.extensions.api.connect.context.IAdapterRuntimeContext;
 import org.apache.streampipes.extensions.api.extractor.IAdapterParameterExtractor;
+import org.apache.streampipes.extensions.api.extractor.IStaticPropertyExtractor;
+import org.apache.streampipes.extensions.connectors.mqtt.shared.MqttConfig;
+import org.apache.streampipes.extensions.connectors.mqtt.shared.MqttConnectUtils;
+import org.apache.streampipes.extensions.connectors.mqtt.shared.MqttConsumer;
+import org.apache.streampipes.extensions.management.connect.adapter.parser.JsonParsers;
+import org.apache.streampipes.extensions.management.connect.adapter.parser.json.JsonObjectParser;
+import org.apache.streampipes.model.AdapterType;
 import org.apache.streampipes.model.connect.guess.GuessSchema;
+import org.apache.streampipes.sdk.builder.adapter.AdapterConfigurationBuilder;
+import org.apache.streampipes.sdk.helpers.Labels;
+import org.apache.streampipes.sdk.helpers.Locales;
+import org.apache.streampipes.sdk.helpers.Options;
+import org.apache.streampipes.sdk.utils.Assets;
+
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.Map;
 
 public class HilscherMqttAdapter implements StreamPipesAdapter {
+
+  public static final String ID = "org.apache.streampipes.connect.iiot.adapters.hilscher";
+
+  private static final Logger LOG = LoggerFactory.getLogger(HilscherMqttAdapter.class);
+
+  private static final String FILTER_KEY = "Filter";
+  private static final String MESSAGES_KEY = "Messages";
+  private static final String PAYLOAD_KEY = "Payload";
+  private static final String PROCESS_DATA_KEY = "processDataInput";
+  private static final String SENSOR_TYPE = "sensor_type";
+
+  private static final String SENSOR_VVB001_LABEL = "VVB001";
+  private static final String SOURCE_KEY = "Source";
+  private final IParser parser;
+  private MqttConsumer mqttConsumer;
+  private MqttConfig mqttConfig;
+
+  private String selectedSensorName;
+
+  public HilscherMqttAdapter() {
+    parser = new JsonParsers(new JsonObjectParser());
+  }
+
   @Override
   public IAdapterConfiguration declareConfig() {
-    return null;
+
+    return AdapterConfigurationBuilder
+        .create(ID, 0, HilscherMqttAdapter::new)
+        .withLocales(Locales.EN)
+        .withAssets(Assets.DOCUMENTATION, Assets.ICON)
+        .withCategory(AdapterType.Generic, AdapterType.Manufacturing)
+        .requiredTextParameter(MqttConnectUtils.getBrokerUrlLabel())
+        .requiredAlternatives(MqttConnectUtils.getAccessModeLabel(), MqttConnectUtils.getAlternativesOne(),
+                              MqttConnectUtils.getAlternativesTwo()
+        )
+        .requiredSingleValueSelection(
+            Labels.withId(SENSOR_TYPE),
+            Options.from(SENSOR_VVB001_LABEL)
+        )
+        .requiredTextParameter(MqttConnectUtils.getTopicLabel())
+        .buildConfiguration();
   }
 
   @Override
@@ -39,7 +103,41 @@ public class HilscherMqttAdapter implements StreamPipesAdapter {
       IEventCollector collector,
       IAdapterRuntimeContext adapterRuntimeContext
   ) throws AdapterException {
+    this.applyConfiguration(extractor.getStaticPropertyExtractor());
+
+    var sensor = new SensorVVB001Hilscher();
+    this.mqttConsumer = new MqttConsumer(
+        this.mqttConfig,
+        (mqttEvent) -> {
+          try {
+            InputStream in = convertByte(mqttEvent);
+            parser.parse(in, (event) -> {
+                           var sensorValues = getProcessData(event);
+
+                           var parsedEvent = sensor.parseEvent(sensorValues);
+
+                           collector.collect(parsedEvent);
 
+                         }
+            );
+          } catch (ParseException e) {
+            LOG.error("Error during parsing of JSON message body: %s", mqttEvent);
+          }
+        }
+    );
+
+    Thread thread = new Thread(this.mqttConsumer);
+    thread.start();
+
+  }
+
+  private InputStream convertByte(byte[] event) {
+    return IOUtils.toInputStream(new String(event), StandardCharsets.UTF_8);
+  }
+
+  private void applyConfiguration(IStaticPropertyExtractor extractor) {
+    mqttConfig = MqttConnectUtils.getMqttConfig(extractor);
+    selectedSensorName = extractor.selectedSingleValue(SENSOR_TYPE, String.class);
   }
 
   @Override
@@ -47,7 +145,7 @@ public class HilscherMqttAdapter implements StreamPipesAdapter {
       IAdapterParameterExtractor extractor,
       IAdapterRuntimeContext adapterRuntimeContext
   ) throws AdapterException {
-
+    mqttConsumer.close();
   }
 
   @Override
@@ -55,6 +153,52 @@ public class HilscherMqttAdapter implements StreamPipesAdapter {
       IAdapterParameterExtractor extractor,
       IAdapterGuessSchemaContext adapterGuessSchemaContext
   ) throws AdapterException {
-    return null;
+    this.applyConfiguration(extractor.getStaticPropertyExtractor());
+    if (selectedSensorName.equals(SENSOR_VVB001_LABEL)) {
+      return new SensorVVB001Hilscher().getEventSchema();
+    }
+    throw new AdapterException("Invalid adapter configuration - selected adapter does not exist: %s".formatted(
+        selectedSensorName));
+  }
+
+  private Map<String, Object> getProcessData(Map<String, Object> event) {
+
+    // extract messages contained in the current event
+    List<Map<String, Object>> messages;
+    if (event.containsKey(MESSAGES_KEY)) {
+      messages = (List<Map<String, Object>>) event.get(MESSAGES_KEY);
+    } else {
+      throw new ParseException("Current event does follow the expected structure - no key '%s' exists".formatted(
+          MESSAGES_KEY));
+    }
+
+    var message =
+        messages.stream()
+                .filter(msg -> msg.getOrDefault(FILTER_KEY, "")
+                                  .equals(PROCESS_DATA_KEY))
+                .findFirst();
+    if (message.isPresent()) {
+      var data = (Map<String, Object>) message.get()
+                                              .get(PAYLOAD_KEY);
+      data.put(
+          SensorVVB001Hilscher.TIMESTAMP_NAME_SP,
+          message.get()
+                 .get(SensorVVB001Hilscher.TIMESTAMP_NAME_SOURCE)
+      );
+      data.put(
+          SensorVVB001Hilscher.SENSOR_ID_NAME,
+          getSensorIdFromSource(message.get()
+                                       .get(SOURCE_KEY)
+                                       .toString())
+      );
+      return (Map<String, Object>) message.get()
+                                          .get(PAYLOAD_KEY);
+    }
+    throw new ParseException("No process data message");
+
+  }
+
+  private String getSensorIdFromSource(String source) {
+    return source.substring(source.lastIndexOf("/") + 1);
   }
 }
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/iolink/IfmAlMqttAdapter.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/iolink/IfmAlMqttAdapter.java
index 9c9fc05caf..576a0a7a13 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/iolink/IfmAlMqttAdapter.java
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/iolink/IfmAlMqttAdapter.java
@@ -20,7 +20,7 @@ package org.apache.streampipes.connect.iiot.adapters.iolink;
 
 import org.apache.streampipes.commons.exceptions.connect.AdapterException;
 import org.apache.streampipes.commons.exceptions.connect.ParseException;
-import org.apache.streampipes.connect.iiot.adapters.iolink.sensor.SensorVVB001;
+import org.apache.streampipes.connect.iiot.adapters.iolink.sensor.SensorVVB001Ifm;
 import org.apache.streampipes.extensions.api.connect.IAdapterConfiguration;
 import org.apache.streampipes.extensions.api.connect.IEventCollector;
 import org.apache.streampipes.extensions.api.connect.IParser;
@@ -96,7 +96,7 @@ public class IfmAlMqttAdapter implements StreamPipesAdapter {
   public void onAdapterStarted(IAdapterParameterExtractor extractor,
                                IEventCollector collector,
                                IAdapterRuntimeContext adapterRuntimeContext) throws AdapterException {
-    var sensor = new SensorVVB001();
+    var sensor = new SensorVVB001Ifm();
 
     this.applyConfiguration(extractor.getStaticPropertyExtractor());
     this.mqttConsumer = new MqttConsumer(
@@ -129,7 +129,7 @@ public class IfmAlMqttAdapter implements StreamPipesAdapter {
                       var parsedEvent = sensor.parseEvent(eventData);
                       parsedEvent.put("timestamp", System.currentTimeMillis() + i);
                       parsedEvent.put("port", "port" + ports.get(i));
-                      parsedEvent.put(SensorVVB001.IO_LINK_MASTER_SN, serialnumber);
+                      parsedEvent.put(SensorVVB001Ifm.IO_LINK_MASTER_SN, serialnumber);
 
                       collector.collect(parsedEvent);
                     } else {
@@ -185,7 +185,7 @@ public class IfmAlMqttAdapter implements StreamPipesAdapter {
                                        IAdapterGuessSchemaContext adapterGuessSchemaContext) throws AdapterException {
     this.applyConfiguration(extractor.getStaticPropertyExtractor());
 
-    return new SensorVVB001().getEventSchema();
+    return new SensorVVB001Ifm().getEventSchema();
   }
 
 
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/iolink/sensor/SensorVVB001Hilscher.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/iolink/sensor/SensorVVB001Hilscher.java
new file mode 100644
index 0000000000..9494860a77
--- /dev/null
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/iolink/sensor/SensorVVB001Hilscher.java
@@ -0,0 +1,131 @@
+package org.apache.streampipes.connect.iiot.adapters.iolink.sensor;
+
+import org.apache.streampipes.model.connect.guess.GuessSchema;
+import org.apache.streampipes.model.schema.PropertyScope;
+import org.apache.streampipes.sdk.builder.PrimitivePropertyBuilder;
+import org.apache.streampipes.sdk.builder.adapter.GuessSchemaBuilder;
+import org.apache.streampipes.sdk.utils.Datatypes;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Map;
+
+import static org.apache.streampipes.sdk.helpers.EpProperties.timestampProperty;
+
+public class SensorVVB001Hilscher {
+
+  public static final String V_RMS_NAME = "v-Rms";
+  public static final String A_PEAK_NAME = "a-Peak";
+  public static final String A_RMS_NAME = "a-Rms";
+  public static final String TEMPERATURE_NAME = "Temperature";
+  public static final String CREST_NAME = "Crest";
+  public static final String STATUS_NAME = "Device status";
+  public static final String OUT_1_NAME = "OUT1";
+  public static final String OUT_2_NAME = "OUT2";
+  public static final String SENSOR_ID_NAME = "SensorID";
+  public static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
+  public static final String TIMESTAMP_NAME_SOURCE = "Timestamp";
+  public static final String TIMESTAMP_NAME_SP = TIMESTAMP_NAME_SOURCE.toLowerCase();
+
+  public static final Double NUMERICAL_SCALE_FACTOR = 0.1;
+
+  public GuessSchema getEventSchema() {
+
+    return GuessSchemaBuilder
+        .create()
+        .property(timestampProperty(TIMESTAMP_NAME_SP))
+        .sample(TIMESTAMP_NAME_SP, 1685525380729L)
+        .property(
+            PrimitivePropertyBuilder
+                .create(Datatypes.Float, V_RMS_NAME)
+                .scope(PropertyScope.MEASUREMENT_PROPERTY)
+                .description("Speed RMS value")
+                .build()
+        )
+        .sample(V_RMS_NAME, 0.0023)
+        .property(
+            PrimitivePropertyBuilder
+                .create(Datatypes.Float, A_PEAK_NAME)
+                .scope(PropertyScope.MEASUREMENT_PROPERTY)
+                .description("Acceleration peak value")
+                .build()
+        )
+        .sample(A_PEAK_NAME, 6.6)
+        .property(
+            PrimitivePropertyBuilder
+                .create(Datatypes.Float, A_RMS_NAME)
+                .scope(PropertyScope.MEASUREMENT_PROPERTY)
+                .description("Acceleration RMS value")
+                .build()
+        )
+        .sample(A_RMS_NAME, 1.8)
+        .property(
+            PrimitivePropertyBuilder
+                .create(Datatypes.Float, TEMPERATURE_NAME)
+                .scope(PropertyScope.MEASUREMENT_PROPERTY)
+                .description("Current temperature")
+                .build()
+        )
+        .sample(TEMPERATURE_NAME, 22.0)
+        .property(
+            PrimitivePropertyBuilder
+                .create(Datatypes.Float, CREST_NAME)
+                .scope(PropertyScope.MEASUREMENT_PROPERTY)
+                .description("Acceleration crest factor")
+                .build()
+        )
+        .sample(CREST_NAME, 3.7)
+        .property(
+            PrimitivePropertyBuilder
+                .create(Datatypes.Boolean, OUT_1_NAME)
+                .scope(PropertyScope.MEASUREMENT_PROPERTY)
+                .description("Current state of the digital signal")
+                .build()
+        )
+        .sample(OUT_1_NAME, true)
+        .property(
+            PrimitivePropertyBuilder
+                .create(Datatypes.Boolean, OUT_2_NAME)
+                .scope(PropertyScope.MEASUREMENT_PROPERTY)
+                .description("Current state of the digital signal")
+                .build()
+        )
+        .sample(OUT_2_NAME, true)
+        .property(
+            PrimitivePropertyBuilder
+                .create(Datatypes.Integer, STATUS_NAME)
+                .scope(PropertyScope.MEASUREMENT_PROPERTY)
+                .description("Device status (0: OK, 1: Maintenance required, "
+                                 + "2: Out of specification, 3: Function Test, 4: Error)")
+                .build()
+        )
+        .sample(STATUS_NAME, 0)
+        .property(
+            PrimitivePropertyBuilder
+                .create(Datatypes.String, SENSOR_ID_NAME)
+                .scope(PropertyScope.DIMENSION_PROPERTY)
+                .description("Identifier of the sensor")
+                .build()
+        )
+        .sample(SENSOR_ID_NAME, "000008740649")
+        .build();
+  }
+
+  public Map<String, Object> parseEvent(Map<String, Object> event){
+    try {
+      // convert timestamp from string representation to UNIX timestamp
+      event.put(TIMESTAMP_NAME_SP, new SimpleDateFormat(DATE_FORMAT).parse((String) event.get(TIMESTAMP_NAME_SP)).getTime());
+
+      // correct all numerical values by scale factor
+      event.put(CREST_NAME,  Float.parseFloat(event.get(CREST_NAME).toString()) * NUMERICAL_SCALE_FACTOR);
+      event.put(TEMPERATURE_NAME,  Float.parseFloat(event.get(TEMPERATURE_NAME).toString()) * NUMERICAL_SCALE_FACTOR);
+      event.put(A_PEAK_NAME,  Float.parseFloat(event.get(A_PEAK_NAME).toString()) * NUMERICAL_SCALE_FACTOR);
+      event.put(A_RMS_NAME,  Float.parseFloat(event.get(A_RMS_NAME).toString()) * NUMERICAL_SCALE_FACTOR);
+      event.put(V_RMS_NAME,  Float.parseFloat(event.get(V_RMS_NAME).toString()) * NUMERICAL_SCALE_FACTOR);
+
+    } catch (ParseException e) {
+      throw new RuntimeException("Error during parsing the raw event: %s".formatted(event));
+    }
+    return event;
+  }
+}
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/iolink/sensor/SensorVVB001Ifm.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/iolink/sensor/SensorVVB001Ifm.java
new file mode 100644
index 0000000000..b0f722557b
--- /dev/null
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/iolink/sensor/SensorVVB001Ifm.java
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.connect.iiot.adapters.iolink.sensor;
+
+import org.apache.streampipes.model.connect.guess.GuessSchema;
+import org.apache.streampipes.model.schema.PropertyScope;
+import org.apache.streampipes.sdk.builder.PrimitivePropertyBuilder;
+import org.apache.streampipes.sdk.builder.adapter.GuessSchemaBuilder;
+import org.apache.streampipes.sdk.utils.Datatypes;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.apache.streampipes.sdk.helpers.EpProperties.timestampProperty;
+
+public class SensorVVB001Ifm implements IoLinkSensor {
+
+  public static final String V_RMS_NAME = "vRms";
+  public static final String A_PEAK_NAME = "aPeak";
+  public static final String A_RMS_NAME = "aRms";
+  public static final String TEMPERATURE_NAME = "temperature";
+  public static final String CREST_NAME = "crest";
+  public static final String STATUS_NAME = "status";
+  public static final String OUT_1_NAME = "out1";
+  public static final String OUT_2_NAME = "out2";
+  public static final String PORT_NAME = "port";
+
+  public static final String IO_LINK_MASTER_SN = "ioLinkMasterSN";
+
+
+  @Override
+  public GuessSchema getEventSchema() {
+
+    return GuessSchemaBuilder.create()
+        .property(timestampProperty("timestamp"))
+        .sample("timestamp", 1685525380729L)
+        .property(
+            PrimitivePropertyBuilder
+                .create(Datatypes.Float, V_RMS_NAME)
+                .scope(PropertyScope.MEASUREMENT_PROPERTY)
+                .description("Speed RMS value")
+                .build()
+        )
+        .sample(V_RMS_NAME, 0.0023)
+        .property(
+            PrimitivePropertyBuilder
+                .create(Datatypes.Float, A_PEAK_NAME)
+                .scope(PropertyScope.MEASUREMENT_PROPERTY)
+                .description("Acceleration peak value")
+                .build()
+        )
+        .sample(A_PEAK_NAME, 6.6)
+        .property(
+            PrimitivePropertyBuilder
+                .create(Datatypes.Float, A_RMS_NAME)
+                .scope(PropertyScope.MEASUREMENT_PROPERTY)
+                .description("Acceleration RMS value")
+                .build()
+        )
+        .sample(A_RMS_NAME, 1.8)
+        .property(
+            PrimitivePropertyBuilder
+                .create(Datatypes.Float, TEMPERATURE_NAME)
+                .scope(PropertyScope.MEASUREMENT_PROPERTY)
+                .description("Current temperature")
+                .build()
+        )
+        .sample(TEMPERATURE_NAME, 22.0)
+        .property(
+            PrimitivePropertyBuilder
+                .create(Datatypes.Float, CREST_NAME)
+                .scope(PropertyScope.MEASUREMENT_PROPERTY)
+                .description("Acceleration crest factor")
+                .build()
+        )
+        .sample(CREST_NAME, 3.7)
+        .property(
+            PrimitivePropertyBuilder
+                .create(Datatypes.Integer, STATUS_NAME)
+                .scope(PropertyScope.MEASUREMENT_PROPERTY)
+                .description("Device status (0: OK, 1: Maintenance required, "
+                             + "2: Out of specification, 3: Function Test, 4: Error)")
+                .build()
+        )
+        .sample(STATUS_NAME, 0)
+        .property(
+            PrimitivePropertyBuilder
+                .create(Datatypes.Boolean, OUT_1_NAME)
+                .scope(PropertyScope.MEASUREMENT_PROPERTY)
+                .description("Current state of the digital signal")
+                .build()
+        )
+        .sample(OUT_1_NAME, true)
+        .property(
+            PrimitivePropertyBuilder
+                .create(Datatypes.Boolean, OUT_2_NAME)
+                .scope(PropertyScope.MEASUREMENT_PROPERTY)
+                .description("Current state of the digital signal")
+                .build()
+        )
+        .sample(OUT_2_NAME, true)
+        .property(
+            PrimitivePropertyBuilder
+                .create(Datatypes.String, PORT_NAME)
+                .scope(PropertyScope.DIMENSION_PROPERTY)
+                .description("Port the sensor is connected to at IOLink master")
+                .build()
+        )
+        .sample(PORT_NAME, "port1")
+        .property(
+            PrimitivePropertyBuilder
+                .create(Datatypes.String, IO_LINK_MASTER_SN)
+                .scope(PropertyScope.DIMENSION_PROPERTY)
+                .description("This is the serial number of the IO-Link Master")
+                .build()
+        )
+        .sample(PORT_NAME, "XXXXXXXXXXXX")
+        .build();
+  }
+
+  @Override
+  public Map<String, Object> parseEvent(String encodedEvent) {
+    var event = new HashMap<String, Object>();
+    event.put(V_RMS_NAME, getValue(0, 4, 0.0001, encodedEvent));
+    event.put(A_PEAK_NAME, getValue(8, 12, 0.1, encodedEvent));
+    event.put(A_RMS_NAME, getValue(16, 20, 0.1, encodedEvent));
+    event.put(TEMPERATURE_NAME, getValue(24, 28, 0.1, encodedEvent));
+    event.put(CREST_NAME, getValue(32, 36, 0.1, encodedEvent));
+    event.put(STATUS_NAME, (int) getValue(38, 39, 1.0, encodedEvent));
+
+    // The last two bits represent the status
+    var outValues = (int) getValue(39, 40, 1.0, encodedEvent);
+    event.put(OUT_1_NAME, (outValues & 1) != 0);
+    event.put(OUT_2_NAME, (outValues & 2) != 0);
+
+    return event;
+  }
+
+  private double getValue(int start, int end, double scaleFactor, String encodedEvent) {
+    var word = encodedEvent.substring(start, end);
+
+    var rawValue = (double) (Integer.parseInt(word, 16));
+
+    return rawValue * scaleFactor;
+  }
+}
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/resources/org.apache.streampipes.connect.iiot.adapters.hilscher/documentation.md b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/resources/org.apache.streampipes.connect.iiot.adapters.hilscher/documentation.md
new file mode 100644
index 0000000000..6b86e5382d
--- /dev/null
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/resources/org.apache.streampipes.connect.iiot.adapters.hilscher/documentation.md
@@ -0,0 +1,73 @@
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~    http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  ~
+  -->
+
+## ifm IOLink
+
+<p align="center"> 
+    <img src="icon.png" width="150px;" class="pe-image-documentation"/>
+</p>
+
+***
+
+## Description
+
+This adapter enables the integration of IO-Link sensor data produced by a Hilscher IO-Link Master with Apache StreamPipes.
+For detailed instructions, please refer to the Hilscher documentation.
+
+### Requirements
+tbc
+
+### Restrictions
+This version supports a single IO-Link master. If you want to connect multiple masters, they must have the same setup.
+If you have different requirements, please inform us through the mailing list or GitHub discussions.
+
+***
+
+## Configuration
+
+Here is a list of the configuration parameters you must provide.
+
+### Broker URL
+
+Enter the URL of the broker, including the protocol (e.g. `tcp://10.20.10.3:1883`)
+
+### Access Mode
+
+If necessary, provide broker credentials.
+
+### Sensor Type
+
+Choose the type of sensor you want to connect. (**IMPORTANT:** Currently, only the VVB001 is supported)
+
+## Output
+
+The output includes all values from the selected sensor type. Here is an example for the `VVB001 sensor`:
+```
+{
+    "a-Rms": 1.8,
+    "OUT2": true,
+    "SensorID": "000008740649",
+    "Temperature": 22,
+    "Crest": 3.7,
+    "v-Rms": 0.0023,
+    "OUT1": true,
+    "Device status": 0,
+    "a-Peak": 6.6,
+    "timestamp": 1685525380729
+}
+```
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/resources/org.apache.streampipes.connect.iiot.adapters.hilscher/icon.png b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/resources/org.apache.streampipes.connect.iiot.adapters.hilscher/icon.png
new file mode 100644
index 0000000000..39c33a25e8
Binary files /dev/null and b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/resources/org.apache.streampipes.connect.iiot.adapters.hilscher/icon.png differ
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/resources/org.apache.streampipes.connect.iiot.adapters.hilscher/strings.en b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/resources/org.apache.streampipes.connect.iiot.adapters.hilscher/strings.en
new file mode 100644
index 0000000000..ce3e41c08e
--- /dev/null
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/resources/org.apache.streampipes.connect.iiot.adapters.hilscher/strings.en
@@ -0,0 +1,47 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+
+org.apache.streampipes.connect.iiot.adapters.hilscher.title=Hilscher IOLink
+org.apache.streampipes.connect.iiot.adapters.hilscher.description=Consumes MQTT data produced by an IOLink master of Hilscher
+
+access-mode.title=Access Mode
+access-mode.description=Provide user credentials for the MQTT broker
+
+anonymous-alternative.title=Unauthenticated
+anonymous-alternative.description=
+
+username-alternative.title=Username/Password
+username-alternative.description=
+
+username-group.title=User Group
+username-group.description=
+
+username.title=Username
+username.description=
+
+password.title=Password
+password.description=
+
+broker_url.title=Broker URL
+broker_url.description=Example: tcp://test-server.com:1883 (Protocol required. Port required)"
+
+topic.title=Topic
+topic.description=Example: test/topic
+
+sensor_type.title=Sensor Type
+sensor_type.description=Select the sensor type that you want to connect
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/test/java/org/apache/streampipes/sensor/SensorVVB001Test.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/test/java/org/apache/streampipes/sensor/SensorVVB001IfmTest.java
similarity index 65%
rename from streampipes-extensions/streampipes-connect-adapters-iiot/src/test/java/org/apache/streampipes/sensor/SensorVVB001Test.java
rename to streampipes-extensions/streampipes-connect-adapters-iiot/src/test/java/org/apache/streampipes/sensor/SensorVVB001IfmTest.java
index 199818d510..b2aaeb06b8 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/test/java/org/apache/streampipes/sensor/SensorVVB001Test.java
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/test/java/org/apache/streampipes/sensor/SensorVVB001IfmTest.java
@@ -18,15 +18,15 @@
 
 package org.apache.streampipes.sensor;
 
-import org.apache.streampipes.connect.iiot.adapters.iolink.sensor.SensorVVB001;
+import org.apache.streampipes.connect.iiot.adapters.iolink.sensor.SensorVVB001Ifm;
 
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
 
-public class SensorVVB001Test {
+public class SensorVVB001IfmTest {
 
-  private SensorVVB001 sensor = new SensorVVB001();
+  private SensorVVB001Ifm sensor = new SensorVVB001Ifm();
 
   private String sampleInput = "0017FC000042FF000012FF00015CFF000025FF03";
 
@@ -40,13 +40,13 @@ public class SensorVVB001Test {
   public void parseEvent() {
     var result = sensor.parseEvent(sampleInput);
 
-    assertEquals(0.0023, (double) result.get(SensorVVB001.V_RMS_NAME), 0.001);
-    assertEquals(6.600, (double) result.get(SensorVVB001.A_PEAK_NAME), 0.001);
-    assertEquals(1.8, (double) result.get(SensorVVB001.A_RMS_NAME), 0.001);
-    assertEquals(34.8, (double) result.get(SensorVVB001.TEMPERATURE_NAME), 0.001);
-    assertEquals(3.7, (double) result.get(SensorVVB001.CREST_NAME), 0.001);
-    assertEquals(0, result.get(SensorVVB001.STATUS_NAME));
-    assertEquals(true, result.get(SensorVVB001.OUT_1_NAME));
-    assertEquals(true, result.get(SensorVVB001.OUT_2_NAME));
+    assertEquals(0.0023, (double) result.get(SensorVVB001Ifm.V_RMS_NAME), 0.001);
+    assertEquals(6.600, (double) result.get(SensorVVB001Ifm.A_PEAK_NAME), 0.001);
+    assertEquals(1.8, (double) result.get(SensorVVB001Ifm.A_RMS_NAME), 0.001);
+    assertEquals(34.8, (double) result.get(SensorVVB001Ifm.TEMPERATURE_NAME), 0.001);
+    assertEquals(3.7, (double) result.get(SensorVVB001Ifm.CREST_NAME), 0.001);
+    assertEquals(0, result.get(SensorVVB001Ifm.STATUS_NAME));
+    assertEquals(true, result.get(SensorVVB001Ifm.OUT_1_NAME));
+    assertEquals(true, result.get(SensorVVB001Ifm.OUT_2_NAME));
   }
 }
\ No newline at end of file


(streampipes) 03/03: revert change

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

bossenti pushed a commit to branch support-hilscher-devices
in repository https://gitbox.apache.org/repos/asf/streampipes.git

commit cce9b4598547ce5dd23068859787f63ad3e99ce2
Author: bossenti <bo...@posteo.de>
AuthorDate: Mon Mar 4 16:38:48 2024 +0100

    revert change
---
 installer/cli/.env | 1 -
 1 file changed, 1 deletion(-)

diff --git a/installer/cli/.env b/installer/cli/.env
index 5e80ec6f68..6616d9a484 100644
--- a/installer/cli/.env
+++ b/installer/cli/.env
@@ -44,4 +44,3 @@ SP_INFLUX_INIT_MODE=setup
 # set to true if you want StreamPipes to expose Prometheus metrics
 #SP_SETUP_PROMETHEUS_ENDPOINT=true
 SP_SETUP_PROMETHEUS_ENDPOINT=false
-SP_TS_STORAGE_BUCKET=migrated


(streampipes) 01/03: tmp

Posted by bo...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

bossenti pushed a commit to branch support-hilscher-devices
in repository https://gitbox.apache.org/repos/asf/streampipes.git

commit d78f6d5b60c2fa88efdcb5984c882e0d88d4aff5
Author: bossenti <bo...@posteo.de>
AuthorDate: Mon Mar 4 10:46:28 2024 +0100

    tmp
---
 installer/cli/.env                                 |  1 +
 .../iiot/IIoTAdaptersExtensionModuleExport.java    |  2 +
 .../iiot/adapters/iolink/HilscherMqttAdapter.java  | 60 ++++++++++++++++++++++
 3 files changed, 63 insertions(+)

diff --git a/installer/cli/.env b/installer/cli/.env
index 6616d9a484..5e80ec6f68 100644
--- a/installer/cli/.env
+++ b/installer/cli/.env
@@ -44,3 +44,4 @@ SP_INFLUX_INIT_MODE=setup
 # set to true if you want StreamPipes to expose Prometheus metrics
 #SP_SETUP_PROMETHEUS_ENDPOINT=true
 SP_SETUP_PROMETHEUS_ENDPOINT=false
+SP_TS_STORAGE_BUCKET=migrated
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/IIoTAdaptersExtensionModuleExport.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/IIoTAdaptersExtensionModuleExport.java
index 9714149241..2a97899f1c 100644
--- a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/IIoTAdaptersExtensionModuleExport.java
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/IIoTAdaptersExtensionModuleExport.java
@@ -18,6 +18,7 @@
 
 package org.apache.streampipes.connect.iiot;
 
+import org.apache.streampipes.connect.iiot.adapters.iolink.HilscherMqttAdapter;
 import org.apache.streampipes.connect.iiot.adapters.iolink.IfmAlMqttAdapter;
 import org.apache.streampipes.connect.iiot.adapters.ros.RosBridgeAdapter;
 import org.apache.streampipes.connect.iiot.adapters.simulator.machine.MachineDataSimulatorAdapter;
@@ -38,6 +39,7 @@ public class IIoTAdaptersExtensionModuleExport implements IExtensionModuleExport
     return List.of(
         new MachineDataSimulatorAdapter(),
         new FileReplayAdapter(),
+        new HilscherMqttAdapter(),
         new IfmAlMqttAdapter(),
         new RosBridgeAdapter(),
         new HttpStreamProtocol(),
diff --git a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/iolink/HilscherMqttAdapter.java b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/iolink/HilscherMqttAdapter.java
new file mode 100644
index 0000000000..2f87d29cda
--- /dev/null
+++ b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/iolink/HilscherMqttAdapter.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.streampipes.connect.iiot.adapters.iolink;
+
+import org.apache.streampipes.commons.exceptions.connect.AdapterException;
+import org.apache.streampipes.extensions.api.connect.IAdapterConfiguration;
+import org.apache.streampipes.extensions.api.connect.IEventCollector;
+import org.apache.streampipes.extensions.api.connect.StreamPipesAdapter;
+import org.apache.streampipes.extensions.api.connect.context.IAdapterGuessSchemaContext;
+import org.apache.streampipes.extensions.api.connect.context.IAdapterRuntimeContext;
+import org.apache.streampipes.extensions.api.extractor.IAdapterParameterExtractor;
+import org.apache.streampipes.model.connect.guess.GuessSchema;
+
+public class HilscherMqttAdapter implements StreamPipesAdapter {
+  @Override
+  public IAdapterConfiguration declareConfig() {
+    return null;
+  }
+
+  @Override
+  public void onAdapterStarted(
+      IAdapterParameterExtractor extractor,
+      IEventCollector collector,
+      IAdapterRuntimeContext adapterRuntimeContext
+  ) throws AdapterException {
+
+  }
+
+  @Override
+  public void onAdapterStopped(
+      IAdapterParameterExtractor extractor,
+      IAdapterRuntimeContext adapterRuntimeContext
+  ) throws AdapterException {
+
+  }
+
+  @Override
+  public GuessSchema onSchemaRequested(
+      IAdapterParameterExtractor extractor,
+      IAdapterGuessSchemaContext adapterGuessSchemaContext
+  ) throws AdapterException {
+    return null;
+  }
+}