Design Pattern: Switch & Dimmer

Hi, thanks for your ideas & comments. Well, I really like the idea of the design patterns and therefore I am happy I can contribute.

I am very new to openhab and therefore have to get around some aspects of the programming model for rules. With your hints I could rephrase the rules a bit, but it is not working, as I am experiencing errors around the Map (missing reference to Object) and functions “put & get” not being available.

Here is my current solution, that should toggle the :

val int globalDelayMillisForDimmer = 500
val Map<String, Timer> SwitchTimers = newHashMap
val Map<String, DateTime> SwitchTimestamps = newHashMap


val SwitchPressed = [ String id |
	logInfo("TMP", "SwitchPressed lambda called for " + id)
	SwitchTimestamps.put(id, now)

	// Start timer if switch is held down
	val offset = now.plusMillis(globalDelayMillisForDimmer)
	SwitchTimers.put(id, createTimer(offset, SwitchHeldDown.apply(id)))
]

val SwitchHeldDown = [ String id |
	logInfo("TMP", "SwitchHeldDown lambda called for " + id)

	// Handle long press
	sendCommand(id + "LongPress", ON)
	sendCommand(id + "LongPress", OFF)
	
	// Reschedule timer for this switch
	val offset = now.plusMillis(globalDelayMillisForDimmer)
	SwitchTimers.get(id)?.reschedule(offset)
]

val SwitchReleased = [ String id |
	logInfo("TMP", "SwitchRelease lambda called for " + id)
	
	// Deactivate the timer (if running)
	SwitchTimers.get(id)?.cancel()
	SwitchTimers.remove(id)

	// Get timestamp of switch pressed down
	var pressed = SwitchTimestamps.get(id)
	SwitchTimestamps.remove(id)

	// Handle short press
	val offset = pressed.plusMillis(globalDelayMillisForDimmer)
	if (offset.isBefore(now)) {
		sendCommand(id + "ShortPress", ON)
		sendCommand(id + "ShortPress", OFF)
	}
]

rule "temp1"
when
	Time cron "0 * * * * ?" or
	Time cron "20 * * * * ?" or
	Time cron "40 * * * * ?"
then
	SwitchPressed.apply("MySwitch1")
end

rule "temp2"
when
	Time cron "5 * * * * ?" or
	Time cron "25 * * * * ?" or
	Time cron "45 * * * * ?"
then
	SwitchReleased.apply("MySwitch1")
end

Maybe one has an idea to fix that Map issue, then I can continue on testing. If those lambdas are ready to go, i think the whole design pattern will be neat to use. :slight_smile:

My bad. You don’t have to import DateTime, but you do need to import java.util.Map.

I tried that already, but it still gives the following errors:

2019-02-07 19:43:25.015 [ERROR] [ntime.internal.engine.ExecuteRuleJob] - Error during the execution of rule 'temp2': cannot invoke method public abstract java.lang.Object java.util.Map.get(java.lang.Object) on null
2019-02-07 19:43:40.027 [ERROR] [ntime.internal.engine.ExecuteRuleJob] - Error during the execution of rule 'temp1': cannot invoke method public abstract java.lang.Object java.util.Map.put(java.lang.Object,java.lang.Object) on null

You have to pass the maps into the lambdas. Global lambdas do not have a context. They cannot see any other global vals or vars. You must pass them as arguments.

Ahh, ok, one needs to know that as well. :wink:

Then finally, I finished the sample, but I am still having one issue regarding the call of sendCommand(String, String):

import java.util.Map

val Map<String, Timer> Timers = newHashMap
val Map<String, DateTime> Timestamps = newHashMap


val SwitchPressed = [ Map<String, Timer> Timers, Map<String, DateTime> Timestamps, String id |
	logInfo("TMP", "SwitchPressed lambda called for " + id)
	Timestamps.put(id, now)

	// Start timer if switch is held down
	val offset = now.plusMillis(500)
	Timers.put(id, createTimer(offset, [|
		logInfo("TMP", "SwitchHeldDown lambda called for " + id)

		// Handle long press
		logInfo("TMP", "sendCommand(" + id + "LongPress, ON)")
		//sendCommand(id + "LongPress", ON)
		logInfo("TMP", "sendCommand(" + id + "LongPress, OFF)")
		//sendCommand(id + "LongPress", OFF)
	
		// Reschedule timer for this switch
		val offset = now.plusMillis(500)
		Timers.get(id)?.reschedule(offset)
	]))
]

val SwitchReleased = [ Map<String, Timer> Timers, Map<String, DateTime> Timestamps, String id |
	logInfo("TMP", "SwitchRelease lambda called for " + id)
	
	// Deactivate the timer (if running)
	Timers.get(id)?.cancel()
	Timers.remove(id)

	// Get timestamp of switch pressed down
	var pressed = Timestamps.get(id)
	Timestamps.remove(id)

	// Handle short press
	val offset = pressed?.plusMillis(500)
	if (now.isBefore(offset)) {
		logInfo("TMP", "sendCommand(" + id + "ShortPress, ON)")
		//sendCommand(id + "ShortPress", ON)
		logInfo("TMP", "sendCommand(" + id + "ShortPress, OFF)")
		////sendCommand(id + "ShortPress", OFF)
	}
]

rule "temp1"
when
	Time cron "0 * * * * ?" or
	Time cron "20 * * * * ?" or
	Time cron "40 * * * * ?"
then
	SwitchPressed.apply(Timers, Timestamps, "Switch1")
end

rule "temp2"
when
	Time cron "3 * * * * ?" or
	Time cron "23 * * * * ?" or
	Time cron "43 * * * * ?"
then
	SwitchReleased.apply(Timers, Timestamps, "Switch1")
end

rule "temp3"
when
	Time cron "10 * * * * ?" or
	Time cron "30 * * * * ?" or
	Time cron "50 * * * * ?"
then
	SwitchPressed.apply(Timers, Timestamps, "Switch1")
	SwitchReleased.apply(Timers, Timestamps, "Switch1")
end

When commenting those lines in, I get errors like:

java.lang.IllegalStateException: Could not invoke method: org.eclipse.smarthome.model.script.actions.BusEvent.sendCommand(java.lang.String,java.lang.String) on instance: null

For some reasons, it seems that the call for sendCommand within a lambda will fail. Could you give me another hint here? With that in place, you can images from the rules temp1-3 how this could be easily be used for all the Switch Items. :slight_smile:

Solved it, by changing to

sendCommand(id + "ShortPress", "ON")
// etc.

after reading your post at: sendCommand() Documentation :slight_smile:

Obvious, but I missed it, that the call clearly needs two Strings. :wink:

Updated the initial post and rules, plus added an application example for a dimmer switch.

4 Likes

Updated the example and introduced a stop for the rescheduler. So after 10 times, the long press action will stop to reschedule itself. This is due to the fact, that sometimes the RELEASE was not received by openhab and led to endless rescheduling. My bad. :slight_smile:

I’m going through all of the DP postings and posting at a minimum Python versions of the code. Here is a Python version of the above. I never used this DP so this code may contain some errors. Please let me know if you encounter any.

from org.joda.time import DateTime
from core.actions import ScriptExecution
from core.rules import rule
from core.triggers import when

timers = {}
timestamps = {}

def pressed_timer(id):
    events.sendCommand("{}LongPress".format(id), "ON")
    events.sendCommand("{}LongPress".format(id), "OFF")

    if DateTime.now().isBefore(timestamps[i].plusSeconds(5)):
        timers[id].reschedule(DateTime.now().plusMillis(500))

@rule("Switch1Events")
@when("Channel enocean:rockerSwitch:********:********:rockerswitchA triggered")
def switch1(event):

    direction = "Up" if event.event.startswith("DIR1") else "Down"

    # switch pressed
    if event.event.endswith("PRESSED"):
        id = "MySwitch1{}".format(direction)

        timestamps[id] = DateTime.now()
        events.sendCommand(id, "ON")

        timers[id] = ScriptExecution.createTimer(
            DateTime.now().plusMillis(500), 
            lambda: pressed_timer(id))

    # switch released
    else:
        id = "MySwitch1{}".format(direction)

        if id in timers:
            timers[id].cancel()
            del timers[id]

        pressed = timestamps[id]
        del timestamps[id]

        if DateTime.now().isBefore(pressed.plusMillis(500):
            events.sendCommand("{}ShortPress".format(id), "ON")
            events.sendCommand("{}ShortPress".format(id), "OFF")

        events.sendCommand(id, "OFF")

from core.rules import rule
from core.triggers import when

my_color_light_command = "INCREASE"

@rule("MyColorLight_OnOff")
@when("Item MySwitch1UpShortPress received command ON")
def mycolorlight_onoff(event):
    color = items["MyColorLight"]
    my_color_light_command = "DECREASE"
    cmd = "OFF"
    if color.brightness == PercentType(0):
        my_color_light_command = "INCREASE"
        cmd = ON
     events.sendCommand("MyColorLight", cmd)

@rule("MyColorLight_Dimmer")
@when("Item MySwitch1UplongPress received command ON")
def mycolorlight_dimmer(event):
    events.sendCommand("MySwitch1Light", my_color_light_command)

@rule("MyColorLight_CommandToggle"
@when("Item MySwitch1Up received command OFF")
def mycolorlight_toggle(event):
    my_color_light_command = "INCREASE" if my_color_light_command == "DECREASE" else "DECREASE"

I’ve tried the above scripts, but the could not be parsed correctly. Therefore, I remain on my versions. I am currently about to extend the behavior such that one can use it for the following scenarios:

  1. Use as regular switch (short press and long press: actionset1)
  2. Use as double switch (short press: actionset1, long press: actionset2)
  3. Use as Dimmer (short press: actionset1, long press: repeating actionset2)
  4. Use as Scenario Player (short press: enum iteration, long press: actionset2)
  5. Use as Scenario Player (short press: enum iteration, long press: repeating actionset2)

Examples for the use cases:

  1. Control a light (on/off), a power plug (on/off), or e.g. a setting for rules in openhab (activate/deactivate)
  2. Same as 1., but use the long press for another control, i.e. you have technically two switches combined in one. I like to use this for actions that I do not use that often, so that they do not block a switch permanently.
  3. Control a dimmable light (on/off, dim), might also be used for roller shutters to close the shutters as long as you push the button, but I have not tried that.
  4. Control scenarios, e.g. every click iterates over a list of scenarios and activates them accordingly. I use this for my living room having 3 presets defined (ambient light, watching movies, night light). In order to activate a scenario I have to click the switch once, twice or three times. I use the long press to switch the lights in that group alternating on or off.
  5. Same as 4 but instead of switching the lights on/off I use that as a dimmer for the light group.

Any further scenarios? :slight_smile:

Best bechte.

2 Likes

First Draft (still has an error):

import java.util.Map
import org.eclipse.smarthome.model.script.ScriptServiceUtil

val Map<String, Timer> Counters = newHashMap
val Map<String, Timer> Timers = newHashMap
val Map<String, DateTime> Timestamps = newHashMap

// ========================================================================= //

val incrementCounter = [ String id, int maxCount, boolean resetCounter, Map<String, Timer> Counters |
  val item = ScriptServiceUtil.getItemRegistry.getItem(id + "Count")
  val count = item.state as Number
  if (count >= maxCount) {
    postUpdate(id + "Count", 1)
  } else {
    postUpdate(id + "Count", count + 1)
  }

  if (resetCounter) {
    // Deactivate the timer (if running)
    Counters.get(id)?.cancel()
    Counters.remove(id)

    val offset = now.plusSeconds(10)
    Counters.put(id, createTimer(offset, [|
      postUpdate(id + "Count", 0)
    ]))
  }
]

// ========================================================================= //

val simpleSwitch = [ val receivedEvent, String id, int maxCount, boolean resetCounter, Map<String, Timer> Counters, Map<String, Timer> Timers, Map<String, DateTime> Timestamps |
  if (receivedEvent.event.endsWith("PRESSED")) {
    incrementCounter(id, maxCount, resetCounter, Counters)
    sendCommand(id, "ON")
  }
  if (receivedEvent.event.endsWith("RELEASED")) {
    sendCommand(id, "OFF")
  }
]

val doubleSwitch = [ val receivedEvent, String id, int maxCount, boolean resetCounter, Map<String, Timer> Counters, Map<String, Timer> Timers, Map<String, DateTime> Timestamps |
  if (receivedEvent.event.endsWith("PRESSED")) {
    Timestamps.put(id, now)
    sendCommand(id, "ON")
  }
  if (receivedEvent.event.endsWith("RELEASED")) {
    // Get timestamp of switch pressed down
    var pressed = Timestamps.get(id)
    Timestamps.remove(id)

    // Handle short or long press
    val offset = pressed?.plusMillis(700)
    if (now.isBefore(offset)) {
      incrementCounter(id, maxCount, resetCounter, Counters)
      sendCommand(id + "ShortPress", "ON")
      sendCommand(id + "ShortPress", "OFF")
    } else {
      sendCommand(id + "LongPress", "ON")
      sendCommand(id + "LongPress", "OFF")
    }
    sendCommand(id, "OFF")
  }
]

val dimmerSwitch = [ val receivedEvent, String id, int maxCount, boolean resetCounter, Map<String, Timer> Counters, Map<String, Timer> Timers, Map<String, DateTime> Timestamps |
  if (receivedEvent.event.endsWith("PRESSED")) {
    Timestamps.put(id, now)
    sendCommand(id, "ON")

    // Start timer if switch is held down
    val offset = now.plusMillis(700)
    Timers.put(id, createTimer(offset, [|
      // Handle long press
      sendCommand(id + "LongPress", "ON")
      sendCommand(id + "LongPress", "OFF")

      // Reschedule timer for this switch, but max. 10 times
      if (now.isBefore(Timestamps.get(id)?.plusSeconds(7))) {
        val offset = now.plusMillis(700)
        Timers.get(id)?.reschedule(offset)
      }
    ]))
  }
  if (receivedEvent.event.endsWith("RELEASED")) {
    // Deactivate the timer (if running)
    Timers.get(id)?.cancel()
    Timers.remove(id)
  
    // Get timestamp of switch pressed down
    var pressed = Timestamps.get(id)
    Timestamps.remove(id)

    // Handle short or long press
    val offset = pressed?.plusMillis(700)
    if (now.isBefore(offset)) {
      incrementCounter(id, maxCount, resetCounter, Counters)
      sendCommand(id + "ShortPress", "ON")
      sendCommand(id + "ShortPress", "OFF")
    }
    
    sendCommand(id, "OFF")
  }
]

// ========================================================================= //

rule "Configuration Button 1"
when
  Channel "enocean:rockerSwitch:FT1I6L57:0035FA61:rockerswitchA" triggered DIR1_PRESSED or
  Channel "enocean:rockerSwitch:FT1I6L57:0035FA61:rockerswitchA" triggered DIR1_RELEASED
then
  simpleSwitch(receivedEvent, "Button_1", 1, false, Counters, Timers, Timestamps)
end

rule "Configuration Button 2"
when
  Channel "enocean:rockerSwitch:FT1I6L57:0035FA61:rockerswitchB" triggered DIR1_PRESSED or
  Channel "enocean:rockerSwitch:FT1I6L57:0035FA61:rockerswitchB" triggered DIR1_RELEASED
then
  doubleSwitch(receivedEvent, "Button_2", 1, false, Counters, Timers, Timestamps)
end

rule "Configuration Button 3"
when
  Channel "enocean:rockerSwitch:FT1I6L57:0035FA61:rockerswitchA" triggered DIR2_PRESSED or
  Channel "enocean:rockerSwitch:FT1I6L57:0035FA61:rockerswitchA" triggered DIR2_RELEASED
then
  dimmerSwitch(receivedEvent, "Button_3", 1, false, Counters, Timers, Timestamps)
end

rule "Configuration of Button 4"
when
  Channel "enocean:rockerSwitch:FT1I6L57:0035FA61:rockerswitchB" triggered DIR2_PRESSED or
  Channel "enocean:rockerSwitch:FT1I6L57:0035FA61:rockerswitchB" triggered DIR2_RELEASED
then
  dimmerSwitch(receivedEvent, "Button_4", 4, true, Counters, Timers, Timestamps)
end

With the following items.xml:

Switch Button_1A "Taster links" <switch> (Switches) {channel="enocean:rockerSwitch:FT1I6L57:0035FA61:rockerswitchA"}
Switch Button_1B "Taster rechts" <switch> (Switches) {channel="enocean:rockerSwitch:FT1I6L57:0035FA61:rockerswitchB"}

Switch Button_1 "Taster 1" <switch> (Switches)
Switch Button_2 "Taster 2" <switch> (Switches)
Switch Button_3 "Taster 3" <switch> (Switches)
Switch Button_4 "Taster 4" <switch> (Switches)

Switch Button_1ShortPress "Taster 1 (kurz)" <switch> (Switches)
Switch Button_2ShortPress "Taster 2 (kurz)" <switch> (Switches)
Switch Button_3ShortPress "Taster 3 (kurz)" <switch> (Switches)
Switch Button_4ShortPress "Taster 4 (kurz)" <switch> (Switches)

Switch Button_1LongPress "Taster 1 (lang)" <switch> (Switches)
Switch Button_2LongPress "Taster 2 (lang)" <switch> (Switches)
Switch Button_3LongPress "Taster 3 (lang)" <switch> (Switches)
Switch Button_4LongPress "Taster 4 (lang)" <switch> (Switches)

Number Button_1Count "Taster 1 (Anzahl)" <none> (Switches)
Number Button_2Count "Taster 2 (Anzahl)" <none> (Switches)
Number Button_3Count "Taster 3 (Anzahl)" <none> (Switches)
Number Button_4Count "Taster 4 (Anzahl)" <none> (Switches)

Error is:

[WARN ] [el.core.internal.ModelRepositoryImpl] - Configuration model 'Schalter.rules' has errors, therefore ignoring it: [33,39]: mismatched input ',' expecting ']'

Have not yet look into it… but it looks like some syntax misunderstanding on my side :wink:

FYI, people normally post tutorials with working code :roll_eyes:. Please update the OP to inform people that your example is not functional until. I haven’t tested Rich’s Python example, but it looks fine to me. If you tried them and saw validation issues, then you probably added them to a .rules file and never setup the new rule engine with scripted automation, Jython, and the helper libraries.

For your example, use VS Code with the OH extension… it will help to debug the errors. There are several!

And the errors were? When I typed the above in I did test that it at least parses. I wasn’t able to do much functional testing though but I did state as such. I’d like to correct it and/or provide further explanation if you encountered problems.

The mentioned solution above works. I wanted to extend it and just keep everybody informed. If that is not in the sense of this community I can stop posting until its ready to be used. Sorry.

Sorry. I didnt know about the new rule engine. I will setup a second raspPI and test it on version 2.5. i wanted to do this update anyway. But it will take some time. Probably mid February

My apologies… I read too fast and jumped to conclusions. I had thought the latest code you posted, which is full of issues, was an evolution of the code in the OP and that it also had those errors.

BTW, here is a related tutorial for a Jython version (there is also a link in it to a DSL version)…

1 Like

Hi,

  • were you able to finish the extended code that can handle ALL that next to normal short/long/dim ?
  • How fast is the reaction of it? (Lagging?)
  • Is there any “GUI” version (like PaperUI) where all these thing could be set instead of manual coding?

Thanks :slight_smile:

Hi, the following code should be working now, but as I moved away from the enocean rocker switches towards Homematic switches, I am no longer able to test it:

import java.util.Map
import org.eclipse.smarthome.model.script.ScriptServiceUtil
import org.eclipse.smarthome.core.thing.events.ChannelTriggeredEvent

val Map<String, Timer> Counters = newHashMap
val Map<String, Timer> Timers = newHashMap
val Map<String, DateTime> Timestamps = newHashMap

// ========================================================================= //

val incrementCounter = [ String id, boolean resetCounter, Map<String, Timer> Counters |
  val item = ScriptServiceUtil.getItemRegistry.getItem(id + "Count")
  val count = (item.state as Number).intValue + 1
  postUpdate(id + "Count", String::format("%d", count))

  if (resetCounter) {
    // Deactivate the timer (if running)
    Counters.get(id)?.cancel()
    Counters.remove(id)

    val offset = now.plusSeconds(10)
    Counters.put(id, createTimer(offset, [|
      postUpdate(id + "Count", "0")
    ]))
  }
]

// ========================================================================= //

val simpleSwitch = [ ChannelTriggeredEvent receivedEvent, String id, boolean resetCounter, Map<String, Timer> Counters, Map<String, Timer> Timers, Map<String, DateTime> Timestamps |
  if (receivedEvent.event.endsWith("PRESSED")) {
    incrementCounter.apply(id, resetCounter, Counters)
    sendCommand(id, "ON")
  }
  if (receivedEvent.event.endsWith("RELEASED")) {
    sendCommand(id, "OFF")
  }
]

val doubleSwitch = [ ChannelTriggeredEvent receivedEvent, String id, boolean resetCounter, Map<String, Timer> Counters, Map<String, Timer> Timers, Map<String, DateTime> Timestamps |
  if (receivedEvent.event.endsWith("PRESSED")) {
    Timestamps.put(id, now)
    sendCommand(id, "ON")
  }
  if (receivedEvent.event.endsWith("RELEASED")) {
    // Get timestamp of switch pressed down
    var pressed = Timestamps.get(id)
    Timestamps.remove(id)

    // Handle short or long press
    val offset = pressed?.plusMillis(700)
    if (now.isBefore(offset)) {
      incrementCounter.apply(id, resetCounter, Counters)
      sendCommand(id + "ShortPress", "ON")
      sendCommand(id + "ShortPress", "OFF")
    } else {
      sendCommand(id + "LongPress", "ON")
      sendCommand(id + "LongPress", "OFF")
    }
    sendCommand(id, "OFF")
  }
]

val dimmerSwitch = [ ChannelTriggeredEvent receivedEvent, String id, boolean resetCounter, Map<String, Timer> Counters, Map<String, Timer> Timers, Map<String, DateTime> Timestamps |
  if (receivedEvent.event.endsWith("PRESSED")) {
    Timestamps.put(id, now)
    sendCommand(id, "ON")

    // Start timer if switch is held down
    val offset = now.plusMillis(700)
    Timers.put(id, createTimer(offset, [|
      // Handle long press
      sendCommand(id + "LongPress", "ON")
      sendCommand(id + "LongPress", "OFF")

      // Reschedule timer for this switch, but max. 10 times
      if (now.isBefore(Timestamps.get(id)?.plusSeconds(7))) {
        val newoffset = now.plusMillis(700)
        Timers.get(id)?.reschedule(newoffset)
      }
    ]))
  }
  if (receivedEvent.event.endsWith("RELEASED")) {
    // Deactivate the timer (if running)
    Timers.get(id)?.cancel()
    Timers.remove(id)
  
    // Get timestamp of switch pressed down
    var pressed = Timestamps.get(id)
    Timestamps.remove(id)

    // Handle short or long press
    val offset = pressed?.plusMillis(700)
    if (now.isBefore(offset)) {
      incrementCounter.apply(id, resetCounter, Counters)
      sendCommand(id + "ShortPress", "ON")
      sendCommand(id + "ShortPress", "OFF")
    }
    
    sendCommand(id, "OFF")
  }
]

// ========================================================================= //

rule "Configuration Button 1"
when
  Channel "enocean:rockerSwitch:FT1I6L57:0035FA61:rockerswitchA" triggered DIR1_PRESSED or
  Channel "enocean:rockerSwitch:FT1I6L57:0035FA61:rockerswitchA" triggered DIR1_RELEASED
then
  simpleSwitch.apply(receivedEvent, "Button_1", false, Counters, Timers, Timestamps)
end

rule "Configuration Button 2"
when
  Channel "enocean:rockerSwitch:FT1I6L57:0035FA61:rockerswitchB" triggered DIR1_PRESSED or
  Channel "enocean:rockerSwitch:FT1I6L57:0035FA61:rockerswitchB" triggered DIR1_RELEASED
then
  doubleSwitch.apply(receivedEvent, "Button_2", false, Counters, Timers, Timestamps)
end

rule "Configuration Button 3"
when
  Channel "enocean:rockerSwitch:FT1I6L57:0035FA61:rockerswitchA" triggered DIR2_PRESSED or
  Channel "enocean:rockerSwitch:FT1I6L57:0035FA61:rockerswitchA" triggered DIR2_RELEASED
then
  dimmerSwitch.apply(receivedEvent, "Button_3", false, Counters, Timers, Timestamps)
end

rule "Configuration of Button 4"
when
  Channel "enocean:rockerSwitch:FT1I6L57:0035FA61:rockerswitchB" triggered DIR2_PRESSED or
  Channel "enocean:rockerSwitch:FT1I6L57:0035FA61:rockerswitchB" triggered DIR2_RELEASED
then
  dimmerSwitch.apply(receivedEvent, "Button_4", true, Counters, Timers, Timestamps)
end

Please note that I remove the “maxCount” variable due to a limitation of the rule dsl that allows a max. of 6 parameters for lambdas. The counter will increment to infinity until it will be reset (if resetCounter boolean was set to true). Otherwise, I suggest that the rule that handles the profiles and reads the Counter Item should reset it, if it exceeds the last known profile id. :slight_smile:

The latency is quite ok. For sure you have a delay for the long press which is a natural thing, as the script needs to wait for the given time until it can detect the long press. I didnt feel like it was a negativ effect.

So give it a try and let us know how it works :slight_smile:

Best Bechte

1 Like

Hi guy’s.

I am brand new to OH3, I have many enocean switches and this is exactly what I was looking for (to dim Tradfri lamps with an enocean switch).

I also understand the code so far, the only question I have is where to put it in OH3 :pleading_face:

Please excuse the stupid question and many thanks for the help