Add `lastStateUpdate`, `lastStateChange` to `ItemStateUpdatedEvent`/`ItemStateChangedEvent` (#4606)
* Add `lastStateUpdate`, `lastStateChange` to `ItemStateUpdatedEvent`/`ItemStateChangedEvent` Signed-off-by: Jimmy Tanagra <jcode@tanagra.id.au>pull/4693/head
parent
40d9a67e53
commit
9cd72164f5
|
@ -122,12 +122,13 @@ public class GroupStateTriggerHandler extends BaseTriggerModuleHandler implement
|
||||||
if (item != null && item.getGroupNames().contains(groupName)) {
|
if (item != null && item.getGroupNames().contains(groupName)) {
|
||||||
State state = isEvent.getItemState();
|
State state = isEvent.getItemState();
|
||||||
if ((this.state == null || state.toFullString().equals(this.state))) {
|
if ((this.state == null || state.toFullString().equals(this.state))) {
|
||||||
Map<String, Object> values = new HashMap<>();
|
Map<String, @Nullable Object> values = new HashMap<>();
|
||||||
if (group != null) {
|
if (group != null) {
|
||||||
values.put("triggeringGroup", group);
|
values.put("triggeringGroup", group);
|
||||||
}
|
}
|
||||||
values.put("triggeringItem", item);
|
values.put("triggeringItem", item);
|
||||||
values.put("state", state);
|
values.put("state", state);
|
||||||
|
values.put("lastStateUpdate", isEvent.getLastStateUpdate());
|
||||||
values.put("event", event);
|
values.put("event", event);
|
||||||
cb.triggered(this.module, values);
|
cb.triggered(this.module, values);
|
||||||
}
|
}
|
||||||
|
@ -142,13 +143,15 @@ public class GroupStateTriggerHandler extends BaseTriggerModuleHandler implement
|
||||||
State oldState = iscEvent.getOldItemState();
|
State oldState = iscEvent.getOldItemState();
|
||||||
|
|
||||||
if (stateMatches(this.state, state) && stateMatches(this.previousState, oldState)) {
|
if (stateMatches(this.state, state) && stateMatches(this.previousState, oldState)) {
|
||||||
Map<String, Object> values = new HashMap<>();
|
Map<String, @Nullable Object> values = new HashMap<>();
|
||||||
if (group != null) {
|
if (group != null) {
|
||||||
values.put("triggeringGroup", group);
|
values.put("triggeringGroup", group);
|
||||||
}
|
}
|
||||||
values.put("triggeringItem", item);
|
values.put("triggeringItem", item);
|
||||||
values.put("oldState", oldState);
|
values.put("oldState", oldState);
|
||||||
values.put("newState", state);
|
values.put("newState", state);
|
||||||
|
values.put("lastStateUpdate", iscEvent.getLastStateUpdate());
|
||||||
|
values.put("lastStateChange", iscEvent.getLastStateChange());
|
||||||
values.put("event", event);
|
values.put("event", event);
|
||||||
cb.triggered(this.module, values);
|
cb.triggered(this.module, values);
|
||||||
}
|
}
|
||||||
|
|
|
@ -132,13 +132,14 @@ public class ItemStateTriggerHandler extends BaseTriggerModuleHandler implements
|
||||||
if (callback != null) {
|
if (callback != null) {
|
||||||
logger.trace("Received Event: Source: {} Topic: {} Type: {} Payload: {}", event.getSource(),
|
logger.trace("Received Event: Source: {} Topic: {} Type: {} Payload: {}", event.getSource(),
|
||||||
event.getTopic(), event.getType(), event.getPayload());
|
event.getTopic(), event.getType(), event.getPayload());
|
||||||
Map<String, Object> values = new HashMap<>();
|
Map<String, @Nullable Object> values = new HashMap<>();
|
||||||
if (event instanceof ItemStateUpdatedEvent updatedEvent
|
if (event instanceof ItemStateUpdatedEvent updatedEvent
|
||||||
&& UPDATE_MODULE_TYPE_ID.equals(module.getTypeUID())) {
|
&& UPDATE_MODULE_TYPE_ID.equals(module.getTypeUID())) {
|
||||||
String state = this.state;
|
String state = this.state;
|
||||||
State itemState = updatedEvent.getItemState();
|
State itemState = updatedEvent.getItemState();
|
||||||
if ((state == null || state.equals(itemState.toFullString()))) {
|
if ((state == null || state.equals(itemState.toFullString()))) {
|
||||||
values.put("state", itemState);
|
values.put("state", itemState);
|
||||||
|
values.put("lastStateUpdate", updatedEvent.getLastStateUpdate());
|
||||||
}
|
}
|
||||||
} else if (event instanceof ItemStateChangedEvent changedEvent
|
} else if (event instanceof ItemStateChangedEvent changedEvent
|
||||||
&& CHANGE_MODULE_TYPE_ID.equals(module.getTypeUID())) {
|
&& CHANGE_MODULE_TYPE_ID.equals(module.getTypeUID())) {
|
||||||
|
@ -148,6 +149,8 @@ public class ItemStateTriggerHandler extends BaseTriggerModuleHandler implements
|
||||||
if (stateMatches(this.state, itemState) && stateMatches(this.previousState, oldItemState)) {
|
if (stateMatches(this.state, itemState) && stateMatches(this.previousState, oldItemState)) {
|
||||||
values.put("oldState", oldItemState);
|
values.put("oldState", oldItemState);
|
||||||
values.put("newState", itemState);
|
values.put("newState", itemState);
|
||||||
|
values.put("lastStateUpdate", changedEvent.getLastStateUpdate());
|
||||||
|
values.put("lastStateChange", changedEvent.getLastStateChange());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!values.isEmpty()) {
|
if (!values.isEmpty()) {
|
||||||
|
|
|
@ -125,6 +125,12 @@
|
||||||
"state"
|
"state"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "lastStateUpdate",
|
||||||
|
"type": "java.time.ZonedDateTime",
|
||||||
|
"description": "the time of the previous state update",
|
||||||
|
"label": "Last State Update"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "event",
|
"name": "event",
|
||||||
"type": "org.openhab.core.events.Event",
|
"type": "org.openhab.core.events.Event",
|
||||||
|
@ -220,8 +226,8 @@
|
||||||
{
|
{
|
||||||
"name": "newState",
|
"name": "newState",
|
||||||
"type": "state",
|
"type": "state",
|
||||||
"description": "the new item state",
|
|
||||||
"label": "New State",
|
"label": "New State",
|
||||||
|
"description": "the new item state",
|
||||||
"tags": [
|
"tags": [
|
||||||
"state"
|
"state"
|
||||||
]
|
]
|
||||||
|
@ -229,8 +235,20 @@
|
||||||
{
|
{
|
||||||
"name": "oldState",
|
"name": "oldState",
|
||||||
"type": "state",
|
"type": "state",
|
||||||
"description": "the old item state",
|
"label": "Old State",
|
||||||
"label": "Old State"
|
"description": "the old item state"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "lastStateUpdate",
|
||||||
|
"type": "java.time.ZonedDateTime",
|
||||||
|
"label": "Last State Update",
|
||||||
|
"description": "the time of the previous state update"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "lastStateChange",
|
||||||
|
"type": "java.time.ZonedDateTime",
|
||||||
|
"label": "Last State Change",
|
||||||
|
"description": "the time of the previous state change"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "event",
|
"name": "event",
|
||||||
|
@ -402,6 +420,12 @@
|
||||||
"state"
|
"state"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "lastStateUpdate",
|
||||||
|
"type": "java.time.ZonedDateTime",
|
||||||
|
"description": "the time of the previous state update",
|
||||||
|
"label": "Last State Update"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "event",
|
"name": "event",
|
||||||
"type": "org.openhab.core.events.Event",
|
"type": "org.openhab.core.events.Event",
|
||||||
|
@ -518,6 +542,18 @@
|
||||||
"description": "the old item state",
|
"description": "the old item state",
|
||||||
"label": "Old State"
|
"label": "Old State"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "lastStateUpdate",
|
||||||
|
"type": "java.time.ZonedDateTime",
|
||||||
|
"label": "Last State Update",
|
||||||
|
"description": "the time of the previous state update"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "lastStateChange",
|
||||||
|
"type": "java.time.ZonedDateTime",
|
||||||
|
"label": "Last State Change",
|
||||||
|
"description": "the time of the previous state change"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "event",
|
"name": "event",
|
||||||
"type": "org.openhab.core.events.Event",
|
"type": "org.openhab.core.events.Event",
|
||||||
|
|
|
@ -258,7 +258,8 @@ public class EventWebSocketTest {
|
||||||
eventWebSocket.processEvent(event);
|
eventWebSocket.processEvent(event);
|
||||||
verify(remoteEndpoint).sendString(gson.toJson(new EventDTO(event)));
|
verify(remoteEndpoint).sendString(gson.toJson(new EventDTO(event)));
|
||||||
|
|
||||||
event = ItemEventFactory.createStateChangedEvent(TEST_ITEM_NAME, DecimalType.ZERO, DecimalType.ZERO);
|
event = ItemEventFactory.createStateChangedEvent(TEST_ITEM_NAME, DecimalType.ZERO, DecimalType.ZERO, null,
|
||||||
|
null);
|
||||||
eventWebSocket.processEvent(event);
|
eventWebSocket.processEvent(event);
|
||||||
verify(remoteEndpoint).sendString(gson.toJson(new EventDTO(event)));
|
verify(remoteEndpoint).sendString(gson.toJson(new EventDTO(event)));
|
||||||
|
|
||||||
|
@ -285,7 +286,8 @@ public class EventWebSocketTest {
|
||||||
verify(remoteEndpoint, times(0)).sendString(any());
|
verify(remoteEndpoint, times(0)).sendString(any());
|
||||||
|
|
||||||
// not excluded topics are sent
|
// not excluded topics are sent
|
||||||
event = ItemEventFactory.createStateChangedEvent(TEST_ITEM_NAME, DecimalType.ZERO, DecimalType.ZERO);
|
event = ItemEventFactory.createStateChangedEvent(TEST_ITEM_NAME, DecimalType.ZERO, DecimalType.ZERO, null,
|
||||||
|
null);
|
||||||
eventWebSocket.processEvent(event);
|
eventWebSocket.processEvent(event);
|
||||||
verify(remoteEndpoint).sendString(gson.toJson(new EventDTO(event)));
|
verify(remoteEndpoint).sendString(gson.toJson(new EventDTO(event)));
|
||||||
|
|
||||||
|
@ -309,7 +311,8 @@ public class EventWebSocketTest {
|
||||||
clearInvocations(remoteEndpoint);
|
clearInvocations(remoteEndpoint);
|
||||||
|
|
||||||
// included topics are sent
|
// included topics are sent
|
||||||
Event event = ItemEventFactory.createStateChangedEvent(TEST_ITEM_NAME, DecimalType.ZERO, DecimalType.ZERO);
|
Event event = ItemEventFactory.createStateChangedEvent(TEST_ITEM_NAME, DecimalType.ZERO, DecimalType.ZERO, null,
|
||||||
|
null);
|
||||||
eventWebSocket.processEvent(event);
|
eventWebSocket.processEvent(event);
|
||||||
verify(remoteEndpoint).sendString(gson.toJson(new EventDTO(event)));
|
verify(remoteEndpoint).sendString(gson.toJson(new EventDTO(event)));
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
package org.openhab.core.model.rule.jvmmodel
|
package org.openhab.core.model.rule.jvmmodel
|
||||||
|
|
||||||
import com.google.inject.Inject
|
import com.google.inject.Inject
|
||||||
|
import java.time.ZonedDateTime
|
||||||
import java.util.Set
|
import java.util.Set
|
||||||
import org.openhab.core.items.Item
|
import org.openhab.core.items.Item
|
||||||
import org.openhab.core.items.ItemRegistry
|
import org.openhab.core.items.ItemRegistry
|
||||||
|
@ -145,10 +146,22 @@ class RulesJvmModelInferrer extends ScriptJvmModelInferrer {
|
||||||
val commandTypeRef = typeRef(Command)
|
val commandTypeRef = typeRef(Command)
|
||||||
parameters += rule.toParameter(VAR_RECEIVED_COMMAND, commandTypeRef)
|
parameters += rule.toParameter(VAR_RECEIVED_COMMAND, commandTypeRef)
|
||||||
}
|
}
|
||||||
|
if ((containsStateChangeTrigger(rule) || containsStateUpdateTrigger(rule)) && !containsParam(parameters, VAR_NEW_STATE)) {
|
||||||
|
val stateTypeRef = typeRef(State)
|
||||||
|
parameters += rule.toParameter(VAR_NEW_STATE, stateTypeRef)
|
||||||
|
}
|
||||||
if (containsStateChangeTrigger(rule) && !containsParam(parameters, VAR_PREVIOUS_STATE)) {
|
if (containsStateChangeTrigger(rule) && !containsParam(parameters, VAR_PREVIOUS_STATE)) {
|
||||||
val stateTypeRef = typeRef(State)
|
val stateTypeRef = typeRef(State)
|
||||||
parameters += rule.toParameter(VAR_PREVIOUS_STATE, stateTypeRef)
|
parameters += rule.toParameter(VAR_PREVIOUS_STATE, stateTypeRef)
|
||||||
}
|
}
|
||||||
|
if (containsStateChangeTrigger(rule) || containsStateUpdateTrigger(rule)) {
|
||||||
|
val lastStateUpdateTypeRef = typeRef(ZonedDateTime)
|
||||||
|
parameters += rule.toParameter(VAR_LAST_STATE_UPDATE, lastStateUpdateTypeRef)
|
||||||
|
}
|
||||||
|
if (containsStateChangeTrigger(rule)) {
|
||||||
|
val lastStateChangeTypeRef = typeRef(ZonedDateTime)
|
||||||
|
parameters += rule.toParameter(VAR_LAST_STATE_CHANGE, lastStateChangeTypeRef)
|
||||||
|
}
|
||||||
if (containsEventTrigger(rule)) {
|
if (containsEventTrigger(rule)) {
|
||||||
val eventTypeRef = typeRef(String)
|
val eventTypeRef = typeRef(String)
|
||||||
parameters += rule.toParameter(VAR_RECEIVED_EVENT, eventTypeRef)
|
parameters += rule.toParameter(VAR_RECEIVED_EVENT, eventTypeRef)
|
||||||
|
@ -163,10 +176,6 @@ class RulesJvmModelInferrer extends ScriptJvmModelInferrer {
|
||||||
val newStatusRef = typeRef(String)
|
val newStatusRef = typeRef(String)
|
||||||
parameters += rule.toParameter(VAR_NEW_STATUS, newStatusRef)
|
parameters += rule.toParameter(VAR_NEW_STATUS, newStatusRef)
|
||||||
}
|
}
|
||||||
if ((containsStateChangeTrigger(rule) || containsStateUpdateTrigger(rule)) && !containsParam(parameters, VAR_NEW_STATE)) {
|
|
||||||
val stateTypeRef = typeRef(State)
|
|
||||||
parameters += rule.toParameter(VAR_NEW_STATE, stateTypeRef)
|
|
||||||
}
|
|
||||||
|
|
||||||
body = rule.script
|
body = rule.script
|
||||||
]
|
]
|
||||||
|
|
|
@ -61,11 +61,16 @@ public class DSLScriptEngine implements javax.script.ScriptEngine {
|
||||||
|
|
||||||
public static final String MIMETYPE_OPENHAB_DSL_RULE = "application/vnd.openhab.dsl.rule";
|
public static final String MIMETYPE_OPENHAB_DSL_RULE = "application/vnd.openhab.dsl.rule";
|
||||||
|
|
||||||
private static final Map<String, String> IMPLICIT_VARS = Map.of("command",
|
private static final Map<String, String> IMPLICIT_VARS = Map.of( //
|
||||||
ScriptJvmModelInferrer.VAR_RECEIVED_COMMAND, "state", ScriptJvmModelInferrer.VAR_NEW_STATE, "newState",
|
"command", ScriptJvmModelInferrer.VAR_RECEIVED_COMMAND, //
|
||||||
ScriptJvmModelInferrer.VAR_NEW_STATE, "oldState", ScriptJvmModelInferrer.VAR_PREVIOUS_STATE,
|
"state", ScriptJvmModelInferrer.VAR_NEW_STATE, //
|
||||||
"triggeringItem", ScriptJvmModelInferrer.VAR_TRIGGERING_ITEM, "triggeringGroup",
|
"newState", ScriptJvmModelInferrer.VAR_NEW_STATE, //
|
||||||
ScriptJvmModelInferrer.VAR_TRIGGERING_GROUP, "input", ScriptJvmModelInferrer.VAR_INPUT);
|
"oldState", ScriptJvmModelInferrer.VAR_PREVIOUS_STATE, //
|
||||||
|
"lastStateUpdate", ScriptJvmModelInferrer.VAR_LAST_STATE_UPDATE, //
|
||||||
|
"lastStateChange", ScriptJvmModelInferrer.VAR_LAST_STATE_CHANGE, //
|
||||||
|
"triggeringItem", ScriptJvmModelInferrer.VAR_TRIGGERING_ITEM, //
|
||||||
|
"triggeringGroup", ScriptJvmModelInferrer.VAR_TRIGGERING_GROUP, //
|
||||||
|
"input", ScriptJvmModelInferrer.VAR_INPUT);
|
||||||
|
|
||||||
private final Logger logger = LoggerFactory.getLogger(DSLScriptEngine.class);
|
private final Logger logger = LoggerFactory.getLogger(DSLScriptEngine.class);
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
package org.openhab.core.model.script.jvmmodel
|
package org.openhab.core.model.script.jvmmodel
|
||||||
|
|
||||||
import com.google.inject.Inject
|
import com.google.inject.Inject
|
||||||
|
import java.time.ZonedDateTime
|
||||||
import java.util.Set
|
import java.util.Set
|
||||||
import org.openhab.core.items.ItemRegistry
|
import org.openhab.core.items.ItemRegistry
|
||||||
import org.openhab.core.model.script.scoping.StateAndCommandProvider
|
import org.openhab.core.model.script.scoping.StateAndCommandProvider
|
||||||
|
@ -61,6 +62,12 @@ class ScriptJvmModelInferrer extends AbstractModelInferrer {
|
||||||
/** Variable name for the new state of an item in a "changed state triggered" or "updated state triggered" rule */
|
/** Variable name for the new state of an item in a "changed state triggered" or "updated state triggered" rule */
|
||||||
public static final String VAR_NEW_STATE = "newState";
|
public static final String VAR_NEW_STATE = "newState";
|
||||||
|
|
||||||
|
/** Variable name for the last update time of an item in a "changed state triggered" or "updated state triggered" rule */
|
||||||
|
public static final String VAR_LAST_STATE_UPDATE = "lastStateUpdate";
|
||||||
|
|
||||||
|
/** Variable name for the last change time of an item in a "changed state triggered" rule */
|
||||||
|
public static final String VAR_LAST_STATE_CHANGE = "lastStateChange";
|
||||||
|
|
||||||
/** Variable name for the received command in a "command triggered" rule */
|
/** Variable name for the received command in a "command triggered" rule */
|
||||||
public static final String VAR_RECEIVED_COMMAND = "receivedCommand";
|
public static final String VAR_RECEIVED_COMMAND = "receivedCommand";
|
||||||
|
|
||||||
|
@ -160,6 +167,10 @@ class ScriptJvmModelInferrer extends AbstractModelInferrer {
|
||||||
parameters += script.toParameter(VAR_NEW_STATUS, newThingStatusRef)
|
parameters += script.toParameter(VAR_NEW_STATUS, newThingStatusRef)
|
||||||
val stateTypeRef2 = typeRef(State)
|
val stateTypeRef2 = typeRef(State)
|
||||||
parameters += script.toParameter(VAR_NEW_STATE, stateTypeRef2)
|
parameters += script.toParameter(VAR_NEW_STATE, stateTypeRef2)
|
||||||
|
val lastStateUpdateTypeRef = typeRef(ZonedDateTime)
|
||||||
|
parameters += script.toParameter(VAR_LAST_STATE_UPDATE, lastStateUpdateTypeRef)
|
||||||
|
val lastStateChangeTypeRef = typeRef(ZonedDateTime)
|
||||||
|
parameters += script.toParameter(VAR_LAST_STATE_CHANGE, lastStateChangeTypeRef)
|
||||||
val privateCacheTypeRef = typeRef(ValueCache)
|
val privateCacheTypeRef = typeRef(ValueCache)
|
||||||
parameters += script.toParameter(VAR_PRIVATE_CACHE, privateCacheTypeRef)
|
parameters += script.toParameter(VAR_PRIVATE_CACHE, privateCacheTypeRef)
|
||||||
val sharedCacheTypeRef = typeRef(ValueCache)
|
val sharedCacheTypeRef = typeRef(ValueCache)
|
||||||
|
|
|
@ -12,12 +12,20 @@
|
||||||
*/
|
*/
|
||||||
package org.openhab.core.events;
|
package org.openhab.core.events;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.TypeAdapter;
|
||||||
|
import com.google.gson.stream.JsonReader;
|
||||||
|
import com.google.gson.stream.JsonToken;
|
||||||
|
import com.google.gson.stream.JsonWriter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link AbstractEventFactory} defines an abstract implementation of the {@link EventFactory} interface. Subclasses
|
* The {@link AbstractEventFactory} defines an abstract implementation of the {@link EventFactory} interface. Subclasses
|
||||||
|
@ -31,7 +39,8 @@ public abstract class AbstractEventFactory implements EventFactory {
|
||||||
|
|
||||||
private final Set<String> supportedEventTypes;
|
private final Set<String> supportedEventTypes;
|
||||||
|
|
||||||
private static final Gson JSONCONVERTER = new Gson();
|
private static final Gson JSONCONVERTER = new GsonBuilder()
|
||||||
|
.registerTypeAdapter(ZonedDateTime.class, new ZonedDateTimeAdapter()).create();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Must be called in subclass constructor to define the supported event types.
|
* Must be called in subclass constructor to define the supported event types.
|
||||||
|
@ -120,4 +129,25 @@ public abstract class AbstractEventFactory implements EventFactory {
|
||||||
throw new IllegalArgumentException("The argument '" + argumentName + "' must not be null or empty.");
|
throw new IllegalArgumentException("The argument '" + argumentName + "' must not be null or empty.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class ZonedDateTimeAdapter extends TypeAdapter<ZonedDateTime> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(JsonWriter out, @Nullable ZonedDateTime value) throws IOException {
|
||||||
|
if (value == null) {
|
||||||
|
out.nullValue();
|
||||||
|
} else {
|
||||||
|
out.value(value.format(DateTimeFormatter.ISO_ZONED_DATE_TIME));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable ZonedDateTime read(JsonReader in) throws IOException {
|
||||||
|
if (in.peek() == JsonToken.NULL) {
|
||||||
|
in.nextNull();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return ZonedDateTime.parse(in.nextString(), DateTimeFormatter.ISO_ZONED_DATE_TIME);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -242,14 +242,15 @@ public abstract class GenericItem implements ActiveItem {
|
||||||
public void setState(State state, @Nullable State lastState, @Nullable ZonedDateTime lastStateUpdate,
|
public void setState(State state, @Nullable State lastState, @Nullable ZonedDateTime lastStateUpdate,
|
||||||
@Nullable ZonedDateTime lastStateChange) {
|
@Nullable ZonedDateTime lastStateChange) {
|
||||||
State oldState = this.state;
|
State oldState = this.state;
|
||||||
|
ZonedDateTime oldStateUpdate = this.lastStateUpdate;
|
||||||
this.state = state;
|
this.state = state;
|
||||||
this.lastState = lastState != null ? lastState : this.lastState;
|
this.lastState = lastState != null ? lastState : this.lastState;
|
||||||
this.lastStateUpdate = lastStateUpdate != null ? lastStateUpdate : this.lastStateUpdate;
|
this.lastStateUpdate = lastStateUpdate != null ? lastStateUpdate : this.lastStateUpdate;
|
||||||
this.lastStateChange = lastStateChange != null ? lastStateChange : this.lastStateChange;
|
this.lastStateChange = lastStateChange != null ? lastStateChange : this.lastStateChange;
|
||||||
notifyListeners(oldState, state);
|
notifyListeners(oldState, state);
|
||||||
sendStateUpdatedEvent(state);
|
sendStateUpdatedEvent(state, lastStateUpdate);
|
||||||
if (!oldState.equals(state)) {
|
if (!oldState.equals(state)) {
|
||||||
sendStateChangedEvent(state, oldState);
|
sendStateChangedEvent(state, oldState, lastStateUpdate, lastStateChange);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,9 +271,9 @@ public abstract class GenericItem implements ActiveItem {
|
||||||
lastState = oldState; // update before we notify listeners
|
lastState = oldState; // update before we notify listeners
|
||||||
}
|
}
|
||||||
notifyListeners(oldState, state);
|
notifyListeners(oldState, state);
|
||||||
sendStateUpdatedEvent(state);
|
sendStateUpdatedEvent(state, lastStateUpdate);
|
||||||
if (stateChanged) {
|
if (stateChanged) {
|
||||||
sendStateChangedEvent(state, oldState);
|
sendStateChangedEvent(state, oldState, lastStateUpdate, lastStateChange);
|
||||||
lastStateChange = now; // update after we've notified listeners
|
lastStateChange = now; // update after we've notified listeners
|
||||||
}
|
}
|
||||||
lastStateUpdate = now;
|
lastStateUpdate = now;
|
||||||
|
@ -322,17 +323,19 @@ public abstract class GenericItem implements ActiveItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendStateUpdatedEvent(State newState) {
|
private void sendStateUpdatedEvent(State newState, @Nullable ZonedDateTime lastStateUpdate) {
|
||||||
EventPublisher eventPublisher1 = this.eventPublisher;
|
EventPublisher eventPublisher1 = this.eventPublisher;
|
||||||
if (eventPublisher1 != null) {
|
if (eventPublisher1 != null) {
|
||||||
eventPublisher1.post(ItemEventFactory.createStateUpdatedEvent(this.name, newState, null));
|
eventPublisher1.post(ItemEventFactory.createStateUpdatedEvent(this.name, newState, lastStateUpdate, null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendStateChangedEvent(State newState, State oldState) {
|
private void sendStateChangedEvent(State newState, State oldState, @Nullable ZonedDateTime lastStateUpdate,
|
||||||
|
@Nullable ZonedDateTime lastStateChange) {
|
||||||
EventPublisher eventPublisher1 = this.eventPublisher;
|
EventPublisher eventPublisher1 = this.eventPublisher;
|
||||||
if (eventPublisher1 != null) {
|
if (eventPublisher1 != null) {
|
||||||
eventPublisher1.post(ItemEventFactory.createStateChangedEvent(this.name, newState, oldState));
|
eventPublisher1.post(ItemEventFactory.createStateChangedEvent(this.name, newState, oldState,
|
||||||
|
lastStateUpdate, lastStateChange));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
*/
|
*/
|
||||||
package org.openhab.core.items;
|
package org.openhab.core.items;
|
||||||
|
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -365,19 +366,22 @@ public class GroupItem extends GenericItem implements StateChangeListener, Metad
|
||||||
State oldState = this.state;
|
State oldState = this.state;
|
||||||
State newState = oldState;
|
State newState = oldState;
|
||||||
ItemStateConverter itemStateConverter = this.itemStateConverter;
|
ItemStateConverter itemStateConverter = this.itemStateConverter;
|
||||||
|
ZonedDateTime lastStateUpdate = this.lastStateUpdate;
|
||||||
|
ZonedDateTime lastStateChange = this.lastStateChange;
|
||||||
if (function instanceof GroupFunction groupFunction && baseItem != null && itemStateConverter != null) {
|
if (function instanceof GroupFunction groupFunction && baseItem != null && itemStateConverter != null) {
|
||||||
State calculatedState = groupFunction.calculate(getStateMembers(getMembers()));
|
State calculatedState = groupFunction.calculate(getStateMembers(getMembers()));
|
||||||
newState = itemStateConverter.convertToAcceptedState(calculatedState, baseItem);
|
newState = itemStateConverter.convertToAcceptedState(calculatedState, baseItem);
|
||||||
setState(newState);
|
setState(newState);
|
||||||
sendGroupStateUpdatedEvent(item.getName(), newState);
|
sendGroupStateUpdatedEvent(item.getName(), newState, lastStateUpdate);
|
||||||
}
|
}
|
||||||
if (!oldState.equals(newState)) {
|
if (!oldState.equals(newState)) {
|
||||||
sendGroupStateChangedEvent(item.getName(), newState, oldState);
|
sendGroupStateChangedEvent(item.getName(), newState, oldState, lastStateUpdate, lastStateChange);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setState(State state) {
|
public void setState(State state) {
|
||||||
|
ZonedDateTime now = ZonedDateTime.now();
|
||||||
State oldState = this.state;
|
State oldState = this.state;
|
||||||
Item baseItem = this.baseItem;
|
Item baseItem = this.baseItem;
|
||||||
if (baseItem instanceof GenericItem item) {
|
if (baseItem instanceof GenericItem item) {
|
||||||
|
@ -387,6 +391,10 @@ public class GroupItem extends GenericItem implements StateChangeListener, Metad
|
||||||
this.state = state;
|
this.state = state;
|
||||||
}
|
}
|
||||||
notifyListeners(oldState, state);
|
notifyListeners(oldState, state);
|
||||||
|
if (!oldState.equals(state)) {
|
||||||
|
lastStateChange = now;
|
||||||
|
}
|
||||||
|
lastStateUpdate = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -405,18 +413,20 @@ public class GroupItem extends GenericItem implements StateChangeListener, Metad
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendGroupStateUpdatedEvent(String memberName, State state) {
|
private void sendGroupStateUpdatedEvent(String memberName, State state, @Nullable ZonedDateTime lastStateUpdate) {
|
||||||
EventPublisher eventPublisher1 = this.eventPublisher;
|
EventPublisher eventPublisher1 = this.eventPublisher;
|
||||||
if (eventPublisher1 != null) {
|
if (eventPublisher1 != null) {
|
||||||
eventPublisher1.post(ItemEventFactory.createGroupStateUpdatedEvent(getName(), memberName, state, null));
|
eventPublisher1.post(
|
||||||
|
ItemEventFactory.createGroupStateUpdatedEvent(getName(), memberName, state, lastStateUpdate, null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendGroupStateChangedEvent(String memberName, State newState, State oldState) {
|
private void sendGroupStateChangedEvent(String memberName, State newState, State oldState,
|
||||||
|
@Nullable ZonedDateTime lastStateUpdate, @Nullable ZonedDateTime lastStateChange) {
|
||||||
EventPublisher eventPublisher1 = this.eventPublisher;
|
EventPublisher eventPublisher1 = this.eventPublisher;
|
||||||
if (eventPublisher1 != null) {
|
if (eventPublisher1 != null) {
|
||||||
eventPublisher1
|
eventPublisher1.post(ItemEventFactory.createGroupStateChangedEvent(getName(), memberName, newState,
|
||||||
.post(ItemEventFactory.createGroupStateChangedEvent(getName(), memberName, newState, oldState));
|
oldState, lastStateUpdate, lastStateChange));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,10 @@
|
||||||
*/
|
*/
|
||||||
package org.openhab.core.items.events;
|
package org.openhab.core.items.events;
|
||||||
|
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.core.types.State;
|
import org.openhab.core.types.State;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,8 +37,9 @@ public class GroupItemStateChangedEvent extends ItemStateChangedEvent {
|
||||||
private final String memberName;
|
private final String memberName;
|
||||||
|
|
||||||
protected GroupItemStateChangedEvent(String topic, String payload, String itemName, String memberName,
|
protected GroupItemStateChangedEvent(String topic, String payload, String itemName, String memberName,
|
||||||
State newItemState, State oldItemState) {
|
State newItemState, State oldItemState, @Nullable ZonedDateTime lastStateUpdate,
|
||||||
super(topic, payload, itemName, newItemState, oldItemState);
|
@Nullable ZonedDateTime lastStateChange) {
|
||||||
|
super(topic, payload, itemName, newItemState, oldItemState, lastStateUpdate, lastStateChange);
|
||||||
this.memberName = memberName;
|
this.memberName = memberName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
*/
|
*/
|
||||||
package org.openhab.core.items.events;
|
package org.openhab.core.items.events;
|
||||||
|
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.core.types.State;
|
import org.openhab.core.types.State;
|
||||||
|
@ -34,8 +36,8 @@ public class GroupStateUpdatedEvent extends ItemStateUpdatedEvent {
|
||||||
private final String memberName;
|
private final String memberName;
|
||||||
|
|
||||||
protected GroupStateUpdatedEvent(String topic, String payload, String itemName, String memberName,
|
protected GroupStateUpdatedEvent(String topic, String payload, String itemName, String memberName,
|
||||||
State newItemState, @Nullable String source) {
|
State newItemState, @Nullable ZonedDateTime lastStateUpdate, @Nullable String source) {
|
||||||
super(topic, payload, itemName, newItemState, source);
|
super(topic, payload, itemName, newItemState, lastStateUpdate, source);
|
||||||
this.memberName = memberName;
|
this.memberName = memberName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ package org.openhab.core.items.events;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -114,9 +115,10 @@ public class ItemEventFactory extends AbstractEventFactory {
|
||||||
private Event createGroupStateUpdatedEvent(String topic, String payload) {
|
private Event createGroupStateUpdatedEvent(String topic, String payload) {
|
||||||
String itemName = getItemName(topic);
|
String itemName = getItemName(topic);
|
||||||
String memberName = getMemberName(topic);
|
String memberName = getMemberName(topic);
|
||||||
ItemEventPayloadBean bean = deserializePayload(payload, ItemEventPayloadBean.class);
|
ItemStateUpdatedEventPayloadBean bean = deserializePayload(payload, ItemStateUpdatedEventPayloadBean.class);
|
||||||
State state = getState(bean.getType(), bean.getValue());
|
State state = getState(bean.getType(), bean.getValue());
|
||||||
return new GroupStateUpdatedEvent(topic, payload, itemName, memberName, state, null);
|
ZonedDateTime lastStateUpdate = bean.getLastUpdate();
|
||||||
|
return new GroupStateUpdatedEvent(topic, payload, itemName, memberName, state, lastStateUpdate, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Event createGroupStateChangedEvent(String topic, String payload) {
|
private Event createGroupStateChangedEvent(String topic, String payload) {
|
||||||
|
@ -125,7 +127,10 @@ public class ItemEventFactory extends AbstractEventFactory {
|
||||||
ItemStateChangedEventPayloadBean bean = deserializePayload(payload, ItemStateChangedEventPayloadBean.class);
|
ItemStateChangedEventPayloadBean bean = deserializePayload(payload, ItemStateChangedEventPayloadBean.class);
|
||||||
State state = getState(bean.getType(), bean.getValue());
|
State state = getState(bean.getType(), bean.getValue());
|
||||||
State oldState = getState(bean.getOldType(), bean.getOldValue());
|
State oldState = getState(bean.getOldType(), bean.getOldValue());
|
||||||
return new GroupItemStateChangedEvent(topic, payload, itemName, memberName, state, oldState);
|
ZonedDateTime lastStateChange = bean.getLastStateChange();
|
||||||
|
ZonedDateTime lastStateUpdate = bean.getLastStateUpdate();
|
||||||
|
return new GroupItemStateChangedEvent(topic, payload, itemName, memberName, state, oldState, lastStateUpdate,
|
||||||
|
lastStateChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Event createCommandEvent(String topic, String payload, @Nullable String source) {
|
private Event createCommandEvent(String topic, String payload, @Nullable String source) {
|
||||||
|
@ -151,9 +156,10 @@ public class ItemEventFactory extends AbstractEventFactory {
|
||||||
|
|
||||||
private Event createStateUpdatedEvent(String topic, String payload) {
|
private Event createStateUpdatedEvent(String topic, String payload) {
|
||||||
String itemName = getItemName(topic);
|
String itemName = getItemName(topic);
|
||||||
ItemEventPayloadBean bean = deserializePayload(payload, ItemEventPayloadBean.class);
|
ItemStateUpdatedEventPayloadBean bean = deserializePayload(payload, ItemStateUpdatedEventPayloadBean.class);
|
||||||
State state = getState(bean.getType(), bean.getValue());
|
State state = getState(bean.getType(), bean.getValue());
|
||||||
return new ItemStateUpdatedEvent(topic, payload, itemName, state, null);
|
ZonedDateTime lastStateUpdate = bean.getLastUpdate();
|
||||||
|
return new ItemStateUpdatedEvent(topic, payload, itemName, state, lastStateUpdate, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Event createStateChangedEvent(String topic, String payload) {
|
private Event createStateChangedEvent(String topic, String payload) {
|
||||||
|
@ -161,7 +167,9 @@ public class ItemEventFactory extends AbstractEventFactory {
|
||||||
ItemStateChangedEventPayloadBean bean = deserializePayload(payload, ItemStateChangedEventPayloadBean.class);
|
ItemStateChangedEventPayloadBean bean = deserializePayload(payload, ItemStateChangedEventPayloadBean.class);
|
||||||
State state = getState(bean.getType(), bean.getValue());
|
State state = getState(bean.getType(), bean.getValue());
|
||||||
State oldState = getState(bean.getOldType(), bean.getOldValue());
|
State oldState = getState(bean.getOldType(), bean.getOldValue());
|
||||||
return new ItemStateChangedEvent(topic, payload, itemName, state, oldState);
|
ZonedDateTime lastStateUpdate = bean.getLastStateUpdate();
|
||||||
|
ZonedDateTime lastStateChange = bean.getLastStateChange();
|
||||||
|
return new ItemStateChangedEvent(topic, payload, itemName, state, oldState, lastStateUpdate, lastStateChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Event createTimeSeriesEvent(String topic, String payload) {
|
private Event createTimeSeriesEvent(String topic, String payload) {
|
||||||
|
@ -319,11 +327,13 @@ public class ItemEventFactory extends AbstractEventFactory {
|
||||||
*
|
*
|
||||||
* @param itemName the name of the item to report the state update for
|
* @param itemName the name of the item to report the state update for
|
||||||
* @param state the new state
|
* @param state the new state
|
||||||
|
* @param lastStateUpdate the time of the last state update
|
||||||
* @return the created item state update event
|
* @return the created item state update event
|
||||||
* @throws IllegalArgumentException if itemName or state is null
|
* @throws IllegalArgumentException if itemName or state is null
|
||||||
*/
|
*/
|
||||||
public static ItemStateUpdatedEvent createStateUpdatedEvent(String itemName, State state) {
|
public static ItemStateUpdatedEvent createStateUpdatedEvent(String itemName, State state,
|
||||||
return createStateUpdatedEvent(itemName, state, null);
|
@Nullable ZonedDateTime lastStateUpdate) {
|
||||||
|
return createStateUpdatedEvent(itemName, state, lastStateUpdate, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -331,16 +341,19 @@ public class ItemEventFactory extends AbstractEventFactory {
|
||||||
*
|
*
|
||||||
* @param itemName the name of the item to report the state update for
|
* @param itemName the name of the item to report the state update for
|
||||||
* @param state the new state
|
* @param state the new state
|
||||||
|
* @param lastStateUpdate the time of the last state update
|
||||||
* @param source the name of the source identifying the sender (can be null)
|
* @param source the name of the source identifying the sender (can be null)
|
||||||
* @return the created item state update event
|
* @return the created item state update event
|
||||||
* @throws IllegalArgumentException if itemName or state is null
|
* @throws IllegalArgumentException if itemName or state is null
|
||||||
*/
|
*/
|
||||||
public static ItemStateUpdatedEvent createStateUpdatedEvent(String itemName, State state, @Nullable String source) {
|
public static ItemStateUpdatedEvent createStateUpdatedEvent(String itemName, State state,
|
||||||
|
@Nullable ZonedDateTime lastStateUpdate, @Nullable String source) {
|
||||||
assertValidArguments(itemName, state, "state");
|
assertValidArguments(itemName, state, "state");
|
||||||
String topic = buildTopic(ITEM_STATE_UPDATED_EVENT_TOPIC, itemName);
|
String topic = buildTopic(ITEM_STATE_UPDATED_EVENT_TOPIC, itemName);
|
||||||
ItemEventPayloadBean bean = new ItemEventPayloadBean(getStateType(state), state.toFullString());
|
ItemStateUpdatedEventPayloadBean bean = new ItemStateUpdatedEventPayloadBean(getStateType(state),
|
||||||
|
state.toFullString(), lastStateUpdate);
|
||||||
String payload = serializePayload(bean);
|
String payload = serializePayload(bean);
|
||||||
return new ItemStateUpdatedEvent(topic, payload, itemName, state, source);
|
return new ItemStateUpdatedEvent(topic, payload, itemName, state, lastStateUpdate, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ItemTimeSeriesEvent createTimeSeriesEvent(String itemName, TimeSeries timeSeries,
|
public static ItemTimeSeriesEvent createTimeSeriesEvent(String itemName, TimeSeries timeSeries,
|
||||||
|
@ -365,17 +378,19 @@ public class ItemEventFactory extends AbstractEventFactory {
|
||||||
* @param groupName the name of the group to report the state update for
|
* @param groupName the name of the group to report the state update for
|
||||||
* @param member the name of the item that updated the group state
|
* @param member the name of the item that updated the group state
|
||||||
* @param state the new state
|
* @param state the new state
|
||||||
|
* @param lastStateUpdate the time of the last state update
|
||||||
* @param source the name of the source identifying the sender (can be null)
|
* @param source the name of the source identifying the sender (can be null)
|
||||||
* @return the created group item state update event
|
* @return the created group item state update event
|
||||||
* @throws IllegalArgumentException if groupName or state is null
|
* @throws IllegalArgumentException if groupName or state is null
|
||||||
*/
|
*/
|
||||||
public static GroupStateUpdatedEvent createGroupStateUpdatedEvent(String groupName, String member, State state,
|
public static GroupStateUpdatedEvent createGroupStateUpdatedEvent(String groupName, String member, State state,
|
||||||
@Nullable String source) {
|
@Nullable ZonedDateTime lastStateUpdate, @Nullable String source) {
|
||||||
assertValidArguments(groupName, member, state, "state");
|
assertValidArguments(groupName, member, state, "state");
|
||||||
String topic = buildGroupTopic(GROUP_STATE_EVENT_TOPIC, groupName, member);
|
String topic = buildGroupTopic(GROUP_STATE_EVENT_TOPIC, groupName, member);
|
||||||
ItemEventPayloadBean bean = new ItemEventPayloadBean(getStateType(state), state.toFullString());
|
ItemStateUpdatedEventPayloadBean bean = new ItemStateUpdatedEventPayloadBean(getStateType(state),
|
||||||
|
state.toFullString(), lastStateUpdate);
|
||||||
String payload = serializePayload(bean);
|
String payload = serializePayload(bean);
|
||||||
return new GroupStateUpdatedEvent(topic, payload, groupName, member, state, source);
|
return new GroupStateUpdatedEvent(topic, payload, groupName, member, state, lastStateUpdate, source);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -403,16 +418,20 @@ public class ItemEventFactory extends AbstractEventFactory {
|
||||||
* @param itemName the name of the item to send the state changed event for
|
* @param itemName the name of the item to send the state changed event for
|
||||||
* @param newState the new state to send
|
* @param newState the new state to send
|
||||||
* @param oldState the old state of the item
|
* @param oldState the old state of the item
|
||||||
|
* @param lastStateChange the time of the last state change
|
||||||
* @return the created item state changed event
|
* @return the created item state changed event
|
||||||
* @throws IllegalArgumentException if itemName or state is null
|
* @throws IllegalArgumentException if itemName or state is null
|
||||||
*/
|
*/
|
||||||
public static ItemStateChangedEvent createStateChangedEvent(String itemName, State newState, State oldState) {
|
public static ItemStateChangedEvent createStateChangedEvent(String itemName, State newState, State oldState,
|
||||||
|
@Nullable ZonedDateTime lastStateUpdate, @Nullable ZonedDateTime lastStateChange) {
|
||||||
assertValidArguments(itemName, newState, "state");
|
assertValidArguments(itemName, newState, "state");
|
||||||
String topic = buildTopic(ITEM_STATE_CHANGED_EVENT_TOPIC, itemName);
|
String topic = buildTopic(ITEM_STATE_CHANGED_EVENT_TOPIC, itemName);
|
||||||
ItemStateChangedEventPayloadBean bean = new ItemStateChangedEventPayloadBean(getStateType(newState),
|
ItemStateChangedEventPayloadBean bean = new ItemStateChangedEventPayloadBean(getStateType(newState),
|
||||||
newState.toFullString(), getStateType(oldState), oldState.toFullString());
|
newState.toFullString(), getStateType(oldState), oldState.toFullString(), lastStateUpdate,
|
||||||
|
lastStateChange);
|
||||||
String payload = serializePayload(bean);
|
String payload = serializePayload(bean);
|
||||||
return new ItemStateChangedEvent(topic, payload, itemName, newState, oldState);
|
return new ItemStateChangedEvent(topic, payload, itemName, newState, oldState, lastStateUpdate,
|
||||||
|
lastStateChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -422,17 +441,22 @@ public class ItemEventFactory extends AbstractEventFactory {
|
||||||
* @param memberName the name of the member causing the group item state change
|
* @param memberName the name of the member causing the group item state change
|
||||||
* @param newState the new state to send
|
* @param newState the new state to send
|
||||||
* @param oldState the old state of the group item
|
* @param oldState the old state of the group item
|
||||||
|
* @param lastStateUpdate the time of the last state update
|
||||||
|
* @param lastStateChange the time of the last state change
|
||||||
* @return the created group item state changed event
|
* @return the created group item state changed event
|
||||||
* @throws IllegalArgumentException if itemName or state is null
|
* @throws IllegalArgumentException if itemName or state is null
|
||||||
*/
|
*/
|
||||||
public static GroupItemStateChangedEvent createGroupStateChangedEvent(String itemName, String memberName,
|
public static GroupItemStateChangedEvent createGroupStateChangedEvent(String itemName, String memberName,
|
||||||
State newState, State oldState) {
|
State newState, State oldState, @Nullable ZonedDateTime lastStateUpdate,
|
||||||
|
@Nullable ZonedDateTime lastStateChange) {
|
||||||
assertValidArguments(itemName, memberName, newState, "state");
|
assertValidArguments(itemName, memberName, newState, "state");
|
||||||
String topic = buildGroupTopic(GROUPITEM_STATE_CHANGED_EVENT_TOPIC, itemName, memberName);
|
String topic = buildGroupTopic(GROUPITEM_STATE_CHANGED_EVENT_TOPIC, itemName, memberName);
|
||||||
ItemStateChangedEventPayloadBean bean = new ItemStateChangedEventPayloadBean(getStateType(newState),
|
ItemStateChangedEventPayloadBean bean = new ItemStateChangedEventPayloadBean(getStateType(newState),
|
||||||
newState.toFullString(), getStateType(oldState), oldState.toFullString());
|
newState.toFullString(), getStateType(oldState), oldState.toFullString(), lastStateUpdate,
|
||||||
|
lastStateChange);
|
||||||
String payload = serializePayload(bean);
|
String payload = serializePayload(bean);
|
||||||
return new GroupItemStateChangedEvent(topic, payload, itemName, memberName, newState, oldState);
|
return new GroupItemStateChangedEvent(topic, payload, itemName, memberName, newState, oldState, lastStateUpdate,
|
||||||
|
lastStateChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -551,6 +575,40 @@ public class ItemEventFactory extends AbstractEventFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a java bean that is used to serialize/deserialize item state updated event payload.
|
||||||
|
*/
|
||||||
|
private static class ItemStateUpdatedEventPayloadBean {
|
||||||
|
private @NonNullByDefault({}) String type;
|
||||||
|
private @NonNullByDefault({}) String value;
|
||||||
|
private @Nullable ZonedDateTime lastUpdate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default constructor for deserialization e.g. by Gson.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
protected ItemStateUpdatedEventPayloadBean() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public ItemStateUpdatedEventPayloadBean(String type, String value, @Nullable ZonedDateTime lastUpdate) {
|
||||||
|
this.type = type;
|
||||||
|
this.value = value;
|
||||||
|
this.lastUpdate = lastUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable ZonedDateTime getLastUpdate() {
|
||||||
|
return lastUpdate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a java bean that is used to serialize/deserialize item state changed event payload.
|
* This is a java bean that is used to serialize/deserialize item state changed event payload.
|
||||||
*/
|
*/
|
||||||
|
@ -593,6 +651,8 @@ public class ItemEventFactory extends AbstractEventFactory {
|
||||||
private @NonNullByDefault({}) String value;
|
private @NonNullByDefault({}) String value;
|
||||||
private @NonNullByDefault({}) String oldType;
|
private @NonNullByDefault({}) String oldType;
|
||||||
private @NonNullByDefault({}) String oldValue;
|
private @NonNullByDefault({}) String oldValue;
|
||||||
|
private @Nullable ZonedDateTime lastStateUpdate;
|
||||||
|
private @Nullable ZonedDateTime lastStateChange;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default constructor for deserialization e.g. by Gson.
|
* Default constructor for deserialization e.g. by Gson.
|
||||||
|
@ -601,11 +661,14 @@ public class ItemEventFactory extends AbstractEventFactory {
|
||||||
protected ItemStateChangedEventPayloadBean() {
|
protected ItemStateChangedEventPayloadBean() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ItemStateChangedEventPayloadBean(String type, String value, String oldType, String oldValue) {
|
public ItemStateChangedEventPayloadBean(String type, String value, String oldType, String oldValue,
|
||||||
|
@Nullable ZonedDateTime lastStateUpdate, @Nullable ZonedDateTime lastStateChange) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.oldType = oldType;
|
this.oldType = oldType;
|
||||||
this.oldValue = oldValue;
|
this.oldValue = oldValue;
|
||||||
|
this.lastStateUpdate = lastStateUpdate;
|
||||||
|
this.lastStateChange = lastStateChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getType() {
|
public String getType() {
|
||||||
|
@ -623,6 +686,14 @@ public class ItemEventFactory extends AbstractEventFactory {
|
||||||
public String getOldValue() {
|
public String getOldValue() {
|
||||||
return oldValue;
|
return oldValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public @Nullable ZonedDateTime getLastStateUpdate() {
|
||||||
|
return lastStateUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable ZonedDateTime getLastStateChange() {
|
||||||
|
return lastStateChange;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ItemTimeSeriesEventPayloadBean {
|
private static class ItemTimeSeriesEventPayloadBean {
|
||||||
|
|
|
@ -12,7 +12,10 @@
|
||||||
*/
|
*/
|
||||||
package org.openhab.core.items.events;
|
package org.openhab.core.items.events;
|
||||||
|
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.core.types.State;
|
import org.openhab.core.types.State;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,6 +37,10 @@ public class ItemStateChangedEvent extends ItemEvent {
|
||||||
|
|
||||||
protected final State oldItemState;
|
protected final State oldItemState;
|
||||||
|
|
||||||
|
protected final @Nullable ZonedDateTime lastStateUpdate;
|
||||||
|
|
||||||
|
protected final @Nullable ZonedDateTime lastStateChange;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new item state changed event.
|
* Constructs a new item state changed event.
|
||||||
*
|
*
|
||||||
|
@ -42,12 +49,16 @@ public class ItemStateChangedEvent extends ItemEvent {
|
||||||
* @param itemName the item name
|
* @param itemName the item name
|
||||||
* @param newItemState the new item state
|
* @param newItemState the new item state
|
||||||
* @param oldItemState the old item state
|
* @param oldItemState the old item state
|
||||||
|
* @param lastStateUpdate the last state update
|
||||||
|
* @param lastStateChange the last state change
|
||||||
*/
|
*/
|
||||||
protected ItemStateChangedEvent(String topic, String payload, String itemName, State newItemState,
|
protected ItemStateChangedEvent(String topic, String payload, String itemName, State newItemState,
|
||||||
State oldItemState) {
|
State oldItemState, @Nullable ZonedDateTime lastStateUpdate, @Nullable ZonedDateTime lastStateChange) {
|
||||||
super(topic, payload, itemName, null);
|
super(topic, payload, itemName, null);
|
||||||
this.itemState = newItemState;
|
this.itemState = newItemState;
|
||||||
this.oldItemState = oldItemState;
|
this.oldItemState = oldItemState;
|
||||||
|
this.lastStateUpdate = lastStateUpdate;
|
||||||
|
this.lastStateChange = lastStateChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -73,6 +84,24 @@ public class ItemStateChangedEvent extends ItemEvent {
|
||||||
return oldItemState;
|
return oldItemState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the timestamp of the previous state update that occurred prior to this event.
|
||||||
|
*
|
||||||
|
* @return the last state update
|
||||||
|
*/
|
||||||
|
public @Nullable ZonedDateTime getLastStateUpdate() {
|
||||||
|
return lastStateUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the timestamp of the previous state change that occurred prior to this event.
|
||||||
|
*
|
||||||
|
* @return the last state change
|
||||||
|
*/
|
||||||
|
public @Nullable ZonedDateTime getLastStateChange() {
|
||||||
|
return lastStateChange;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("Item '%s' changed from %s to %s", itemName, oldItemState, itemState);
|
return String.format("Item '%s' changed from %s to %s", itemName, oldItemState, itemState);
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
*/
|
*/
|
||||||
package org.openhab.core.items.events;
|
package org.openhab.core.items.events;
|
||||||
|
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.eclipse.jdt.annotation.Nullable;
|
import org.eclipse.jdt.annotation.Nullable;
|
||||||
import org.openhab.core.types.State;
|
import org.openhab.core.types.State;
|
||||||
|
@ -31,6 +33,7 @@ public class ItemStateUpdatedEvent extends ItemEvent {
|
||||||
public static final String TYPE = ItemStateUpdatedEvent.class.getSimpleName();
|
public static final String TYPE = ItemStateUpdatedEvent.class.getSimpleName();
|
||||||
|
|
||||||
protected final State itemState;
|
protected final State itemState;
|
||||||
|
protected final @Nullable ZonedDateTime lastStateUpdate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a new item state event.
|
* Constructs a new item state event.
|
||||||
|
@ -39,12 +42,14 @@ public class ItemStateUpdatedEvent extends ItemEvent {
|
||||||
* @param payload the payload
|
* @param payload the payload
|
||||||
* @param itemName the item name
|
* @param itemName the item name
|
||||||
* @param itemState the item state
|
* @param itemState the item state
|
||||||
|
* @param lastStateUpdate the last state update
|
||||||
* @param source the source, can be null
|
* @param source the source, can be null
|
||||||
*/
|
*/
|
||||||
protected ItemStateUpdatedEvent(String topic, String payload, String itemName, State itemState,
|
protected ItemStateUpdatedEvent(String topic, String payload, String itemName, State itemState,
|
||||||
@Nullable String source) {
|
@Nullable ZonedDateTime lastStateUpdate, @Nullable String source) {
|
||||||
super(topic, payload, itemName, source);
|
super(topic, payload, itemName, source);
|
||||||
this.itemState = itemState;
|
this.itemState = itemState;
|
||||||
|
this.lastStateUpdate = lastStateUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -61,6 +66,15 @@ public class ItemStateUpdatedEvent extends ItemEvent {
|
||||||
return itemState;
|
return itemState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the timestamp of the previous state update that occurred prior to this event.
|
||||||
|
*
|
||||||
|
* @return the last state update
|
||||||
|
*/
|
||||||
|
public @Nullable ZonedDateTime getLastStateUpdate() {
|
||||||
|
return lastStateUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("Item '%s' updated to %s", itemName, itemState);
|
return String.format("Item '%s' updated to %s", itemName, itemState);
|
||||||
|
|
|
@ -142,7 +142,7 @@ class ExpireManagerTest {
|
||||||
Event event = ItemEventFactory.createCommandEvent(ITEMNAME, new DecimalType(1));
|
Event event = ItemEventFactory.createCommandEvent(ITEMNAME, new DecimalType(1));
|
||||||
expireManager.receive(event);
|
expireManager.receive(event);
|
||||||
Thread.sleep(1500L);
|
Thread.sleep(1500L);
|
||||||
event = ItemEventFactory.createStateChangedEvent(ITEMNAME, new DecimalType(2), new DecimalType(1));
|
event = ItemEventFactory.createStateChangedEvent(ITEMNAME, new DecimalType(2), new DecimalType(1), null, null);
|
||||||
expireManager.receive(event);
|
expireManager.receive(event);
|
||||||
Thread.sleep(1500L);
|
Thread.sleep(1500L);
|
||||||
verify(eventPublisherMock, never()).post(any());
|
verify(eventPublisherMock, never()).post(any());
|
||||||
|
@ -194,7 +194,7 @@ class ExpireManagerTest {
|
||||||
Event event = ItemEventFactory.createStateEvent(ITEMNAME, new DecimalType(1));
|
Event event = ItemEventFactory.createStateEvent(ITEMNAME, new DecimalType(1));
|
||||||
expireManager.receive(event);
|
expireManager.receive(event);
|
||||||
Thread.sleep(1500L);
|
Thread.sleep(1500L);
|
||||||
event = ItemEventFactory.createStateChangedEvent(ITEMNAME, new DecimalType(2), new DecimalType(1));
|
event = ItemEventFactory.createStateChangedEvent(ITEMNAME, new DecimalType(2), new DecimalType(1), null, null);
|
||||||
expireManager.receive(event);
|
expireManager.receive(event);
|
||||||
Thread.sleep(1500L);
|
Thread.sleep(1500L);
|
||||||
verify(eventPublisherMock, never()).post(any());
|
verify(eventPublisherMock, never()).post(any());
|
||||||
|
|
|
@ -56,6 +56,8 @@ public class GenericItemTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testItemPostsEventsCorrectly() {
|
public void testItemPostsEventsCorrectly() {
|
||||||
|
ZonedDateTime lastStateUpdate;
|
||||||
|
ZonedDateTime lastStateChange;
|
||||||
EventPublisher publisher = mock(EventPublisher.class);
|
EventPublisher publisher = mock(EventPublisher.class);
|
||||||
|
|
||||||
TestItem item = new TestItem("member1");
|
TestItem item = new TestItem("member1");
|
||||||
|
@ -78,6 +80,7 @@ public class GenericItemTest {
|
||||||
assertEquals(item.getName(), updated.getItemName());
|
assertEquals(item.getName(), updated.getItemName());
|
||||||
assertEquals("openhab/items/member1/stateupdated", updated.getTopic());
|
assertEquals("openhab/items/member1/stateupdated", updated.getTopic());
|
||||||
assertEquals(item.getState(), updated.getItemState());
|
assertEquals(item.getState(), updated.getItemState());
|
||||||
|
assertEquals(null, updated.getLastStateUpdate()); // this is the first update, so there is no previous update
|
||||||
assertEquals(ItemStateUpdatedEvent.TYPE, updated.getType());
|
assertEquals(ItemStateUpdatedEvent.TYPE, updated.getType());
|
||||||
|
|
||||||
// second event should be changed event
|
// second event should be changed event
|
||||||
|
@ -87,12 +90,16 @@ public class GenericItemTest {
|
||||||
assertEquals("openhab/items/member1/statechanged", change.getTopic());
|
assertEquals("openhab/items/member1/statechanged", change.getTopic());
|
||||||
assertEquals(oldState, change.getOldItemState());
|
assertEquals(oldState, change.getOldItemState());
|
||||||
assertEquals(item.getState(), change.getItemState());
|
assertEquals(item.getState(), change.getItemState());
|
||||||
|
assertEquals(null, change.getLastStateChange()); // this is the first change, so there is no previous change
|
||||||
assertEquals(ItemStateChangedEvent.TYPE, change.getType());
|
assertEquals(ItemStateChangedEvent.TYPE, change.getType());
|
||||||
|
|
||||||
// reset invocations and captor
|
// reset invocations and captor
|
||||||
clearInvocations(publisher);
|
clearInvocations(publisher);
|
||||||
captor = ArgumentCaptor.forClass(ItemEvent.class);
|
captor = ArgumentCaptor.forClass(ItemEvent.class);
|
||||||
|
|
||||||
|
lastStateChange = item.getLastStateChange();
|
||||||
|
lastStateUpdate = item.getLastStateUpdate();
|
||||||
|
|
||||||
// State doesn't change -> only update event is fired
|
// State doesn't change -> only update event is fired
|
||||||
item.setState(item.getState());
|
item.setState(item.getState());
|
||||||
verify(publisher).post(captor.capture());
|
verify(publisher).post(captor.capture());
|
||||||
|
@ -106,7 +113,25 @@ public class GenericItemTest {
|
||||||
assertEquals(item.getName(), updated.getItemName());
|
assertEquals(item.getName(), updated.getItemName());
|
||||||
assertEquals("openhab/items/member1/stateupdated", updated.getTopic());
|
assertEquals("openhab/items/member1/stateupdated", updated.getTopic());
|
||||||
assertEquals(item.getState(), updated.getItemState());
|
assertEquals(item.getState(), updated.getItemState());
|
||||||
|
assertEquals(lastStateUpdate, updated.getLastStateUpdate());
|
||||||
assertEquals(ItemStateUpdatedEvent.TYPE, updated.getType());
|
assertEquals(ItemStateUpdatedEvent.TYPE, updated.getType());
|
||||||
|
|
||||||
|
// State changes -> the ItemStateChangedEvent should include the lastStateChange
|
||||||
|
clearInvocations(publisher);
|
||||||
|
captor = ArgumentCaptor.forClass(ItemEvent.class);
|
||||||
|
|
||||||
|
lastStateUpdate = item.getLastStateUpdate();
|
||||||
|
|
||||||
|
// New State
|
||||||
|
item.setState(new RawType(new byte[1], RawType.DEFAULT_MIME_TYPE));
|
||||||
|
verify(publisher, times(2)).post(captor.capture());
|
||||||
|
|
||||||
|
events = captor.getAllValues();
|
||||||
|
assertEquals(2, events.size());
|
||||||
|
assertInstanceOf(ItemStateChangedEvent.class, events.get(1));
|
||||||
|
change = (ItemStateChangedEvent) events.get(1);
|
||||||
|
assertEquals(lastStateUpdate, change.getLastStateUpdate());
|
||||||
|
assertEquals(lastStateChange, change.getLastStateChange());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -16,6 +16,8 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.is;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
|
||||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.openhab.core.events.Event;
|
import org.openhab.core.events.Event;
|
||||||
|
@ -225,8 +227,10 @@ public class ItemEventFactoryTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCreateGroupStateChangedEventRawType() throws Exception {
|
public void testCreateGroupStateChangedEventRawType() throws Exception {
|
||||||
|
ZonedDateTime lastStateUpdate = ZonedDateTime.now();
|
||||||
|
ZonedDateTime lastStateChange = ZonedDateTime.now().minusMinutes(1);
|
||||||
GroupItemStateChangedEvent giEventSource = ItemEventFactory.createGroupStateChangedEvent(GROUP_NAME, ITEM_NAME,
|
GroupItemStateChangedEvent giEventSource = ItemEventFactory.createGroupStateChangedEvent(GROUP_NAME, ITEM_NAME,
|
||||||
NEW_RAW_ITEM_STATE, RAW_ITEM_STATE);
|
NEW_RAW_ITEM_STATE, RAW_ITEM_STATE, lastStateUpdate, lastStateChange);
|
||||||
|
|
||||||
Event giEventParsed = factory.createEvent(giEventSource.getType(), giEventSource.getTopic(),
|
Event giEventParsed = factory.createEvent(giEventSource.getType(), giEventSource.getTopic(),
|
||||||
giEventSource.getPayload(), giEventSource.getSource());
|
giEventSource.getPayload(), giEventSource.getSource());
|
||||||
|
@ -242,5 +246,7 @@ public class ItemEventFactoryTest {
|
||||||
assertNull(groupItemStateChangedEvent.getSource());
|
assertNull(groupItemStateChangedEvent.getSource());
|
||||||
assertEquals(NEW_RAW_ITEM_STATE, groupItemStateChangedEvent.getItemState());
|
assertEquals(NEW_RAW_ITEM_STATE, groupItemStateChangedEvent.getItemState());
|
||||||
assertEquals(RAW_ITEM_STATE, groupItemStateChangedEvent.getOldItemState());
|
assertEquals(RAW_ITEM_STATE, groupItemStateChangedEvent.getOldItemState());
|
||||||
|
assertEquals(lastStateUpdate, groupItemStateChangedEvent.getLastStateUpdate());
|
||||||
|
assertEquals(lastStateChange, groupItemStateChangedEvent.getLastStateChange());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -191,7 +191,7 @@ public abstract class BasicConditionHandlerTest extends JavaOSGiTest {
|
||||||
logger.info("Rule is enabled and idle");
|
logger.info("Rule is enabled and idle");
|
||||||
|
|
||||||
logger.info("Send and wait for item state is ON");
|
logger.info("Send and wait for item state is ON");
|
||||||
eventPublisher.post(ItemEventFactory.createStateUpdatedEvent(testItemName1, OnOffType.ON));
|
eventPublisher.post(ItemEventFactory.createStateUpdatedEvent(testItemName1, OnOffType.ON, null));
|
||||||
|
|
||||||
waitForAssert(() -> {
|
waitForAssert(() -> {
|
||||||
assertThat(itemEvent, is(notNullValue()));
|
assertThat(itemEvent, is(notNullValue()));
|
||||||
|
@ -207,7 +207,7 @@ public abstract class BasicConditionHandlerTest extends JavaOSGiTest {
|
||||||
|
|
||||||
// prepare the execution
|
// prepare the execution
|
||||||
itemEvent = null;
|
itemEvent = null;
|
||||||
eventPublisher.post(ItemEventFactory.createStateUpdatedEvent(testItemName1, OnOffType.ON));
|
eventPublisher.post(ItemEventFactory.createStateUpdatedEvent(testItemName1, OnOffType.ON, null));
|
||||||
Thread.sleep(200); // without this, the assertion will be immediately fulfilled regardless of event processing
|
Thread.sleep(200); // without this, the assertion will be immediately fulfilled regardless of event processing
|
||||||
assertThat(itemEvent, is(nullValue()));
|
assertThat(itemEvent, is(nullValue()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,7 +168,7 @@ public class IntervalConditionHandlerTest extends BasicConditionHandlerTest {
|
||||||
logger.info("Rule is enabled and idle");
|
logger.info("Rule is enabled and idle");
|
||||||
|
|
||||||
logger.info("Send and wait for item state is ON");
|
logger.info("Send and wait for item state is ON");
|
||||||
eventPublisher.post(ItemEventFactory.createStateUpdatedEvent(testItemName1, OnOffType.ON));
|
eventPublisher.post(ItemEventFactory.createStateUpdatedEvent(testItemName1, OnOffType.ON, null));
|
||||||
|
|
||||||
// the first event is always processed
|
// the first event is always processed
|
||||||
waitForAssert(() -> {
|
waitForAssert(() -> {
|
||||||
|
@ -182,7 +182,7 @@ public class IntervalConditionHandlerTest extends BasicConditionHandlerTest {
|
||||||
|
|
||||||
// Send a second event to check if the condition is still satisfied
|
// Send a second event to check if the condition is still satisfied
|
||||||
itemEvent = null; // reset it
|
itemEvent = null; // reset it
|
||||||
eventPublisher.post(ItemEventFactory.createStateUpdatedEvent(testItemName1, OnOffType.ON));
|
eventPublisher.post(ItemEventFactory.createStateUpdatedEvent(testItemName1, OnOffType.ON, null));
|
||||||
|
|
||||||
waitForAssert(() -> {
|
waitForAssert(() -> {
|
||||||
assertThat(itemEvent, is(notNullValue()));
|
assertThat(itemEvent, is(notNullValue()));
|
||||||
|
@ -198,7 +198,7 @@ public class IntervalConditionHandlerTest extends BasicConditionHandlerTest {
|
||||||
|
|
||||||
// prepare the execution
|
// prepare the execution
|
||||||
itemEvent = null;
|
itemEvent = null;
|
||||||
eventPublisher.post(ItemEventFactory.createStateUpdatedEvent(testItemName1, OnOffType.ON));
|
eventPublisher.post(ItemEventFactory.createStateUpdatedEvent(testItemName1, OnOffType.ON, null));
|
||||||
|
|
||||||
// the first event is always allowed
|
// the first event is always allowed
|
||||||
waitForAssert(() -> {
|
waitForAssert(() -> {
|
||||||
|
@ -209,7 +209,7 @@ public class IntervalConditionHandlerTest extends BasicConditionHandlerTest {
|
||||||
|
|
||||||
// the second event is not allowed
|
// the second event is not allowed
|
||||||
itemEvent = null;
|
itemEvent = null;
|
||||||
eventPublisher.post(ItemEventFactory.createStateUpdatedEvent(testItemName1, OnOffType.ON));
|
eventPublisher.post(ItemEventFactory.createStateUpdatedEvent(testItemName1, OnOffType.ON, null));
|
||||||
Thread.sleep(200); // without this, the assertion will be immediately fulfilled regardless of event processing
|
Thread.sleep(200); // without this, the assertion will be immediately fulfilled regardless of event processing
|
||||||
assertThat(itemEvent, is(nullValue()));
|
assertThat(itemEvent, is(nullValue()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -360,7 +360,7 @@ public class CommunicationManagerOSGiTest extends JavaOSGiTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testItemStateEventSingleLink() {
|
public void testItemStateEventSingleLink() {
|
||||||
manager.receive(ItemEventFactory.createStateUpdatedEvent(ITEM_NAME_2, OnOffType.ON));
|
manager.receive(ItemEventFactory.createStateUpdatedEvent(ITEM_NAME_2, OnOffType.ON, null));
|
||||||
waitForAssert(() -> {
|
waitForAssert(() -> {
|
||||||
verify(stateProfileMock).onStateUpdateFromItem(eq(OnOffType.ON));
|
verify(stateProfileMock).onStateUpdateFromItem(eq(OnOffType.ON));
|
||||||
verify(triggerProfileMock).onStateUpdateFromItem(eq(OnOffType.ON));
|
verify(triggerProfileMock).onStateUpdateFromItem(eq(OnOffType.ON));
|
||||||
|
@ -371,7 +371,7 @@ public class CommunicationManagerOSGiTest extends JavaOSGiTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testItemStateEventMultiLink() {
|
public void testItemStateEventMultiLink() {
|
||||||
manager.receive(ItemEventFactory.createStateUpdatedEvent(ITEM_NAME_1, OnOffType.ON));
|
manager.receive(ItemEventFactory.createStateUpdatedEvent(ITEM_NAME_1, OnOffType.ON, null));
|
||||||
waitForAssert(() -> {
|
waitForAssert(() -> {
|
||||||
verify(stateProfileMock, times(2)).onStateUpdateFromItem(eq(OnOffType.ON));
|
verify(stateProfileMock, times(2)).onStateUpdateFromItem(eq(OnOffType.ON));
|
||||||
verify(triggerProfileMock, times(2)).onStateUpdateFromItem(eq(OnOffType.ON));
|
verify(triggerProfileMock, times(2)).onStateUpdateFromItem(eq(OnOffType.ON));
|
||||||
|
@ -382,8 +382,8 @@ public class CommunicationManagerOSGiTest extends JavaOSGiTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testItemStateEventNotToSource() {
|
public void testItemStateEventNotToSource() {
|
||||||
manager.receive(
|
manager.receive(ItemEventFactory.createStateUpdatedEvent(ITEM_NAME_1, OnOffType.ON, null,
|
||||||
ItemEventFactory.createStateUpdatedEvent(ITEM_NAME_1, OnOffType.ON, STATE_CHANNEL_UID_2.getAsString()));
|
STATE_CHANNEL_UID_2.getAsString()));
|
||||||
waitForAssert(() -> {
|
waitForAssert(() -> {
|
||||||
verify(stateProfileMock).onStateUpdateFromItem(eq(OnOffType.ON));
|
verify(stateProfileMock).onStateUpdateFromItem(eq(OnOffType.ON));
|
||||||
verify(triggerProfileMock, times(2)).onStateUpdateFromItem(eq(OnOffType.ON));
|
verify(triggerProfileMock, times(2)).onStateUpdateFromItem(eq(OnOffType.ON));
|
||||||
|
|
Loading…
Reference in New Issue