Skip to content
This repository has been archived by the owner on May 7, 2020. It is now read-only.

Feature/triggers #1936

Merged
merged 26 commits into from
Sep 24, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
a12c392
Implemented trigger channels.
phxql Aug 25, 2016
818be92
Using channel id instead of thing id for event.
phxql Aug 30, 2016
5c8202b
Smaller fixes.
phxql Sep 1, 2016
bf76bb8
Ran mvn:licenseformat
phxql Sep 1, 2016
eac79ba
Renamed ThingTriggerEvent to ChannelTriggeredEvent
phxql Sep 1, 2016
3583fcb
Added tests to ThingEventFactoryTest.
phxql Sep 1, 2016
5e283cd
Changed StateOption in EventDescription to new class EventOption.
phxql Sep 1, 2016
b375f09
Removed unused constant
phxql Sep 1, 2016
261dc5d
ChannelTriggeredEvent now includes the channel which triggered the ev…
phxql Sep 1, 2016
8f2f99e
Code cleanuo
phxql Sep 1, 2016
106a715
Run formatter on RulesJvmModelInferrer.xtend
phxql Sep 1, 2016
affe3b0
Refactored XML. A channel now has a kind, which can be (atm) STATE or…
phxql Sep 1, 2016
961058e
Fix XML parsing.
phxql Sep 1, 2016
ff09f31
Ensure that channel kind is never null.
phxql Sep 1, 2016
e12a223
Removed trigger event types. Every trigger event is now of type string.
phxql Sep 2, 2016
100cc02
Fixed a bug where channel kind hasn't been applied.
phxql Sep 2, 2016
dadb9cb
Added JavaDoc.
phxql Sep 2, 2016
dc7c5fe
Reset targetplatform launch script.
phxql Sep 2, 2016
cc981d2
Improved null checks for kind fields.
phxql Sep 2, 2016
37cf37a
Fixed a bug where the item types of custom channels was null.
phxql Sep 5, 2016
6a736e4
Added system trigger types.
phxql Sep 8, 2016
691cb1d
Added missing license header.
phxql Sep 8, 2016
8d871d8
Merge remote-tracking branch 'upstream/master' into feature/triggers
phxql Sep 19, 2016
2207d95
Fixed line break.
phxql Sep 21, 2016
e85dd53
Fixed useless line breaks.
phxql Sep 21, 2016
32c8048
Fixed logger declaration.
phxql Sep 21, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ bin/
.metadata/
*/plugin.xml_gen
.DS_Store
*.iml
.idea/

distribution/smarthome/logs/*.log
distribution/smarthome/*.zip
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,41 @@
"reference":"itemStateChangeTriggerID.event"
}
]
},
{
"uid":"ChannelEventTrigger",
"label":"Channel Trigger",
"description":"This triggers a rule if a channel emits a trigger",
"configDescriptions":[
{
"name":"channelUID",
"type":"TEXT",
"context":"channel",
"label":"Channel",
"description":"the id of the channel which should be observed for triggers",
"required":true
}
],
"children":[
{
"id":"channelEventTriggerId",
"type":"GenericEventTrigger",
"configuration":{
"eventSource":"$channelUID",
"eventTopic":"smarthome/channels/*/triggered",
"eventTypes":"ChannelTriggeredEvent"
}
}
],
"outputs":[
{
"name":"event",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, I see that this is done in the existing modules this way, too, but it is something I already wanted to have changed since a long time.
I would very much prefer if the output of this trigger would be a "Type", so exactly what the handler emits (e.g. "TRIGGERED"). This would make it much nicer for following rule actions to use it. WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, thought of that too. But you'll lose the other information of the event, like topic etc.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be fine with that, because the topic etc. is "raw" information that is not really the level of this module anymore.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And the channel which was triggered?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed, because the whole module only exists for one channel (which is in its configuration).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about this discussion?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer to not make that change in the scope of this PR, as this also affects the other rules.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok for me

"type":"org.eclipse.smarthome.core.events.Event",
"description":"the event of the channel trigger",
"label":"Event",
"reference":"channelEventTriggerId.event"
}
]
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Import-Package: com.google.common.collect,
org.eclipse.smarthome.core.items,
org.eclipse.smarthome.core.items.events,
org.eclipse.smarthome.core.library.types,
org.eclipse.smarthome.core.thing.events,
org.eclipse.smarthome.core.types,
org.osgi.framework,
org.osgi.service.component,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@
import org.eclipse.smarthome.automation.module.core.handler.ItemStateConditionHandler;
import org.eclipse.smarthome.core.events.EventPublisher;
import org.eclipse.smarthome.core.items.ItemRegistry;
import org.eclipse.smarthome.core.thing.events.ThingEventFactory;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -39,10 +44,10 @@ public class BasicModuleHandlerFactory extends BaseModuleHandlerFactory {

private Logger logger = LoggerFactory.getLogger(BasicModuleHandlerFactory.class);

private static final Collection<String> types = Arrays
.asList(new String[] { ItemStateConditionHandler.ITEM_STATE_CONDITION,
ItemPostCommandActionHandler.ITEM_POST_COMMAND_ACTION, GenericEventTriggerHandler.MODULE_TYPE_ID,
EventConditionHandler.MODULETYPE_ID, CompareConditionHandler.MODULE_TYPE });
private static final Collection<String> types = Arrays.asList(new String[] {
ItemStateConditionHandler.ITEM_STATE_CONDITION, ItemPostCommandActionHandler.ITEM_POST_COMMAND_ACTION,
GenericEventTriggerHandler.MODULE_TYPE_ID, EventConditionHandler.MODULETYPE_ID,
CompareConditionHandler.MODULE_TYPE });

private ItemRegistry itemRegistry;
private EventPublisher eventPublisher;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ public void receive(Event event) {
if (callback != null) {
logger.trace("Received Event: Source: " + event.getSource() + " Topic: " + event.getTopic() + " Type: "
+ event.getType() + " Payload: " + event.getPayload());

if (!event.getTopic().contains(source)) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--

Copyright (c) 2014-2016 by the respective copyright holders.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html

-->
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" immediate="true" modified="modified" name="org.eclipse.smarthome.persistence">
<implementation class="org.eclipse.smarthome.core.persistence.internal.PersistenceServiceRegistryImpl"/>
<property name="service.pid" type="String" value="org.eclipse.smarthome.persistence"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ package org.eclipse.smarthome.core.thing.events;
import static org.hamcrest.CoreMatchers.*
import static org.junit.Assert.*
import static org.junit.matchers.JUnitMatchers.*

import org.eclipse.smarthome.core.events.Event
import org.eclipse.smarthome.core.thing.ChannelUID
import org.eclipse.smarthome.core.thing.ThingStatus
import org.eclipse.smarthome.core.thing.ThingStatusDetail
import org.eclipse.smarthome.core.thing.ThingUID
import org.eclipse.smarthome.core.thing.binding.builder.ThingStatusInfoBuilder
import org.eclipse.smarthome.core.thing.dto.ThingDTOMapper
import org.eclipse.smarthome.core.thing.events.ThingEventFactory.TriggerEventPayloadBean
import org.eclipse.smarthome.core.thing.internal.ThingImpl
import org.eclipse.smarthome.test.OSGiTest
import org.junit.Test

import com.google.gson.Gson

/**
Expand All @@ -40,13 +40,18 @@ class ThingEventFactoryTest extends OSGiTest {

def THING_STATUS_EVENT_TYPE = ThingStatusInfoEvent.TYPE
def THING_ADDED_EVENT_TYPE = ThingAddedEvent.TYPE
def CHANNEL_TRIGGERED_EVENT_TYPE = ChannelTriggeredEvent.TYPE

def THING_STATUS_EVENT_TOPIC = ThingEventFactory.THING_STATUS_INFO_EVENT_TOPIC.replace("{thingUID}", THING_UID.getAsString())
def THING_ADDED_EVENT_TOPIC = ThingEventFactory.THING_ADDED_EVENT_TOPIC.replace("{thingUID}", THING_UID.getAsString())

def THING_STATUS_EVENT_PAYLOAD = new Gson().toJson(THING_STATUS_INFO)
def THING_ADDED_EVENT_PAYLOAD = new Gson().toJson(ThingDTOMapper.map(THING))

def CHANNEL_UID = new ChannelUID(THING_UID, "channel")
def CHANNEL_TRIGGERED_EVENT_TOPIC = ThingEventFactory.CHANNEL_TRIGGERED_EVENT_TOPIC.replace("{channelUID}", CHANNEL_UID.getAsString())
def TRIGGER_EVENT = "PRESSED"
def CHANNEL_TRIGGERED_EVENT_PAYLOAD = new Gson().toJson(new TriggerEventPayloadBean(TRIGGER_EVENT, CHANNEL_UID.getAsString()))

@Test
void 'ThingEventFactory creates Event as ThingStatusInfoEvent correctly'() {
Expand Down Expand Up @@ -95,4 +100,28 @@ class ThingEventFactoryTest extends OSGiTest {
assertThat event.getThing(), not(null)
assertThat event.getThing().UID, is(THING_UID.getAsString())
}

@Test
void 'ThingEventFactory creates ChannelTriggeredEvent correctly'() {
ChannelTriggeredEvent event = ThingEventFactory.createTriggerEvent(TRIGGER_EVENT, CHANNEL_UID)

assertThat event.getType(), is(CHANNEL_TRIGGERED_EVENT_TYPE)
assertThat event.getTopic(), is(CHANNEL_TRIGGERED_EVENT_TOPIC)
assertThat event.getPayload(), is(CHANNEL_TRIGGERED_EVENT_PAYLOAD)
assertThat event.getEvent(), not(null)
assertThat event.getEvent(), is(TRIGGER_EVENT)
}

@Test
void 'ThingEventFactory creates Event as ChannelTriggeredEvent correctly'() {
Event event = factory.createEvent(CHANNEL_TRIGGERED_EVENT_TYPE, CHANNEL_TRIGGERED_EVENT_TOPIC, CHANNEL_TRIGGERED_EVENT_PAYLOAD, null)

assertThat event, is(instanceOf(ChannelTriggeredEvent))
ChannelTriggeredEvent triggeredEvent = event as ChannelTriggeredEvent
assertThat triggeredEvent.getType(), is(CHANNEL_TRIGGERED_EVENT_TYPE)
assertThat triggeredEvent.getTopic(), is(CHANNEL_TRIGGERED_EVENT_TOPIC)
assertThat triggeredEvent.getPayload(), is(CHANNEL_TRIGGERED_EVENT_PAYLOAD)
assertThat triggeredEvent.getEvent(), not(null)
assertThat triggeredEvent.getEvent(), is(TRIGGER_EVENT)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@
* definition information within an XML document into a concrete type object.
* <p>
* This class should be used for each type definition which inherits from the {@link AbstractDescriptionType} class.
*
*
* @param <T> the result type of the conversion
*
*
* @author Michael Grammling - Initial Contribution
*/
public abstract class AbstractDescriptionTypeConverter<T> extends GenericUnmarshaller<T> {
Expand All @@ -42,7 +42,7 @@ public abstract class AbstractDescriptionTypeConverter<T> extends GenericUnmarsh

/**
* Creates a new instance of this class with the specified parameter.
*
*
* @param clazz the class of the result type (must not be null)
* @param type the name of the type (e.g. "thing-type", "channel-type")
*/
Expand All @@ -56,7 +56,7 @@ public AbstractDescriptionTypeConverter(Class<T> clazz, String type) {

/**
* Returns the {@code id} attribute of the specific XML type definition.
*
*
* @param attributes the attributes where to extract the ID information (must not be null)
* @return the ID of the type definition (neither null, nor empty)
*/
Expand All @@ -66,10 +66,10 @@ protected String getID(Map<String, String> attributes) {

/**
* Returns the full extracted UID of the specific XML type definition.
*
*
* @param attributes the attributes where to extract the ID information (must not be null)
* @param context the context where to extract the binding ID information (must not be null)
*
*
* @return the UID of the type definition (neither null, nor empty)
*/
protected String getUID(Map<String, String> attributes, UnmarshallingContext context) {
Expand All @@ -83,7 +83,7 @@ protected String getUID(Map<String, String> attributes, UnmarshallingContext con

/**
* Returns the value of the {@code label} tag from the specific XML type definition.
*
*
* @param nodeIterator the iterator to be used to extract the information (must not be null)
* @return the value of the label (neither null, nor empty)
* @throws ConversionException if the label could not be read
Expand All @@ -94,7 +94,7 @@ protected String readLabel(NodeIterator nodeIterator) throws ConversionException

/**
* Returns the value of the {@code description} tag from the specific XML type definition.
*
*
* @param nodeIterator the iterator to be used to extract the information (must not be null)
* @return the value of the description (could be null or empty)
*/
Expand All @@ -109,8 +109,8 @@ private URI readConfigDescriptionURI(NodeIterator nodeIterator) throws Conversio
try {
return new URI(uriText);
} catch (NullPointerException | URISyntaxException ex) {
throw new ConversionException("The URI '" + uriText + "' in node "
+ "'config-description-ref' is invalid!", ex);
throw new ConversionException(
"The URI '" + uriText + "' in node " + "'config-description-ref' is invalid!", ex);
}
}

Expand All @@ -134,9 +134,9 @@ private ConfigDescription readConfigDescription(NodeIterator nodeIterator) {
/**
* Returns the value of the {@code config-description-ref} and the {@code config-description} tags from the specific
* XML type definition.
*
*
* @param nodeIterator the iterator to be used to extract the information (must not be null)
*
*
* @return the URI and configuration object
* (contains two elements: URI - could be null, ConfigDescription - could be null)
*/
Expand All @@ -155,19 +155,19 @@ protected Object[] getConfigDescriptionObjects(NodeIterator nodeIterator) {

/**
* The abstract unmarshal method which must be implemented by the according type converter.
*
*
* @param reader the reader to be used to read XML information from a stream (not null)
*
*
* @param context the context to be used for the XML document conversion (not null)
*
*
* @param attributes the attributes map containing attributes of the type - only UID -
* (not null, could be empty)
*
*
* @param nodeIterator the iterator to be used to simply extract information in the right
* order and appearance from the XML stream
*
*
* @return the concrete type definition object (could be null)
*
*
* @throws ConversionException if any conversion error occurs
*/
protected abstract T unmarshalType(HierarchicalStreamReader reader, UnmarshallingContext context,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.smarthome.config.core.ConfigDescription;
import org.eclipse.smarthome.config.xml.util.ConverterAttributeMapValidator;
import org.eclipse.smarthome.config.xml.util.NodeIterator;
import org.eclipse.smarthome.config.xml.util.NodeValue;
import org.eclipse.smarthome.core.thing.type.ChannelKind;
import org.eclipse.smarthome.core.thing.type.ChannelType;
import org.eclipse.smarthome.core.thing.type.ChannelTypeUID;
import org.eclipse.smarthome.core.types.EventDescription;
import org.eclipse.smarthome.core.types.StateDescription;

import com.thoughtworks.xstream.converters.ConversionException;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
Expand All @@ -33,7 +33,7 @@
* <p>
* This converter converts {@code channel-type} XML tags. It uses the {@link AbstractDescriptionTypeConverter} which
* offers base functionality for each type definition.
*
*
* @author Michael Grammling - Initial Contribution
* @author Ivan Iliev - Added support for system wide channel types
*/
Expand All @@ -42,8 +42,8 @@ public class ChannelTypeConverter extends AbstractDescriptionTypeConverter<Chann
public ChannelTypeConverter() {
super(ChannelTypeXmlResult.class, "channel-type");

super.attributeMapValidator = new ConverterAttributeMapValidator(new String[][] { { "id", "true" },
{ "advanced", "false" }, { "system", "false" } });
super.attributeMapValidator = new ConverterAttributeMapValidator(
new String[][] { { "id", "true" }, { "advanced", "false" }, { "system", "false" } });
}

private boolean readBoolean(Map<String, String> attributes, String attributeName, boolean defaultValue) {
Expand All @@ -57,7 +57,11 @@ private boolean readBoolean(Map<String, String> attributes, String attributeName
}

private String readItemType(NodeIterator nodeIterator) throws ConversionException {
return (String) nodeIterator.nextValue("item-type", true);
return (String) nodeIterator.nextValue("item-type", false);
}

private String readKind(NodeIterator nodeIterator) throws ConversionException {
return (String) nodeIterator.nextValue("kind", false);
}

private String readCategory(NodeIterator nodeIterator) throws ConversionException {
Expand Down Expand Up @@ -104,6 +108,20 @@ private StateDescription readStateDescription(NodeIterator nodeIterator) {
return null;
}

private EventDescription readEventDescription(NodeIterator nodeIterator) {
Object nextNode = nodeIterator.next();

if (nextNode != null) {
if (nextNode instanceof EventDescription) {
return (EventDescription) nextNode;
}

nodeIterator.revert();
}

return null;
}

@Override
protected ChannelTypeXmlResult unmarshalType(HierarchicalStreamReader reader, UnmarshallingContext context,
Map<String, String> attributes, NodeIterator nodeIterator) throws ConversionException {
Expand All @@ -115,17 +133,24 @@ protected ChannelTypeXmlResult unmarshalType(HierarchicalStreamReader reader, Un
ChannelTypeUID channelTypeUID = new ChannelTypeUID(uid);

String itemType = readItemType(nodeIterator);
String kind = readKind(nodeIterator);
String label = super.readLabel(nodeIterator);
String description = super.readDescription(nodeIterator);
String category = readCategory(nodeIterator);
Set<String> tags = readTags(nodeIterator);

StateDescription stateDescription = readStateDescription(nodeIterator);
EventDescription eventDescription = readEventDescription(nodeIterator);

Object[] configDescriptionObjects = super.getConfigDescriptionObjects(nodeIterator);

ChannelType channelType = new ChannelType(channelTypeUID, advanced, itemType, label, description, category,
tags, stateDescription, (URI) configDescriptionObjects[0]);
if (kind == null) {
// Default for kind is 'state'
kind = "state";
}

ChannelType channelType = new ChannelType(channelTypeUID, advanced, itemType, ChannelKind.parse(kind), label,
description, category, tags, stateDescription, eventDescription, (URI) configDescriptionObjects[0]);

ChannelTypeXmlResult channelTypeXmlResult = new ChannelTypeXmlResult(channelType,
(ConfigDescription) configDescriptionObjects[1], system);
Expand Down
Loading