[automation] Added EphemerisConditions for NGRE (#915)

Signed-off-by: Christoph Weitkamp <github@christophweitkamp.de>
This commit is contained in:
Christoph Weitkamp 2019-10-20 01:37:56 +02:00 committed by Kai Kreuzer
parent 36ca073ff4
commit a3d91bebfc
18 changed files with 516 additions and 235 deletions

View File

@ -29,6 +29,11 @@
<artifactId>org.openhab.core.thing</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openhab.core.bundles</groupId>
<artifactId>org.openhab.core.ephemeris</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.openhab.core.bundles</groupId>
<artifactId>org.openhab.core.test</artifactId>

View File

@ -16,7 +16,6 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.automation.Module;
@ -34,7 +33,7 @@ import org.openhab.core.automation.Rule;
@NonNullByDefault
public abstract class BaseModuleHandlerFactory implements ModuleHandlerFactory {
private final Map<@NonNull String, @NonNull ModuleHandler> handlers = new HashMap<>();
private final Map<String, ModuleHandler> handlers = new HashMap<>();
/**
* Should be overridden by the implementations that extend this base class. Called from DS to deactivate the
@ -73,7 +72,7 @@ public abstract class BaseModuleHandlerFactory implements ModuleHandlerFactory {
/**
* Creates a new {@link ModuleHandler} for a given {@code module} and {@code ruleUID}.
*
* @param module the {@link Module} for which a handler should be created.
* @param module the {@link Module} for which a handler should be created.
* @param ruleUID the identifier of the {@link Rule} that the given module belongs to.
* @return a {@link ModuleHandler} instance or {@code null} if thins module type is not supported.
*/

View File

@ -0,0 +1,89 @@
/**
* Copyright (c) 2010-2019 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.core.automation.internal.module.factory;
import java.util.Collection;
import java.util.Collections;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.core.ephemeris.EphemerisManager;
import org.openhab.core.automation.Condition;
import org.openhab.core.automation.Module;
import org.openhab.core.automation.handler.BaseModuleHandlerFactory;
import org.openhab.core.automation.handler.ModuleHandler;
import org.openhab.core.automation.handler.ModuleHandlerFactory;
import org.openhab.core.automation.internal.module.handler.EphemerisConditionHandler;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This HandlerFactory creates ModuleHandlers to control items within the RuleManager. It contains basic Ephemeris
* Conditions.
*
* @author Christoph Weitkamp - Initial contribution
*/
@Component
@NonNullByDefault
public class EphemerisModuleHandlerFactory extends BaseModuleHandlerFactory implements ModuleHandlerFactory {
private final Logger logger = LoggerFactory.getLogger(EphemerisModuleHandlerFactory.class);
private static final Collection<String> TYPES = Collections.unmodifiableList(Stream
.of(EphemerisConditionHandler.HOLIDAY_MODULE_TYPE_ID, EphemerisConditionHandler.WEEKEND_MODULE_TYPE_ID,
EphemerisConditionHandler.WEEKDAY_MODULE_TYPE_ID, EphemerisConditionHandler.DAYSET_MODULE_TYPE_ID)
.collect(Collectors.toList()));
private final EphemerisManager ephemerisManager;
@Activate
public EphemerisModuleHandlerFactory(final @Reference EphemerisManager ephemerisManager) {
this.ephemerisManager = ephemerisManager;
}
@Override
@Deactivate
protected void deactivate() {
super.deactivate();
}
@Override
public Collection<String> getTypes() {
return TYPES;
}
@Override
protected @Nullable ModuleHandler internalCreate(final Module module, final String ruleUID) {
final String moduleTypeUID = module.getTypeUID();
logger.trace("create {} -> {} : {}", module.getId(), moduleTypeUID, ruleUID);
if (module instanceof Condition) {
switch (moduleTypeUID) {
case EphemerisConditionHandler.HOLIDAY_MODULE_TYPE_ID:
case EphemerisConditionHandler.WEEKEND_MODULE_TYPE_ID:
case EphemerisConditionHandler.WEEKDAY_MODULE_TYPE_ID:
case EphemerisConditionHandler.DAYSET_MODULE_TYPE_ID:
return new EphemerisConditionHandler((Condition) module, ephemerisManager);
}
}
logger.error("The ModuleHandler is not supported: {}", moduleTypeUID);
return null;
}
}

View File

@ -93,7 +93,7 @@ public class CompareConditionHandler extends BaseConditionModuleHandler {
case "GT":
case ">":
// Greater
if (toCompare == null || rightValue == null) {
if (toCompare == null) {
return false;
} else {
return compare(toCompare, rightValue) > 0;
@ -103,7 +103,7 @@ public class CompareConditionHandler extends BaseConditionModuleHandler {
case ">=":
case "=>":
// Greater or equal
if (toCompare == null || rightValue == null) {
if (toCompare == null) {
return false;
} else {
return compare(toCompare, rightValue) >= 0;
@ -111,7 +111,7 @@ public class CompareConditionHandler extends BaseConditionModuleHandler {
case "lt":
case "LT":
case "<":
if (toCompare == null || rightValue == null) {
if (toCompare == null) {
return false;
} else {
return compare(toCompare, rightValue) < 0;
@ -120,14 +120,14 @@ public class CompareConditionHandler extends BaseConditionModuleHandler {
case "LTE":
case "<=":
case "=<":
if (toCompare == null || rightValue == null) {
if (toCompare == null) {
return false;
} else {
return compare(toCompare, rightValue) <= 0;
}
case "matches":
// Matcher...
if (toCompare instanceof String && rightValue != null && rightValue instanceof String) {
if (toCompare instanceof String && rightValue instanceof String) {
return ((String) toCompare).matches((String) rightValue);
}
default:

View File

@ -0,0 +1,94 @@
/**
* Copyright (c) 2010-2019 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.core.automation.internal.module.handler;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.smarthome.config.core.Configuration;
import org.eclipse.smarthome.core.ephemeris.EphemerisManager;
import org.openhab.core.automation.Condition;
import org.openhab.core.automation.handler.BaseModuleHandler;
import org.openhab.core.automation.handler.ConditionHandler;
/**
* ConditionHandler implementation for Ephemeris based conditions.
*
* @author Christoph Weitkamp - Initial contribution
*/
@NonNullByDefault
public class EphemerisConditionHandler extends BaseModuleHandler<Condition> implements ConditionHandler {
public static final String HOLIDAY_MODULE_TYPE_ID = "ephemeris.HolidayCondition";
public static final String WEEKEND_MODULE_TYPE_ID = "ephemeris.WeekendCondition";
public static final String WEEKDAY_MODULE_TYPE_ID = "ephemeris.WeekdayCondition";
public static final String DAYSET_MODULE_TYPE_ID = "ephemeris.DaysetCondition";
private static final String DAYSET = "dayset";
private static final String OFFSET = "offset";
private final EphemerisManager ephemerisManager;
private final @Nullable String dayset;
private final int offset;
public EphemerisConditionHandler(Condition condition, EphemerisManager ephemerisManager) {
super(condition);
this.ephemerisManager = ephemerisManager;
this.dayset = DAYSET_MODULE_TYPE_ID.equals(module.getTypeUID())
? getValidStringConfigParameter(DAYSET, module.getConfiguration(), module.getId())
: null;
this.offset = getValidIntegerConfigParameter(OFFSET, module.getConfiguration(), module.getId());
}
private static int getValidIntegerConfigParameter(String parameter, Configuration config, String moduleId) {
Object value = config.get(parameter);
if (value != null && value instanceof Integer) {
return (Integer) value;
} else {
throw new IllegalStateException(String.format(
"Config parameter '%s' is missing in the configuration of module '%s'.", parameter, moduleId));
}
}
private static String getValidStringConfigParameter(String parameter, Configuration config, String moduleId) {
Object value = config.get(parameter);
if (value != null && value instanceof String && !((String) value).trim().isEmpty()) {
return (String) value;
} else {
throw new IllegalStateException(String.format(
"Config parameter '%s' is missing in the configuration of module '%s'.", parameter, moduleId));
}
}
@Override
public boolean isSatisfied(Map<String, Object> inputs) {
switch (module.getTypeUID()) {
case HOLIDAY_MODULE_TYPE_ID:
return ephemerisManager.isBankHoliday(offset);
case WEEKEND_MODULE_TYPE_ID:
return ephemerisManager.isWeekend(offset);
case WEEKDAY_MODULE_TYPE_ID:
return !ephemerisManager.isWeekend(offset);
case DAYSET_MODULE_TYPE_ID:
final String dayset = this.dayset;
if (dayset != null) {
return ephemerisManager.isInDayset(dayset, offset);
}
break;
}
// If none of these conditions apply false is returned.
return false;
}
}

View File

@ -1,20 +1,20 @@
{
"conditions":[
{
"uid":"timer.DayOfWeekCondition",
"label":"it is a certain day of the week",
"description":"checks for the current day of the week",
"configDescriptions":[
{
"name":"days",
"context":"dayOfWeek",
"type":"TEXT",
"label":"Days of the week",
"description":"the days of the week when the rule should be active",
"required":true,
"multiple":true
}
]
}
]
{
"conditions": [
{
"uid": "timer.DayOfWeekCondition",
"label": "it is a certain day of the week",
"description": "checks for the current day of the week",
"configDescriptions": [
{
"name": "days",
"context": "dayOfWeek",
"type": "TEXT",
"label": "Days of the week",
"description": "the days of the week when the rule should be active",
"required": true,
"multiple": true
}
]
}
]
}

View File

@ -0,0 +1,75 @@
{
"conditions": [
{
"uid": "ephemeris.HolidayCondition",
"label": "It is a holiday",
"description": "Checks if the current day is a holiday.",
"configDescriptions": [
{
"name": "offset",
"type": "integer",
"label": "Offset",
"description": "Today +/- offset days (+1 = tomorrow, -1 = yesterday).",
"default": 0,
"step": 1,
"required": false
}
]
},
{
"uid": "ephemeris.WeekendCondition",
"label": "It is a weekend",
"description": "Checks if the current day is on the weekend.",
"configDescriptions": [
{
"name": "offset",
"type": "integer",
"label": "Offset",
"description": "Today +/- offset days (+1 = tomorrow, -1 = yesterday).",
"default": 0,
"step": 1,
"required": false
}
]
},
{
"uid": "ephemeris.WeekdayCondition",
"label": "It is a weekday",
"description": "Checks if the current day is not on the weekend.",
"configDescriptions": [
{
"name": "offset",
"type": "integer",
"label": "Offset",
"description": "Today +/- offset days (+1 = tomorrow, -1 = yesterday).",
"default": 0,
"step": 1,
"required": false
}
]
},
{
"uid": "ephemeris.DaysetCondition",
"label": "It is a day in a configured dayset",
"description": "Checks if the current day is in a configured dayset.",
"configDescriptions": [
{
"name": "dayset",
"type": "text",
"label": "Dayset",
"description": "Name of the requested dayset, without prefix.",
"required": true
},
{
"name": "offset",
"type": "integer",
"label": "Offset",
"description": "Today +/- offset days (+1 = tomorrow, -1 = yesterday).",
"default": 0,
"step": 1,
"required": false
}
]
}
]
}

View File

@ -1,83 +1,83 @@
{
"conditions":[
{
"uid":"core.GenericEventCondition",
"label":"Event Condition",
"description":"Condition for events",
"visibility":"HIDDEN",
"configDescriptions":[
{
"name":"topic",
"type":"TEXT",
"description":"topic should match",
"required":false
},
{
"name":"eventType",
"type":"TEXT",
"description":"eventType should match",
"required":false
},
{
"name":"source",
"type":"TEXT",
"description":"source should match",
"required":false
},
{
"name":"payload",
"type":"TEXT",
"description":"payload should match",
"required":false
}
],
"inputs":[
{
"name":"event",
"type":"org.eclipse.smarthome.core.events.Event",
"label":"Event",
"description":"The events which was sent.",
"required":true
}
]
},
{
"uid":"core.GenericCompareCondition",
"label":"CompareCondition",
"description":"configurable compare condition",
"visibility":"HIDDEN",
"configDescriptions":[
{
"name":"inputproperty",
"label":"Input property",
"type":"TEXT",
"description":"property of the input type to be compared",
"required":false
},
{
"name":"right",
"type":"TEXT",
"label":"compare with",
"description":"the value to be compared with the input",
"required":true
},
{
"name":"operator",
"type":"TEXT",
"description":"the compare operator, allowed are <,>,=,!=,>=,<= matches",
"required":true,
"default":"="
}
],
"inputs": [
{
"name":"input",
"type": "java.lang.Object",
"label": "input which will be compared",
"description": "The input which will be compared.",
"required":true
}
]
}
]
{
"conditions": [
{
"uid": "core.GenericEventCondition",
"label": "Event Condition",
"description": "Condition for events",
"visibility": "HIDDEN",
"configDescriptions": [
{
"name": "topic",
"type": "TEXT",
"description": "topic should match",
"required": false
},
{
"name": "eventType",
"type": "TEXT",
"description": "eventType should match",
"required": false
},
{
"name": "source",
"type": "TEXT",
"description": "source should match",
"required": false
},
{
"name": "payload",
"type": "TEXT",
"description": "payload should match",
"required": false
}
],
"inputs": [
{
"name": "event",
"type": "org.eclipse.smarthome.core.events.Event",
"label": "Event",
"description": "The events which was sent.",
"required": true
}
]
},
{
"uid": "core.GenericCompareCondition",
"label": "CompareCondition",
"description": "configurable compare condition",
"visibility": "HIDDEN",
"configDescriptions": [
{
"name": "inputproperty",
"label": "Input property",
"type": "TEXT",
"description": "property of the input type to be compared",
"required": false
},
{
"name": "right",
"type": "TEXT",
"label": "compare with",
"description": "the value to be compared with the input",
"required": true
},
{
"name": "operator",
"type": "TEXT",
"description": "the compare operator, allowed are <,>,=,!=,>=,<= matches",
"required": true,
"default": "="
}
],
"inputs": [
{
"name": "input",
"type": "java.lang.Object",
"label": "input which will be compared",
"description": "The input which will be compared.",
"required": true
}
]
}
]
}

View File

@ -1,88 +1,88 @@
{
"conditions":[
{
"uid":"core.ItemStateCondition",
"label":"an item has a given state",
"description":"Compares the item state with the given value",
"configDescriptions":[
{
"name":"itemName",
"type":"TEXT",
"label":"Item",
"context":"item",
"description":"the name of the item",
"required":true
},
{
"name":"operator",
"type":"TEXT",
"label":"Operator",
"description":"the compare operator (one of =,<,>,!=,>=,<=)",
"required":false,
"limitToOptions":true,
"options":[
{
"label": "=",
"value": "="
},
{
"label": "!=",
"value": "!="
},
{
"label": ">",
"value": ">"
},
{
"label": ">=",
"value": ">="
},
{
"label": "<",
"value": "<"
},
{
"label": "<=",
"value": "<="
}
],
"default":"="
},
{
"name":"state",
"type":"TEXT",
"label":"State",
"description":"the state to be compared with",
"required":true,
"limitToOptions":false,
"options":[
{
"label": "ON",
"value": "ON"
},
{
"label": "OFF",
"value": "OFF"
},
{
"label": "OPEN",
"value": "OPEN"
},
{
"label": "CLOSED",
"value": "CLOSED"
},
{
"label": "UP",
"value": "UP"
},
{
"label": "DOWN",
"value": "DOWN"
}
]
}
]
}
]
{
"conditions": [
{
"uid": "core.ItemStateCondition",
"label": "an item has a given state",
"description": "Compares the item state with the given value",
"configDescriptions": [
{
"name": "itemName",
"type": "TEXT",
"label": "Item",
"context": "item",
"description": "the name of the item",
"required": true
},
{
"name": "operator",
"type": "TEXT",
"label": "Operator",
"description": "the compare operator (one of =,<,>,!=,>=,<=)",
"required": false,
"limitToOptions": true,
"options": [
{
"label": "=",
"value": "="
},
{
"label": "!=",
"value": "!="
},
{
"label": ">",
"value": ">"
},
{
"label": ">=",
"value": ">="
},
{
"label": "<",
"value": "<"
},
{
"label": "<=",
"value": "<="
}
],
"default": "="
},
{
"name": "state",
"type": "TEXT",
"label": "State",
"description": "the state to be compared with",
"required": true,
"limitToOptions": false,
"options": [
{
"label": "ON",
"value": "ON"
},
{
"label": "OFF",
"value": "OFF"
},
{
"label": "OPEN",
"value": "OPEN"
},
{
"label": "CLOSED",
"value": "CLOSED"
},
{
"label": "UP",
"value": "UP"
},
{
"label": "DOWN",
"value": "DOWN"
}
]
}
]
}
]
}

View File

@ -1,27 +1,27 @@
{
"conditions":[
{
"uid":"core.TimeOfDayCondition",
"label":"it is a certain time of day",
"description":"Evaluates if the current time is within a user-configured time span.",
"configDescriptions":[
{
"name":"startTime",
"context":"time",
"type":"TEXT",
"label":"Start Time",
"description":"Start of the time span (in hh:mm)",
"required":true
},
{
"name":"endTime",
"context":"time",
"type":"TEXT",
"label":"End Time",
"description":"End of the time span (in hh:mm)",
"required":true
}
]
}
]
{
"conditions": [
{
"uid": "core.TimeOfDayCondition",
"label": "it is a certain time of day",
"description": "Evaluates if the current time is within a user-configured time span.",
"configDescriptions": [
{
"name": "startTime",
"context": "time",
"type": "TEXT",
"label": "Start Time",
"description": "Start of the time span (in hh:mm)",
"required": true
},
{
"name": "endTime",
"context": "time",
"type": "TEXT",
"label": "End Time",
"description": "End of the time span (in hh:mm)",
"required": true
}
]
}
]
}

View File

@ -37,7 +37,7 @@ public interface EphemerisManager {
/**
* Tests given day (related to today) status against configured dayset
*
* @param daysetName name of the requested dayset, witout prefix
* @param daysetName name of the requested dayset, without prefix
* @param offset Today +/- offset days (+1 = tomorrow, -1 = yesterday)
* @return whether the day is on weekend
*/

View File

@ -73,6 +73,7 @@
<feature name="openhab-core-automation" version="${project.version}">
<feature>openhab-core-base</feature>
<feature>openhab-core-ephemeris</feature>
<bundle>mvn:org.openhab.core.bundles/org.openhab.core.automation/${project.version}</bundle>
</feature>

View File

@ -45,4 +45,7 @@ Bundle-SymbolicName: ${project.artifactId}
osgi.enroute.junit.wrapper;version='[4.12.0,4.12.1)',\
slf4j.api;version='[1.7.25,1.7.26)',\
tec.uom.lib.uom-lib-common;version='[1.0.3,1.0.4)',\
tec.uom.se;version='[1.0.10,1.0.11)'
tec.uom.se;version='[1.0.10,1.0.11)',\
jollyday;version='[0.5.8,0.5.9)',\
org.openhab.core.ephemeris;version='[2.5.0,2.5.1)',\
org.threeten.extra;version='[1.4.0,1.4.1)'

View File

@ -41,4 +41,7 @@ Fragment-Host: org.openhab.core.automation
osgi.enroute.junit.wrapper;version='[4.12.0,4.12.1)',\
slf4j.api;version='[1.7.25,1.7.26)',\
tec.uom.lib.uom-lib-common;version='[1.0.3,1.0.4)',\
tec.uom.se;version='[1.0.10,1.0.11)'
tec.uom.se;version='[1.0.10,1.0.11)',\
jollyday;version='[0.5.8,0.5.9)',\
org.openhab.core.ephemeris;version='[2.5.0,2.5.1)',\
org.threeten.extra;version='[1.4.0,1.4.1)'

View File

@ -41,4 +41,7 @@ Bundle-SymbolicName: ${project.artifactId}
osgi.enroute.junit.wrapper;version='[4.12.0,4.12.1)',\
slf4j.api;version='[1.7.25,1.7.26)',\
tec.uom.lib.uom-lib-common;version='[1.0.3,1.0.4)',\
tec.uom.se;version='[1.0.10,1.0.11)'
tec.uom.se;version='[1.0.10,1.0.11)',\
jollyday;version='[0.5.8,0.5.9)',\
org.openhab.core.ephemeris;version='[2.5.0,2.5.1)',\
org.threeten.extra;version='[1.4.0,1.4.1)'

View File

@ -42,4 +42,7 @@ Fragment-Host: org.openhab.core.automation.module.script
osgi.enroute.junit.wrapper;version='[4.12.0,4.12.1)',\
slf4j.api;version='[1.7.25,1.7.26)',\
tec.uom.lib.uom-lib-common;version='[1.0.3,1.0.4)',\
tec.uom.se;version='[1.0.10,1.0.11)'
tec.uom.se;version='[1.0.10,1.0.11)',\
jollyday;version='[0.5.8,0.5.9)',\
org.openhab.core.ephemeris;version='[2.5.0,2.5.1)',\
org.threeten.extra;version='[1.4.0,1.4.1)'

View File

@ -41,4 +41,7 @@ Fragment-Host: org.openhab.core.automation
org.openhab.core.test;version='[2.5.0,2.5.1)',\
slf4j.api;version='[1.7.25,1.7.26)',\
tec.uom.lib.uom-lib-common;version='[1.0.3,1.0.4)',\
tec.uom.se;version='[1.0.10,1.0.11)'
tec.uom.se;version='[1.0.10,1.0.11)',\
jollyday;version='[0.5.8,0.5.9)',\
org.openhab.core.ephemeris;version='[2.5.0,2.5.1)',\
org.threeten.extra;version='[1.4.0,1.4.1)'

View File

@ -14,12 +14,20 @@ Fragment-Host: org.openhab.core.automation
# done
#
-runbundles: \
ch.qos.logback.classic;version='[1.2.3,1.2.4)',\
ch.qos.logback.core;version='[1.2.3,1.2.4)',\
com.google.gson;version='[2.8.2,2.8.3)',\
javax.measure.unit-api;version='[1.0.0,1.0.1)',\
jollyday;version='[0.5.8,0.5.9)',\
org.apache.commons.collections;version='[3.2.1,3.2.2)',\
org.apache.commons.io;version='[2.2.0,2.2.1)',\
org.apache.commons.lang;version='[2.6.0,2.6.1)',\
org.apache.felix.http.servlet-api;version='[1.1.2,1.1.3)',\
org.apache.felix.scr;version='[2.1.10,2.1.11)',\
org.apache.servicemix.specs.activation-api-1.1;version='[2.9.0,2.9.1)',\
org.apache.servicemix.specs.annotation-api-1.3;version='[1.3.0,1.3.1)',\
org.apache.servicemix.specs.jaxb-api-2.2;version='[2.9.0,2.9.1)',\
org.apache.servicemix.specs.stax-api-1.2;version='[2.9.0,2.9.1)',\
org.eclipse.equinox.event;version='[1.4.300,1.4.301)',\
org.eclipse.jetty.http;version='[9.4.11,9.4.12)',\
org.eclipse.jetty.io;version='[9.4.11,9.4.12)',\
@ -31,19 +39,14 @@ Fragment-Host: org.openhab.core.automation
org.openhab.core.automation;version='[2.5.0,2.5.1)',\
org.openhab.core.automation.tests;version='[2.5.0,2.5.1)',\
org.openhab.core.config.core;version='[2.5.0,2.5.1)',\
org.openhab.core.ephemeris;version='[2.5.0,2.5.1)',\
org.openhab.core.io.console;version='[2.5.0,2.5.1)',\
org.openhab.core.test;version='[2.5.0,2.5.1)',\
org.openhab.core.thing;version='[2.5.0,2.5.1)',\
org.osgi.service.event;version='[1.4.0,1.4.1)',\
org.threeten.extra;version='[1.4.0,1.4.1)',\
osgi.enroute.hamcrest.wrapper;version='[1.3.0,1.3.1)',\
osgi.enroute.junit.wrapper;version='[4.12.0,4.12.1)',\
ch.qos.logback.core;version='[1.2.3,1.2.4)',\
slf4j.api;version='[1.7.25,1.7.26)',\
ch.qos.logback.classic;version='[1.2.3,1.2.4)',\
com.google.gson;version='[2.8.2,2.8.3)',\
org.apache.servicemix.specs.activation-api-1.1;version='[2.9.0,2.9.1)',\
org.apache.servicemix.specs.annotation-api-1.3;version='[1.3.0,1.3.1)',\
org.apache.servicemix.specs.jaxb-api-2.2;version='[2.9.0,2.9.1)',\
org.apache.servicemix.specs.stax-api-1.2;version='[2.9.0,2.9.1)',\
tec.uom.lib.uom-lib-common;version='[1.0.3,1.0.4)',\
tec.uom.se;version='[1.0.10,1.0.11)'