Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@
@NonNullByDefault
public class PersistenceManagerImpl implements ItemRegistryChangeListener, StateChangeListener, ReadyTracker,
PersistenceServiceConfigurationRegistryChangeListener, TimeSeriesListener, PersistenceManager {
private static final String PERSISTENCE_SOURCE = "org.openhab.core.persistence";

private final Logger logger = LoggerFactory.getLogger(PersistenceManagerImpl.class);

private final ReadyMarker marker = new ReadyMarker("persistence", "restore");
Expand Down Expand Up @@ -613,7 +615,7 @@ private void restoreItemStateIfPossible(Item item) {
}
}
genericItem.removeStateChangeListener(PersistenceManagerImpl.this);
genericItem.setState(state, lastState, lastStateUpdate, lastStateChange);
genericItem.setState(state, lastState, lastStateUpdate, lastStateChange, PERSISTENCE_SOURCE);
genericItem.addStateChangeListener(PersistenceManagerImpl.this);
if (logger.isDebugEnabled()) {
logger.debug("Restored item state from '{}' for item '{}' -> '{}'",
Expand Down Expand Up @@ -658,7 +660,7 @@ public void scheduleNextPersistedForecastForItem(String itemName) {
private void restoreItemState(String itemName, State state) {
Item item = itemRegistry.get(itemName);
if (item != null) {
((GenericItem) item).setState(state);
((GenericItem) item).setState(state, PERSISTENCE_SOURCE);
}
scheduleNextPersistedForecastForItem(itemName);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ protected void receiveUpdate(ItemStateEvent updateEvent) {
}
}
if (isAccepted) {
item.setState(newState);
item.setState(newState, updateEvent.getSource());
} else {
logger.debug("Received update of a not accepted type ({}) for item {}",
newState.getClass().getSimpleName(), itemName);
Expand All @@ -91,7 +91,7 @@ protected void receiveCommand(ItemCommandEvent commandEvent) {
try {
Item item = itemRegistry.getItem(commandEvent.getItemName());
if (item instanceof GroupItem groupItem) {
groupItem.send(commandEvent.getItemCommand());
groupItem.send(commandEvent.getItemCommand(), commandEvent.getSource());
}
} catch (ItemNotFoundException e) {
logger.debug("Received command for non-existing item: {}", e.getMessage());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,20 @@ protected void internalSend(Command command, @Nullable String source) {
}
}

/**
* Set a new state.
*
* Subclasses may override this method in order to do necessary conversions upfront. Afterwards,
* {@link #applyState(State)} should be called by classes overriding this method.
*
* @param state new state of this item
* @param source the source of the state update. See
* https://www.openhab.org/docs/developer/utils/events.html#the-core-events
*/
public void setState(State state, @Nullable String source) {
applyState(state, source);
}

/**
* Set a new state.
*
Expand All @@ -226,8 +240,8 @@ protected void internalSend(Command command, @Nullable String source) {
*
* @param state new state of this item
*/
public void setState(State state) {
applyState(state);
public final void setState(State state) {
setState(state, null);
}

/**
Expand All @@ -240,16 +254,16 @@ public void setState(State state) {
* @param lastStateChange last state change of this item
*/
public void setState(State state, @Nullable State lastState, @Nullable ZonedDateTime lastStateUpdate,
@Nullable ZonedDateTime lastStateChange) {
@Nullable ZonedDateTime lastStateChange, @Nullable String source) {
State oldState = this.state;
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, lastStateUpdate);
sendStateUpdatedEvent(state, lastStateUpdate, source);
if (!oldState.equals(state)) {
sendStateChangedEvent(state, oldState, lastStateUpdate, lastStateChange);
sendStateChangedEvent(state, oldState, lastStateUpdate, lastStateChange, source);
}
}

Expand All @@ -261,7 +275,7 @@ public void setState(State state, @Nullable State lastState, @Nullable ZonedDate
*
* @param state new state of this item
*/
protected final void applyState(State state) {
protected final void applyState(State state, @Nullable String source) {
ZonedDateTime now = ZonedDateTime.now();
State oldState = this.state;
boolean stateChanged = !oldState.equals(state);
Expand All @@ -270,9 +284,9 @@ protected final void applyState(State state) {
lastState = oldState; // update before we notify listeners
}
notifyListeners(oldState, state);
sendStateUpdatedEvent(state, lastStateUpdate);
sendStateUpdatedEvent(state, lastStateUpdate, source);
if (stateChanged) {
sendStateChangedEvent(state, oldState, lastStateUpdate, lastStateChange);
sendStateChangedEvent(state, oldState, lastStateUpdate, lastStateChange, source);
lastStateChange = now; // update after we've notified listeners
}
lastStateUpdate = now;
Expand Down Expand Up @@ -322,19 +336,21 @@ protected final void applyTimeSeries(TimeSeries timeSeries) {
}
}

private void sendStateUpdatedEvent(State newState, @Nullable ZonedDateTime lastStateUpdate) {
private void sendStateUpdatedEvent(State newState, @Nullable ZonedDateTime lastStateUpdate,
@Nullable String source) {
EventPublisher eventPublisher1 = this.eventPublisher;
if (eventPublisher1 != null) {
eventPublisher1.post(ItemEventFactory.createStateUpdatedEvent(this.name, newState, lastStateUpdate, null));
eventPublisher1
.post(ItemEventFactory.createStateUpdatedEvent(this.name, newState, lastStateUpdate, source));
}
}

private void sendStateChangedEvent(State newState, State oldState, @Nullable ZonedDateTime lastStateUpdate,
@Nullable ZonedDateTime lastStateChange) {
@Nullable ZonedDateTime lastStateChange, @Nullable String source) {
EventPublisher eventPublisher1 = this.eventPublisher;
if (eventPublisher1 != null) {
eventPublisher1.post(ItemEventFactory.createStateChangedEvent(this.name, newState, oldState,
lastStateUpdate, lastStateChange));
lastStateUpdate, lastStateChange, source));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -397,12 +397,12 @@ public void stateUpdated(Item item, State state) {
}

@Override
public void setState(State state) {
public void setState(State state, @Nullable String source) {
ZonedDateTime now = ZonedDateTime.now();
State oldState = this.state;
Item baseItem = this.baseItem;
if (baseItem instanceof GenericItem item) {
item.setState(state);
item.setState(state, source);
this.state = baseItem.getState();
} else {
this.state = state;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public class GroupItemStateChangedEvent extends ItemStateChangedEvent {
protected GroupItemStateChangedEvent(String topic, String payload, String itemName, String memberName,
State newItemState, State oldItemState, @Nullable ZonedDateTime lastStateUpdate,
@Nullable ZonedDateTime lastStateChange) {
super(topic, payload, itemName, newItemState, oldItemState, lastStateUpdate, lastStateChange);
super(topic, payload, itemName, newItemState, oldItemState, lastStateUpdate, lastStateChange, null);
this.memberName = memberName;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ protected Event createEventByType(String eventType, String topic, String payload
} else if (ItemStateUpdatedEvent.TYPE.equals(eventType)) {
return createStateUpdatedEvent(topic, payload);
} else if (ItemStateChangedEvent.TYPE.equals(eventType)) {
return createStateChangedEvent(topic, payload);
return createStateChangedEvent(topic, payload, source);
} else if (ItemTimeSeriesEvent.TYPE.equals(eventType)) {
return createTimeSeriesEvent(topic, payload);
} else if (ItemTimeSeriesUpdatedEvent.TYPE.equals(eventType)) {
Expand Down Expand Up @@ -162,14 +162,15 @@ private Event createStateUpdatedEvent(String topic, String payload) {
return new ItemStateUpdatedEvent(topic, payload, itemName, state, lastStateUpdate, null);
}

private Event createStateChangedEvent(String topic, String payload) {
private Event createStateChangedEvent(String topic, String payload, @Nullable String source) {
String itemName = getItemName(topic);
ItemStateChangedEventPayloadBean bean = deserializePayload(payload, ItemStateChangedEventPayloadBean.class);
State state = getState(bean.getType(), bean.getValue());
State oldState = getState(bean.getOldType(), bean.getOldValue());
ZonedDateTime lastStateUpdate = bean.getLastStateUpdate();
ZonedDateTime lastStateChange = bean.getLastStateChange();
return new ItemStateChangedEvent(topic, payload, itemName, state, oldState, lastStateUpdate, lastStateChange);
return new ItemStateChangedEvent(topic, payload, itemName, state, oldState, lastStateUpdate, lastStateChange,
source);
}

private Event createTimeSeriesEvent(String topic, String payload) {
Expand Down Expand Up @@ -419,19 +420,35 @@ public static ItemStatePredictedEvent createStatePredictedEvent(String itemName,
* @param newState the new state to send
* @param oldState the old state of the item
* @param lastStateChange the time of the last state change
* @param source the name of the source identifying the sender (can be null)
* @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,
@Nullable ZonedDateTime lastStateUpdate, @Nullable ZonedDateTime lastStateChange) {
@Nullable ZonedDateTime lastStateUpdate, @Nullable ZonedDateTime lastStateChange, @Nullable String source) {
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(), lastStateUpdate,
lastStateChange);
String payload = serializePayload(bean);
return new ItemStateChangedEvent(topic, payload, itemName, newState, oldState, lastStateUpdate,
lastStateChange);
return new ItemStateChangedEvent(topic, payload, itemName, newState, oldState, lastStateUpdate, lastStateChange,
source);
}

/**
* Creates an item state changed event.
*
* @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,
@Nullable ZonedDateTime lastStateUpdate, @Nullable ZonedDateTime lastStateChange) {
return createStateChangedEvent(itemName, newState, oldState, lastStateUpdate, lastStateChange, null);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@ public class ItemStateChangedEvent extends ItemEvent {
* @param lastStateChange the last state change
*/
protected ItemStateChangedEvent(String topic, String payload, String itemName, State newItemState,
State oldItemState, @Nullable ZonedDateTime lastStateUpdate, @Nullable ZonedDateTime lastStateChange) {
super(topic, payload, itemName, null);
State oldItemState, @Nullable ZonedDateTime lastStateUpdate, @Nullable ZonedDateTime lastStateChange,
@Nullable String source) {
super(topic, payload, itemName, source);
this.itemState = newItemState;
this.oldItemState = oldItemState;
this.lastStateUpdate = lastStateUpdate;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ public List<Class<? extends Command>> getAcceptedCommandTypes() {
}

@Override
public void setState(State state) {
public void setState(State state, @Nullable String source) {
if (isAcceptedState(ACCEPTED_DATA_TYPES, state)) {
applyState(state);
applyState(state, source);
} else {
logSetTypeError(state);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public List<Class<? extends Command>> getAcceptedCommandTypes() {
}

@Override
public void setState(State state) {
public void setState(State state, @Nullable String source) {
if (isAcceptedState(ACCEPTED_DATA_TYPES, state)) {
State currentState = this.state;

Expand All @@ -86,24 +86,26 @@ public void setState(State state) {
PercentType saturation = hsbType.getSaturation();
// we map ON/OFF values to dark/bright, so that the hue and saturation values are not changed
if (state == OnOffType.OFF) {
applyState(new HSBType(hue, saturation, PercentType.ZERO));
applyState(new HSBType(hue, saturation, PercentType.ZERO), source);
} else if (state == OnOffType.ON) {
applyState(new HSBType(hue, saturation, PercentType.HUNDRED));
applyState(new HSBType(hue, saturation, PercentType.HUNDRED), source);
} else if (state instanceof PercentType percentType && !(state instanceof HSBType)) {
applyState(new HSBType(hue, saturation, percentType));
applyState(new HSBType(hue, saturation, percentType), source);
} else if (state instanceof DecimalType decimalType && !(state instanceof HSBType)) {
applyState(new HSBType(hue, saturation,
new PercentType(decimalType.toBigDecimal().multiply(BigDecimal.valueOf(100)))));
applyState(
new HSBType(hue, saturation,
new PercentType(decimalType.toBigDecimal().multiply(BigDecimal.valueOf(100)))),
source);
} else {
applyState(state);
applyState(state, source);
}
} else {
// try conversion
State convertedState = state.as(HSBType.class);
if (convertedState != null) {
applyState(convertedState);
applyState(convertedState, source);
} else {
applyState(state);
applyState(state, source);
}
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ public List<Class<? extends Command>> getAcceptedCommandTypes() {
}

@Override
public void setState(State state) {
public void setState(State state, @Nullable String source) {
if (isAcceptedState(ACCEPTED_DATA_TYPES, state)) {
applyState(state);
applyState(state, source);
} else {
logSetTypeError(state);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,14 @@ public void send(DateTimeType command, @Nullable String source) {
}

@Override
public void setState(State state) {
public void setState(State state, @Nullable String source) {
if (isAcceptedState(ACCEPTED_DATA_TYPES, state)) {
// try conversion
State convertedState = state.as(DateTimeType.class);
if (convertedState != null) {
applyState(convertedState);
applyState(convertedState, source);
} else {
applyState(state);
applyState(state, source);
}
} else {
logSetTypeError(state);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,14 @@ public List<Class<? extends Command>> getAcceptedCommandTypes() {
}

@Override
public void setState(State state) {
public void setState(State state, @Nullable String source) {
if (isAcceptedState(ACCEPTED_DATA_TYPES, state)) {
// try conversion
State convertedState = state.as(PercentType.class);
if (convertedState != null) {
applyState(convertedState);
applyState(convertedState, source);
} else {
applyState(state);
applyState(state, source);
}
} else {
logSetTypeError(state);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ public List<Class<? extends Command>> getAcceptedCommandTypes() {
}

@Override
public void setState(State state) {
public void setState(State state, @Nullable String source) {
if (isAcceptedState(ACCEPTED_DATA_TYPES, state)) {
applyState(state);
applyState(state, source);
} else {
logSetTypeError(state);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,9 @@ public DecimalType distanceFrom(@Nullable LocationItem awayItem) {
}

@Override
public void setState(State state) {
public void setState(State state, @Nullable String source) {
if (isAcceptedState(ACCEPTED_DATA_TYPES, state)) {
applyState(state);
applyState(state, source);
} else {
logSetTypeError(state);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,14 +200,14 @@ public void send(QuantityType<?> command, @Nullable String source) {
}

@Override
public void setState(State state) {
public void setState(State state, @Nullable String source) {
if (state instanceof DecimalType || state instanceof QuantityType<?>) {
State internalState = getInternalState(state);
if (internalState != null) {
applyState(internalState);
applyState(internalState, source);
}
} else if (state instanceof UnDefType) {
applyState(state);
applyState(state, source);
} else {
logSetTypeError(state);
}
Expand Down
Loading
Loading