Rule with average

This is the line that’s the problem.

var future_predictor = setInterval(MySampleCollector, interval_time); 

That line runs every time the script runs and every time it runs, it creates a new Interval.

That section of the code will indeed clear the interval once that specific timer reaches ten samples. But future_predictor won’t be pointing at that timer any more, it’ll point at the interval created in the most recent run of the rule. Every time the rule triggers, the rule also resets the sample_count and future_predictor.

Let’s imagine we trigger the rule three times within ten seconds.

  1. interval1 is created, sample _count is 0
  2. one second passes
  3. interval1 runs, sample_count is set to 1
  4. half a second passes, rule is triggered again
  5. sample_count is set back to 0, interval2 is created, reference to interval1 is lost
  6. half a second passes
  7. interval1 runs, sample_count is set to 1
  8. half a second passes, interval2 runs, sample_count is set to 2
  9. a quarter of a second passes, rule is triggered again
  10. sample_count is set back to 0, interval3 is created, reference to interval2 is now lost too

Hopefully you can see now how the intervals continue to build up. The rule doesn’t check before creating a new one so every time the rule runs it resets all the variables and creates a new interval without clearing the old one so the old one continues to run.

Now ten seconds have passed and we finally get to that block of code at the end of “do the math…”.

  1. interval1 reaches sample_count == number_of_samples_to_take
  2. clearInterval(interval3) gets called because future_predictor only points to the most recent interval created
  3. interval2 reaches sample count == number_of_samples_to_take
  4. clearInterval(interval3) gets called again

Interval3 got cancelled so it never runs again. But because interval1 and interval2 never got cleared, they continue to run every second forever or until they error out (the way it’s written it will never error out so the intervals continue forever).

In addition to increasing the likelihood of multithreaded exceptions, you can also expect that the time between samples gets shorter and shorter too as the separate intervals run at less than a second apart.

What I’m saying is you shouldn’t blindly create a new interval if one is already running. If you do need to create a new interval, clear the old one first.

The cache is mainly being used here because that’s the only way that the reference to the previously created interval on the previous run of the rule can be seen. Without using the cache, the reference gets lost and the second trigger of the rule can’t know that an interval is already running. The cache is how data can be persisted across multiple runs of the rule.

No, intervals and timers don’t consume a thread except when they are actively running so you’d never see more than one thread in use in any given thread dump. If two threads were to try to run at the same time the multithreaded access exception will be thrown.

I’m happy to clear up any confusion or mysteries on this topic.

Hi Rich,
I follow your points and understand how if the rule was retriggered during the sample interval that could happen and it would orphan the previous interval timer.
However if the rule was not retriggered during the 10 seconds the samples where being collected then it would run to completion clear the interval timer and on next trigger reset and start all over correct?
This was exactly why I asked OP to create a generic switch item to be turned on when rule started and then asked him to set his “But only if” conditions to only allow the rule to trigger when the switch was off. The “windspeed_monitor_cycle_active” variable was just a way for him to expand or add some bell , whistle other action to take only when it was running it was purely optional (actually a remnant of something else I use a similar rule for. And just left it in the code in case it was needed. Since this approach would not have blocked a rule trigger without as you say setting it in the cache and having the rule read its state). I saw that getting very complicated to try and explain to the OP so I avoided that approach. The main reason I did not do a list or even create an array or add a for loop was I wanted to keep the flow and script behavior as clear as possible since when someone is unfamiliar with scripting it is easier to explain a conditional if statement’s behavior and much easier for them to follow that flow. I also agree it had no error handling again same reasoning easy to explain. And yes I also agree recommending him to use Blockly would be better and make it easier for other folks to help him going forward.
what I had expected he would have ended up with was something like this

configuration: {}
triggers:
  - id: "2"
    configuration:
      itemName: Wind_Sensor
    type: core.ItemStateChangeTrigger
conditions:
  - inputs: {}
    id: "3"
    configuration:
      itemName: wind_monitor_active
      state: OFF
      operator: =
    type: core.ItemStateCondition
  - inputs: {}
    id: "4"
    configuration:
      itemName: Test_Roller_Shutter
      state: "0"
      operator: ">"
    type: core.ItemStateCondition
actions:
  - inputs: {}
    id: "1"
    configuration:
      type: application/javascript
      script: >+
        var current_windspeed = items.getItem('Wind_Sensor').numericState; //
        UPDATE THIS TO YOUR WIND SPEED SENSOR ITEM NAME this would be your item
        that provides the actual wind speed

        var windspeed_too_high = 32.60; //UPDATE THIS TO YOUR MAXIMUM WIND SPEED This sets your wind level to act on  so if your first wind speed change is greater or equal to this value then this your monitor will start

        var windspeed_super_high = 42.95; //UPDATE THIS FOR YOUR SUPER HIGH WIND VALUE 

        var number_of_samples_to_take = 10; //UPDATE THIS TO NUMBER OF SAMPLES TO COLLECT This sets your number of samples  if you change greater then 10 you must add samples and if statments to populate them

        var interval_time = 1000; // UPDATE THIS TO YOUR DESIRED INTERVAL TIME BETWEEN SAMPLES IN MILLISECONDS. 1000 milliseconds  = 1 second. This sets the interval time between samples value MUST be in milliseconds. 

        var windspeed_sample_sum = 0; //this is a sum of all 10 samples

        var windspeed_sample_1 = 0;  //this is your first live measurement during your 10 second intraval 

        var windspeed_sample_2 = 0;  //this is your second live measurement during your 10 second intraval

        var windspeed_sample_3 = 0;  //this is your third live measurement during your 10 second intraval

        var windspeed_sample_4 = 0;  //this is your forth live measurement during your 10 second intraval

        var windspeed_sample_5 = 0;  //this is your fifth live measurement during your 10 second intraval

        var windspeed_sample_6 = 0;  //this is your sixth live measurement during your 10 second intraval

        var windspeed_sample_7 = 0;  //this is your seventh live measurement during your 10 second intraval

        var windspeed_sample_8 = 0;  //this is your eighth live measurement during your 10 second intraval

        var windspeed_sample_9 = 0;  //this is your nineth live measurement during your 10 second intraval

        var windspeed_sample_10 = 0; //this is your tenth live measurement during your 10 second intraval

        var sample_count = 0; //this sets your count back to 0 at start of rule run

        var windspeed_monitor_cycle_active = 0; //This sets the state of your monitor  you could make this a switch item and when it is on then you could have your rule be blocked from retriggering till it is set to off after sample run is complete

        var wind_speed_average = 0; //this sets your wind speed average back to 0 at start of rule run

        var future_predictor = setInterval(MySampleCollector, interval_time); //this is your 1 second timer the interval time "interval_time" is in milliseconds you could change that to a higher of lower value as you see fit with the interval_time varible.


        if(current_windspeed >= windspeed_too_high) // this compares your wind speed value based on your first event change and if it the intial wind speed or gust is equal to or greater then the defined value it starts the counter 

          {
            windspeed_monitor_cycle_active = 1; //this sets the monitor cycle to track script is still running 
            items.getItem('wind_monitor_active').sendCommand('ON'); //UPDATE THIS TO YOUR GENERIC SWITCH ITEM USED TOO BLOCK/UNBLOCK RETRIGGER
            sample_count = 0;
            console.warn('Wind is too high starting monitor cycle '+'The wind speed is '+current_windspeed);
          }
        else if(current_windspeed < windspeed_too_high)

        {
          console.info('windspeed was not high enough to start measurement cycle ' + current_windspeed )
          clearInterval(future_predictor);
        } 

        function MySampleCollector()

        { 
          sample_count = sample_count + 1;


           
          if(sample_count == 1)
            {
             
             windspeed_sample_1 = items.getItem('Wind_Sensor').numericState; //UPDATE THIS TO YOUR WIND SENSOR ITEM NAME
            //windspeed_sample_1 = current_windspeed;    
            console.debug('this is windspeed at intraval 1 '+ windspeed_sample_1 );
            console.debug('this is sample_count '+ sample_count );
            
            }
          if(sample_count == 2)
           {
             windspeed_sample_2 = items.getItem('Wind_Sensor').numericState; //UPDATE THIS TO YOUR WIND SENSOR ITEM NAME
            //windspeed_sample_2 = current_windspeed;
            console.debug('this is windspeed at intraval 2 '+ windspeed_sample_2 );
            console.debug('this is sample_count '+ sample_count );
            
           }
          if(sample_count == 3)
           {
            windspeed_sample_3 = items.getItem('Wind_Sensor').numericState; //UPDATE THIS TO YOUR WIND SENSOR ITEM NAME
            //windspeed_sample_3 = current_windspeed;
            console.debug('this is windspeed at intraval 3 '+ windspeed_sample_3 );
            console.debug('this is sample_count '+ sample_count );
            
           }
          if(sample_count == 4)
           {
            windspeed_sample_4 = items.getItem('Wind_Sensor').numericState; //UPDATE THIS TO YOUR WIND SENSOR ITEM NAME
            //windspeed_sample_4 = current_windspeed;
            console.debug('this is windspeed at intraval 4 '+ windspeed_sample_4 );
            console.debug('this is sample_count '+ sample_count );
           
           }
          if(sample_count == 5)
           {
            windspeed_sample_5 = items.getItem('Wind_Sensor').numericState; //UPDATE THIS TO YOUR WIND SENSOR ITEM NAME
            //windspeed_sample_5 = current_windspeed;
            console.debug('this is windspeed at intraval 5 '+ windspeed_sample_5 );
            console.debug('this is sample_count '+ sample_count );
           }
          if(sample_count == 6)
           {
            windspeed_sample_6 = items.getItem('Wind_Sensor').numericState; //UPDATE THIS TO YOUR WIND SENSOR ITEM NAME
            //windspeed_sample_6 = current_windspeed;
            console.debug('this is windspeed at intraval 6 '+ windspeed_sample_6 );
            console.debug('this is sample_count '+ sample_count );
            
           }
          if(sample_count == 7)
           {
            windspeed_sample_7 = items.getItem('Wind_Sensor').numericState; //UPDATE THIS TO YOUR WIND SENSOR ITEM NAME
            //windspeed_sample_7 = current_windspeed;
            console.debug('this is windspeed at intraval 7 '+ windspeed_sample_7 );
            console.debug('this is sample_count '+ sample_count );
           }
          if(sample_count == 8)
           {
            windspeed_sample_8 = items.getItem('Wind_Sensor').numericState; //UPDATE THIS TO YOUR WIND SENSOR ITEM NAME
            //windspeed_sample_8 = current_windspeed;
            console.debug('this is windspeed at intraval 8 '+ windspeed_sample_8 );
            console.debug('this is sample_count '+ sample_count );
            
           }
          if(sample_count == 9)
           {
            windspeed_sample_9 = items.getItem('Wind_Sensor').numericState; //UPDATE THIS TO YOUR WIND SENSOR ITEM NAME
            //windspeed_sample_9 = current_windspeed;
            console.debug('this is windspeed at intraval 9 '+ windspeed_sample_9 );
            console.debug('this is sample_count '+ sample_count );
            
           }
          if(sample_count == 10)
           {
            windspeed_sample_10 = items.getItem('Wind_Sensor').numericState; //UPDATE THIS TO YOUR WIND SENSOR ITEM NAME
            //windspeed_sample_10 = current_windspeed;
            console.debug('this is windspeed at intraval 10 '+ windspeed_sample_10 );
            console.debug('this is sample_count '+ sample_count );
            
           }
           

            if(windspeed_monitor_cycle_active = 1)
              {
                 
                //you can uncomment use this as a way to show like maybe a change a icon or card background a switch state on your UI while monitor is running
                //items.GetItem('My_Generic_Switch').sendCommand('ON');
                
              }


           if(sample_count == number_of_samples_to_take)
            {
              console.debug('This is sample_count value = '+ sample_count +'  This is number of samples to take value = '+ number_of_samples_to_take );
              clearInterval(future_predictor);      
              windspeed_monitor_cycle_active = 0;
              items.getItem('wind_monitor_active').sendCommand('OFF'); //UPDATE THIS TO YOUR GENERIC SWITCH ITEM USED TOO BLOCK/UNBLOCK RETRIGGER 
              Do_all_math_and_control_shutter();
            }
        };

        function Do_all_math_and_control_shutter()

        {
         windspeed_sample_sum = (windspeed_sample_1 + windspeed_sample_2 + windspeed_sample_3 + windspeed_sample_4 + windspeed_sample_5
                                 + windspeed_sample_6 + windspeed_sample_7 + windspeed_sample_8 + windspeed_sample_9 + windspeed_sample_10);
         //var Wind_10_second_average = (windspeed_sample_sum / number_of_samples_to_take);

        wind_speed_average= (windspeed_sample_sum / number_of_samples_to_take);
          if(wind_speed_average >= windspeed_too_high)
            {  
              
            items.getItem('Test_Roller_Shutter').sendCommand('30'); //UPDATE THIS TO YOUR ROLLER SHUTTER CONTROL
            console.warn('wind is too high partly closing shutter '+ 'Wind speed average is '+ wind_speed_average ); 
            // action to partly close shutter to specific position 
            }





          
        else
          {
            console.info('wind is not high  '+ 'Wind speed average is '+ wind_speed_average );
            //No action required    
          }
          if(wind_speed_average >= windspeed_super_high)
              {
                items.getItem('Test_Roller_Shutter').sendCommand('10'); //UPDATE THIS TO YOUR ROLLER SHUTTER CONTROL
                console.warn('wind is super high fully closing shutter '+ 'Wind speed average is '+ wind_speed_average ); 
              // action to fully close shutter to specific position
              }
          
         console.debug('this is sum '+ windspeed_sample_sum );
         console.debug('this is '+number_of_samples_to_take+' second average '+ wind_speed_average );
         console.debug('this is sample_count '+ sample_count );
         sample_count = 0; 
        }
         



    type: script.ScriptAction

And I would not have thought this would create the error he mentioned.
So this is where I am still a bit unclear and why I was asking for his occurrences.
So based on this complete sample I posted above do you think this also would have caused the error or abandoned timers?

Correct, if you guarantee that the rule does not run in the ten seconds that the interval is running then there shouldn’t be a problem. But you repeatedly triggered the rule manually much faster than ten seconds and saw the multithreaded exception and I was explaining why and how to avoid that.

This is not a complete solution because of timing. It is possible for the rule to trigger and start running between the time the “locking” switch has the postUpdate to ON called and the Item actually updates to ON.

The problem with that variable, as implemented, was the same as future_predictor, it gets reset every time the rule runs.

It largely depends on how often the wind sensor reports. If it reports often (every second or less) the likelihood that the timing works out just wrong increases.

It would happen less often by a lot but it wouldn’t eliminate them. The timing could work out just right between updating the condition Item and the Item actually changing state that a second run of the rule would proceed when it’s not supposed to. A Switch Item makes a really poor lock.

A better approach to avoid that instead of a locking Item would be to not use setInterval, or timers at all. Instead use java.lang.Thread.sleep() instead. That will cause the rule to take ten seconds to run instead of pushing the loop into the background. That will guarantee that only one loop exists because nothing is running in the background. However, the rule will still get triggered and each one of those triggers will queue up and be worked off in sequence. You will very likely end up with a situation where the rule is never not running and is just constantly working off queued up triggers and never catching up.

The only full proof way to always avoid the problem even in those weird timing edge cases is to account for it in the code. You either need to take into account that whether the timer exists already or not before creating a new one or you need to not use timers in the first place.

One approach that would work given the approach above would be to use a cron trigger on the rule instead of using setInterval. Just let the rule run every second instead of based on when the wind Item is changing and when it gets to ten samples calculate the average and reset everything for the next run. Though you’d need to use Items or the cache to hold the samples, sum, and average.

As soon as timers come into play, anything you try to do to simplify the code is likely going to lead to problems. Timers are complex and need to be treated accordingly.

Hi Rich,
If I am understanding correctly what you are stating is the only reliable way to prevent a rule from retriggering is either sleep the thread for whatever time, or increase the I/O by having it read from cache? Whether to see if a timer has already been created to reuse “preventing the multithread error” or place some kind of flag file or other cache based approach.

I’m not saying that at all. I’m saying that in this particular case, the way the rule is implemented, the only reliable way to prevent the creation of multiple timers is to use the cache to test for the existence of a timer before creating a new one.

If one used the shared cache instead of the private one, one could add a script condition to check to see if a timer already exists in the cache and only pass if there isn’t one. That’s basically the same implementation but it uses a rule script condition instead of doing everything in the script action.

But it’s important to realize that reading one value from an in memory hashmap is hardly going to increase the load by any measurable amount and is not worth consideration. The cache is not written to disk so there is no increase in file I/O.

Here are some relevant facts about how OH works which are relevant here:

  1. Only one instance of a rule can run at a time as a result of a trigger. If the rule is already running at the time it’s triggered, that subsequent trigger is queued and they are worked off in order.

  2. The caches (both shared and private) are in memory hashmaps that live outside the rule. The values in the shared cache can be accessed from multiple scripts and multiple rules whereas the values in the private cache can only be accessed from the script that put it there. The caches are where you save values from one run of a rule to the next or where you save values to share between multiple scripts.

  3. The only way to completely prevent a rule’s actions from running is by disabling the rule. If you manually run the rule the rule conditions are not considered. If the rule is called from another rule, the caller gets to decide whether the conditions are considered. You should always code your action scripts under the assumption that they could run at any time. If there are situations where it shouldn’t do anything, or do something different based on what the previous run did (e.g. created a Timer), you need to store that information into the cache.

  4. Sending a command to an Item or posting an update are asynchronous and there can be some time between when the call to sendCommand or postUpdate returns and the Item actually receives and processes the event. The Item may not change state as a result of a command.

  5. GraalVM JS does not allow multiple threads to access a single context at the same time. A thread is accessing the context under the following circumstances:

  • when a script is running
  • when a timer is actively running
  • accessing non-primitive values from the cache (I’m not positive about this one, needs to be tested)
  • having two rules call the same rule at the same time
  1. There are locks placed around the context that prevent multiple threads from accessing many of the cases outlined in 5, but not all. When two threads attempt to access a context at the same time, the Multithreaded exception is thrown.

So, if we use a sleep instead of a timer, we are taking advantage of 1 above. Since the triggers are queued up instead of processed in parallel, we don’t have to worry about timers at all.

Using an Item as a lock doesn’t always work because of both 3 and 4.

But I want to emphasize I’m only talking about the way this particular rule is implemented. The context matters a lot.

For example, if the rule were implemented with a cron * * * * * ? * every second trigger then the rule would just run every second no matter what and there would be no risk of the exception at all. The implementation could look like this:

// Constants
var NUM_SAMPLES = 10; // sets the number of samples to use for the average
var WIND_THRESHOLD = 32.60; // could be in an Item
var WIND_HIGH_THRESHOLD = 42.95; // Could be in an Item

// Pull samples and index from cache
var currSampleIndex = (cache.private.get('i', () => -1) + 1) % NUM_SAMPLES; // calculate the next sample index, will cycle through 0 to 9 then back to 0, implementing a circular list
var samples = cache.private.get('samples', () => []); // store the number of samples in the cache as a JS array

// Calculate the average
samples[currSampleIndex] = items.Windspeed.numericState; // we do no need to preallocate the array in JS
var sum = samples.reduce( (result, a) => result + a, 0); // sum the members of the array
var avg = sum / sum.length; // calculate the average using the length of the array so the first nine samples still produce reasonable results

// store the index and samples back in the cache for the next run
cache.private.put('i', currSampleIndex);
cache.private.put('samples', samples);

var shutter = items.Test_Roller_Shutter;

// Control the shutter based on average wind speed
if(avg >= WIND_HIGH_THRESHOLD && shutter.numericState > 10) {
  shutter.sendCommand('10');
  console.warn('wind is super high fully closing shutter, wind speed average is ' + avg);
}
else if(avg >= WIND_THRESHOLD && shutter.numericState > 30) {
  shutter.sendCommand('30');
  console.warn('wind is too high partly closing shutter, wind speed average is ' + avg);
}
else {
  console.info('wind is no high, wind speed average is ' + avg);
}  

With this approach there is never any problem with multithreaded exceptions because the rule just runs every second without fail. And because it keeps a running average instead of taking an average every ten seconds, this approach is more responsive because the second that the average rises above the thresholds the action is taken. With the interval approach it can be up to ten seconds before the average is taken and the shutters are lowered.

I do a couple of intermediate JavaScript operations above but, given the improvement to understandability and long term maintainability it’s my opinion it’s worth the effort to understand them.

Line What’s going on
cache.private.get('i', () => -1 Pull the last index i from the cache. If it doesn’t exist, initialize it in the cache as -1 and return that.
var currSampleIndex = (cache.private.get('i', () => -1) + 1) % NUM_SAMPLES; Once the last index is pulled from the cache, add one and then do a modulo (aka remainder) with NUM_SAMPLES. So when the value gets to 10 it will return 0 and start the index over again. This creates a circular index which goes from 0 to 9 and back to 0.
var samples = cache.private.get('samples', () => []); Pull the list of samples from the cache. If it doesn’t exist initialize the cache with an empty list and return that.
samples[currSampleIndex] = items.Windspeed.numericState; Store the current windspeed in the list. In JavaScript you do not need to preallocate the array so the array will grow as needed.
var sum = samples.reduce( (result, a) => result + a, 0); JS Arrays (other languages too) support powerful operations that can manipulate the values of an array. I’m using reduce here to sum up all the members of the array. See JavaScript Array reduce() Method

Everything else is straight forward basic JavaScript.

The above is very implementable using Blockly as well.

Got it so you are actually saying the only way to prevent a rule from retriggering is to disable the rule.

I also understand manually triggering the rule ignores the conditions that is not what I would consider a “normal user use case”
All other options are creating solutions that either consume more of the memory footprint and / or additional CPU cycles. like in the example of the rule never stops running.
Thank you for the clarification.

In a home automation context, more memory or additional CPU cycles almost never matter. You should never avoid something because because it’s “less efficient” in your rules until you know it actually causes efficiency problems. Having code that is relatively simple, easy to understand and maintain in the long run and remains robust (i.e. won’t fail on edge cases or timing of events type issues) is way more important than a few dozen extra CPU cycles or a couple kB of RAM.

Even on an RPi 3 you pretty much have to try to write a rule whose impact on the overall system resources is measurable. It’s not going to happen by accident and it’s definitely not going to happen by using features like the cache.

But, if resources are a concern just because, the cron triggered rule above uses fewer resources than the setInterval approach because the rule is shorter and it doesn’t require all the infrastructure built around storing, scheduling, and running a Timer. Both the CPU and RAM required to store 11 numbers in the cache is orders of magnitude smaller than the amount of CPU and RAM required to create and run a timer. But even then we are talking about CPU cycles and RAM amounts so low you couldn’t even measure it.

Thanks again Rich for the clarifications.
I will leave this discussion alone going any further is not fruitful.
Folks should aways decide themselves how much TSR they really want in their systems as long as they understand that is what they are creating.

2024-05-03 21:36:09.226 [WARN ] [ore.internal.scheduler.SchedulerImpl] - Scheduled job 'sampleCollector' failed and stopped
java.lang.IllegalStateException: Multi threaded access requested by thread Thread[OH-scheduler-11,5,main] but is not allowed for language(s) js.
	at com.oracle.truffle.polyglot.PolyglotEngineException.illegalState(PolyglotEngineException.java:129) ~[?:?]
	at com.oracle.truffle.polyglot.PolyglotContextImpl.throwDeniedThreadAccess(PolyglotContextImpl.java:1034) ~[?:?]
	at com.oracle.truffle.polyglot.PolyglotContextImpl.checkAllThreadAccesses(PolyglotContextImpl.java:893) ~[?:?]
	at com.oracle.truffle.polyglot.PolyglotContextImpl.enterThreadChanged(PolyglotContextImpl.java:723) ~[?:?]
	at com.oracle.truffle.polyglot.PolyglotEngineImpl.enterCached(PolyglotEngineImpl.java:1991) ~[?:?]
	at com.oracle.truffle.polyglot.HostToGuestRootNode.execute(HostToGuestRootNode.java:110) ~[?:?]
	at com.oracle.truffle.api.impl.DefaultCallTarget.callDirectOrIndirect(DefaultCallTarget.java:85) ~[?:?]
	at com.oracle.truffle.api.impl.DefaultCallTarget.call(DefaultCallTarget.java:102) ~[?:?]
	at com.oracle.truffle.polyglot.PolyglotFunctionProxyHandler.invoke(PolyglotFunctionProxyHandler.java:154) ~[?:?]
	at jdk.proxy1.$Proxy417.run(Unknown Source) ~[?:?]
	at org.openhab.automation.jsscripting.internal.threading.ThreadsafeTimers.lambda$0(ThreadsafeTimers.java:85) ~[?:?]
	at org.openhab.core.internal.scheduler.SchedulerImpl.lambda$12(SchedulerImpl.java:189) ~[?:?]
	at org.openhab.core.internal.scheduler.SchedulerImpl.lambda$1(SchedulerImpl.java:88) ~[?:?]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) [?:?]
	at java.util.concurrent.FutureTask.run(FutureTask.java:264) [?:?]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) [?:?]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) [?:?]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) [?:?]
	at java.lang.Thread.run(Thread.java:833) [?:?]
Caused by: com.oracle.truffle.api.TruffleStackTrace$LazyStackTrace

Hi tried to follow your discussion, got lost obviously. My initial intention was to extend my old rule to roll the shutter up and building step by step a rule to move dynamically my shutter based on calculate virtual outside solar light and wind condition, to roll them up partially or totally on windspeed average and even to roll them back if the wind get low during the day. Is it for your experience possible that?

Tried to copy with blocky Rich’s rule adding a second command for “windspeed super high” and found this warn in the logs
Is it that because I added a “wind:super_high” trigger command?
Don’t know if it helps somehow.
My shutter never received command “100” only “70” also if the average was higher then super_high_windspeed trigger. Do I put the command in a wrong way?
Thank you both of for your time and to Rich who gave me an example building rule with Blocky.

anything is possible you just need to understand how the code flows.
you may want to start by having 2 different rules just to understand how they each work and then later after you have clearly grasped how each rule interacts independently try combine approaches

I still do not think this is due to having the 2 commands

You may want to read here

Thank you for your reply justaold man
I have changed the rule in this

the problem is that once triggered the rule doesn’t stop the cycle even if the sensor is inactive and my shutter recive command 70 and 100 repeatedly. This is the logs

2024-05-04 09:27:58.326 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Tende' received command 70
2024-05-04 09:27:58.330 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Tendadasole4_BlindsControl' received command 70
2024-05-04 09:27:58.339 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Tendadasole3_BlindsControl' received command 70
2024-05-04 09:27:58.341 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Tendadasole5_BlindsControl' received command 70
2024-05-04 09:27:58.351 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Tende' received command 100
2024-05-04 09:27:58.355 [INFO ] [hab.event.GroupItemStateChangedEvent] - Item 'Tende_terrazzo' changed from 100.00000000 to 70.00000000 through Tende
2024-05-04 09:27:58.359 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Tendadasole4_BlindsControl' changed from 100 to 70
2024-05-04 09:27:58.367 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Tendadasole4_BlindsControl' received command 100
2024-05-04 09:27:58.375 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Tendadasole3_BlindsControl' received command 100
2024-05-04 09:27:58.384 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Tendadasole5_BlindsControl' received command 100
2024-05-04 09:27:58.389 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Tendadasole3_BlindsControl' changed from 100 to 70
2024-05-04 09:27:58.394 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Tendadasole5_BlindsControl' changed from 100 to 70
2024-05-04 09:27:58.399 [INFO ] [hab.event.GroupItemStateChangedEvent] - Item 'Tende' changed from 100 to 70.00000000 through Tendadasole4_BlindsControl
2024-05-04 09:27:58.402 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Tendadasole4_BlindsControl' changed from 70 to 100
2024-05-04 09:27:58.404 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Tendadasole3_BlindsControl' changed from 70 to 100
2024-05-04 09:27:58.406 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Tendadasole5_BlindsControl' changed from 70 to 100
2024-05-04 09:27:58.408 [INFO ] [hab.event.GroupItemStateChangedEvent] - Item 'Tende' changed from 70.00000000 to 100.00000000 through Tendadasole5_BlindsControl
2024-05-04 09:27:58.411 [INFO ] [hab.event.GroupItemStateChangedEvent] - Item 'Tende_terrazzo' changed from 70.00000000 to 100.00000000 through Tende
2024-05-04 09:27:59.263 [INFO ] [openhab.event.ChannelTriggeredEvent ] - mqtt:broker:8a2724a23e:Publish triggered 9.48
2024-05-04 09:27:59.268 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Vento_Terrazza' changed from 12.4 km/h to 9.48 km/h
==> /var/log/openhab/openhab.log <==
2024-05-04 09:27:59.389 [WARN ] [nhab.automation.script.ui.97ba6d2f35] - this is wind speed interval121.31This is a sample_ count1
==> /var/log/openhab/events.log <==
2024-05-04 09:28:00.054 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Tv_salone__Forza_del_Segnale' changed from 2 to 1
2024-05-04 09:28:00.263 [INFO ] [openhab.event.ChannelTriggeredEvent ] - mqtt:broker:8a2724a23e:Publish triggered 12.40
2024-05-04 09:28:00.267 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Vento_Terrazza' changed from 9.48 km/h to 12.4 km/h
==> /var/log/openhab/openhab.log <==
2024-05-04 09:28:00.394 [WARN ] [nhab.automation.script.ui.97ba6d2f35] - this is wind speed interval221.31This is a sample_ count2
==> /var/log/openhab/events.log <==
2024-05-04 09:28:01.264 [INFO ] [openhab.event.ChannelTriggeredEvent ] - mqtt:broker:8a2724a23e:Publish triggered 9.48
2024-05-04 09:28:01.280 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Vento_Terrazza' changed from 12.4 km/h to 9.48 km/h
==> /var/log/openhab/openhab.log <==
2024-05-04 09:28:01.399 [WARN ] [nhab.automation.script.ui.97ba6d2f35] - this is wind speed interval321.31This is a sample_ count3
2024-05-04 09:28:02.404 [WARN ] [nhab.automation.script.ui.97ba6d2f35] - this is wind speed interval421.31This is a sample_ count4
2024-05-04 09:28:03.410 [WARN ] [nhab.automation.script.ui.97ba6d2f35] - this is wind speed interval521.31This is a sample_ count5
2024-05-04 09:28:04.419 [WARN ] [nhab.automation.script.ui.97ba6d2f35] - this is wind speed interval621.31This is a sample_ count6
2024-05-04 09:28:04.421 [WARN ] [nhab.automation.script.ui.97ba6d2f35] - Wind speed too high closing shutter149.16999999999985
==> /var/log/openhab/events.log <==
2024-05-04 09:28:04.424 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Tende' received command 70
==> /var/log/openhab/openhab.log <==
2024-05-04 09:28:04.424 [WARN ] [nhab.automation.script.ui.97ba6d2f35] - Wind speed super high closing shutter149.16999999999985
==> /var/log/openhab/events.log <==
2024-05-04 09:28:04.425 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Tendadasole4_BlindsControl' received command 70
2024-05-04 09:28:04.427 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Tendadasole3_BlindsControl' received command 70
2024-05-04 09:28:04.428 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Tendadasole5_BlindsControl' received command 70
2024-05-04 09:28:04.430 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Tende' received command 100
2024-05-04 09:28:04.432 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Tendadasole4_BlindsControl' received command 100
2024-05-04 09:28:04.433 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Tendadasole3_BlindsControl' received command 100
2024-05-04 09:28:04.434 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Tendadasole5_BlindsControl' received command 100
2024-05-04 09:28:04.443 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Tendadasole4_BlindsControl' changed from 100 to 70
2024-05-04 09:28:04.447 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Tendadasole3_BlindsControl' changed from 100 to 70
2024-05-04 09:28:04.450 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Tendadasole5_BlindsControl' changed from 100 to 70
2024-05-04 09:28:04.452 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Tendadasole4_BlindsControl' changed from 70 to 100
2024-05-04 09:28:04.458 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Tendadasole3_BlindsControl' changed from 70 to 100
2024-05-04 09:28:04.460 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Tendadasole5_BlindsControl' changed from 70 to 100
2024-05-04 09:28:05.269 [INFO ] [openhab.event.ChannelTriggeredEvent ] - mqtt:broker:8a2724a23e:Publish triggered 6.61
2024-05-04 09:28:05.273 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Vento_Terrazza' changed from 9.48 km/h to 6.61 km/h
==> /var/log/openhab/openhab.log <==
2024-05-04 09:28:05.434 [WARN ] [nhab.automation.script.ui.97ba6d2f35] - this is wind speed interval121.31This is a sample_ count1
==> /var/log/openhab/events.log <==
2024-05-04 09:28:05.812 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Vento_vetrata' changed from 0 km/h to 3.89 km/h
==> /var/log/openhab/openhab.log <==
2024-05-04 09:28:06.439 [WARN ] [nhab.automation.script.ui.97ba6d2f35] - this is wind speed interval221.31This is a sample_ count2
==> /var/log/openhab/events.log <==
2024-05-04 09:28:06.814 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Vento_vetrata' changed from 3.89 km/h to 0 km/h
==> /var/log/openhab/openhab.log <==
2024-05-04 09:28:07.445 [WARN ] [nhab.automation.script.ui.97ba6d2f35] - this is wind speed interval321.31This is a sample_ count3
==> /var/log/openhab/events.log <==
2024-05-04 09:28:08.061 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Tende' received command STOP
2024-05-04 09:28:08.065 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Tendadasole4_BlindsControl' received command STOP
2024-05-04 09:28:08.067 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Tendadasole3_BlindsControl' received command STOP
2024-05-04 09:28:08.068 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Tendadasole5_BlindsControl' received command STOP
==> /var/log/openhab/openhab.log <==
2024-05-04 09:28:08.449 [WARN ] [nhab.automation.script.ui.97ba6d2f35] - this is wind speed interval421.31This is a sample_ count4
2024-05-04 09:28:09.455 [WARN ] [nhab.automation.script.ui.97ba6d2f35] - this is wind speed interval521.31This is a sample_ count5
2024-05-04 09:28:10.462 [WARN ] [nhab.automation.script.ui.97ba6d2f35] - this is wind speed interval621.31This is a sample_ count6
2024-05-04 09:28:10.466 [WARN ] [nhab.automation.script.ui.97ba6d2f35] - Wind speed too high closing shutter170.4799999999998
2024-05-04 09:28:10.468 [WARN ] [nhab.automation.script.ui.97ba6d2f35] - Wind speed super high closing shutter170.4799999999998
==> /var/log/openhab/events.log <==
2024-05-04 09:28:10.468 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Tende' received command 70
2024-05-04 09:28:10.475 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Tendadasole4_BlindsControl' received command 70
2024-05-04 09:28:10.482 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Tendadasole3_BlindsControl' received command 70
2024-05-04 09:28:10.483 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Tendadasole5_BlindsControl' received command 70
2024-05-04 09:28:10.485 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Tende' received command 100
2024-05-04 09:28:10.486 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Tendadasole4_BlindsControl' received command 100
2024-05-04 09:28:10.488 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Tendadasole3_BlindsControl' received command 100
2024-05-04 09:28:10.489 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'Tendadasole5_BlindsControl' received command 100
2024-05-04 09:28:10.490 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Tendadasole4_BlindsControl' changed from 100 to 70
2024-05-04 09:28:10.494 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Tendadasole3_BlindsControl' changed from 100 to 70
2024-05-04 09:28:10.505 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Tendadasole5_BlindsControl' changed from 100 to 70
2024-05-04 09:28:10.508 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Tendadasole4_BlindsControl' changed from 70 to 100
2024-05-04 09:28:10.513 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Tendadasole3_BlindsControl' changed from 70 to 100
2024-05-04 09:28:10.515 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'Tendadasole5_BlindsControl' changed from 70 to 100
2024-05-04 09:28:10.516 [INFO ] [hab.event.GroupItemStateChangedEvent] - Item 'Tende_terrazzo' changed from 70.00000000 to 100.00000000 through Tende
2024-05-04 09:28:10.517 [INFO ] [hab.event.GroupItemStateChangedEvent] - Item 'Tende_terrazzo' changed from 100.00000000 to 70.00000000 through Tende

How often does the wind Item update?

Post the code generated by the blocks.

I agree it’s not because of the two commands. I’m not sure what it causing it though. Despite all that has been posted here, there isn’t enough information to diagnose the source of the problem.

I might have made an assumption somewhere that doesn’t hold true. Seeing the code generated by the blocks will help.

However, I think it might be prudent to move to the cron based approach like I posted above, at least for the short run. It eliminates all the complexities that come with managing a timer and it provides a running average as opposed to a ten second average every ten seconds. This should make it much easier to debug. This also eliminates any possibility of the multithreaded exception because there are never any timers running in the background. And by eliminating the timer, the whole logic becomes more straight forward overall. This version should be easier to debug and expand/adjust going forward.

As I wrote above, use a time based trigger using the cron expression above to run every second. Then the Blockly version of the code will look something like this:


`
Be sure to set the MyItem blocks to your Items. You can adjust the thresholds and number of samples to tune the behavior. For example, a smaller NUM_SAMPLES will make the rule more responsive since it will be averaging fewer readings, but it will also be more variable.

The rule will run once a second, record a sample and throw away the oldest sample, and calculate the average of the samples. So if NUM_SAMPLES is 10, it will calculate a ten second running average every second. Then it adjusts the rollershutters based on that running average.

Hi Rich thank you for your time.
Just done. This is the logs

2024-05-04 17:58:07.264 [ERROR] [b.automation.script.javascript.stack] - Failed to execute script:
org.graalvm.polyglot.PolyglotException: TypeError: invokeMember (getItem) on org.openhab.core.internal.items.ItemRegistryImpl@16d33a8 failed due to: Cannot convert '[object Object]'(language: JavaScript, type: Item) to Java type 'java.lang.String': Invalid or lossy primitive coercion.
	at <js>.getItem(/node_modules/openhab.js:2) ~[?:?]
	at <js>.:program(<eval>:11) ~[?:?]
	at org.graalvm.polyglot.Context.eval(Context.java:399) ~[?:?]
	at com.oracle.truffle.js.scriptengine.GraalJSScriptEngine.eval(GraalJSScriptEngine.java:458) ~[?:?]
	at com.oracle.truffle.js.scriptengine.GraalJSScriptEngine.eval(GraalJSScriptEngine.java:426) ~[?:?]
	at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:262) ~[java.scripting:?]
	at org.openhab.automation.jsscripting.internal.scriptengine.DelegatingScriptEngineWithInvocableAndAutocloseable.eval(DelegatingScriptEngineWithInvocableAndAutocloseable.java:53) ~[?:?]
	at org.openhab.automation.jsscripting.internal.scriptengine.InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.eval(InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.java:78) ~[?:?]
	at org.openhab.automation.jsscripting.internal.scriptengine.DelegatingScriptEngineWithInvocableAndAutocloseable.eval(DelegatingScriptEngineWithInvocableAndAutocloseable.java:53) ~[?:?]
	at org.openhab.automation.jsscripting.internal.scriptengine.InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.eval(InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.java:78) ~[?:?]
	at org.openhab.core.automation.module.script.internal.handler.ScriptActionHandler.lambda$0(ScriptActionHandler.java:71) ~[?:?]
	at java.util.Optional.ifPresent(Optional.java:178) [?:?]
	at org.openhab.core.automation.module.script.internal.handler.ScriptActionHandler.execute(ScriptActionHandler.java:68) [bundleFile:?]
	at org.openhab.core.automation.internal.RuleEngineImpl.executeActions(RuleEngineImpl.java:1188) [bundleFile:?]
	at org.openhab.core.automation.internal.RuleEngineImpl.runRule(RuleEngineImpl.java:997) [bundleFile:?]
	at org.openhab.core.automation.internal.TriggerHandlerCallbackImpl$TriggerData.run(TriggerHandlerCallbackImpl.java:87) [bundleFile:?]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) [?:?]
	at java.util.concurrent.FutureTask.run(FutureTask.java:264) [?:?]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) [?:?]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) [?:?]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) [?:?]
	at java.lang.Thread.run(Thread.java:833) [?:?]
2024-05-04 17:58:07.275 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID '97ba6d2f35' failed: org.graalvm.polyglot.PolyglotException: TypeError: invokeMember (getItem) on org.openhab.core.internal.items.ItemRegistryImpl@16d33a8 failed due to: Cannot convert '[object Object]'(language: JavaScript, type: Item) to Java type 'java.lang.String': Invalid or lossy primitive coercion.

2024-05-04 18:00:23.450 [ERROR] [b.automation.script.javascript.stack] - Failed to execute script:
org.graalvm.polyglot.PolyglotException: TypeError: invokeMember (getItem) on org.openhab.core.internal.items.ItemRegistryImpl@16d33a8 failed due to: Cannot convert '[object Object]'(language: JavaScript, type: Item) to Java type 'java.lang.String': Invalid or lossy primitive coercion.
	at <js>.getItem(/node_modules/openhab.js:2) ~[?:?]
	at <js>.:program(<eval>:11) ~[?:?]
	at org.graalvm.polyglot.Context.eval(Context.java:399) ~[?:?]
	at com.oracle.truffle.js.scriptengine.GraalJSScriptEngine.eval(GraalJSScriptEngine.java:458) ~[?:?]
	at com.oracle.truffle.js.scriptengine.GraalJSScriptEngine.eval(GraalJSScriptEngine.java:426) ~[?:?]
	at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:262) ~[java.scripting:?]
	at org.openhab.automation.jsscripting.internal.scriptengine.DelegatingScriptEngineWithInvocableAndAutocloseable.eval(DelegatingScriptEngineWithInvocableAndAutocloseable.java:53) ~[?:?]
	at org.openhab.automation.jsscripting.internal.scriptengine.InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.eval(InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.java:78) ~[?:?]
	at org.openhab.automation.jsscripting.internal.scriptengine.DelegatingScriptEngineWithInvocableAndAutocloseable.eval(DelegatingScriptEngineWithInvocableAndAutocloseable.java:53) ~[?:?]
	at org.openhab.automation.jsscripting.internal.scriptengine.InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.eval(InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.java:78) ~[?:?]
	at org.openhab.core.automation.module.script.internal.handler.ScriptActionHandler.lambda$0(ScriptActionHandler.java:71) ~[?:?]
	at java.util.Optional.ifPresent(Optional.java:178) [?:?]
	at org.openhab.core.automation.module.script.internal.handler.ScriptActionHandler.execute(ScriptActionHandler.java:68) [bundleFile:?]
	at org.openhab.core.automation.internal.RuleEngineImpl.executeActions(RuleEngineImpl.java:1188) [bundleFile:?]
	at org.openhab.core.automation.internal.RuleEngineImpl.runRule(RuleEngineImpl.java:997) [bundleFile:?]
	at org.openhab.core.automation.internal.TriggerHandlerCallbackImpl$TriggerData.run(TriggerHandlerCallbackImpl.java:87) [bundleFile:?]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) [?:?]
	at java.util.concurrent.FutureTask.run(FutureTask.java:264) [?:?]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) [?:?]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) [?:?]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) [?:?]
	at java.lang.Thread.run(Thread.java:833) [?:?]
2024-05-04 18:00:23.456 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID '97ba6d2f35' failed: org.graalvm.polyglot.PolyglotException: TypeError: invokeMember (getItem) on org.openhab.core.internal.items.ItemRegistryImpl@16d33a8 failed due to: Cannot convert '[object Object]'(language: JavaScript, type: Item) to Java type 'java.lang.String': Invalid or lossy primitive coercion.

Thank you for your time.

My sensor item is updated on every change over mqqt messages
And my roller state 100 is fully up, 0 is fully down so I have changed according hope without errors your rule.

I think I see the error.

On the line that sets “shutterState”, it should read “set shutterState to get numeric state of item shutterItem”, not “set shutterState to get numeric state of item get item shutterItem”

Post the code that is generated by the blockly. It’s impossible to tell which block is throwing that error, but with the code I can find the line number reported in the exception (line 11).

Hi,
As @rlkoshak has asked you already please post the code behind your blocky.
Once you have eliminated this latest new error

Keep in mind regardless of the approach you go with timers or continuous run cron expression The rule with keep sending the commands to take action to the shutter repeatedly.
The reason is you do not have a condition check to block the sending of the command if the shutter value is already completed.
The if check for wind speed also needs an additional check to confirm the shutter is not already in the state the command would tell it to go to. Otherwise, it will spam your event bus because the wind speed check is greater than the threshold resolves to a true condition until the wind speed drops below the exceed value.
Edit: Never Mind I saw in your latest post and version you added that check .

Even though the latest versions of the code do have the checks in place, I just want to mention that repeatedly commanding the Item even when it’s not needed is not necessarily a problem, so long as the developer is aware that will happen.

I will defer offering an opinion on that statement and refrain from further engaging in what if discussions.

I don’t understand this statement at all.

Your reply does strongly imply an opinion and my statement isn’t a what if discussion. Given how OH works, the bindings, and the underlying technologies, sending a command to an Item that doesn’t need it does not always cause problem. In fact it rarely causes a problem. You can test that your yourself, anyone can. It’s super easy to test.

Even though it came as a reply to you, my statement wasn’t really even directed at you. It was directed at @Jadblack and future readers of the tread. Essentially I’m saying “hey man, don’t worry about the extra commands, they aren’t hurting anything, let’s focus on what’s not working”.

But if you want to not talk about it by announcing how you’re not going to talk about it, that’s fine too. You seem to be taking issue with something I’ve said so maybe I should just bow out. I can’t imagine how I may have caused offense but if I have, I apologize.

Hi @rlkoshak ,
No offense taken and no apologies needed.
I was trying to step back from the topic of repeating commands as I had very much earlier in the long number of posts in this chain made the same statement regarding extra commands and at least one way he could avoid that.

So, I did not want to repeat what I had offered the OP originally around setting a condition to avoid sending the command after it was already complete.

1 Like

Hello, I have corrected the rule as suggested by Rich and this is the code generated

configuration: {}
triggers:
  - id: "2"
    configuration:
      itemName: Vento_vetrata
    type: core.ItemStateChangeTrigger
conditions: []
actions:
  - inputs: {}
    id: "1"
    configuration:
      blockSource: <xml
        xmlns="https://developers.google.com/blockly/xml"><variables><variable
        id="#:-(Xt]*D+.de6X:lrik">NUM_SAMPLES</variable><variable
        id="Ub}(f?.}5AL*r3U;}y*(">WIND_THREHOLD</variable><variable
        id="}WcUTMxq~IGApQ2.hE:o">WIND_THREHOLD_HIGH</variable><variable
        id="H^#H[AJ@T-iM6Y/TK]dm">WIND_HIDH_ROLLERSHUTTER</variable><variable
        id="+dTtO4*p?H)XqOTh^j,b">WIND_ROLLERSHUTTER</variable><variable
        id="[xzFcQtH8S`L$J.+l14N">curSpeed</variable><variable
        id="6j5zHjQ+K:Sy-Rdr_oUk">shutterItem</variable><variable
        id="OP!..;87,m?]t/$kO3?P">shutterState</variable><variable
        id="^bgxT=plTgkB,N8?:gof">samples</variable><variable
        id="Tp}bOW}QL(O{(ZjheYJ/">index</variable><variable
        id="sMuBpxdu({kT`5VuK8R`">sum</variable><variable
        id="X]rxixgS(FcHlxFz]Kl!">j</variable><variable
        id="X[B(JDe/;c#]7XH=V8N+">avg</variable></variables><block
        type="variables_set" id="L8,%GbB=G?MBx}e|3Ol5" x="727" y="-336"><field
        name="VAR" id="#:-(Xt]*D+.de6X:lrik">NUM_SAMPLES</field><value
        name="VALUE"><block type="math_number" id="U!0M[,IR$;be(3Q%5g#,"><field
        name="NUM">6</field></block></value><next><block type="variables_set"
        id="CZ$R8Q9_26S,+LBV:*f6"><field name="VAR"
        id="Ub}(f?.}5AL*r3U;}y*(">WIND_THREHOLD</field><value
        name="VALUE"><block type="math_number" id="ict48-{{^?XN3bwRQ//_"><field
        name="NUM">14</field></block></value><next><block type="variables_set"
        id="151w]W];p#x+_ls`VDUD"><field name="VAR"
        id="}WcUTMxq~IGApQ2.hE:o">WIND_THREHOLD_HIGH</field><value
        name="VALUE"><block type="math_number" id="l{S%#{)/:u/HGA@*_Rp7"><field
        name="NUM">25</field></block></value><next><block type="variables_set"
        id="`B|FIZJi9g6B,1)B?fNv"><field name="VAR"
        id="H^#H[AJ@T-iM6Y/TK]dm">WIND_HIDH_ROLLERSHUTTER</field><value
        name="VALUE"><block type="math_number" id="fmAa5KqL{l;YIl1gsFQx"><field
        name="NUM">100</field></block></value><next><block type="variables_set"
        id="@R1@ndF%8Z+!S.A1%HR."><field name="VAR"
        id="+dTtO4*p?H)XqOTh^j,b">WIND_ROLLERSHUTTER</field><value
        name="VALUE"><block type="math_number" id="zndsqWGRH$|nvt6fFrAS"><field
        name="NUM">70</field></block></value><next><block type="variables_set"
        id="o=gh-tT@VTEkjW,4[E}B"><field name="VAR"
        id="[xzFcQtH8S`L$J.+l14N">curSpeed</field><value name="VALUE"><block
        type="oh_getitem_attribute" id="I4S`Qn3Iq+kpo!r8[O{0"><mutation
        attributeName="NumericState"></mutation><field
        name="attributeName">NumericState</field><value name="item"><shadow
        type="oh_getitem" id="Lig3=AE5WV]J%Wdg|c`!"><value
        name="itemName"><shadow type="oh_item"
        id="36]_(7@jkjaUg`RL/s{S"><mutation itemName="MyItem"
        itemLabel="MyItem"></mutation><field
        name="itemName">MyItem</field></shadow></value></shadow><block
        type="oh_getitem" id=":R7RWur]J}uLnDs{Ldhi"><value
        name="itemName"><shadow type="oh_item"
        id="|d}mSoZ%R!fj?(-2SXV4"><mutation itemName="MyItem"
        itemLabel="MyItem"></mutation><field
        name="itemName">MyItem</field></shadow><block type="oh_item"
        id=";`jOCzu(R04:0;*/|^R,"><mutation itemName="Vento_vetrata"
        itemLabel="Vento vetrata"></mutation><field
        name="itemName">Vento_vetrata</field></block></value></block></value></block></value><next><block
        type="variables_set" id=";ul^_PP2pQEpPm8mNvF5"><field name="VAR"
        id="6j5zHjQ+K:Sy-Rdr_oUk">shutterItem</field><value name="VALUE"><block
        type="oh_getitem" id="A.L4Y}@a3K[j5`-b,gcc"><value
        name="itemName"><shadow type="oh_item"
        id="jR_?qSHz;z_d5P4}x]v1"><mutation itemName="MyItem"
        itemLabel="MyItem"></mutation><field
        name="itemName">MyItem</field></shadow><block type="oh_item"
        id="pKC0_N0Os:7k@l?@Cdw%"><mutation itemName="Tende" itemLabel="Tende
        vetrata"></mutation><field
        name="itemName">Tende</field></block></value></block></value><next><block
        type="variables_set" id="OlZo#L$[H|rA9T`rmJ)R"><field name="VAR"
        id="OP!..;87,m?]t/$kO3?P">shutterState</field><value name="VALUE"><block
        type="oh_getitem_attribute" id="Q*`1~pi}jt4PvyWUY_=]"><mutation
        attributeName="NumericState"></mutation><field
        name="attributeName">NumericState</field><value name="item"><shadow
        type="oh_getitem" id="Lig3=AE5WV]J%Wdg|c`!"><value
        name="itemName"><shadow type="oh_item"
        id="36]_(7@jkjaUg`RL/s{S"><mutation itemName="MyItem"
        itemLabel="MyItem"></mutation><field
        name="itemName">MyItem</field></shadow></value></shadow><block
        type="variables_get" id="?LpH4WT~-P7kAllH^;jp"><field name="VAR"
        id="6j5zHjQ+K:Sy-Rdr_oUk">shutterItem</field></block></value></block></value><next><block
        type="controls_if" id="z@Jks29DKPl[$xEb9Zg~"><value name="IF0"><block
        type="oh_check_undefined_value" id="g)]!(D0WW1m#!m2G#^ZA"><field
        name="cacheType">.private</field><value name="key"><shadow type="text"
        id="X6eR=U@O8:~PYgf@{?J0"><field name="TEXT">key</field></shadow><block
        type="text" id=")tIL?$_uepQ]0i?f7i{l"><field
        name="TEXT">index</field></block></value></block></value><statement
        name="DO0"><block type="oh_store_value" id="!3J/kWNnreqqYhxjAv6|"><field
        name="cacheType">.private</field><value name="value"><shadow type="text"
        id="lRDP/qa8f[F?y40g{z=]"><field
        name="TEXT">value</field></shadow><block type="math_number"
        id="SG#3GS_=^%~|Inx2I,!n"><field
        name="NUM">-1</field></block></value><value name="key"><shadow
        type="text" id="6k2e`{,VT.2,_pM4ogaN"><field
        name="TEXT">key</field></shadow><block type="text"
        id="7ILi6e-Pr6{jv=y~s:5#"><field
        name="TEXT">index</field></block></value></block></statement><next><block
        type="controls_if" id="xSixWUS~`$[^fW..A?r!"><value name="IF0"><block
        type="oh_check_undefined_value" id="RxsQ#[a|Pq%bSq9e{KY4"><field
        name="cacheType">.private</field><value name="key"><shadow type="text"
        id="X6eR=U@O8:~PYgf@{?J0"><field name="TEXT">key</field></shadow><block
        type="text" id="/dKbJ^3$WFj]%7t$SRR~"><field
        name="TEXT">samples</field></block></value></block></value><statement
        name="DO0"><block type="variables_set" id="*#DFFA|vmb##o}6fsYXN"><field
        name="VAR" id="^bgxT=plTgkB,N8?:gof">samples</field><value
        name="VALUE"><block type="lists_create_with"
        id="S+y$DWBfH+pyg^zVps,^"><mutation
        items="0"></mutation></block></value><next><block type="oh_store_value"
        id="kv8XXf{NgP_L5O$1kB+?"><field name="cacheType">.private</field><value
        name="value"><shadow type="text" id="lRDP/qa8f[F?y40g{z=]"><field
        name="TEXT">value</field></shadow><block type="variables_get"
        id="%PZ.Q6hvm;h:PVb)fiyt"><field name="VAR"
        id="^bgxT=plTgkB,N8?:gof">samples</field></block></value><value
        name="key"><shadow type="text" id="6k2e`{,VT.2,_pM4ogaN"><field
        name="TEXT">key</field></shadow><block type="text"
        id="J}OT5BZdt^T]SsgjLx}4"><field
        name="TEXT">index</field></block></value></block></next></block></statement><next><block
        type="variables_set" id="y52F,Sv$tq9hH[r!yZqW"><field name="VAR"
        id="Tp}bOW}QL(O{(ZjheYJ/">index</field><value name="VALUE"><block
        type="math_modulo" id="Phg_g0PKnV]@D[u,.+2l"><value
        name="DIVIDEND"><shadow type="math_number"
        id="Ymzp,[TZTj$XD-cmJtqF"><field name="NUM">64</field></shadow><block
        type="math_arithmetic" id="i@7NHt_Q}!jX~Q{6Jl)f"><field
        name="OP">ADD</field><value name="A"><shadow type="math_number"
        id="Dh5!]/CYnmK%QXli$]di"><field name="NUM">1</field></shadow><block
        type="oh_get_value" id="#`fCRUmx8(.4Jv)^TcnF"><field
        name="cacheType">.private</field><value name="key"><shadow type="text"
        id="@iHr.z=Q~9[BKgwkc~GG"><field name="TEXT">key</field></shadow><block
        type="text" id="O+I;IWGX:yD3j!v;@A10"><field
        name="TEXT">index</field></block></value></block></value><value
        name="B"><shadow type="math_number" id="1r2Vcy0l+q|t*{c]+70z"><field
        name="NUM">1</field></shadow></value></block></value><value
        name="DIVISOR"><shadow type="math_number"
        id="Q:l,E[FC4dS/ssOcDu[e"><field name="NUM">0</field></shadow><block
        type="variables_get" id="?0uC._EM-`TM0z[Y/Iug"><field name="VAR"
        id="#:-(Xt]*D+.de6X:lrik">NUM_SAMPLES</field></block></value></block></value><next><block
        type="variables_set" id="6X*WO)caNmHEy7DiTW9:"><field name="VAR"
        id="^bgxT=plTgkB,N8?:gof">samples</field><value name="VALUE"><block
        type="oh_get_value" id=")_Ii@iG:+hd3%4U#Y)|*"><field
        name="cacheType">.private</field><value name="key"><shadow type="text"
        id="@iHr.z=Q~9[BKgwkc~GG"><field name="TEXT">key</field></shadow><block
        type="text" id="Qf;|+?WQ$[QWyRKWJilt"><field
        name="TEXT">samples</field></block></value></block></value><next><block
        type="lists_setIndex" id="_/$#$pbnO4*N/=^kz{i}"><mutation
        at="true"></mutation><field name="MODE">SET</field><field
        name="WHERE">FROM_START</field><value name="LIST"><block
        type="variables_get" id="?bVD(D9$*{ue526KLo]o"><field name="VAR"
        id="^bgxT=plTgkB,N8?:gof">samples</field></block></value><value
        name="AT"><block type="variables_get" id="xuXzfIHACcr9Z[;]Ie8#"><field
        name="VAR" id="Tp}bOW}QL(O{(ZjheYJ/">index</field></block></value><value
        name="TO"><block type="variables_get" id="hUKteNQf%O=vaiTFss=]"><field
        name="VAR"
        id="[xzFcQtH8S`L$J.+l14N">curSpeed</field></block></value><next><block
        type="variables_set" id="P*D%O1PsfqgfkZ4AoJ;L"><field name="VAR"
        id="sMuBpxdu({kT`5VuK8R`">sum</field><value name="VALUE"><block
        type="math_number" id="}1?4lP=0oR[Zp_I75Xt4"><field
        name="NUM">0</field></block></value><next><block type="controls_forEach"
        id="pSlgP4rQ5J}L%Nh0Qvld"><field name="VAR"
        id="X]rxixgS(FcHlxFz]Kl!">j</field><value name="LIST"><block
        type="variables_get" id="qN+6FEXtm]_t}XhO;~Ju"><field name="VAR"
        id="^bgxT=plTgkB,N8?:gof">samples</field></block></value><statement
        name="DO"><block type="variables_set" id="T+kV+M[i?h*bMR^/Zv*f"><field
        name="VAR" id="sMuBpxdu({kT`5VuK8R`">sum</field><value
        name="VALUE"><block type="math_arithmetic"
        id="R#V3L:]^XbM]iV)BO;KO"><field name="OP">ADD</field><value
        name="A"><shadow type="math_number" id="1EJ6jYF*fI)OGf)=g)xl"><field
        name="NUM">1</field></shadow><block type="variables_get"
        id="Z?vC~ACruHO:fw|MRq.S"><field name="VAR"
        id="sMuBpxdu({kT`5VuK8R`">sum</field></block></value><value
        name="B"><shadow type="math_number" id="s!+5_`mo|,f(!{X5KgcL"><field
        name="NUM">1</field></shadow></value></block></value></block></statement><next><block
        type="variables_set" id="zb:vEyuAS1#,NEd#l*?j"><field name="VAR"
        id="X[B(JDe/;c#]7XH=V8N+">avg</field><value name="VALUE"><block
        type="math_arithmetic" id="r*!fjCn8KFP(yFsVoNxz"><field
        name="OP">DIVIDE</field><value name="A"><shadow type="math_number"
        id="1EJ6jYF*fI)OGf)=g)xl"><field name="NUM">1</field></shadow><block
        type="variables_get" id="*qLTanV25ke3J|3Qkukf"><field name="VAR"
        id="sMuBpxdu({kT`5VuK8R`">sum</field></block></value><value
        name="B"><shadow type="math_number" id="[aQ*2,fXtPccl6Z7y7!d"><field
        name="NUM">1</field></shadow><block type="lists_length"
        id="[H!N-6C!qT9-wwIf=Uk4"><value name="VALUE"><block
        type="variables_get" id="U8x#I~dEsHrE~-fBzV*7"><field name="VAR"
        id="^bgxT=plTgkB,N8?:gof">samples</field></block></value></block></value></block></value><next><block
        type="oh_store_value" id="I}qmKi5XYU%0}E8Ac(NK"><field
        name="cacheType">.private</field><value name="value"><shadow type="text"
        id="lRDP/qa8f[F?y40g{z=]"><field
        name="TEXT">value</field></shadow><block type="variables_get"
        id="4KOLt96.3biZ/ciJ(iku"><field name="VAR"
        id="Tp}bOW}QL(O{(ZjheYJ/">index</field></block></value><value
        name="key"><shadow type="text" id="6k2e`{,VT.2,_pM4ogaN"><field
        name="TEXT">key</field></shadow><block type="text"
        id="$7Iq@Ues_nMLF$)@F^TR"><field
        name="TEXT">index</field></block></value><next><block
        type="oh_store_value" id="83i(!T9w6sfT4G2+F:qH"><field
        name="cacheType">.private</field><value name="value"><shadow type="text"
        id="lRDP/qa8f[F?y40g{z=]"><field
        name="TEXT">value</field></shadow><block type="variables_get"
        id="|pdH@X80mPBXbe-`=tps"><field name="VAR"
        id="^bgxT=plTgkB,N8?:gof">samples</field></block></value><value
        name="key"><shadow type="text" id="6k2e`{,VT.2,_pM4ogaN"><field
        name="TEXT">key</field></shadow><block type="variables_get"
        id="5nL-/ICqh]m.%g*-T_cz"><field name="VAR"
        id="X[B(JDe/;c#]7XH=V8N+">avg</field></block></value><next><block
        type="oh_log" id="qDggrI/p?nR^qmTYpf};"><field
        name="severity">info</field><value name="message"><shadow type="text"
        id="j$w:rQR*]YuW/zX?xa%X"><field name="TEXT">abc</field></shadow><block
        type="text_join" id="~6x~qu4}j=f[wS@5k:2+"><mutation
        items="2"></mutation><value name="ADD0"><block type="text"
        id="r(6{.?b]M=((_sCfOI`_"><field name="TEXT">Windspeed lavarage
        is</field></block></value></block></value><next><block
        type="controls_if" id="iF|bnUG+f%]#A1NjbLQ2"><mutation elseif="1"
        else="1"></mutation><value name="IF0"><block type="logic_operation"
        id="kXE.JH...gA~0vfY53[R"><field name="OP">AND</field><value
        name="A"><block type="logic_compare" id="iw%$GDJ%PSOcM,qb=49:"><field
        name="OP">GT</field><value name="A"><block type="variables_get"
        id="^oXOv-cm@1MUbnvWin6W"><field name="VAR"
        id="X[B(JDe/;c#]7XH=V8N+">avg</field></block></value><value
        name="B"><block type="variables_get" id="jFEMBBP|;vO|TwqJZG/f"><field
        name="VAR"
        id="}WcUTMxq~IGApQ2.hE:o">WIND_THREHOLD_HIGH</field></block></value></block></value><value
        name="B"><block type="logic_compare" id="q4FfQz*y!O*Ii5[e}za;"><field
        name="OP">LT</field><value name="A"><block type="variables_get"
        id="}YB:H1!!a;!W#}xY@v|H"><field name="VAR"
        id="OP!..;87,m?]t/$kO3?P">shutterState</field></block></value><value
        name="B"><block type="variables_get" id="f%YjdG)}]9fsLRo)h4D/"><field
        name="VAR"
        id="H^#H[AJ@T-iM6Y/TK]dm">WIND_HIDH_ROLLERSHUTTER</field></block></value></block></value></block></value><statement
        name="DO0"><block type="oh_event" id="]cKJW3c7KUDsLWv2w9kT"><field
        name="eventType">sendCommand</field><value name="value"><shadow
        type="text" id="0Ma/c0u_v_PEMuyyi3ET"><field
        name="TEXT">value</field></shadow><block type="variables_get"
        id="qc0(,:2j8sr5HOM,?fK|"><field name="VAR"
        id="H^#H[AJ@T-iM6Y/TK]dm">WIND_HIDH_ROLLERSHUTTER</field></block></value><value
        name="itemName"><shadow type="oh_item"
        id="^:FxTi`C?5[1!M3;I_Tv"><mutation itemName="MyItem"
        itemLabel="MyItem"></mutation><field
        name="itemName">MyItem</field></shadow><block type="variables_get"
        id="G7uI0+TA?|+9pBpgBG;q"><field name="VAR"
        id="6j5zHjQ+K:Sy-Rdr_oUk">shutterItem</field></block></value><next><block
        type="oh_log" id="+%R{c}r7_dfB-Rj55VAV"><field
        name="severity">warn</field><value name="message"><shadow type="text"
        id="ZM0$9mLi8ny`C44D*N/0"><field name="TEXT">abc</field></shadow><block
        type="text" id=":)$)FV??~[d7u]Xww$]B"><field name="TEXT">Avarage
        windspeed is very high adjusting
        shutters</field></block></value></block></next></block></statement><value
        name="IF1"><block type="logic_operation"
        id="vkm;`T.3j%)aZ6pMdyUb"><field name="OP">AND</field><value
        name="A"><block type="logic_compare" id="tA+5H||~}mmx5utA~b~7"><field
        name="OP">GT</field><value name="A"><block type="variables_get"
        id="Y2,A:3+1y{U%x}#E}bhU"><field name="VAR"
        id="X[B(JDe/;c#]7XH=V8N+">avg</field></block></value><value
        name="B"><block type="variables_get" id="^bg=t1+fllO+.9K4%26l"><field
        name="VAR"
        id="Ub}(f?.}5AL*r3U;}y*(">WIND_THREHOLD</field></block></value></block></value><value
        name="B"><block type="logic_compare" id="cn}{BI|}D%uLRSE8X/qc"><field
        name="OP">LT</field><value name="A"><block type="variables_get"
        id="-chs{{11eASm@MUP7enT"><field name="VAR"
        id="OP!..;87,m?]t/$kO3?P">shutterState</field></block></value><value
        name="B"><block type="variables_get" id="zg]Lr%8xw.jZ`:z|%pJk"><field
        name="VAR"
        id="+dTtO4*p?H)XqOTh^j,b">WIND_ROLLERSHUTTER</field></block></value></block></value></block></value><statement
        name="DO1"><block type="oh_event" id="jild1s/n|{`%K4L(rb}6"><field
        name="eventType">sendCommand</field><value name="value"><shadow
        type="text" id="0Ma/c0u_v_PEMuyyi3ET"><field
        name="TEXT">value</field></shadow><block type="variables_get"
        id="u|[;t5QbTm9Z~t]3{TIO"><field name="VAR"
        id="+dTtO4*p?H)XqOTh^j,b">WIND_ROLLERSHUTTER</field></block></value><value
        name="itemName"><shadow type="oh_item"
        id="^:FxTi`C?5[1!M3;I_Tv"><mutation itemName="MyItem"
        itemLabel="MyItem"></mutation><field
        name="itemName">MyItem</field></shadow><block type="variables_get"
        id="}J*vASm@_hTUoYkdeLu="><field name="VAR"
        id="6j5zHjQ+K:Sy-Rdr_oUk">shutterItem</field></block></value><next><block
        type="oh_log" id="`N0._LD!.q7BsQt4}0fF"><field
        name="severity">warn</field><value name="message"><shadow type="text"
        id="ZM0$9mLi8ny`C44D*N/0"><field name="TEXT">abc</field></shadow><block
        type="text" id="fY:AfebEa@R+*#PopnrA"><field name="TEXT">Avarage
        windspeed is high adjusting
        shutters</field></block></value></block></next></block></statement><statement
        name="ELSE"><block type="oh_log" id="iM40w69(71NDH(3.gx!g"><field
        name="severity">info</field><value name="message"><shadow type="text"
        id="ZM0$9mLi8ny`C44D*N/0"><field name="TEXT">abc</field></shadow><block
        type="text" id="3|?z$~[aFwd_,nlv3/$B"><field name="TEXT">Avarage
        windspeed is not
        high</field></block></value></block></statement></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></xml>
      type: application/javascript
      script: >
        var NUM_SAMPLES, WIND_THREHOLD, WIND_THREHOLD_HIGH,
        WIND_HIDH_ROLLERSHUTTER, WIND_ROLLERSHUTTER, curSpeed, shutterItem,
        shutterState, samples, index, sum, j, avg;



        NUM_SAMPLES = 6;

        WIND_THREHOLD = 14;

        WIND_THREHOLD_HIGH = 25;

        WIND_HIDH_ROLLERSHUTTER = 100;

        WIND_ROLLERSHUTTER = 70;

        curSpeed = items.getItem('Vento_vetrata').numericState;

        shutterItem = items.getItem('Tende');

        shutterState = shutterItem.numericState;

        if (cache.private.exists('index') === false) {
          cache.private.put('index', (-1));
        }

        if (cache.private.exists('samples') === false) {
          samples = [];
          cache.private.put('index', samples);
        }

        index = ((cache.private.get('index')) + 1) % NUM_SAMPLES;

        samples = (cache.private.get('samples'));

        samples[(index - 1)] = curSpeed;

        sum = 0;

        for (var j_index in samples) {
          j = samples[j_index];
          sum = sum + 1;
        }

        avg = sum / samples.length;

        cache.private.put('index', index);

        cache.private.put(avg, samples);

        console.info(('Windspeed lavarage is' + ''));

        if (avg > WIND_THREHOLD_HIGH && shutterState < WIND_HIDH_ROLLERSHUTTER) {
          shutterItem.sendCommand(WIND_HIDH_ROLLERSHUTTER);
          console.warn('Avarage windspeed is very high adjusting shutters');
        } else if (avg > WIND_THREHOLD && shutterState < WIND_ROLLERSHUTTER) {
          shutterItem.sendCommand(WIND_ROLLERSHUTTER);
          console.warn('Avarage windspeed is high adjusting shutters');
        } else {
          console.info('Avarage windspeed is not high');
        }
    type: script.ScriptAction

When the item wind changes I found thes on the logs

2024-05-05 10:36:30.279 [ERROR] [b.automation.script.javascript.stack] - Failed to execute script:
org.graalvm.polyglot.PolyglotException: TypeError: Cannot set property "0" of null
	at <js>.:program(<eval>:21) ~[?:?]
	at org.graalvm.polyglot.Context.eval(Context.java:399) ~[?:?]
	at com.oracle.truffle.js.scriptengine.GraalJSScriptEngine.eval(GraalJSScriptEngine.java:458) ~[?:?]
	at com.oracle.truffle.js.scriptengine.GraalJSScriptEngine.eval(GraalJSScriptEngine.java:426) ~[?:?]
	at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:262) ~[java.scripting:?]
	at org.openhab.automation.jsscripting.internal.scriptengine.DelegatingScriptEngineWithInvocableAndAutocloseable.eval(DelegatingScriptEngineWithInvocableAndAutocloseable.java:53) ~[?:?]
	at org.openhab.automation.jsscripting.internal.scriptengine.InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.eval(InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.java:78) ~[?:?]
	at org.openhab.automation.jsscripting.internal.scriptengine.DelegatingScriptEngineWithInvocableAndAutocloseable.eval(DelegatingScriptEngineWithInvocableAndAutocloseable.java:53) ~[?:?]
	at org.openhab.automation.jsscripting.internal.scriptengine.InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.eval(InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.java:78) ~[?:?]
	at org.openhab.core.automation.module.script.internal.handler.ScriptActionHandler.lambda$0(ScriptActionHandler.java:71) ~[?:?]
	at java.util.Optional.ifPresent(Optional.java:178) [?:?]
	at org.openhab.core.automation.module.script.internal.handler.ScriptActionHandler.execute(ScriptActionHandler.java:68) [bundleFile:?]
	at org.openhab.core.automation.internal.RuleEngineImpl.executeActions(RuleEngineImpl.java:1188) [bundleFile:?]
	at org.openhab.core.automation.internal.RuleEngineImpl.runRule(RuleEngineImpl.java:997) [bundleFile:?]
	at org.openhab.core.automation.internal.TriggerHandlerCallbackImpl$TriggerData.run(TriggerHandlerCallbackImpl.java:87) [bundleFile:?]
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) [?:?]
	at java.util.concurrent.FutureTask.run(FutureTask.java:264) [?:?]
	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) [?:?]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) [?:?]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) [?:?]
	at java.lang.Thread.run(Thread.java:833) [?:?]
2024-05-05 10:36:30.291 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID '97ba6d2f35' failed: org.graalvm.polyglot.PolyglotException: TypeError: Cannot set property "0" of null

Thanks for your assistance .