[automation] Added 'ThingStatusTrigger' for NGRE (#911)

* Added ThingStatusTrigger for NGRE

Signed-off-by: Christoph Weitkamp <github@christophweitkamp.de>
This commit is contained in:
Christoph Weitkamp 2019-07-10 11:57:54 +02:00 committed by Kai Kreuzer
parent 781165f3d8
commit 17c756513a
4 changed files with 343 additions and 7 deletions

View File

@ -34,6 +34,7 @@ import org.openhab.core.automation.internal.module.handler.ItemStateConditionHan
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.ThingStatusTriggerHandler;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
@ -46,9 +47,8 @@ import org.slf4j.LoggerFactory;
* This HandlerFactory creates ModuleHandlers to control items within the
* RuleManager. It contains basic Triggers, Conditions and Actions.
*
* @author Benedikt Niehues - Initial contribution and API
* @author Benedikt Niehues - Initial contribution
* @author Kai Kreuzer - refactored and simplified customized module handling
*
*/
@Component
public class CoreModuleHandlerFactory extends BaseModuleHandlerFactory implements ModuleHandlerFactory {
@ -57,6 +57,7 @@ public class CoreModuleHandlerFactory extends BaseModuleHandlerFactory implement
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,
@ -151,13 +152,15 @@ public class CoreModuleHandlerFactory extends BaseModuleHandlerFactory implement
final String moduleTypeUID = module.getTypeUID();
if (module instanceof Trigger) {
// Handle triggers
if (GenericEventTriggerHandler.MODULE_TYPE_ID.equals(moduleTypeUID)) {
return new GenericEventTriggerHandler((Trigger) module, bundleContext);
} else if (ChannelEventTriggerHandler.MODULE_TYPE_ID.equals(moduleTypeUID)) {
return new ChannelEventTriggerHandler((Trigger) module, bundleContext);
} else if (ItemCommandTriggerHandler.MODULE_TYPE_ID.equals(moduleTypeUID)) {
return new ItemCommandTriggerHandler((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);
@ -175,7 +178,6 @@ public class CoreModuleHandlerFactory extends BaseModuleHandlerFactory implement
}
} else if (module instanceof Action) {
// Handle actions
if (ItemCommandActionHandler.ITEM_COMMAND_ACTION.equals(moduleTypeUID)) {
final ItemCommandActionHandler postCommandActionHandler = new ItemCommandActionHandler((Action) module);
postCommandActionHandler.setEventPublisher(eventPublisher);

View File

@ -0,0 +1,150 @@
/**
* Copyright (c) 2010-2019 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.core.automation.internal.module.handler;
import java.util.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.eclipse.smarthome.core.events.Event;
import org.eclipse.smarthome.core.events.EventFilter;
import org.eclipse.smarthome.core.events.EventSubscriber;
import org.eclipse.smarthome.core.thing.ThingStatus;
import org.eclipse.smarthome.core.thing.events.ThingStatusInfoChangedEvent;
import org.eclipse.smarthome.core.thing.events.ThingStatusInfoEvent;
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.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 thing status event occurs. The
* eventType and status value can be set in the configuration.
*
* @author Christoph Weitkamp - Initial contribution
*/
@NonNullByDefault
public class ThingStatusTriggerHandler extends BaseTriggerModuleHandler implements EventSubscriber, EventFilter {
private final Logger logger = LoggerFactory.getLogger(ThingStatusTriggerHandler.class);
private final String thingUID;
private @Nullable final String status;
private @Nullable final String previousStatus;
private final Set<String> types;
private final BundleContext bundleContext;
public static final String UPDATE_MODULE_TYPE_ID = "core.ThingStatusUpdateTrigger";
public static final String CHANGE_MODULE_TYPE_ID = "core.ThingStatusChangeTrigger";
private static final String CFG_THING_UID = "thingUID";
private static final String CFG_STATUS = "status";
private static final String CFG_PREVIOUS_STATUS = "previousStatus";
private static final String OUT_STATUS = "status";
private static final String OUT_NEW_STATUS = "newStatus";
private static final String OUT_OLD_STATUS = "oldStatus";
private static final String OUT_EVENT = "event";
private final ServiceRegistration<?> eventSubscriberRegistration;
public ThingStatusTriggerHandler(Trigger module, BundleContext bundleContext) {
super(module);
this.thingUID = (String) module.getConfiguration().get(CFG_THING_UID);
this.status = (String) module.getConfiguration().get(CFG_STATUS);
this.previousStatus = (String) module.getConfiguration().get(CFG_PREVIOUS_STATUS);
if (UPDATE_MODULE_TYPE_ID.equals(module.getTypeUID())) {
this.types = Collections.singleton(ThingStatusInfoEvent.TYPE);
} else {
this.types = Collections.singleton(ThingStatusInfoChangedEvent.TYPE);
}
this.bundleContext = bundleContext;
Dictionary<String, Object> properties = new Hashtable<>();
properties.put("event.topics", "smarthome/things/" + thingUID + "/*");
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) {
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<String, Object> values = new HashMap<>();
if (event instanceof ThingStatusInfoEvent && UPDATE_MODULE_TYPE_ID.equals(module.getTypeUID())) {
ThingStatus status = ((ThingStatusInfoEvent) event).getStatusInfo().getStatus();
if (statusMatches(this.status, status)) {
values.put(OUT_STATUS, status);
}
} else if (event instanceof ThingStatusInfoChangedEvent && CHANGE_MODULE_TYPE_ID.equals(module.getTypeUID())) {
ThingStatus newStatus = ((ThingStatusInfoChangedEvent) event).getStatusInfo().getStatus();
ThingStatus oldStatus = ((ThingStatusInfoChangedEvent) event).getOldStatusInfo().getStatus();
if (statusMatches(this.status, newStatus) && statusMatches(this.previousStatus, oldStatus)) {
values.put(OUT_NEW_STATUS, newStatus);
values.put(OUT_OLD_STATUS, oldStatus);
}
}
if (!values.isEmpty()) {
values.put(OUT_EVENT, event);
thCallback.triggered(module, values);
}
}
private boolean statusMatches(@Nullable String requiredStatus, ThingStatus status) {
if (requiredStatus == null) {
return true;
}
String reqStatus = requiredStatus.trim();
return reqStatus.isEmpty() || reqStatus.equals(status.toString());
}
/**
* do the cleanup: unregistering eventSubscriber...
*/
@Override
public void dispose() {
eventSubscriberRegistration.unregister();
super.dispose();
}
@Override
public boolean apply(Event event) {
logger.trace("->FILTER: {}: {}", event.getTopic(), thingUID);
return event.getTopic().contains("smarthome/thing/" + thingUID + "/");
}
}

View File

@ -59,7 +59,7 @@
"name":"event",
"type":"org.eclipse.smarthome.core.events.Event",
"label":"Event",
"description":"The events which was sent.",
"description":"The event which was sent.",
"reference":"event"
}
]
@ -123,7 +123,7 @@
"name":"event",
"type":"org.eclipse.smarthome.core.events.Event",
"label":"Event",
"description":"The events which was sent.",
"description":"The event which was sent.",
"reference":"event"
}
]
@ -227,7 +227,7 @@
"name":"event",
"type":"org.eclipse.smarthome.core.events.Event",
"label":"Event",
"description":"The events which was sent.",
"description":"The event which was sent.",
"reference":"event"
}
]

View File

@ -0,0 +1,184 @@
{
"triggers": [
{
"uid": "core.ThingStatusUpdateTrigger",
"label": "A thing status is updated",
"description": "This triggers the rule if a thing status is updated (even if it does not change).",
"configDescriptions": [
{
"name": "thingUID",
"type": "TEXT",
"context": "thing",
"label": "Thing",
"description": "The UID of the thing.",
"required": true
},
{
"name": "status",
"type": "TEXT",
"label": "Status",
"description": "The status of the thing.",
"required": false,
"limitToOptions": true,
"options": [
{
"label": "UNINITIALIZED",
"value": "UNINITIALIZED"
},
{
"label": "INITIALIZING",
"value": "INITIALIZING"
},
{
"label": "UNKNOWN",
"value": "UNKNOWN"
},
{
"label": "ONLINE",
"value": "ONLINE"
},
{
"label": "OFFLINE",
"value": "OFFLINE"
},
{
"label": "REMOVING",
"value": "REMOVING"
},
{
"label": "REMOVED",
"value": "REMOVED"
}
]
}
],
"outputs": [
{
"name": "status",
"type": "org.eclipse.smarthome.core.thing.ThingStatus",
"label": "Status",
"description": "The status of the thing."
},
{
"name": "event",
"type": "org.eclipse.smarthome.core.events.Event",
"label": "Event",
"description": "The event which was sent.",
"reference": "event"
}
]
},
{
"uid": "core.ThingStatusChangeTrigger",
"label": "A thing status changes",
"description": "This triggers the rule if a thing status has changed.",
"configDescriptions": [
{
"name": "thingUID",
"type": "TEXT",
"context": "thing",
"label": "Thing",
"description": "The UID of the thing.",
"required": true
},
{
"name": "previousStatus",
"type": "TEXT",
"label": "Previous Status",
"description": "The previous status of the thing.",
"required": false,
"limitToOptions": true,
"options": [
{
"label": "UNINITIALIZED",
"value": "UNINITIALIZED"
},
{
"label": "INITIALIZING",
"value": "INITIALIZING"
},
{
"label": "UNKNOWN",
"value": "UNKNOWN"
},
{
"label": "ONLINE",
"value": "ONLINE"
},
{
"label": "OFFLINE",
"value": "OFFLINE"
},
{
"label": "REMOVING",
"value": "REMOVING"
},
{
"label": "REMOVED",
"value": "REMOVED"
}
]
},
{
"name": "status",
"type": "TEXT",
"label": "Status",
"description": "The status of the thing.",
"required": false,
"limitToOptions": true,
"options": [
{
"label": "UNINITIALIZED",
"value": "UNINITIALIZED"
},
{
"label": "INITIALIZING",
"value": "INITIALIZING"
},
{
"label": "UNKNOWN",
"value": "UNKNOWN"
},
{
"label": "ONLINE",
"value": "ONLINE"
},
{
"label": "OFFLINE",
"value": "OFFLINE"
},
{
"label": "REMOVING",
"value": "REMOVING"
},
{
"label": "REMOVED",
"value": "REMOVED"
}
]
}
],
"outputs": [
{
"name": "newStatus",
"type": "org.eclipse.smarthome.core.thing.ThingStatus",
"label": "New Status",
"description": "The new status of the thing."
},
{
"name": "oldStatus",
"type": "org.eclipse.smarthome.core.thing.ThingStatus",
"label": "Old Status",
"description": "The old status of the thing."
},
{
"name": "event",
"type": "org.eclipse.smarthome.core.events.Event",
"label": "Event",
"description": "The event which was sent.",
"reference": "event"
}
]
}
]
}