Use script output in rule

I use a python script for reading the temperature of my BME280 sensor in the form of xx.xx like 22.54

test.things

Thing exec:command:gettemp [ command=“/home/pi/scripts/getBMEtemp.sh”, interval=30, timeout=20 ]

test.items

String MyTemp { channel=“exec:command:gettemp:output” }
Number MyTempProxy

test.sitemap

Text item=MyTemp

I read and display the value fine but I want to use now the temperature in a rule and I fail with this message:

22:24:52.897 [ERROR] [.script.engine.ScriptExecutionThread] - Rule ‘checkcurrtemp’: org.eclipse.smarthome.core.library.types.DecimalType

Here is the rule
test.rules

rule “convertproxy”
when
Item MyTemp changed
then
MyTempProxy.postUpdate((MyTemp.state as DecimalType))
end

rule “checkcurrtemp”
when
Item TempCurrSetpoint changed or
Item TempSetpoint changed or
Item MyTemp changed
then
if (MyTempProxy.state > TempSetpoint.state) {
postUpdate(Raspi23, OFF)
} else if (MyTempProxy.state < TempSetpoint.state) {
postUpdate(Raspi23, ON)
}
end

Any hints?

This seems to fix it:

Hi, i tried the same to read out my two power meters.

I defined 2 things in things-file. powermeter1 (house) + powermeter2 (solar)

I want to do some maths with this two states. So how can i do this in a rule? I need the powermeter state from the same time.

—> actual house power = powermeter1 - powermeter2

How can i do this in rule to check, if both powermeters have given an update in the last few seconds?

If i make a rule:
when
item powermeter1 changed
then
xxx

then maybe powermeter2 has still old values in it and doing maths would be no good idea.

did you use proxy as described in the link. Read the whole thread as some info is described in previous posts. I am not sure about mathematical operations. I wanted to only compare the temperature read from the script (and converted from string to number via a proxy inside a separate rule) with a setpoint. Do you get an errror on the log? Do you get the things work correctly? Try displaying them first to confirm there are values read into it. Please post your items, rules too.

I used it this way before, but there i sometimes get errors:

rule "Alle Stromzähler auslesen"
	when
		Time cron "0/30 * * * * ?"
	then
		// getting the payload of the meter
		var String meter_payload = executeCommandLine("/usr/src/sml_server /dev/lesekopf0",5000)
		var String solar_meter_payload = executeCommandLine("/usr/src/sml_server1 /dev/lesekopf1",5000)
        ...

So i got the values from both power meters inside the rule.

Now i tested your way with the exec-command in a thing. It works much better and i nearly every time get values send. But the problem is, i need the values from the same time, so that i can calculate the power consumption of my house.

At night it is no plroblem. Then i can use the power usage from my first power meter, but on day when the sun is shining, i have to calculate the first wit the second powermeter, so that i get power usage and not the power which i send to the electricity network.

I made this things-file:

Thing exec:command:powermeter0 [ command="/usr/src/sml_server /dev/lesekopf0", interval=30, timeout=5 ]
Thing exec:command:powermeter1 [ command="/usr/src/sml_server1 /dev/lesekopf1", interval=30, timeout=5 ]

It works very good, but the two exec-commands are fired one on another and not at the same time. So i get a little bit difference in time. I logged this with some loginfo-lines in my rules.

When i use my rule above, the two commands are fired nearly at the same time and do their work at the same time (2 running instances) instead of the thing-exec-command (i think only 1 running instance?).

Also if i use a rule to calculate the two values, i have to wait until both values are updated. If i don´t wait, maybe i calculate with one new value and one old value from 30 seconds ago. And i don´t know how i can check if both values are new.

I think, the best way would be, if i can start the execution of the exec-command in the thing from my rule and not to let the thing execute it all 30 seconds. But i don´t think, that is possible. So i have to use my old rule which did the job (but sometimes i get no values received).

Although I have no experience with custom bindings, I believe your best bet is to write your own binding for that :frowning:

Should be:

MyTempProxy.postUpdate(MyTemp.state.toString)

Number Items are able to parse valid number Strings into a DecimalType. You can’t just cast from a String to a DecimalType. You actually have to parse it.

You will need to do it in a Rule. You do not have the ability to make sure the scripts in your two Things execute close together in time. So you would need to continue to implement it the way you did before.

Or you can modify your scripts to query both power meters and print both readings and use a rule to parse the two values out into two proxy Items that represent each power meter separately. You need to parse the String in a Rule anyway so you are not losing much. But you will get the two readings from the same time.

I don´t understand your last words… I already get a variable from both meters with only values of one powermeter.

And then i can do my calculation with the two values.

What do you want to say to me with your last sentence in the posting? Is this not what you are thinking of?

You say you want to read two meters at the same time.
Openhab will not do that.
You already have scripts that read each meter individually into a string.
Make a new script that reads both meters into one string (you are limited to only passing one string to Openhab at a time).
Write a rule that parses out the single string into two (or more) OH Items, then you can do what you wish with them.

In more details… if you only return two numeric values, lets say with 2 decimal points like 23.54 and 76.65 have only one script run and collect the values from your sensors and then return them as a single string with a special character like @ or ! in the middle so the return string will be 23.54@76.65
Then in the rule use the “@” as a delimiter and cut the string in two strings and convert them to numbers. search in the forum for string manipulation to help you with the functions needed in the rule.

But i do this already? I get new values from both of my power meters every 0 and 30 second of each minute. And i calculate this new values inside the rule, so no old values, only new ones.

Don´t know what would make it better, if i read both strings into one string? I will get the same result? Because the script executes the linux-programm in two instances at the same time and because i print the new values to variables, there can only be new values in it.

But i have seen, that the way with exec and things works better. With my version i often get reading errors, with thing/exec i nearly everytime get good values.

Don´t know why, because the same linux-program is running to read out the power meters.

But you complain about errors. Perhaps a bit more detail about the error would allow fixing the underlying problem, perhaps there is a communication timeout or something. Perhaps truly simultaneous reads clash with each other.

Because you complained about the two reads not happening simultaneously. If you are happy that the rule-based exec action runs two at the same time, then there is no improvement over that.

That might be because it is hiding the errors, if a thing update fails your Item will most likely keep its old value.
You could change your rule to zero or blank the readings after you have used them, to be sure you get a fresh reading next time.

Except that if there was one script to call that returns both values the Exec binding could be used instead of executeCommandLine, which is what I though the whole thread was about.

If the Exec binding and Things is working better, so much more reason to explore the suggestion of making the two calls from a script and parsing out the two numbers in a rule. Then you can have the one Thing call one script which returns the two values as a String.

That is the whole point of my suggestion. To give you a way to get the two power readings very colse together in time using the Exec 2.0 binding.

It could be that the calls are made too close together when you are using executeCommandLine and the scripts are interfearing with eachother. When you used the two Things, the calls to each script were farther apart in time so had no chance of interfearing with eachother.

I made some logging, so i saw that with exec/thing i everytime get new values. And i saw also in logging, that with executecommandline sometimes one of the values is still blank.

I will do some brain storming, if i can write a linux script which reads out both power meters and gives one value back to openhab.

#!/bin/bash

meter = "$(/usr/src/sml_server /dev/lesekopf0)"
solar = "$(/usr/src/sml_server1 /dev/lesekopf1)"

echo "${meter} ${solar}"

The rule would be:

rule "Alle Stromzähler auslesen"
when
    Item PowerMeter received update // String Item linked to exec:command channel that runs above script
then
    val readings = PowerMeter.state.toString.split()
    PowerMeter.postUpdate(readings.get(0)) // assumes the values returned by the scripts are valid Numbers (e.g. no trailing white space)
    SolarMeter.postUpdate(readings.get(1))
end

If the apparent communication issue is due to two reads close together, that should show it up nicely :wink:

Wow, thank you!

I will try this.

The linux script from above gives me two errors:

./sml_reading.sh: line3: meter: command not found
./sml_reading.sh: line4: solar: command not found

EDIT: Found out the error in the script:

It has to be

echo $meter $solar

in the last line.

EDIT2:

Seems also not working properly…

echo -e "$meter \n $solar"

Now this is working so far…

Sadly i get another problem:

If i execute the command without extra script, i get the output in some lines with linebreak after each value.

If i do it your way with the script, i get a long string without linebreak, all in one single long line.

Here is the string i get:

1-0:1.8.0*255#9900.365# 1-0:2.8.0*255#42728.936# 1-0:1.8.1*255#9900.365# 1-0:2.8.1*255#42728.936# 1-0:16.7.0*255#-6.587# 1-0:1.8.0*255#47652.250# 1-0:2.8.0*255#26.066# 1-0:1.8.1*255#47652.250# 1-0:2.8.1*255#26.066# 1-0:16.7.0*255#6.778#

I need the values between the “#”.

If i use the command without script, i get:

1-0:1.8.0*255#9900.365#
1-0:2.8.0*255#42727.616#
1-0:1.8.1*255#9900.365#
1-0:2.8.1*255#42727.616#
1-0:16.7.0*255#-6.706#

From one of the meters and i can split with /n to read out the values.

Any ideas?

You could split on something else. # looks promising.