This is an automated email from the ASF dual-hosted git repository.
zehnder pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/streampipes.git
The following commit(s) were added to refs/heads/dev by this push:
new 50199e09b Sp 1592 (#1647)
50199e09b is described below
commit 50199e09b7fb847470eb32bccfef5c8b6292f9e7
Author: Philipp Zehnder <[email protected]>
AuthorDate: Mon Jun 5 15:17:36 2023 +0200
Sp 1592 (#1647)
* [hotfix] Remove set adapters from extensions
* [hotfix] Remove old resource files
* [#1289] Remove data set model
* [#1289] Remove data set model from ui
* [#1289] Remove `adapterType` and fix tests
* [#1289] Remove class `SpDataSet`
* [#1289] Remove legacy code in class `AdapterDescription`
* [#1289] Remove class `AdapterStreamDescription`
* [#1289] Remove class `ProtocolStreamDescription`
* [hotfix] Remove class `AdapterDescription`
* [#1289] Very first version for new adapter interface
* [#1289] Started to migrate the API
* [#1289] Deactivate old protocol API
* [#1289] Remove old models from the ui
* [#1289] Remove old models from the ui
* [#1289] Fix icons for adapters
* [#1289] Fix minor bug
* [#1289] Fix maven build
* [#1289] WIP refactor `AdapterConfigurationBuilder`
* [#1289] Fix AdapterConfigurationBuilder
* [#1289] Fix AdapterConfigurationBuilder
* [#1289] Guess schema works now for NewMachineDataSimulatorAdapter
* [#1289] Add start adapter
* [#1289] First version of new machine data simulator works
* [#1289] Working on the first new parser
* [#1289] First version of declare parser description
* [WIP] Add adapter configuration test
* [#1289] First generic adapter works now
* [#1289] Add parser exception to json parser
* [#1289] Add csv parser
* [#1289] Change implementation for json parser
* [#1289] Add json array parsers
* Add runtime context to adapters (#1290)
* Extract interface of (#1290)
* Refactor OPC-UA adapter to new model (#1290)
* Refactor S7 adapter (#1290)
* Refactor Modbus adapter (#1290)
* Refactor Ros adapter (#1290)
* [#1289] Add geo json parser
* [#1289] Add xml parser
* [#1289] Add image parser
* Refactor Kafka adapter (#1290)
* Refactor MQTT adapter (#1290)
* Refactor Nats adapter (#1290)
* Refactor Pulsar adapter (#1290)
* Refactor RocketMQ adapter (#1290)
* Refactor TubeMQ adapter (#1290)
* Refactor HTTP server adapter (#1290)
* Refactor HTTP Stream adapter (#1290)
* [WIP] Refactor Parser API
* [WIP] Refactor Parser API
* [#1289] Fix file stream e2e test
* [#1289] Fix tests and csv parser for timestamps
* [#1289] Fix e2e connect tests
* [hotfix] Fix build
* [hotfix] Deactivate Mqtt integration test
* [#1289] Remove old format implementation from backend
* [#1289] Remove old format implementation from backend
* [#1289] Remove old format implementation from ui
* [#1289] Fix kafka e2e test
* Add migration script for specific adapters (#1289)
* Add initial version to migrate generic adapters (#1289)
* Modify format migrators (#1289)
* [#1289] Migrate influxdb to new interface
* [#1289] Fix ROS bridge adapter
* [#1289] Rename specific-adapter-configuration.component
* [#1289] Remove old data model
* [#1289] Fix mqtt integration test
* [#1289] Update Pulsar integration test
* [#1289] Remove DebugAdapterSink which is no longer needed for integration
tests
* [#1289] Fix kafka adapter on restart
* [#1289] Fix migrations for all parser
* [hotfix] Fix image parser for adapters
* [hotfix] Change StreamPipes version to fix build problem
* [#1289] Move adapters
* [hotfix] Remove duplicate licence headers
* [hotfix] Fix conversion of pipeline element templates
* Move PullAdapter to extensions-management and api modules (#1289)
* Refactor structure of extensions-api, add supplier to adapter interface
(#1581)
* Rename AdapterInterface to StreamPipesAdapter (#1590)
* [hotfix] Fix checkstyle issues
* [hotfix] Fix checkstyle issue
* [hotfix] Fix checkstyle issue
* [hotfix] Fix checkstyle
* Migrate ISS adapter and Flic adapter (#1289)
* Migrate connect adapters to new model (#1289)
* Properly apply configs to influx adapter (#1289)
* [hotfix] Fix checkstyle
* fix: minor adaptions
* fix: remove data set artifacts
* fix: minor fixes
* [hotfix] Regenerate typescript model
* [#1592] Add first version for an io link adapter
* Refactor data processor and sink API (#1632) (#1633)
* chore: mark streampipes-wrapper-python as deprecated (#1623)
* Bump types-requests in /streampipes-client-python (#1588)
Bumps [types-requests](https://github.com/python/typeshed) from 2.30.0.0 to
2.31.0.0.
- [Commits](https://github.com/python/typeshed/commits)
---
updated-dependencies:
- dependency-name: types-requests
dependency-type: direct:development
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot]
<49699333+dependabot[bot]@users.noreply.github.com>
* Bump mkdocstrings[python] in /streampipes-client-python (#1631)
* chore: add missing support of NATS as messaging protocol (#1628)
* Bump spring-boot.version from 3.0.6 to 3.1.0 (#1595)
Bumps `spring-boot.version` from 3.0.6 to 3.1.0.
Updates `spring-boot-properties-migrator` from 3.0.6 to 3.1.0
- [Release notes](https://github.com/spring-projects/spring-boot/releases)
-
[Commits](https://github.com/spring-projects/spring-boot/compare/v3.0.6...v3.1.0)
Updates `spring-boot-starter-jersey` from 3.0.6 to 3.1.0
- [Release notes](https://github.com/spring-projects/spring-boot/releases)
-
[Commits](https://github.com/spring-projects/spring-boot/compare/v3.0.6...v3.1.0)
Updates `spring-boot-starter-jetty` from 3.0.6 to 3.1.0
- [Release notes](https://github.com/spring-projects/spring-boot/releases)
-
[Commits](https://github.com/spring-projects/spring-boot/compare/v3.0.6...v3.1.0)
Updates `spring-boot-starter-oauth2-client` from 3.0.6 to 3.1.0
- [Release notes](https://github.com/spring-projects/spring-boot/releases)
-
[Commits](https://github.com/spring-projects/spring-boot/compare/v3.0.6...v3.1.0)
Updates `spring-boot-starter-undertow` from 3.0.6 to 3.1.0
- [Release notes](https://github.com/spring-projects/spring-boot/releases)
-
[Commits](https://github.com/spring-projects/spring-boot/compare/v3.0.6...v3.1.0)
Updates `spring-boot-starter-web` from 3.0.6 to 3.1.0
- [Release notes](https://github.com/spring-projects/spring-boot/releases)
-
[Commits](https://github.com/spring-projects/spring-boot/compare/v3.0.6...v3.1.0)
Updates `spring-boot-maven-plugin` from 3.0.6 to 3.1.0
- [Release notes](https://github.com/spring-projects/spring-boot/releases)
-
[Commits](https://github.com/spring-projects/spring-boot/compare/v3.0.6...v3.1.0)
---
updated-dependencies:
- dependency-name: org.springframework.boot:spring-boot-properties-migrator
dependency-type: direct:production
update-type: version-update:semver-minor
- dependency-name: org.springframework.boot:spring-boot-starter-jersey
dependency-type: direct:production
update-type: version-update:semver-minor
- dependency-name: org.springframework.boot:spring-boot-starter-jetty
dependency-type: direct:production
update-type: version-update:semver-minor
- dependency-name:
org.springframework.boot:spring-boot-starter-oauth2-client
dependency-type: direct:production
update-type: version-update:semver-minor
- dependency-name: org.springframework.boot:spring-boot-starter-undertow
dependency-type: direct:production
update-type: version-update:semver-minor
- dependency-name: org.springframework.boot:spring-boot-starter-web
dependency-type: direct:production
update-type: version-update:semver-minor
- dependency-name: org.springframework.boot:spring-boot-maven-plugin
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot]
<49699333+dependabot[bot]@users.noreply.github.com>
* Refactor data processor and sink API (#1632)
* Cleanup pom file (#1632)
* Migrate processors to API (#1632)
* [hotfix] Add runtime provider, update pom
* Fix bug in standalone wrapper (#1632)
* Fix instance provision in compatibility layer (#1632)
* [hotfix] Disable Maven cache in workflow file
* [hotfix] Fix failing build by reverting Flink version
* [hotfix] Add proper time selection to another cypress test (#1641)
* Fix bug in aggregation flink module
* Properly return output source and schema info
---------
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: Tim <[email protected]>
Co-authored-by: dependabot[bot]
<49699333+dependabot[bot]@users.noreply.github.com>
* chore: remove Plc4xPassiveAdapter
* Add implementation for schema guessing from the example file in the HTTP
resolves #1637
fixes #1518 for streampipes-extensions
* [#1592] Add io link master id to event
* [#1592] Provide documentation for io link adapter
---------
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: Dominik Riemer <[email protected]>
Co-authored-by: Stefan Obermeier <[email protected]>
Co-authored-by: bossenti <[email protected]>
Co-authored-by: Tim <[email protected]>
Co-authored-by: dependabot[bot]
<49699333+dependabot[bot]@users.noreply.github.com>
---
.../connect/iiot/ConnectAdapterIiotInit.java | 2 +
.../iiot/adapters/iolink/IfmAlMqttAdapter.java | 186 +++++++++++++++++++++
.../iiot/adapters/iolink/sensor/IoLinkSensor.java | 29 ++++
.../iiot/adapters/iolink/sensor/SensorVVB001.java | 162 ++++++++++++++++++
.../documentation.md | 84 ++++++++++
.../icon.png | Bin 0 -> 9219 bytes
.../strings.en | 50 ++++++
.../streampipes/sensor/SensorVVB001Test.java | 52 ++++++
8 files changed, 565 insertions(+)
diff --git
a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/ConnectAdapterIiotInit.java
b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/ConnectAdapterIiotInit.java
index 03685343b..dcd646eac 100644
---
a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/ConnectAdapterIiotInit.java
+++
b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/ConnectAdapterIiotInit.java
@@ -18,6 +18,7 @@
package org.apache.streampipes.connect.iiot;
+import org.apache.streampipes.connect.iiot.adapters.iolink.IfmAlMqttAdapter;
import org.apache.streampipes.connect.iiot.adapters.opcua.OpcUaAdapter;
import
org.apache.streampipes.connect.iiot.adapters.plc4x.modbus.Plc4xModbusAdapter;
import org.apache.streampipes.connect.iiot.adapters.plc4x.s7.Plc4xS7Adapter;
@@ -49,6 +50,7 @@ public class ConnectAdapterIiotInit extends
ExtensionsModelSubmitter {
8001)
.registerAdapter(new MachineDataSimulatorAdapter())
.registerAdapter(new FileReplayAdapter())
+ .registerAdapter(new IfmAlMqttAdapter())
.registerAdapter(new RosBridgeAdapter())
.registerAdapter(new OpcUaAdapter())
.registerAdapter(new Plc4xS7Adapter())
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
new file mode 100644
index 000000000..c5db51d94
--- /dev/null
+++
b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/iolink/IfmAlMqttAdapter.java
@@ -0,0 +1,186 @@
+/*
+ * 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.commons.exceptions.connect.ParseException;
+import org.apache.streampipes.connect.iiot.adapters.iolink.sensor.SensorVVB001;
+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.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.StreamPipesErrorMessage;
+import org.apache.streampipes.model.connect.guess.GuessSchema;
+import org.apache.streampipes.model.monitoring.SpLogEntry;
+import org.apache.streampipes.pe.shared.config.mqtt.MqttConfig;
+import org.apache.streampipes.pe.shared.config.mqtt.MqttConnectUtils;
+import org.apache.streampipes.pe.shared.config.mqtt.MqttConsumer;
+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.util.List;
+import java.util.Map;
+
+public class IfmAlMqttAdapter implements StreamPipesAdapter {
+
+ public static final String ID =
"org.apache.streampipes.connect.iiot.adapters.iolink";
+
+ private static final Logger LOG =
LoggerFactory.getLogger(IfmAlMqttAdapter.class);
+
+ private static final String PORTS = "ports";
+ private static final String SENSOR_TYPE = "sensor_type";
+
+ private MqttConsumer mqttConsumer;
+ private MqttConfig mqttConfig;
+
+ private final IParser parser;
+
+ private List<String> ports;
+
+ public IfmAlMqttAdapter() {
+ parser = new JsonParsers(new JsonObjectParser());
+ }
+
+ @Override
+ public IAdapterConfiguration declareConfig() {
+ return AdapterConfigurationBuilder
+ .create(ID, IfmAlMqttAdapter::new)
+ .withLocales(Locales.EN)
+ .withAssets(Assets.DOCUMENTATION, Assets.ICON)
+ .withCategory(AdapterType.Generic, AdapterType.Manufacturing)
+ .requiredTextParameter(MqttConnectUtils.getBrokerUrlLabel())
+ .requiredAlternatives(MqttConnectUtils.getAccessModeLabel(),
MqttConnectUtils.getAlternativesOne(),
+ MqttConnectUtils.getAlternativesTwo())
+ .requiredMultiValueSelection(Labels.withId(PORTS),
+ Options.from("Port 1", "Port 2", "Port 3", "Port 4"))
+ .requiredSingleValueSelection(Labels.withId(SENSOR_TYPE),
+ Options.from("VVB001"))
+ .requiredTextParameter(MqttConnectUtils.getTopicLabel())
+ .buildConfiguration();
+ }
+
+ @Override
+ public void onAdapterStarted(IAdapterParameterExtractor extractor,
+ IEventCollector collector,
+ IAdapterRuntimeContext adapterRuntimeContext)
throws AdapterException {
+ var sensor = new SensorVVB001();
+
+ this.applyConfiguration(extractor.getStaticPropertyExtractor());
+ this.mqttConsumer = new MqttConsumer(
+ this.mqttConfig,
+ (mqttEvent) -> {
+ try {
+ InputStream in = convertByte(mqttEvent);
+ parser.parse(in, (event) -> {
+
+ var data = getMap(event, "data");
+ var payload = getMap(data, "payload");
+
+ var deviceInfo = getMap(payload, "/deviceinfo/serialnumber");
+ var serialnumber = deviceInfo.get("data");
+
+ for (int i = 0; i < ports.size(); i++) {
+
+ var portResult = getMap(payload,
+
"/iolinkmaster/port[%s]/iolinkdevice/pdin".formatted(ports.get(i)));
+ var eventData = (String) portResult.get("data");
+
+ 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);
+
+ collector.collect(parsedEvent);
+ }
+ });
+ } catch (Exception e) {
+ adapterRuntimeContext
+ .getLogger()
+ .addErrorMessage(
+ extractor.getAdapterDescription().getElementId(),
+ SpLogEntry.from(System.currentTimeMillis(),
StreamPipesErrorMessage.from(e)));
+ LOG.error("Could not parse event", e);
+ }
+ });
+
+ Thread thread = new Thread(this.mqttConsumer);
+ thread.start();
+ }
+
+ @Override
+ public void onAdapterStopped(IAdapterParameterExtractor extractor,
+ IAdapterRuntimeContext adapterRuntimeContext)
throws AdapterException {
+ this.mqttConsumer.close();
+ }
+
+ @Override
+ public GuessSchema onSchemaRequested(IAdapterParameterExtractor extractor,
+ IAdapterGuessSchemaContext
adapterGuessSchemaContext) throws AdapterException {
+ this.applyConfiguration(extractor.getStaticPropertyExtractor());
+
+ return new SensorVVB001().getEventSchema();
+ }
+
+
+ private void applyConfiguration(IStaticPropertyExtractor extractor) {
+ mqttConfig = MqttConnectUtils.getMqttConfig(extractor);
+ String sensorType = extractor.selectedSingleValue(SENSOR_TYPE,
String.class);
+ var selectedPorts = extractor.selectedMultiValues(PORTS, String.class);
+ ports = selectedPorts.stream()
+ .map(port -> port.substring(5))
+ .toList();
+ }
+
+ private Map<String, Object> getMap(Map<String, Object> event, String key) {
+ if (event.containsKey(key)) {
+ var payload = event.get(key);
+ if (payload instanceof Map) {
+ return (Map<String, Object>) event.get(key);
+ } else {
+ throw new ParseException(getErrorMessage(key));
+ }
+ } else {
+ throw new ParseException(getErrorMessage(key));
+ }
+ }
+
+ private String getErrorMessage(String key) {
+ return "The event does not contain key: %s. Please reconfigure the IOLink
master to include this key".formatted(
+ key);
+ }
+
+ private InputStream convertByte(byte[] event) {
+ return IOUtils.toInputStream(new String(event), "UTF-8");
+ }
+}
diff --git
a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/iolink/sensor/IoLinkSensor.java
b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/iolink/sensor/IoLinkSensor.java
new file mode 100644
index 000000000..f371aa1e3
--- /dev/null
+++
b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/iolink/sensor/IoLinkSensor.java
@@ -0,0 +1,29 @@
+/*
+ * 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 java.util.Map;
+
+public interface IoLinkSensor {
+ GuessSchema getEventSchema();
+
+ Map<String, Object> parseEvent(String encodedEvent);
+}
diff --git
a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/iolink/sensor/SensorVVB001.java
b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/iolink/sensor/SensorVVB001.java
new file mode 100644
index 000000000..61bf36954
--- /dev/null
+++
b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/java/org/apache/streampipes/connect/iiot/adapters/iolink/sensor/SensorVVB001.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 SensorVVB001 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.iolink/documentation.md
b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/resources/org.apache.streampipes.connect.iiot.adapters.iolink/documentation.md
new file mode 100644
index 000000000..37c176779
--- /dev/null
+++
b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/resources/org.apache.streampipes.connect.iiot.adapters.iolink/documentation.md
@@ -0,0 +1,84 @@
+<!--
+ ~ 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 an ifm
IO-Link Master
+(e.g., AL1350) with Apache StreamPipes. To use this adapter, you need to
configure your IO-Link
+master to publish events to an MQTT broker. This can be achieved through a
REST interface or via
+the browser at `http://##IP_OF_IO_LINK_MASTER##/web/subscribe`. For detailed
instructions,
+please refer to the ifm documentation.
+
+### Requirements
+The JSON events should include the following information:
+- `deviceinfo.serialnumber`
+- Only the pdin value is required for each port (e.g., `port[0]`).
+- The event `timer[1].datachanged` can be used as a trigger.
+Using this adapter, you can create a stream for sensors of the same type.
+
+### 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.
+
+### Ports
+
+Select the ports that are connected to the IO-Link sensors.
+
+### 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`:
+```
+{
+ "aPeak": 6.6,
+ "aRms": 1.8,
+ "crest": 3.7,
+ "out1": true,
+ "out2": true,
+ "port": "000000001234",
+ "status": 0,
+ "temperature": 22,
+ "timestamp": 1685525380729,
+ "vRms": 0.0023
+}
+```
diff --git
a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/resources/org.apache.streampipes.connect.iiot.adapters.iolink/icon.png
b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/resources/org.apache.streampipes.connect.iiot.adapters.iolink/icon.png
new file mode 100644
index 000000000..39c33a25e
Binary files /dev/null and
b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/resources/org.apache.streampipes.connect.iiot.adapters.iolink/icon.png
differ
diff --git
a/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/resources/org.apache.streampipes.connect.iiot.adapters.iolink/strings.en
b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/resources/org.apache.streampipes.connect.iiot.adapters.iolink/strings.en
new file mode 100644
index 000000000..099298627
--- /dev/null
+++
b/streampipes-extensions/streampipes-connect-adapters-iiot/src/main/resources/org.apache.streampipes.connect.iiot.adapters.iolink/strings.en
@@ -0,0 +1,50 @@
+#
+# 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.iolink.title=ifm IOLink
+org.apache.streampipes.connect.iiot.adapters.iolink.description=Consumes MQTT
data produced by an IOLink master of ifm
+
+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
+
+ports.title=Ports
+ports.description=Select the ports with the selected sensor type
+
+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/SensorVVB001Test.java
new file mode 100644
index 000000000..199818d51
--- /dev/null
+++
b/streampipes-extensions/streampipes-connect-adapters-iiot/src/test/java/org/apache/streampipes/sensor/SensorVVB001Test.java
@@ -0,0 +1,52 @@
+/*
+ * 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.sensor;
+
+import org.apache.streampipes.connect.iiot.adapters.iolink.sensor.SensorVVB001;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class SensorVVB001Test {
+
+ private SensorVVB001 sensor = new SensorVVB001();
+
+ private String sampleInput = "0017FC000042FF000012FF00015CFF000025FF03";
+
+ @Test
+ public void checkEventSize() {
+ var result = sensor.parseEvent(sampleInput);
+ assertEquals(8, result.keySet().size());
+ }
+
+ @Test
+ 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));
+ }
+}
\ No newline at end of file