Skip to content

Commit

Permalink
Add getLastChange, getLastUpdate, and getPreviousState to Gener…
Browse files Browse the repository at this point in the history
…icItem

Signed-off-by: Jimmy Tanagra <jcode@tanagra.id.au>
  • Loading branch information
jimtng committed Aug 17, 2024
1 parent 7659783 commit 178df65
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@
public class EnrichedGroupItemDTO extends EnrichedItemDTO {

public EnrichedGroupItemDTO(ItemDTO itemDTO, EnrichedItemDTO[] members, String link, String state,
String transformedState, StateDescription stateDescription, String unitSymbol) {
super(itemDTO, link, state, transformedState, stateDescription, null, unitSymbol);
String previousState, Long lastUpdate, Long lastChange, String transformedState,
StateDescription stateDescription, String unitSymbol) {
super(itemDTO, link, state, previousState, lastUpdate, lastChange, transformedState, stateDescription, null,
unitSymbol);
this.members = members;
this.groupType = ((GroupItemDTO) itemDTO).groupType;
this.function = ((GroupItemDTO) itemDTO).function;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,17 @@ public class EnrichedItemDTO extends ItemDTO {
public String state;
public String transformedState;
public StateDescription stateDescription;
public String unitSymbol;
public CommandDescription commandDescription;
public String previousState;
public Long lastUpdate;
public Long lastChange;
public String unitSymbol;
public Map<String, Object> metadata;
public Boolean editable;

public EnrichedItemDTO(ItemDTO itemDTO, String link, String state, String transformedState,
StateDescription stateDescription, CommandDescription commandDescription, String unitSymbol) {
public EnrichedItemDTO(ItemDTO itemDTO, String link, String state, String previousState, Long lastUpdate,
Long lastChange, String transformedState, StateDescription stateDescription,
CommandDescription commandDescription, String unitSymbol) {
this.type = itemDTO.type;
this.name = itemDTO.name;
this.label = itemDTO.label;
Expand All @@ -50,6 +54,9 @@ public EnrichedItemDTO(ItemDTO itemDTO, String link, String state, String transf
this.transformedState = transformedState;
this.stateDescription = stateDescription;
this.commandDescription = commandDescription;
this.previousState = previousState;
this.lastUpdate = lastUpdate;
this.lastChange = lastChange;
this.unitSymbol = unitSymbol;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
Expand Down Expand Up @@ -91,6 +92,12 @@ private static EnrichedItemDTO map(Item item, ItemDTO itemDTO, boolean drillDown
}
StateDescription stateDescription = considerTransformation(item.getStateDescription(locale));

String previousState = Optional.ofNullable(item.getPreviousState()).map(State::toFullString).orElse(null);
Long lastUpdate = Optional.ofNullable(item.getLastUpdate()).map(zdt -> zdt.toInstant().toEpochMilli())
.orElse(null);
Long lastChange = Optional.ofNullable(item.getLastChange()).map(zdt -> zdt.toInstant().toEpochMilli())
.orElse(null);

final String link;
if (uriBuilder != null) {
link = uriBuilder.build(itemDTO.name).toASCIIString();
Expand Down Expand Up @@ -124,11 +131,11 @@ private static EnrichedItemDTO map(Item item, ItemDTO itemDTO, boolean drillDown
} else {
memberDTOs = new EnrichedItemDTO[0];
}
enrichedItemDTO = new EnrichedGroupItemDTO(itemDTO, memberDTOs, link, state, transformedState,
stateDescription, unitSymbol);
enrichedItemDTO = new EnrichedGroupItemDTO(itemDTO, memberDTOs, link, state, previousState, lastUpdate,
lastChange, transformedState, stateDescription, unitSymbol);
} else {
enrichedItemDTO = new EnrichedItemDTO(itemDTO, link, state, transformedState, stateDescription,
item.getCommandDescription(locale), unitSymbol);
enrichedItemDTO = new EnrichedItemDTO(itemDTO, link, state, previousState, lastUpdate, lastChange,
transformedState, stateDescription, item.getCommandDescription(locale), unitSymbol);
}

return enrichedItemDTO;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/
package org.openhab.core.items;

import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
Expand Down Expand Up @@ -77,6 +78,10 @@ public abstract class GenericItem implements ActiveItem {
protected final String type;

protected State state = UnDefType.NULL;
protected @Nullable State previousState;

protected @Nullable ZonedDateTime lastUpdate;
protected @Nullable ZonedDateTime lastChange;

protected @Nullable String label;

Expand All @@ -103,6 +108,21 @@ public State getState() {
return state.as(typeClass);
}

@Override
public @Nullable State getPreviousState() {
return previousState;
}

@Override
public @Nullable ZonedDateTime getLastUpdate() {
return lastUpdate;
}

@Override
public @Nullable ZonedDateTime getLastChange() {
return lastChange;
}

@Override
public String getUID() {
return getName();
Expand Down Expand Up @@ -218,13 +238,20 @@ public void setState(State state) {
* @param state new state of this item
*/
protected final void applyState(State state) {
ZonedDateTime now = ZonedDateTime.now();
State oldState = this.state;
boolean stateChanged = !oldState.equals(state);
this.state = state;
if (stateChanged) {
previousState = oldState; // update before we notify listeners
}
notifyListeners(oldState, state);
sendStateUpdatedEvent(state);
if (!oldState.equals(state)) {
if (stateChanged) {
sendStateChangedEvent(state, oldState);
lastChange = now; // update after we've notified listeners
}
lastUpdate = now;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/
package org.openhab.core.items;

import java.time.ZonedDateTime;
import java.util.List;
import java.util.Locale;
import java.util.Set;
Expand Down Expand Up @@ -56,6 +57,30 @@ public interface Item extends Identifiable<String> {
*/
<T extends State> @Nullable T getStateAs(Class<T> typeClass);

/**
* Returns the previous state of the item.
*
* @return the previous state of the item, or null if the item has never been changed.
*/
@Nullable
State getPreviousState();

/**
* Returns the time the item was last updated.
*
* @return the time the item was last updated, or null if the item has never been updated.
*/
@Nullable
ZonedDateTime getLastUpdate();

/**
* Returns the time the item was last changed.
*
* @return the time the item was last changed, or null if the item has never been changed.
*/
@Nullable
ZonedDateTime getLastChange();

/**
* returns the name of the item
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@
package org.openhab.core.items;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.closeTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.*;

import java.time.ZonedDateTime;
import java.util.List;
import java.util.Locale;

Expand All @@ -39,6 +42,7 @@
import org.openhab.core.types.State;
import org.openhab.core.types.StateDescriptionFragmentBuilder;
import org.openhab.core.types.StateOption;
import org.openhab.core.types.UnDefType;

/**
* The GenericItemTest tests functionality of the GenericItem.
Expand Down Expand Up @@ -133,6 +137,47 @@ public void testGetStateAsWithNull() {
assertNull(item.getStateAs(toNull()));
}

@Test
public void testGetLastUpdate() {
TestItem item = new TestItem("member1");
assertNull(item.getLastUpdate());
item.setState(PercentType.HUNDRED);
assertThat(item.getLastUpdate().toInstant().toEpochMilli() * 1.0,
is(closeTo(ZonedDateTime.now().toInstant().toEpochMilli(), 5)));
}

@Test
public void testGetLastChange() throws InterruptedException {
TestItem item = new TestItem("member1");
assertNull(item.getLastChange());
item.setState(PercentType.HUNDRED);
ZonedDateTime initialChangeTime = ZonedDateTime.now();
assertThat(item.getLastChange().toInstant().toEpochMilli() * 1.0,
is(closeTo(initialChangeTime.toInstant().toEpochMilli(), 5)));

Thread.sleep(50);
item.setState(PercentType.HUNDRED);
assertThat(item.getLastChange().toInstant().toEpochMilli() * 1.0,
is(closeTo(initialChangeTime.toInstant().toEpochMilli(), 5)));

Thread.sleep(50);
ZonedDateTime secondChangeTime = ZonedDateTime.now();
item.setState(PercentType.ZERO);
assertThat(item.getLastChange().toInstant().toEpochMilli() * 1.0,
is(closeTo(secondChangeTime.toInstant().toEpochMilli(), 5)));
}

@Test
public void testGetPreviousState() {
TestItem item = new TestItem("member1");
assertEquals(UnDefType.NULL, item.getState());
assertNull(item.getPreviousState());
item.setState(PercentType.HUNDRED);
assertEquals(UnDefType.NULL, item.getPreviousState());
item.setState(PercentType.ZERO);
assertEquals(PercentType.HUNDRED, item.getPreviousState());
}

@Test
public void testDispose() {
TestItem item = new TestItem("test");
Expand Down

0 comments on commit 178df65

Please sign in to comment.