Expression variable coercion and initial values

I have been lately playing more with expressions and here is one finding which may be useful to others.

There is an example where data is pushed to an array and then calculations can be done with the data:

In this example there is three main parts
-create interval condition which is then triggering expression
-push data to array
-do something with array values

So something like this

getstate( "Reactor Sensor 13", "urn:toggledbits-com:serviceId:ReactorGroup", "GroupStatus_root" )

if( isint=="1", push( series, tonumber(  getstate( "BR_Temperature", "urn:upnp-org:serviceId:TemperatureSensor1", "CurrentTemperature" )  ), 5), series)


The issue is that variables get initial value of null. So if now the interval driving isint is set for example to one hour, during the first hour series is null, range tries to get min and max out of null and that will result to coercion error. After the first push to array happens then everything works ok.

To fix this, an initial value can be used:

getstate( "Reactor Sensor 13", "urn:toggledbits-com:serviceId:ReactorGroup", "GroupStatus_root" )

tonumber(getstate("BR_Temperature", "urn:upnp-org:serviceId:TemperatureSensor1", "CurrentTemperature"))

if(series==null, list(temperature1), if( isint=="1", push( series, temperature1, 5), series))


Now if the series is null, it will be initiated as an array with a value and range calculation works from the beginning.

Above issue is not limited to only arrays, but all variables. For example take this simple expression which tries to store minimum value:

if(temperature1 < mintemp, temperature1)

Since the initial value of mintemp is null, the result is only error message “[luaxp]Invalid comparison (number<table) at 15”. The same fix can be applied:

if(mintemp==null, temperature1, if(temperature1 < mintemp, temperature1))

An improvement idea might be a box next to expression/variable where initial value could be given (number, string, array) :slight_smile:

One thing the expressions could be used is filtering. I have some data sources where data has some noise and needs to be filtered. Here couple examples I have been working on.
First collect data to an array:

if(temps==null, list(outtemp,outtemp,outtemp),if(every5min=="1", push(temps, outtemp, 3) , temps))

low-pass filtering:

if(LPtemp==null, temps[1], if(every5min=="1",0.6*temps[1]+0.4*temps[2],LPtemp))

median filtering:

if( (temps[1]<=temps[2])&&(temps[1]<=temps[3]), if(temps[2]<=temps[3],temps[2],temps[3]), if( (temps[2]<=temps[1])&&(temps[2]<=temps[3]), if(temps[1]<=temps[3],temps[1],temps[3]) , if(temps[1]<=temps[2],temps[1],temps[2])))

If the LuaXP had median function this would be much easier :wink:

1 Like

series = push( series, somevalue )

results immediately in a non-null array even if series is null on the first execution. It is the specific purpose of push() to create an array if its first argument evaluates to null.

The coercion error is expected, because you can’t add/subtract null from/to anything.

But this all seems much ado about nothing, as all the expressions function once there is one data element in the array. No complex initializations or exceptions are needed. Let it take an error on the first pass. Probably harmless. If not, just disable your action until the array is seeded and move on. It’s probably not going to stay that way for long, and once rolling, it’s probably never empty again.

Best Home Automation shopping experience. Shop at getvera!

© 2020 Vera Control Ltd., All Rights Reserved. Terms of Use | Privacy Policy | Forum Rules