[SOLVED] Rule to power cycle an offline device - need help with logic

Hello all,

I trying to get a rule correct which will power cycle a device which has gone offline.I’m having trouble with the logic and hoping folks here can point me in the right direction. My rule attempt is below.

Some more info:
One of my old Sonos players goes offline every week or two and I’d like to automatically reboot it. I have the state of the device being tracked successfully using the network binding. I also have a z-wave appliance module in place to turn power off and on again.

My basic logic:
Detect change in online state
if offline & not currently rebooting (give the device time to boot)
Turn off, set timer to turn on and set rebooting flag
If online
Clear timers and flags

var Timer powerCycleTime = null
var Timer delayPowerCycle = null

rule "Sonos online test"

when
	Item Sonos_ZP3_online changed
then
    if (Sonos_ZP3_online.state === OFF && flag_sonosRebooting === OFF){
		Switch_LR_Sonos.sendCommand(OFF)
		flag_sonosRebooting.sendCommand(ON)
		powerCycleTime = createTimer(now.plusSeconds(10) [|
			Switch_LR_Sonos.sendCommand(ON)
			powerCycleTime = null
			])
		delayPowerCycle = createTimer(now.plusMinutes(5) [|
			flag_sonosRebooting.sendCommand(OFF)
			delayPowerCycle = null
			])
		
	} else if (Sonos_ZP3_online.state === ON) {
		powerCycleTime = null
		delayPowerCycle = null
		flag_sonosRebooting.sendCommand(OFF)
	}
end

Associated things:

Switch Sonos_ZP3_online "Sonos LR online" (Networking) { channel="network:pingdevice:192_168_1_92:online" }

Switch flag_sonosRebooting "Sonos is rebooting" (HA_Flags)

Switch Switch_LR_Sonos	"LR Sonos [%s]"	(FF_Living)	[ "Switchable" ]	{channel="zwave:device:512:node73:switch_binary"} /* Sonos Control */

  • Platform information:
    • Hardware: RaspberryPi
    • OS: OpenHabian
    • Java Runtime Environment: (Whatever is on OpenHabian by default)
    • openHAB version: 2.3.0-1

Thanks in advance,
Reeves

I use this rule for iPhone presents to turn on/off a light when not home. I think if you use the same logic it will work for your Sonos. You can try with changing the names to match and setting the expire time to suit your needs, maybe 5 min for your situation. Note the items are grouped and there is an expire timer (where you set the 5min) with command off. Also in things I use a retry, timeout, and refresh to make sure the connection is valid before starting the rule.

Rule:

rule "start gPresent on system start"
when
    System started
then
    Present.sendCommand(OFF) 
end

rule "gPresent updated, at least one change of state"
when
    Item gPresent received update
then
    if(gPresent.state == ON && Present.state != ON) { 
        Present_Timer.postUpdate(OFF) // cancel the timer if necessary
        Present.sendCommand(ON)
    }

    // no answer from Sonos and timer is not yet ticking (otherwise endless loop)
    else if(gPresent.state == OFF && Present.state != OFF && Present_Timer.state != ON) {
        Present_Timer.sendCommand(ON) // start the timer
    }
end

rule "Present_Timer expired"
when
	Item Present_Timer received command OFF
then
	Present.sendCommand(OFF)
end

Items:

Group:Switch:AND(OFF,ON) gPresent <present>
Switch Present "Phone is home" <present>  // Your Sonos is online
Switch Present_Timer { expire="20m, command=OFF" }  // Timer for power cycle of Sonos
Switch MyDevice <network> (gPresent) { channel="network:pingdevice:SiPhone:online" }

Things:

Thing network:pingdevice:SiPhone [ hostname="10.X.X.XX", retry=30, timeout=15000, refreshInterval=60000 ]
1 Like
...
    if (Sonos_ZP3_online.state == OFF && flag_sonosRebooting.state == OFF){
...
	} else if (Sonos_ZP3_online.state == ON) {
...
1 Like

Thanks Harry, that did the trick. In an earlier iteration I was checking for the timers to be null and needed the identity operator. When I switched the logic I never changed it back to the equality operator.

Thanks so much @H102, I ended up reworking my rules to follow a model more like yours. I wasn’t aware of the Expire binding and found it worked better than the timers for my case. Thanks also for recommending the retries on the ping.

Here are my corrected and functioning rules and related items.

// Assume Sonos online at system start
rule "Set Sonos rebooting off on system start"
when
    System started
then
    Sonos_ZP3_online.postUpdate(ON)
end

// Sonos state has changed, see if reboot needed
rule "Sonos online test"
when
	Item Sonos_ZP3_online received update
then
    // no answer from Sonos and timer is not yet ticking (otherwise endless loop)
     if(Sonos_ZP3_online.state == OFF && sonos_rebootTimer.state != ON) {
        sonos_rebootTimer.sendCommand(ON) // start the timer
		Switch_LR_Sonos.sendCommand(OFF)
    }
    else if(Sonos_ZP3_online.state == ON) { 
        sonos_rebootTimer.postUpdate(OFF) // cancel the timer if necessary
    }
end

Items:

Switch Switch_LR_Sonos	"LR Sonos [%s]"	(FF_Living)	[ "Switchable" ]	{channel="zwave:device:512:node73:switch_binary", expire="30s,command=ON"} // Z-wave switch only stays off for 30 sec
Switch Sonos_ZP3_online "Sonos LR online" (Networking) { channel="network:pingdevice:192_168_1_92:online" } // Thing configured in paper UI with 3 retries
Switch sonos_rebootTimer "Sonos rebooting" { expire="5m, command=OFF" }  // Flag with timer to allow Sonos time to start

Thanks,
Reees

1 Like