[SOLVED] Reading value from shell script, Tinkerforge Outdoor Weather Station

Hello openHAB Users,

a weather station provides really interesting input for a smarthome. I’m using a “indoor” weather station with the OH binding “tinkerforge”, which works great. Pressure, luminance and humidity (this value has to be handled carefully, it depends on the temperature) are shown in the UI and stored in a chart.

Now i added a “outdoor” weather station. The waterproof sensor lies outside the house and send its data via radio to the receiver (called Outdoor Weather bricklet). There are several more sensors available, like wind and rain sensors. This system is not yet implemented in the OH Binding.

1. Command: I can run a script in the shell, to read the values from the tinkerforge system (running on an remote raspberry):

user@openhab:~$ /home/user/tinkerforge/tinkerforge --host 192.168.178.137 --port 4223 call outdoor-weather-bricklet Es8 get-sensor-data 24

output

temperature=237
humidity=55
last-change=19

2. Command: You can parse the output for the temperature:

user@openhab:~$ /home/user/tinkerforge/tinkerforge --host 192.168.178.137 --port 4223 call outdoor-weather-bricklet Es8 get-sensor-data 24 --execute "echo 'scale=2; {temperature} / 10' | bc | xargs printf '%.1f\n'"

output:

23,7

(followed: Tinkerforge Formatting Output and Outdoor Weather Bricklet )

Now, i want to process these values with openHAB.
Used this document: OH Exec Binding

This thing causes a problem:

Thing exec:command:get_outdoorweather_temp [command="/home/user/tinkerforge/tinkerforge --host 192.168.178.137 --port 4223 call outdoor-weather-bricklet Es8 get-sensor-data 24 --execute "echo 'scale=2; {temperature} / 10' | bc | xargs printf '%.1f\n'"", interval=0, autorun=true]
[WARN ] [el.core.internal.ModelRepositoryImpl] - Configuration model 'weatherscriptexe.things' has errors, therefore ignoring it: [3,187]: missing ']' at 'echo'
[3,224]: no viable alternative at input 'bc'
[3,250]: missing EOF at '""'

The double quotes after the “–execute” argument are misinterpreted. OH wants the thing to be ended with square brackets. I tried, in OH and in the shell, to exchange the double qoutes with single qoutes, but that doesnt worked. So i cannot use this command to provide openhab a single number (here the temperature).

Next approach is to parse the output with regex within OH. Here the first command from above is used:

Thing exec:command:get_outdoorweather_raw [command="/home/user/tinkerforge/tinkerforge --host 192.168.178.137 --port 4223 call outdoor-weather-bricklet Es8 get-sensor-data 24", interval=0, autorun=true, transform="REGEX((.*?))"]

therefore a rule ist needed (from the OH Docs):

rule "Your Execution"
  when
     Item YourTrigger changed
  then
       get_outdoorweather_temp_out.postUpdate(get_outdoorweather_raw.state)
end

When the rule is triggered via the item “YourTrigger”, the logging shows:

[ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Your Execution': The name 'get_outdoorweather_raw' cannot be resolved to an item or type; line 29, column 46, length 22
end

My goal is, to read the whole output from the the shell script and show it as a string. The next step would be, to alter the regex expression and convert the string to different number variables (temperature, humidity) to use them in a chart or rule.

The demo rule points in the right direction:

      // If the returned string is just a number it can be parsed
      // If not a regex or another transformation can be used
      YourNumber.postUpdate(
            (Integer::parseInt(yourcommand_out.state.toString) as Number )
      )

but i’m stuck with both ways: neither i can execute the script, which gives back a number, nor i can parse the script which gives me back a string.

I would be really happy, if someone gives me a hint! :slight_smile:

Certainly, extending the original tinkerforge binding with this new outdoor weather extension would be fine.

Have a good day!
Richard

Similar topics:
https://community.openhab.org/t/regex-transformation-please-help/26604
https://community.openhab.org/t/openhab2-exec-binding/27819
https://www.openhab.org/addons/transformations/regex/

Maybe we should ask @theo if he already has plans (and time!) to implement new bricklets.

You need to escape the characters in the Thing

Thing exec:command:get_outdoorweather_temp [command="/home/user/tinkerforge/tinkerforge --host 192.168.178.137 --port 4223 call outdoor-weather-bricklet Es8 get-sensor-data 24 --execute \"echo 'scale=2; {temperature} / 10' | bc | xargs printf '%.1f\n\'"", interval=0, autorun=true]

Thank you!

with this thing (changed the \ one step to the right)

Thing exec:command:get_outdoorweather_temp [command="/home/rot/tinkerforge/tinkerforge --host 192.168.178.137 --port 4223 call outdoor-weather-bricklet Es8 get-sensor-data 24 --execute \"echo 'scale=2; {temperature} / 10' | bc | xargs printf '%.1f\n'\"", interval=0, autorun=true]

this rule should update the item

Number TF_Outdoor_Temperature "Aussen Temp.  [%.1f °C]"
rule "Your Execution"
  when
     Item YourTrigger changed
  then
      TF_Outdoor_Temperature.postUpdate((Integer::parseInt(get_outdoorweather_temp.state.toString) as Number ))

the result in the log file is

[ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Your Execution': The name 'get_outdoorweather_temp' cannot be resolved to an item or type; line 26, column 32, length 2

Hmmmm…

Yes. Also i would like to learn, how to develeop this binding. Perhaps Theo can give us a hint.

In this post, Theo is also asked for his help: Tinkerunity Tinkerforge Openhab Development

You can’t use a Thing’s name in the scripts
Add the channel to your item like a binding:

{channel=“exec:command:apc:output”}

Number TF_Outdoor_Temperature "Aussen Temp.  [%.1f °C]" { channel="exec:command:get_outdoorweather_temp:output" }

But you will need to change the interval in you thing definition depending on how often you want the value to be pulled

As @vzorglub already said you can not link a thing as trigger for the rule.
Have a look at the detailed example to get a better understanding on how things work.

changed this to:

Thing exec:command:get_outdoorweather_temp [command="/home/user/tinkerforge/tinkerforge --host 192.168.178.137 --port 4223 call outdoor-weather-bricklet Es8 get-sensor-data 24 --execute \"echo 'scale=2; {temperature} / 10' | bc | xargs printf '%.1f\n'\"", interval=30, timeout=15, autorun=false]

the thing ist successfully loaded but i can not see a execution within 30 seconds, nor a error or the temperature shown in the user inferface.

I tought, a rule is needed to update this thing. But ok, there is this interval feature.

I read this thread. They are “sending” values/arguments to a shell script. I am searching for the “opposite” way around: “reading” a value from an script.

This was meant for a better understanding of things channels items etc, as it is explained there in detail.

You may follow up with this where basically is done what you do.

There is a " missing after the =.

As your command directly returns only the value you can link the output channel directly to the item and it should work, no need for a rule.

Ooops sorry

Thank you!
Found this missing ".

Read your suggested post.

Ok, this string item should receive the value directly from the “channel” of the “thing”.

Thing:

Thing exec:command:get_outdoorweather_temp [command="/home/user/tinkerforge/tinkerforge --host 192.168.178.137 --port 4223 call outdoor-weather-bricklet Es8 get-sensor-data 24 --execute \"echo 'scale=2; {temperature} / 10' | bc | xargs printf '%.1f\n'\"", interval=0, autorun=true]

String item:

String TF_Outdoor_Temperature { channel="exec:command:get_outdoorweather_temp:output" }

And from there on, a rule is needed to convert the string into a number?

Your thread:

Is there a direct way to debug this string? Perhaps my userinterface can’t show the string. Or, perhaps, the script isn’t executed at all.

Now I will refer to my first post :wink:

Make a switch to trigger a rule and trigger the command line, then post the returned value from the execution to the log. Watch the log and press the button. See what is returned back.

Did you try to execute the command as user openhab in the command line? ( This is shown in the examples).

What I could imagine is that echo or xargs does not work with the exec command as the user openhab does not execute commands with a bash. So this has to be enabled or the conversion, stripping of the result has to be done in a rule.

I would suggest you try to do the switch to trigger a rule and then try to execute the script without echo then with echo and see what is in the log.

I never thought about user priviliges.

You were testing this with:

sudo -u openhab /opt/vc/bin/vcgencmd measure_temp

and this works in my shell with user “openhab”

 sudo -u openhab /home/user/tinkerforge/tinkerforge --host 192.168.178.137 --port 4223 call outdoor-weather-bricklet Es8 get-sensor-data 24 --execute "echo 'scale=2; {temperature} / 10' | bc | xargs printf '%.1f\n'"

The result is: “30,2”. No problem.

That’s good, but still this is executed in a bash.

Other thing could be the ,. Maybe you have German as language for the pi and English for openhab. And this makes trouble.

followed your suggestion:

Number TF_Outdoor_Temperature "Aussen Temp.  [%.1f °C]" <temperature> (gTemperaturen)
String TF_Outdoor_Temperature_out "[%s]" { channel="exec:command:get_outdoorweather_temp:output" }
Thing exec:command:get_outdoorweather_temp [command="/home/user/tinkerforge/tinkerforge --host 192.168.178.137 --port 4223 call outdoor-weather-bricklet Es8 get-sensor-data 24 --execute \"echo 'scale=2; {temperature} / 10' | bc | xargs printf '%.1f\n'\"", interval=30, autorun=true]

and the rule

rule "Convert String to Item Type and reading temparature value"
  when
    Item YourTrigger changed
    then
    
    // post the new value to the Number Item
    postUpdate( TF_Outdoor_Temperature.toString , TF_Outdoor_Temperature_out.state.toString )

    logInfo("Rule was triggered", " state "+ TF_Outdoor_Temperature_out.state) 
 end

these are the results.

 [INFO ] [home.model.script.Rule was triggered] -  state NULL
 [ERROR] [ui.internal.items.ItemUIRegistryImpl] - Cannot retrieve item 'get_outdoorweather_temp_out' for widget org.eclipse.smarthome.model.sitemap.Text
 [ERROR] [ui.internal.items.ItemUIRegistryImpl] - Cannot retrieve item 'get_outdoorweather_temp_out' for widget org.eclipse.smarthome.model.sitemap.Text
rule "Convert String to Item Type and reading temparature value"
when
    Item TF_Outdoor_Temperature_out changed
then
    logInfo("Rule was triggered", "state " + TF_Outdoor_Temperature_out.state.toString) 
    // post the new value to the Number Item
    postUpdate("TF_Outdoor_Temperature", TF_Outdoor_Temperature_out.state.toString)
end

Hello Vincent,

thank you for your patient correction of my rule. I thought, the item “TF_Outdoor_Temperature_out” can’t change itself, but it is bound to the thing, which updates every 30s. OK.

But, sadly, OH ist not happy:

 [ERROR] [ui.internal.items.ItemUIRegistryImpl] - Cannot retrieve item 'get_outdoorweather_temp_out' for widget org.eclipse.smarthome.model.sitemap.Text
[ERROR] [ui.internal.items.ItemUIRegistryImpl] - Cannot retrieve item 'get_outdoorweather_temp_out' for widget org.eclipse.smarthome.model.sitemap.Text

I think, i should try the following steps:

a) use a simple “dummy” script, to check the openHAB syntax and mechanism
b) trying to use the regex transformation. But, before digging into this transformation, i would like to know, if the data from shell script is transfered correctly to openHAB.

Have a good day! :slight_smile:

this regex way:

the output from the script is:

temperature=251
humidity=43
last-change=20

on https://regex101.com/ with “temperature=(.) humidity=(.)” the result is

Group 1. 12-15 440
Group 2. 25-27 43

So, IF the data from the script find its way into openHAB; then there should be a way to transform it to the corresponding number items “Humidity” and “Temperature”.

What i meant was something like this.

Switch ExecuteComand 
Switch RunScript { channel="exec:command:get_outdoorweather_temp:run" }
String TF_Outdoor_Temperature_out "[%s]" { channel="exec:command:get_outdoorweather_temp:output" }

Attention i removed the --execute echo ... part to first see if the script gets executed and the expected values are shown.


Thing exec:command:get_outdoorweather_temp [command="/home/user/tinkerforge/tinkerforge --host 192.168.178.137 --port 4223 call outdoor-weather-bricklet Es8 get-sensor-data 24", interval=0, autorun=false]
rule "Execute Script and get back return value"
  when
    Item ExecuteComand changed
    then
    
    RunScript.sendCommand(ON)

     // Wait for the command to complete.
     while(RunScript.state != OFF){
       Thread::sleep(100)
     }

    logInfo("Script executed", TF_Outdoor_Temperature_out.state.toString) 
 end