An OH3 rule based alternative to OH2 global timer variable

Hey Folks,

I have no pride of authorship and open to your solutions and improvements to these rules. This first post will have a door notification set of rules. I’ll post different iterations of these rules as I finish them on my OH3 installation.

Notes are in the code.

Rule 1:
Template Door Trigger V2

triggers:
  - id: "1"
    configuration:
      itemName: ChangeMeDoor
    type: core.ItemStateChangeTrigger
conditions: []
actions:
  - inputs: {}
    id: "2"
    configuration:
      type: application/vnd.openhab.dsl.rule
      script: >-
        /*--------------- 

        The intent for these rules is to alert the administrator if a door is left open for a period of time. i.e. Your kids don’t close the garage freezer door all the way when getting a popsicle. I use Notepad ++ as an editor and find and replace to set the rule to any particular item. 

        ChangeMeTimer - Serves as what was a global timer variable in on OH2. Set the value of the timer to whatever suites your situation. I use 5 minutes for the refrigerator / freezer doors. Maybe you want a different period of time for another door. Like a notification if the garage is open for more than X period of time. 

        ChangeMeCounter – One limiting issue with the timer is that it could loop continuously unless the trigger is resolved. While it is useful to know that there is an issue with the door open, it may not be feasible to act on it immediately and you don’t want a repeating notification every 5 minutes. The timer allows the administrator to limit the number of times an alert is issued.

        ChangeMeSwitch – Serves as the trigger for the counter and cancel rules. 

        ------------Find and Replace the following-----------

        --Description—

        Template (provide a text description for logging) i.e. Freezer Door

        --Existing Item--

        ChangeMeDoor

        --New Items--

        Switch ChangeMeSwitch "Template switch V2" [AlertTemplate]  

        Switch ChangeMeCounter "Template counter V2" [AlertTemplate]    

        Number ChangeMeTimer "Template timer V2" [AlertTemplate]

        --Rules--

        Template Door Trigger V2 – Required to set the monitored item in the state of alert or normal

        Template Door Timer w/Counter V2 – Required notify the administrator of the item state

        Template Door Cancel V2 – Optional if the administrator wants notification of the item state as resolved

        ----------------*/

        val door = ChangeMeDoor.state

        logInfo("Template Trigger V2 Rule","Started. Door is " + door)

        if ((door == "OPEN") && (ChangeMeSwitch.state == OFF) || (ChangeMeSwitch.state == NULL)


        {
          logInfo("Template Trigger V2 Rule","Initialized. Door is " + door)
          sendCommand(ChangeMeSwitch, ON)
          ChangeMeCounter.postUpdate(3) //This value needs to correlate with the ChangeMeCounter trigger item in the ruel Template Door Timer w/Counter V2
          //Do something here if you want to be notified immediately. Warning.. You may not want to be notified every time the door is open.
        }


        if ((door == "CLOSED") && (ChangeMeSwitch.state == ON) || (ChangeMeSwitch.state == NULL)) //!= in case switch is null


        {
          logInfo("Template Trigger V2 Rule","No trigger initialized. All is ok. Door is " + door)
          sendCommand(ChangeMeSwitch, OFF)
          createTimer(now.plusSeconds(5), 
          [|
            ChangeMeCounter.postUpdate(0) //delayed so that the rule Template Door Cancel V2 is not triggered if you don't want an immediate notifiation.
          ])
        }
    type: script.ScriptAction

Rule 2:
Template Door Timer w/Counter V2

triggers:
  - id: "2"
    configuration:
      itemName: ChangeMeSwitch
      command: ON
    type: core.ItemCommandTrigger
  - id: "3"
    configuration:
      itemName: ChangeMeTimer
      command: ON
    type: core.ItemCommandTrigger
conditions: []
actions:
  - inputs: {}
    id: "1"
    configuration:
      type: application/vnd.openhab.dsl.rule
      script: >-
        if ((ChangeMeCounter.state > 0) && (ChangeMeSwitch.state == ON))


        {
          logInfo("Template Timer V2 Rule", "Initialized.")
            createTimer(now.plusMinutes(5),
            //createTimer(now.plusSeconds(15), //For testing
            [|
            var Number varCount = ChangeMeCounter.state as DecimalType
            val door = ChangeMeDoor.state
            if (varCount != 0)
             {
              if (varCount == 3)
              {
                varCount = varCount - 1
                logInfo("Template Timer V2 Rule","Counter initialized. Current varCount is at " + varCount)
                ChangeMeCounter.postUpdate(varCount)
                sendCommand(ChangeMeTimer, ON)
               //Do something after the first timer has cycled. i.e. the door has now been open for 5 minutes.
              }
              else
              {
              if (varCount == 1)
                {
                varCount = varCount - 1
                logInfo("Template Timer V2 Rule","Counter This is the last notification. Current varCount is at " + varCount)
                ChangeMeCounter.postUpdate(varCount)
                sendCommand(ChangeMeTimer, ON)
                //Do if you want to be notified the trigger items is not resolved and this is the last notification.
                }
                else
                {           
                varCount = varCount - 1
                logInfo("Template Timer V2 Rule","Counter repeating. Current varCount is at " + varCount)
                ChangeMeCounter.postUpdate(varCount)
                sendCommand(ChangeMeTimer, ON)
                //Do if you want to be reminded each time the timer cycles
                }
              }    
            }
            ])
        } 


        else


        {


        ChangeMeCounter.postUpdate(0)


        logInfo("Template Timer V2 Rule","Counter complete.")


        }

    type: script.ScriptAction

Rule 3: Optional
Template Door Cancel V2

triggers:
  - id: "1"
    configuration:
      itemName: ChangeMeSwitch
      state: OFF
      previousState: ON
    type: core.ItemStateChangeTrigger
conditions:
  - inputs: {}
    id: "3"
    configuration:
      itemName: ChangeMeCounter
      state: "3"
      operator: "!="
    type: core.ItemStateCondition
actions:
  - inputs: {}
    id: "2"
    configuration:
      type: application/vnd.openhab.dsl.rule
      script: >-
        val door = ChangeMeDoor.state

        logInfo("Template Cancel V2 Rule","Resolved. Door is " + door) 


        //Do something here if you want confirmation that the trigger item is resolved.
    type: script.ScriptAction

You should consider posting these as Rule Templates in the Marketplace. Then all the “find and replace” stuff gets handled via configuration parameters.

There are some things that can be done to improve this code and one potential problem.

First the problem. Your Rule 2 can be triggered by a command sent to ChangeMeSwitch. The command is received and processed by the rule prior to the ChangeMeSwitch Item’s state updating and potentially changing. So if the rule is triggered by a command ON being sent to ChangeMeSwitch, it’s going to be just the luck of timing whether ChangeMeSwitch.state == ON will be true or not. Given this is checked as the first line of the rule, on a fast machine, ChangeMeSwitch.state will almost always still be OFF (assuming it changed from ON to OFF). The update in response to the command will still be processing and won’t have happened yet.

Unfortunately this is a hard problem to deal with in this situation. Ultimately I think it will invalidate the whole approach since you are using ON commands to ChangeMeSwitch and ChangeMeSwitch’s state. And you have two Items that can trigger this rule which means that the you can’t rely on received command. About the only solutions I can guess at are to:

  • don’t test that ChangeMeSwitch.state == ON. If the rule is triggered we assume that it’s OK to process the event
  • add yet another Item that will be ON when the rule is allowed to run and check for the state of that Item instead
  • go back to a looping Timer (note a looping timer is no more or less likely to run forever than this implementation if you use the same criteria used here to determine whether or not to continue the loop
  • move to JavaScript which has a way to preserve the values of some variables from one rule to the next.

Assuming the first option is acceptable, even though it might slightly change the behavior of the rule (i.e. if ChangeMeTimer receives an ON command, which actually doesn’t make sense given what you described this Item does) the rule will trigger no matter what state ChangeMeSwitch is in I also recommend the following changes to the second rule to make it shorter and easier to maintain.

var timerTime = 5 // maybe this is supposed to be ChangeMeTimer.state.intValue()?
var count = 3 // provide one easy place up top to change parameters, also helps with templates
       
logInfo("Template Timer V2 Rule", "Initialized.") // consider making debug
if ((ChangeMeCounter.state > 0))  {
    createTimer(now.plusMinutes(timerTime), [|
        // If it doesn't change, use a val instead of var
        // Don't over specify the type unless absolutely necessary
        // Avoid the use of DecimalType in favor of Number
        val varCount = ChangeMeCounter.state as Number 
        val door = ChangeMeDoor.state // This isn't actually used anywhere, shouldn't it be considered when deciding to continue?
        // Still iterating
        if(varCount > 0) {
            // This Item is always updated with the count decremented, just do it once up front
            ChangeMeCounter.postUpdate(varCount-1)
            // As long as count > 0 we always sendCommand ON, do it just once up front, use the method on the Item, not the sendCommand(item, state) Action
            ChangeMeTimer.sendCommand(ON)

            // First run
            if(varCount == count){
                logInfo("Template Timer V2 Rule", "Counter initialized. Current varCount is at " + varCount )
                // stuff to do on first run
            }
            // Last run
            else if(varCount == 1) {
                logInfo("Template Timer V2 Rule","Counter This is the last notification. Current varCount is at " + varCount)
            }
            // intermediate run
           else {
               logInfo("Template Timer V2 Rule", "Counter This is the last notification. Current varCount is at " + varCount)
           }
        }
    ])
}
// Done iterating
else {
    ChangeMeCounter.postUpdate(0) // this line is probably redundant since we already know it's 0 at this point
    logInfo("Template Timer V2 Rule","Counter complete.")
}

I’ve tested and this is working.

Rule : Template Door Trigger V2.1
Checking the state of ChangeMeSwitch is likely more complex than needed for ChangeMeDoor (door).

if ((door == “OPEN”) && (ChangeMeSwitch.state == OFF) || (ChangeMeSwitch.state == NULL)

And could be written as

if (door == “OPEN”)

Checking the state of ChangeMeSwitch is necessary for an item such as ChangeMeTemp (temperature) where the temperature value could be updating and still be less than a certain threshold.

if ((temp > 28) && (ChangeMeSwitch.state == OFF) || (ChangeMeSwitch.state == NULL))

At this point Template Door Trigger V2 is “triggered” every time the monitored item is updated and

In alert state, will set ChangeMeSwitch to ON and set ChangeMeCounter to X to initiate the Template Door Timer w/Counter V2 rule loop.

In normal state, will set ChangeMeSwitch to OFF and set ChangeMeCounter to 0 to cancel the Template Door Timer w/Counter V2 rule loop.

Added a timer to compensate for the update of a state

createTimer(now.plusSeconds(3), 
[|
//timer for potential delay in update state by software
])

Added a variable for the loop count

var count = 3 // provide one easy place up top to change parameters, also helps with templates

Here’s the script.

/*--------------- 
The intent for these rules is to alert the administrator if a door is left open for a period of time. i.e. Your kids don’t close the garage freezer door all the way when getting a popsicle. I use Notepad ++ as an editor and find and replace to set the rule to any particular item. 
ChangeMeTimer - Serves as what was a global timer variable in on OH2. Set the value of the timer to whatever suites your situation. I use 5 minutes for the refrigerator / freezer doors. Maybe you want a different period of time for another door. Like a notification if the garage is open for more than X period of time. 
ChangeMeCounter – One limiting issue with the timer is that it could loop continuously unless the trigger is resolved. While it is useful to know that there is an issue with the door open, it may not be feasible to act on it immediately and you don’t want a repeating notification every 5 minutes. The timer allows the administrator to limit the number of times an alert is issued.
ChangeMeSwitch – Serves as the trigger for the counter and cancel rules. 
------------Find and Replace the following-----------
--Descriptoin—
Template (provide a text description for logging) i.e. Freezer Door
--Existing Item--
ChangeMeDoor
--New Items--
Switch ChangeMeSwitch "Template switch V2" [AlertTemplate]  
Switch ChangeMeCounter "Template counter V2" [AlertTemplate]    
Number ChangeMeTimer "Template timer V2" [AlertTemplate]
--Rules--
Template Door Trigger V2 – Required to set the monitored item in the state of alert or normal
Template Door Timer w/Counter V2 – Required notify the administrator of the item state
Template Door Cancel V2 – Optional if the administrator wants notification of the item state as resolved
----------------*/
val door = ChangeMeDoor.state
var count = 3 // provide one easy place up top to change parameters, also helps with templates
logInfo("Template Trigger V2 Rule","Started. Door is " + door)
createTimer(now.plusSeconds(3), 
[|
//timer for potential delay in update state by software
])
if ((door == "OPEN") && (ChangeMeSwitch.state == OFF) || (ChangeMeSwitch.state == NULL))

{
  logInfo("Template Trigger V2 Rule","Initialized. Door is " + door)
  sendCommand(ChangeMeSwitch, ON)
  ChangeMeCounter.postUpdate(count) //This value needs to correlate with the ChangeMeCounter trigger item in the rule Template Door Timer w/Counter V2
  //Do something here if you want to be notified immediately. Warning.. You may not want to be notified every time the door is open.
}

if ((door == "CLOSED") && (ChangeMeSwitch.state == ON) || (ChangeMeSwitch.state == NULL)) //!= in case switch is null

{
  logInfo("Template Trigger V2 Rule","No trigger initialized. All is ok. Door is " + door)
  sendCommand(ChangeMeSwitch, OFF)
  createTimer(now.plusSeconds(3), 
  [|
    ChangeMeCounter.postUpdate(0) //delayed so that the rule Template Door Cancel V2 is not triggered if you don't want an immediate notification.
  ])
}

Rule: Template Door Timer w/Counter V2.1

Updated with your code… Thank you.

var count = 3 is commented out. I get the following error.

Cannot refer to the non-final variable count inside a lambda expression; line 17, column 566, length 5

var timerDuration = 15 //Set the vaule of the time below
//var count = 3 commented out with error --Cannot refer to the non-final variable count inside a lambda expression; line 17, column 566, length 5 --

if ((ChangeMeCounter.state > 0))  
{
	logInfo("Template Timer V2 Rule", "Initialized.")
	//createTimer(now.plusMinutes(timerDuration),
	createTimer(now.plusSeconds(timerDuration), //For testing
	[|
		val Number varCount = ChangeMeCounter.state as Number 
		val door = ChangeMeDoor.state
		if(varCount > 0) 
		{
			// This Item is always updated with the count decremented, just do it once up front
			ChangeMeCounter.postUpdate(varCount - 1)
			ChangeMeTimer.sendCommand(ON)
			if(varCount == 3)
				{
				logInfo("Template Timer V2 Rule", "FIRST Loop action. Current varCount is at " + varCount )
				//do something here on the FIRST loop only.
				}
			else if(varCount == 1) 
				{
				//do something here on the LAST loop only. 
				logInfo("Template Timer V2 Rule","LAST Loop action. Current varCount is at " + varCount)
				}
		else 
		{
			//do something here every loop. 
			logInfo("Template Timer V2 Rule", "In between FIRST and LAST Loop action. Current varCount is at " + varCount)
		}
		}
	])
}

Change it from a var to a val. It never changes so should be a val anyway.

Note, most of the time that error can be ignored and the rule will work just fine. That’s a hold over from a previous version of the language. But in this case you can make it go away by making it final by using val.

Here is the current set of rules for the door alert. I’m going to start work on the temperature set next.

Rule: Template Door Trigger V2.1

  - id: "1"
    configuration:
      itemName: ChangeMeDoor
    type: core.ItemStateChangeTrigger
conditions: []
actions:
  - inputs: {}
    id: "2"
    configuration:
      type: application/vnd.openhab.dsl.rule
      script: >-
        /*--------------- 

        The intent for these rules is to alert the administrator if a door is left open for a period of time. i.e. Your kids don’t close the garage freezer door all the way when getting a popsicle. I use Notepad ++ as an editor and find and replace to set the rule to any particular item. 

        ChangeMeTimer - Serves as what was a global timer variable in on OH2. Set the value of the timer to whatever suites your situation. I use 5 minutes for the refrigerator / freezer doors. Maybe you want a different period of time for another door. Like a notification if the garage is open for more than X period of time. 

        ChangeMeCounter – One limiting issue with the timer is that it could loop continuously unless the trigger is resolved. While it is useful to know that there is an issue with the door open, it may not be feasible to act on it immediately and you don’t want a repeating notification every 5 minutes. The timer allows the administrator to limit the number of times an alert is issued.

        ChangeMeSwitch – Serves as the trigger for the counter and cancel rules. 

        ------------Find and Replace the following-----------

        --Description—

        Template (provide a text description for logging) i.e. Freezer Door

        --Existing Item--

        ChangeMeDoor

        --New Items--

        Switch ChangeMeSwitch "Template switch V2.1" [AlertTemplate]  

        Switch ChangeMeCounter "Template counter V2.1" [AlertTemplate]    

        Number ChangeMeTimer "Template timer V2.1" [AlertTemplate]

        --Rules--

        Template Door Trigger V2.1 – Required to set the monitored item in the state of alert or normal

        Template Door Timer w/Counter V2.1 – Required notify the administrator of the item state

        Template Door Cancel V2.1 – Optional if the administrator wants notification of the item state as resolved

        ----------------*/

        val door = ChangeMeDoor.state

        var count = 3 //Set the number of loops. This vaule need to match var count in Template Door Timer w/Counter V2.1 script and trigger item in  Template Door Cancel

        logInfo("Template Trigger V2.1 Rule","Started. Door is " + door)

        createTimer(now.plusSeconds(3), 

        [|

        //timer for potential delay in update state by software

        ])

        if ((door == "OPEN") && (ChangeMeSwitch.state == OFF) || (ChangeMeSwitch.state == NULL))


        {
          logInfo("Template Trigger V2.1 Rule","Initialized. Door is " + door)
          sendCommand(ChangeMeSwitch, ON)
          ChangeMeCounter.postUpdate(count) //This value needs to correlate with the ChangeMeCounter trigger item in the rule Template Door Timer w/Counter V2
          //Do something here if you want to be notified immediately. Warning.. You may not want to be notified every time the door is open.
        }


        if ((door == "CLOSED") && (ChangeMeSwitch.state == ON) || (ChangeMeSwitch.state == NULL)) //!= in case switch is null


        {
          logInfo("Template Trigger V2.1 Rule","No trigger initialized. All is ok. Door is " + door)
          sendCommand(ChangeMeSwitch, OFF)
          createTimer(now.plusSeconds(3), 
          [|
            ChangeMeCounter.postUpdate(0) //delayed so that the rule Template Door Cancel V2.1 is not triggered if you don't want an immediate notification.
          ])
        }
    type: script.ScriptAction

Rule: Template Door Timer w/Counter V2.1

  - id: "2"
    configuration:
      itemName: ChangeMeSwitch
      command: ON
    type: core.ItemCommandTrigger
  - id: "3"
    configuration:
      itemName: ChangeMeTimer
      command: ON
    type: core.ItemCommandTrigger
conditions: []
actions:
  - inputs: {}
    id: "1"
    configuration:
      type: application/vnd.openhab.dsl.rule
      script: >-
        var timerDuration = 5 //Set the duration of each loop. 

        val count = 3 //Set the number of loops. This vaule need to match var count in Template Door Trigger V2.1 script and trigger item in  Template Door Cancel
          
        if ((ChangeMeCounter.state > 0))  

        {
        	logInfo("Template Timer V2.1 Rule", "Initialized.")
        	createTimer(now.plusMinutes(timerDuration),
        	//createTimer(now.plusSeconds(timerDuration), //For testing
        	[|
        		val Number varCount = ChangeMeCounter.state as Number 
        		val door = ChangeMeDoor.state
        		if(varCount > 0) 
        		{
        			// This Item is always updated with the count decremented, just do it once up front
        			ChangeMeCounter.postUpdate(varCount - 1)
        			ChangeMeTimer.sendCommand(ON)
        			if(varCount == count)
        				{
        				logInfo("Template Timer V2.1 Rule", "FIRST Loop action. Current varCount is at " + varCount )
        				//do something here on the FIRST loop only.
        				}
        			else if(varCount == 1) 
        				{
        				//do something here on the LAST loop only. 
        				logInfo("Template Timer V2.1 Rule","LAST Loop action. Current varCount is at " + varCount)
        				}
        		else 
        		{
        			//do something here every loop. 
        			logInfo("Template Timer V2.1 Rule", "In between FIRST and LAST Loop action. Current varCount is at " + varCount)
        		}
        		}
        	])
        }
    type: script.ScriptAction

Rule: Template Door Cancel V2.1

  - id: "1"
    configuration:
      itemName: ChangeMeSwitch
      state: OFF
      previousState: ON
    type: core.ItemStateChangeTrigger
conditions:
  - inputs: {}
    id: "3"
    configuration:
      itemName: ChangeMeCounter
      state: "3"
      operator: "!="
    type: core.ItemStateCondition
actions:
  - inputs: {}
    id: "2"
    configuration:
      type: application/vnd.openhab.dsl.rule
      script: >-
        val door = ChangeMeDoor.state

        logInfo("Template Cancel V2.1 Rule","Resolved. Door is " + door)

        //Do something here if you want confirmation that the trigger item is resolved.
    type: script.ScriptAction

Template for temperature alerts

Template Temperature Trigger V2.1

triggers:
  - id: "1"
    configuration:
      itemName: ChangeMeTemp
    type: core.ItemStateChangeTrigger
conditions: []
actions:
  - inputs: {}
    id: "2"
    configuration:
      type: application/vnd.openhab.dsl.rule
      script: >-
        /*--------------- 

        The intent for these rules is to alert the administrator if a temperature over a maximum threshold for a period of time. i.e. Your kids don’t close the garage freezer temperature all the way when getting a popsicle. I use Notepad ++ as an editor and find and replace to set the rule to any particular item. 

        ChangeMeTimer - Serves as what was a global timer variable in on OH2. Set the value of the timer to whatever suites your situation. I use 20 minutes for the refrigerator / freezer temperature. Maybe you want a different period of time for another temperature. Like a notification if the refrigerator is over 40 degrees for more than X period of time. 

        ChangeMeCounter – One limiting issue with the timer is that it could loop continuously unless the trigger is resolved. While it is useful to know that there is an issue with the temperature, it may not be feasible to act on it immediately and you don’t want a repeating notification every 5 minutes. The timer allows the administrator to limit the number of times an alert is issued.

        ChangeMeSwitch – Serves as the trigger for the counter and cancel rules. 

        ------------Find and Replace the following-----------

        --Description—

        Template (provide a text description for logging) i.e. Freezer temperature

        --Existing Item--

        ChangeMeTemp

        --New Items--

        Switch ChangeMeSwitch "Template temperature switch V2.1" [AlertTemplate]  

        Switch ChangeMeCounter "Template temperature counter V2.1" [AlertTemplate]    

        Number ChangeMeTimer "Template temperature timer V2.1" [AlertTemplate]

        --Rules--

        Template Temperature Trigger V2.1 – Required to set the monitored item in the state of alert or normal

        Template Temperature Timer w/Counter V2.1 – Required notify the administrator of the item state

        Template Temperature Cancel V2.1 – Optional if the administrator wants notification of the item state as resolved

        ----------------*/

        val temp = ChangeMeTemp.state as Number

        var thresh = 28 //Threshold value for trigger

        var count = 3 //Set the number of loops. This vaule need to match var count in Garage Freezer Door Timer w/Counter V2.1 script and trigger item in  Garage Freezer Door Cancel

        logInfo("Template Trigger V2.1 Rule","Started. Temperature is " + temp)

        createTimer(now.plusSeconds(3), 

        [|

        //timer for potential delay in update state by software

        ])

        if ((temp > thresh) && (ChangeMeSwitch.state == OFF) || (ChangeMeSwitch.state == NULL))


        {
          logInfo("Template Trigger V2.1 Rule","Initialized. Temperature is " + temp)
          sendCommand(ChangeMeSwitch, ON)
          ChangeMeCounter.postUpdate(count) //This value needs to correlate with the ChangeMeCounter trigger item in the rule Template Temperature Timer w/Counter V2
          //Do something here if you want to be notified immediately. Warning.. You may not want to be notified every time the temperature of over the threshold.
        }


        if ((temp < thresh) && (ChangeMeSwitch.state == ON) || (ChangeMeSwitch.state == NULL)) //!= in case switch is null


        {
          logInfo("Template Trigger V2.1 Rule","No trigger initialized. All is ok. Temperature is " + temp)
          sendCommand(ChangeMeSwitch, OFF)
          createTimer(now.plusSeconds(3), 
          [|
            ChangeMeCounter.postUpdate(0) //delayed so that the rule Template Temperature Cancel V2.1 is not triggered if you don't want an immediate notification.
          ])
        }
    type: script.ScriptAction

Template Temperature Timer w/Counter V2.1

triggers:
  - id: "2"
    configuration:
      itemName: ChangeMeSwitch
      command: ON
    type: core.ItemCommandTrigger
  - id: "3"
    configuration:
      itemName: ChangeMeTimer
      command: ON
    type: core.ItemCommandTrigger
conditions: []
actions:
  - inputs: {}
    id: "1"
    configuration:
      type: application/vnd.openhab.dsl.rule
      script: >-
        var timerDuration = 20 //Set the duration of each loop. 

        val count = 3 //Set the number of loops. This vaule need to match var count in Template Temperature Trigger V2.1 script and trigger item in  Template Temperature Cancel
          
        if ((ChangeMeCounter.state > 0))  

        {
        	logInfo("Template Timer V2.1 Rule", "Initialized.")
        	createTimer(now.plusMinutes(timerDuration),
        	//createTimer(now.plusSeconds(timerDuration), //For testing
        	[|
        		val Number varCount = ChangeMeCounter.state as Number 
        		val temp = ChangeMeTemp.state
        		if(varCount > 0) 
        		{
        			// This Item is always updated with the count decremented, just do it once up front
        			ChangeMeCounter.postUpdate(varCount - 1)
        			ChangeMeTimer.sendCommand(ON)
        			if(varCount == count)
        				{
        				logInfo("Template Timer V2.1 Rule", "FIRST Loop action. Current varCount is at " + varCount )
        				//do something here on the FIRST loop only.
        				}
        			else if(varCount == 1) 
        				{
        				//do something here on the LAST loop only. 
        				logInfo("Template Timer V2.1 Rule","LAST Loop action. Current varCount is at " + varCount)
        				}
        		else 
        		{
        			//do something here every loop. 
        			logInfo("Template Timer V2.1 Rule", "In between FIRST and LAST Loop action. Current varCount is at " + varCount)
        		}
        		}
        	])
        }
    type: script.ScriptAction

Template Temperature Cancel V2.1

triggers:
  - id: "1"
    configuration:
      itemName: ChangeMeSwitch
      state: OFF
      previousState: ON
    type: core.ItemStateChangeTrigger
conditions:
  - inputs: {}
    id: "3"
    configuration:
      itemName: ChangeMeCounter
      state: "3"
      operator: "!="
    type: core.ItemStateCondition
actions:
  - inputs: {}
    id: "2"
    configuration:
      type: application/vnd.openhab.dsl.rule
      script: >-
        val temp = ChangeMeTemp.state

        logInfo("Template Cancel V2.1 Rule","Resolved. Temperature is " + temp)

        //Do something here if you want confirmation that the trigger item is resolved.
    type: script.ScriptAction

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.