Getting array in rules, doesn't work all the times

Hi, I have a set point for temperature and humidity which change every 12 hours. For this, I have a array to set from it. some times when 12 hour passes, the next number in the line does not set and it stuck at previous number until i change rule names or restart whole raspberry. some times it need multiple reset to sort it out. here is my rules:

var Number tmcount


val theArray1 = newArrayList(40, 40, 50, 50, 60, 60, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 49, 49, 49, 49, 49, 49, 54, 54, 54, 55, 55, 55, 60, 60, 60, 60, 60, 60, 60, 82, 82, 82)

val theArray2 = newArrayList(100, 100, 100, 100, 100, 100, 78, 78, 78, 78, 78, 78, 78, 78, 70, 70, 70, 70, 70, 70, 58, 58, 58, 58, 58, 58, 46, 46, 46, 46, 46, 46, 32, 32, 32, 32, 32, 32, 22, 22, 22, 22, 22, 22, 15, 15, 15, 15, 15, 15, 15, 26, 26, 26)

rule "Restarting"
when
    System started
then
        Thread::sleep(1000)
        if(prepare.state == ON){
	Thread::sleep(2000)
          prepare.sendCommand("OFF")
          Thread::sleep(5000)
	        set.sendCommand("OFF")
          Thread::sleep(2000)
          stage1.sendCommand(stage2.state as Number)
          Thread::sleep(10000)
          prepare.sendCommand("ON")
        }
end

rule "wqtaging1"
when
      Item stage2 received update
then

if(rush175.state == ON)  {
goaltemp.sendCommand(theArray1.get((stage2.state as Number).intValue))
goalhumidity.sendCommand(theArray2.get((stage2.state as Number).intValue))
}

end

rule "tmcounting"
when
      Time cron "0 0 0/12 1/1 * ? *"
then

if(start.state == ON) {

  if(pause.state == OFF) {

        tmcount = tmcount + 1
        stage2.sendCommand(tmcount)
        stage2.postUpdate(tmcount)
  }

}
end

each 12 hours tmcount goes +1 and stage 2 updates. when stage 2 updates, goaltemp and goalhumidity should update accordingly. it usually does. but some times it stuck. some times the power outage cause this problem. Is there any solution here? or other way instead of using arrays?
thanks in advance.

  • Platform information:
    • Hardware: RPI400
    • OS: Raspbian
    • Java Runtime Environment: 1.8
    • openHAB version: 2.5

Not really sure, but you should not use thread.sleep but timers instead.
Especially as you have quite long sleeping times.

1 Like

I believe cron works on a 24 hour clock. Shouldn’t the trigger use 0/23 instead of 0/12?

And I’ll second @hmerk’s advice. Long running rules should be avoided. Long running is anything over 250 msec. A rule that takes 20 seconds to complete is a really bad idea. Though since this is a rule only triggered once at system startup, you are less likely to encounter some of the problems that can arise from long running rules.

Implemented with timers would look something like:

then
    createTimer(now.plusSeconds(1), [ |
        if(prepare.state == ON) {
            createTimer(now.plusSeconds(2), [ |
                prepare.sendCommand("OFF")
                createTimer(now.plusSeconds(5), [ | set.sendCommand("OFF")])
                createTimer(now.plusSeconds(7), [ | stage1.sendCommand(state2.state as Number) ])
                createTimer(now.plusSeconds(17), [ | prepare.sendCommand("ON") ])
            ])
        }
    ])
end

It gets simpler if you don’t have to wait that first second before you test to see if prepare.state is ON.

if(prepare.state == ON) {
    createTimer(now.plusSeconds(3), [ | prepare.sendCommand("OFF") ])
    createTimer(now.plusSeconds(8), [ | set.sendCommand("OFF") ])
    createTimer(now.plusSeconds(10), [ | stage1.sendCommand(stage2.state as Number) ])
    createTimer(now.plusSeconds(20), [ | prepare.sendCommand("ON") ])
}

If using JS Scripting with the OHRT library it would look something like this,

var { Deferred } = require('openhab_rules_tools');

setTimeout(() => { 
  if(prepare.state == "ON") {
    Deferred.defer("prepare", "OFF", "PT2S");
    Deferred.defer("set", "OFF", "PT7S");
    Deferred.defer("stage1", items.state2.state, "PT9S");
    Deferred.defer("prepare", "ON", "PT19S");
  }
}

Using Gatekeeper from OHRT would look something like:

var { Gatekeeper } = require('openhab_rules_tools');
cache.private.get('gk', () => Gatekeeper());

gk.addCommand('PT1S', () => {}); // do nothing for the first second
gk.addCommand('PT2S', () => { 
  if(prepare.state == "ON") {
    gk.addCommand('PT5S', () => items.prepare.sendCommand("OFF") );
    gk.addCommand('PT2S', () => items.set.sendCommand("OFF") );
    gk.addCommand('PT10S', () => items.stage1.sendCommand(items.stage2.state) );
    gk.addCommand('PT0S', () => items.prepare.sendCommand("ON") );
  }
});

Gatekeeper is the best way to schedule a sequence of commands. The time is how long to wait after executing the command before allowing the next command to run. Think of it like irrigation, the time is how long you want the water to stay on before stopping it and moving on to the next valve.

1 Like

Can he use OHRT with openHAB 2.5?
I doubt so….

  • To alleviate power outage and your counter resetting back, you can use persistence with restore on startup
  • What happens when tmcounter goes beyond the number of elements in the array?
  • What’s the initial state of stage2? Where is it initialised?
  • Why is tmcount not initialised?
  • Are stage1 and stage2 used elsewhere, or are they just for this purpose?
1 Like

thanks. I’m sure that this rule execute each 12 hours without any problem

rule "tmcounting"
when
      Time cron "0 0 0/12 1/1 * ? *"
then

if(start.state == ON) {

  if(pause.state == OFF) {

        tmcount = tmcount + 1
        stage2.sendCommand(tmcount)
        stage2.postUpdate(tmcount)
  }

}
end

it increases tmcount and stage2
the problem is in this rule:

rule "wqtaging1"
when
      Item stage2 received update
then

if(rush175.state == ON)  {
goaltemp.sendCommand(theArray1.get((stage2.state as Number).intValue))
goalhumidity.sendCommand(theArray2.get((stage2.state as Number).intValue))
}

end

some times it stuck at previous index of the array despite stage2 updates to new number
do you mean that this problem relates to thread::sleep which i use in start ups?

hi, i persist every thing, counter works as I wrote in my previous post and explained there more. the problem is stage2 some times has problem getting new indexes of the array.
2 - if tm counter goes beyond it stays at last index of the array
3- at frist user in basicUi define a stage1 and I use that to set stage2 at the begining.
4

rule "preparng"
when
    Item prepare received command ON
then
    start.sendCommand("ON")
    tmcount = stage1.state as Number
    stage2.postUpdate(tmcount)
    Fan.sendCommand(ON)
    pause.sendCommand("OFF")
end

it initialised as above
The user in basicui define stage1 with a set point. after prepare button clicks. tmcount and stage2 sets.

According to ArrayList (Java Platform SE 8 ) it would throw an error if it goes out of bounds.

Maybe rush175 state is not ON?

Since you’re on openhab 2, I don’t know. Things have changed in OH3 and OH4 in regards to threading and rule executions.

I’m not sure if the thread::sleep caused this problem. If it did, it would only cause problems for the first however many seconds in total, and after that it should have no bearing on the issue. Although you should still follow @rlkoshak’s suggestion to use timers, because Thread::Sleep blocks the script/rule.

1 Like

I didn’t see that he was on 2.5. I should have looked more closely. I wonder if it makes sense to have a “Legacy” category in the forum where anyone running a version of OH older than say two years or four years can post and perhaps find people able to help. I can usually help with generic stuff that is still the same today as it was back in 2.5 but I do not trust my ability to support most of the stuff that has changed since 2.5 any more.

And it may not be fair, but it’s hard to not have the feeling that if you want to keep running unsupported versions of software years and years after it’s no longer supported, you shouldn’t be changing anything: no new rules, no new bindings and things and Items, no updates to the OS. It should be a time capsule humming along until something outside the system breaks it and you are forced to upgrade, which is going to be a whole lot more work all at once than keeping up with the upgrades would have been.

Anyway, I was mainly posting for future readers of this thread who balk at how awkward the timer approach in Rules DSL is to show there are better ways. I don’t expect @Javad_Effat_doost to change their rules over to some other language, if for no other reason than for the most part those users who are willing to change have done so already. Anyone left using Rules DSL is likely unwilling to change.

But there is a version of OHRT written in Python that could be used in 2.5 which provides both deferred and gatekeeper. GitHub - rkoshak/openhab-rules-tools at before-npm. I originally wrote OHRT for 2.5 in Jython way back in the OH 2.x days. I converted it to JS Scripting in OH 3.0 because it took some time for Jython support to come to OH 3 and at the time the JS Scripting devs were the only ones willing to help address the needs of managed rules users.

Two different problems. The Thread::sleep problem is a potential problem unrelated to the arraylist index.

Why both a command and an update? Unless you’ve disabled autoupdate, the command will result in an update meaning statge2 receives two updates and the rule runs twice.

How do you know the index is stuck? Log out what you postUpdate and sendCommand in the one rule and log out what is it in the rule that triggers based on the updates. Also log out what’s in the ArrayList. Maybe it’s not what you assume. When code doesn’t work you cannot assume anything. You must verify everything.

It’s less of a problem to use Thread::sleep on OH 3.0+ than it was to use it in Rules DSL in 2.5 and before.

In OH 2.5 there were only five threads (IIRC) available to run rules and there was no lock to prevent the same rule from being triggered again and running in more than one thread at the same time. Since the one rule can take up more than one thread and there are only five threads a long running rule can consume all the available threads and starve out all the rest of your rules, forcing them to wait until one of those long running rules exits before any other rule can run. (OH 1.x and OH 2.x Rules DSL only] Why have my Rules stopped running? Why Thread::sleep is a bad idea

Additional problems includes that each thread running the rule is running the same rule meaning that one thread can modify variables that impact all the other threads running that same rule.

In OH 3.0+ each rule gets it’s very own thread and that thread is locked so you can never have more than one copy of a rule running at a time. So at worst you would starve out that one rule’s ability to run as triggeres queue up and are worked off in sequence instead of starving out all your rules.

But because this is a system started triggered rule, it’s only ever going to be triggered the one time so the risks that come with long running rules is reduced.

3 Likes

I use tread::sleep in other places too! for example it may triggers by users who want to pause the program like this:

rule "pause"
when
    Item pause received command ON
then
    Heater.sendCommand(OFF)
    Thread::sleep(2000)
    Vent.sendCommand(OFF)
    Thread::sleep(2000)
    Fan.sendCommand(OFF)
    Thread::sleep(2000)
    Spray.sendCommand(OFF)
end

can I use these and reduce them to 250 milliseconds?
the reason i’m using tread::sleep is because i’m using MQTT to control some relays and I want to be sure that commands works without any interference, so I added the Tread::sleep. I may be wrong about this. If you have any information about this, it would be helpful. Can I remove them entirely?

one time I added the postUpdate to solve this problem!! it stayed there after that. should have remove them.

I have stage2 shown in basicUI, the number changes. I think there is some error in the system. because when this happens, If I turn off the process, set the stage2 again(I have a set point in the basicUI to set stage2). It does not work. it stuck at the same array index.
consider this: I have two process, each of them has different arrays. when this problem occurs for one process, If I trigger the other process, it easily gets the correct array index, but when I trigger the first one which has the problem, the problem is still there unless i restarts the system.
if with this information, no light shed on the problem, I may have change things …because I turned off the logs entirely, this is due to the SD Card failures. without logs, my cards are working for almost two years without any problem.

I see, I will take care of it. thanks.

No, It is on.

thanks again for your time and patience. :slightly_smiling_face:

You should use timers instead of sleeps in any situation where any given rule can be triggered faster than it takes for the rule to run. The longer the rule takes to run, the higher the likelihood that you’ll starve out all of your rules.

Almost certainly you can remove them. If you are worried about things on the MQTT side, set the QOS on both the MQTT Thing and the subscribers to 2 which will guarantee each message gets delivered and only delivered once.

Though in practice, on a typical LAN, even on a QOS 0 each message gets delivered every time and only delivered once. If for some reason you do need to space these commands out it will be because of the end device, not MQTT.

Don’t solve problems you don’t know you even have and don’t understand. This leads to “Galello’s Column” style problems (tl;dr an engineer wanted to keep columns which are laid on their side on supports at either end from cracking so they added a support in the middle and increased the likelihood that the column cracks instead of reduces it) or brand new problems.

So start without any delays. Then if and only if there are problems start to experimentally determine what delay is actually required and implement the minimum delay required to reliably work. And if your delays lead to a long running rule, use timers instead of sleeps.

This is only going to tell you what you already know, it doesn’t work. It’s not going to tell you why it doesn’t work. For this you need to know the value of everything that the rule is working with and what it does with that data and the only place to get that is from the rule itself.

1 Like

Hello again. I try to refactor my rule and get rid of all sleeps … here is my new rule:

var Timer timer1 = null
var Timer timer2 = null
var Number tmcount


val theArray5 = newArrayList(49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 55, 55, 55, 55, 55, 55, 55, 60, 60, 60, 60, 60, 60, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 71, 71, 71, 71, 71, 71)

val theArray6 = newArrayList(80, 80, 80, 80, 75, 75, 75, 75, 70, 70, 60, 60, 60, 50, 50, 50, 40, 40, 40, 40, 35, 35, 35, 35, 35, 35, 35, 31, 31, 31, 34, 34, 34, 34, 21, 21, 21, 21, 15, 15, 15, 15, 15, 15, 15, 15, 21, 21, 21, 21)

val theArray1 = newArrayList(40, 40, 50, 50, 60, 60, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 49, 49, 49, 49, 49, 49, 54, 54, 54, 55, 55, 55, 60, 60, 60, 60, 60, 60, 60, 82, 82, 82)

val theArray2 = newArrayList(100, 100, 100, 100, 100, 100, 78, 78, 78, 78, 78, 78, 78, 78, 70, 70, 70, 70, 70, 70, 58, 58, 58, 58, 58, 58, 46, 46, 46, 46, 46, 46, 32, 32, 32, 32, 32, 32, 22, 22, 22, 22, 22, 22, 15, 15, 15, 15, 15, 15, 15, 26, 26, 26)



rule "Restarting"
when
    System started
then
    createTimer(now.plusSeconds(3)) [|
        if(prepare.state == ON){
            createTimer(now.plusSeconds(2)) [| prepare.sendCommand(OFF) ]
            createTimer(now.plusSeconds(7)) [| set.sendCommand(OFF) ]
            createTimer(now.plusSeconds(14)) [| stage1.sendCommand(stage2.state as Number) ]
            createTimer(now.plusSeconds(19)) [| prepare.sendCommand(ON) ]
        }
    ]
end




rule "pause"
when
    Item pause received command ON
then
    Heater.sendCommand(OFF)
    SprinklerSystemSchedule.sendCommand("OFF")
    createTimer(now.plusSeconds(1)) [| Vent.sendCommand(OFF) ]
    createTimer(now.plusSeconds(2)) [| Fan.sendCommand(OFF) ]
    createTimer(now.plusSeconds(3)) [| Spray.sendCommand(OFF) ]
end


rule "resume"
when
    Item pause received command OFF
then
    if(Fan.state != ON) Fan.sendCommand(ON)
end

rule "preparng"
when
    Item prepare received command ON
then
    start.sendCommand("ON")
    tmcount = stage1.state as Number
    stage2.sendCommand(tmcount)
    Fan.sendCommand(ON)
    pause.sendCommand("OFF")
end



rule "starting1"
when
    Item rush175 received command ON or
    Item tooska3 received command ON
then
    prepare.sendCommand(ON)
end


rule "stadfsing1"
when
    Item rush175 received command OFF or
    Item tooska3 received command OFF
then
    prepare.sendCommand(OFF)
end



rule "tmcounting"
when
    Time cron "0 0/3 * 1/1 * ? *"
then
    if(start.state == ON && pause.state == OFF) {
        tmcount = tmcount + 1
        stage2.sendCommand(tmcount)
        
    }
end

rule "drye223m2dity"
when
    Item h1 received update or
    Item h2 received update
then
    if(start.state == ON && pause.state == OFF) {
        if(Fan.state != ON) Fan.sendCommand(ON)
        if(((h1.state as DecimalType) > (goalhumidity.state as DecimalType)+8) || ((h2.state as DecimalType) > (goalhumidity.state as DecimalType)+8)) {
            if(SprinklerSystemSchedule.state != OFF) SprinklerSystemSchedule.sendCommand(OFF)
            if(Vent.state != ON) Vent.sendCommand(ON)
            if(Spray.state != OFF) Spray.sendCommand(OFF)
        } else if(((h1.state as DecimalType) < (goalhumidity.state as DecimalType)) && ((h2.state as DecimalType) < (goalhumidity.state as DecimalType))) {
            if(Spray.state != ON) Spray.sendCommand(ON)
            if(Vent.state != OFF) Vent.sendCommand(OFF)
        }
    }
end

rule "1msde3din"
when
    Item t1 received update or
    Item t2 received update or
    Item t3 received update
then
    if(start.state == ON && pause.state == OFF) {
        if(((t1.state as DecimalType) > (goaltemp.state as DecimalType)) || ((t2.state as DecimalType) > (goaltemp.state as DecimalType)) || ((t3.state as DecimalType) > (goaltemp.state as DecimalType))) {
            if(Heater.state != OFF) Heater.sendCommand(OFF)
        } else if(((t1.state as DecimalType) < (goaltemp.state as DecimalType)-2) && ((t2.state as DecimalType) < (goaltemp.state as DecimalType)-2) && ((t3.state as DecimalType) < (goaltemp.state as DecimalType)-2)) {
            if(Heater.state != ON) Heater.sendCommand(ON)
        }
    }
end

rule "egr2sh"
when
    Item stage2 received update
then
    if(rush175.state == ON)  {
      goalhumidity.sendCommand(theArray2.get((stage2.state as Number).intValue))
      goaltemp.sendCommand(theArray1.get((stage2.state as Number).intValue))

    }
 
    if(tooska3.state == ON)  {
      goalhumidity.sendCommand(theArray6.get((stage2.state as Number).intValue))
      goaltemp.sendCommand(theArray5.get((stage2.state as Number).intValue))

    }
    
    if((stage2.state as Number) > 48 && rush175.state == ON) {
      rush175.sendCommand("OFF")
    }
    if((stage2.state as Number) > 51 && tooska3.state == ON) {
      tooska3.sendCommand("OFF")
    }
end


rule "stop1"
when
    Item prepare received command OFF
then
    start.sendCommand("OFF")
end

rule "st33op"
when
    Item start received command OFF
then
    Heater.sendCommand(OFF)
    createTimer(now.plusSeconds(1)) [| Vent.sendCommand(OFF) ]
    createTimer(now.plusSeconds(2)) [| Fan.sendCommand(OFF) ]
    createTimer(now.plusSeconds(3)) [| 
        if(SprinklerSystemSchedule.state != OFF) SprinklerSystemSchedule.sendCommand(OFF)
    ]
    createTimer(now.plusSeconds(4)) [| Spray.sendCommand(OFF) ]
end



rule "checkrelay"
when
    Time cron "0 0/3 * 1/1 * ? *"
then
    Heater.sendCommand(Heater.state.toString)
    Vent.sendCommand(Vent.state.toString)
    Fan.sendCommand(Fan.state.toString)
    Spray.sendCommand(Spray.state.toString)
end




rule "Stagdeset"
when
    Item set received command ON
then
    stage1.sendCommand(tm.state as Number)

end


rule "spra2ycycle1"
when
    Time cron "0 0/8 * 1/1 * ? *"
then
    if(SprinklerSystemSchedule.state == ON) {
        Spray.sendCommand(ON)
        timer1?.cancel
        timer1 = createTimer(now.plusSeconds(10)) [|
            Spray.sendCommand(OFF)
            timer1 = null
        ]
    }
end


rule "da3251wf"
when
    Item t1 received update or
    Item t2 received update or
    Item t3 received update
then
    if(t1.state as DecimalType > goaltemp.state as DecimalType + 20 || t2.state as DecimalType > goaltemp.state as DecimalType + 20 || t3.state as DecimalType > goaltemp.state as DecimalType + 20) {
        if(Heater.state != OFF) Heater.sendCommand(OFF)
    }
end




I enabled the logs.
the “egr2sh” rule, executed at first. than I reboot the Rpi and suddenly goaltemp and goal humidity don’t update which exist in this rule. after one or two reboot, goaltemp changes but no changes in goalhumidity, I guess this is random.
here are my logs:

2024-07-15 14:00:45.189 [vent.ItemStateChangedEvent] - set changed from OFF to ON
2024-07-15 14:00:45.196 [vent.ItemStateChangedEvent] - stage1 changed from 12 to 8
2024-07-15 14:00:48.083 [ome.event.ItemCommandEvent] - Item 'tooska3' received command ON
2024-07-15 14:00:48.095 [ome.event.ItemCommandEvent] - Item 'prepare' received command ON
2024-07-15 14:00:48.098 [vent.ItemStateChangedEvent] - tooska3 changed from OFF to ON
2024-07-15 14:00:48.109 [ome.event.ItemCommandEvent] - Item 'start' received command ON
2024-07-15 14:00:48.113 [vent.ItemStateChangedEvent] - prepare changed from OFF to ON
2024-07-15 14:00:48.119 [ome.event.ItemCommandEvent] - Item 'stage2' received command 8
2024-07-15 14:00:48.140 [ome.event.ItemCommandEvent] - Item 'Fan' received command ON
2024-07-15 14:00:48.146 [ome.event.ItemCommandEvent] - Item 'pause' received command OFF
2024-07-15 14:00:48.152 [vent.ItemStateChangedEvent] - start changed from OFF to ON
2024-07-15 14:00:48.156 [nt.ItemStatePredictedEvent] - Fan predicted to become ON
2024-07-15 14:00:48.185 [vent.ItemStateChangedEvent] - stage2 changed from 12 to 8
2024-07-15 14:00:48.200 [ome.event.ItemCommandEvent] - Item 'Fan' received command ON
2024-07-15 14:00:48.204 [vent.ItemStateChangedEvent] - Fan changed from OFF to ON
2024-07-15 14:00:48.207 [nt.ItemStatePredictedEvent] - Fan predicted to become ON
2024-07-15 14:00:57.899 [ome.event.ItemCommandEvent] - Item 'tooska3' received command OFF

as you can see after stage2 got its new value goaltemp and goalhumidity don’t update
one time it updates:


as you see it only goaltemp.
is there any possibility that a problem exist in this part:

goalhumidity.sendCommand(theArray2.get((stage2.state as Number).intValue))
      goaltemp.sendCommand(theArray1.get((stage2.state as Number).intValue))

by the way, the easy solution for fixing this problem is to change array numbers, for example if I change array1 and 2 to 5 and 6 and reset the openhab. it works for a while unless power outage happens then it may come back.
thanks

goalhumidity and goaltemp will only update if tooka3’s state is ON or rush175’s state is ON.

Those events.log entries don’t tell us what’s happening inside the rule so a first thing to do is add lots of logging.

But because most of those log entries you’ve posted happen within a second of each other, it’s likely the case that tooska3 is still in the process of becoming ON when the rule triggers, meaning it’s still OFF.

1 Like

thanks. I change the trigger to cron timer and add some loggings:

rule "qegr2sh"
when
    Time cron "0 0/1 * 1/1 * ? *"
then
    if(rush175.state == ON)  {
      logInfo("egr2sh", "before updating goaltemp for rush175 stage: " + stage2.state)
      goaltemp.sendCommand(theArray1.get((stage2.state as Number).intValue))

            logInfo("egr2sh", "before updating humidity for rush175 stage: " + stage2.state)
      goalhumidity.sendCommand(theArray2.get((stage2.state as Number).intValue))
      logInfo("egr2sh", "after updating goalhumidity for rush175 stage: " + stage2.state)



    }
 
    if(tooska3.state == ON)  {
            logInfo("egr2sh", "before updating goaltemp for tooska3 stage: " + stage2.state)

            goaltemp.sendCommand(theArray5.get((stage2.state as Number).intValue))
            logInfo("egr2sh", "before updating humidity for tooska3 stage: " + stage2.state)

      goalhumidity.sendCommand(theArray6.get((stage2.state as Number).intValue))
            logInfo("egr2sh", "after updating goalhumidity for tooska3 stage: " + stage2.state)


    }
    
    if((stage2.state as Number) > 48 && rush175.state == ON) {
      rush175.sendCommand("OFF")
    }
    if((stage2.state as Number) > 51 && tooska3.state == ON) {
      tooska3.sendCommand("OFF")
    }
end

after several reboots, the problems occurs and it seems that randomly one or several of my arrays are not initialized properly when system starts.
Here is the log when I start tooska3 or rush175, in both cases problem occurs:

2024-07-16 00:29:00.013 [INFO ] [clipse.smarthome.model.script.egr2sh] - before updating goaltemp for tooska3 stage: 5.0
2024-07-16 00:29:00.024 [INFO ] [clipse.smarthome.model.script.egr2sh] - before updating humidity for tooska3 stage: 5.0
2024-07-16 00:29:00.031 [ERROR] [ntime.internal.engine.ExecuteRuleJob] - Error during the execution of rule 'qegr2sh': cannot invoke method public java.lang.Object java.util.ArrayList.get(int) on null


2024-07-16 00:32:00.017 [INFO ] [clipse.smarthome.model.script.egr2sh] - before updating goaltemp for rush175 stage: 3
2024-07-16 00:32:00.023 [ERROR] [ntime.internal.engine.ExecuteRuleJob] - Error during the execution of rule 'qegr2sh': cannot invoke method public java.lang.Object java.util.ArrayList.get(int) on null

can I put arrays in system started rule? or any other solution? Thanks

You can but that’s only going to make sure that the arrays get populated even later. Global variables in Rules DSL get populated when the file is loaded which always happens before rules start triggering.

It’s really hard to undersand what’s going on. We don’t acually know what (stage2.state as Number).intValue is resolving to. Log that.

We don’t know what theArray5 and theArray6 are. Log those (btw, why such meaningless names? Variables should always have a meaningful and understandable name that describes it’s purpose).

null errors like that usually mean Rules DSL failed to coerce the arguments it’s passed into a type it can use, not that a variable is actually null. It’s one of the many reasons why I recommend no longer doing new development of rules using Rules DSL. These are existing rules so we must soldier on or rewrite them using a different language.

1 Like

thanks.
I added some logs.
(stage2.state as Number).intValue
is not a problem and each time it gets its value.
but trying to log arrays and it return null when problem occurs.
when openhab starts it gives me this error:

2024-07-16 01:53:53.697 [WARN ] [me.internal.engine.RuleContextHelper] - Variable 'theArray1' on rule file 'home.rules' cannot be initialized with value 'newArrayList(<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>)': The name 'newArrayList' cannot be resolved to an item or type; line 10, column 17, length 228
2024-07-16 01:53:53.715 [WARN ] [me.internal.engine.RuleContextHelper] - Variable 'theArray2' on rule file 'home.rules' cannot be initialized with value 'newArrayList(<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>,<XNumberLiteralImpl>)': The name 'newArrayList' cannot be resolved to an item or type; line 12, column 17, length 234

then in the logs, arrays which has problem are null.
I will change the naming and I want to upgrade to newer version. but this problem is causing me a lot of problem nowadays and we have a lot of power outage during the these days!

OK, that’s the root cause of the problem. Indeed it’s failing to initialize “theArray” variables. Why? :man_shrugging:

It seems like it’s not liking “newArrayList” perhaps? There are lots of other ways to create and initialize an ArrayList in Rules DSL. How to define global variables in Rules? shows one.

1 Like

Thanks a lot for your help and patience. :slightly_smiling_face:
problem solved. it seems that sometimes it is mistaken the array with object.
I populate each array when the specific process is called and define it with the way you’ve provided. after couple of days, it seems every thing work as expected.

import java.util.ArrayList

var Timer timer1 = null
var Timer timer2 = null
var Number tmcount


var ArrayList<Integer> temperatureArray = null
var ArrayList<Integer> humidityArray = null


rule "Restarting"
when
    System started
then
    createTimer(now.plusSeconds(3)) [|
        if(prepare.state == ON){
            createTimer(now.plusSeconds(2)) [| prepare.sendCommand(OFF) ]
            createTimer(now.plusSeconds(7)) [| set.sendCommand(OFF) ]
            createTimer(now.plusSeconds(14)) [| stage1.sendCommand(stage2.state as Number) ]
            createTimer(now.plusSeconds(19)) [| prepare.sendCommand(ON) ]
        }
    ]
end

rule "preparng"
when
    Item prepare received command ON
then
    if(rush175.state == ON) {
        temperatureArray = newArrayList(49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 55, 55, 55, 55, 55, 55, 55, 60, 60, 60, 60, 60, 60, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 71, 71, 71, 71, 71, 71)
        humidityArray = newArrayList(80, 80, 80, 80, 75, 75, 75, 75, 70, 70, 60, 60, 60, 50, 50, 50, 40, 40, 40, 40, 35, 35, 35, 35, 35, 35, 35, 31, 31, 31, 34, 34, 34, 34, 21, 21, 21, 21, 15, 15, 15, 15, 15, 15, 15, 15, 21, 21, 21, 21)
    }
    if(tooska3.state == ON) {
        temperatureArray = newArrayList(40, 40, 50, 50, 60, 60, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 49, 49, 49, 49, 49, 49, 54, 54, 54, 55, 55, 55, 60, 60, 60, 60, 60, 60, 60, 82, 82, 82)
        humidityArray = newArrayList(100, 100, 100, 100, 100, 100, 78, 78, 78, 78, 78, 78, 78, 78, 70, 70, 70, 70, 70, 70, 58, 58, 58, 58, 58, 58, 46, 46, 46, 46, 46, 46, 32, 32, 32, 32, 32, 32, 22, 22, 22, 22, 22, 22, 15, 15, 15, 15, 15, 15, 15, 26, 26, 26)
    }
    createTimer(now.plusSeconds(5)) [| 
        start.sendCommand("ON")
        tmcount = stage1.state as Number
        stage2.sendCommand(tmcount)
        Fan.sendCommand(ON)
        pause.sendCommand("OFF")
    ]
    
end

Thanks