DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
  1. DZone
  2. Data Engineering
  3. Databases
  4. OpenHab Persistence Tutorial: Using Persistence in Your Rules

OpenHab Persistence Tutorial: Using Persistence in Your Rules

Augment your smart home project by learning about the importance of persistence in rules.

David Cabanero user avatar by
David Cabanero
·
Nov. 05, 18 · Tutorial
Like (2)
Save
Tweet
Share
13.02K Views

Join the DZone community and get the full member experience.

Join For Free

Have you implemented OpenHab Persistence and are looking to step up your rules? Using persistence on your rules can make them more powerful and efficient. In this post, I want to walk you through the different methods and how to use them.

This post is part of a series of three pieces on OpenHab Persistence:

  1. OpenHab Persistence Part 1: Restore The Value if your Items on Startup
  2. OpenHab Persistence Part 2: Build Graphs Using InfluxDB and Grafana
  3. OpenHab Persistence Part 3: Using Persistence in Your Rules

1. OpenHab Persistence in Rules: Why?

If you have reached this point, I think it is clear to you why implementing persistence is a game changer for your Home Automation Project. Now the question is...

How this can improve your rules?

The first reason is monitoring, being able to access prior data allows you to monitor and detect trends. This type of insight can be used to deliver alerts when needed.

Are you using your AC more than usual? Has the temperature of the fridge descended significantly in the last 2 hours?

Persistence is a great tool to deliver information within a context.

Another important feature is the ability to predict an event in the near future. For example, predicting when someone will be home based on presence detection over the past few weeks.

There is a practical example at the end of the post, in case you want to skip the theory.

2. OpenHab Persistence In Rules: Methods

On this section, I will walk you through the different methods that you can use in your rules. The persistence methods use JODA to specify the time. If you want to get into more complex features, you should check the JODA Docs.

<item>.persist

The first method to know about is persist, which is used to tell OpenHab that you want to store the value of an item right now.

mqtt_entrance_contact.persist

In this case, I am telling OpenHab to store the value of mqtt_entrance_contact in this very same moment.

The rest of the methods will be classified into three categories:

  • Methods that detect if an item has been changed or updated within a period of time.
  • Methods that collect metrics on the value of your items.
  • The last category is reserved for those that retrieve historical information about your items.

Detect Whether an Item Has Changed or Updated

<item>.lastUpdate

Pretty simple, it will give the timestamp of the last update for <item>.

Example:

mqtt_entrance_contact.lastUpdate()

Response:

[INFO ]  - lastUpdate: 2018-07-14T12:45:00.028-04:00


<item>.changedSince(AbstractInstant)

ChangeSince returns true if the item that you are requesting the data for has changed since AbstractInstant.

Example:

mqtt_entrance_contact.changedSince(now.minusHours(6))

Response:

[INFO ]  - changedSince: false

This is telling you that the value of the item mqtt_entrance_contact has been the same one for the past 6 hours.

<item>.updatedSince(AbstractInstant)

updatedSince is similar to ChangeSince but it will report on every update that the item has gone through, regardless if that value has changed or not.

Example:

mqtt_entrance_contact.updatedSince(now.minusHours(6)))

Response:

[INFO ] - updatedSince: true

As you saw in the prior example, the value mqtt_entrance_contact has not changed in the last 6 hours, however, we used mqtt_entrance_contact.persist() at the beginning of the rule hence the item has just received an update.

Collect Metrics on Your Items

<item>.maximumSince(AbstractInstant)

Reference to the item with the maximum value since AbstractInstant.

Example:

mqtt_livingroom_temperature.maximumSince(now.minusHours(2)).state

Response:

[INFO ]  - maximumSince: 34.0

Over the past two hours, the item mqtt_livingroom_temperature received a number of updates.

The method maximumSince() will return a pointer to mqtt_livingroom_temperature when the temperature was at its highest value.

You might have noticed that in this case, I have used *.state at the end.

That is because this method returns a pointer to an object, as opposed to the ones that we have seen so far that return a value directly.

<item>.minimumSince(AbstractInstant)

Reference to the item with the minimum value since AbstractInstant.

Example:

mqtt_livingroom_temperature.minimumSince(now.minusHours(10)).state

Response:

[INFO ]  - minimumSince: 18.2


<item>.averageSince(AbstractInstant)

Returns the average values for that item since AbstractInstant.

Example:

mqtt_livingroom_temperature.averageSince(now.minusMinutes(10))

Response:

[INFO ]  - averageSince: 23.14730032883388


<item>.deltaSince(AbstractInstant)

DeltaSince will provide you with the value that a given item has been increased or decreased by.

Example:

mqtt_livingroom_temperature.deltaSince(now.minusMinutes(10))

Response:

[INFO ]  - deltaSince: -0.9

The temperature in my living room has dropped by 0.9 degrees in the last 10 minutes.

<item>.sumSince(AbstractInstant)

Sum of all the different values since AbstractInstant.

Example:

mqtt_livingroom_temperature.sumSince(now.minusMinutes(10))

Response:

[INFO ] - sumSince: 324.1


Retrieve Historical Values

<item>.historicState(AbstractInstant)

Example:

mqtt_entrance_contact.historicState(parse("2018-07-10T16:42:00.0000")).state

Response:

[INFO ]  - historicState: CLOSED

This method returns a pointer to the item mqtt_entrance_contact on July 10th at 4:42 PM.

<item>.previousState()

PreviousState provides a pointer to the item on its previous state.

Example:

mqtt_entrance_contact.previousState().state

Response:

[INFO ]  - previousState: CLOSED

I haven't opened my entrance door in the past few hours so the immediate prior value is still CLOSED.

<item>.previousState(true)

When you pass true as a parameter to the previousState method, it returns the first previous state that is different from the current one.

Example:

mqtt_entrance_contact.previousState(true).state

Response:

[INFO ]  - previousState(true): OPEN


3. OpenHab Persistence Rules: Practical Example

I want to finish this post with a practical example of a rule that I actually use myself.

I have several wireless nodes spread all over the apartment and I would like to monitor that they all sending updates in a timely manner.

Using persistence, this feature is very easy to implement.

As a prerequisite, I add all my nodes to OpenHab Groups (this is on the items file).

Contact mqtt_entrance_contact   (gSensors,gSensorsContact) {mqtt="<[mosquitto:mygateway1-out/4/1/#:state:OPEN:1],<[mosquitto:mygateway1-out/4/1/#:state:CLOSED:0]"}

The rule is triggered by a cron job every 10 minutes to check if any of the nodes has gone on an IoT strike.

rule "Node Offline"
when
	Time cron "0 0/10 * * * ?"   // every 10 minutes
then

In the rule, I iterate over the different nodes in the group and check if they have been updated recently.

gSensorsContact.members.forEach 
  [ item | 			
    if (!item.updatedSince(now.minusMinutes(120))) 
	{
	sendNotification("test@gmail.com", "Node " + item.name + " is offline. Last Update: " + item.lastUpdate)
	sendCommand(echo_livingroom_speak,"David, Node " + item.name + " appears to be offline.")				
	}		
  ]

If the node hasn't been updated within the predefined interval, OpenHab will send me a notification on the cell phone and will broadcast a message through my Amazon Echo's around the apartment.

Here you have the full rule in case you want to check it out.

rule "Node Offline"
when
	Time cron "0 0/10 * * * ?"   // every 10 minutes
then
	gSensorsTemperature.members.forEach 
		[ item | 			
			if (!item.updatedSince(now.minusMinutes(10))) 
				{
				sendNotification("test@gmail.com", "Node " + item.name + " is offline. Last Update: " + item.lastUpdate)
				sendCommand(echo_livingroom_speak,"David, Node " + item.name + " appears to be offline.")				
				}		
		]
 
	gSensorsHumidity.members.forEach 
		[ item | 			
			if (!item.updatedSince(now.minusMinutes(10))) 
				{
				sendNotification("test@gmail.com", "Node " + item.name + " is offline. Last Update: " + item.lastUpdate)
				sendCommand(echo_livingroom_speak,"David, Node " + item.name + " appears to be offline.")				
				}		
		]		
 
	gSensorsContact.members.forEach 
		[ item | 			
			if (!item.updatedSince(now.minusMinutes(120))) 
				{
				sendNotification("test@gmail.com", "Node " + item.name + " is offline. Last Update: " + item.lastUpdate)
				sendCommand(echo_livingroom_speak,"David, Node " + item.name + " appears to be offline.")				
				}		
		]	
 
	gSensorsMotion.members.forEach 
		[ item | 			
			if (!item.updatedSince(now.minusMinutes(120))) 
				{
				sendNotification("test@gmail.com", "Node " + item.name + " is offline. Last Update: " + item.lastUpdate)
				sendCommand(echo_livingroom_speak,"David, Node " + item.name + " appears to be offline.")
				}		
		]	
 
end

As a side note, I use different groups because every node type has a different update interval. If you don't care about that, you could use the same group for all of them.

I hope you learned something today. If you have questions, leave them in the comments.

Persistence (computer science) OpenHAB

Published at DZone with permission of David Cabanero, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Building a Scalable Search Architecture
  • The 12 Biggest Android App Development Trends in 2023
  • How Do the Docker Client and Docker Servers Work?
  • Tech Layoffs [Comic]

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: