Yet Another Exec Question

Hello!

My actual use case is I want to end up with a button or switch in a sitemap that my wife can poke from openhab on her cellphone to turn my son’s internet access on and off. To do that, I think I want to use the exec binding as that will let me check the running state of the script so multiple hits won’t lose sync with what’s on the switch. Running the script takes a little bit - less that a minute, but not much less, so having her mashing at the button could be a thing.

Right now it looks like everything works up to actually calling the script. The implementation is based on the document at https://www.openhab.org/addons/bindings/exec/ except I don’t think I need a return value from my script at this point. I’ve added some internal tests to the script (write to a file in /tmp) that never gets called, but the log entry that fires immediately prior does log (the check state entry). The script runs fine as “sudo -u openhab /sbin/jonas)internet. py ON” and even ran fine when I stripped everything out and just did a blind executeCommand thing like this:

THIS_WORKED:
rule “Jonas internet”
when
Item JonasTrigger changed
then
if(JonasTrigger.state == ON){
executeCommandLine(’/sbin/jonas_internet.py@@ON’, 180000)
}else{
executeCommandLine(’/sbin/jonas_internet.py@@OFF’, 180000)
}
end

The only thing with doing it this way is the button dohickey stays green all the time and I’m not sure what toggling the switch a bunch of times in a row will leave me with. I’m totally game for trying other things, I’m already to the point of considering a flask instance with an api call and then using the http binding if I can’t get this to work.

Once running, I hope to add mysql persistence to this trigger so a restart will bring it back up in the last known state.

Thank you for reading my wall of text.
-ian

=================================================================

  • Platform information:

    • Hardware: VM with 2GB ram and four vcpus

    • OS: Ubuntu 18.04

    • Java Runtime Environment: openjdk version “1.8.0_252”
      OpenJDK Runtime Environment (build 1.8.0_252-8u252-b09-1~18.04-b09)
      OpenJDK 64-Bit Server VM (build 25.252-b09, mixed mode)

    • openHAB version:
      root@openhab:~# dpkg -l | grep openhab
      ii openhab2 2.5.6-2 all openhab2
      ii openhab2-addons 2.5.6-2 all openhab2-addons

  • Issue of the topic: Trying to run python3 script from exec but script doesn’t seem to be actually getting called.

  • Please post configurations (if applicable):

misc

For security reasons all commands that are used by the exec binding or transformation need to be whitelisted.

Every command needs to be listed on a separate line below.

/sbin/jonas_internet.py %2$s
/sbin/jonas_internet.py@@%2$s
/sbin/jonas_internet.py ON
/sbin/jonas_internet.py OFF

**I’m trying everything here - not sure if this is blocking?

things

Thing exec:command:jonasinternet [ command="/sbin/jonas_internet.py@@%2$s", interval=0, timeout=180000, autorun=false ]

**Tried with @@ and without

items

Switch JonasTrigger “Turn Jonas Internet [%s]”
Switch jonasinternet_Run {channel=“exec:command:jonasinternet:run”, autoupdate=“false”}
String jonasinternet_Args {channel=“exec:command:jonasinternet:input”}

rules

rule “Set up your parameters”
when
Item JonasTrigger changed
then
if(JonasTrigger.state == ON){
jonasinternet_Args.sendCommand(“ON”)
}else{
jonasinternet_Args.sendCommand(“OFF”)
}
end

rule “begin your execution”
when
Item jonasinternet_Args received command
then
logInfo(“jonasinternet”, “args passed ok, trying to start script”)
if (jonasinternet_Run.state != ON) {
logInfo(“jonasinternet”, “Passed state not ON check”)
jonasinternet_Run.sendCommand(ON)
}else{
logInfo(“Jonas Internet”, “Script already in use, skipping execution.”)
}
end

rule “script complete”
when
Item jonasinternet_Run changed from ON to OFF
then
logInfo(“Jonas Internet”, “Script has completed.”)
end

sitemap

// Name of file and name of sitemap has to be the same
sitemap jonasinternet label=“Jonas Internet”
{
Frame {
Switch item=JonasTrigger
}
}

The actual script being called

#!/usr/bin/python3
import sys
from pprint import pprint
from jnpr.junos import Device
from jnpr.junos.utils.config import Config

host = ‘my_switch’
user = ‘my_user’
password = ‘my_password’

commands = {
‘ON’: ‘turn on switch configuration stuff’,
‘OFF’: ‘turn off switch configuration stuff’
}

with open(’/tmp/jonasinternet.log’, ‘a’) as f:
f.write(“I ran!”)

if len(sys.argv) != 2:
raise ValueError(“Need to specify ON or OFF”)

if sys.argv[1] not in commands:
raise ValueError(“Invalid arguement”)

dev = Device(host=host, user=user, password=password ).open()
dev.timeout = 120

with Config(dev) as config:
config.load(commands[sys.argv[1]], format=‘set’)
config.commit()

dev.close()

print(sys.argv[1])

logs

2020-07-01 04:22:19.813 [INFO ] [smarthome.model.script.jonasinternet] - args passed ok, trying to start script
2020-07-01 04:22:19.815 [INFO ] [smarthome.model.script.jonasinternet] - Passed state not ON check

First, please How to use code fences. Stuff gets hidden, spacing gets messed up and over all your code and configs and logs become really challenging to read.

Thank you for posting your over all goal. It really helps provide the best answer we can.

One thing I don’t see here which will shed a whole lot of light on what is going on are logs. Do you see errors in openhab.log? Do you see Items changing states in events.log? All you’ve posted are the log statements from the Rules.

Many if not all of your questions will be answered by watching the logs as you interact with the button. In particular:

There are messages in openhab.log when you execute a command that isn’t in the whitelist.

I think by default the Exec binding will log out the command that it ran in openhab.log as well as what is returned by the script. Even if it doesn’t, you can see what the script produced by linking a String Item to the output Channel and watching events.log for changes to that Item.

I don’t know either, but watching the logs while you toggle the button should answer that question fairly quickly.

I follow the philosophy that one should do the simple thing first and test whether it works. Only if it doesn’t work should one move on to something more complicated. So rather than being afraid and ignorant about what happens with repeatedly tapping the toggle on the sitemap, try it out! You won’t break anything and it will be way easier to just set the autorun flag to "true" and avoid all the Rules. Only when that fails should we worry about adding a latch to the Rule to prevent it from running when it’s already running.

Your overall rules approach looks reasonable. But we need more information to understand what is going wrong, if anything. Definitely have your script output something and capture the output (i.e. link an Item to the output channel. There might be some unexpected error or at a minimum we will see if the script is actually running successfully.

not related to OH…i use node-red to debug issues with exec…
than i come back here smarter, and implemnt
it is just easier to debug

Thank you for the pointer on the code fences - I will definitely do that in the future.

In the logs, the only thing besides those two lines getting logged when I hit the trigger button is the java exceptions being thrown by “Missing SslContextFactory” which seems to be a known thing of upnp trying to discover samsung devices in the network. Those roll pretty continuously. I’m still getting things started, so other than some simple rules telling OH what to do when a lutron pico button gets pushed, this python script is it.

The events.log shows very similar output (I grepped out the yamaha receiver that is apparently changing state constantly)

2020-07-01 04:22:19.755 [ome.event.ItemCommandEvent] - Item 'JonasTrigger' received command ON
2020-07-01 04:22:19.756 [vent.ItemStateChangedEvent] - JonasTrigger changed from NULL to ON
2020-07-01 04:22:19.809 [ome.event.ItemCommandEvent] - Item 'jonasinternet_Args' received command ON
2020-07-01 04:22:19.812 [nt.ItemStatePredictedEvent] - jonasinternet_Args predicted to become NULL
2020-07-01 04:22:19.817 [ome.event.ItemCommandEvent] - Item 'jonasinternet_Run' received command ON
2020-07-02 02:48:20.634 [ome.event.ItemCommandEvent] - Item 'JonasTrigger' received command OFF
2020-07-02 02:48:20.637 [vent.ItemStateChangedEvent] - JonasTrigger changed from ON to OFF
2020-07-02 02:48:20.645 [ome.event.ItemCommandEvent] - Item 'jonasinternet_Args' received command OFF
2020-07-02 02:48:20.647 [nt.ItemStatePredictedEvent] - jonasinternet_Args predicted to become NULL
2020-07-02 02:48:20.648 [ome.event.ItemCommandEvent] - Item 'jonasinternet_Run' received command ON
2020-07-02 19:08:10.236 [ome.event.ItemCommandEvent] - Item 'JonasTrigger' received command ON
2020-07-02 19:08:10.241 [vent.ItemStateChangedEvent] - JonasTrigger changed from OFF to ON
2020-07-02 19:08:10.247 [ome.event.ItemCommandEvent] - Item 'jonasinternet_Args' received command ON
2020-07-02 19:08:10.248 [nt.ItemStatePredictedEvent] - jonasinternet_Args predicted to become NULL
2020-07-02 19:08:10.251 [ome.event.ItemCommandEvent] - Item 'jonasinternet_Run' received command ON

Good to know about exec logging whitelist errors. Interestingly, if I comment everything out of misc/exec.whitelist and click the trigger, nothing is logged when I would expect to see something about the command not being on the list.

I added the exec binding via the paperui - is this possibly a case of it not actually being installed/finding it? I would think that lacking the binding would also log a bunch.

Regarding my statement about not knowing what would happen if the the event was triggered a bunch in a row, it was more about keeping state between the network switch the script is trying to update and what is reflected in OH. The network switch will only let one set of changes be committed at a time, so if you were to have a bunch of state toggles on the trigger and only one or two actually get committed, I won’t know what state the network switch will actually be in (ON or OFF). I guess the smarter thing to do would be to have the script do the verifying and whatnot, but it looked like the exec state bits would have that covered.

Thanks for helping, I really appreciate it.
-ian

Thanks for the pointer to node-red. It definitely looks interesting.

Now, what’s going on there? This Item has autoupdate enabled by default. Exec binding doesn’t care about the state of the Item, it will use the sent command.
But nevertheless autoupdate should do its thing and predict/update state to match command.
It’s a curiosity of autoupdate that in case of a broken channel link, it “predicts” a command failure - that is to say, predicts existing state. NULL in this case.

So, why does it think the Item is linked to a broken channel?

Is the exec binding installed? Sure it’s exec version 2.x , not 1.x?

I can’t see anything wrong with the Item definition, String type, channel UID.
Presume your xxx.items file is loaded okay, because the Item exists, we can see it producing event logs.
There is a possibility your Item is linked to something else by PaperUI invisibly.

The command being sent to it is sensible - a string.

Your Thing definition looks sensible - you don’t need the @@ but so what.
Is that xxx.things file being loaded? We cannot tell, you must look in your openhab.log to find out, or look in PaperUI for the Thing.

I pasted your Item and Thing defs into my OH system, and arguments update as expected when Item commanded.
events.log -

2020-07-03 00:53:22.078 [ome.event.ItemCommandEvent] - Item 'jonasinternet_Args' received command ON
2020-07-03 00:53:22.101 [nt.ItemStatePredictedEvent] - jonasinternet_Args predicted to become ON
2020-07-03 00:53:22.130 [vent.ItemStateChangedEvent] - jonasinternet_Args changed from NULL to ON

Conclusion - something funny about your args Item/channel/binding, not obvious.

Trying to command the run Item produces the expected error - I don’t have your script - but it tries, and the correct argument is inserted.
openhab.log

2020-07-03 00:57:11.734 [ERROR] [ng.exec.internal.handler.ExecHandler] - An exception occurred while executing '/sbin/jonas_internet.py ON' : 'Cannot run program "/sbin/jonas_internet.py": CreateProcess error=2, The system cannot find the file specified'

events.log, showing abortive Run condition

2020-07-03 00:57:11.704 [ome.event.ItemCommandEvent] - Item 'jonasinternet_Run' received command ON
2020-07-03 00:57:11.734 [vent.ItemStateChangedEvent] - jonasinternet_Run changed from NULL to ON
2020-07-03 00:57:11.737 [vent.ItemStateChangedEvent] - jonasinternet_Run changed from ON to OFF

As a complete aside to the problem solving, you could probably simplify your rules and solve the possible multiple start issue by making your exec Thing autorun=true. The docs describe what that does, but it has the magical property of only starting off a script run if the command to args is different from the last command.
When autupdate works, the state of args will reflect the last script was run for on or off.

It;s not unusual to need to restart OH when making changes to some text config files. The entry in the whitelist should match exactly the command as entered in the Exec binding Thing.

I would expect that you would use some external sensor to determine that, in this case the Network binding seems like it would be a good match. Even without the rapid toggling, you can’t ever really know what state the switch is in unless what ever turns it off and on provides positive feedback, which is sounds like it doesn’t.

You can’t rely on the Exec binding Items because they don’t actually tell you if the Python script was successful or not, just whether it is currently running or not.

On a different note: how does your Python script work? Are you interacting with the router? Selenium?

Going back through the paperUI, I do notice that I can see the items - jonasinteret_Run and jonasinternet_Args, but I don’t see the Thing - jonasinternet listed. I can’t tell how to determine which version of the Exec binding is installed - how can I do that from either the web or cli? I’m really thinking it’s missing finding the actual Thing part.

I tried editing the things/jonasinternet.things file (I removed the @@ and replaced them with a space) and the logs did not reflect any update/re-read of the file. I restarted openhab with no change in behavior.

So i guess I really need to figure out how to confirm the binding version and figure out why OH doesn’t seem to be finding the thing.

As for the script - it’s up at the top. I’ll put it here in code fences for clarity

#!/usr/bin/python3
import sys
from pprint import pprint
from jnpr.junos import Device
from jnpr.junos.utils.config import Config

host = ‘my_switch’
user = ‘my_user’
password = ‘my_password’

commands = {
‘ON’: ‘turn on switch configuration stuff’,
‘OFF’: ‘turn off switch configuration stuff’
}

with open(’/tmp/jonasinternet.log’, ‘a’) as f:
f.write(“I ran!”)

if len(sys.argv) != 2:
raise ValueError(“Need to specify ON or OFF”)

if sys.argv[1] not in commands:
raise ValueError(“Invalid arguement”)

dev = Device(host=host, user=user, password=password ).open()
dev.timeout = 120

with Config(dev) as config:
config.load(commands[sys.argv[1]], format=‘set’)
config.commit()

dev.close()

print(sys.argv[1])

The network switch is a juniper ex2200-c. Juniper provides a python library ‘eznc’ that lets you do all kinds of stuff to the equipment. In this trivial case, I’m actually activating and deactivating a mac address filter on the house vlan to block his gear. Since the house is dual-stacked ipv4 and ipv6, trying to block him at layer 3 isn’t really a thing, thus the mac block.

Right now I’m using juniper’s event triggers to shut things on and off on a schedule, but I’d really rather hand that off to OH with the ability to override the state as needed (he did foo so gets extra inet time, he didn’t do bar and it needs to be off until he does it, blah…)

So any pointers to how to validate binding versions and where things would be?

Thanks,
-ian

Okay, that’s your real clue. There’s only two ways that can’t happen -
Filename must be xxx.things form, people sometimes end up with xxx.things.txt by accident with editors, xxx.thing is not acceptable either.
File location must be /things folder. Exact folder path depends on your host installation, but it should be a sibling of the /items , /rules, etc. folders and I think already contain a readme.

OMG that was it. I had jonasinternet.thing not jonasinternet.things. For lack of an s. Thank you! With that simple rename, the script is running as expected and shows up in the paperui. I don’t know how many times I looked at that. Well, at least I have a file there now so the next set of Things I create will have an example.

Thank you all for the help!
-ian