How to restart or shutdown a remote Raspberry Pi over SSH within openHAB

Hi,

I treated myself to a few little things. For example, I use the network binding for all devices in the network to display their availability. Openhabian runs on several Raspberry Pi’s and I distribute their system states via a rule and MQTT. So I thought it would be cool if I could switch off and restart these Raspberry Pi’s and start, stop and restart openHAB on them. Operating the openhab service even works this way. What surprises me is that the command to shut down and restart the Raspberry Pi via the terminal works, but clicking in openHAB does nothing. This is despite the fact that both were actually implemented according to the same principle.

It has nothing to do with the exec.whitelist:

/usr/bin/sshpass -p openhabian /usr/bin/ssh -t -o StrictHostKeyChecking=no openhabian@192.168.0.11 'sudo shutdown -h now'
/usr/bin/sshpass -p openhabian /usr/bin/ssh -t -o StrictHostKeyChecking=no openhabian@192.168.0.11 'sudo reboot'

/usr/bin/sshpass -p openhabian /usr/bin/ssh -t -o StrictHostKeyChecking=no openhabian@192.168.0.11 'sudo systemctl start openhab2.service'
/usr/bin/sshpass -p openhabian /usr/bin/ssh -t -o StrictHostKeyChecking=no openhabian@192.168.0.11 'sudo systemctl stop openhab2.service'
/usr/bin/sshpass -p openhabian /usr/bin/ssh -t -o StrictHostKeyChecking=no openhabian@192.168.0.11 'sudo systemctl restart openhab2.service'

So If I run inside the terminal

/usr/bin/sshpass -p openhabian /usr/bin/ssh -t -o StrictHostKeyChecking=no openhabian@192.168.0.11 'sudo reboot'

it worked. Also of course:

/usr/bin/sshpass -p openhabian /usr/bin/ssh -t -o StrictHostKeyChecking=no openhabian@192.168.0.11 'sudo systemctl restart openhab2.service'

Okay, I have now simply changed the password to openhabian. I think it was the default password, wasn’t it?

Inside my thing file I created:

Thing exec:command:openhabianShlPiGeneral_shutdown [command="/usr/bin/sshpass -p openhabian /usr/bin/ssh -t -o StrictHostKeyChecking=no openhabian@192.168.0.11 'sudo shutdown -h now'", autorun=true]
Thing exec:command:openhabianShlPiGeneral_reboot [command="/usr/bin/sshpass -p openhabian /usr/bin/ssh -t -o StrictHostKeyChecking=no openhabian@192.168.0.11 'sudo reboot'", autorun=true]

Thing exec:command:openhabianShlPiGeneral_start [command="/usr/bin/sshpass -p openhabian /usr/bin/ssh -t -o StrictHostKeyChecking=no openhabian@192.168.0.11 'sudo systemctl start openhab2.service'", autorun=true]
Thing exec:command:openhabianShlPiGeneral_stop [command="/usr/bin/sshpass -p openhabian /usr/bin/ssh -t -o StrictHostKeyChecking=no openhabian@192.168.0.11 'sudo systemctl stop openhab2.service'", autorun=true]
Thing exec:command:openhabianShlPiGeneral_restart [command="/usr/bin/sshpass -p openhabian /usr/bin/ssh -t -o StrictHostKeyChecking=no openhabian@192.168.0.11 'sudo systemctl restart openhab2.service'", autorun=true]

Then inside my items:

String ShlPiGeneral_Shutdown "shlPiGeneral Shutdown"  (gSystemInfoShlPiGeneral)  { channel="exec:command:openhabianShlPiGeneral_shutdown:input" }
String ShlPiGeneral_Reboot "shlPiGeneral Reboot"  (gSystemInfoShlPiGeneral)  { channel="exec:command:openhabianShlPiGeneral_reboot:input" }

String ShlPiGeneral_Start "shlPiGeneral Start"  (gSystemInfoShlPiGeneral)  { channel="exec:command:openhabianShlPiGeneral_start:input" }
String ShlPiGeneral_Stop "shlPiGeneral Stop"  (gSystemInfoShlPiGeneral)  { channel="exec:command:openhabianShlPiGeneral_stop:input" }
String ShlPiGeneral_Restart "shlPiGeneral Restart"  (gSystemInfoShlPiGeneral)  { channel="exec:command:openhabianShlPiGeneral_restart:input" }

And at least the sitemap:

    Text label="shlPiGeneral" {
      Switch item=ShlPiGeneral_Shutdown icon="exec_restart" label="shlPiGeneral herunterfahren" mappings=[ON="Herunterfahren"]
      Switch item=ShlPiGeneral_Reboot icon="exec_restart" label="shlPiGeneral neustarten" mappings=[ON="Neustarten"]
      Switch item=ShlPiGeneral_Start icon="exec_restart" label="shlPiGeneral openHAB" mappings=[ON="openHAB starten"]
      Switch item=ShlPiGeneral_Stop icon="exec_restart" label="shlPiGeneral openHAB" mappings=[ON="openHAB stoppen"]
      Switch item=ShlPiGeneral_Restart icon="exec_restart" label="shlPiGeneral openHAB" mappings=[ON="openHAB neustarten"]
    }

I am still using openHAB 2 in the latest version on both devices. It is started from an Ubuntu 18.04 VM and yes, there is a Raspberry Pi 3 Model B+ on the other side.

I am puzzled by the fact that I can execute the command from the terminal of the VM and the openHAB service works, but reboot and shutdown somehow do not.

Thanks in advance.

You need to edit sudoers.d to allow the openHAB user to run commands.

Okay, the problem is not the sudoers.d file. The problem is the state inside openHAB. After rebooting or shutdown the state is on which means, that I can not click it again. So I need another solution for a button or I will have to write a rule which turns the state off after I pressed it.

I tried it as example with:

rule "switch off release buzzer"
when
    Item ShlPiGeneral_Shutdown received command ON
then
    createTimer(now.plusMillis(1000), [ |
        ShlPiGeneral_Shutdown.sendCommand(OFF)
    ])
end

rule "switch off release buzzer"
when
    Item ShlPiGeneral_Reboot received command ON
then
    createTimer(now.plusMillis(1000), [ |
        ShlPiGeneral_Reboot.sendCommand(OFF)
    ])
end

I found it here. Also there I found the solution that I can use a Switch as a Button. But the problem is not solved.

Remember I used this inside the sitemap:

Switch item=ShlPiGeneral_Reboot icon="exec_restart" label="shlPiGeneral neustarten" mappings=[ON="Neustarten"]

And inside the items I used a string:

String ShlPiGeneral_Reboot "shlPiGeneral Reboot"  (gSystemInfoShlPiGeneral)  { channel="exec:command:openhabianShlPiGeneral_reboot:input" }

Another approach was:

rule "switch off release buzzer"
when
    Item ShlPiGeneral_Reboot changed
then
    if (ShlPiGeneral_Reboot.state == ON) {
        createTimer(now.plusMillis(1000), [ |
            ShlPiGeneral_Reboot.sendCommand(OFF)
        ])
    }
end

I think it`s because of the String. I am not sure how to make a better solution. Hopefully there is someone who can help me. Thanks in advance.

This scenario is what the Expire functionality is used for, depending on how you setup your items (GUI vs CLi) will dictate how you have to go about adding an expire to the items you want to have their state turn OFF (or some other value) after a set amount of time.

Persistence records the last value sent to the item. That’s covered in the tutorial in the section about persistence.

I’ve abandoned this strategy after realizing it wasn’t necessary. Instead, I just send Flag_System an empty command before rebooting or powering off my system, which becomes the state that’s restored by MapDB.

Basically, have your rule send the item a command before you run the shutdown/reboot command, and that’s what will be restored when OH restarts.

You can’t send ON/OFF commands to a string. It won’t know what to do with states. But you don’t need ON/OFF…you just need a single string item to which you’ll send string values from your sitemap. Your rule will trigger based on the string value.

The solution is in the tutorial if you want it. It’s certainly not the only way to do it, but I’ve received lots of positive feedback on it.

I think it has nothing to do with the items or sitemap. My problem is that you can run it with the exec binding only once:

What I want to achieve is that I can run it multiple times. It`s not a problem with the item state because the Karaf console shows me that it received multiple times the on state.

Okay, I got it. I have to use run instead of input because I have to use a Switch instead of an String. So my items look like this:

Switch ShlPiGeneral_Shutdown "shlPiGeneral Shutdown"  (gSystemInfoShlPiGeneral)  { channel="exec:command:openhabianShlPiGeneral_shutdown:run" }
Switch ShlPiGeneral_Reboot "shlPiGeneral Reboot"  (gSystemInfoShlPiGeneral)  { channel="exec:command:openhabianShlPiGeneral_reboot:run" }

Switch ShlPiGeneral_Start "shlPiGeneral Start"  (gSystemInfoShlPiGeneral)  { channel="exec:command:openhabianShlPiGeneral_start:run" }
Switch ShlPiGeneral_Stop "shlPiGeneral Stop"  (gSystemInfoShlPiGeneral)  { channel="exec:command:openhabianShlPiGeneral_stop:run" }
Switch ShlPiGeneral_Restart "shlPiGeneral Restart"  (gSystemInfoShlPiGeneral)  { channel="exec:command:openhabianShlPiGeneral_restart:run" }

So to break it down:

This

String ShlPiGeneral_Restart "shlPiGeneral Restart"  (gSystemInfoShlPiGeneral)  { channel="exec:command:openhabianShlPiGeneral_restart:input" }

should be

Switch ShlPiGeneral_Restart "shlPiGeneral Restart"  (gSystemInfoShlPiGeneral)  { channel="exec:command:openhabianShlPiGeneral_restart:run" }

And then you have to use an rule file because after you will press the button and maybe openHAB restart on the remote PI the state is currently ON and not OFF.

So in this example:

rule "switch off release buzzer"
when
    Item ShlPiGeneral_Restart received command ON
then
    createTimer(now.plusMillis(1000), [ |
        ShlPiGeneral_Restart.sendCommand(OFF)
    ])
end

Now you can restart openHAB as often as you like. Also restarting the PI or what script you want to execute.

1 Like

Glad that you got it working, but you don’t need the exec binding at all to do this. A string item can trigger a rule that then sends the command via the built-in exec action.

1 Like