# Switch/Group changed Rule not working as expected

**URL:** <https://community.openhab.org/t/switch-group-changed-rule-not-working-as-expected/90355>\
**Category:** Beginners\
**Created:** [January 13, 2020, 8:48pm UTC](https://community.openhab.org/t/switch-group-changed-rule-not-working-as-expected/90355 "2020-01-13T20:48:28Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![tillykeats](https://community.openhab.org/letter_avatar_proxy/v4/letter/t/58f4c7/32.png) [@tillykeats](https://community.openhab.org/u/tillykeats)\
**Post date:** [January 13, 2020, 8:48pm UTC](https://community.openhab.org/t/switch-group-changed-rule-not-working-as-expected/90355/1 "2020-01-13T20:48:28Z")

</div>

This rule sort of works, nearly, it is intended to switch off the Central Heating when the maximum actual temperature of any TRV in a group is greater than the maximum desired temperature of any TRV in the group. In other words, the actual temp is higher than the highest setpoint for a TRV.

However, what happens when max actual \> max setpoint , is that when I move a Switch widget (for Central Heating) on a Sitemap , from OFF to ON, widget immediately indicates ON then immediately goes to OFF (I suspect, the rule fires and correctly turns off the Switch). However the Sitemap widget then goes back to ON and only after I refresh the screen , does the widget now indicates OFF.

I have checked the openhab.log and the automated message is fired as soon as I select ON .So how do I refresh a sitemap in the rule? although I wouldn’t have thought I needed to do this because the widgets are linked to items linked to channels/groups so OH knows to refresh the ON/OFF widget?

## Rule

```csv
rule 
    "HVAC_CH_Off"
when
    Member of g_TRV_Actual_Temperature changed 
    or Member of g_TRV_Set_Temperature changed 
    or Member of g_HVAC_Switch changed to ON
then 
    /*
    logInfo("HVAC_CH_Off.rules", "Checking ACTUAL temp {} against MAX temp {}", g_TRV_Actual_Temperature.state, g_TRV_Set_Temperature.state)
    */
    if (i_HVAC_CH_Switch.state == ON && (g_TRV_Actual_Temperature.state >= g_TRV_Set_Temperature.state)) {
    i_HVAC_CH_Switch.sendCommand(OFF)
    logInfo("HVAC_CH_Off.rules", "CENTRAL HEATING turned off by rule")
    }
end

```

## Items

```csv
Group g_HVAC
Group g_HVAC_Switch
Group:Number:MAX g_TRV_Actual_Temperature "Max Temp TRV"
Group:Number:MAX g_TRV_Set_Temperature "Max Temp TRV"
...
String i_TRV_Lounge_Get_Temperature "Current temperature [%s]C"	<temperature> (g_HVAC, g_TRV, g_TRV_Actual_Temperature) {channel="mqtt:topic:b_MQTT_Broker:t_TRV_Lounge:c_Temperature"}
String i_TRV_Lounge_Set_Temperature "Set temperature [%s]" <temperature>	(g_HVAC, g_TRV, g_TRV_Set_Temperature) {channel="mqtt:topic:b_MQTT_Broker:t_TRV_Lounge:c_Set_Temperature"}
...
/* Danfoss RF Controller */
Switch	i_HVAC_CH_Switch "CH On/Off" <switch>	(g_HVAC, g_HVAC_Switch)	{channel = "zwave:4849599d:t_Zcontroller:node3:swtich_binary2"}
Switch	i_HVAC_HW_Switch "HW On/Off" <switch>	(g_HVAC, g_HVAC_Switch)	{channel = "zwave:4849599d:t_Zcontroller:node3:swtich_binary1"}

```

## Sitemap

```csv
	Frame label="HEATING CONTROLS" {
		Switch item=i_HVAC_CH_Switch label="Central heating On/Off" 
		Switch item=i_HVAC_HW_Switch label="Hot water On/Off"
		Text item=g_TRV_Set_Temperature label="Max desired temperature [%.1f]" icon="temperature"
		Text item=g_TRV_Actual_Temperature label="Max ACTUAL temperature [%.1f]" icon="fire"
	}

```

???

EDIT: Oh, and I’m on a LAN (i.e. not Cloud / WAN) , and , I am using the OH app on Android. I note a refresh must be done manually (swipe down on Android) and browser (F5).,

## Events

```csv
2020-01-13 20:51:16.604 [GroupItemStateChangedEvent] - g_TRV_Actual_Temperature changed from 21.6992 to 21.5 through i_TRV_Lounge_Get_Temperature
2020-01-13 20:56:04.396 [ome.event.ItemCommandEvent] - Item 'i_HVAC_CH_Switch' received command ON
2020-01-13 20:56:04.470 [nt.ItemStatePredictedEvent] - i_HVAC_CH_Switch predicted to become ON
2020-01-13 20:56:04.521 [vent.ItemStateChangedEvent] - i_HVAC_CH_Switch changed from OFF to ON
2020-01-13 20:56:04.524 [ome.event.ItemCommandEvent] - Item 'i_HVAC_CH_Switch' received command OFF
2020-01-13 20:56:04.586 [nt.ItemStatePredictedEvent] - i_HVAC_CH_Switch predicted to become OFF
2020-01-13 20:56:04.607 [vent.ItemStateChangedEvent] - i_HVAC_CH_Switch changed from ON to OFF

```

---

<div class="post-metadata">

**Author:** ![rossko57](https://community.openhab.org/user_avatar/community.openhab.org/rossko57/32/70263_2.png) [@rossko57](https://community.openhab.org/u/rossko57)\
**Post date:** [January 13, 2020, 9:08pm UTC](https://community.openhab.org/t/switch-group-changed-rule-not-working-as-expected/90355/2 "2020-01-13T21:08:29Z")

</div>

> [@tillykeats](#):
>
> .So how do I refresh a sitemap in the rule?

You can’t.

> [@tillykeats](#):
>
> I wouldn’t have thought I needed to do this

That’s correct. The various UIs are more or less effective at auto-refreshing when states change. It is possible to misconfigure to make that worse.

> [@tillykeats](#):
>
> I suspect, the rule fires and correctly turns off the Switch

Well, let’s try and nail it down it a bit.  
May we see your `openhab.log` and `events.log` entries showing the sequence?

I don’t really understand your choice of rule trigger, in conjunction with comparison.

```php
when
   Member of g_TRV_Actual_Temperature changed

```

okay … but your comparison

```php
(g_TRV_Actual_Temperature.state >= g_TRV_Set_Temperature.state))

```

is about the states of the Groups (the MAX), not about states of members.  
Frankly, you don’t care when a member changes at all, and you’re really interested in (and should trigger from) the group state changing.

---

<div class="post-metadata">

**Author:** ![tillykeats](https://community.openhab.org/letter_avatar_proxy/v4/letter/t/58f4c7/32.png) [@tillykeats](https://community.openhab.org/u/tillykeats)\
**Post date:** [January 13, 2020, 9:15pm UTC](https://community.openhab.org/t/switch-group-changed-rule-not-working-as-expected/90355/3 "2020-01-13T21:15:21Z")

</div>

Apologies, I edited the prev post to include the log.

mmm, ok, I may have done something wrong here, but …

```csv
(g_TRV_Actual_Temperature.state >= g_TRV_Set_Temperature.state))

```

So here, I intended to test whether the maximum value of any of the TRVs temperature reading (g\_TRV\_Actual\_Temperature) is higher than the maximum value from the Setpoints (g\_TRV\_Set\_Temperature) from all the TRVs. If so, then turn off the boiler because it’s not needed until a room cools down and the inverse holds true (i.e. Actual is less than Set)  
The comparison is needed because the change in states of groups could be in the other direction where I need to turn ON the boiler automatically if a room cools down.

As I say, it appears to be working looking at the logs, the issue is that the sitemap isnt being refreshed - I think 🙂

---

<div class="post-metadata">

**Author:** ![rossko57](https://community.openhab.org/user_avatar/community.openhab.org/rossko57/32/70263_2.png) [@rossko57](https://community.openhab.org/u/rossko57)\
**Post date:** [January 13, 2020, 9:21pm UTC](https://community.openhab.org/t/switch-group-changed-rule-not-working-as-expected/90355/4 "2020-01-13T21:21:25Z")

</div>

Yes. My comment is that you are running your rule for every change of every member device.  
Pointless, as you are comparing group states.  
Group states are calculated from MAX.  
You can make a hundred member changes without changing MAX.  
Trigger the rule when group state changes, who cares if a member Item changes and does not cause a group state change.

In other threads you are worrying about unnecessary overheads - here’s one, a trivial one, but they add up.

> [@tillykeats](#):
>
> the issue is that the sitemap isnt being refreshed - I think

Yes. I’ve no experience with Android app, but do search your `openhab.log` for sitemap related messages.

---

<div class="post-metadata">

**Author:** ![tillykeats](https://community.openhab.org/letter_avatar_proxy/v4/letter/t/58f4c7/32.png) [@tillykeats](https://community.openhab.org/u/tillykeats)\
**Post date:** [January 13, 2020, 9:27pm UTC](https://community.openhab.org/t/switch-group-changed-rule-not-working-as-expected/90355/5 "2020-01-13T21:27:29Z")

</div>

Sorry , I am not following you. To recap:-

I have two groups aggregated by MAX which gives me the Max of both the actual temperate and the (desired) Set temperatures.

```csv
Group:Number:MAX g_TRV_Actual_Temperature "Max Temp TRV"
Group:Number:MAX g_TRV_Set_Temperature "Max Set TRV"

```

TheI have to n compare max actual temp (g\_TRV\_Actual\_Temperature) with max set temp (g\_TRV\_Set\_Temperature) to test if the boiler can be turned off (i.e. max actual temp read by all TRVs is greater than the highest set point of all TRVs).

```csv
    if (i_HVAC_CH_Switch.state == ON && (g_TRV_Actual_Temperature.state >= g_TRV_Set_Temperature.state)) {
    i_HVAC_CH_Switch.sendCommand(OFF)
    logInfo("HVAC_CH_Off.rules", "CENTRAL HEATING turned off by rule")
    } 

```

I don’t think I follow you when you say it is not needed , can you elaborate by example please.

---

<div class="post-metadata">

**Author:** ![rossko57](https://community.openhab.org/user_avatar/community.openhab.org/rossko57/32/70263_2.png) [@rossko57](https://community.openhab.org/u/rossko57)\
**Post date:** [January 13, 2020, 9:30pm UTC](https://community.openhab.org/t/switch-group-changed-rule-not-working-as-expected/90355/6 "2020-01-13T21:30:50Z")

</div>

This rule triggers when Group state changes. If the group doesn’t change, the rule doesn’t trigger.

```php
when
   Item myGroup changed

```

This rule triggers when any member of the Group changes. The Group itself may or may not change state.

```php
when
   Member of myGroup changed

```

In the case of your rule with comparison, there’s no point running the rule unless the things you are comparing have changed.

---

<div class="post-metadata">

**Author:** ![tillykeats](https://community.openhab.org/letter_avatar_proxy/v4/letter/t/58f4c7/32.png) [@tillykeats](https://community.openhab.org/u/tillykeats)\
**Post date:** [January 13, 2020, 9:31pm UTC](https://community.openhab.org/t/switch-group-changed-rule-not-working-as-expected/90355/7 "2020-01-13T21:31:04Z")

</div>

oh hang on, I get, you mean remove “Member of” on the rule, but I still need the comparison?

---

<div class="post-metadata">

**Author:** ![tillykeats](https://community.openhab.org/letter_avatar_proxy/v4/letter/t/58f4c7/32.png) [@tillykeats](https://community.openhab.org/u/tillykeats)\
**Post date:** [January 13, 2020, 9:40pm UTC](https://community.openhab.org/t/switch-group-changed-rule-not-working-as-expected/90355/8 "2020-01-13T21:40:11Z")

</div>

Ok, so this is the new rule.

```csv
rule 
    "HVAC_CH_Off"
when
    Item g_TRV_Actual_Temperature changed 
    or
    Item g_TRV_Set_Temperature changed 
then 
    /*
    logInfo("HVAC_CH_Off.rules", "Checking ACTUAL temp {} against MAX temp {}", g_TRV_Actual_Temperature.state, g_TRV_Set_Temperature.state)
    */
    if (i_HVAC_CH_Switch.state == ON && (g_TRV_Actual_Temperature.state >= g_TRV_Set_Temperature.state)) {
    i_HVAC_CH_Switch.sendCommand(OFF)
    logInfo("HVAC_CH_Off.rules", "CENTRAL HEATING turned off by rule")
    } 
end

```

You were correct, Thank You. I was triggering the rule on member changes and not when the MAX of the Group value changes (up or down). I also fixed the on/off/on/off issue - I was sending the OFF command to the Switch and the rule had a trigger on the switch. So kind of recursive loop.

Anyway, all sorted now in terms of the Rule, AND, I also added rule code to turn heating ON for the inverse condition. But the refresh of the UI still isnt happening unless I refresh manually on the browser or android app. Any ideas on this?

EDIT: Just noted your initial comment on my question “how do I refresh a sitemap in a rule” , your reply “you can’t”. Mmmm, this sounds like a bug … I would imagine ., in any software, the GUI presentation should reflect a change in any of the underlying hierarchy. I mean Windows does this , most OS and apps do. Is this a bug or “feature request”.?

---

<div class="post-metadata">

**Author:** ![tillykeats](https://community.openhab.org/letter_avatar_proxy/v4/letter/t/58f4c7/32.png) [@tillykeats](https://community.openhab.org/u/tillykeats)\
**Post date:** [January 13, 2020, 10:56pm UTC](https://community.openhab.org/t/switch-group-changed-rule-not-working-as-expected/90355/9 "2020-01-13T22:56:48Z")

</div>

Solution for anyone visiting here as a search (credit to @rossko57)

## Sitemap

```csv
Text item=i_HVAC_HW_Timer label="Hot water off in [%d minutes]" visibility=[i_HVAC_HW_Switch!=OFF]

```

## Items

```csv
Number i_HVAC_HW_Timer "Hot water timer" <clock-on> (g_HVAC)

```

## Rule

```csv
rule 
    "HVAC_HW_Timer"
when
    Item i_HVAC_HW_Switch changed 
then 
    /* Initiate 60 minute timer if Hot Water demanded */
    if (i_HVAC_HW_Switch.state == ON) {
        HW_Timer = createTimer(now.plusMinutes(60), [|
            // code that should execute on expiry of timer
            i_HVAC_HW_Switch.sendCommand(OFF)
            logInfo("HVAC_HW.rules", "HOT WATER turned OFF by rule")
            ])          
        logInfo("HVAC_HW.rules", "HOT WATER countdown timer started by rule")
    }
end

rule 
    "HVAC_HW_Countdown"
when
    Item i_HVAC_HW_Switch changed to ON
then
    /* Display 60 minute countdown */
    var count = 60
    while(count >= 0) {
        i_HVAC_HW_Timer.postUpdate(count)
        count = count - 1
        Thread::sleep(60000)
    }
end

```

---

<div class="post-metadata">

**Author:** ![rossko57](https://community.openhab.org/user_avatar/community.openhab.org/rossko57/32/70263_2.png) [@rossko57](https://community.openhab.org/u/rossko57)\
**Post date:** [January 13, 2020, 11:02pm UTC](https://community.openhab.org/t/switch-group-changed-rule-not-working-as-expected/90355/10 "2020-01-13T23:02:38Z")

</div>

> [@tillykeats](#):
>
> Mmmm, this sounds like a bug

Nope.  
By design, the UI refresh is autonomous. You can do nothing about it from rules, not least because you have no idea (and cannot influence) what UI the user is using.

The autonomous part can go wrong of course.

Have you searched your `openhab.log` for mention of ‘sitemap’ yet?

---

<div class="post-metadata">

**Author:** ![tillykeats](https://community.openhab.org/letter_avatar_proxy/v4/letter/t/58f4c7/32.png) [@tillykeats](https://community.openhab.org/u/tillykeats)\
**Post date:** [January 14, 2020, 1:08am UTC](https://community.openhab.org/t/switch-group-changed-rule-not-working-as-expected/90355/11 "2020-01-14T01:08:38Z")

</div>

I explored Timers a bit more, and searching the forums came upon Expiry Timers from a great post from @rlkoshak here [Design Pattern: Expire Binding Based Timers](https://community.openhab.org/t/design-pattern-expire-binding-based-timers/32634)

But my timer isnt expiring (sending the OFF command)

Any ideas why?

## items

```csv
/* HW Countdown Timer , even set to 1 minute to interrupt the 60 minute counter. Didnt work */
Switch i_HVAC_HW_Timer_Switch { expire="1m,command=OFF" }
Number i_HVAC_HW_Counter "Hot water timer" <clock-on> (g_HVAC) 
/* Sitemap switch */
Switch	i_HVAC_HW_Switch "HW On/Off" <switch>	(g_HVAC, g_HVAC_Switch)	{channel = "zwave:4849599d:t_Zcontroller:node3:swtich_binary1"}

```

## Rule

```csv
// Global var count can be updated from any rule
var count = 0 

rule
    // Start timer when HW switch set to ON
    "HVAC_HW_Start_Timer"
when
    Item i_HVAC_HW_Switch changed to ON
then
    // Start expiry timer
    logInfo("HVAC_HW.rules", "HOT WATER countdown timer STARTED by rule")    
    i_HVAC_HW_Timer_Switch.postUpdate(ON)
    count = 60
    while (count >= 0) {
        i_HVAC_HW_Counter.postUpdate(count)
        count = count - 1
        // Sleep for one minute
        Thread::sleep(60000)
    }
    logInfo("HVAC_HW.rules", "HOT WATER countdown updates finished")    
    i_HVAC_HW_Timer_Switch.sendCommand(OFF)
end

rule 
    // When timer has expired
    "HVAC_HW_Timer_Expired"
when
    Item i_HVAC_HW_Timer_Switch received command OFF
then
    // Set counter to zero - will occult the timer value on the sietmap
    logInfo("HVAC_HW.rules", "HOT WATER countdown timer EXPIRED")    
    count = 0
    //Expiry on switch doesnt send the "OFF" command so force it ??
    i_HVAC_HW_Switch.postUpdate(OFF)
end

rule 
    // Cancel timer if HW switch set to OFF by user
    "HVAC_HW_Cancel_Timer"
when
    Item i_HVAC_HW_Switch changed to OFF
then
    if (i_HVAC_HW_Timer_Switch.state == ON) {
        // Interrupt timer and force expiry
        logInfo("HVAC_HW.rules", "HOT WATER countdown timer INTERRUPTED by rule")    
        count=0
        i_HVAC_HW_Timer_Switch.sendCommand(OFF)
    }
end

```

On the GUI, when I select HW (i\_HVAC\_HW\_Switch) to ON, the events fire and the timer is started and the countdown appears in the GUI, but the expiry on the **Switch i\_HVAC\_HW\_Timer\_Switch { expire=“1m,command=OFF” }** does not “fire” the OFF command so that the rule  
**HVAC\_HW\_Timer\_Expired** is executed.

Any ideas?

---

<div class="post-metadata">

**Author:** ![rossko57](https://community.openhab.org/user_avatar/community.openhab.org/rossko57/32/70263_2.png) [@rossko57](https://community.openhab.org/u/rossko57)\
**Post date:** [January 14, 2020, 1:32am UTC](https://community.openhab.org/t/switch-group-changed-rule-not-working-as-expected/90355/12 "2020-01-14T01:32:21Z")

</div>

Have you installed the expire binding?

Does item ever go ON? Inspect `events.log`  
Does your rule send it an OFF before it expires? Inspect `events.log`  
Does your rule send it another ON before it expires? This you won’t see in events.log, because updates-to-same are not logged.  
But it’s easy to make a diagnostic rule to trigger and report updates.

Please don’t use while-sleep in a finished rule, it is horribly bad practice.

Here is a sleep free countdown technique.

> [@Design Pattern : Expire Binding based Countdown timer](https://community.openhab.org/t/design-pattern-expire-binding-based-countdown-timer/49225):
>
> Problem Statement Sometimes you need to run a timer, but want to able to inspect the remaining time. This is not directly possible with either createTimer() or the Expire binding. Example - I have lighting-on timers that run for different duration depending on the trigger source or time of day. It is useful to have the timer behave “intelligently” - do not apply a new 5-minute request where there is still seven minutes of a previous trigger to run. But do apply it if there is only two minu…

---

<div class="post-metadata">

**Author:** ![tillykeats](https://community.openhab.org/letter_avatar_proxy/v4/letter/t/58f4c7/32.png) [@tillykeats](https://community.openhab.org/u/tillykeats)\
**Post date:** [January 14, 2020, 2:34am UTC](https://community.openhab.org/t/switch-group-changed-rule-not-working-as-expected/90355/13 "2020-01-14T02:34:56Z")

</div>

ok . I installed expiry binding and have this item:

```csv
Number i_HVAC_HW_Counter <clock> {expire="60s,command=-1", autoupdate="false"} 

```

but my rule **HVAC\_HW\_Countdown\_Tick** is fired every minute instead of every second . Is there anyway i can trap ticks every second, because it’s a 60 sec counter and i want to display the countdown in seconds ?

```csv

rule
    // Start timer when HW switch set to ON
    "HVAC_HW_Start_Timer"
when
    Item i_HVAC_HW_Switch changed to ON
then
    // Start expiry timer
    logInfo("HVAC_HW.rules", "HOT WATER countdown timer STARTED by rule")    
    i_HVAC_HW_Counter.sendCommand(60) // sixty seconds ??
end

rule
    // When counter is running
     "HVAC_HW_Countdown_Tick" 
when
	Item i_HVAC_HW_Counter received command
then
	var cmd = (receivedCommand as Number).intValue // integers only
	var count = 0

    logInfo("HVAC_HW.rules", "HW countdown tick")

    // 1st time run
	if (i_HVAC_HW_Counter.state != NULL) { // avoid 1st time run error
		count = (i_HVAC_HW_Counter.state as Number).intValue
        logInfo("HVAC_HW.rules", "HOT WATER count set to {}",count) 
	}
end

```

---

<div class="post-metadata">

**Author:** ![rossko57](https://community.openhab.org/user_avatar/community.openhab.org/rossko57/32/70263_2.png) [@rossko57](https://community.openhab.org/u/rossko57)\
**Post date:** [January 14, 2020, 12:54pm UTC](https://community.openhab.org/t/switch-group-changed-rule-not-working-as-expected/90355/14 "2020-01-14T12:54:00Z")

</div>

> [@tillykeats](#):
>
> … {expire="60s, …

That is the “tick” rate of your countdown timer, you got what you asked for.

I would not advise using this method for a seconds based counter.  
Expire binding has a won’t-fix accuracy bug for times in seconds; this is detailed in the expire-counter thread comments.

The method is intended for “minutes” use e.g. lighting delays, it is not accurate nor particularly efficient for seconds based counting (and we’re back to why would you want to control hot water with a seconds based timer anyway??)

If you must go with seconds, explore alternative means

> [@Design Pattern: Looping Timers](https://community.openhab.org/t/design-pattern-looping-timers/47699):
>
> Edit: Update for OH 4 Please see [Design Pattern: What is a Design Pattern and How Do I Use Them](https://community.openhab.org/t/design-pattern-what-is-a-design-pattern-and-how-do-i-use-them/40319) to understand the scope and purpose of this and other Design Patterns. Problem Statement Often one may require a loop in a Rule, to wait for some event to occur or some state to change before doing something. For example, if a door is opened for a long time to send an alert every hour until the door is closed. Concept Use a Timer that reschedules itself instead of a while loop or sleeps. …

---

<div class="post-metadata">

**Author:** ![tillykeats](https://community.openhab.org/letter_avatar_proxy/v4/letter/t/58f4c7/32.png) [@tillykeats](https://community.openhab.org/u/tillykeats)\
**Post date:** [January 14, 2020, 2:55pm UTC](https://community.openhab.org/t/switch-group-changed-rule-not-working-as-expected/90355/15 "2020-01-14T14:55:12Z")

</div>

@rossko57 you are - as always from my perspective - spot on and correct in your advice. however, I just want the 1sec tick so as to visualise my sitemap in an “accelerated” manner then I switch to 60s ticks.

---

<div class="post-metadata">

**Author:** ![rossko57](https://community.openhab.org/user_avatar/community.openhab.org/rossko57/32/70263_2.png) [@rossko57](https://community.openhab.org/u/rossko57)\
**Post date:** [January 14, 2020, 2:59pm UTC](https://community.openhab.org/t/switch-group-changed-rule-not-working-as-expected/90355/16 "2020-01-14T14:59:16Z")

</div>

Okay … presumably you’ve achieved that, then. The expire binding time setting is the tick rate for this countdown. 60s is one tick/count per minute. 1s is once per second (except that the binding bug will make it tick per two seconds)

When finished playing, note that expire 1m will be more accurate than 60s because of the binding bug.

---

<div class="post-metadata">

**Author:** ![tillykeats](https://community.openhab.org/letter_avatar_proxy/v4/letter/t/58f4c7/32.png) [@tillykeats](https://community.openhab.org/u/tillykeats)\
**Post date:** [January 14, 2020, 3:06pm UTC](https://community.openhab.org/t/switch-group-changed-rule-not-working-as-expected/90355/17 "2020-01-14T15:06:21Z")

</div>

understood. Thank You

---

<div class="post-metadata">

**Author:** ![tillykeats](https://community.openhab.org/letter_avatar_proxy/v4/letter/t/58f4c7/32.png) [@tillykeats](https://community.openhab.org/u/tillykeats)\
**Post date:** [January 14, 2020, 4:51pm UTC](https://community.openhab.org/t/switch-group-changed-rule-not-working-as-expected/90355/18 "2020-01-14T16:51:43Z")

</div>

Final Solution for a 1 HOUR “Boost” timer for Hot Water boiler.  
HVAC=Hot water, Ventilation and Air Conditioning.  
HW=Hot Water

HW switch on the sitemap. When moved to ON , the countdown timer is initialised and “ticks” processed at 12 minute intervals. A countdown timer shows “minutes left to HW off”. Initial timer value is 60 (60 x 1 minute = 1 Hour). This can be modified in the rule by adjusting the **val timeout**

credits to: @rlkoshak and @rossko57

## items

```csv
/* Danfoss RF Controller */
Switch	i_HVAC_CH_Switch "CH On/Off" <switch>	(g_HVAC, g_HVAC_Switch)	{channel = "zwave:4849599d:t_Zcontroller:node3:swtich_binary2"}
Switch	i_HVAC_HW_Switch "HW On/Off" <switch>	(g_HVAC, g_HVAC_Switch)	{channel = "zwave:4849599d:t_Zcontroller:node3:swtich_binary1"}

/* HW Countdown Timer */
Number i_HVAC_HW_Counter <clock> {expire="1m,command=-1",autoupdate="false"} 

```

## rules

```csv
rule
    // Start timer when HW switch set to ON
    "HVAC_HW_Start_Timer"
when
    Item i_HVAC_HW_Switch changed to ON
then
    // Start expiry timer for HW
    val timeout=60 // ONE HOUR
    //val timeout=5 // SECS for test. Set expiry item to "1s"

    logInfo("HVAC_HW.rules", "User turned on HW. Countdown set to {}",timeout)    
    i_HVAC_HW_Counter.sendCommand(timeout)
end

rule
    // When counter is running -
     "HVAC_HW_Countdown" 
when
	Item i_HVAC_HW_Counter received command
then
	var cmd = (receivedCommand as Number).intValue // integers only
	var count = 0

    logInfo("HVAC_HW.rules", "COUNTER TICK - Start")
    
    // Avoid decrementing when timer not initialised
	if (i_HVAC_HW_Counter.state != NULL) {  
		count = (i_HVAC_HW_Counter.state as Number).intValue
        logInfo("HVAC_HW.rules", "...Counter {} is not null",count)
	}

    // Counter running / timer tick so action on command received
	if (cmd == -1 && count > 0) {  

        // Command -1 received so decrement counter, do not go below zero
        logInfo("HVAC_HW.rules", "...Command=-1, Counter>0 ({}). Decrement",count)
        if (count == 1) {

			// Do actions for NORMAL counter expiry, as we about to zero it now.
            // Send Zero to counter to cancel it.
            logInfo("HVAC_HW.rules", "...Counter will expire normally.")
            //i_HVAC_HW_Counter.postUpdate(0)
            //i_HVAC_HW_Switch.sendCommand(OFF)
        }

        // Counter > 1 so Decrement counter
        i_HVAC_HW_Counter.postUpdate(count - 1)
        logInfo("HVAC_HW.rules", "...Counter now set to {}",count-1)
        
    // Check if Command to refresh/set Counter
    } else if (cmd >= count || cmd < -1) {  
    
        // New or refreshed counter value
        logInfo("HVAC_HW.rules", "...Command {} received. Set Counter to same",cmd)
        if (cmd < -1) {  
            // Force override
			cmd = 0 - cmd  
            logInfo("HVAC_HW.rules", "...Command={} so forcing override",cmd)
    	}

        // We still update even if equal value - resets expire binding
	    logInfo("HVAC_HW.rules", "...Counter reset to {} using Command val", cmd)
        i_HVAC_HW_Counter.postUpdate(cmd)  
		
        // Do startup/continue actions when HW not on.
		if (i_HVAC_HW_Switch.state != ON) {
            logInfo("HVAC_HW.rules", "...Command {} received when HW off so turning ON")
            i_HVAC_HW_Switch.sendCommand(ON)
		}

    // Test if Command 0 received to stop Counter early.
	} else if (cmd == 0) {  

        // Command 0 received so interrupt countdown and turn off HW
        logInfo("HVAC_HW.rules", "...Command 0 received")
        //if (i_HVAC_HW_Switch.state != OFF) {
            // Force HW OFF
        logInfo("HVAC_HW.rules", "...Post 0 to Counter")
        i_HVAC_HW_Counter.postUpdate(0)
        //}
	} else if (count == 0) {

        // Expired. Turn off HW
        logInfo("HVAC_HW.rules", "...EXPIRED. Request HW Off")
        i_HVAC_HW_Switch.sendCommand(OFF)
    }

    // End of timer tick
    logInfo("HVAC_HW.rules", "COUNTER TICK - End")
end

rule 
    // HW turned off
    "HVAC_HW_Off"
when
    Item i_HVAC_HW_Switch changed to OFF
then
    logInfo("HVAC_HW.rules", "HW Switch OFF event received")
    if (i_HVAC_HW_Counter.state != 0) { 
        
        logInfo("HVAC_HW.rules", "User set HW to Off. Stop Counter")
        // Reset counter to Zero.
        // The "Tick" event will be fired that will request HW OFF.
        // However, we have already set HW to OFF above so this "changed to OFF" event will not fire.
        i_HVAC_HW_Counter.sendCommand(0)
    }
end

```

## sitemap

```csv
Switch item=i_HVAC_HW_Switch label="Hot water On/Off"
Text item=i_HVAC_HW_Counter label="Hot water off in [%d minutes]" icon="clock-on"	visibility=[i_HVAC_HW_Switch == ON]

```
