One function for "ON/OFF", "long press" and "double press"

I’m reading the status of a button via serial port and getting an update when button is pressed and another when button is released.
I wand to implement the functions:

  1. “short press”: just switch ON/OFF light
  2. “long press”: dimmer the light till 0 or 100 (if light is already ON decrease, if light is OFF increase intensity)
  3. “double press”: change light color to next theme (no clue how to do this in code)

I’m not sure if this can be generally be made at all but I started with rules and would need help on them. Where reading a lot already in forum but just find parts of this requirement.

To be able to reuse this function for a lot of buttons I have I put the stuff inside a function.

I added a lot of logging entries for better debugging.

Any help is very welcome. This these are functions often needed. Will publish the solution for others. So please help.

val org.eclipse.xtext.xbase.lib.Functions$Function2<SwitchItem, DimmerItem, Void> lightButtonDimmerTimer = [
    SwitchItem button,
    DimmerItem light |
        val longPressDuration = 300     // min time button to press to be recognized as "long press"
        val doublePressDuration = 300   // time within button needs to be pressed twice to be "double press"
        val fadingStepTime = 200        // time between to fading changes
        var fadingStep = 10             // fading steps
        var Timer fade_Timer = null     // timer for fadeing

        logInfo("lightButtonDimmerTimer logging", "start rule")

        var percent = (light.state as DecimalType).intValue
        logInfo("lightButtonDimmerTimer logging", "current light percent: "+percent)

        // check if we need to fade IN our OUT
        var fadeIn = light.state < 100
        logInfo("loggerttonDimmerTimer loggingName", "fadeIn: "+fadeIn)

        // inverse fadeing if needed (fadeOut)
        if (!fadeIn) fadingStep *= -1 
        logInfo("loggerttonDimmerTimer loggingName", "fadingStep: "+fadingStep)

        logInfo("loggerttonDimmerTimer loggingName", "button.state: "+button.state)
        if (button.state == ON) {
            logInfo("loggerttonDimmerTimer loggingName", "button pressed: "+button.state)

            fade_Timer = createTimer(now.plusMillis(longPressDuration)) [|
                logInfo("loggerttonDimmerTimer loggingName", "inside timer, percent: "+percent)
                if (percent >= 0 && percent <= 100) {
                    light.sendCommand(percent)
                    percent += fadingStep
                    logInfo("loggerttonDimmerTimer loggingName", "change percent to: "+percent)
                    fade_Timer.reschedule(now.plusMillis(fadingStepTime))
                    logInfo("loggerttonDimmerTimer loggingName", "rescheduled timer: "+fadingStepTime)
                }
            ]
        } else {
            logInfo("loggerttonDimmerTimer loggingName", "button released: "+button.state)

            // cancel timer if needed (from "long press")
            if (fade_Timer?.isRunning()) {
                fade_Timer.cancel
                fade_Timer = null
                logInfo("loggerttonDimmerTimer loggingName", "canceled timer")
            } else {
                logInfo("loggerttonDimmerTimer loggingName", "no running timer. short pressed. just switch power")
                if (light.state > 0) {
                    light.sendCommand(OFF)
                } else {
                    light.sendCommand(ON)
                }
            }
        }
    ]   

rule "kitchen light button 1"
when
    Item kitchenSwitch1Button1 changed
then
    lightButtonDimmerTimer.apply(kitchenSwitch1Button1, Light_GF_Office_Brightness)
end

log entries during “short press”. System is fadeing but should only switch ON or OFF.

2019-03-02 23:14:10.115 [vent.ItemStateChangedEvent] - serialsT1 changed from » to »
2019-03-02 23:14:10.165 [vent.ItemStateChangedEvent] - kitchenSwitch1Light1 changed from 0 to 100

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:14:10.245 [INFO ] [thome.model.script.rule check values] - command: BB0101
2019-03-02 23:14:10.250 [INFO ] [ome.model.script.rule checker values] - button1 pressed

==> /var/log/openhab2/events.log <==

2019-03-02 23:14:10.263 [vent.ItemStateChangedEvent] - kitchenSwitch1Button1 changed from OFF to ON
2019-03-02 23:14:10.266 [vent.ItemStateChangedEvent] - serialsT1 changed from » to »

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:14:11.862 [INFO ] [cript.lightButtonDimmerTimer logging] - start rule
2019-03-02 23:14:11.876 [INFO ] [cript.lightButtonDimmerTimer logging] - current light percent: 100
2019-03-02 23:14:11.891 [INFO ] [pt.loggerttonDimmerTimer loggingName] - fadeIn: false
2019-03-02 23:14:11.910 [INFO ] [pt.loggerttonDimmerTimer loggingName] - fadingStep: -10
2019-03-02 23:14:11.922 [INFO ] [pt.loggerttonDimmerTimer loggingName] - button.state: ON
2019-03-02 23:14:11.943 [INFO ] [pt.loggerttonDimmerTimer loggingName] - button pressed: ON
2019-03-02 23:14:12.006 [INFO ] [thome.model.script.rule check values] - command: BB0100
2019-03-02 23:14:12.010 [INFO ] [ome.model.script.rule checker values] - button1 released

==> /var/log/openhab2/events.log <==

2019-03-02 23:14:12.022 [vent.ItemStateChangedEvent] - kitchenSwitch1Button1 changed from ON to OFF

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:14:12.039 [INFO ] [cript.lightButtonDimmerTimer logging] - start rule
2019-03-02 23:14:12.047 [INFO ] [cript.lightButtonDimmerTimer logging] - current light percent: 100
2019-03-02 23:14:12.054 [INFO ] [pt.loggerttonDimmerTimer loggingName] - fadeIn: false
2019-03-02 23:14:12.064 [INFO ] [pt.loggerttonDimmerTimer loggingName] - fadingStep: -10
2019-03-02 23:14:12.069 [INFO ] [pt.loggerttonDimmerTimer loggingName] - button.state: OFF
2019-03-02 23:14:12.076 [INFO ] [pt.loggerttonDimmerTimer loggingName] - button released: OFF
2019-03-02 23:14:12.081 [INFO ] [pt.loggerttonDimmerTimer loggingName] - no running timer. short pressed. just switch power

==> /var/log/openhab2/events.log <==

2019-03-02 23:14:12.092 [ome.event.ItemCommandEvent] - Item 'Light_GF_Office_Brightness' received command OFF
2019-03-02 23:14:12.102 [nt.ItemStatePredictedEvent] - Light_GF_Office_Brightness predicted to become OFF
2019-03-02 23:14:12.106 [vent.ItemStateChangedEvent] - Light_GF_Office_Brightness changed from 100 to 0
2019-03-02 23:14:12.171 [vent.ItemStateChangedEvent] - Light_GF_Office_Alert changed from NONE to SELECT

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:14:12.250 [INFO ] [pt.loggerttonDimmerTimer loggingName] - inside timer, percent: 100

==> /var/log/openhab2/events.log <==

2019-03-02 23:14:12.264 [ome.event.ItemCommandEvent] - Item 'Light_GF_Office_Brightness' received command 100
2019-03-02 23:14:12.270 [nt.ItemStatePredictedEvent] - Light_GF_Office_Brightness predicted to become 100
2019-03-02 23:14:12.281 [vent.ItemStateChangedEvent] - Light_GF_Office_Brightness changed from 0 to 100

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:14:12.281 [INFO ] [pt.loggerttonDimmerTimer loggingName] - change percent to: 90
2019-03-02 23:14:12.297 [INFO ] [pt.loggerttonDimmerTimer loggingName] - rescheduled timer: 200
2019-03-02 23:14:12.494 [INFO ] [pt.loggerttonDimmerTimer loggingName] - inside timer, percent: 90
2019-03-02 23:14:12.508 [INFO ] [pt.loggerttonDimmerTimer loggingName] - change percent to: 80

==> /var/log/openhab2/events.log <==

2019-03-02 23:14:12.517 [ome.event.ItemCommandEvent] - Item 'Light_GF_Office_Brightness' received command 90

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:14:12.518 [INFO ] [pt.loggerttonDimmerTimer loggingName] - rescheduled timer: 200

==> /var/log/openhab2/events.log <==

2019-03-02 23:14:12.524 [nt.ItemStatePredictedEvent] - Light_GF_Office_Brightness predicted to become 90
2019-03-02 23:14:12.535 [vent.ItemStateChangedEvent] - Light_GF_Office_Brightness changed from 100 to 90

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:14:12.717 [INFO ] [pt.loggerttonDimmerTimer loggingName] - inside timer, percent: 80

==> /var/log/openhab2/events.log <==

2019-03-02 23:14:12.740 [ome.event.ItemCommandEvent] - Item 'Light_GF_Office_Brightness' received command 80
2019-03-02 23:14:12.749 [nt.ItemStatePredictedEvent] - Light_GF_Office_Brightness predicted to become 80

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:14:12.757 [INFO ] [pt.loggerttonDimmerTimer loggingName] - change percent to: 70
2019-03-02 23:14:12.776 [INFO ] [pt.loggerttonDimmerTimer loggingName] - rescheduled timer: 200

==> /var/log/openhab2/events.log <==

2019-03-02 23:14:12.784 [vent.ItemStateChangedEvent] - Light_GF_Office_Brightness changed from 90 to 80

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:14:12.970 [INFO ] [pt.loggerttonDimmerTimer loggingName] - inside timer, percent: 70

==> /var/log/openhab2/events.log <==

2019-03-02 23:14:12.982 [ome.event.ItemCommandEvent] - Item 'Light_GF_Office_Brightness' received command 70

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:14:12.986 [INFO ] [pt.loggerttonDimmerTimer loggingName] - change percent to: 60

==> /var/log/openhab2/events.log <==

2019-03-02 23:14:12.991 [nt.ItemStatePredictedEvent] - Light_GF_Office_Brightness predicted to become 70

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:14:13.001 [INFO ] [pt.loggerttonDimmerTimer loggingName] - rescheduled timer: 200

==> /var/log/openhab2/events.log <==

2019-03-02 23:14:13.001 [vent.ItemStateChangedEvent] - Light_GF_Office_Brightness changed from 80 to 70

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:14:13.197 [INFO ] [pt.loggerttonDimmerTimer loggingName] - inside timer, percent: 60

==> /var/log/openhab2/events.log <==

2019-03-02 23:14:13.210 [ome.event.ItemCommandEvent] - Item 'Light_GF_Office_Brightness' received command 60

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:14:13.214 [INFO ] [pt.loggerttonDimmerTimer loggingName] - change percent to: 50

==> /var/log/openhab2/events.log <==

2019-03-02 23:14:13.224 [nt.ItemStatePredictedEvent] - Light_GF_Office_Brightness predicted to become 60

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:14:13.226 [INFO ] [pt.loggerttonDimmerTimer loggingName] - rescheduled timer: 200

==> /var/log/openhab2/events.log <==

2019-03-02 23:14:13.235 [vent.ItemStateChangedEvent] - Light_GF_Office_Brightness changed from 70 to 60

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:14:13.421 [INFO ] [pt.loggerttonDimmerTimer loggingName] - inside timer, percent: 50
2019-03-02 23:14:13.441 [INFO ] [pt.loggerttonDimmerTimer loggingName] - change percent to: 40
2019-03-02 23:14:13.451 [INFO ] [pt.loggerttonDimmerTimer loggingName] - rescheduled timer: 200

==> /var/log/openhab2/events.log <==

2019-03-02 23:14:13.451 [ome.event.ItemCommandEvent] - Item 'Light_GF_Office_Brightness' received command 50
2019-03-02 23:14:13.455 [nt.ItemStatePredictedEvent] - Light_GF_Office_Brightness predicted to become 50
2019-03-02 23:14:13.468 [vent.ItemStateChangedEvent] - Light_GF_Office_Brightness changed from 60 to 50

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:14:13.650 [INFO ] [pt.loggerttonDimmerTimer loggingName] - inside timer, percent: 40
2019-03-02 23:14:13.682 [INFO ] [pt.loggerttonDimmerTimer loggingName] - change percent to: 30

==> /var/log/openhab2/events.log <==

2019-03-02 23:14:13.686 [ome.event.ItemCommandEvent] - Item 'Light_GF_Office_Brightness' received command 40
2019-03-02 23:14:13.693 [nt.ItemStatePredictedEvent] - Light_GF_Office_Brightness predicted to become 40

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:14:13.711 [INFO ] [pt.loggerttonDimmerTimer loggingName] - rescheduled timer: 200

==> /var/log/openhab2/events.log <==

2019-03-02 23:14:13.717 [vent.ItemStateChangedEvent] - Light_GF_Office_Brightness changed from 50 to 40

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:14:13.889 [INFO ] [pt.loggerttonDimmerTimer loggingName] - inside timer, percent: 30

==> /var/log/openhab2/events.log <==

2019-03-02 23:14:13.901 [ome.event.ItemCommandEvent] - Item 'Light_GF_Office_Brightness' received command 30

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:14:13.908 [INFO ] [pt.loggerttonDimmerTimer loggingName] - change percent to: 20

==> /var/log/openhab2/events.log <==

2019-03-02 23:14:13.908 [nt.ItemStatePredictedEvent] - Light_GF_Office_Brightness predicted to become 30

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:14:13.919 [INFO ] [pt.loggerttonDimmerTimer loggingName] - rescheduled timer: 200

==> /var/log/openhab2/events.log <==

2019-03-02 23:14:13.922 [vent.ItemStateChangedEvent] - Light_GF_Office_Brightness changed from 40 to 30

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:14:14.116 [INFO ] [pt.loggerttonDimmerTimer loggingName] - inside timer, percent: 20
2019-03-02 23:14:14.135 [INFO ] [pt.loggerttonDimmerTimer loggingName] - change percent to: 10
2019-03-02 23:14:14.143 [INFO ] [pt.loggerttonDimmerTimer loggingName] - rescheduled timer: 200

==> /var/log/openhab2/events.log <==

2019-03-02 23:14:14.148 [ome.event.ItemCommandEvent] - Item 'Light_GF_Office_Brightness' received command 20
2019-03-02 23:14:14.152 [nt.ItemStatePredictedEvent] - Light_GF_Office_Brightness predicted to become 20
2019-03-02 23:14:14.162 [vent.ItemStateChangedEvent] - Light_GF_Office_Brightness changed from 30 to 20

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:14:14.341 [INFO ] [pt.loggerttonDimmerTimer loggingName] - inside timer, percent: 10
2019-03-02 23:14:14.353 [INFO ] [pt.loggerttonDimmerTimer loggingName] - change percent to: 0

==> /var/log/openhab2/events.log <==

2019-03-02 23:14:14.359 [ome.event.ItemCommandEvent] - Item 'Light_GF_Office_Brightness' received command 10

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:14:14.363 [INFO ] [pt.loggerttonDimmerTimer loggingName] - rescheduled timer: 200

==> /var/log/openhab2/events.log <==

2019-03-02 23:14:14.367 [nt.ItemStatePredictedEvent] - Light_GF_Office_Brightness predicted to become 10
2019-03-02 23:14:14.382 [vent.ItemStateChangedEvent] - Light_GF_Office_Brightness changed from 20 to 10

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:14:14.563 [INFO ] [pt.loggerttonDimmerTimer loggingName] - inside timer, percent: 0

==> /var/log/openhab2/events.log <==

2019-03-02 23:14:14.581 [ome.event.ItemCommandEvent] - Item 'Light_GF_Office_Brightness' received command 0

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:14:14.585 [INFO ] [pt.loggerttonDimmerTimer loggingName] - change percent to: -10
2019-03-02 23:14:14.598 [INFO ] [pt.loggerttonDimmerTimer loggingName] - rescheduled timer: 200

==> /var/log/openhab2/events.log <==

2019-03-02 23:14:14.603 [nt.ItemStatePredictedEvent] - Light_GF_Office_Brightness predicted to become 0
2019-03-02 23:14:14.616 [vent.ItemStateChangedEvent] - Light_GF_Office_Brightness changed from 10 to 0

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:14:14.792 [INFO ] [pt.loggerttonDimmerTimer loggingName] - inside timer, percent: -10

==> /var/log/openhab2/events.log <==

2019-03-02 23:14:17.282 [vent.ItemStateChangedEvent] - Light_GF_Office_Alert changed from SELECT to NONE

log entries during “long press”. System is fadeing but as soon as button is released light goes OFF. Also fading should stop when button is released

2019-03-02 23:22:13.861 [vent.ItemStateChangedEvent] - serialsT1 changed from » to »

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:22:13.999 [INFO ] [thome.model.script.rule check values] - command: BB0101
2019-03-02 23:22:14.003 [INFO ] [ome.model.script.rule checker values] - button1 pressed

==> /var/log/openhab2/events.log <==

2019-03-02 23:22:14.020 [vent.ItemStateChangedEvent] - kitchenSwitch1Button1 changed from OFF to ON

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:22:14.043 [INFO ] [cript.lightButtonDimmerTimer logging] - start rule
2019-03-02 23:22:14.052 [INFO ] [cript.lightButtonDimmerTimer logging] - current light percent: 0
2019-03-02 23:22:14.061 [INFO ] [pt.loggerttonDimmerTimer loggingName] - fadeIn: true
2019-03-02 23:22:14.068 [INFO ] [pt.loggerttonDimmerTimer loggingName] - fadingStep: 10
2019-03-02 23:22:14.075 [INFO ] [pt.loggerttonDimmerTimer loggingName] - button.state: ON
2019-03-02 23:22:14.085 [INFO ] [pt.loggerttonDimmerTimer loggingName] - button pressed: ON

==> /var/log/openhab2/events.log <==

2019-03-02 23:22:14.358 [vent.ItemStateChangedEvent] - kitchenSwitch1Light1 changed from 100 to 0

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:22:14.392 [INFO ] [pt.loggerttonDimmerTimer loggingName] - inside timer, percent: 0

==> /var/log/openhab2/events.log <==

2019-03-02 23:22:14.407 [ome.event.ItemCommandEvent] - Item 'Light_GF_Office_Brightness' received command 0

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:22:14.412 [INFO ] [pt.loggerttonDimmerTimer loggingName] - change percent to: 10

==> /var/log/openhab2/events.log <==

2019-03-02 23:22:14.417 [nt.ItemStatePredictedEvent] - Light_GF_Office_Brightness predicted to become 0

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:22:14.424 [INFO ] [pt.loggerttonDimmerTimer loggingName] - rescheduled timer: 200
2019-03-02 23:22:14.619 [INFO ] [pt.loggerttonDimmerTimer loggingName] - inside timer, percent: 10
2019-03-02 23:22:14.644 [INFO ] [pt.loggerttonDimmerTimer loggingName] - change percent to: 20

==> /var/log/openhab2/events.log <==

2019-03-02 23:22:14.646 [ome.event.ItemCommandEvent] - Item 'Light_GF_Office_Brightness' received command 10
2019-03-02 23:22:14.650 [nt.ItemStatePredictedEvent] - Light_GF_Office_Brightness predicted to become 10

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:22:14.663 [INFO ] [pt.loggerttonDimmerTimer loggingName] - rescheduled timer: 200

==> /var/log/openhab2/events.log <==

2019-03-02 23:22:14.668 [vent.ItemStateChangedEvent] - Light_GF_Office_Brightness changed from 0 to 10

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:22:14.852 [INFO ] [pt.loggerttonDimmerTimer loggingName] - inside timer, percent: 20
2019-03-02 23:22:14.871 [INFO ] [pt.loggerttonDimmerTimer loggingName] - change percent to: 30

==> /var/log/openhab2/events.log <==

2019-03-02 23:22:14.874 [ome.event.ItemCommandEvent] - Item 'Light_GF_Office_Brightness' received command 20
2019-03-02 23:22:14.876 [nt.ItemStatePredictedEvent] - Light_GF_Office_Brightness predicted to become 20

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:22:14.881 [INFO ] [pt.loggerttonDimmerTimer loggingName] - rescheduled timer: 200

==> /var/log/openhab2/events.log <==

2019-03-02 23:22:14.888 [vent.ItemStateChangedEvent] - Light_GF_Office_Brightness changed from 10 to 20

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:22:15.077 [INFO ] [pt.loggerttonDimmerTimer loggingName] - inside timer, percent: 30

==> /var/log/openhab2/events.log <==

2019-03-02 23:22:15.093 [ome.event.ItemCommandEvent] - Item 'Light_GF_Office_Brightness' received command 30

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:22:15.093 [INFO ] [pt.loggerttonDimmerTimer loggingName] - change percent to: 40

==> /var/log/openhab2/events.log <==

2019-03-02 23:22:15.102 [nt.ItemStatePredictedEvent] - Light_GF_Office_Brightness predicted to become 30

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:22:15.107 [INFO ] [pt.loggerttonDimmerTimer loggingName] - rescheduled timer: 200

==> /var/log/openhab2/events.log <==

2019-03-02 23:22:15.113 [vent.ItemStateChangedEvent] - Light_GF_Office_Brightness changed from 20 to 30

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:22:15.300 [INFO ] [pt.loggerttonDimmerTimer loggingName] - inside timer, percent: 40

==> /var/log/openhab2/events.log <==

2019-03-02 23:22:15.312 [ome.event.ItemCommandEvent] - Item 'Light_GF_Office_Brightness' received command 40

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:22:15.317 [INFO ] [pt.loggerttonDimmerTimer loggingName] - change percent to: 50

==> /var/log/openhab2/events.log <==

2019-03-02 23:22:15.322 [nt.ItemStatePredictedEvent] - Light_GF_Office_Brightness predicted to become 40

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:22:15.328 [INFO ] [pt.loggerttonDimmerTimer loggingName] - rescheduled timer: 200

==> /var/log/openhab2/events.log <==

2019-03-02 23:22:15.333 [vent.ItemStateChangedEvent] - Light_GF_Office_Brightness changed from 30 to 40
2019-03-02 23:22:15.517 [vent.ItemStateChangedEvent] - Light_GF_Office_Alert changed from NONE to SELECT

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:22:15.527 [INFO ] [pt.loggerttonDimmerTimer loggingName] - inside timer, percent: 50

==> /var/log/openhab2/events.log <==

2019-03-02 23:22:15.548 [ome.event.ItemCommandEvent] - Item 'Light_GF_Office_Brightness' received command 50

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:22:15.560 [INFO ] [pt.loggerttonDimmerTimer loggingName] - change percent to: 60

==> /var/log/openhab2/events.log <==

2019-03-02 23:22:15.571 [nt.ItemStatePredictedEvent] - Light_GF_Office_Brightness predicted to become 50

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:22:15.575 [INFO ] [pt.loggerttonDimmerTimer loggingName] - rescheduled timer: 200

==> /var/log/openhab2/events.log <==

2019-03-02 23:22:15.614 [vent.ItemStateChangedEvent] - Light_GF_Office_Brightness changed from 40 to 50

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:22:15.767 [INFO ] [pt.loggerttonDimmerTimer loggingName] - inside timer, percent: 60

==> /var/log/openhab2/events.log <==

2019-03-02 23:22:15.784 [ome.event.ItemCommandEvent] - Item 'Light_GF_Office_Brightness' received command 60
2019-03-02 23:22:15.786 [nt.ItemStatePredictedEvent] - Light_GF_Office_Brightness predicted to become 60

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:22:15.792 [INFO ] [pt.loggerttonDimmerTimer loggingName] - change percent to: 70

==> /var/log/openhab2/events.log <==

2019-03-02 23:22:15.797 [vent.ItemStateChangedEvent] - Light_GF_Office_Brightness changed from 50 to 60

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:22:15.803 [INFO ] [pt.loggerttonDimmerTimer loggingName] - rescheduled timer: 200
2019-03-02 23:22:16.000 [INFO ] [pt.loggerttonDimmerTimer loggingName] - inside timer, percent: 70
2019-03-02 23:22:16.015 [INFO ] [pt.loggerttonDimmerTimer loggingName] - change percent to: 80

==> /var/log/openhab2/events.log <==

2019-03-02 23:22:16.019 [ome.event.ItemCommandEvent] - Item 'Light_GF_Office_Brightness' received command 70

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:22:16.026 [INFO ] [pt.loggerttonDimmerTimer loggingName] - rescheduled timer: 200

==> /var/log/openhab2/events.log <==

2019-03-02 23:22:16.026 [nt.ItemStatePredictedEvent] - Light_GF_Office_Brightness predicted to become 70
2019-03-02 23:22:16.033 [vent.ItemStateChangedEvent] - Light_GF_Office_Brightness changed from 60 to 70

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:22:16.222 [INFO ] [pt.loggerttonDimmerTimer loggingName] - inside timer, percent: 80

==> /var/log/openhab2/events.log <==

2019-03-02 23:22:16.240 [ome.event.ItemCommandEvent] - Item 'Light_GF_Office_Brightness' received command 80
2019-03-02 23:22:16.244 [nt.ItemStatePredictedEvent] - Light_GF_Office_Brightness predicted to become 80

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:22:16.245 [INFO ] [pt.loggerttonDimmerTimer loggingName] - change percent to: 90

==> /var/log/openhab2/events.log <==

2019-03-02 23:22:16.252 [vent.ItemStateChangedEvent] - Light_GF_Office_Brightness changed from 70 to 80

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:22:16.258 [INFO ] [pt.loggerttonDimmerTimer loggingName] - rescheduled timer: 200
2019-03-02 23:22:16.453 [INFO ] [pt.loggerttonDimmerTimer loggingName] - inside timer, percent: 90

==> /var/log/openhab2/events.log <==

2019-03-02 23:22:16.476 [ome.event.ItemCommandEvent] - Item 'Light_GF_Office_Brightness' received command 90
2019-03-02 23:22:16.483 [nt.ItemStatePredictedEvent] - Light_GF_Office_Brightness predicted to become 90
2019-03-02 23:22:16.497 [vent.ItemStateChangedEvent] - Light_GF_Office_Brightness changed from 80 to 90

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:22:16.503 [INFO ] [pt.loggerttonDimmerTimer loggingName] - change percent to: 100
2019-03-02 23:22:16.525 [INFO ] [pt.loggerttonDimmerTimer loggingName] - rescheduled timer: 200
2019-03-02 23:22:16.712 [INFO ] [pt.loggerttonDimmerTimer loggingName] - inside timer, percent: 100
2019-03-02 23:22:16.726 [INFO ] [pt.loggerttonDimmerTimer loggingName] - change percent to: 110

==> /var/log/openhab2/events.log <==

2019-03-02 23:22:16.731 [ome.event.ItemCommandEvent] - Item 'Light_GF_Office_Brightness' received command 100
2019-03-02 23:22:16.735 [nt.ItemStatePredictedEvent] - Light_GF_Office_Brightness predicted to become 100

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:22:16.749 [INFO ] [pt.loggerttonDimmerTimer loggingName] - rescheduled timer: 200

==> /var/log/openhab2/events.log <==

2019-03-02 23:22:16.749 [vent.ItemStateChangedEvent] - Light_GF_Office_Brightness changed from 90 to 100

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:22:16.932 [INFO ] [pt.loggerttonDimmerTimer loggingName] - inside timer, percent: 110

==> /var/log/openhab2/events.log <==

2019-03-02 23:22:19.081 [vent.ItemStateChangedEvent] - serialsT1 changed from » to »

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:22:19.209 [INFO ] [thome.model.script.rule check values] - command: BB0100
2019-03-02 23:22:19.214 [INFO ] [ome.model.script.rule checker values] - button1 released

==> /var/log/openhab2/events.log <==

2019-03-02 23:22:19.247 [vent.ItemStateChangedEvent] - kitchenSwitch1Button1 changed from ON to OFF

==> /var/log/openhab2/openhab.log <==

2019-03-02 23:22:19.257 [INFO ] [cript.lightButtonDimmerTimer logging] - start rule
2019-03-02 23:22:19.265 [INFO ] [cript.lightButtonDimmerTimer logging] - current light percent: 100
2019-03-02 23:22:19.271 [INFO ] [pt.loggerttonDimmerTimer loggingName] - fadeIn: false
2019-03-02 23:22:19.281 [INFO ] [pt.loggerttonDimmerTimer loggingName] - fadingStep: -10
2019-03-02 23:22:19.286 [INFO ] [pt.loggerttonDimmerTimer loggingName] - button.state: OFF
2019-03-02 23:22:19.297 [INFO ] [pt.loggerttonDimmerTimer loggingName] - button released: OFF
2019-03-02 23:22:19.302 [INFO ] [pt.loggerttonDimmerTimer loggingName] - no running timer. short pressed. just switch power

==> /var/log/openhab2/events.log <==

2019-03-02 23:22:19.318 [ome.event.ItemCommandEvent] - Item 'Light_GF_Office_Brightness' received command OFF
2019-03-02 23:22:19.325 [nt.ItemStatePredictedEvent] - Light_GF_Office_Brightness predicted to become OFF
2019-03-02 23:22:19.330 [vent.ItemStateChangedEvent] - Light_GF_Office_Brightness changed from 100 to 0

It would be even better to use a Group and the Member of trigger and triggeringItem and then you can have one Rule to process all buttons.

See the associated items design pattern for examples.

A better syntax is

val lightButtonDimmer = [ SwitchItem button, DimmerItem light |

I’m really happy to see the use of a looping timer instead of a while loop with a sleep.

Great post!

Reason why it is not working as expected is the timer. It is defined inside the method call. So the variable gets initialised with NULL each time the method gets called. So when ON it gets set to a timer. But when ON that variable is no longer present (because new method call). It starts at the top of the method and therefore is NULL again and does not get set to a timer (because that was done in the last method call).

So best way would be to somehow store this outside of the method. Maybe in a map?

Second Problem seems to be in fade_Timer?.isRunning(). From what I read here that means that the code is being executed. The code is executed within milliseconds. while it is scheduled, it is not running.
So the logic here seems flawed.

This one here should work correctly:

import java.util.Map

val Map<String, Timer> timers = newHashMap()
val Map<String, Long> timerStartTimes = newHashMap()
val lightButtonDimmerTimer = [ SwitchItem button, DimmerItem light, Map<String, Timer> timers, Map<String, Long> timerStartTimes |
        val longPressDuration = 300     // min time button to press to be recognized as "long press"
        val doublePressDuration = 300   // time within button needs to be pressed twice to be "double press"
        val fadingStepTime = 200        // time between to fading changes
        var fadingStep = 10             // fading steps
        val String timerId = button.getUID() + "|||" + light.getUID()

        logInfo("lightButtonDimmerTimer logging", "start rule")
        logInfo("lightButtonDimmerTimer logging", "button id " + button.getUID())
        logInfo("lightButtonDimmerTimer logging", "light id " + light.getUID())

        var percent = (light.state as DecimalType).intValue
        logInfo("lightButtonDimmerTimer logging", "current light percent: "+percent)

        // check if we need to fade IN our OUT
        var fadeIn = light.state < 100
        logInfo("loggerttonDimmerTimer loggingName", "fadeIn: "+fadeIn)

        // inverse fadeing if needed (fadeOut)
        if (!fadeIn) fadingStep *= -1 
        logInfo("loggerttonDimmerTimer loggingName", "fadingStep: "+fadingStep)

        logInfo("loggerttonDimmerTimer loggingName", "button.state: "+button.state)
        if (button.state == ON) {
            logInfo("loggerttonDimmerTimer loggingName", "button pressed: "+button.state)

            val Timer fade_Timer = null
            fade_Timer = createTimer(now.plusMillis(longPressDuration)) [|
                logInfo("loggerttonDimmerTimer loggingName", "inside timer, percent: "+percent)
                if (percent >= 0 && percent <= 100) {
                    light.sendCommand(percent)
                    percent += fadingStep
                    logInfo("loggerttonDimmerTimer loggingName", "change percent to: "+percent)
                    fade_Timer.reschedule(now.plusMillis(fadingStepTime))
                    logInfo("loggerttonDimmerTimer loggingName", "rescheduled timer: "+fadingStepTime)
                }
            ]
            timers.put(timerId, fade_Timer)
            timerStartTimes.put(timerId, now.getMillis())
        } else {
            logInfo("loggerttonDimmerTimer loggingName", "button released: "+button.state)
            val fade_Timer = timers.remove(timerId)
            fade_Timer?.cancel() // needs to be canceled in any case

            val clickDuration = now.getMillis() - timerStartTimes.remove(timerId)
            logInfo("loggerttonDimmerTimer loggingName", "click duration = " + clickDuration + "ms")
            if (clickDuration < longPressDuration) {
                logInfo("loggerttonDimmerTimer loggingName", "short pressed. switch power")
                if (light.state > 0) {
                    light.sendCommand(OFF)
                } else {
                    light.sendCommand(ON)
                }
            }
        }
    ]
1 Like

If you implement it as a single Role instead of a lambda you can use global variables or a Map of variables. If you stick to the lambda, your only choice is to use a global Map and pass it as an argument to the lambda.

Typically what we do is use null to indicate whether a timer is scheduled or not. Initialize fade_timer to null. Where ever you cancel the timer set fade_timer to null. And there last thing the timer body does is set fade_timer to null. Then you can test to see if fade_timer === null to know whether they’re is a timer set.

Continuing the discussion from One function for "ON/OFF", "long press" and "double press":

Hello,
Сould you explain how to properly call this function from a rule?

1 Like

Skull

I just got it running with minor modifications. Added a few comments for me since I am new to java.

Now working on double click to change scenes/color

.rules

import java.util.Map

// val = define value
// var = define variable
// Map<String, Timer> = Hashmap of datatype Timer with locator datatype String
// timersMap = name of Hashmap

// Example of Hashmaps(arrays):
//    val Map<String, String> articleMapOne = newHashMap()
//    articleMapOne.put("ar01", "Intro to Map")
//    articleMapOne.put("ar02", "Some article")

val Map<String, Timer> timersMap = newHashMap()
val Map<String, Long> timerStartTimesMap = newHashMap()

// Method definition: val Name = [type name, type name, ... | code]
val lightButtonDimmerTimer = [ SwitchItem button, DimmerItem light, Map<String, Timer> timersMap, Map<String, Long> timerStartTimesMap |

    val longPressDuration = 300     // min time button to press to be recognized as "long press"
    val doublePressDuration = 300   // time within button needs to be pressed twice to be "double press"
    val fadingStepTime = 250        // time between to fading changes
    var fadingStep = 5              // fading steps
    

    val String timerId = button.getUID() + "|" + light.getUID()   // Create unique timer id
    var percent = (light.state as DecimalType).intValue             // get curent status

    var fadeIn = light.state < 100                                  // if max. brightness change direction
    if (!fadeIn) fadingStep *= -1

    logInfo("rules.DimmerTimer", "timerId: '" + timerId + "' ## button.state: "+button.state+" ## current percent: "+percent+" ## fadingStep: "+fadingStep)

    if (button.state == OPEN) {
        var Timer fade_Timer = null // define timer

        Timer fade_Timer = createTimer(now.plusMillis(longPressDuration)) [| // Call timer [| code to be executed when timer done ]
            if (percent >= 0 && percent <= 100) {
                light.sendCommand(percent)
                percent += fadingStep
                logInfo("rules.DimmerTimer", "long pressed - change percent to: "+percent)
                fade_Timer.reschedule(now.plusMillis(fadingStepTime)) // add more time to timer
            }
        ]
        timersMap.put(timerId, fade_Timer)                  // Save timer in hashmap
        timerStartTimesMap.put(timerId, now.getMillis())
    }
    else if (button.state == CLOSED) {
        val fade_Timer = timersMap.remove(timerId)
        fade_Timer.cancel() // needs to be canceled in any case

        val clickDuration = now.getMillis() - timerStartTimesMap.remove(timerId)
        logInfo("rules.DimmerTimer.released", "click duration = "+clickDuration+" ms")
        if (clickDuration < longPressDuration) {
            logInfo("rules.DimmerTimer.released", "short pressed. switch power")
            if (light.state > 0) {
                light.sendCommand(OFF)
            } else {
                light.sendCommand(ON)
            }
        }
    }
            
]

rule "Test"
when
    Item TestButtonItem changed
then
    lightButtonDimmerTimer.apply(TestButtonItem, DimmerItem, timersMap, timerStartTimesMap)
end

Could one not also use the pie programmed " profile" function.

Raw-button-dimmer i believe it is called?