diff --git a/docs/usage/misc/persistence.md b/docs/usage/misc/persistence.md index 87548d833..0cd32e6d8 100644 --- a/docs/usage/misc/persistence.md +++ b/docs/usage/misc/persistence.md @@ -11,31 +11,31 @@ grand_parent: Usage [Persistence](https://www.openhab.org/docs/configuration/persistence.html) functions can be accessed through the item object. The following methods related to persistence are available: -| Method | Parameters | Example | -| ----------------- | ------------------------------------- | --------------------------------------------------------------- | -| `persist` | service | `Item1.persist` | -| `last_update` | service | `Item1.last_update` | -| `previous_state` | skip_equal: (default: false), service | `Item1.previous_state` `Item1.previous_state(skip_equal: true)` | -| `average_since` | timestamp, service | `Item1.average_since(-1.hours, :influxdb)` | -| `changed_since` | timestamp, service | | -| `delta_since` | timestamp, service | | -| `deviation_since` | timestamp, service | | -| `evolution_rate` | timestamp, service | | -| `historic_state` | timestamp, service | | -| `maximum_since` | timestamp, service | | -| `minimum_since` | timestamp, service | | -| `sum_since` | timestamp, service | | -| `updated_since` | timestamp, service | | -| `variance_since` | timestamp, service | | +| Method | Parameters | Return Value | Example | +| ----------------- | ------------------------------------- | ----------------------- | --------------------------------------------------------------- | +| `persist` | service | Nil | `Item1.persist` | +| `last_update` | service | ZonedDateTime | `Item1.last_update` | +| `previous_state` | skip_equal: (default: false), service | item state | `Item1.previous_state` `Item1.previous_state(skip_equal: true)` | +| `average_since` | timestamp, service | DecimalType or Quantity | `Item1.average_since(-1.hours, :influxdb)` | +| `changed_since` | timestamp, service | boolean | | +| `delta_since` | timestamp, service | DecimalType or Quantity | | +| `deviation_since` | timestamp, service | DecimalType or Quantity | | +| `evolution_rate` | timestamp, service | DecimalType | | +| `historic_state` | timestamp, service | HistoricState | | +| `maximum_since` | timestamp, service | HistoricState | | +| `minimum_since` | timestamp, service | HistoricState | | +| `sum_since` | timestamp, service | DecimalType or Quantity | | +| `updated_since` | timestamp, service | boolean | | +| `variance_since` | timestamp, service | DecimalType or Quantity | | * The `timestamp` parameter accepts a java ZonedDateTime or a [Duration](../duration/) object that specifies how far back in time. * The `service` optional parameter accepts the name of the persistence service to use, as a String or Symbol. When not specified, the system's default persistence service will be used. -* The return value of the following persistence methods is a [Quantity](../../items/number/#quantities) when the corresponding item is a dimensioned NumberItem: - * `average_since` - * `delta_since` - * `deviation_since` - * `sum_since` - * `variance_since` +* Dimensioned NumberItems will return a [Quantity](../../items/number/#quantities) object +* `HistoricState` holds the item state and the timestamp data from OpenHAB's [HistoricItem](https://openhab.org/javadoc/latest/org/openhab/core/persistence/historicitem). It contains the following properties: + * `timestamp` - a ZonedDateTime object indicating the timestamp of the persisted data + * `state` - the state of the item persisted at the timestamp above. This will be a Quantity for dimensioned NumberItem. It is not necessary to access the `state` property, as the HistoricState itself will return the state. See the example below. + + ### Examples: @@ -64,6 +64,13 @@ if Power_Usage.average_since(15.minutes) > '5 kW' end ``` +HistoricState + +```ruby +max = Power_Usage.maximum_since(24.hours) +logger.info("Max power usage: #{max}, at: #{max.timestamp}) +``` + ## Persistence Block A persistence block can group multiple persistence operations together under a single service. For example, instead of: diff --git a/features/persistence.feature b/features/persistence.feature index 50b4b9be7..d8506a540 100644 --- a/features/persistence.feature +++ b/features/persistence.feature @@ -77,8 +77,8 @@ Feature: persistence | Number:Power | Max_Power | Max Power | %.1f kW | MAX | And items: - | type | name | label | pattern | state | groups | - | Number:Power | Number_Power | Power | %.1f kW | 0 kW | Max_Power | + | type | name | label | pattern | state | groups | + | Number:Power | Number_Power | Power | %.1f kW | 0 kW | Max_Power | And code in a rules file: """ @@ -95,3 +95,24 @@ Feature: persistence When I deploy the rule Then It should log 'Average: 3 kW' within 10 seconds And It should log 'Average Max: 3 kW' within 10 seconds + + Scenario: Check that HistoricState directly returns a state + Given items: + | type | name | label | pattern | state | + | Number:Power | Number_Power | Power | %.1f kW | 0 kW | + + And code in a rules file: + """ + rule 'Check HistoricState' do + on_start + run { Number_Power.update "3 kW" } + delay 3.second + run do + max = Number_Power.maximum_since(10.seconds, :mapdb) + logger.info("Max time: #{max.timestamp}") # If this caused an error, the next line won't execute + logger.info("Max: #{max}") if max == max.state + end + end + """ + When I deploy the rule + Then It should log 'Max: 3 kW' within 10 seconds diff --git a/lib/openhab/dsl/monkey_patch/items/persistence.rb b/lib/openhab/dsl/monkey_patch/items/persistence.rb index 965e98a95..e7905a439 100644 --- a/lib/openhab/dsl/monkey_patch/items/persistence.rb +++ b/lib/openhab/dsl/monkey_patch/items/persistence.rb @@ -9,6 +9,18 @@ module Items # module Persistence java_import Java::OrgOpenhabCoreTypesUtil::UnitUtils + + # A wrapper for OpenHAB's HistoricItem that returns the state directly + class HistoricState < SimpleDelegator + attr_reader :timestamp, :state + + def initialize(state, timestamp) + @state = state + @timestamp = timestamp + super(@state) + end + end + # All persistence methods that could return a Quantity QUANTITY_METHODS = %i[average_since delta_since @@ -45,13 +57,18 @@ module Persistence # def previous_state(service = nil, skip_equal: false) service ||= persistence_service - PersistenceExtensions.previous_state(self, skip_equal, service&.to_s) + result = PersistenceExtensions.previous_state(self, skip_equal, service&.to_s) + HistoricState.new(quantify(result.state), result.timestamp) end PERSISTENCE_METHODS.each do |method| define_method(method) do |timestamp, service = nil| service ||= persistence_service result = PersistenceExtensions.public_send(method, self, to_zdt(timestamp), service&.to_s) + if result.is_a? Java::OrgOpenhabCorePersistence::HistoricItem + return HistoricState.new(quantify(result.state), result.timestamp) + end + QUANTITY_METHODS.include?(method) ? quantify(result) : result end end