-
Notifications
You must be signed in to change notification settings - Fork 313
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Added type conversion math component
Signed-off-by: MMaiero <[email protected]>
- Loading branch information
Showing
5 changed files
with
366 additions
and
0 deletions.
There are no files selected for viewing
47 changes: 47 additions & 0 deletions
47
...g.eclipse.kura.example.wire.math.singleport.provider/OSGI-INF/TypeConversionComponent.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!-- | ||
Copyright (c) 2024 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 | ||
--> | ||
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" | ||
name="org.eclipse.kura.wire.TypeConversion" | ||
activate="activate" | ||
deactivate="deactivate" | ||
modified="updated" | ||
enabled="true" | ||
immediate="true" | ||
configuration-policy="require"> | ||
<implementation class="org.eclipse.kura.example.wire.math.singleport.typeconversion.TypeConversionComponent"/> | ||
<service> | ||
<provide interface="org.eclipse.kura.configuration.ConfigurableComponent"/> | ||
<provide interface="org.eclipse.kura.wire.WireComponent"/> | ||
<provide interface="org.osgi.service.wireadmin.Consumer"/> | ||
<provide interface="org.eclipse.kura.wire.WireEmitter"/> | ||
<provide interface="org.eclipse.kura.wire.WireReceiver"/> | ||
<provide interface="org.osgi.service.wireadmin.Producer"/> | ||
</service> | ||
<reference bind="bindWireHelperService" | ||
cardinality="1..1" | ||
interface="org.eclipse.kura.wire.WireHelperService" | ||
name="WireHelperService" | ||
policy="static" | ||
unbind="unbindWireHelperService"/> | ||
<property name="service.pid" value="org.eclipse.kura.wire.TypeConversion"/> | ||
<property name="kura.ui.service.hide" type="Boolean" value="true"/> | ||
<property name="input.cardinality.minimum" type="Integer" value="1"/> | ||
<property name="input.cardinality.maximum" type="Integer" value="1"/> | ||
<property name="input.cardinality.default" type="Integer" value="1"/> | ||
<property name="output.cardinality.minimum" type="Integer" value="1"/> | ||
<property name="output.cardinality.maximum" type="Integer" value="1"/> | ||
<property name="output.cardinality.default" type="Integer" value="1"/> | ||
</scr:component> |
41 changes: 41 additions & 0 deletions
41
....wire.math.singleport.provider/OSGI-INF/metatype/org.eclipse.kura.wire.TypeConversion.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<!-- | ||
Copyright (c) 2024 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 | ||
--> | ||
<MetaData xmlns="http://www.osgi.org/xmlns/metatype/v1.2.0" localization="en_us"> | ||
<OCD id="org.eclipse.kura.wire.TypeConversion" | ||
name="GainOffset" | ||
description="A wire component that applies a type conversion to a configurable set of numerical input properties."> | ||
|
||
<AD id="channels" | ||
name="Channels and Conversion" | ||
type="String" cardinality="0" | ||
required="true" | ||
default="channel1|Long" | ||
description="Specifies the properties on which apply the type conversion. Separated by a new line|textarea"> | ||
</AD> | ||
|
||
<AD id="emit.received.properties" | ||
name="emit.received.properties" | ||
type="Boolean" cardinality="0" | ||
required="true" | ||
default="false" | ||
description="Specifies whether received properties should be included in the emitted envelope or not."> | ||
</AD> | ||
</OCD> | ||
|
||
<Designate pid="org.eclipse.kura.wire.TypeConversion" factoryPid="org.eclipse.kura.wire.TypeConversion"> | ||
<Object ocdref="org.eclipse.kura.wire.TypeConversion"/> | ||
</Designate> | ||
</MetaData> |
141 changes: 141 additions & 0 deletions
141
...org/eclipse/kura/example/wire/math/singleport/typeconversion/TypeConversionComponent.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
/******************************************************************************* | ||
* Copyright (c) 2024 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.example.wire.math.singleport.typeconversion; | ||
|
||
import java.util.ArrayList; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
import org.eclipse.kura.configuration.ConfigurableComponent; | ||
import org.eclipse.kura.type.DataType; | ||
import org.eclipse.kura.type.TypedValue; | ||
import org.eclipse.kura.type.TypedValues; | ||
import org.eclipse.kura.wire.WireComponent; | ||
import org.eclipse.kura.wire.WireEmitter; | ||
import org.eclipse.kura.wire.WireEnvelope; | ||
import org.eclipse.kura.wire.WireHelperService; | ||
import org.eclipse.kura.wire.WireReceiver; | ||
import org.eclipse.kura.wire.WireRecord; | ||
import org.eclipse.kura.wire.WireSupport; | ||
import org.osgi.framework.ServiceReference; | ||
import org.osgi.service.component.ComponentContext; | ||
import org.osgi.service.wireadmin.Wire; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
public class TypeConversionComponent implements WireEmitter, WireReceiver, ConfigurableComponent { | ||
|
||
private static final Logger logger = LoggerFactory.getLogger(TypeConversionComponent.class); | ||
|
||
private WireHelperService wireHelperService; | ||
private WireSupport wireSupport; | ||
|
||
private TypeConversionComponentOptions options; | ||
|
||
public void bindWireHelperService(final WireHelperService wireHelperService) { | ||
this.wireHelperService = wireHelperService; | ||
} | ||
|
||
public void unbindWireHelperService(final WireHelperService wireHelperService) { | ||
if (this.wireHelperService == wireHelperService) { | ||
this.wireHelperService = null; | ||
} | ||
} | ||
|
||
public void activate(final Map<String, Object> properties, ComponentContext componentContext) { | ||
this.wireSupport = this.wireHelperService.newWireSupport(this, | ||
(ServiceReference<WireComponent>) componentContext.getServiceReference()); | ||
updated(properties); | ||
} | ||
|
||
public void updated(final Map<String, Object> properties) { | ||
try { | ||
this.options = new TypeConversionComponentOptions(properties); | ||
} catch (Exception e) { | ||
logger.warn("Invalid configuration, please review", e); | ||
this.options = null; | ||
} | ||
} | ||
|
||
public void deactivate() { | ||
} | ||
|
||
@Override | ||
public Object polled(Wire wire) { | ||
return wireSupport.polled(wire); | ||
} | ||
|
||
@Override | ||
public void consumersConnected(Wire[] wires) { | ||
wireSupport.consumersConnected(wires); | ||
} | ||
|
||
@Override | ||
public void updated(Wire wire, Object value) { | ||
wireSupport.updated(wire, value); | ||
} | ||
|
||
@Override | ||
public void producersConnected(Wire[] wires) { | ||
wireSupport.producersConnected(wires); | ||
} | ||
|
||
@Override | ||
public void onWireReceive(WireEnvelope wireEnvelope) { | ||
if (options == null) { | ||
logger.warn("Invalid configuration, please review"); | ||
} | ||
final List<WireRecord> inputRecords = wireEnvelope.getRecords(); | ||
final List<WireRecord> records = new ArrayList<>(inputRecords.size()); | ||
for (final WireRecord record : inputRecords) { | ||
records.add(processRecord(record)); | ||
} | ||
this.wireSupport.emit(records); | ||
} | ||
|
||
private WireRecord processRecord(WireRecord record) { | ||
final Map<String, TypedValue<?>> inputProperties = record.getProperties(); | ||
final Map<String, TypedValue<?>> outProperties = new HashMap<>(); | ||
if (this.options.shouldEmitReceivedProperties()) { | ||
outProperties.putAll(inputProperties); | ||
} | ||
for (TypeConversionEntry e : this.options.getEntries()) { | ||
final String propertyName = e.getPropertyName(); | ||
final TypedValue<?> typedValue = inputProperties.get(propertyName); | ||
if (typedValue == null) { | ||
continue; | ||
} | ||
final Object value = typedValue.getValue(); | ||
if (!(value instanceof Number)) { | ||
logger.warn("Invalid property value: {}={}", propertyName, typedValue); | ||
continue; | ||
} | ||
if (e.getType().equals(DataType.DOUBLE)) { | ||
outProperties.put(propertyName, | ||
TypedValues.newDoubleValue(((Number) value).doubleValue())); | ||
} else if (e.getType().equals(DataType.FLOAT)) { | ||
outProperties.put(propertyName, | ||
TypedValues.newFloatValue(((Number) value).floatValue())); | ||
} else if (e.getType().equals(DataType.INTEGER)) { | ||
outProperties.put(propertyName, | ||
TypedValues.newFloatValue(((Number) value).intValue())); | ||
} else if (e.getType().equals(DataType.LONG)) { | ||
outProperties.put(propertyName, | ||
TypedValues.newFloatValue(((Number) value).longValue())); | ||
} | ||
} | ||
return new WireRecord(outProperties); | ||
} | ||
} |
52 changes: 52 additions & 0 deletions
52
...ipse/kura/example/wire/math/singleport/typeconversion/TypeConversionComponentOptions.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/******************************************************************************* | ||
* Copyright (c) 2024 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.example.wire.math.singleport.typeconversion; | ||
|
||
import java.util.List; | ||
import java.util.Map; | ||
|
||
public class TypeConversionComponentOptions { | ||
|
||
private static final String CONFIGURATION_PROP_NAME = "channels"; | ||
private static final String EMIT_RECEIVED_PROPERTIES_PROP_NAME = "emit.received.properties"; | ||
|
||
private static final boolean EMIT_RECEIVED_PROPERTIES_DEFAULT = false; | ||
private static final String CONFIGURATION_DEFAULT = ""; | ||
|
||
private List<TypeConversionEntry> entries; | ||
private boolean emitReceivedProperties; | ||
|
||
public TypeConversionComponentOptions(final Map<String, Object> properties) { | ||
this.emitReceivedProperties = getSafe(properties.get(EMIT_RECEIVED_PROPERTIES_PROP_NAME), | ||
EMIT_RECEIVED_PROPERTIES_DEFAULT); | ||
this.entries = TypeConversionEntry | ||
.parseAll(getSafe(properties.get(CONFIGURATION_PROP_NAME), CONFIGURATION_DEFAULT)); | ||
} | ||
|
||
public List<TypeConversionEntry> getEntries() { | ||
return entries; | ||
} | ||
|
||
public boolean shouldEmitReceivedProperties() { | ||
return emitReceivedProperties; | ||
} | ||
|
||
@SuppressWarnings("unchecked") | ||
private <T> T getSafe(Object o, T defaultValue) { | ||
if (defaultValue.getClass().isInstance(o)) { | ||
return (T) o; | ||
} | ||
return defaultValue; | ||
} | ||
} |
85 changes: 85 additions & 0 deletions
85
...ava/org/eclipse/kura/example/wire/math/singleport/typeconversion/TypeConversionEntry.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
/******************************************************************************* | ||
* Copyright (c) 2024 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.example.wire.math.singleport.typeconversion; | ||
|
||
import static java.util.Objects.requireNonNull; | ||
|
||
import java.util.List; | ||
import java.util.regex.Pattern; | ||
import java.util.stream.Collectors; | ||
|
||
import org.eclipse.kura.type.DataType; | ||
|
||
public class TypeConversionEntry { | ||
|
||
private static final Pattern ENTRY_DELIMITER = Pattern.compile("[;\n]"); | ||
private static final Pattern FIELD_DELIMITER = Pattern.compile("[|]"); | ||
|
||
private final String propertyName; | ||
private final DataType type; | ||
|
||
public TypeConversionEntry(final String propertyName, final DataType type) { | ||
this.propertyName = propertyName; | ||
this.type = type; | ||
} | ||
|
||
public String getPropertyName() { | ||
return propertyName; | ||
} | ||
|
||
public DataType getType() { | ||
return type; | ||
} | ||
|
||
private static void clear(String[] entryArray) { | ||
entryArray[0] = null; | ||
entryArray[1] = null; | ||
} | ||
|
||
private static TypeConversionEntry parse(final String entryString, final String[] tempArray) { | ||
try { | ||
clear(tempArray); | ||
|
||
FIELD_DELIMITER.splitAsStream(entryString).map(String::trim).filter(s -> !s.isEmpty()) | ||
.toArray(i -> tempArray); | ||
|
||
requireNonNull(tempArray[0]); | ||
requireNonNull(tempArray[1]); | ||
String typeTemp = tempArray[1]; | ||
DataType dataType; | ||
|
||
if ("double".equalsIgnoreCase(typeTemp)) { | ||
dataType = DataType.DOUBLE; | ||
} else if ("float".equalsIgnoreCase(typeTemp)) { | ||
dataType = DataType.FLOAT; | ||
} else if ("integer".equalsIgnoreCase(typeTemp)) { | ||
dataType = DataType.INTEGER; | ||
} else if ("long".equalsIgnoreCase(typeTemp)) { | ||
dataType = DataType.LONG; | ||
} else { | ||
throw new IllegalArgumentException("Unsupported type"); | ||
} | ||
|
||
return new TypeConversionEntry(tempArray[0], dataType); | ||
} catch (Exception e) { | ||
throw new IllegalArgumentException("Invalid entry: " + entryString); | ||
} | ||
} | ||
|
||
public static List<TypeConversionEntry> parseAll(String configuration) { | ||
final String[] tempArray = new String[3]; | ||
return ENTRY_DELIMITER.splitAsStream(configuration).map(String::trim).filter(s -> !s.isEmpty()) | ||
.map(entryString -> parse(entryString, tempArray)).collect(Collectors.toList()); | ||
} | ||
} |