From aa3595a470510f8ce75b6b23dc4f872db038ddb1 Mon Sep 17 00:00:00 2001 From: Kai Kreuzer Date: Mon, 1 Jun 2020 00:37:23 +0200 Subject: [PATCH 1/3] Added group and system triggers to automation component Signed-off-by: Kai Kreuzer --- .../factory/CoreModuleHandlerFactory.java | 37 ++- .../handler/GenericCronTriggerHandler.java | 6 +- .../handler/GroupCommandTriggerHandler.java | 136 ++++++++++ .../handler/GroupStateTriggerHandler.java | 170 ++++++++++++ .../module/handler/SystemTriggerHandler.java | 119 +++++++++ .../automation/moduletypes/ItemTriggers.json | 250 ++++++++++++++++++ .../moduletypes/SystemTriggers.json | 26 ++ .../core/events/system/StartlevelEvent.java | 60 +++++ .../events/system/SystemEventFactory.java | 91 +++++++ 9 files changed, 888 insertions(+), 7 deletions(-) create mode 100644 bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/GroupCommandTriggerHandler.java create mode 100644 bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/GroupStateTriggerHandler.java create mode 100644 bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/SystemTriggerHandler.java create mode 100644 bundles/org.openhab.core.automation/src/main/resources/OH-INF/automation/moduletypes/SystemTriggers.json create mode 100644 bundles/org.openhab.core/src/main/java/org/openhab/core/events/system/StartlevelEvent.java create mode 100644 bundles/org.openhab.core/src/main/java/org/openhab/core/events/system/SystemEventFactory.java diff --git a/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/factory/CoreModuleHandlerFactory.java b/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/factory/CoreModuleHandlerFactory.java index a6c9f7721b8..c3d75f747c8 100644 --- a/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/factory/CoreModuleHandlerFactory.java +++ b/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/factory/CoreModuleHandlerFactory.java @@ -26,12 +26,15 @@ import org.openhab.core.automation.internal.module.handler.CompareConditionHandler; import org.openhab.core.automation.internal.module.handler.GenericEventConditionHandler; import org.openhab.core.automation.internal.module.handler.GenericEventTriggerHandler; +import org.openhab.core.automation.internal.module.handler.GroupCommandTriggerHandler; +import org.openhab.core.automation.internal.module.handler.GroupStateTriggerHandler; import org.openhab.core.automation.internal.module.handler.ItemCommandActionHandler; import org.openhab.core.automation.internal.module.handler.ItemCommandTriggerHandler; import org.openhab.core.automation.internal.module.handler.ItemStateConditionHandler; import org.openhab.core.automation.internal.module.handler.ItemStateTriggerHandler; import org.openhab.core.automation.internal.module.handler.RuleEnablementActionHandler; import org.openhab.core.automation.internal.module.handler.RunRuleActionHandler; +import org.openhab.core.automation.internal.module.handler.SystemTriggerHandler; import org.openhab.core.automation.internal.module.handler.ThingStatusTriggerHandler; import org.openhab.core.events.EventPublisher; import org.openhab.core.items.ItemRegistry; @@ -56,12 +59,14 @@ public class CoreModuleHandlerFactory extends BaseModuleHandlerFactory implement private final Logger logger = LoggerFactory.getLogger(CoreModuleHandlerFactory.class); private static final Collection TYPES = Arrays.asList(ItemCommandTriggerHandler.MODULE_TYPE_ID, - ItemStateTriggerHandler.UPDATE_MODULE_TYPE_ID, ItemStateTriggerHandler.CHANGE_MODULE_TYPE_ID, - ThingStatusTriggerHandler.UPDATE_MODULE_TYPE_ID, ThingStatusTriggerHandler.CHANGE_MODULE_TYPE_ID, - ItemStateConditionHandler.ITEM_STATE_CONDITION, ItemCommandActionHandler.ITEM_COMMAND_ACTION, - GenericEventTriggerHandler.MODULE_TYPE_ID, ChannelEventTriggerHandler.MODULE_TYPE_ID, - GenericEventConditionHandler.MODULETYPE_ID, GenericEventConditionHandler.MODULETYPE_ID, - CompareConditionHandler.MODULE_TYPE, RuleEnablementActionHandler.UID, RunRuleActionHandler.UID); + GroupCommandTriggerHandler.MODULE_TYPE_ID, ItemStateTriggerHandler.UPDATE_MODULE_TYPE_ID, + ItemStateTriggerHandler.CHANGE_MODULE_TYPE_ID, GroupStateTriggerHandler.UPDATE_MODULE_TYPE_ID, + GroupStateTriggerHandler.CHANGE_MODULE_TYPE_ID, ThingStatusTriggerHandler.UPDATE_MODULE_TYPE_ID, + ThingStatusTriggerHandler.CHANGE_MODULE_TYPE_ID, ItemStateConditionHandler.ITEM_STATE_CONDITION, + ItemCommandActionHandler.ITEM_COMMAND_ACTION, GenericEventTriggerHandler.MODULE_TYPE_ID, + ChannelEventTriggerHandler.MODULE_TYPE_ID, GenericEventConditionHandler.MODULETYPE_ID, + GenericEventConditionHandler.MODULETYPE_ID, CompareConditionHandler.MODULE_TYPE, + SystemTriggerHandler.STARTLEVEL_MODULE_TYPE_ID, RuleEnablementActionHandler.UID, RunRuleActionHandler.UID); private ItemRegistry itemRegistry; private EventPublisher eventPublisher; @@ -97,6 +102,10 @@ protected void setItemRegistry(ItemRegistry itemRegistry) { ((ItemStateConditionHandler) handler).setItemRegistry(this.itemRegistry); } else if (handler instanceof ItemCommandActionHandler) { ((ItemCommandActionHandler) handler).setItemRegistry(this.itemRegistry); + } else if (handler instanceof GroupCommandTriggerHandler) { + ((GroupCommandTriggerHandler) handler).setItemRegistry(this.itemRegistry); + } else if (handler instanceof GroupStateTriggerHandler) { + ((GroupStateTriggerHandler) handler).setItemRegistry(this.itemRegistry); } } } @@ -112,6 +121,10 @@ protected void unsetItemRegistry(ItemRegistry itemRegistry) { ((ItemStateConditionHandler) handler).unsetItemRegistry(this.itemRegistry); } else if (handler instanceof ItemCommandActionHandler) { ((ItemCommandActionHandler) handler).unsetItemRegistry(this.itemRegistry); + } else if (handler instanceof GroupCommandTriggerHandler) { + ((GroupCommandTriggerHandler) handler).unsetItemRegistry(this.itemRegistry); + } else if (handler instanceof GroupStateTriggerHandler) { + ((GroupStateTriggerHandler) handler).unsetItemRegistry(this.itemRegistry); } } this.itemRegistry = null; @@ -158,12 +171,24 @@ protected synchronized ModuleHandler internalCreate(final Module module, final S return new ChannelEventTriggerHandler((Trigger) module, bundleContext); } else if (ItemCommandTriggerHandler.MODULE_TYPE_ID.equals(moduleTypeUID)) { return new ItemCommandTriggerHandler((Trigger) module, bundleContext); + } else if (SystemTriggerHandler.STARTLEVEL_MODULE_TYPE_ID.equals(moduleTypeUID)) { + return new SystemTriggerHandler((Trigger) module, bundleContext); } else if (ThingStatusTriggerHandler.CHANGE_MODULE_TYPE_ID.equals(moduleTypeUID) || ThingStatusTriggerHandler.UPDATE_MODULE_TYPE_ID.equals(moduleTypeUID)) { return new ThingStatusTriggerHandler((Trigger) module, bundleContext); } else if (ItemStateTriggerHandler.CHANGE_MODULE_TYPE_ID.equals(moduleTypeUID) || ItemStateTriggerHandler.UPDATE_MODULE_TYPE_ID.equals(moduleTypeUID)) { return new ItemStateTriggerHandler((Trigger) module, bundleContext); + } else if (GroupCommandTriggerHandler.MODULE_TYPE_ID.equals(moduleTypeUID)) { + final GroupCommandTriggerHandler handler = new GroupCommandTriggerHandler((Trigger) module, + bundleContext); + handler.setItemRegistry(itemRegistry); + return handler; + } else if (GroupStateTriggerHandler.CHANGE_MODULE_TYPE_ID.equals(moduleTypeUID) + || GroupStateTriggerHandler.UPDATE_MODULE_TYPE_ID.equals(moduleTypeUID)) { + final GroupStateTriggerHandler handler = new GroupStateTriggerHandler((Trigger) module, bundleContext); + handler.setItemRegistry(itemRegistry); + return handler; } } else if (module instanceof Condition) { // Handle conditions diff --git a/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/GenericCronTriggerHandler.java b/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/GenericCronTriggerHandler.java index 432d168b54f..ef0731ead2b 100644 --- a/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/GenericCronTriggerHandler.java +++ b/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/GenericCronTriggerHandler.java @@ -72,6 +72,10 @@ public synchronized void dispose() { @Override public void run() { - ((TriggerHandlerCallback) callback).triggered(module, null); + if (callback != null) { + ((TriggerHandlerCallback) callback).triggered(module, null); + } else { + logger.debug("Tried to trigger, but callback isn't available!"); + } } } diff --git a/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/GroupCommandTriggerHandler.java b/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/GroupCommandTriggerHandler.java new file mode 100644 index 00000000000..5b8e4463495 --- /dev/null +++ b/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/GroupCommandTriggerHandler.java @@ -0,0 +1,136 @@ +/** + * Copyright (c) 2010-2020 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.Collections; +import java.util.Dictionary; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; +import java.util.Set; + +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.events.Event; +import org.openhab.core.events.EventFilter; +import org.openhab.core.events.EventSubscriber; +import org.openhab.core.items.Item; +import org.openhab.core.items.ItemRegistry; +import org.openhab.core.items.events.ItemCommandEvent; +import org.openhab.core.types.Command; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This is an ModuleHandler implementation for Triggers which trigger the rule + * if a member of an item group receives a command. + * The group name and command value can be set with the configuration. + * + * @author Kai Kreuzer - Initial contribution + */ +public class GroupCommandTriggerHandler extends BaseTriggerModuleHandler implements EventSubscriber, EventFilter { + + private final Logger logger = LoggerFactory.getLogger(GroupCommandTriggerHandler.class); + + private final String groupName; + private final String command; + private final String topic; + + private final Set types; + private final BundleContext bundleContext; + + public static final String MODULE_TYPE_ID = "core.GroupCommandTrigger"; + + private static final String CFG_GROUPNAME = "groupName"; + private static final String CFG_COMMAND = "command"; + + @SuppressWarnings("rawtypes") + private ServiceRegistration eventSubscriberRegistration; + private ItemRegistry itemRegistry; + + public GroupCommandTriggerHandler(Trigger module, BundleContext bundleContext) { + super(module); + this.groupName = (String) module.getConfiguration().get(CFG_GROUPNAME); + this.command = (String) module.getConfiguration().get(CFG_COMMAND); + this.types = Collections.singleton(ItemCommandEvent.TYPE); + this.bundleContext = bundleContext; + Dictionary properties = new Hashtable<>(); + this.topic = "smarthome/items/"; + properties.put("event.topics", topic); + eventSubscriberRegistration = this.bundleContext.registerService(EventSubscriber.class.getName(), this, + properties); + } + + @Override + public Set getSubscribedEventTypes() { + return types; + } + + @Override + public EventFilter getEventFilter() { + return this; + } + + @Override + public void receive(Event event) { + if (callback != null) { + ModuleHandlerCallback cb = callback; + logger.trace("Received Event: Source: {} Topic: {} Type: {} Payload: {}", event.getSource(), + event.getTopic(), event.getType(), event.getPayload()); + Map values = new HashMap<>(); + if (event instanceof ItemCommandEvent) { + String itemName = ((ItemCommandEvent) event).getItemName(); + Item item = itemRegistry.get(itemName); + if (item != null && item.getGroupNames().contains(groupName)) { + Command command = ((ItemCommandEvent) event).getItemCommand(); + if (this.command == null || this.command.equals(command.toFullString())) { + values.put("triggeringItem", item); + values.put("command", command); + values.put("event", event); + ((TriggerHandlerCallback) cb).triggered(this.module, values); + } + } + } + } + } + + /** + * do the cleanup: unregistering eventSubscriber... + */ + @Override + public void dispose() { + super.dispose(); + if (eventSubscriberRegistration != null) { + eventSubscriberRegistration.unregister(); + eventSubscriberRegistration = null; + } + } + + @Override + public boolean apply(Event event) { + logger.trace("->FILTER: {}", event.getTopic()); + return event.getTopic().startsWith(topic); + } + + public void setItemRegistry(ItemRegistry itemRegistry) { + this.itemRegistry = itemRegistry; + } + + public void unsetItemRegistry(ItemRegistry itemRegistry) { + this.itemRegistry = null; + } +} diff --git a/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/GroupStateTriggerHandler.java b/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/GroupStateTriggerHandler.java new file mode 100644 index 00000000000..4b589e727ee --- /dev/null +++ b/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/GroupStateTriggerHandler.java @@ -0,0 +1,170 @@ +/** + * Copyright (c) 2010-2020 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.Collections; +import java.util.Dictionary; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Map; +import java.util.Set; + +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.events.Event; +import org.openhab.core.events.EventFilter; +import org.openhab.core.events.EventSubscriber; +import org.openhab.core.items.Item; +import org.openhab.core.items.ItemRegistry; +import org.openhab.core.items.events.GroupItemStateChangedEvent; +import org.openhab.core.items.events.ItemStateChangedEvent; +import org.openhab.core.items.events.ItemStateEvent; +import org.openhab.core.types.State; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This is an ModuleHandler implementation for Triggers which trigger the rule + * if state event of a member of an item group occurs. + * The group name and state value can be set with the configuration. + * + * @author Kai Kreuzer - Initial contribution + */ +public class GroupStateTriggerHandler extends BaseTriggerModuleHandler implements EventSubscriber, EventFilter { + private final Logger logger = LoggerFactory.getLogger(GroupStateTriggerHandler.class); + + private final String groupName; + private final String state; + private final String previousState; + private Set types; + private final BundleContext bundleContext; + private ItemRegistry itemRegistry; + + public static final String UPDATE_MODULE_TYPE_ID = "core.GroupStateUpdateTrigger"; + public static final String CHANGE_MODULE_TYPE_ID = "core.GroupStateChangeTrigger"; + + private static final String CFG_GROUPNAME = "groupName"; + private static final String CFG_STATE = "state"; + private static final String CFG_PREVIOUS_STATE = "previousState"; + + @SuppressWarnings("rawtypes") + private ServiceRegistration eventSubscriberRegistration; + + public GroupStateTriggerHandler(Trigger module, BundleContext bundleContext) { + super(module); + this.groupName = (String) module.getConfiguration().get(CFG_GROUPNAME); + this.state = (String) module.getConfiguration().get(CFG_STATE); + this.previousState = (String) module.getConfiguration().get(CFG_PREVIOUS_STATE); + if (UPDATE_MODULE_TYPE_ID.equals(module.getTypeUID())) { + this.types = Collections.singleton(ItemStateEvent.TYPE); + } else { + Set set = new HashSet<>(); + set.add(ItemStateChangedEvent.TYPE); + set.add(GroupItemStateChangedEvent.TYPE); + this.types = Collections.unmodifiableSet(set); + } + this.bundleContext = bundleContext; + Dictionary properties = new Hashtable<>(); + properties.put("event.topics", "smarthome/items/*"); + eventSubscriberRegistration = this.bundleContext.registerService(EventSubscriber.class.getName(), this, + properties); + } + + @Override + public Set getSubscribedEventTypes() { + return types; + } + + @Override + public EventFilter getEventFilter() { + return this; + } + + @Override + public void receive(Event event) { + if (callback != null) { + ModuleHandlerCallback cb = callback; + logger.trace("Received Event: Source: {} Topic: {} Type: {} Payload: {}", event.getSource(), + event.getTopic(), event.getType(), event.getPayload()); + Map values = new HashMap<>(); + if (event instanceof ItemStateEvent && UPDATE_MODULE_TYPE_ID.equals(module.getTypeUID())) { + String itemName = ((ItemStateEvent) event).getItemName(); + Item item = itemRegistry.get(itemName); + if (item != null && item.getGroupNames().contains(groupName)) { + State state = ((ItemStateEvent) event).getItemState(); + if ((this.state == null || this.state.equals(state.toFullString()))) { + values.put("triggeringItem", item); + values.put("state", state); + } + } + } else if (event instanceof ItemStateChangedEvent && CHANGE_MODULE_TYPE_ID.equals(module.getTypeUID())) { + String itemName = ((ItemStateChangedEvent) event).getItemName(); + Item item = itemRegistry.get(itemName); + if (item != null && item.getGroupNames().contains(groupName)) { + State state = ((ItemStateChangedEvent) event).getItemState(); + State oldState = ((ItemStateChangedEvent) event).getOldItemState(); + + if (stateMatches(this.state, state) && stateMatches(this.previousState, oldState)) { + values.put("triggeringItem", item); + values.put("oldState", oldState); + values.put("newState", state); + } + } + } + if (!values.isEmpty()) { + values.put("event", event); + ((TriggerHandlerCallback) cb).triggered(this.module, values); + } + } + } + + private boolean stateMatches(String requiredState, State state) { + if (requiredState == null) { + return true; + } + + String reqState = requiredState.trim(); + return reqState.isEmpty() || reqState.equals(state.toFullString()); + } + + /** + * do the cleanup: unregistering eventSubscriber... + */ + @Override + public void dispose() { + super.dispose(); + if (eventSubscriberRegistration != null) { + eventSubscriberRegistration.unregister(); + eventSubscriberRegistration = null; + } + } + + @Override + public boolean apply(Event event) { + logger.trace("->FILTER: {}:{}", event.getTopic(), groupName); + return event.getTopic().startsWith("smarthome/items/"); + } + + public void setItemRegistry(ItemRegistry itemRegistry) { + this.itemRegistry = itemRegistry; + } + + public void unsetItemRegistry(ItemRegistry itemRegistry) { + this.itemRegistry = null; + } +} diff --git a/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/SystemTriggerHandler.java b/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/SystemTriggerHandler.java new file mode 100644 index 00000000000..e248a951408 --- /dev/null +++ b/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/SystemTriggerHandler.java @@ -0,0 +1,119 @@ +/** + * Copyright (c) 2010-2020 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.math.BigDecimal; +import java.util.Collections; +import java.util.Dictionary; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +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.events.Event; +import org.openhab.core.events.EventFilter; +import org.openhab.core.events.EventSubscriber; +import org.openhab.core.events.system.StartlevelEvent; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * This is a ModuleHandler implementation for Triggers which trigger the rule if a certain system event occurs. + * + * @author Kai Kreuzer - Initial contribution + */ +@NonNullByDefault +public class SystemTriggerHandler extends BaseTriggerModuleHandler implements EventSubscriber, EventFilter { + + private final Logger logger = LoggerFactory.getLogger(SystemTriggerHandler.class); + + public static final String STARTLEVEL_MODULE_TYPE_ID = "core.SystemStartlevelTrigger"; + private static final String CFG_STARTLEVEL = "startlevel"; + private static final String OUT_STARTLEVEL = "startlevel"; + + private final Integer startlevel; + private final Set types; + private final BundleContext bundleContext; + + private ServiceRegistration eventSubscriberRegistration; + + public SystemTriggerHandler(Trigger module, BundleContext bundleContext) { + super(module); + this.startlevel = ((BigDecimal) module.getConfiguration().get(CFG_STARTLEVEL)).intValue(); + if (STARTLEVEL_MODULE_TYPE_ID.equals(module.getTypeUID())) { + this.types = Collections.singleton(StartlevelEvent.TYPE); + } else { + logger.warn("Module type '{}' is not (yet) handled by this class.", module.getTypeUID()); + throw new IllegalArgumentException(module.getTypeUID() + " is no valid module type."); + } + this.bundleContext = bundleContext; + Dictionary properties = new Hashtable<>(); + properties.put("event.topics", "smarthome/system/*"); + eventSubscriberRegistration = this.bundleContext.registerService(EventSubscriber.class.getName(), this, + properties); + } + + @Override + public Set getSubscribedEventTypes() { + return types; + } + + @Override + public @Nullable EventFilter getEventFilter() { + return this; + } + + @Override + public void receive(Event event) { + final ModuleHandlerCallback callback = this.callback; + if (!(callback instanceof TriggerHandlerCallback)) { + return; + } + + TriggerHandlerCallback thCallback = (TriggerHandlerCallback) callback; + logger.trace("Received Event: Source: {} Topic: {} Type: {} Payload: {}", event.getSource(), event.getTopic(), + event.getType(), event.getPayload()); + Map values = new HashMap<>(); + if (event instanceof StartlevelEvent && STARTLEVEL_MODULE_TYPE_ID.equals(module.getTypeUID())) { + Integer sl = ((StartlevelEvent) event).getStartlevel(); + if (startlevel.equals(sl)) { + values.put(OUT_STARTLEVEL, sl); + } + } + if (!values.isEmpty()) { + thCallback.triggered(module, values); + } + } + + /** + * do the cleanup: unregistering eventSubscriber... + */ + @Override + public void dispose() { + eventSubscriberRegistration.unregister(); + super.dispose(); + } + + @Override + public boolean apply(Event event) { + return true; + } +} diff --git a/bundles/org.openhab.core.automation/src/main/resources/OH-INF/automation/moduletypes/ItemTriggers.json b/bundles/org.openhab.core.automation/src/main/resources/OH-INF/automation/moduletypes/ItemTriggers.json index c05459e799f..bb5d462d18e 100644 --- a/bundles/org.openhab.core.automation/src/main/resources/OH-INF/automation/moduletypes/ItemTriggers.json +++ b/bundles/org.openhab.core.automation/src/main/resources/OH-INF/automation/moduletypes/ItemTriggers.json @@ -231,6 +231,256 @@ "reference": "event" } ] + }, + { + "uid": "core.GroupCommandTrigger", + "label": "a member of an item group receives a command", + "description": "This triggers the rule if a member of an item group receives a command.", + "configDescriptions": [ + { + "name": "groupName", + "type": "TEXT", + "context": "item", + "label": "Group", + "description": "the name of the item group", + "required": true + }, + { + "name": "command", + "type": "TEXT", + "label": "Command", + "description": "the received command", + "required": false, + "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" + } + ] + } + ], + "outputs": [ + { + "name": "triggeringItem", + "type": "org.openhab.core.items.Item", + "description": "the member of the group that received the command", + "label": "Triggering Item" + }, + { + "name": "command", + "type": "command", + "description": "the received command", + "label": "Command" + }, + { + "name": "event", + "type": "org.openhab.core.events.Event", + "label": "Event", + "description": "The event which was sent.", + "reference": "event" + } + ] + }, + { + "uid": "core.GroupStateUpdateTrigger", + "label": "the state of a member of an item group is updated", + "description": "This triggers the rule if the state of a member of an item group is updated (even if it does not change).", + "configDescriptions": [ + { + "name": "groupName", + "type": "TEXT", + "context": "item", + "label": "Group", + "description": "the name of the item group", + "required": true + }, + { + "name": "state", + "type": "TEXT", + "label": "State", + "description": "the state of the item", + "required": false, + "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" + } + ] + } + ], + "outputs": [ + { + "name": "triggeringItem", + "type": "org.openhab.core.items.Item", + "description": "the member of the group that updated its state", + "label": "Triggering Item" + }, + { + "name": "state", + "type": "state", + "description": "the item state", + "label": "State" + }, + { + "name": "event", + "type": "org.openhab.core.events.Event", + "label": "Event", + "description": "The event which was sent.", + "reference": "event" + } + ] + }, + { + "uid": "core.GroupStateChangeTrigger", + "label": "the state of a member of an item group changes", + "description": "This triggers the rule if the state of a member of an item group has changed.", + "configDescriptions": [ + { + "name": "groupName", + "type": "TEXT", + "context": "item", + "label": "Group", + "description": "the name of the item group", + "required": true + }, + { + "name": "previousState", + "type": "TEXT", + "label": "Previous State", + "description": "the required previous state of the item", + "required": false, + "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" + } + ] + }, + { + "name": "state", + "type": "TEXT", + "label": "State", + "description": "the state of the item", + "required": false, + "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" + } + ] + } + ], + "outputs": [ + { + "name": "triggeringItem", + "type": "org.openhab.core.items.Item", + "description": "the member of the group that changed its state", + "label": "Triggering Item" + }, + { + "name": "newState", + "type": "state", + "description": "the new item state", + "label": "New State" + }, + { + "name": "oldState", + "type": "state", + "description": "the old item state", + "label": "Old State" + }, + { + "name": "event", + "type": "org.openhab.core.events.Event", + "label": "Event", + "description": "The event which was sent.", + "reference": "event" + } + ] } ] } diff --git a/bundles/org.openhab.core.automation/src/main/resources/OH-INF/automation/moduletypes/SystemTriggers.json b/bundles/org.openhab.core.automation/src/main/resources/OH-INF/automation/moduletypes/SystemTriggers.json new file mode 100644 index 00000000000..168a1f9e5d2 --- /dev/null +++ b/bundles/org.openhab.core.automation/src/main/resources/OH-INF/automation/moduletypes/SystemTriggers.json @@ -0,0 +1,26 @@ +{ + "triggers": [ + { + "uid": "core.SystemStartlevelTrigger", + "label": "A system startlevel is reached", + "description": "This triggers the rule if a given startlevel is reached by the system.", + "configDescriptions": [ + { + "name": "startlevel", + "type": "INTEGER", + "label": "Start Level", + "description": "The system start level.", + "required": true + } + ], + "outputs": [ + { + "name": "startlevel", + "type": "INTEGER", + "label": "Start Level", + "description": "The system start level." + } + ] + } + ] +} diff --git a/bundles/org.openhab.core/src/main/java/org/openhab/core/events/system/StartlevelEvent.java b/bundles/org.openhab.core/src/main/java/org/openhab/core/events/system/StartlevelEvent.java new file mode 100644 index 00000000000..8566babc553 --- /dev/null +++ b/bundles/org.openhab.core/src/main/java/org/openhab/core/events/system/StartlevelEvent.java @@ -0,0 +1,60 @@ +/** + * Copyright (c) 2010-2020 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.events.system; + +import org.openhab.core.events.AbstractEvent; + +/** + * {@link StartlevelEvent}s will be delivered through the openHAB event bus if the start level of the system has + * changed. + * + * @author Kai Kreuzer - Initial contribution + */ +public class StartlevelEvent extends AbstractEvent { + + public static final String TYPE = StartlevelEvent.class.getSimpleName(); + + private final Integer startlevel; + + /** + * Creates a new system startlevel event object. + * + * @param topic the topic + * @param payload the payload + * @param source the source + * @param startlevel the system startlevel + */ + protected StartlevelEvent(String topic, String payload, String source, Integer startlevel) { + super(topic, payload, source); + this.startlevel = startlevel; + } + + @Override + public String getType() { + return TYPE; + } + + /** + * Gets the system startlevel. + * + * @return the startlevel + */ + public Integer getStartlevel() { + return startlevel; + } + + @Override + public String toString() { + return String.format("Startlevel '%d' reached.", startlevel); + } +} diff --git a/bundles/org.openhab.core/src/main/java/org/openhab/core/events/system/SystemEventFactory.java b/bundles/org.openhab.core/src/main/java/org/openhab/core/events/system/SystemEventFactory.java new file mode 100644 index 00000000000..88ee3483d32 --- /dev/null +++ b/bundles/org.openhab.core/src/main/java/org/openhab/core/events/system/SystemEventFactory.java @@ -0,0 +1,91 @@ +/** + * Copyright (c) 2010-2020 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.events.system; + +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.core.events.AbstractEventFactory; +import org.openhab.core.events.Event; +import org.openhab.core.events.EventFactory; +import org.openhab.core.types.Type; +import org.osgi.service.component.annotations.Component; + +/** + * Factory that creates system events. + * + * @author Kai Kreuzer - Initial contribution + */ +@Component(immediate = true, service = EventFactory.class) +public class SystemEventFactory extends AbstractEventFactory { + + static final String SYSTEM_STARTLEVEL_TOPIC = "smarthome/system/startlevel"; + + public SystemEventFactory() { + super(Stream.of(StartlevelEvent.TYPE).collect(Collectors.toSet())); + } + + /** + * Creates a trigger event from a {@link Type}. + * + * @param startlevel Startlevel of system + * @return Created start level event. + */ + public static StartlevelEvent createStartlevelEvent(Integer startlevel) { + SystemEventPayloadBean bean = new SystemEventPayloadBean(startlevel); + String payload = serializePayload(bean); + return new StartlevelEvent(SYSTEM_STARTLEVEL_TOPIC, payload, null, startlevel); + } + + @Override + protected @NonNull Event createEventByType(@NonNull String eventType, @NonNull String topic, + @NonNull String payload, @Nullable String source) throws Exception { + return createStartlevelEvent(topic, payload, source); + } + + /** + * Creates a startlevel event from a payload. + * + * @param topic Event topic + * @param source Event source + * @param payload Payload + * @return created startlevel event + */ + public StartlevelEvent createStartlevelEvent(String topic, String payload, String source) { + SystemEventPayloadBean bean = deserializePayload(payload, SystemEventPayloadBean.class); + return new StartlevelEvent(topic, payload, source, bean.getStartlevel()); + } + + /** + * This is a java bean that is used to serialize/deserialize system event payload. + */ + public static class SystemEventPayloadBean { + private Integer startlevel; + + /** + * Default constructor for deserialization e.g. by Gson. + */ + protected SystemEventPayloadBean() { + } + + public SystemEventPayloadBean(Integer startlevel) { + this.startlevel = startlevel; + } + + public Integer getStartlevel() { + return startlevel; + } + } +} From 8d61d5b655f7a32c5168bfc1ec1acf485c22e256 Mon Sep 17 00:00:00 2001 From: Kai Kreuzer Date: Tue, 2 Jun 2020 21:17:44 +0200 Subject: [PATCH 2/3] addressed review comments Signed-off-by: Kai Kreuzer --- .../handler/GroupCommandTriggerHandler.java | 41 +++++++------- .../handler/GroupStateTriggerHandler.java | 53 ++++++++++--------- .../module/handler/SystemTriggerHandler.java | 4 +- .../events/system/SystemEventFactory.java | 11 ++-- 4 files changed, 56 insertions(+), 53 deletions(-) diff --git a/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/GroupCommandTriggerHandler.java b/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/GroupCommandTriggerHandler.java index 5b8e4463495..8fc92696a74 100644 --- a/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/GroupCommandTriggerHandler.java +++ b/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/GroupCommandTriggerHandler.java @@ -19,7 +19,8 @@ import java.util.Map; import java.util.Set; -import org.openhab.core.automation.ModuleHandlerCallback; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.core.automation.Trigger; import org.openhab.core.automation.handler.BaseTriggerModuleHandler; import org.openhab.core.automation.handler.TriggerHandlerCallback; @@ -42,6 +43,7 @@ * * @author Kai Kreuzer - Initial contribution */ +@NonNullByDefault public class GroupCommandTriggerHandler extends BaseTriggerModuleHandler implements EventSubscriber, EventFilter { private final Logger logger = LoggerFactory.getLogger(GroupCommandTriggerHandler.class); @@ -58,9 +60,8 @@ public class GroupCommandTriggerHandler extends BaseTriggerModuleHandler impleme private static final String CFG_GROUPNAME = "groupName"; private static final String CFG_COMMAND = "command"; - @SuppressWarnings("rawtypes") - private ServiceRegistration eventSubscriberRegistration; - private ItemRegistry itemRegistry; + private ServiceRegistration eventSubscriberRegistration; + private @Nullable ItemRegistry itemRegistry; public GroupCommandTriggerHandler(Trigger module, BundleContext bundleContext) { super(module); @@ -81,27 +82,30 @@ public Set getSubscribedEventTypes() { } @Override - public EventFilter getEventFilter() { + public @Nullable EventFilter getEventFilter() { return this; } @Override public void receive(Event event) { - if (callback != null) { - ModuleHandlerCallback cb = callback; + if (callback instanceof TriggerHandlerCallback) { + TriggerHandlerCallback cb = (TriggerHandlerCallback) callback; logger.trace("Received Event: Source: {} Topic: {} Type: {} Payload: {}", event.getSource(), event.getTopic(), event.getType(), event.getPayload()); Map values = new HashMap<>(); if (event instanceof ItemCommandEvent) { - String itemName = ((ItemCommandEvent) event).getItemName(); - Item item = itemRegistry.get(itemName); - if (item != null && item.getGroupNames().contains(groupName)) { - Command command = ((ItemCommandEvent) event).getItemCommand(); - if (this.command == null || this.command.equals(command.toFullString())) { - values.put("triggeringItem", item); - values.put("command", command); - values.put("event", event); - ((TriggerHandlerCallback) cb).triggered(this.module, values); + ItemCommandEvent icEvent = (ItemCommandEvent) event; + String itemName = icEvent.getItemName(); + if (itemRegistry != null) { + Item item = itemRegistry.get(itemName); + if (item != null && item.getGroupNames().contains(groupName)) { + Command command = icEvent.getItemCommand(); + if (this.command.equals(command.toFullString())) { + values.put("triggeringItem", item); + values.put("command", command); + values.put("event", event); + cb.triggered(this.module, values); + } } } } @@ -114,10 +118,7 @@ public void receive(Event event) { @Override public void dispose() { super.dispose(); - if (eventSubscriberRegistration != null) { - eventSubscriberRegistration.unregister(); - eventSubscriberRegistration = null; - } + eventSubscriberRegistration.unregister(); } @Override diff --git a/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/GroupStateTriggerHandler.java b/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/GroupStateTriggerHandler.java index 4b589e727ee..9f3786b8c88 100644 --- a/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/GroupStateTriggerHandler.java +++ b/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/GroupStateTriggerHandler.java @@ -20,6 +20,8 @@ import java.util.Map; import java.util.Set; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.core.automation.ModuleHandlerCallback; import org.openhab.core.automation.Trigger; import org.openhab.core.automation.handler.BaseTriggerModuleHandler; @@ -45,15 +47,16 @@ * * @author Kai Kreuzer - Initial contribution */ +@NonNullByDefault public class GroupStateTriggerHandler extends BaseTriggerModuleHandler implements EventSubscriber, EventFilter { private final Logger logger = LoggerFactory.getLogger(GroupStateTriggerHandler.class); private final String groupName; - private final String state; + private final @Nullable String state; private final String previousState; private Set types; private final BundleContext bundleContext; - private ItemRegistry itemRegistry; + private @Nullable ItemRegistry itemRegistry; public static final String UPDATE_MODULE_TYPE_ID = "core.GroupStateUpdateTrigger"; public static final String CHANGE_MODULE_TYPE_ID = "core.GroupStateChangeTrigger"; @@ -62,8 +65,7 @@ public class GroupStateTriggerHandler extends BaseTriggerModuleHandler implement private static final String CFG_STATE = "state"; private static final String CFG_PREVIOUS_STATE = "previousState"; - @SuppressWarnings("rawtypes") - private ServiceRegistration eventSubscriberRegistration; + private ServiceRegistration eventSubscriberRegistration; public GroupStateTriggerHandler(Trigger module, BundleContext bundleContext) { super(module); @@ -91,7 +93,7 @@ public Set getSubscribedEventTypes() { } @Override - public EventFilter getEventFilter() { + public @Nullable EventFilter getEventFilter() { return this; } @@ -104,25 +106,29 @@ public void receive(Event event) { Map values = new HashMap<>(); if (event instanceof ItemStateEvent && UPDATE_MODULE_TYPE_ID.equals(module.getTypeUID())) { String itemName = ((ItemStateEvent) event).getItemName(); - Item item = itemRegistry.get(itemName); - if (item != null && item.getGroupNames().contains(groupName)) { - State state = ((ItemStateEvent) event).getItemState(); - if ((this.state == null || this.state.equals(state.toFullString()))) { - values.put("triggeringItem", item); - values.put("state", state); + if (itemRegistry != null) { + Item item = itemRegistry.get(itemName); + if (item != null && item.getGroupNames().contains(groupName)) { + State state = ((ItemStateEvent) event).getItemState(); + if ((this.state == null || state.toFullString().equals(this.state))) { + values.put("triggeringItem", item); + values.put("state", state); + } } } } else if (event instanceof ItemStateChangedEvent && CHANGE_MODULE_TYPE_ID.equals(module.getTypeUID())) { String itemName = ((ItemStateChangedEvent) event).getItemName(); - Item item = itemRegistry.get(itemName); - if (item != null && item.getGroupNames().contains(groupName)) { - State state = ((ItemStateChangedEvent) event).getItemState(); - State oldState = ((ItemStateChangedEvent) event).getOldItemState(); - - if (stateMatches(this.state, state) && stateMatches(this.previousState, oldState)) { - values.put("triggeringItem", item); - values.put("oldState", oldState); - values.put("newState", state); + if (itemRegistry != null) { + Item item = itemRegistry.get(itemName); + if (item != null && item.getGroupNames().contains(groupName)) { + State state = ((ItemStateChangedEvent) event).getItemState(); + State oldState = ((ItemStateChangedEvent) event).getOldItemState(); + + if (stateMatches(this.state, state) && stateMatches(this.previousState, oldState)) { + values.put("triggeringItem", item); + values.put("oldState", oldState); + values.put("newState", state); + } } } } @@ -133,7 +139,7 @@ public void receive(Event event) { } } - private boolean stateMatches(String requiredState, State state) { + private boolean stateMatches(@Nullable String requiredState, State state) { if (requiredState == null) { return true; } @@ -148,10 +154,7 @@ private boolean stateMatches(String requiredState, State state) { @Override public void dispose() { super.dispose(); - if (eventSubscriberRegistration != null) { - eventSubscriberRegistration.unregister(); - eventSubscriberRegistration = null; - } + eventSubscriberRegistration.unregister(); } @Override diff --git a/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/SystemTriggerHandler.java b/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/SystemTriggerHandler.java index e248a951408..7149d745989 100644 --- a/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/SystemTriggerHandler.java +++ b/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/SystemTriggerHandler.java @@ -96,11 +96,9 @@ public void receive(Event event) { Integer sl = ((StartlevelEvent) event).getStartlevel(); if (startlevel.equals(sl)) { values.put(OUT_STARTLEVEL, sl); + thCallback.triggered(module, values); } } - if (!values.isEmpty()) { - thCallback.triggered(module, values); - } } /** diff --git a/bundles/org.openhab.core/src/main/java/org/openhab/core/events/system/SystemEventFactory.java b/bundles/org.openhab.core/src/main/java/org/openhab/core/events/system/SystemEventFactory.java index 88ee3483d32..d6a85d62fc7 100644 --- a/bundles/org.openhab.core/src/main/java/org/openhab/core/events/system/SystemEventFactory.java +++ b/bundles/org.openhab.core/src/main/java/org/openhab/core/events/system/SystemEventFactory.java @@ -15,7 +15,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; import org.openhab.core.events.AbstractEventFactory; import org.openhab.core.events.Event; @@ -29,6 +29,7 @@ * @author Kai Kreuzer - Initial contribution */ @Component(immediate = true, service = EventFactory.class) +@NonNullByDefault public class SystemEventFactory extends AbstractEventFactory { static final String SYSTEM_STARTLEVEL_TOPIC = "smarthome/system/startlevel"; @@ -50,8 +51,8 @@ public static StartlevelEvent createStartlevelEvent(Integer startlevel) { } @Override - protected @NonNull Event createEventByType(@NonNull String eventType, @NonNull String topic, - @NonNull String payload, @Nullable String source) throws Exception { + protected Event createEventByType(String eventType, String topic, String payload, @Nullable String source) + throws Exception { return createStartlevelEvent(topic, payload, source); } @@ -63,7 +64,7 @@ public static StartlevelEvent createStartlevelEvent(Integer startlevel) { * @param payload Payload * @return created startlevel event */ - public StartlevelEvent createStartlevelEvent(String topic, String payload, String source) { + public StartlevelEvent createStartlevelEvent(String topic, String payload, @Nullable String source) { SystemEventPayloadBean bean = deserializePayload(payload, SystemEventPayloadBean.class); return new StartlevelEvent(topic, payload, source, bean.getStartlevel()); } @@ -72,7 +73,7 @@ public StartlevelEvent createStartlevelEvent(String topic, String payload, Strin * This is a java bean that is used to serialize/deserialize system event payload. */ public static class SystemEventPayloadBean { - private Integer startlevel; + private @NonNullByDefault({}) Integer startlevel; /** * Default constructor for deserialization e.g. by Gson. From 7f4b8fb4de0269ceece5948409c1d52b1ea49ef2 Mon Sep 17 00:00:00 2001 From: Kai Kreuzer Date: Wed, 3 Jun 2020 22:04:44 +0200 Subject: [PATCH 3/3] addressed further review comments Signed-off-by: Kai Kreuzer --- .../handler/GroupStateTriggerHandler.java | 28 ++++++++++--------- .../core/events/system/StartlevelEvent.java | 5 +++- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/GroupStateTriggerHandler.java b/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/GroupStateTriggerHandler.java index 9f3786b8c88..548b288a21a 100644 --- a/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/GroupStateTriggerHandler.java +++ b/bundles/org.openhab.core.automation/src/main/java/org/openhab/core/automation/internal/module/handler/GroupStateTriggerHandler.java @@ -22,7 +22,6 @@ import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; -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; @@ -99,43 +98,46 @@ public Set getSubscribedEventTypes() { @Override public void receive(Event event) { - if (callback != null) { - ModuleHandlerCallback cb = callback; + if (callback instanceof TriggerHandlerCallback) { + TriggerHandlerCallback cb = (TriggerHandlerCallback) callback; logger.trace("Received Event: Source: {} Topic: {} Type: {} Payload: {}", event.getSource(), event.getTopic(), event.getType(), event.getPayload()); - Map values = new HashMap<>(); if (event instanceof ItemStateEvent && UPDATE_MODULE_TYPE_ID.equals(module.getTypeUID())) { - String itemName = ((ItemStateEvent) event).getItemName(); + ItemStateEvent isEvent = (ItemStateEvent) event; + String itemName = isEvent.getItemName(); if (itemRegistry != null) { Item item = itemRegistry.get(itemName); if (item != null && item.getGroupNames().contains(groupName)) { - State state = ((ItemStateEvent) event).getItemState(); + State state = isEvent.getItemState(); if ((this.state == null || state.toFullString().equals(this.state))) { + Map values = new HashMap<>(); values.put("triggeringItem", item); values.put("state", state); + values.put("event", event); + cb.triggered(this.module, values); } } } } else if (event instanceof ItemStateChangedEvent && CHANGE_MODULE_TYPE_ID.equals(module.getTypeUID())) { - String itemName = ((ItemStateChangedEvent) event).getItemName(); + ItemStateChangedEvent iscEvent = (ItemStateChangedEvent) event; + String itemName = iscEvent.getItemName(); if (itemRegistry != null) { Item item = itemRegistry.get(itemName); if (item != null && item.getGroupNames().contains(groupName)) { - State state = ((ItemStateChangedEvent) event).getItemState(); - State oldState = ((ItemStateChangedEvent) event).getOldItemState(); + State state = iscEvent.getItemState(); + State oldState = iscEvent.getOldItemState(); if (stateMatches(this.state, state) && stateMatches(this.previousState, oldState)) { + Map values = new HashMap<>(); values.put("triggeringItem", item); values.put("oldState", oldState); values.put("newState", state); + values.put("event", event); + cb.triggered(this.module, values); } } } } - if (!values.isEmpty()) { - values.put("event", event); - ((TriggerHandlerCallback) cb).triggered(this.module, values); - } } } diff --git a/bundles/org.openhab.core/src/main/java/org/openhab/core/events/system/StartlevelEvent.java b/bundles/org.openhab.core/src/main/java/org/openhab/core/events/system/StartlevelEvent.java index 8566babc553..ff139dd1e7a 100644 --- a/bundles/org.openhab.core/src/main/java/org/openhab/core/events/system/StartlevelEvent.java +++ b/bundles/org.openhab.core/src/main/java/org/openhab/core/events/system/StartlevelEvent.java @@ -12,6 +12,8 @@ */ package org.openhab.core.events.system; +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; import org.openhab.core.events.AbstractEvent; /** @@ -20,6 +22,7 @@ * * @author Kai Kreuzer - Initial contribution */ +@NonNullByDefault public class StartlevelEvent extends AbstractEvent { public static final String TYPE = StartlevelEvent.class.getSimpleName(); @@ -34,7 +37,7 @@ public class StartlevelEvent extends AbstractEvent { * @param source the source * @param startlevel the system startlevel */ - protected StartlevelEvent(String topic, String payload, String source, Integer startlevel) { + protected StartlevelEvent(String topic, String payload, @Nullable String source, Integer startlevel) { super(topic, payload, source); this.startlevel = startlevel; }