Why am I getting "null" error?

Hi,

I am running openhab2 on a Raspbian.

I am trying to create a timer based rule as follow:

rule "Galerie Dimmer"

when
        Item OG_Galerie_Taster_Eltako changed from OFF to ON
then
        OG_Galerie_Taster_Eltako_kurz.sendCommand(ON) // schaltet das Licht an
        timer1 = createTimer(now.plusMillis(200), [|
                dimm = (OG_Galerie_Helligkeit.state as Number)
                timer1 = null
                ])
        if (OG_Galerie_Taster_Eltako.state == ON ) {
        if ( timer === null) {
                timer = createTimer(now.plusMillis(delay), [ |
                        dimm = dimm + step
                        if (dimm > 100) {
                                step = -5
                                dimm = 100
                        }
                        if (dimm < 0) {
                                step = 5
                                dimm = 0
                        }
                        OG_Galerie_Helligkeit.sendCommand(dimm)
                        ])
                }
                else {
                        if (OG_Galerie_Taster_Eltako.state == ON ) {
                                if ( timer !== null ) {
                                        timer.reschedule(now.plusMillis(delay))
                                }
                        }
                }
        }
end

But when the rule fires I am getting errors in openhab.log:

2020-10-03 23:35:55.660 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Galerie Dimmer': 'reschedule' is not a member of 'null'; line 79, column 5, length 39
2020-10-03 23:36:29.563 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Galerie Dimmer': 'reschedule' is not a member of 'null'; line 79, column 5, length 39

I do not know why I am getting this error. I proove the timer it not null (timer !== null) before rescheduling. But it does not help.

Any ideas?

/CV

Have you declared timer, timer1, dimm, delay and step as globals?

The names are not very adventurous -might they be used in other rules?

Hi,

I created these in the rule file. As you suggest I meanwhile renamed these but still getting the same error:

var timerGalerie
var Number dimmGalerie = 0
var stepGalerie = 5
var delayGalerie = 500

rule "Galerie Dimmer"
when
        Item OG_Galerie_Taster_Eltako changed from OFF to ON
then
        OG_Galerie_Taster_Eltako_kurz.sendCommand(ON) // schaltet das Licht an
        timerGalerie = createTimer(now.plusMillis(200), [|
                dimmGalerie = (OG_Galerie_Helligkeit.state as Number)
                timerGalerie = null
                ])
        if (OG_Galerie_Taster_Eltako.state == ON ) {
        if ( timerGalerie === null) {
                timerGalerie = createTimer(now.plusMillis(delay), [ |
                        dimmGalerie = dimmGalerie + stepGalerie
                        if (dimmGalerie > 100) {
                                stepGalerie = -5
                                dimmGalerie = 100
                        }
                        if (dimmGalerie < 0) {
                                stepGalerie = 5
                                dimmGalerie = 0
                        }
                        OG_Galerie_Helligkeit.sendCommand(dimmGalerie)
                        ])
                }
                else {
                        if (OG_Galerie_Taster_Eltako.state == ON ) {
                                if ( timerGalerie !== null ) {
                                        timerGalerie.reschedule(now.plusMillis(delay))
                                }
                        }
                }
        }
end

This is what I get:

2020-10-04 09:36:43.931 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule 'Galerie Dimmer': 'reschedule' is not a member of 'null'; line 79, column 6, length 46

Note: There are other rules in the file therefore the line # does not match, but it is the line with the “reschedule” command.

Hello @knebb,

please check this discussion “"==" or "===" "!=" or "!=="”.

== : equals to, it compares the data of the two operands for equivalency
!= : not equals, it compares the data of the two operands for non-equivalency
=== : identity, it compares the two Objects to see if they are the same (i.e. both variable point to the same space in RAM)
!== : not identity, it compares the two Objects to see if they are not the same (i.e. both point to different space in RAM)

You should (I think :slight_smile: - of course not really tested right now) only use “!=” instead of “!==”.

null is the special case where you do want to use === or !==

Okay, initially your rule had two different timer handles, but now it’s only one. I don’t understand what it is supposed to do, but let’s follow the action.

Just about the first thing that happens is creating a timer and keeping a global handle for it
timerGalerie = createTimer(now.plusMillis(200) ...

Then we do a pointless test (you already know this is ON because the rule only triggers when it changes to ON)
if (OG_Galerie_Taster_Eltako.state == ON ) {

Then, another pointless test as you know you just put a timer handle in there (we should arrive here long before the timer executes)
if ( timerGalerie === null) {

So we should next arrive at the else part, do another pointless test for ON, do another pointless test for null

Finally we get to your suspect line, which is the suspect because the error message contains the rule name and mention of reschedule
timerGalerie.reschedule(now.plusMillis(delay))

I would expect that to fail because delay is undefined, but it doesn’t seem like the most sensible error message.

So let’s take the message at face value. The handle is not null but doesn’t have a reschedule method. Let’s interpret that as perhaps meaning the timer is not yet fully-formed. Is that possible?

Sure - on the face of it, this rule is creating a timer and then immediately trying to reschedule it. I recall we’ve seen before that timer creation is not synchronous, the handle is returned an rule execution continued before the timer is fully built,
It’s not normally a problem because most people don’t use timers this way.

Prove the point with a small uhh, delay

Thread::sleep(50)
timerGalerie.reschedule(now.plusMillis(delay))

Oh.

Looks like I completely misunderstood the timer thing.So creating a timer creates a new thread? And the parent one continues execution?

Ok, I will rewrite my rule then. Sorry for confusion and thanks for the hints.

/KNEBB

Yes, that is the whole point. Creating a timer puts that block of code into an independent function, and sets an alarm clock to run it.
The rule that created it continues immediately, and will normally exit long before the timer block runs.
The handle allows you access to these “detached” timers later, so that you can cancel or reschedule.

Your original code should work, although it is really a ‘dumb’ thing to do - create and immediately reschedule - and I think you were unlucky to fall in a timing race created by multi-threading timer handling alongside timer creation.

It looks like you are ramping a dimmer? There are examples to be found -

A lot of these dimmer solutions do in fact create a timer and almost immediately reschedule … I think they get away with it because the rescheduling is within the timer’s own code block, not external.