Automatic shutdown rule for an PI5, when an Item changes

Hi all,

is there any easy way to shutdown my PI 5 with OH 4.2.1, when my attached USV has less than 300 sec lifetime? The “Network UPS tools binding” is deliver me all needed information as trigger.
So the question how the script with e.g. something like “sudo shutdown -h now” should be looking like, and where I should place it and how to call it from rule in the OH GUI interface.

Thanks for the help.

You will need the Exec Binding for that. There are many example using the search :wink:

1 Like

This is something that can be and probably is best implemented in NUT itself since you already have NUT installed. It’s kind of one of the main reasons NUT exists in the first place.

Depending on how you set up the NUT server, you just need to install the NUT Client, configure it to monitor the NUT Server. The MONITOR property in upsmon.conf includes an upsmon role (master or slave on older versions, primary or secondary on newer versions of NUT) which controls whether this machine shutsdown first or last (master is usually the machine running the NUT server so it shuts down last). There are lots of options available to control when everything starts to shutdown (percentage of battery left, time on battery, etc.). I just use the defaults and set all the machines connected to the UPS set as secondary and configure the one that runs the NUT server as the primary so it shutsdown last.

I agree with Rich: let NUT do the work as intended.

But since you ask how to have OH run a shutdown command:

Thanks Rich for your fast feedback.

My PI’s are already getting all the values from the UPS. A couple of values are already active in the dashboard.The UPS is connected via USB to my Synology NAS, which act as master and shutdown iteself if needed. So the values are there, it’s only about a rule to shut down the PI if needed.

Thanks

Hello Russ,
thanks as well as to Rich, for the fast feedback.

Is there not an easier way without all this option etc. which is listed here in the documentation.

I only need a small rule to shutdown the PI when a value from a OH changes. e.g. < 300 sec of livetime from the UPS.

Thanks in advanced.

I tryed it now step by step. Added to stuff for the sudo, added the file with the commands.
The I generated my rule, it looks like that:

configuration: {}
triggers:
  - id: "1"
    configuration:
      itemName: NetworkUPSTool_BatteryRuntime
      state: < 300 s
    type: core.ItemStateChangeTrigger
conditions: []
actions:
  - inputs: {}
    id: "2"
    configuration:
      type: application/javascript
      script: executeCommandLine("sudo","poweroff") //OH3 version with new
        executeCommandLine syntax
    type: script.ScriptAction

But when checking the logfile I get this error:

==> /var/log/openhab/openhab.log <==
2024-08-15 09:05:28.521 [ERROR] [omation.script.javascript.7a2ff73a12] - Failed to execute script: ReferenceError: "executeCommandLine" is not defined
        at <js>.:program(<eval>:1)
        at org.graalvm.polyglot.Context.eval(Context.java:399)
        at com.oracle.truffle.js.scriptengine.GraalJSScriptEngine.eval(GraalJSScriptEngine.java:458)
        at com.oracle.truffle.js.scriptengine.GraalJSScriptEngine.eval(GraalJSScriptEngine.java:426)
        at java.scripting/javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:262)
        ... 74 more
2024-08-15 09:05:28.523 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID '7a2ff73a12' failed: org.graalvm.polyglot.PolyglotException: ReferenceError: "executeCommandLine" is not defined

Also the Exec Binding is installed, as it was the Tipp from hans-jörg.
JavaScript Scripting is installed and in my system, and ~80 other rules are doing their job…

Any tipp for me?

After Rich’s comment, I had a look at the shutdown config from nut and found it quite easy to setup. Just 2 config files had to be edited. Done within 10 minutes.
So I would prefer to go this route…

1 Like
actions.Exec.executeCommandLine(time.Duration.ofSeconds(3),"sudo","poweroff");

When not using Exec binding you need to make sure that sudo poweroff is not asking for a password for user openhab by editing through

sudo visudo
openhab ALL= NOPASSWD: poweroff

When using it like this you do not need Exec binding.

As all the other posters mention, I‘d also prefer it via NUT as the poweroff routine works even if openhab is not running.

Thanks Oliver2

I have added you idea:

sudo visudo
openhab ALL= NOPASSWD: poweroff

the result in the logfile is now the following:

==> /var/log/openhab/openhab.log <==
2024-08-15 17:18:01.522 [ERROR] [omation.script.javascript.7a2ff73a12] - Failed to execute script: ReferenceError: "executeCommandLine" is not defined
        at <js>.:program(<eval>:1)
        at org.graalvm.polyglot.Context.eval(Context.java:399)
        at com.oracle.truffle.js.scriptengine.GraalJSScriptEngine.eval(GraalJSScriptEngine.java:458)
        at com.oracle.truffle.js.scriptengine.GraalJSScriptEngine.eval(GraalJSScriptEngine.java:426)
        at java.scripting/javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:262)
        ... 74 more
2024-08-15 17:18:01.523 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID '7a2ff73a12' failed: org.graalvm.polyglot.PolyglotException: ReferenceError: "executeCommandLine" is not defined
==> /var/log/openhab/events.log <==

YES, I have the NUT binding installed on my PI5. The client is working I get all data from the UPS.
The UPS itself is connected via USB to the NAS and my NAS is the Master with all stuff.
So all the trigger point for the rule to start I have.

It’s only about the rule and the needed syntax to shutdown the PI5 which is not working.

Did you add
actions.Exec. prior to executeCommandLine?

1 Like

remove this comment above and try again.

The easier way is to do what we suggested earlier: let NUT do the work.

2 Likes

assuming you do not have a random command like what you code snippet showed.
assuming you have exec binding installed
assuming you have edited the sudoers as @Oliver2 suggested.
ASSUMING you edited the whitelist as the Exec binding tells you must do.

Binding Configuration

For security reasons all commands need to be whitelisted. Allowed commands need to be added to the misc/exec.whitelist file in the configuration directory. Every command needs to be on a separate line.
The exact command that @Oliver2 gave you will work fine if openhab is running.
But if openhab is not running your server will not shutdown.
So it is better to do as all the folks here have said and configure your shutdown command to use NUTS and not have a dependency on another application to handle the hardware power down management.
Edit one other item I will mention.
At least for me on a debian 12 as I tested with when you edit the sudoers file you need to provide full path so the actual entry should look like this I also added the -i to ignore any other logged on users just as a precaution.

openhab ALL= NOPASSWD: /sbin/poweroff, /sbin/reboot

note I also added the ability to do a reboot as well to mine.
and exec.whitelist looks like this

/sbin/poweroff
/sbin/poweroff -i
/sbin/reboot

Thanks for all for all the tips.
I have not seen the tip from @Oliver2 with the “actions.Exec.”
Added this, now it work, perfectly.

I will now do a short summery what I have had do that it works:

Precondition:
A: “Network UPS Tools Binding” is installed
B: An Thing is created with the active NUT server, which is my case is my local NAS Server
C: All the channels are created, e.g. the channel “Battery Runtime”

The configuation starts:

  1. Install the “exec Binding” (—> Not needed anymore, see comment down)
  2. Created a file under cd /etc/sudoers.d/ called accessrights
sudo visudo -f  /etc/sudoers.d/accessrights

Content of the file is:

# Allow openhab user to execute shutdown, poweroff, and systemctl commands
openhab   ALL=(ALL) NOPASSWD: /sbin/shutdown, /sbin/poweroff, /sbin/systemctl, /sbin/reboot
  1. Open the file with
sudo visudo

and added here:

# Allow members of group sudo to execute any command
%sudo   ALL=(ALL:ALL) ALL
openhabian ALL= NOPASSWD: /sbin/poweroff, /sbin/reboot
  1. Edit the next file under /etc/openhab/misc
sudo nano /etc/openhab/misc/exec.whitelist

and added to the file “exec.whitelist”

/sbin/poweroff
/sbin/poweroff -i
/sbin/reboot
# 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.

5.Final I have created a rule which looks like this:

configuration: {}
triggers:
  - id: "1"
    configuration:
      itemName: NetworkUPSTool_BatteryRuntime
      state: < 300 s
    type: core.ItemStateChangeTrigger
conditions: []
actions:
  - inputs: {}
    id: "2"
    configuration:
      type: application/javascript
      script: actions.Exec.executeCommandLine("sudo","poweroff")
    type: script.ScriptAction

Thats all, I hope I have nothing forgotten.

So, the rule start when my UPS (the NUT server is installed on my NAS), has less that 300 sec
livetime and then it shutdown my PI5 and my PI4 (prod and test system), that I do not have a data lost when the power would be away. Normal lifetime from all attched clients conneted via the UPS is ~ 25min.

One more thanks to all, and I hope some other can participate from this.

As said, the exec binding incl. whitelist is not required.

1 Like

This is a mistake I also made when I first got started (and is actually referenced in my reboot tutorial). I had thought that the Exec Binding was required, because I didn’t understand that executeCommandLine is built into the openHAB core.

@Oliver2 was 100% correct that the exec binding was not needed based on for what OP wanted
However, if you want to use the exec binding (and it can be used to do this as well) you must add the commands you need to the whitelist.

All that was needed is to correctly edit the sudoers file with path (at least in Debian 12 install it was needed.
and to add the actions.exec to his ExecuteCommandLine statement exactly as @Oliver2 stated.
But the fact remains that if Openhab is not running then this approach will not shutdown his RPi5 and may cause him to have data loss or corruption.
Still the best approach remains handling this with NUT and not depending on another application like Openhab to do the power management of the device.

Thanks…

that’s nice, the I can remove now the “exec binding”. (will mark that in the tutorial).
Just done and it still works :slight_smile:
However, I’m fully aware, that in this extrem unrealistic scenario, that OH is not more running exeactly in this case, when the power will be away, that the OH is not shutdown beforehand.

As said, I want 100% sure, that my NAS is shutdown down itself, that’s why I have it directly connected via USB to the UPS. That’s more important in this case, as the OH Installation.
As backup I have all the needed configuration saved on the NAS and a 1:1 copy from the SD-Card on a other SD-Card in the wallmounted tessor… Should be safe…

Curious about this. This page shows examples with “actions.Exec.”: JavaScript Scripting - Automation | openHAB, but this page uses “Exec.” as the example: actions - Documentation

Obviously the former works as it is tested. Is the “actions.” prefix sometimes or always optional?