Why does a rule with item trigger doesn't process ItemStateEvent

  • Platform information:
    • Hardware: RPi 3B
    • OS: Raspbian Buster
    • Java Runtime Environment: OpenJDK Runtime Environment (Zulu8.40.0.178-CA-linux_aarch32hf) (build 1.8.0_222-b178)
    • openHAB version: 2.5.3
  • Issue of the topic:
    I’ve created a rule to manage the brighness in accordance to the time of a day.
    Simply put, when an item’s brightness changes from zero, it checks a time of a day and sets the new level of brightness.
    Unfortunately, when I activate a physical switch or switch it in the paper UI it doesn’t trigger aforementioned rule.
    After some debugging I’ve found out that the only event indicating brightness changes is org.eclipse.smarthome.core.items.events.ItemStateEvent. I also found that org.eclipse.smarthome.model.rule.runtime.internal.engine.RuleEngineImpl#receive doesnt’ process this kind of events.
    Is that intentional? Any advice on how else can I implement this kind of rule using this kind of rule engine?
  • Please post configurations (if applicable):your code goes here
    • Rule:
import java.time.LocalTime
import java.time.Instant;
import java.time.ZoneId;
import java.util.concurrent.locks.ReentrantLock

val LOGGER_NAME = "Toilet brightness rule"
val lock = new ReentrantLock()
var switchOnCounter = 0L
var lastSwitchOnTime = 0L
val nightTime = LocalTime.of(23, 00)
val dayTime = LocalTime.of(8, 00)

rule "Corridor brightness by the time of a day"
when
    Item zwave_device_c37bfa25_node24_switch_dimmer changed from 0
    ////or 
    //Item zwave_device_c37bfa25_node24_switch_dimmer received command ON
then
    logInfo(LOGGER_NAME, "Firing toilet rule")
    val cInstant = Instant.now()
    val cMillis = cInstant.toEpochMilli();
    val cTime = cInstant.atZone(ZoneId.systemDefault())
    val cLocalTime = cTime.toLocalTime()
    val diff = cMillis - lastSwitchOnTime

    lock.lock()
    try{
        logInfo(LOGGER_NAME, "Current counter is " + switchOnCounter)
        logInfo(LOGGER_NAME, "Current diff is " + diff)
        if (diff > 3000 || diff < 0){
            logInfo(LOGGER_NAME, "Setting counter to one")
            switchOnCounter = 1
        } else {
            switchOnCounter += 1
            logInfo(LOGGER_NAME, "Current diff is incremented counter to " + switchOnCounter)
        }
        lastSwitchOnTime = cMillis
        
        logInfo(LOGGER_NAME, "Current local time is " + cLocalTime)
        if (switchOnCounter < 2 && (cLocalTime.isBefore(dayTime) || cLocalTime.isAfter(nightTime))){
            logInfo(LOGGER_NAME, "Dimming toilet lights")
            zwave_device_c37bfa25_node24_switch_dimmer.sendCommand(10)
        } else {
            logInfo(LOGGER_NAME, "Brightening toilet lights")
            zwave_device_c37bfa25_node24_switch_dimmer.sendCommand(100)
        }
    } finally {
        lock.unlock
    }
end

You really don’t need to be digging in there to write rules. Use the features provided.

Look in your events.log to see what events do happen.
I assume you have some Items controlled by your UI, what are they?
I assume you have some Items linked to physical switches, what are they?

Your long Item name suggests that you have simple mode turned on, resulting in automatic creation of Items (with useless names)
If you are creating rules of this complexity you almost certainly do not need that any more.
It often seems to result in people getting into a mess when they create duplicate Items and Things.

2 Likes

Thanks for suggestions!

You really don’t need to be digging in there to write rules. Use the features provided.

Well, using the features provided was my initial intent anyway.
I forgot to mention, that the device under control is an Aeotec Nano Dimmer ZW111.

I assume you have some Items controlled by your UI, what are they?

It’s a zwave_device_c37bfa25_node24_switch_binary (Switch Binary Z-Wave command class).

I assume you have some Items linked to physical switches, what are they?

A physical switch is a bistable switch attached directly to the dimmer. Like the one at the image:
image
So it’s neither z-wave device nor controlling/controlled by OpenHAB directly.

Look in your events.log to see what events do happen.
When physical switch triggered there’s only one event:

2020-04-13 20:27:52.934 [vent.ItemStateChangedEvent] - zwave_device_c37bfa25_node24_switch_dimmer changed from 0 to 10

And then goes reports like:

2020-04-13 21:02:16.313 [vent.ItemStateChangedEvent] - zwave_device_c37bfa25_node24_meter_voltage changed from 67.37 to 67.38
2020-04-13 21:02:16.414 [vent.ItemStateChangedEvent] - zwave_device_c37bfa25_node24_meter_current changed from 0.028 to 0.027
2020-04-13 21:02:16.513 [vent.ItemStateChangedEvent] - zwave_device_c37bfa25_node24_meter_watts changed from 1.7 to 1.67
2020-04-13 21:02:26.316 [vent.ItemStateChangedEvent] - zwave_device_c37bfa25_node24_meter_voltage changed from 67.38 to 67.39
2020-04-13 21:02:26.408 [vent.ItemStateChangedEvent] - zwave_device_c37bfa25_node24_meter_current changed from 0.027 to 0.028
2020-04-13 21:02:26.507 [vent.ItemStateChangedEvent] - zwave_device_c37bfa25_node24_meter_watts changed from 1.67 to 1.69

for every ten seconds.

When the binary switch triggered from the UI we have these events:

2020-04-13 21:07:52.051 [ome.event.ItemCommandEvent] - Item 'zwave_device_c37bfa25_node24_switch_binary' received command ON

2020-04-13 21:07:52.105 [nt.ItemStatePredictedEvent] - zwave_device_c37bfa25_node24_switch_binary predicted to become ON

2020-04-13 21:07:52.127 [vent.ItemStateChangedEvent] - zwave_device_c37bfa25_node24_switch_binary changed from OFF to ON

2020-04-13 21:07:54.363 [vent.ItemStateChangedEvent] - zwave_device_c37bfa25_node24_switch_dimmer changed from 0 to 10

And then go reports as in the first case.

In this case, we have ItemCommandEvent, that can trigger the rule if the trigger will be modified for “binary switch goes to ON”. But it doesn’t solve a case for the physical switch, which doesn’t emit such an event.

Any suggestions on how to trigger the rule for the physical switch?

You can’t, if there is no event.
You can listen for changes in the dimmer state, as you do.
If openHAB didn’t command that, then it was an external event.
Determining who-done-it is harder.

There’s only one event for that:

2020-04-13 20:27:52.934 [vent.ItemStateChangedEvent] - zwave_device_c37bfa25_node24_switch_dimmer changed from 0 to 10

And it doesnt’ trigger the rule.

Determining who-done-it is harder.

Maybe I said something misleading. I don’t need to differentiate the source of an event. My point is that the only event they have in common is the ItemStateEvent, and I expect it to trigger the rule.

Returning to my original question, is ItemStateEvent ignored on purpose?

It should. Investigate.

Look in your openhab.log and make sure you see a "Loading model 'xxx.rules' " message

Make another rule with just changed trigger, in case your initial value is 0.0 or 0% and not plain 0

Not a useful question in the context of rule triggers, which are given as Item xx changed or Item xx updated and do of course work for everyone else.

Note that your rule uses a lock, which are bit can be dangerous in DSL rules and do not play nice. If your rule code breaks, the lock is not guaranteed to be released. The body of your rule would never run again, though of course your initial “Firing” log should still happen.

I think the issue is caused by the fact, that I have two rules with the same name.
They are stored in org.eclipse.smarthome.model.rule.runtime.internal.engine.RuleTriggerManager#changedEventTriggeredRules and deleted by name in org.eclipse.smarthome.model.rule.runtime.internal.engine.RuleTriggerManager#removeRules.
There’s no warning in this case. So it’s hard to find out what’s wrong without debugging if you’re not attentive enough.
Anyway, I greatly appreciate your help.
Thanks!

Every rule must have a unique name. I think everyone learns that one the hard way. There’s no warning because you might be making a deliberate edit/replacement, I suspect.

<RULE_NAME> - Each rule must have a unique name