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)) {
|
||||
State state = isEvent.getItemState();
|
||||
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) {
|
||||
values.put("triggeringGroup", group);
|
||||
}
|
||||
values.put("triggeringItem", item);
|
||||
values.put("state", state);
|
||||
values.put("lastStateUpdate", isEvent.getLastStateUpdate());
|
||||
values.put("event", event);
|
||||
cb.triggered(this.module, values);
|
||||
}
|
||||
|
@ -142,13 +143,15 @@ public class GroupStateTriggerHandler extends BaseTriggerModuleHandler implement
|
|||
State oldState = iscEvent.getOldItemState();
|
||||
|
||||
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) {
|
||||
values.put("triggeringGroup", group);
|
||||
}
|
||||
values.put("triggeringItem", item);
|
||||
values.put("oldState", oldState);
|
||||
values.put("newState", state);
|
||||
values.put("lastStateUpdate", iscEvent.getLastStateUpdate());
|
||||
values.put("lastStateChange", iscEvent.getLastStateChange());
|
||||
values.put("event", event);
|
||||
cb.triggered(this.module, values);
|
||||
}
|
||||
|
|
|
@ -132,13 +132,14 @@ public class ItemStateTriggerHandler extends BaseTriggerModuleHandler implements
|
|||
if (callback != null) {
|
||||
logger.trace("Received Event: Source: {} Topic: {} Type: {} Payload: {}", event.getSource(),
|
||||
event.getTopic(), event.getType(), event.getPayload());
|
||||
Map<String, Object> values = new HashMap<>();
|
||||
Map<String, @Nullable Object> values = new HashMap<>();
|
||||
if (event instanceof ItemStateUpdatedEvent updatedEvent
|
||||
&& UPDATE_MODULE_TYPE_ID.equals(module.getTypeUID())) {
|
||||
String state = this.state;
|
||||
State itemState = updatedEvent.getItemState();
|
||||
if ((state == null || state.equals(itemState.toFullString()))) {
|
||||
values.put("state", itemState);
|
||||
values.put("lastStateUpdate", updatedEvent.getLastStateUpdate());
|
||||
}
|
||||
} else if (event instanceof ItemStateChangedEvent changedEvent
|
||||
&& 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)) {
|
||||
values.put("oldState", oldItemState);
|
||||
values.put("newState", itemState);
|
||||
values.put("lastStateUpdate", changedEvent.getLastStateUpdate());
|
||||
values.put("lastStateChange", changedEvent.getLastStateChange());
|
||||
}
|
||||
}
|
||||
if (!values.isEmpty()) {
|
||||
|
|
|
@ -125,6 +125,12 @@
|
|||
"state"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "lastStateUpdate",
|
||||
"type": "java.time.ZonedDateTime",
|
||||
"description": "the time of the previous state update",
|
||||
"label": "Last State Update"
|
||||
},
|
||||
{
|
||||
"name": "event",
|
||||
"type": "org.openhab.core.events.Event",
|
||||
|
@ -220,8 +226,8 @@
|
|||
{
|
||||
"name": "newState",
|
||||
"type": "state",
|
||||
"description": "the new item state",
|
||||
"label": "New State",
|
||||
"description": "the new item state",
|
||||
"tags": [
|
||||
"state"
|
||||
]
|
||||
|
@ -229,8 +235,20 @@
|
|||
{
|
||||
"name": "oldState",
|
||||
"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",
|
||||
|
@ -402,6 +420,12 @@
|
|||
"state"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "lastStateUpdate",
|
||||
"type": "java.time.ZonedDateTime",
|
||||
"description": "the time of the previous state update",
|
||||
"label": "Last State Update"
|
||||
},
|
||||
{
|
||||
"name": "event",
|
||||
"type": "org.openhab.core.events.Event",
|
||||
|
@ -518,6 +542,18 @@
|
|||
"description": "the old item 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",
|
||||
"type": "org.openhab.core.events.Event",
|
||||
|
|
|
@ -258,7 +258,8 @@ public class EventWebSocketTest {
|
|||
eventWebSocket.processEvent(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);
|
||||
verify(remoteEndpoint).sendString(gson.toJson(new EventDTO(event)));
|
||||
|
||||
|
@ -285,7 +286,8 @@ public class EventWebSocketTest {
|
|||
verify(remoteEndpoint, times(0)).sendString(any());
|
||||
|
||||
// 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);
|
||||
verify(remoteEndpoint).sendString(gson.toJson(new EventDTO(event)));
|
||||
|
||||
|
@ -309,7 +311,8 @@ public class EventWebSocketTest {
|
|||
clearInvocations(remoteEndpoint);
|
||||
|
||||
// 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);
|
||||
verify(remoteEndpoint).sendString(gson.toJson(new EventDTO(event)));
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
package org.openhab.core.model.rule.jvmmodel
|
||||
|
||||
import com.google.inject.Inject
|
||||
import java.time.ZonedDateTime
|
||||
import java.util.Set
|
||||
import org.openhab.core.items.Item
|
||||
import org.openhab.core.items.ItemRegistry
|
||||
|
@ -145,10 +146,22 @@ class RulesJvmModelInferrer extends ScriptJvmModelInferrer {
|
|||
val commandTypeRef = typeRef(Command)
|
||||
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)) {
|
||||
val stateTypeRef = typeRef(State)
|
||||
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)) {
|
||||
val eventTypeRef = typeRef(String)
|
||||
parameters += rule.toParameter(VAR_RECEIVED_EVENT, eventTypeRef)
|
||||
|
@ -163,10 +176,6 @@ class RulesJvmModelInferrer extends ScriptJvmModelInferrer {
|
|||
val newStatusRef = typeRef(String)
|
||||
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
|
||||
]
|
||||
|
|
|
@ -61,11 +61,16 @@ public class DSLScriptEngine implements javax.script.ScriptEngine {
|
|||
|
||||
public static final String MIMETYPE_OPENHAB_DSL_RULE = "application/vnd.openhab.dsl.rule";
|
||||
|
||||
private static final Map<String, String> IMPLICIT_VARS = Map.of("command",
|
||||
ScriptJvmModelInferrer.VAR_RECEIVED_COMMAND, "state", ScriptJvmModelInferrer.VAR_NEW_STATE, "newState",
|
||||
ScriptJvmModelInferrer.VAR_NEW_STATE, "oldState", ScriptJvmModelInferrer.VAR_PREVIOUS_STATE,
|
||||
"triggeringItem", ScriptJvmModelInferrer.VAR_TRIGGERING_ITEM, "triggeringGroup",
|
||||
ScriptJvmModelInferrer.VAR_TRIGGERING_GROUP, "input", ScriptJvmModelInferrer.VAR_INPUT);
|
||||
private static final Map<String, String> IMPLICIT_VARS = Map.of( //
|
||||
"command", ScriptJvmModelInferrer.VAR_RECEIVED_COMMAND, //
|
||||
"state", ScriptJvmModelInferrer.VAR_NEW_STATE, //
|
||||
"newState", ScriptJvmModelInferrer.VAR_NEW_STATE, //
|
||||
"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);
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
package org.openhab.core.model.script.jvmmodel
|
||||
|
||||
import com.google.inject.Inject
|
||||
import java.time.ZonedDateTime
|
||||
import java.util.Set
|
||||
import org.openhab.core.items.ItemRegistry
|
||||
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 */
|
||||
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 */
|
||||
public static final String VAR_RECEIVED_COMMAND = "receivedCommand";
|
||||
|
||||
|
@ -160,6 +167,10 @@ class ScriptJvmModelInferrer extends AbstractModelInferrer {
|
|||
parameters += script.toParameter(VAR_NEW_STATUS, newThingStatusRef)
|
||||
val stateTypeRef2 = typeRef(State)
|
||||
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)
|
||||
parameters += script.toParameter(VAR_PRIVATE_CACHE, privateCacheTypeRef)
|
||||
val sharedCacheTypeRef = typeRef(ValueCache)
|
||||
|
|
|
@ -12,12 +12,20 @@
|
|||
*/
|
||||
package org.openhab.core.events;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
|
||||
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
|
||||
|
@ -31,7 +39,8 @@ public abstract class AbstractEventFactory implements EventFactory {
|
|||
|
||||
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.
|
||||
|
@ -120,4 +129,25 @@ public abstract class AbstractEventFactory implements EventFactory {
|
|||
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,
|
||||
@Nullable ZonedDateTime lastStateChange) {
|
||||
State oldState = this.state;
|
||||
ZonedDateTime oldStateUpdate = this.lastStateUpdate;
|
||||
this.state = state;
|
||||
this.lastState = lastState != null ? lastState : this.lastState;
|
||||
this.lastStateUpdate = lastStateUpdate != null ? lastStateUpdate : this.lastStateUpdate;
|
||||
this.lastStateChange = lastStateChange != null ? lastStateChange : this.lastStateChange;
|
||||
notifyListeners(oldState, state);
|
||||
sendStateUpdatedEvent(state);
|
||||
sendStateUpdatedEvent(state, lastStateUpdate);
|
||||
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
|
||||
}
|
||||
notifyListeners(oldState, state);
|
||||
sendStateUpdatedEvent(state);
|
||||
sendStateUpdatedEvent(state, lastStateUpdate);
|
||||
if (stateChanged) {
|
||||
sendStateChangedEvent(state, oldState);
|
||||
sendStateChangedEvent(state, oldState, lastStateUpdate, lastStateChange);
|
||||
lastStateChange = now; // update after we've notified listeners
|
||||
}
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
@ -365,19 +366,22 @@ public class GroupItem extends GenericItem implements StateChangeListener, Metad
|
|||
State oldState = this.state;
|
||||
State newState = oldState;
|
||||
ItemStateConverter itemStateConverter = this.itemStateConverter;
|
||||
ZonedDateTime lastStateUpdate = this.lastStateUpdate;
|
||||
ZonedDateTime lastStateChange = this.lastStateChange;
|
||||
if (function instanceof GroupFunction groupFunction && baseItem != null && itemStateConverter != null) {
|
||||
State calculatedState = groupFunction.calculate(getStateMembers(getMembers()));
|
||||
newState = itemStateConverter.convertToAcceptedState(calculatedState, baseItem);
|
||||
setState(newState);
|
||||
sendGroupStateUpdatedEvent(item.getName(), newState);
|
||||
sendGroupStateUpdatedEvent(item.getName(), newState, lastStateUpdate);
|
||||
}
|
||||
if (!oldState.equals(newState)) {
|
||||
sendGroupStateChangedEvent(item.getName(), newState, oldState);
|
||||
sendGroupStateChangedEvent(item.getName(), newState, oldState, lastStateUpdate, lastStateChange);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setState(State state) {
|
||||
ZonedDateTime now = ZonedDateTime.now();
|
||||
State oldState = this.state;
|
||||
Item baseItem = this.baseItem;
|
||||
if (baseItem instanceof GenericItem item) {
|
||||
|
@ -387,6 +391,10 @@ public class GroupItem extends GenericItem implements StateChangeListener, Metad
|
|||
this.state = state;
|
||||
}
|
||||
notifyListeners(oldState, state);
|
||||
if (!oldState.equals(state)) {
|
||||
lastStateChange = now;
|
||||
}
|
||||
lastStateUpdate = now;
|
||||
}
|
||||
|
||||
@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;
|
||||
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;
|
||||
if (eventPublisher1 != null) {
|
||||
eventPublisher1
|
||||
.post(ItemEventFactory.createGroupStateChangedEvent(getName(), memberName, newState, oldState));
|
||||
eventPublisher1.post(ItemEventFactory.createGroupStateChangedEvent(getName(), memberName, newState,
|
||||
oldState, lastStateUpdate, lastStateChange));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,10 @@
|
|||
*/
|
||||
package org.openhab.core.items.events;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.types.State;
|
||||
|
||||
/**
|
||||
|
@ -34,8 +37,9 @@ public class GroupItemStateChangedEvent extends ItemStateChangedEvent {
|
|||
private final String memberName;
|
||||
|
||||
protected GroupItemStateChangedEvent(String topic, String payload, String itemName, String memberName,
|
||||
State newItemState, State oldItemState) {
|
||||
super(topic, payload, itemName, newItemState, oldItemState);
|
||||
State newItemState, State oldItemState, @Nullable ZonedDateTime lastStateUpdate,
|
||||
@Nullable ZonedDateTime lastStateChange) {
|
||||
super(topic, payload, itemName, newItemState, oldItemState, lastStateUpdate, lastStateChange);
|
||||
this.memberName = memberName;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
*/
|
||||
package org.openhab.core.items.events;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.types.State;
|
||||
|
@ -34,8 +36,8 @@ public class GroupStateUpdatedEvent extends ItemStateUpdatedEvent {
|
|||
private final String memberName;
|
||||
|
||||
protected GroupStateUpdatedEvent(String topic, String payload, String itemName, String memberName,
|
||||
State newItemState, @Nullable String source) {
|
||||
super(topic, payload, itemName, newItemState, source);
|
||||
State newItemState, @Nullable ZonedDateTime lastStateUpdate, @Nullable String source) {
|
||||
super(topic, payload, itemName, newItemState, lastStateUpdate, source);
|
||||
this.memberName = memberName;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ package org.openhab.core.items.events;
|
|||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.time.Instant;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
@ -114,9 +115,10 @@ public class ItemEventFactory extends AbstractEventFactory {
|
|||
private Event createGroupStateUpdatedEvent(String topic, String payload) {
|
||||
String itemName = getItemName(topic);
|
||||
String memberName = getMemberName(topic);
|
||||
ItemEventPayloadBean bean = deserializePayload(payload, ItemEventPayloadBean.class);
|
||||
ItemStateUpdatedEventPayloadBean bean = deserializePayload(payload, ItemStateUpdatedEventPayloadBean.class);
|
||||
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) {
|
||||
|
@ -125,7 +127,10 @@ public class ItemEventFactory extends AbstractEventFactory {
|
|||
ItemStateChangedEventPayloadBean bean = deserializePayload(payload, ItemStateChangedEventPayloadBean.class);
|
||||
State state = getState(bean.getType(), bean.getValue());
|
||||
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) {
|
||||
|
@ -151,9 +156,10 @@ public class ItemEventFactory extends AbstractEventFactory {
|
|||
|
||||
private Event createStateUpdatedEvent(String topic, String payload) {
|
||||
String itemName = getItemName(topic);
|
||||
ItemEventPayloadBean bean = deserializePayload(payload, ItemEventPayloadBean.class);
|
||||
ItemStateUpdatedEventPayloadBean bean = deserializePayload(payload, ItemStateUpdatedEventPayloadBean.class);
|
||||
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) {
|
||||
|
@ -161,7 +167,9 @@ public class ItemEventFactory extends AbstractEventFactory {
|
|||
ItemStateChangedEventPayloadBean bean = deserializePayload(payload, ItemStateChangedEventPayloadBean.class);
|
||||
State state = getState(bean.getType(), bean.getValue());
|
||||
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) {
|
||||
|
@ -319,11 +327,13 @@ public class ItemEventFactory extends AbstractEventFactory {
|
|||
*
|
||||
* @param itemName the name of the item to report the state update for
|
||||
* @param state the new state
|
||||
* @param lastStateUpdate the time of the last state update
|
||||
* @return the created item state update event
|
||||
* @throws IllegalArgumentException if itemName or state is null
|
||||
*/
|
||||
public static ItemStateUpdatedEvent createStateUpdatedEvent(String itemName, State state) {
|
||||
return createStateUpdatedEvent(itemName, state, null);
|
||||
public static ItemStateUpdatedEvent createStateUpdatedEvent(String itemName, State state,
|
||||
@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 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)
|
||||
* @return the created item state update event
|
||||
* @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");
|
||||
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);
|
||||
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,
|
||||
|
@ -365,17 +378,19 @@ public class ItemEventFactory extends AbstractEventFactory {
|
|||
* @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 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)
|
||||
* @return the created group item state update event
|
||||
* @throws IllegalArgumentException if groupName or state is null
|
||||
*/
|
||||
public static GroupStateUpdatedEvent createGroupStateUpdatedEvent(String groupName, String member, State state,
|
||||
@Nullable String source) {
|
||||
@Nullable ZonedDateTime lastStateUpdate, @Nullable String source) {
|
||||
assertValidArguments(groupName, member, state, "state");
|
||||
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);
|
||||
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 newState the new state to send
|
||||
* @param oldState the old state of the item
|
||||
* @param lastStateChange the time of the last state change
|
||||
* @return the created item state changed event
|
||||
* @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");
|
||||
String topic = buildTopic(ITEM_STATE_CHANGED_EVENT_TOPIC, itemName);
|
||||
ItemStateChangedEventPayloadBean bean = new ItemStateChangedEventPayloadBean(getStateType(newState),
|
||||
newState.toFullString(), getStateType(oldState), oldState.toFullString());
|
||||
newState.toFullString(), getStateType(oldState), oldState.toFullString(), lastStateUpdate,
|
||||
lastStateChange);
|
||||
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 newState the new state to send
|
||||
* @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
|
||||
* @throws IllegalArgumentException if itemName or state is null
|
||||
*/
|
||||
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");
|
||||
String topic = buildGroupTopic(GROUPITEM_STATE_CHANGED_EVENT_TOPIC, itemName, memberName);
|
||||
ItemStateChangedEventPayloadBean bean = new ItemStateChangedEventPayloadBean(getStateType(newState),
|
||||
newState.toFullString(), getStateType(oldState), oldState.toFullString());
|
||||
newState.toFullString(), getStateType(oldState), oldState.toFullString(), lastStateUpdate,
|
||||
lastStateChange);
|
||||
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.
|
||||
*/
|
||||
|
@ -593,6 +651,8 @@ public class ItemEventFactory extends AbstractEventFactory {
|
|||
private @NonNullByDefault({}) String value;
|
||||
private @NonNullByDefault({}) String oldType;
|
||||
private @NonNullByDefault({}) String oldValue;
|
||||
private @Nullable ZonedDateTime lastStateUpdate;
|
||||
private @Nullable ZonedDateTime lastStateChange;
|
||||
|
||||
/**
|
||||
* Default constructor for deserialization e.g. by Gson.
|
||||
|
@ -601,11 +661,14 @@ public class ItemEventFactory extends AbstractEventFactory {
|
|||
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.value = value;
|
||||
this.oldType = oldType;
|
||||
this.oldValue = oldValue;
|
||||
this.lastStateUpdate = lastStateUpdate;
|
||||
this.lastStateChange = lastStateChange;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
|
@ -623,6 +686,14 @@ public class ItemEventFactory extends AbstractEventFactory {
|
|||
public String getOldValue() {
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
public @Nullable ZonedDateTime getLastStateUpdate() {
|
||||
return lastStateUpdate;
|
||||
}
|
||||
|
||||
public @Nullable ZonedDateTime getLastStateChange() {
|
||||
return lastStateChange;
|
||||
}
|
||||
}
|
||||
|
||||
private static class ItemTimeSeriesEventPayloadBean {
|
||||
|
|
|
@ -12,7 +12,10 @@
|
|||
*/
|
||||
package org.openhab.core.items.events;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.types.State;
|
||||
|
||||
/**
|
||||
|
@ -34,6 +37,10 @@ public class ItemStateChangedEvent extends ItemEvent {
|
|||
|
||||
protected final State oldItemState;
|
||||
|
||||
protected final @Nullable ZonedDateTime lastStateUpdate;
|
||||
|
||||
protected final @Nullable ZonedDateTime lastStateChange;
|
||||
|
||||
/**
|
||||
* Constructs a new item state changed event.
|
||||
*
|
||||
|
@ -42,12 +49,16 @@ public class ItemStateChangedEvent extends ItemEvent {
|
|||
* @param itemName the item name
|
||||
* @param newItemState the new 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,
|
||||
State oldItemState) {
|
||||
State oldItemState, @Nullable ZonedDateTime lastStateUpdate, @Nullable ZonedDateTime lastStateChange) {
|
||||
super(topic, payload, itemName, null);
|
||||
this.itemState = newItemState;
|
||||
this.oldItemState = oldItemState;
|
||||
this.lastStateUpdate = lastStateUpdate;
|
||||
this.lastStateChange = lastStateChange;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -73,6 +84,24 @@ public class ItemStateChangedEvent extends ItemEvent {
|
|||
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
|
||||
public String toString() {
|
||||
return String.format("Item '%s' changed from %s to %s", itemName, oldItemState, itemState);
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
*/
|
||||
package org.openhab.core.items.events;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.eclipse.jdt.annotation.Nullable;
|
||||
import org.openhab.core.types.State;
|
||||
|
@ -31,6 +33,7 @@ public class ItemStateUpdatedEvent extends ItemEvent {
|
|||
public static final String TYPE = ItemStateUpdatedEvent.class.getSimpleName();
|
||||
|
||||
protected final State itemState;
|
||||
protected final @Nullable ZonedDateTime lastStateUpdate;
|
||||
|
||||
/**
|
||||
* Constructs a new item state event.
|
||||
|
@ -39,12 +42,14 @@ public class ItemStateUpdatedEvent extends ItemEvent {
|
|||
* @param payload the payload
|
||||
* @param itemName the item name
|
||||
* @param itemState the item state
|
||||
* @param lastStateUpdate the last state update
|
||||
* @param source the source, can be null
|
||||
*/
|
||||
protected ItemStateUpdatedEvent(String topic, String payload, String itemName, State itemState,
|
||||
@Nullable String source) {
|
||||
@Nullable ZonedDateTime lastStateUpdate, @Nullable String source) {
|
||||
super(topic, payload, itemName, source);
|
||||
this.itemState = itemState;
|
||||
this.lastStateUpdate = lastStateUpdate;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -61,6 +66,15 @@ public class ItemStateUpdatedEvent extends ItemEvent {
|
|||
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
|
||||
public String toString() {
|
||||
return String.format("Item '%s' updated to %s", itemName, itemState);
|
||||
|
|
|
@ -142,7 +142,7 @@ class ExpireManagerTest {
|
|||
Event event = ItemEventFactory.createCommandEvent(ITEMNAME, new DecimalType(1));
|
||||
expireManager.receive(event);
|
||||
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);
|
||||
Thread.sleep(1500L);
|
||||
verify(eventPublisherMock, never()).post(any());
|
||||
|
@ -194,7 +194,7 @@ class ExpireManagerTest {
|
|||
Event event = ItemEventFactory.createStateEvent(ITEMNAME, new DecimalType(1));
|
||||
expireManager.receive(event);
|
||||
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);
|
||||
Thread.sleep(1500L);
|
||||
verify(eventPublisherMock, never()).post(any());
|
||||
|
|
|
@ -56,6 +56,8 @@ public class GenericItemTest {
|
|||
|
||||
@Test
|
||||
public void testItemPostsEventsCorrectly() {
|
||||
ZonedDateTime lastStateUpdate;
|
||||
ZonedDateTime lastStateChange;
|
||||
EventPublisher publisher = mock(EventPublisher.class);
|
||||
|
||||
TestItem item = new TestItem("member1");
|
||||
|
@ -78,6 +80,7 @@ public class GenericItemTest {
|
|||
assertEquals(item.getName(), updated.getItemName());
|
||||
assertEquals("openhab/items/member1/stateupdated", updated.getTopic());
|
||||
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());
|
||||
|
||||
// second event should be changed event
|
||||
|
@ -87,12 +90,16 @@ public class GenericItemTest {
|
|||
assertEquals("openhab/items/member1/statechanged", change.getTopic());
|
||||
assertEquals(oldState, change.getOldItemState());
|
||||
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());
|
||||
|
||||
// reset invocations and captor
|
||||
clearInvocations(publisher);
|
||||
captor = ArgumentCaptor.forClass(ItemEvent.class);
|
||||
|
||||
lastStateChange = item.getLastStateChange();
|
||||
lastStateUpdate = item.getLastStateUpdate();
|
||||
|
||||
// State doesn't change -> only update event is fired
|
||||
item.setState(item.getState());
|
||||
verify(publisher).post(captor.capture());
|
||||
|
@ -106,7 +113,25 @@ public class GenericItemTest {
|
|||
assertEquals(item.getName(), updated.getItemName());
|
||||
assertEquals("openhab/items/member1/stateupdated", updated.getTopic());
|
||||
assertEquals(item.getState(), updated.getItemState());
|
||||
assertEquals(lastStateUpdate, updated.getLastStateUpdate());
|
||||
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
|
||||
|
|
|
@ -16,6 +16,8 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
|||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
import org.eclipse.jdt.annotation.NonNullByDefault;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.openhab.core.events.Event;
|
||||
|
@ -225,8 +227,10 @@ public class ItemEventFactoryTest {
|
|||
|
||||
@Test
|
||||
public void testCreateGroupStateChangedEventRawType() throws Exception {
|
||||
ZonedDateTime lastStateUpdate = ZonedDateTime.now();
|
||||
ZonedDateTime lastStateChange = ZonedDateTime.now().minusMinutes(1);
|
||||
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(),
|
||||
giEventSource.getPayload(), giEventSource.getSource());
|
||||
|
@ -242,5 +246,7 @@ public class ItemEventFactoryTest {
|
|||
assertNull(groupItemStateChangedEvent.getSource());
|
||||
assertEquals(NEW_RAW_ITEM_STATE, groupItemStateChangedEvent.getItemState());
|
||||
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("Send and wait for item state is ON");
|
||||
eventPublisher.post(ItemEventFactory.createStateUpdatedEvent(testItemName1, OnOffType.ON));
|
||||
eventPublisher.post(ItemEventFactory.createStateUpdatedEvent(testItemName1, OnOffType.ON, null));
|
||||
|
||||
waitForAssert(() -> {
|
||||
assertThat(itemEvent, is(notNullValue()));
|
||||
|
@ -207,7 +207,7 @@ public abstract class BasicConditionHandlerTest extends JavaOSGiTest {
|
|||
|
||||
// prepare the execution
|
||||
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
|
||||
assertThat(itemEvent, is(nullValue()));
|
||||
}
|
||||
|
|
|
@ -168,7 +168,7 @@ public class IntervalConditionHandlerTest extends BasicConditionHandlerTest {
|
|||
logger.info("Rule is enabled and idle");
|
||||
|
||||
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
|
||||
waitForAssert(() -> {
|
||||
|
@ -182,7 +182,7 @@ public class IntervalConditionHandlerTest extends BasicConditionHandlerTest {
|
|||
|
||||
// Send a second event to check if the condition is still satisfied
|
||||
itemEvent = null; // reset it
|
||||
eventPublisher.post(ItemEventFactory.createStateUpdatedEvent(testItemName1, OnOffType.ON));
|
||||
eventPublisher.post(ItemEventFactory.createStateUpdatedEvent(testItemName1, OnOffType.ON, null));
|
||||
|
||||
waitForAssert(() -> {
|
||||
assertThat(itemEvent, is(notNullValue()));
|
||||
|
@ -198,7 +198,7 @@ public class IntervalConditionHandlerTest extends BasicConditionHandlerTest {
|
|||
|
||||
// prepare the execution
|
||||
itemEvent = null;
|
||||
eventPublisher.post(ItemEventFactory.createStateUpdatedEvent(testItemName1, OnOffType.ON));
|
||||
eventPublisher.post(ItemEventFactory.createStateUpdatedEvent(testItemName1, OnOffType.ON, null));
|
||||
|
||||
// the first event is always allowed
|
||||
waitForAssert(() -> {
|
||||
|
@ -209,7 +209,7 @@ public class IntervalConditionHandlerTest extends BasicConditionHandlerTest {
|
|||
|
||||
// the second event is not allowed
|
||||
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
|
||||
assertThat(itemEvent, is(nullValue()));
|
||||
}
|
||||
|
|
|
@ -360,7 +360,7 @@ public class CommunicationManagerOSGiTest extends JavaOSGiTest {
|
|||
|
||||
@Test
|
||||
public void testItemStateEventSingleLink() {
|
||||
manager.receive(ItemEventFactory.createStateUpdatedEvent(ITEM_NAME_2, OnOffType.ON));
|
||||
manager.receive(ItemEventFactory.createStateUpdatedEvent(ITEM_NAME_2, OnOffType.ON, null));
|
||||
waitForAssert(() -> {
|
||||
verify(stateProfileMock).onStateUpdateFromItem(eq(OnOffType.ON));
|
||||
verify(triggerProfileMock).onStateUpdateFromItem(eq(OnOffType.ON));
|
||||
|
@ -371,7 +371,7 @@ public class CommunicationManagerOSGiTest extends JavaOSGiTest {
|
|||
|
||||
@Test
|
||||
public void testItemStateEventMultiLink() {
|
||||
manager.receive(ItemEventFactory.createStateUpdatedEvent(ITEM_NAME_1, OnOffType.ON));
|
||||
manager.receive(ItemEventFactory.createStateUpdatedEvent(ITEM_NAME_1, OnOffType.ON, null));
|
||||
waitForAssert(() -> {
|
||||
verify(stateProfileMock, times(2)).onStateUpdateFromItem(eq(OnOffType.ON));
|
||||
verify(triggerProfileMock, times(2)).onStateUpdateFromItem(eq(OnOffType.ON));
|
||||
|
@ -382,8 +382,8 @@ public class CommunicationManagerOSGiTest extends JavaOSGiTest {
|
|||
|
||||
@Test
|
||||
public void testItemStateEventNotToSource() {
|
||||
manager.receive(
|
||||
ItemEventFactory.createStateUpdatedEvent(ITEM_NAME_1, OnOffType.ON, STATE_CHANNEL_UID_2.getAsString()));
|
||||
manager.receive(ItemEventFactory.createStateUpdatedEvent(ITEM_NAME_1, OnOffType.ON, null,
|
||||
STATE_CHANNEL_UID_2.getAsString()));
|
||||
waitForAssert(() -> {
|
||||
verify(stateProfileMock).onStateUpdateFromItem(eq(OnOffType.ON));
|
||||
verify(triggerProfileMock, times(2)).onStateUpdateFromItem(eq(OnOffType.ON));
|
||||
|
|
Loading…
Reference in New Issue