Rule to monitor device status ON/OFF and calculating total usage

First thing I noticed that the first rule “TV State” then block has only two if statements. It just checks them and then does nothing.

To see what is happening you have to see logs. Do you have frontail running? Always when I’m doing something with rules or oh itself, I have frontail open in a browser tab.

And if logs aren’t telling you enough you add more logging statements to your rule starting from the top.

To speed up your debugging and developing I suggest that you create virtual items and use them in your rule and sitemap:

Switch TVStatus_test
Number TVStatus_runtime_test

This way you don’t have to wait for the real item to switch on and off. After the rule is running properly, you replace those with real items.

HI,

It looks like you have a typos in your rules

if (LGTVStatus.state = 0FF) LGTVStatus.postUpdate(OFF) 
    if (LGTVStatus.state = 0N) LGTVStatus.postUpdate(ON)

LGTVStatus.state = OFF and LGTVStatus.state = ON have zeros instead of a letter.

I changed typos but this didnt make any difference. Checking event log, but cant find any evidence this rule works. Just to make it clear I only have one feedback from device informing me if the unit is in ON or OFF state.
Not sure what is the function of this line

var Number Epoch_Time = 0

This is my current rule:

// Switch LGTVStatus "TV State" <switch> - Item Definition (items) 
// Number LGTVStatus_Start_Time "TV Start Time [%d]" - Item Definition (items) - Stores Epoch timestamp 
// Number LGTVStatus_Stop_Time "TV Stop Time [%d]" - Item Definition (items) - Stores Epoch timestamp 
// Number LGTVStatus_Runtime_Minutes "TV Runtime Minutes [%d]" Item Definition (items) - Stores runtime minutes 

var Number Epoch_Time = 0 
var Number LGTVStatus_Runtime = 0 

rule "TV State" 
when 
    Item LGTVStatus changed 
then
    if (LGTVStatus.state == 0) LGTVStatus.postUpdate(OFF) 
    if (LGTVStatus.state > 0) LGTVStatus.postUpdate(ON) 
end

rule "Calculate TV Runtime" 
when
    Item LGTVStatus changed
	then Epoch_Time = now.millis
	if (LGTVStatus.state == OFF) LGTVStatus_Stop_Time.postUpdate(Epoch_Time)
	if (LGTVStatus.state == ON) LGTVStatus_Start_Time.postUpdate(Epoch_Time)
	if ((LGTVStatus_Start_Time.state as DecimalType) > 0 && (LGTVStatus_Stop_Time.state as DecimalType) > 0) { 
	     LGTVStatus_Runtime = ((LGTVStatus_Stop_Time.state as DecimalType) - (LGTVStatus_Start_Time.state as DecimalType)) / 60000
         LGTVStatus_Runtime_Minutes.postUpdate(LGTVStatus_Runtime)
         logInfo("LGTV", "LGTV Runtime - " + LGTVStatus_Runtime)
		 }
end

Epoch_time holds current time in milliseconds. It is used for runtime calculation.

In Burzins code snippet the first rule is used to convert a power meters readings to ON/OFF state. As you already have your item as switch, you don’t need the first rule.

Add more logging into your rule to see what it does and what not.

I removed the first rule as advised (commented out for now). Still no getting any values out of this rule.
As it stands my rule looks like follow at the moment.

// Switch LGTVStatus "TV State" <switch> - Item Definition (items) 
// Number LGTVStatus_Start_Time "TV Start Time [%d]" - Item Definition (items) - Stores Epoch timestamp 
// Number LGTVStatus_Stop_Time "TV Stop Time [%d]" - Item Definition (items) - Stores Epoch timestamp 
// Number LGTVStatus_Runtime_Minutes "TV Runtime Minutes [%d]" Item Definition (items) - Stores runtime minutes 

var Number Epoch_Time = 0 
var Number LGTVStatus_Runtime = 0 

// rule "TV State" 
// when 
//    Item LGTVStatus changed 
// then
//    if (LGTVStatus.state == 0) LGTVStatus.postUpdate(OFF) 
//    if (LGTVStatus.state > 0) LGTVStatus.postUpdate(ON) 
// end

rule "Calculate TV Runtime" 
when
    Item LGTVStatus changed
	then Epoch_Time = now.millis
	if (LGTVStatus.state == OFF) LGTVStatus_Stop_Time.postUpdate(Epoch_Time)
	if (LGTVStatus.state == ON) LGTVStatus_Start_Time.postUpdate(Epoch_Time)
	if ((LGTVStatus_Start_Time.state as DecimalType) > 0 && (LGTVStatus_Stop_Time.state as DecimalType) > 0) { 
	     LGTVStatus_Runtime = ((LGTVStatus_Stop_Time.state as DecimalType) - (LGTVStatus_Start_Time.state as DecimalType)) / 60000
         LGTVStatus_Runtime_Minutes.postUpdate(LGTVStatus_Runtime)
         logInfo("LGTV", "LGTV Runtime - " + LGTVStatus_Runtime)
		 }
end


Sitemap


```csv
Text item=LGTVStatus_Runtime_Minutes label="Runtime Time [%d]"

Items


```csv
Number LGTVStatus_Runtime_Minutes "TV Runtime Minutes"

Looking at the openhab log can see the following error.

2018-12-24 22:47:20.782 [WARN ] [el.core.internal.ModelRepositoryImpl] - Configuration model 'home.rules' has errors, therefore ignoring it: [77,1]: missing EOF at 'var'

What else is missing ?

Looks like you may have eberything firgued out, but here are some useful threads…

Is this a copy paste error? If not, check indentation.

Something is wrong at line 77 as that error says. Is that the only rule in that file?

I have other rules in that file. Other rules are from demo house I believe.
I will check line 77 .

If I’m not mistaken it could be a missing bracket or end statement in the previous rule in that file.

I removed extra gap between last and previous rule and warning now moved down to line 85

2018-12-25 14:32:17.409 [WARN ] [el.core.internal.ModelRepositoryImpl] - Configuration model 'home.rules' has errors, therefore ignoring it: [85,1]: missing EOF at 'var'

I think I must to have fundamental issue with this rule. Do I need to setup anything in persistence - rrd4j ?

If you could post everything in the rules file, not just a single rule, it might be easier to help spot the problem.:wink:

Good suggestion. Attached my entire file. There is not a lot there at the moment :wink:

import org.openhab.core.library.types.*
import org.openhab.core.persistence.*
import org.openhab.model.script.actions.*

var Number counter = 1
var Timer timer = null

// Creates an item that stores the last update time of this item
rule "Records last weather update time"
when
  Item Weather_Temperature received update
then
  postUpdate(Weather_LastUpdate, new DateTimeType())
end

 rule "Initialize Location"
	when 
		System started
	then
		DemoLocation.postUpdate(new PointType ("51.44666,-0.85117"))
end

rule "Set daily max and min temperature" 
when 
     Item Weather_Temperature changed or 
     Time cron "0 0 0 * * ?" or 
     System started 
then 
     val max = Weather_Temperature.maximumSince(now.withTimeAtStartOfDay) 
     val min = Weather_Temperature.minimumSince(now.withTimeAtStartOfDay) 
     if (max !== null && min !== null) { 
         postUpdate(Weather_Temp_Max, max.state) 
         postUpdate(Weather_Temp_Min, min.state) 
     } 
end 

/** shows how to use sensor values from the past */
rule "Persistence Demo"
when
	Time cron "0 * * * * ?"
then	
	if(Weather_Temperature.changedSince(now.minusMinutes(1))) {
		logInfo("PersistenceDemo", "2 minutes ago, the temperature was " + Weather_Temperature.historicState(now.minusMinutes(2)) + " degrees.")
	}
end


// Creates an item that stores the last update time of this item
rule "Records last weather update time"
when
  Item Weather_Temperature received update
then
  postUpdate(Weather_LastUpdate, new DateTimeType())
end


// This rule will be used to test Scale transformation service
rule "Compute humidex"
when
    Item Weather_Temperature changed or
	Item Weather_Humidity changed
then
	var Number T = Weather_Temperature.state as DecimalType
	var Number H = Weather_Humidity.state as DecimalType	
	var Number x = 7.5 * T/(237.7 + T)
	var Number e = 6.112 * Math::pow(10, x.doubleValue) * H/100
	var Number humidex = T + (new Double(5) / new Double(9)) * (e - 10)
	postUpdate(Weather_Humidex, humidex)
end


// Switch LGTVStatus "TV State" <switch> - Item Definition (items) 
// Number LGTVStatus_Start_Time "TV Start Time [%d]" - Item Definition (items) - Stores Epoch timestamp 
// Number LGTVStatus_Stop_Time "TV Stop Time [%d]" - Item Definition (items) - Stores Epoch timestamp 
// Number LGTVStatus_Runtime_Minutes "TV Runtime Minutes [%d]" Item Definition (items) - Stores runtime minutes 

// rule "TV State" 
// when 
//    Item LGTVStatus changed 
// then
//    if (LGTVStatus.state == 0) LGTVStatus.postUpdate(OFF) 
//    if (LGTVStatus.state > 0) LGTVStatus.postUpdate(ON) 
// end

var Number Epoch_Time = 0 
var Number LGTVStatus_Runtime = 0 

rule "Calculate TV Runtime" 
when
    Item LGTVStatus changed
	then Epoch_Time = now.millis
	if (LGTVStatus.state == OFF) LGTVStatus_Stop_Time.postUpdate(Epoch_Time)
	if (LGTVStatus.state == ON) LGTVStatus_Start_Time.postUpdate(Epoch_Time)
	if ((LGTVStatus_Start_Time.state as DecimalType) > 0 && (LGTVStatus_Stop_Time.state as DecimalType) > 0) { 
	     LGTVStatus_Runtime = ((LGTVStatus_Stop_Time.state as DecimalType) - (LGTVStatus_Start_Time.state as DecimalType)) / 60000
         LGTVStatus_Runtime_Minutes.postUpdate(LGTVStatus_Runtime)
         logInfo("LGTV", "LGTV Runtime - " + LGTVStatus_Runtime)
		 }
end




var Number Epoch_Time = 0 
var Number LGTVStatus_Runtime = 0 

Try moving the two global var’s to the top of the rules file or place them inside the rule.

This removes the error as long as you don’t need those two var’s in the rules above.

rule "Calculate TV Runtime" 
when
    Item LGTVStatus changed
	then
	var Number Epoch_Time = 0
        var Number LGTVStatus_Runtime = 0 
 
	Epoch_Time = now.millis
	if (LGTVStatus.state == OFF) { LGTVStatus_Stop_Time.postUpdate(Epoch_Time) }
	if (LGTVStatus.state == ON) { LGTVStatus_Start_Time.postUpdate(Epoch_Time) }
	if ((LGTVStatus_Start_Time.state as DecimalType) > 0 && (LGTVStatus_Stop_Time.state as DecimalType) > 0) { 
	     LGTVStatus_Runtime = ((LGTVStatus_Stop_Time.state as DecimalType) - (LGTVStatus_Start_Time.state as DecimalType)) / 60000
         LGTVStatus_Runtime_Minutes.postUpdate(LGTVStatus_Runtime)
         logInfo("LGTV", "LGTV Runtime - " + LGTVStatus_Runtime)
		 }
end

If you need the var’s this also removes the error:

import org.openhab.core.library.types.*
import org.openhab.core.persistence.*
import org.openhab.model.script.actions.*

var Number counter = 1
var Timer timer = null
var Number Epoch_Time = 0
var Number LGTVStatus_Runtime = 0 

// Creates an item that stores the last update time of this item
rule "Records last weather update time"
when
  Item Weather_Temperature received update
then
  postUpdate(Weather_LastUpdate, new DateTimeType())
end

 rule "Initialize Location"
	when 
		System started
	then
		DemoLocation.postUpdate(new PointType ("51.24626,-0.75117"))
end

rule "Set daily max and min temperature" 
when 
     Item Weather_Temperature changed or 
     Time cron "0 0 0 * * ?" or 
     System started 
then 
     val max = Weather_Temperature.maximumSince(now.withTimeAtStartOfDay) 
     val min = Weather_Temperature.minimumSince(now.withTimeAtStartOfDay) 
     if (max !== null && min !== null) { 
         postUpdate(Weather_Temp_Max, max.state) 
         postUpdate(Weather_Temp_Min, min.state) 
     } 
end 

/** shows how to use sensor values from the past */
rule "Persistence Demo"
when
	Time cron "0 * * * * ?"
then	
	if(Weather_Temperature.changedSince(now.minusMinutes(1))) {
		logInfo("PersistenceDemo", "2 minutes ago, the temperature was " + Weather_Temperature.historicState(now.minusMinutes(2)) + " degrees.")
	}
end


// Creates an item that stores the last update time of this item
rule "Records last weather update time"
when
  Item Weather_Temperature received update
then
  postUpdate(Weather_LastUpdate, new DateTimeType())
end


// This rule will be used to test Scale transformation service
rule "Compute humidex"
when
    Item Weather_Temperature changed or
	Item Weather_Humidity changed
then
	var Number T = Weather_Temperature.state as DecimalType
	var Number H = Weather_Humidity.state as DecimalType	
	var Number x = 7.5 * T/(237.7 + T)
	var Number e = 6.112 * Math::pow(10, x.doubleValue) * H/100
	var Number humidex = T + (new Double(5) / new Double(9)) * (e - 10)
	postUpdate(Weather_Humidex, humidex)
end


// Switch LGTVStatus "TV State" <switch> - Item Definition (items) 
// Number LGTVStatus_Start_Time "TV Start Time [%d]" - Item Definition (items) - Stores Epoch timestamp 
// Number LGTVStatus_Stop_Time "TV Stop Time [%d]" - Item Definition (items) - Stores Epoch timestamp 
// Number LGTVStatus_Runtime_Minutes "TV Runtime Minutes [%d]" Item Definition (items) - Stores runtime minutes 

// rule "TV State" 
// when 
//    Item LGTVStatus changed 
// then
//    if (LGTVStatus.state == 0) LGTVStatus.postUpdate(OFF) 
//    if (LGTVStatus.state > 0) LGTVStatus.postUpdate(ON) 
// end


rule "Calculate TV Runtime" 
when
    Item LGTVStatus changed
	then
	Epoch_Time = now.millis
	if (LGTVStatus.state == OFF) { LGTVStatus_Stop_Time.postUpdate(Epoch_Time) }
	if (LGTVStatus.state == ON) { LGTVStatus_Start_Time.postUpdate(Epoch_Time) }
	if ((LGTVStatus_Start_Time.state as DecimalType) > 0 && (LGTVStatus_Stop_Time.state as DecimalType) > 0) { 
	     LGTVStatus_Runtime = ((LGTVStatus_Stop_Time.state as DecimalType) - (LGTVStatus_Start_Time.state as DecimalType)) / 60000
         LGTVStatus_Runtime_Minutes.postUpdate(LGTVStatus_Runtime)
         logInfo("LGTV", "LGTV Runtime - " + LGTVStatus_Runtime)
		 }
end

Thanks @H102 by moving both var`s to the top of the rule this resolve issue with previous warning (missing EOF).

Looking at openhab log file it is showing me some additional validation issues but (INFO) not sure if this is anything to worry about.

2018-12-25 16:10:38.145 [INFO ] [el.core.internal.ModelRepositoryImpl] - Validation issues found in configuration model 'home.rules', using it anyway:
The use of wildcard imports is deprecated.
The use of wildcard imports is deprecated.
The use of wildcard imports is deprecated.
2018-12-25 16:10:38.153 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model 'home.rules'
2018-12-25 16:18:16.454 [INFO ] [el.core.internal.ModelRepositoryImpl] - Validation issues found in configuration model 'home.rules', using it anyway:
The use of wildcard imports is deprecated.
The use of wildcard imports is deprecated.
The use of wildcard imports is deprecated.
2018-12-25 16:18:16.584 [INFO ] [el.core.internal.ModelRepositoryImpl] - Refreshing model 'home.rules'

But I still don’t get any calculations out of this rule.

Is my syntax correct ?

Sitemap

Text item=LGTVStatus_Runtime_Minutes label="Runtime Time [%d]"

Items

Number LGTVStatus_Runtime_Minutes "TV Runtime Minutes"

Should I set anything in rrd4j ? So far I only been adjusting rule file, sitemap & items.

This error is from:

import org.openhab.core.library.types.*
import org.openhab.core.persistence.*
import org.openhab.model.script.actions.*

the * in the imports.

Do you need the imports? Most rule’s with OH run without calling for imports. Maybe try the rule without and see if it still runs or try removing the *.

I didn’t really study the rule to much, wrapping paper is everywhere.:laughing:

If you are trying to compare a current value to an older one then yes you will need to add the items to the persist file.

Example:

Strategies {
	// for rrd chart cron strategy every minute
	everyMinute : "0 * * * * ?"
	// get data reduced for older values to keep database small
	everyHour : "0 0 * * * ?"
	everyDay : "0 0 0 * * ?"

	default = everyChange
}

Items {
LGTVStatus_Runtime_Minutes : strategy = everyUpdate, everyMinute, restoreOnStartup
* : strategy = everyUpdate, everyMinute, restoreOnStartup
}

You can list all item separate or use the * to add all of them like the second line in items above. See the doc’s for more details and examples.

Thanks. At the moment my goal is to display total usage time in one day as bare minimum. Later will try to expand it to week/month & year primarily for internal analysis only :wink:

I just discovered some errors in log file with regards to rule.

2018-12-25 16:47:44.282 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Calculate TV Runtime': The name 'LGTVStatus_Stop_Time' cannot be resolved to an item or type; line 91, column 31, length 20
2018-12-25 16:48:31.928 [INFO ] [el.core.internal.ModelRepositoryImpl] - Validation issues found in configuration model 'home.sitemap', using it anyway:
Sitemap should contain either only frames or none at all
2018-12-25 16:48:31.964 [INFO ] [el.core.internal.ModelRepositoryImpl] - Refreshing model 'home.sitemap'
2018-12-25 16:49:47.439 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Calculate TV Runtime': The name 'LGTVStatus_Start_Time' cannot be resolved to an item or type; line 92, column 30, length 21
2018-12-25 16:51:47.165 [INFO ] [el.core.internal.ModelRepositoryImpl] - Validation issues found in configuration model 'home.rules', using it anyway:
The use of wildcard imports is deprecated.
The use of wildcard imports is deprecated.
The use of wildcard imports is deprecated.
2018-12-25 16:51:47.268 [INFO ] [el.core.internal.ModelRepositoryImpl] - Refreshing model 'home.rules'

It doesn’t like ‘LGTVStatus_Stop_Time’ & ‘LGTVStatus_Start_Time’

Those two should be virtual items created by you.

You can forget the persistence for now. Main goal is to get your this rule running. When you do so, you can set up a second rule to reset the counter item at midnight to see daily calculations.

I tried replacing LGTVStatus with another running item at home (light switch) but there is still nothing being populated in this rule. Should I be restarting openhab after updating rule file ?

I seen this topic earlier , probably with slightly easier rule and Vincent solution to increment counter. Will try test it quickly to see if it works.

A restart is not needed.

And yes, you can experiment with something more simple.

Do you know what a virtual item is? You don’t have to replace your tv status item with some other actual item that is linked to a physical switch. Just one “test” item.

I gather the idea of virtual item. I will try to set up test switch which I could toggle freely and will see if it works. There must be some fundamental mistake in my syntax somewhere.

1 Like