Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Additional improvements to persistence article #535

Merged
96 changes: 66 additions & 30 deletions configuration/persistence.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,59 +11,73 @@ openHAB can store data over time; this is known as persistence.
The data may be retrieved at a later time, for example to restore your system after startup, or to prepare graphs for display on a UI.

openHAB persists Item states in a database, and most popular databases are supported.
You may have more that one persistence add-on loaded, and each of these may be configured independently.
You may have more than one persistence add-on loaded, and each of these may be configured independently.

A complete list of supported persistence add-ons may be found in the [persistence]({{base}}/addons/persistence.html) section of the on-line openHAB documentation.

## Persistence Add-on Configuration
## Add-on Configuration
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once about the "Configuration" headline issue. I think it would best be solved if you simply removed this one.
wdyt?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes - that makes sense.


Each persistence add-on you install will need to be configured.
Please refer to the specific [on-line documentation]({{base}}/addons/persistence.html) for your selected persistence add-on for configuration instructions.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In most other articles we are linking the subject directly. I.e.

Please refer to the documentation of available persistence service add-ons for configuration instructions.

(besides I for one would write online instead of on-line...?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to, "Please refer to the available persistence service add-on documentation for your selected persistence add-on for configuration instructions."


## Default Persistence Service

You may install more than one persistence add-on.
Therefore, it is important to select a default persistence service.
It is important to select a default persistence service.
You should do this even if you have only one persistence add-on installed.

To select a default persistence service, in paper UI, select Configuration and then System from the side menu.
Scroll down to "Persistence", and select your Default Service from the drop-down list.
Scroll down to "Persistence", and select your default service from the drop-down list.
Note that you must first install a persistence add-on before you make this selection.
Be sure to save your choice once you have selected your default service.

## Configuration
## Persistence Configuration

Persistence Strategies are configured in a file named `<persistenceservice>.persist`, stored in `$OPENHAB_CONF/persistence` ("persistenceservice" is replaced by the name of your add-on (e.g. `rrd4j.persist`)).
Persistence Strategies are configured in a file named `<persistenceservice>.persist`, stored in `$OPENHAB_CONF/persistence` (Replace "persistenceservice" with the name of your persistence add-on (e.g. `rrd4j.persist`)).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

double brackets? 😕

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about one sentence to introduce the concept. Short example: "Configuration defines which Item, when, where."

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed.


Strategies may be used to persist an Item state when some event has occurred (e.g. an Item state has been updated or changed), on a time schedule, or at a specific time of day (e.g. through a [cron expression](http://www.quartz-scheduler.org/documentation/quartz-2.1.x/tutorials/crontrigger).
### Persistence Triggers

Persistence configuration files consist of several sections:
The persistence of an Item's state may be triggered when that Item changes state or when the Item is updated (even if its state did not change).
Persistence may also be triggered by a time-related event (see Cron Persistence Triggers below).

### Strategies section
### Strategies

This section allows you to define strategies and to declare a set of default strategies to use for this persistence service. The syntax is as follows:
This section allows you to define one or more `Strategies` that will be applied to `Items` (you specifiy the `Items` in the `Items` section).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-you
?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Strategies section allows to define one or more persistence strategies. A strategy defines the event that leads to the storage of an Item's state in the persistence service.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two points.

  1. I tend to write technical information in a more personal style than some people. If this is not your preference, then I can go to an impersonal style, but I find it reads in a very strangely sometimes. Also, a little humanity can go a long way if it does not interfere or get too chatty. But this is your project and your call. Let me know what you prefer.

  2. "allows to define" is a broken English sentence. You need an object. So the alternatives are, "The Strategies section allows YOU to define..." or the more impersonal, "The Strategies section allows ONE to define...". We could restructure it as follows and dodge the point... "The Strategies section defines one or more persistence strategies."

Thoughts?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thought 1: This is not my project! 😄 I'm merely the guy who joined the game a few months earlier than you 😉 You have an argument for the "you" and with that I'm fine to leave it in.

Regarding 2: Interesting. I am pretty sure that I'm using all three versions depending on my mood ^^ I'll try to remember that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool - we will leave "you" in. And okay on not being your project - got it. But don't want to step on your work either.

Regarding 2, the first is definitely broken, so it would be best to avoid this construction.

While we are on this topic, we should really avoid the English passive voice. The example in Wikipedia is great...

Good - Brutus stabbed Caesar
Bad - Caesar was stabbed by Brutus

The subject of the sentence should be the "doer" - the person/thing doing the doing.

Good - "The Binding updates the Item"
Bad - "The Item is updated by the binding"

This section also defines a default strategy.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Combine with the explanation below (either here or there).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

The syntax is as follows:

```java
Strategies {
<strategyName1> : "cronexpression1>"
<strategyName2> : "cronexpression2"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With our without <>?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right - ERROR. Will change to : "cronexpression1"

...
default = everyChange
...
}
```

The following strategies are defined internally:
The `default` parameter assigns a strategy to be used if one is not specified in the `Items` section below.
The `default` parameter may be omitted from the `Strategies` section, but only if a strategy is provided in each line of the `Items` section.

#### Predefined Strategies

The following strategies are defined internally and may be used in place of `strategyName` above:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is below referring to?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep - better to delete it.


- everyChange: persist the Item state whenever its state has changed
- everyUpdate: persist the Item state whenever its state has been updated, even if it did not change
- restoreOnStartup: load and initialize the last persisted Item state on openHAB startup (if the Item state is undefined (`UNDEF`)). See below.
- restoreOnStartup: load and initialize the last persisted state of the Item on openHAB startup (if the Item state is undefined (`UNDEF`)). See below.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"restoreOnStartup will load and ..." ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, the way it is currently written (this is the original language from the Wiki) it matches the other points. RE:

everyChange: persist the...
everyUpdate: persist the...
restoreOnStartup: load and initialize the...

I could change as follows:

restoreOnStatup: will load and initialize the...

but then I think the others should follow the same form:

everyChange: will persist the...
everyUpdate: will persist the...

My two cents are that the "will" is extra, but I am happy to put it in if you like. But I do feel they should all be the same.

Copy link
Member

@ThomDietrich ThomDietrich Oct 23, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, this is not the first time I'm misleading you with super short comments.

  1. Yes all three
  2. Please add code fences
  3. I'm fine with either of
    • restoreOnStartup: load...
    • restoreOnStartup - load...
    • restoreOnStartup will load...

Up to you!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. Not misleading. But...

Two of them cause a persistence action. The last one causes a restore action. So 1 & 2 should be "persist" or "store". Number 3 should be "load". Agree?


### Items section
#### Cron Persistence Triggers
openHAB uses [Quartz](http://www.quartz-scheduler.org/documentation/quartz-2.1.x/quick-start.html) for time-related cron events.
In the `Strategies` syntax example above, "cronexpression" is a Quartz cron-like expression.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cronexpression

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree

See the [Quartz cron tutorial](http://www.quartz-scheduler.org/documentation/quartz-2.1.x/tutorials/crontrigger) for examples of valid time-related trigger expressions.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cron topic is also addressed under rules. There the description might also not be perfect but at least some useful links are given. Imho we should link to there instead of repeating incomplete info here!? http://docs.openhab.org/configuration/rules-dsl.html#time-based-triggers

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes - I looked at the Rules page when I wrote this. I agree that, to the greatest extent possible, there should be "one source of the truth" rather than scattering information around in different places. So...

Does this mean that there should be a separate article on Quartz and that both the Rules and Persistence articles should link to it?

Do you know for sure if you can use "midnight" and "noon" in persistence rules? This is why I did not point to the Items article. (Also, I did some brief digging but did not find any definite information about whether terms other than those two are supported. Or...

I can take the quick way out and just point to the Rules article (but there is no sub-link that I can point to that would take them straight to the Time section of the Rules document. (I could add that as a quick PR.)

Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay - I will change the examples to your heating example. I agree something that is not updated by a binding is better.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be okay to link to the rules article. I'm not sure what you mean by sub-link. This one should be it?
http://docs.openhab.org/configuration/rules-dsl.html#time-based-triggers

Regarding midnight and all other doubts: Honestly you can imho ignore that for now. There is a totally new scheduler at the verge of being merged to eclipse smarthome. We'll have to touch documentation because of that soon enough.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Okay - I will simply link to that article.
  • Yep - that is what I meant by the sub-link. (But I did not see the little chain link symbol on the documentation page in HTML, so I assumed the links had not been added. I need to go look at the source for the Rules page.)
  • Okay - I was just concerned that someone might dive into the Rules link, see the "midnight" terminology and immediately put it into a persistence definition only to have it blow up (or work - I have no idea whether it is supported in persistence configs or not). Not a big deal.


### Items

This section defines which items should be persisted with which strategy.
The syntax is as follows:

```java
Items {
<itemlist1 [-> "<alias1>"] : [strategy = <strategy1>, <strategy2>, ...]
<itemlist1> [-> "<alias1>"] : [strategy = <strategy1>, <strategy2>, ...]
<itemlist2> [-> "<alias2>"] : [strategy = <strategyX>, <strategyY>, ...]
...

Expand All @@ -76,6 +90,8 @@ where `<itemlist>` is a comma-separated list consisting of one or more of the fo
- `<itemName>` a single Item identified by its name. This Item can be a group Item. But note that only the group value will be persisted. The value of the individual group members will not be persisted using this option.
- `<groupName>*` - all members of this group will be persisted, but not the group itself. If no strategies are provided, the default strategies that are declared in the first section are applied. Optionally, an alias may be provided if the persistence service requires special names (e.g. a table to be used in a database, a feed id for an IoT service, etc.)

Note: if the `strategy` portion of the `itemlist` is omitted, the `default` strategy specified in the `Strategies` section will be applied.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add an example below.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about the following:

For example, given an Item named GF_Hall_Light, if default in the Strategies section is set to everyChange, then the following Items section,

Items {
    GF_Hall_Light
}

will cause the state of GF_Hall_Light to be persisted on every change.


A valid persistence configuration file might look like this:

```java
Expand Down Expand Up @@ -139,20 +155,40 @@ You can easily imagine that you can implement very powerful rules using this fea

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the unchanged part above, please capitalize headlines

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay - will ensure all headlines are capitalized in the entire article.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment has been addressed

Here is the full list of available persistence extensions:

```java
<item>.persist - Persists the current state
<item>.lastUpdate - Query for the last update timestamp of a given Item.
<item>.historicState(AbstractInstant) - Retrieves the historic Item at a certain point in time
<item>.changedSince(AbstractInstant) - Checks if the state of the Item has (ever) changed since a certain point in time
<item>.updatedSince(AbstractInstant) - Checks if the state of the Item has been updated since a certain point in time
<item>.maximumSince(AbstractInstant) - Gets the Item with the maximum value (state) since a certain point in time
<item>.minimumSince(AbstractInstant) - Gets the Item with the minimum value (state) since a certain point in time
<item>.averageSince(AbstractInstant) - Gets the average value of the state of a given Item since a certain point in time.
<item>.deltaSince(AbstractInstant) - Gets the difference value of the state of a given Item since a certain point in time.
<item>.previousState() - Retrieves the previous Item (returns HistoricItem).
<item>.previousState(true) - Retrieves the previous Item, skips items with equal state values and searches the first Item with state not equal the current state (returns HistoricItem).
<item>.sumSince(AbstractInstant) - Retrieves the sum of the previous states since a certain point in time. (OpenHab 1.8)
```
- <item>.persist - Persists the current state


- <item>.lastUpdate - Query for the last update timestamp of a given Item.


- <item>.historicState(AbstractInstant) - Retrieves the historic Item at a certain point in time


- <item>.changedSince(AbstractInstant) - Checks if the state of the Item has (ever) changed since a certain point in time


- <item>.updatedSince(AbstractInstant) - Checks if the state of the Item has been updated since a certain point in time


- <item>.maximumSince(AbstractInstant) - Gets the Item with the maximum value (state) since a certain point in time


- <item>.minimumSince(AbstractInstant) - Gets the Item with the minimum value (state) since a certain point in time


- <item>.averageSince(AbstractInstant) - Gets the average value of the state of a given Item since a certain point in time


- <item>.deltaSince(AbstractInstant) - Gets the difference value of the state of a given Item since a certain point in time


- <item>.previousState() - Retrieves the previous Item (returns HistoricItem)


- <item>.previousState(true) - Retrieves the previous Item, skips items with equal state values and searches the first Item with state not equal the current state (returns HistoricItem)


- <item>.sumSince(AbstractInstant) - Retrieves the sum of the previous states since a certain point in time. (OpenHab 1.8)

These extensions use the default persistence service that is configured as the default persistence service. (Refer to Default Persistence Service above to configure this.)

Expand Down