[SOLVED] Dimmer Rule with exec Binding

AWESOME. Its working now…but way to fast. I think you wanted to show me that :slight_smile:

plusSeconds not plusMillis

                timer.reschedule(now.plusSeconds(timeoutSecs)) // reschedule timer like a loop

Now, you need to go through the code line by line.
I advise you to save it somewhere.
The delete the rule and copy it, line by line. Don’t copy and paste.
Understand the code.

1 Like

I’m on it :slight_smile:

This is my rules for Sunrise (vice versa):

val int timeoutSecs = 9 // 9 seconds for 15 minutes
var int dimLevel = 100 // Start from 100
var Timer timer = null // Initialise timer to null

rule "Slowly Dim Down"
when
    Item GPIO1 changed to ON
then
    if (timer === null) { // If there is no timer
        logInfo("TIMER", "Starting dimmer loop")
        timer = createTimer(now.plusSeconds(0), [ |   //Starts immediately
            if (dimLevel == 0) { //If we have reached 0
                timer = null // cancel timer
            } else {
                dimLevel = dimLevel - 1 // Decrease dimLevel by 1
                val int pwmValue = ((dimLevel * 1024) / 100).intValue // Scale dimLevel from 0-100 to 0-1024
                val commandString = "gpio pwm 1 " + pwmValue // Create command String
                logInfo("LOOP Command Line: ", commandString)
                executeCommandLine(commandString) // Execute command String
                timer.reschedule(now.plusSeconds(timeoutSecs)) // reschedule timer like a loop
            }
        ])
    }
end

PWM signal 1024 is the lowest dimming value so I need to start with dimLevel 100.

OK I have a problem now.
The 2nd rules dont start. Just when I restart openhab it will. This are the 2 rules:

val int timeoutSecs = 9 // 9 seconds for 15 minutes

var int dimLevel = 0 // Start from 0

var Timer timer = null // Initialise timer to null

rule "Slowly Dim Up"

when

    Item DUMMY changed to ON

then

    if (timer === null) { // If there is no timer

        logInfo("TIMER", "Starting dimmer loop")

        timer = createTimer(now.plusSeconds(0), [ |   //Starts immediately

            if (dimLevel == 100) { //If we have reached 100

                timer = null // cancel timer

            } else {

                dimLevel = dimLevel +1 // Increase dimLevel by 1

                val int pwmValue = ((dimLevel * 1024) / 100).intValue // Scale $

                val commandString = "gpio pwm 1 " + pwmValue // Create command $

                logInfo("LOOP Command Line: ", commandString)

                executeCommandLine(commandString) // Execute command String

                timer.reschedule(now.plusSeconds(timeoutSecs)) // reschedule ti$

            }

        ])

    }

end

and

val int timeoutSecs = 9 // 9 seconds for 15 minutes

var int dimLevel = 100 // Start from 100

var Timer timer = null // Initialise timer to null



rule "Slowly Dim Up"

when

    Item GPIO4 changed to ON

then

    if (timer === null) { // If there is no timer

        logInfo("TIMER", "Starting dimmer loop")

        timer = createTimer(now.plusSeconds(0), [ |   //Starts immediately

            if (dimLevel == 0) { //If we have reached 0

                timer = null // cancel timer

            } else {

                dimLevel = dimLevel -1 // Decrease dimLevel by 1

                val int pwmValue = ((dimLevel * 1024) / 100).intValue // Scale $

                val commandString = "gpio pwm 1 " + pwmValue // Create command $

                logInfo("LOOP Command Line: ", commandString)

                executeCommandLine(commandString) // Execute command String

                timer.reschedule(now.plusSeconds(timeoutSecs)) // reschedule ti$

            }

        ])

    }

end




So if rule 1 got executed, rule 2 will not start and vice versa. Looks like I need a command in each rules to stop it.

Rules must have unique names. The last rule to load with the same name “wins”.

1 Like

Ah damn. That was too easy :smiley:
Thank you :slight_smile:

OK I changed the name but it still doesn’t work.
It starts with “Starting dimmer loop” but doesn’t execute the “GPIO PWM” commands. When I restart openhab and trigger GPIO4 again it works fine.
Any ideas?

It’s not clear if you have also “unique-ified” the global variable names, like dimlevel.

Okay, so it gets into a rule. Which one? Edit your logInfos somehow so that you can tell.
If it doesn’t run the loop, what does it do instead? We could add a logInfo into the “final exit” part and see if we go straight to that.

But really - assuming you have looked in openhab.log for execution errors - we can guess it must have gone that way. How could that happen? Suspect if (dimlevel is not giving the result we expect.

OK first thing I found in the logs is a wrong loop. “sun rise” is going down to 399 PWM and then it jumps down to 40 - 30 - 20 - 10 - 0 and this several time

2019-01-27 11:08:41.055 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 409'
2019-01-27 11:08:50.071 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 399
2019-01-27 11:08:50.079 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 399'
2019-01-27 11:14:06.002 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 40
2019-01-27 11:14:06.009 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 40'
2019-01-27 11:14:15.027 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 30
2019-01-27 11:14:15.035 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 30'
2019-01-27 11:14:24.051 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 20
2019-01-27 11:14:24.058 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 20'
2019-01-27 11:14:33.077 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 10
2019-01-27 11:14:33.085 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 10'
2019-01-27 11:14:42.106 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 0
2019-01-27 11:14:42.113 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 0'
2019-01-27 11:14:06.002 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 40
2019-01-27 11:14:06.009 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 40'
2019-01-27 11:14:15.027 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 30
2019-01-27 11:14:15.035 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 30'
2019-01-27 11:14:24.051 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 20
2019-01-27 11:14:24.058 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 20'
2019-01-27 11:14:33.077 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 10
2019-01-27 11:14:33.085 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 10'
2019-01-27 11:14:42.106 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 0
2019-01-27 11:14:42.113 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 0'
2019-01-27 11:14:06.002 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 40
2019-01-27 11:14:06.009 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 40'
2019-01-27 11:14:15.027 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 30
2019-01-27 11:14:15.035 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 30'
2019-01-27 11:14:24.051 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 20
2019-01-27 11:14:24.058 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 20'
2019-01-27 11:14:33.077 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 10
2019-01-27 11:14:33.085 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 10'
2019-01-27 11:14:42.106 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 0
2019-01-27 11:14:42.113 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 0'
2019-01-27 11:14:06.002 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 40
2019-01-27 11:14:06.009 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 40'
2019-01-27 11:14:15.027 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 30
2019-01-27 11:14:15.035 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 30'
2019-01-27 11:14:24.051 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 20
2019-01-27 11:14:24.058 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 20'
2019-01-27 11:14:33.077 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 10
2019-01-27 11:14:33.085 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 10'
2019-01-27 11:14:42.106 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 0
2019-01-27 11:14:42.113 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 0'
2019-01-27 11:14:06.002 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 40
2019-01-27 11:14:06.009 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 40'
2019-01-27 11:14:15.027 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 30
2019-01-27 11:14:15.035 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 30'
2019-01-27 11:14:24.051 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 20
2019-01-27 11:14:24.058 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 20'
2019-01-27 11:14:33.077 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 10
2019-01-27 11:14:33.085 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 10'
2019-01-27 11:14:42.106 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 0
2019-01-27 11:14:42.113 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 0'
2019-01-27 11:14:06.002 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 40
2019-01-27 11:14:06.009 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 40'
2019-01-27 11:14:15.027 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 30
2019-01-27 11:14:15.035 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 30'
2019-01-27 11:14:24.051 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 20
2019-01-27 11:14:24.058 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 20'
2019-01-27 11:14:33.077 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 10
2019-01-27 11:14:33.085 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 10'
2019-01-27 11:14:42.106 [INFO ] [ome.model.script.LOOP Command Line: ] - gpio pwm 1 0
2019-01-27 11:14:42.113 [INFO ] [lipse.smarthome.io.net.exec.ExecUtil] - executed commandLine 'gpio pwm 1 0'

Furthermore the logs yesterday for the sunset was fine. It started at pwm 0 and increased in 10th steps to 1024.

So rule sunrise -> sunset worked
sunset -> sunrise didn’t work. Needed to restart openhab to trigger it manually and then it worked with some strange errors (log above).

Here are the two rules again (may has some changes)

sunrise:

val int timeoutSecs = 9 // 9 seconds for 15 minutes
var int dimLevel = 100 // Start from 100
var Timer timer = null // Initialise timer to null

rule "Slowly Dim Up"

when

    Item GPIO4 changed to ON

then

    if (timer === null) { // If there is no timer
        logInfo("TIMER", "Starting dimmer loop")
        timer = createTimer(now.plusSeconds(0), [ |   //Starts immediately
            if (dimLevel == 0) { //If we have reached 0
                timer = null // cancel timer
            } else {
                dimLevel = dimLevel -1 // Decrease dimLevel by 1
                val int pwmValue = ((dimLevel * 1024) / 100).intValue // Scale dimLevel from 0-100 to 0-1024
                val commandString = "gpio pwm 1 " + pwmValue // Create command String
                logInfo("LOOP Command Line: ", commandString)
                executeCommandLine(commandString) // Execute command String
                timer.reschedule(now.plusSeconds(timeoutSecs)) // reschedule timer like a loop
            }
        ])
    }
end

Sunset

val int timeoutSecs = 9 // 9 seconds for 15 minutes
var int dimLevel = 0 // Start from 0
var Timer timer = null // Initialise timer to null

rule "Slowly Dim Down"

when

    Item DUMMY changed to ON

then

    if (timer === null) { // If there is no timer
        logInfo("TIMER", "Starting dimmer loop")
        timer = createTimer(now.plusSeconds(0), [ |   //Starts immediately
            if (dimLevel == 100) { //If we have reached 100
                timer = null // cancel timer
            } else {
                dimLevel = dimLevel +1 // Increase dimLevel by 1
                val int pwmValue = ((dimLevel * 1024) / 100).intValue // Scale dimLevel from 0-100 to 0-1024
                val commandString = "gpio pwm 1 " + pwmValue // Create command String
                logInfo("LOOP Command Line: ", commandString)
                executeCommandLine(commandString) // Execute command String
                timer.reschedule(now.plusSeconds(timeoutSecs)) // reschedule timer like a loop
            }
        ])
    }
end

No one an idea?

You seem to have missed the comment about global variables.
You cannot, in the same rules file, create a global variable dimlevel which is both 100 and 0.
I would have expected this to generate errors in openhab.log actually.

You can share the timer and timeoutSecs globals, but you should create them only once.
Personally, I would give timer a more unique name to avoid confusion some other time.

So I should use “dimLevel” and maybe “dimmingLevel”?
Same with timer?

It’s up to you.

Thinking about it a bit more, you’re not going to want both rules to run at the same time. Having a shared global timer should stop that happening, so that’s probably a good thing.
I would give it a different name so that you don’t write another rule later also using ‘timer’ and get unexpected happenings.

Regarding dimlevel - if we make sure the rules only run one at a time, you could actually use the same global variable. Only define it with var once, of course.
But when you define it as a global, it only gets set to its initial vale when the rules file loads. When the rules run, they will alter it.

So before entering your timer loop in each rule, set the dimlevel to whatever is needed, 0 or 100

Quick question, are these two rules in separate files?

Yes, they are.

OK - I’m trying to understand it :wink:
So I don’t need a dimLevel in each rule because the level is set by the rules befor. If I use “Timer” for both timer, both timer will run in the background, right? So I could try this rules:

val int timeoutSecs = 9 // 9 seconds for 15 minutes
var int dimLevel = 100 // Start from 100
var Timer_Up timer = null // Initialise timer to null

rule "Slowly Dim Up"

when

    Item GPIO4 changed to ON

then

    if (timer === null) { // If there is no timer
        logInfo("TIMER", "Starting dimmer loop")
        timer = createTimer(now.plusSeconds(0), [ |   //Starts immediately
            if (dimLevel == 0) { //If we have reached 0
                timer = null // cancel timer
            } else {
                dimLevel = dimLevel -1 // Decrease dimLevel by 1
                val int pwmValue = ((dimLevel * 1024) / 100).intValue // Scale dimLevel from 0-100 to 0-1024
                val commandString = "gpio pwm 1 " + pwmValue // Create command String
                logInfo("LOOP Command Line: ", commandString)
                executeCommandLine(commandString) // Execute command String
                timer.reschedule(now.plusSeconds(timeoutSecs)) // reschedule timer like a loop
            }
        ])
    }
end

val int timeoutSecs = 9 // 9 seconds for 15 minutes
var Timer_Down timer = null // Initialise timer to null

rule "Slowly Dim Down"

when

    Item DUMMY changed to ON

then

    if (timer === null) { // If there is no timer
        logInfo("TIMER", "Starting dimmer loop")
        timer = createTimer(now.plusSeconds(0), [ |   //Starts immediately
            if (dimLevel == 100) { //If we have reached 100
                timer = null // cancel timer
            } else {
                dimLevel = dimLevel +1 // Increase dimLevel by 1
                val int pwmValue = ((dimLevel * 1024) / 100).intValue // Scale dimLevel from 0-100 to 0-1024
                val commandString = "gpio pwm 1 " + pwmValue // Create command String
                logInfo("LOOP Command Line: ", commandString)
                executeCommandLine(commandString) // Execute command String
                timer.reschedule(now.plusSeconds(timeoutSecs)) // reschedule timer like a loop
            }
        ])
    }
end

I’m on a good way? :smiley:

Maybe if I offer a briefing on so called “global variables

If you define a variable with var or val inside a rule, it only exists within that rule and is effectively created each time the rule runs and destroyed when it ends.

If instead you define it outside of any rule, we call it global because it can be shared by any rules in that rules file.
It’s a useful way for one rule to alter something that another rule can read later.
Or for all rules to share some common value, like a timeout.

Good practice is to define any globals at the top of your rules file, before any actual rules.
Pretty obviously, each global has to have a unique name.

If you assign an initial value,
var myGlobal = 22
that value will be given to the variable when the rules file loads.
But if any rules alter the value, it stays altered and dos not revert to that initial value (until next time you boot or edit the rules file).

So if var or val inside a rule only operate in this rule I dont need to change the name.
Wait - lets start again? Whats the different between global variable an the variable who operate only inside of one rule?
Is this global:

val int timeoutSecs = 9 // 9 seconds for 15 minutes
var int dimLevel = 100 // Start from 100
var Timer_Up timer = null // Initialise timer to null

rule "Slowly Dim Up"

and this not:

rule "Slowly Dim Up"

val int timeoutSecs = 9 // 9 seconds for 15 minutes
var int dimLevel = 100 // Start from 100
var Timer_Up timer = null // Initialise timer to null

?

You got it