Updated license headers

Signed-off-by: Kai Kreuzer <kai@openhab.org>
This commit is contained in:
Wouter Born 2021-01-02 22:03:14 +01:00 committed by Kai Kreuzer
parent 734c3b06ff
commit 6f9c605eeb
8143 changed files with 12932 additions and 8236 deletions

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
@ -10,7 +10,6 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
@org.osgi.annotation.bundle.Header(name = org.osgi.framework.Constants.DYNAMICIMPORT_PACKAGE, value = "*")
package org.openhab.automation.groovyscripting.internal;

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
@ -10,7 +10,6 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
@org.osgi.annotation.bundle.Header(name = org.osgi.framework.Constants.DYNAMICIMPORT_PACKAGE, value = "*")
package org.openhab.automation.jythonscripting;

View File

@ -0,0 +1,44 @@
/**
* Copyright (c) 2010-2021 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.automation.pidcontroller.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
* Realizes an first-order FIR low pass filter. To keep code complexity low, it is implemented as moving average (all
* FIR coefficients are set to normalized ones).
*
* The exponential decaying function is used for the calculation (see https://en.wikipedia.org/wiki/Time_constant). That
* means the output value is approx. 63% of the input value after one time constant and approx. 99% after 5 time
* constants.
*
* @author Fabian Wolter - Initial contribution
*
*/
@NonNullByDefault
public class LowpassFilter {
/**
* Executes one low pass filter step.
*
* @param lastOutput the current filter value (result of the last invocation)
* @param newValue the just sampled value
* @param timeQuotient quotient of the current time and the time constant
* @return the new filter value
*/
public static double calculate(double lastOutput, double newValue, double timeQuotient) {
double output = lastOutput * Math.exp(-timeQuotient);
output += newValue * (1 - Math.exp(-timeQuotient));
return output;
}
}

View File

@ -0,0 +1,41 @@
/**
* Copyright (c) 2010-2021 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.automation.pidcontroller.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
*
* Constants for PID controller.
*
* @author Fabian Wolter - Initial contribution
*
*/
@NonNullByDefault
public class PIDControllerConstants {
public static final String AUTOMATION_NAME = "pidcontroller";
public static final String CONFIG_INPUT_ITEM = "input";
public static final String CONFIG_SETPOINT_ITEM = "setpoint";
public static final String CONFIG_OUTPUT_LOWER_LIMIT = "outputLowerLimit";
public static final String CONFIG_OUTPUT_UPPER_LIMIT = "outputUpperLimit";
public static final String CONFIG_LOOP_TIME = "loopTime";
public static final String CONFIG_KP_GAIN = "kp";
public static final String CONFIG_KI_GAIN = "ki";
public static final String CONFIG_KD_GAIN = "kd";
public static final String CONFIG_KD_TIMECONSTANT = "kdTimeConstant";
public static final String P_INSPECTOR = "pInspector";
public static final String I_INSPECTOR = "iInspector";
public static final String D_INSPECTOR = "dInspector";
public static final String E_INSPECTOR = "eInspector";
public static final String OUTPUT = "output";
}

View File

@ -0,0 +1,31 @@
/**
* Copyright (c) 2010-2021 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.automation.pidcontroller.internal;
import org.eclipse.jdt.annotation.NonNullByDefault;
/**
*
* Common Exception for PID controller.
*
* @author Fabian Wolter - Initial contribution
*
*/
@NonNullByDefault
public class PIDException extends Exception {
private static final long serialVersionUID = -3029834022610530982L;
public PIDException(String message) {
super(message);
}
}

View File

@ -0,0 +1,72 @@
/**
* Copyright (c) 2010-2021 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.automation.pidcontroller.internal.factory;
import java.util.Collection;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.automation.pidcontroller.internal.handler.PIDControllerActionHandler;
import org.openhab.automation.pidcontroller.internal.handler.PIDControllerTriggerHandler;
import org.openhab.core.automation.Action;
import org.openhab.core.automation.Module;
import org.openhab.core.automation.Trigger;
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.events.EventPublisher;
import org.openhab.core.items.ItemRegistry;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
/**
*
* @author Hilbrand Bouwkamp - Initial Contribution
*/
@Component(service = ModuleHandlerFactory.class, configurationPid = "action.pidcontroller")
@NonNullByDefault
public class PIDControllerModuleHandlerFactory extends BaseModuleHandlerFactory {
private static final Collection<String> TYPES = Set.of(PIDControllerTriggerHandler.MODULE_TYPE_ID,
PIDControllerActionHandler.MODULE_TYPE_ID);
private ItemRegistry itemRegistry;
private EventPublisher eventPublisher;
private BundleContext bundleContext;
@Activate
public PIDControllerModuleHandlerFactory(@Reference ItemRegistry itemRegistry,
@Reference EventPublisher eventPublisher, BundleContext bundleContext) {
this.itemRegistry = itemRegistry;
this.eventPublisher = eventPublisher;
this.bundleContext = bundleContext;
}
@Override
public Collection<String> getTypes() {
return TYPES;
}
@Override
protected @Nullable ModuleHandler internalCreate(Module module, String ruleUID) {
switch (module.getTypeUID()) {
case PIDControllerTriggerHandler.MODULE_TYPE_ID:
return new PIDControllerTriggerHandler((Trigger) module, itemRegistry, eventPublisher, bundleContext);
case PIDControllerActionHandler.MODULE_TYPE_ID:
return new PIDControllerActionHandler((Action) module, itemRegistry, eventPublisher);
}
return null;
}
}

View File

@ -0,0 +1,82 @@
/**
* Copyright (c) 2010-2021 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.automation.pidcontroller.internal.handler;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.automation.pidcontroller.internal.LowpassFilter;
/**
* The {@link PIDController} provides the necessary methods for retrieving part(s) of the PID calculations
* and it provides the method for the overall PID calculations. It also resets the PID controller
*
* @author George Erhan - Initial contribution
* @author Hilbrand Bouwkamp - Adapted for new rule engine
* @author Fabian Wolter - Add T1 to D part, add debugging ability for PID values
*/
@NonNullByDefault
class PIDController {
private final double outputLowerLimit;
private final double outputUpperLimit;
private double integralResult;
private double derivativeResult;
private double previousError;
private double output;
private double kp;
private double ki;
private double kd;
private double derivativeTimeConstantSec;
public PIDController(double outputLowerLimit, double outputUpperLimit, double kpAdjuster, double kiAdjuster,
double kdAdjuster, double derivativeTimeConstantSec) {
this.outputLowerLimit = outputLowerLimit;
this.outputUpperLimit = outputUpperLimit;
this.kp = kpAdjuster;
this.ki = kiAdjuster;
this.kd = kdAdjuster;
this.derivativeTimeConstantSec = derivativeTimeConstantSec;
}
public PIDOutputDTO calculate(double input, double setpoint, long lastInvocationMs) {
final double lastInvocationSec = lastInvocationMs / 1000d;
final double error = setpoint - input;
// derivative T1 calculation
final double timeQuotient = lastInvocationSec / derivativeTimeConstantSec;
if (derivativeTimeConstantSec != 0) {
derivativeResult = LowpassFilter.calculate(derivativeResult, error - previousError, timeQuotient);
previousError = error;
}
// integral calculation
integralResult += error * lastInvocationSec;
// limit to output limits
if (ki != 0) {
final double maxIntegral = outputUpperLimit / ki;
final double minIntegral = outputLowerLimit / ki;
integralResult = Math.min(maxIntegral, Math.max(minIntegral, integralResult));
}
// calculate parts
final double proportionalPart = kp * error;
final double integralPart = ki * integralResult;
final double derivativePart = kd * derivativeResult;
output = proportionalPart + integralPart + derivativePart;
// limit output value
output = Math.min(outputUpperLimit, Math.max(outputLowerLimit, output));
return new PIDOutputDTO(output, proportionalPart, integralPart, derivativePart, error);
}
}

View File

@ -0,0 +1,78 @@
/**
* Copyright (c) 2010-2021 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.automation.pidcontroller.internal.handler;
import static org.openhab.automation.pidcontroller.internal.PIDControllerConstants.*;
import java.math.BigDecimal;
import java.util.Map;
import java.util.stream.Stream;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.automation.Action;
import org.openhab.core.automation.handler.ActionHandler;
import org.openhab.core.automation.handler.BaseModuleHandler;
import org.openhab.core.events.EventPublisher;
import org.openhab.core.items.ItemRegistry;
import org.openhab.core.items.events.ItemCommandEvent;
import org.openhab.core.items.events.ItemEventFactory;
import org.openhab.core.library.types.DecimalType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author Hilbrand Bouwkamp - Initial Contribution
* @author Fabian Wolter - Add PID debugging items
*/
@NonNullByDefault
public class PIDControllerActionHandler extends BaseModuleHandler<Action> implements ActionHandler {
public static final String MODULE_TYPE_ID = AUTOMATION_NAME + ".action";
private final Logger logger = LoggerFactory.getLogger(PIDControllerActionHandler.class);
private ItemRegistry itemRegistry;
private EventPublisher eventPublisher;
public PIDControllerActionHandler(Action module, ItemRegistry itemRegistry, EventPublisher eventPublisher) {
super(module);
this.itemRegistry = itemRegistry;
this.eventPublisher = eventPublisher;
}
@Override
public @Nullable Map<String, Object> execute(Map<String, Object> context) {
Stream.of(OUTPUT, P_INSPECTOR, I_INSPECTOR, D_INSPECTOR, E_INSPECTOR).forEach(arg -> {
final String itemName = (String) module.getConfiguration().get(arg);
if (itemName == null || itemName.isBlank()) {
return;
}
final BigDecimal command = (BigDecimal) context.get("1." + arg);
if (command != null) {
final DecimalType outputValue = new DecimalType(command);
final ItemCommandEvent itemCommandEvent = ItemEventFactory.createCommandEvent(itemName, outputValue);
eventPublisher.post(itemCommandEvent);
} else {
logger.warn(
"Command was not posted because either the configuration was not correct or a service was missing: ItemName: {}, Command: {}, eventPublisher: {}, ItemRegistry: {}",
itemName, command, eventPublisher, itemRegistry);
}
});
return null;
}
}

View File

@ -0,0 +1,226 @@
/**
* Copyright (c) 2010-2021 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.automation.pidcontroller.internal.handler;
import static org.openhab.automation.pidcontroller.internal.PIDControllerConstants.*;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.automation.pidcontroller.internal.PIDException;
import org.openhab.core.automation.ModuleHandlerCallback;
import org.openhab.core.automation.Trigger;
import org.openhab.core.automation.handler.BaseTriggerModuleHandler;
import org.openhab.core.automation.handler.TriggerHandlerCallback;
import org.openhab.core.common.NamedThreadFactory;
import org.openhab.core.config.core.Configuration;
import org.openhab.core.events.Event;
import org.openhab.core.events.EventFilter;
import org.openhab.core.events.EventPublisher;
import org.openhab.core.events.EventSubscriber;
import org.openhab.core.items.Item;
import org.openhab.core.items.ItemNotFoundException;
import org.openhab.core.items.ItemRegistry;
import org.openhab.core.items.events.ItemEventFactory;
import org.openhab.core.items.events.ItemStateChangedEvent;
import org.openhab.core.items.events.ItemStateEvent;
import org.openhab.core.library.types.StringType;
import org.openhab.core.types.RefreshType;
import org.openhab.core.types.State;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author Hilbrand Bouwkamp - Initial Contribution
* @author Fabian Wolter - Add PID debug output values
*/
@NonNullByDefault
public class PIDControllerTriggerHandler extends BaseTriggerModuleHandler implements EventSubscriber {
public static final String MODULE_TYPE_ID = AUTOMATION_NAME + ".trigger";
private static final Set<String> SUBSCRIBED_EVENT_TYPES = Set.of(ItemStateEvent.TYPE, ItemStateChangedEvent.TYPE);
private final Logger logger = LoggerFactory.getLogger(PIDControllerTriggerHandler.class);
private final ScheduledExecutorService scheduler = Executors
.newSingleThreadScheduledExecutor(new NamedThreadFactory("OH-automation-" + AUTOMATION_NAME, true));
private final ServiceRegistration<?> eventSubscriberRegistration;
private final PIDController controller;
private final int loopTimeMs;
private @Nullable ScheduledFuture<?> controllerjob;
private long previousTimeMs = System.currentTimeMillis();
private Item inputItem;
private Item setpointItem;
private EventFilter eventFilter;
public PIDControllerTriggerHandler(Trigger module, ItemRegistry itemRegistry, EventPublisher eventPublisher,
BundleContext bundleContext) {
super(module);
Configuration config = module.getConfiguration();
String inputItemName = (String) requireNonNull(config.get(CONFIG_INPUT_ITEM), "Input item is not set");
String setpointItemName = (String) requireNonNull(config.get(CONFIG_SETPOINT_ITEM), "Setpoint item is not set");
try {
inputItem = itemRegistry.getItem(inputItemName);
} catch (ItemNotFoundException e) {
throw new IllegalArgumentException("Configured input item not found: " + inputItemName, e);
}
try {
setpointItem = itemRegistry.getItem(setpointItemName);
} catch (ItemNotFoundException e) {
throw new IllegalArgumentException("Configured setpoint item not found: " + setpointItemName, e);
}
double outputLowerLimit = getDoubleFromConfig(config, CONFIG_OUTPUT_LOWER_LIMIT);
double outputUpperLimit = getDoubleFromConfig(config, CONFIG_OUTPUT_UPPER_LIMIT);
double kpAdjuster = getDoubleFromConfig(config, CONFIG_KP_GAIN);
double kiAdjuster = getDoubleFromConfig(config, CONFIG_KI_GAIN);
double kdAdjuster = getDoubleFromConfig(config, CONFIG_KD_GAIN);
double kdTimeConstant = getDoubleFromConfig(config, CONFIG_KD_TIMECONSTANT);
loopTimeMs = ((BigDecimal) requireNonNull(config.get(CONFIG_LOOP_TIME), CONFIG_LOOP_TIME + " is not set"))
.intValue();
controller = new PIDController(outputLowerLimit, outputUpperLimit, kpAdjuster, kiAdjuster, kdAdjuster,
kdTimeConstant);
eventFilter = event -> {
String topic = event.getTopic();
return topic.equals("openhab/items/" + inputItemName + "/state")
|| topic.equals("openhab/items/" + inputItemName + "/statechanged")
|| topic.equals("openhab/items/" + setpointItemName + "/statechanged");
};
eventSubscriberRegistration = bundleContext.registerService(EventSubscriber.class.getName(), this, null);
eventPublisher.post(ItemEventFactory.createCommandEvent(inputItemName, RefreshType.REFRESH));
controllerjob = scheduler.scheduleWithFixedDelay(this::calculate, 0, loopTimeMs, TimeUnit.MILLISECONDS);
}
private <T> T requireNonNull(T obj, String message) {
if (obj == null) {
throw new IllegalArgumentException(message);
}
return obj;
}
private double getDoubleFromConfig(Configuration config, String key) {
return ((BigDecimal) Objects.requireNonNull(config.get(key), key + " is not set")).doubleValue();
}
private void calculate() {
double input;
double setpoint;
try {
input = getItemValueAsNumber(inputItem);
} catch (PIDException e) {
logger.warn("Input item: {}", e.getMessage());
return;
}
try {
setpoint = getItemValueAsNumber(setpointItem);
} catch (PIDException e) {
logger.warn("Setpoint item: {}", e.getMessage());
return;
}
long now = System.currentTimeMillis();
PIDOutputDTO output = controller.calculate(input, setpoint, now - previousTimeMs);
previousTimeMs = now;
Map<String, BigDecimal> outputs = new HashMap<>();
putBigDecimal(outputs, OUTPUT, output.getOutput());
putBigDecimal(outputs, P_INSPECTOR, output.getProportionalPart());
putBigDecimal(outputs, I_INSPECTOR, output.getIntegralPart());
putBigDecimal(outputs, D_INSPECTOR, output.getDerivativePart());
putBigDecimal(outputs, E_INSPECTOR, output.getError());
ModuleHandlerCallback localCallback = callback;
if (localCallback != null && localCallback instanceof TriggerHandlerCallback) {
((TriggerHandlerCallback) localCallback).triggered(module, outputs);
} else {
logger.warn("No callback set");
}
}
private void putBigDecimal(Map<String, BigDecimal> map, String key, double value) {
map.put(key, BigDecimal.valueOf(value));
}
private double getItemValueAsNumber(Item item) throws PIDException {
State setpointState = item.getState();
if (setpointState instanceof Number) {
double doubleValue = ((Number) setpointState).doubleValue();
if (Double.isFinite(doubleValue)) {
return doubleValue;
}
} else if (setpointState instanceof StringType) {
try {
return Double.parseDouble(setpointState.toString());
} catch (NumberFormatException e) {
// nothing
}
}
throw new PIDException(
"Item type is not a number: " + setpointState.getClass().getSimpleName() + ": " + setpointState);
}
@Override
public void receive(Event event) {
if (event instanceof ItemStateChangedEvent) {
calculate();
}
}
@Override
public Set<String> getSubscribedEventTypes() {
return SUBSCRIBED_EVENT_TYPES;
}
@Override
public @Nullable EventFilter getEventFilter() {
return eventFilter;
}
@Override
public void dispose() {
eventSubscriberRegistration.unregister();
ScheduledFuture<?> localControllerjob = controllerjob;
if (localControllerjob != null) {
localControllerjob.cancel(true);
}
super.dispose();
}
}

View File

@ -0,0 +1,54 @@
/**
* Copyright (c) 2010-2021 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.automation.pidcontroller.internal.handler;
/**
*
* @author Fabian Wolter - Initial Contribution
*/
public class PIDOutputDTO {
private double output;
private double proportionalPart;
private double integralPart;
private double derivativePart;
private double error;
public PIDOutputDTO(double output, double proportionalPart, double integralPart, double derivativePart,
double error) {
this.output = output;
this.proportionalPart = proportionalPart;
this.integralPart = integralPart;
this.derivativePart = derivativePart;
this.error = error;
}
public double getOutput() {
return output;
}
public double getProportionalPart() {
return proportionalPart;
}
public double getIntegralPart() {
return integralPart;
}
public double getDerivativePart() {
return derivativePart;
}
public double getError() {
return error;
}
}

View File

@ -0,0 +1,64 @@
/**
* Copyright (c) 2010-2021 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.automation.pidcontroller.internal.template;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.automation.pidcontroller.internal.PIDControllerConstants;
import org.openhab.automation.pidcontroller.internal.handler.PIDControllerActionHandler;
import org.openhab.automation.pidcontroller.internal.handler.PIDControllerTriggerHandler;
import org.openhab.automation.pidcontroller.internal.type.PIDControllerActionType;
import org.openhab.core.automation.Action;
import org.openhab.core.automation.Condition;
import org.openhab.core.automation.Trigger;
import org.openhab.core.automation.Visibility;
import org.openhab.core.automation.template.RuleTemplate;
import org.openhab.core.automation.util.ModuleBuilder;
import org.openhab.core.config.core.ConfigDescriptionParameter;
/**
*
* @author Hilbrand Bouwkamp - Initial Contribution
*/
@NonNullByDefault
public class PIDControllerRuleTemplate extends RuleTemplate {
public static final String UID = "PIDControllerRuleTemplate";
public static PIDControllerRuleTemplate initialize() {
final String triggerId = UUID.randomUUID().toString();
final List<Trigger> triggers = List.of(ModuleBuilder.createTrigger().withId(triggerId)
.withTypeUID(PIDControllerTriggerHandler.MODULE_TYPE_ID).withLabel("PID Controller Trigger").build());
final Map<String, String> actionInputs = Map.of(PIDControllerActionType.INPUT,
triggerId + "." + PIDControllerConstants.OUTPUT);
final List<Action> actions = List.of(ModuleBuilder.createAction().withId(UUID.randomUUID().toString())
.withTypeUID(PIDControllerActionHandler.MODULE_TYPE_ID).withLabel("PID Controller Action")
.withInputs(actionInputs).build());
return new PIDControllerRuleTemplate(Set.of("PID Controller"), triggers, Collections.emptyList(), actions,
Collections.emptyList());
}
public PIDControllerRuleTemplate(Set<String> tags, List<Trigger> triggers, List<Condition> conditions,
List<Action> actions, List<ConfigDescriptionParameter> configDescriptions) {
super(UID, "PID Controller", "Template for a PID controlled rule", tags, triggers, conditions, actions,
configDescriptions, Visibility.VISIBLE);
}
}

View File

@ -0,0 +1,59 @@
/**
* Copyright (c) 2010-2021 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.automation.pidcontroller.internal.template;
import java.util.Collection;
import java.util.Locale;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.automation.template.RuleTemplate;
import org.openhab.core.automation.template.RuleTemplateProvider;
import org.openhab.core.common.registry.ProviderChangeListener;
import org.osgi.service.component.annotations.Component;
/**
*
* @author Hilbrand Bouwkamp - Initial Contribution
*/
@Component
@NonNullByDefault
public class PIDControllerTemplateProvider implements RuleTemplateProvider {
private static final RuleTemplate PROVIDED_RULE_TEMPLATE = PIDControllerRuleTemplate.initialize();
@Override
public @Nullable RuleTemplate getTemplate(String uid, @Nullable Locale locale) {
return uid.equals(PIDControllerRuleTemplate.UID) ? PROVIDED_RULE_TEMPLATE : null;
}
@Override
public Collection<RuleTemplate> getTemplates(@Nullable Locale locale) {
return Set.of(PROVIDED_RULE_TEMPLATE);
}
@Override
public void addProviderChangeListener(ProviderChangeListener<RuleTemplate> listener) {
// does nothing because this provider does not change
}
@Override
public Collection<RuleTemplate> getAll() {
return Set.of(PROVIDED_RULE_TEMPLATE);
}
@Override
public void removeProviderChangeListener(ProviderChangeListener<RuleTemplate> listener) {
// does nothing because this provider does not change
}
}

View File

@ -0,0 +1,71 @@
/**
* Copyright (c) 2010-2021 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.automation.pidcontroller.internal.type;
import static org.openhab.automation.pidcontroller.internal.PIDControllerConstants.*;
import java.math.BigDecimal;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.automation.pidcontroller.internal.handler.PIDControllerActionHandler;
import org.openhab.core.automation.Visibility;
import org.openhab.core.automation.type.ActionType;
import org.openhab.core.automation.type.Input;
import org.openhab.core.config.core.ConfigDescriptionParameter;
import org.openhab.core.config.core.ConfigDescriptionParameter.Type;
import org.openhab.core.config.core.ConfigDescriptionParameterBuilder;
/**
*
* @author Hilbrand Bouwkamp - Initial Contribution
*/
@NonNullByDefault
public class PIDControllerActionType extends ActionType {
public static final String INPUT = "input";
public static PIDControllerActionType initialize() {
final ConfigDescriptionParameter outputItem = ConfigDescriptionParameterBuilder.create(OUTPUT, Type.TEXT)
.withRequired(true).withMultiple(false).withContext("item").withLabel("Output Item")
.withDescription("Item to send output").build();
final ConfigDescriptionParameter pInspectorItem = ConfigDescriptionParameterBuilder
.create(P_INSPECTOR, Type.TEXT).withRequired(false).withMultiple(false).withContext("item")
.withLabel("P Inspector Item").withDescription("Item for debugging the P part").build();
final ConfigDescriptionParameter iInspectorItem = ConfigDescriptionParameterBuilder
.create(I_INSPECTOR, Type.TEXT).withRequired(false).withMultiple(false).withContext("item")
.withLabel("I Inspector Item").withDescription("Item for debugging the I part").build();
final ConfigDescriptionParameter dInspectorItem = ConfigDescriptionParameterBuilder
.create(D_INSPECTOR, Type.TEXT).withRequired(false).withMultiple(false).withContext("item")
.withLabel("D Inspector Item").withDescription("Item for debugging the D part").build();
final ConfigDescriptionParameter eInspectorItem = ConfigDescriptionParameterBuilder
.create(E_INSPECTOR, Type.TEXT).withRequired(false).withMultiple(false).withContext("item")
.withLabel("Error Inspector Item").withDescription("Item for debugging the error value").build();
List<ConfigDescriptionParameter> config = List.of(outputItem, pInspectorItem, iInspectorItem, dInspectorItem,
eInspectorItem);
List<Input> inputs = List.of(createInput(INPUT), createInput(P_INSPECTOR), createInput(I_INSPECTOR),
createInput(D_INSPECTOR), createInput(E_INSPECTOR));
return new PIDControllerActionType(config, inputs);
}
private static Input createInput(String name) {
return new Input(name, BigDecimal.class.getName());
}
public PIDControllerActionType(List<ConfigDescriptionParameter> configDescriptions, List<Input> inputs) {
super(PIDControllerActionHandler.MODULE_TYPE_ID, configDescriptions, "calculate PID output", null, null,
Visibility.VISIBLE, inputs, null);
}
}

View File

@ -0,0 +1,66 @@
/**
* Copyright (c) 2010-2021 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.automation.pidcontroller.internal.type;
import java.util.Collection;
import java.util.Collections;
import java.util.Locale;
import java.util.Map;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.automation.pidcontroller.internal.handler.PIDControllerActionHandler;
import org.openhab.automation.pidcontroller.internal.handler.PIDControllerTriggerHandler;
import org.openhab.core.automation.type.ModuleType;
import org.openhab.core.automation.type.ModuleTypeProvider;
import org.openhab.core.common.registry.ProviderChangeListener;
import org.osgi.service.component.annotations.Component;
/**
*
* @author Hilbrand Bouwkamp - Initial Contribution
*/
@Component
@NonNullByDefault
public class PIDControllerModuleTypeProvider implements ModuleTypeProvider {
private static final Map<String, ModuleType> PROVIDED_MODULE_TYPES = Map.of(
PIDControllerActionHandler.MODULE_TYPE_ID, PIDControllerActionType.initialize(),
PIDControllerTriggerHandler.MODULE_TYPE_ID, PIDControllerTriggerType.initialize());
@SuppressWarnings("unchecked")
@Override
public <T extends ModuleType> T getModuleType(@Nullable String UID, @Nullable Locale locale) {
return (T) PROVIDED_MODULE_TYPES.get(UID);
}
@SuppressWarnings("unchecked")
@Override
public <T extends ModuleType> Collection<T> getModuleTypes(@Nullable Locale locale) {
return (Collection<T>) PROVIDED_MODULE_TYPES.values();
}
@Override
public void addProviderChangeListener(ProviderChangeListener<ModuleType> listener) {
// does nothing because this provider does not change
}
@Override
public Collection<ModuleType> getAll() {
return Collections.unmodifiableCollection(PROVIDED_MODULE_TYPES.values());
}
@Override
public void removeProviderChangeListener(ProviderChangeListener<ModuleType> listener) {
// does nothing because this provider does not change
}
}

View File

@ -0,0 +1,88 @@
/**
* Copyright (c) 2010-2021 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.automation.pidcontroller.internal.type;
import static org.openhab.automation.pidcontroller.internal.PIDControllerConstants.*;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.openhab.automation.pidcontroller.internal.handler.PIDControllerTriggerHandler;
import org.openhab.core.automation.Visibility;
import org.openhab.core.automation.type.Output;
import org.openhab.core.automation.type.TriggerType;
import org.openhab.core.config.core.ConfigDescriptionParameter;
import org.openhab.core.config.core.ConfigDescriptionParameter.Type;
import org.openhab.core.config.core.ConfigDescriptionParameterBuilder;
/**
*
* @author Hilbrand Bouwkamp - Initial Contribution
*/
@NonNullByDefault
public class PIDControllerTriggerType extends TriggerType {
private static final String DEFAULT_LOOPTIME_MS = "1000";
public static PIDControllerTriggerType initialize() {
List<ConfigDescriptionParameter> configDescriptions = new ArrayList<>();
configDescriptions.add(ConfigDescriptionParameterBuilder.create(CONFIG_INPUT_ITEM, Type.TEXT).withRequired(true)
.withReadOnly(true).withMultiple(false).withContext("item").withLabel("Input Item")
.withDescription("Item to monitor").build());
configDescriptions.add(ConfigDescriptionParameterBuilder.create(CONFIG_SETPOINT_ITEM, Type.TEXT)
.withRequired(true).withReadOnly(true).withMultiple(false).withContext("item").withLabel("Setpoint")
.withDescription("Targeted setpoint").build());
configDescriptions.add(ConfigDescriptionParameterBuilder.create(CONFIG_KP_GAIN, Type.DECIMAL).withRequired(true)
.withMultiple(false).withDefault("1.0").withLabel("Proportional Gain (Kp)")
.withDescription("Change to output propertional to current error value.").build());
configDescriptions.add(ConfigDescriptionParameterBuilder.create(CONFIG_KI_GAIN, Type.DECIMAL).withRequired(true)
.withMultiple(false).withDefault("1.0").withLabel("Integral Gain (Ki)")
.withDescription("Accelerate movement towards the setpoint.").build());
configDescriptions.add(ConfigDescriptionParameterBuilder.create(CONFIG_KD_GAIN, Type.DECIMAL).withRequired(true)
.withMultiple(false).withDefault("1.0").withLabel("Derivative Gain (Kd)")
.withDescription("Slows the rate of change of the output.").build());
configDescriptions.add(ConfigDescriptionParameterBuilder.create(CONFIG_KD_TIMECONSTANT, Type.DECIMAL)
.withRequired(true).withMultiple(false).withDefault("1.0").withLabel("Derivative Time Constant")
.withDescription("Slows the rate of change of the D Part (T1) in seconds.").withUnit("s").build());
configDescriptions.add(ConfigDescriptionParameterBuilder.create(CONFIG_OUTPUT_LOWER_LIMIT, Type.DECIMAL)
.withRequired(true).withMultiple(false).withDefault("0").withLabel("Output Lower Limit")
.withDescription("The output of the PID controller will be min this value").build());
configDescriptions.add(ConfigDescriptionParameterBuilder.create(CONFIG_OUTPUT_UPPER_LIMIT, Type.DECIMAL)
.withRequired(true).withMultiple(false).withDefault("100").withLabel("Output Upper Limit")
.withDescription("The output of the PID controller will be max this value").build());
configDescriptions.add(ConfigDescriptionParameterBuilder.create(CONFIG_LOOP_TIME, Type.DECIMAL)
.withRequired(true).withMultiple(false).withDefault(DEFAULT_LOOPTIME_MS).withLabel("Loop Time")
.withDescription("The interval the output value is updated in ms").withUnit("ms").build());
Output output = new Output(OUTPUT, BigDecimal.class.getName(), "Output", "Output value of the PID Controller",
null, null, null);
Output pInspector = new Output(P_INSPECTOR, BigDecimal.class.getName(), "P Inspector",
"Current P value of the pid controller", null, null, null);
Output iInspector = new Output(I_INSPECTOR, BigDecimal.class.getName(), "I Inspector",
"Current I value of the pid controller", null, null, null);
Output dInspector = new Output(D_INSPECTOR, BigDecimal.class.getName(), "D Inspector",
"Current D value of the pid controller", null, null, null);
Output eInspector = new Output(E_INSPECTOR, BigDecimal.class.getName(), "Error Value Inspector",
"Current error value of the pid controller", null, null, null);
List<Output> outputs = List.of(output, pInspector, iInspector, dInspector, eInspector);
return new PIDControllerTriggerType(configDescriptions, outputs);
}
public PIDControllerTriggerType(List<ConfigDescriptionParameter> configDescriptions, List<Output> outputs) {
super(PIDControllerTriggerHandler.MODULE_TYPE_ID, configDescriptions, "PID controller triggers", null, null,
Visibility.VISIBLE, outputs);
}
}

View File

@ -0,0 +1,68 @@
/**
* Copyright (c) 2010-2021 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.automation.pidcontroller.internal;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.junit.jupiter.api.Test;
/**
* Test for LowpassFilter.
*
* @author Fabian Wolter - Initial contribution
*
*/
@NonNullByDefault
class LowpassFilterTest {
@Test
void test0to1after1tau() {
double output = LowpassFilter.calculate(0, 1, 1);
assertEquals(0.63, output, 0.01);
}
@Test
void test0to1after2tau() {
double output = LowpassFilter.calculate(0, 1, 1);
output = LowpassFilter.calculate(output, 1, 1);
assertEquals(0.86, output, 0.01);
}
@Test
void test0to1after5tau() {
double output = LowpassFilter.calculate(0, 1, 1);
output = LowpassFilter.calculate(output, 1, 1);
output = LowpassFilter.calculate(output, 1, 1);
output = LowpassFilter.calculate(output, 1, 1);
output = LowpassFilter.calculate(output, 1, 1);
assertEquals(0.99, output, 0.01);
}
@Test
void test0to1after1tau2timeConstant() {
double output = LowpassFilter.calculate(0, 1, 2);
assertEquals(0.86, output, 0.01);
}
@Test
void test0to1after0_1tau() {
double output = LowpassFilter.calculate(0, 1, 0.1);
assertEquals(0.095162582, output, 0.000000001);
}
@Test
void test1to0after1tau() {
double output = LowpassFilter.calculate(1, 0, 1);
assertEquals(0.36, output, 0.01);
}
}

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2010-2020 Contributors to the openHAB project
* Copyright (c) 2010-2021 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.

Some files were not shown because too many files have changed in this diff Show More