diff --git a/bundles/org.openhab.persistence.mapdb/src/main/java/org/openhab/persistence/mapdb/internal/MapDbItem.java b/bundles/org.openhab.persistence.mapdb/src/main/java/org/openhab/persistence/mapdb/internal/MapDbItem.java index 85d337f677c03..623871ca22a5e 100644 --- a/bundles/org.openhab.persistence.mapdb/src/main/java/org/openhab/persistence/mapdb/internal/MapDbItem.java +++ b/bundles/org.openhab.persistence.mapdb/src/main/java/org/openhab/persistence/mapdb/internal/MapDbItem.java @@ -13,14 +13,13 @@ package org.openhab.persistence.mapdb.internal; import java.text.DateFormat; -import java.time.Instant; import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.Date; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; -import org.openhab.core.persistence.HistoricItem; +import org.openhab.core.persistence.PersistedItem; import org.openhab.core.persistence.PersistenceItemInfo; import org.openhab.core.types.State; import org.openhab.core.types.UnDefType; @@ -29,21 +28,24 @@ * This is a Java bean used to persist item states with timestamps in the database. * * @author Jens Viebig - Initial contribution + * @author Mark Herwege - Add lastState and lastStateChange * */ @NonNullByDefault -public class MapDbItem implements HistoricItem, PersistenceItemInfo { +class MapDbItem implements PersistedItem, PersistenceItemInfo { private String name = ""; private State state = UnDefType.NULL; private Date timestamp = new Date(0); + private @Nullable State lastState = null; + private @Nullable Date lastStateChange = null; @Override public String getName() { return name; } - public void setName(String name) { + void setName(String name) { this.name = name; } @@ -52,7 +54,7 @@ public State getState() { return state; } - public void setState(State state) { + void setState(State state) { this.state = state; } @@ -61,13 +63,27 @@ public ZonedDateTime getTimestamp() { return ZonedDateTime.ofInstant(timestamp.toInstant(), ZoneId.systemDefault()); } - public void setTimestamp(Date timestamp) { + void setTimestamp(Date timestamp) { this.timestamp = timestamp; } @Override - public Instant getInstant() { - return timestamp.toInstant(); + public @Nullable State getLastState() { + return lastState; + } + + void setLastState(@Nullable State lastState) { + this.lastState = lastState; + } + + @Override + public @Nullable ZonedDateTime getLastStateChange() { + return lastStateChange != null ? ZonedDateTime.ofInstant(lastStateChange.toInstant(), ZoneId.systemDefault()) + : null; + } + + void setLastStateChange(@Nullable Date lastStateChange) { + this.lastStateChange = lastStateChange; } @Override @@ -90,7 +106,7 @@ public String toString() { return null; } - public boolean isValid() { + boolean isValid() { return name != null && state != null && timestamp != null; } } diff --git a/bundles/org.openhab.persistence.mapdb/src/main/java/org/openhab/persistence/mapdb/internal/MapDbPersistenceService.java b/bundles/org.openhab.persistence.mapdb/src/main/java/org/openhab/persistence/mapdb/internal/MapDbPersistenceService.java index 38857b1909c30..46f74d568e5b2 100644 --- a/bundles/org.openhab.persistence.mapdb/src/main/java/org/openhab/persistence/mapdb/internal/MapDbPersistenceService.java +++ b/bundles/org.openhab.persistence.mapdb/src/main/java/org/openhab/persistence/mapdb/internal/MapDbPersistenceService.java @@ -18,6 +18,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.time.Instant; +import java.time.ZonedDateTime; import java.util.Date; import java.util.List; import java.util.Locale; @@ -38,6 +39,7 @@ import org.openhab.core.library.types.DateTimeType; import org.openhab.core.persistence.FilterCriteria; import org.openhab.core.persistence.HistoricItem; +import org.openhab.core.persistence.PersistedItem; import org.openhab.core.persistence.PersistenceItemInfo; import org.openhab.core.persistence.PersistenceService; import org.openhab.core.persistence.QueryablePersistenceService; @@ -185,7 +187,11 @@ public void store(Item item, @Nullable String alias) { MapDbItem mItem = new MapDbItem(); mItem.setName(localAlias); mItem.setState(state); - mItem.setTimestamp(new Date()); + mItem.setLastState(item.getLastState()); + ZonedDateTime lastStateUpdate = item.getLastStateUpdate(); + mItem.setTimestamp(lastStateUpdate != null ? Date.from(lastStateUpdate.toInstant()) : new Date()); + ZonedDateTime lastStateChange = item.getLastStateChange(); + mItem.setLastStateChange(lastStateChange != null ? Date.from(lastStateChange.toInstant()) : null); threadPool.submit(() -> { String json = serialize(mItem); map.put(localAlias, json); @@ -204,6 +210,16 @@ public Iterable query(FilterCriteria filter) { return item.isPresent() ? List.of(item.get()) : List.of(); } + @Override + public @Nullable PersistedItem persistedItem(String itemName) { + String json = map.get(itemName); + if (json == null) { + return null; + } + Optional item = deserialize(json); + return item.isPresent() ? item.get() : null; + } + private String serialize(MapDbItem item) { return mapper.toJson(item); } diff --git a/itests/org.openhab.persistence.mapdb.tests/src/main/java/org/openhab/persistence/mapdb/MapDbPersistenceServiceOSGiTest.java b/itests/org.openhab.persistence.mapdb.tests/src/main/java/org/openhab/persistence/mapdb/MapDbPersistenceServiceOSGiTest.java index 56e3656b11769..a960688238687 100644 --- a/itests/org.openhab.persistence.mapdb.tests/src/main/java/org/openhab/persistence/mapdb/MapDbPersistenceServiceOSGiTest.java +++ b/itests/org.openhab.persistence.mapdb.tests/src/main/java/org/openhab/persistence/mapdb/MapDbPersistenceServiceOSGiTest.java @@ -17,12 +17,14 @@ import static org.hamcrest.beans.HasPropertyWithValue.hasProperty; import static org.hamcrest.collection.IsEmptyIterable.emptyIterable; import static org.hamcrest.collection.IsIterableContainingInOrder.contains; +import static org.junit.jupiter.api.Assertions.assertNull; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.time.ZonedDateTime; import java.util.stream.Stream; import org.junit.jupiter.api.AfterAll; @@ -32,6 +34,7 @@ import org.openhab.core.library.items.ColorItem; import org.openhab.core.library.items.DimmerItem; import org.openhab.core.library.items.SwitchItem; +import org.openhab.core.library.types.DecimalType; import org.openhab.core.library.types.HSBType; import org.openhab.core.library.types.OnOffType; import org.openhab.core.library.types.PercentType; @@ -133,4 +136,26 @@ public void queryShouldFindStoredItemsByAlias() { waitForAssert(() -> assertThat(persistenceService.query(filterByAlias), contains(allOf(hasProperty("name", equalTo(alias)), hasProperty("state", equalTo(state)))))); } + + @Test + public void persistedItemShouldFindItem() { + String name = "decimal"; + State state = DecimalType.valueOf("100"); + State lastState = DecimalType.ZERO; + ZonedDateTime lastStateUpdate = ZonedDateTime.now().minusHours(1); + ZonedDateTime lastStateChange = ZonedDateTime.now().minusHours(2); + + GenericItem item = new DimmerItem(name); + item.setState(state, lastState, lastStateUpdate, lastStateChange); + + assertNull(persistenceService.persistedItem(name)); + + persistenceService.store(item); + + waitForAssert(() -> assertThat(persistenceService.persistedItem(name), + allOf(hasProperty("name", equalTo(name)), hasProperty("state", equalTo(state)), + hasProperty("lastState", equalTo(lastState)), + hasProperty("timestamp", any(ZonedDateTime.class)), + hasProperty("lastStateChange", any(ZonedDateTime.class))))); + } }