Skip to content

Commit

Permalink
[automation] Added group and system triggers to automation component (o…
Browse files Browse the repository at this point in the history
…penhab#1509)

* Added group and system triggers to automation component

Signed-off-by: Kai Kreuzer <kai@openhab.org>
GitOrigin-RevId: d265e16
  • Loading branch information
kaikreuzer authored and splatch committed Jul 11, 2023
1 parent d408434 commit 0566384
Show file tree
Hide file tree
Showing 7 changed files with 620 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -56,12 +59,14 @@ public class CoreModuleHandlerFactory extends BaseModuleHandlerFactory implement
private final Logger logger = LoggerFactory.getLogger(CoreModuleHandlerFactory.class);

private static final Collection<String> 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;
Expand Down Expand Up @@ -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);
}
}
}
Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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!");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/**
* 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.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;
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
*/
@NonNullByDefault
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<String> 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";

private ServiceRegistration<?> eventSubscriberRegistration;
private @Nullable 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<String, Object> properties = new Hashtable<>();
this.topic = "smarthome/items/";
properties.put("event.topics", topic);
eventSubscriberRegistration = this.bundleContext.registerService(EventSubscriber.class.getName(), this,
properties);
}

@Override
public Set<String> getSubscribedEventTypes() {
return types;
}

@Override
public @Nullable EventFilter getEventFilter() {
return this;
}

@Override
public void receive(Event event) {
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<String, Object> values = new HashMap<>();
if (event instanceof ItemCommandEvent) {
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);
}
}
}
}
}
}

/**
* do the cleanup: unregistering eventSubscriber...
*/
@Override
public void dispose() {
super.dispose();
eventSubscriberRegistration.unregister();
}

@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;
}
}
Loading

0 comments on commit 0566384

Please sign in to comment.