Rule with average

Hello everybody need someone who point me in the right direction.
I want my roller shutter goes up if avarage wind speed is greater then a value.
So I persist my wind speed every second modyfing rrd4j.persist accordingly
I create a rule with blocky and I get the state of my wind speed item (only if it is updated)since now minus 5 seconds and if wind average is above my trigger value my roller goes up.
The problem is that it works only with the expression ‘get the state of my item since now minus 5 seconds and I would like to get the average with ‘since now plus my seconds’ it would be better but it won’t work.
Thanks in advance for any help

Blockquote

You need to show more about what you’ve tried and describe more about what you mean by “won’t work”. As written, we don’t even know if you are using blockly, Rules DSL, JS, file based rules or the UI, whether the problem is a syntax error or you got the wrong answer, etc.

OK, I’m out.

There is nothing wrong with my reading comprehension. Reposting a copy of your original post adds nothing new and does not answer my question.

Good luck!

Thank you for your reply Rich.

I was trying to reply and involuntary i published it twice.

This is my rrd4j.persist

Strategies {

everySecond : “* * * * * ?”
everyMinute : “0 * * * * ?”
every10Sec : “0/10 * * * * ?”
default = everyChange, everyUpdate
}

Items {
Vento_vetrata : strategy = everySecond, everyChange, everyUpdate
Vento_Terrazza : strategy = everSecond, everyChange, everyUpdate
}


strong text

OK, that’s better. This helps.

To make it easier to read on the forum, be sure to use code fences when posting code and logs.

```
code goes here
```

Also, when posting anything else (rules, Items, Things, etc.) click on the “Code” tag and paste the YAML code you find there, again in code fences. Screen shots are really hard to use and leave a whole lot out .

So the last part is what do you mean by “doesn’t work”. Does it give the wrong answer? Errors generated in the logs (if so please post them)?

1 Like

Thanks again Rich I try to post the code

I don’t read errors in the logs and the rule work only if I get the avarage plus minus.
I would like to get the future average once the item is updated
Many thanks for your help

Configuration: {}
triggers:

  • id: “1”
    configuration:
    itemName: Vento_Terrazza
    type: core.ItemStateChangeTrigger
    conditions:
    actions:
  • inputs: {}
    id: “2”
    configuration:
    blockSource: GTEaverageSinceVento_Terrazzadefaultrrd4jminusSeconds5minusSeconds5514LTETende_camere70sendCommand70100Tende_camere
    type: application/javascript
    script: >
    if
    ((items.getItem(‘Vento_Terrazza’).history.averageSince(time.ZonedDateTime.now().minusSeconds(5),
    ‘rrd4j’)) >= ‘14’) {
    if (items.getItem(‘Tende_camere’).state <= ‘70’) {
    items.getItem(‘Tende_camere’).sendCommand(‘100’);
    }
    }
    type: script.ScriptAction

Again, please use code fences.

```
code goes here
```

The contents of the code tabs have meangingful white space. without code fences you lose the whote space and therefore some of the meaning, not to mention it’s really hard to read. Everything in < > gets lost as well.

rrd4j doesn’t store future values so there is no such thing as a future average. You can get the average from now to any time in the past, but not the future. You’ll need to use a different persistence database to support storing future values. And of course you’ll need a binding to populate the database with the future values.

Thank you Rich for your assistance and to whom like you that makes this things affordable.
I tried with influxdb as well with same strategy but with no succes. Rule is triggered only if I get the avarage in the past.
I would like my terrace rollers go up when the wind intensity it lasts enough, at least 7/10 seconds.
Many thanks indeed

I can’t tell if there is a language issue or something else. You talk about a “future average” but now you say “when the wind intensity it lasts enough” which only requires past data.

But “7/10” seconds is far too short to get anything out of rrd4j. It only saves data on changes and every minute. And even if your sensor is changing really fast, rrd4j doesn’t save data fast enough that you’ll ever have more than one or two values over a 10 second period. So it’s always just going to give you the most recent value.

You’ve still not said what the “average since” is actually returning. What is “doesn’t work”?

How often does this Item update? If it’s not at least once a second (but no faster as rrd4j will throw away values faster than once per second) you’ll never get anything meaningful from average since.

All average since does is get all the records between now and the time you pass to it and gives you the average of those values. If there’s only one record between now and ten seconds ago there’s no average.

Getting the average over the past five minutes should work. Over the past minute might work. Anything shorter than that is almost certainly not going to work. You need to keep a running average yourself and can’t use persistence for this.


configuration:%20%7B%7D%0Atriggers%3A%0A%20%20-%20id%3A%20%221%22%0A%20%20%20%20configuration%3A%0A%20%20%20%20%20%20itemName%3A%20Vento_Terrazza%0A%20%20%20%20type%3A%20core.ItemStateChangeTrigger%0Aconditions%3A%20%5B%5D%0Aactions%3A%0A%20%20-%20inputs%3A%20%7B%7D%0A%20%20%20%20id%3A%20%222%22%0A%20%20%20%20configuration%3A%0A%20%20%20%20%20%20blockSource%3A%20%3Cxml%20xmlns=%22https%3A//developers.google.com/blockly/xml%22%3E%3Cblock%0A%20%20%20%20%20%20%20%20type=%22controls_if%22%20id=%227d2%238gysc%604N*@5/,n!Q%22%20x=%2279%22%20y=%2278%22%3E%3Cvalue%0A%20%20%20%20%20%20%20%20name=%22IF0%22%3E%3Cblock%20type=%22logic_compare%22%20id=%22+FimiDkdjc%5DvzYm_Fr%7B?%22%3E%3Cfield%0A%20%20%20%20%20%20%20%20name=%22OP%22%3EGTE%3C/field%3E%3Cvalue%20name=%22A%22%3E%3Cblock%20type=%22oh_get_persistvalue%22%0A%20%20%20%20%20%20%20%20id=%225Dta+wH@S:TW+%7Bcf?cV2%22%3E%3Cfield%0A%20%20%20%20%20%20%20%20name=%22methodName%22%3EaverageSince%3C/field%3E%3Cvalue%20name=%22itemName%22%3E%3Cshadow%0A%20%20%20%20%20%20%20%20type=%22oh_item%22%20id=%228eh0!6%7CTQm.y-P*ew=_%7B%22%3E%3Cmutation%0A%20%20%20%20%20%20%20%20itemName=%22Vento_Terrazza%22%20itemLabel=%22Vento%20Terrazza%22%3E%3C/mutation%3E%3Cfield%0A%20%20%20%20%20%20%20%20name=%22itemName%22%3EVento_Terrazza%3C/field%3E%3C/shadow%3E%3C/value%3E%3Cvalue%0A%20%20%20%20%20%20%20%20name=%22persistenceName%22%3E%3Cshadow%20type=%22oh_persistence_dropdown%22%0A%20%20%20%20%20%20%20%20id=%22H,C-1(0$?m%5B%25mLFy%7B=,-%22%3E%3Cfield%0A%20%20%20%20%20%20%20%20name=%22persistence%22%3Edefault%3C/field%3E%3C/shadow%3E%3Cblock%0A%20%20%20%20%20%20%20%20type=%22oh_persistence_dropdown%22%20id=%22$WC%5Br/YA4U3T%5D~hC;%60R1%22%3E%3Cfield%0A%20%20%20%20%20%20%20%20name=%22persistence%22%3Errd4j%3C/field%3E%3C/block%3E%3C/value%3E%3Cvalue%0A%20%20%20%20%20%20%20%20name=%22dayInfo%22%3E%3Cshadow%20type=%22oh_zdt_plusminus%22%0A%20%20%20%20%20%20%20%20id=%22?:64Nu;qCO6!6Y(!u,HU%22%3E%3Cfield%20name=%22plusminus%22%3Eminus%3C/field%3E%3Cfield%0A%20%20%20%20%20%20%20%20name=%22period%22%3ESeconds%3C/field%3E%3Cvalue%20name=%22offset%22%3E%3Cshadow%0A%20%20%20%20%20%20%20%20type=%22math_number%22%20id=%22X%5E~%60rH%5E4ysiSpe.!cm*F%22%3E%3Cfield%0A%20%20%20%20%20%20%20%20name=%22NUM%22%3E5%3C/field%3E%3C/shadow%3E%3C/value%3E%3C/shadow%3E%3Cblock%0A%20%20%20%20%20%20%20%20type=%22oh_zdt_plusminus%22%20id=%22(?/@OId%23y!_@ve,,1s%7B%7B%22%3E%3Cfield%0A%20%20%20%20%20%20%20%20name=%22plusminus%22%3Eminus%3C/field%3E%3Cfield%20name=%22period%22%3ESeconds%3C/field%3E%3Cvalue%0A%20%20%20%20%20%20%20%20name=%22offset%22%3E%3Cshadow%20type=%22math_number%22%0A%20%20%20%20%20%20%20%20id=%22%25%23spbmunwv4~+5%60?;pjs%22%3E%3Cfield%20name=%22NUM%22%3E5%3C/field%3E%3C/shadow%3E%3Cblock%0A%20%20%20%20%20%20%20%20type=%22math_number%22%20id=%22zSK%5D_S%25B:XF%603j$t%5D%5Ebf%22%3E%3Cfield%0A%20%20%20%20%20%20%20%20name=%22NUM%22%3E5%3C/field%3E%3C/block%3E%3C/value%3E%3C/block%3E%3C/value%3E%3C/block%3E%3C/value%3E%3Cvalue%0A%20%20%20%20%20%20%20%20name=%22B%22%3E%3Cblock%20type=%22text%22%20id=%22L;/bLPJcp%5E$Dd$:B%605qn%22%3E%3Cfield%0A%20%20%20%20%20%20%20%20name=%22TEXT%22%3E14%3C/field%3E%3C/block%3E%3C/value%3E%3C/block%3E%3C/value%3E%3Cstatement%0A%20%20%20%20%20%20%20%20name=%22DO0%22%3E%3Cblock%20type=%22controls_if%22%20id=%22%5D.dLf.*+%60x*x5ka%5E7-~%25%22%3E%3Cvalue%0A%20%20%20%20%20%20%20%20name=%22IF0%22%3E%3Cblock%20type=%22logic_compare%22%20id=%22EL_$wgab?C/+p%5E%7CBSLVf%22%3E%3Cfield%0A%20%20%20%20%20%20%20%20name=%22OP%22%3ELTE%3C/field%3E%3Cvalue%20name=%22A%22%3E%3Cblock%20type=%22oh_getitem_state%22%0A%20%20%20%20%20%20%20%20id=%22ml1K~Hz,,)twfBl~-oaq%22%3E%3Cvalue%20name=%22itemName%22%3E%3Cshadow%20type=%22oh_item%22%0A%20%20%20%20%20%20%20%20id=%22kBZl,SUC:%5Ep%60Y26)Bl:Z%22%3E%3Cmutation%20itemName=%22Tende_camere%22%0A%20%20%20%20%20%20%20%20itemLabel=%22Tende%20camere%22%3E%3C/mutation%3E%3Cfield%0A%20%20%20%20%20%20%20%20name=%22itemName%22%3ETende_camere%3C/field%3E%3C/shadow%3E%3C/value%3E%3C/block%3E%3C/value%3E%3Cvalue%0A%20%20%20%20%20%20%20%20name=%22B%22%3E%3Cblock%20type=%22text%22%20id=%2291$nVNAFFdUcNW8+,z3e%22%3E%3Cfield%0A%20%20%20%20%20%20%20%20name=%22TEXT%22%3E70%3C/field%3E%3C/block%3E%3C/value%3E%3C/block%3E%3C/value%3E%3Cstatement%0A%20%20%20%20%20%20%20%20name=%22DO0%22%3E%3Cblock%20type=%22oh_event%22%20id=%227FycnG;3_+SNP%60I2JM0R%22%3E%3Cfield%0A%20%20%20%20%20%20%20%20name=%22eventType%22%3EsendCommand%3C/field%3E%3Cvalue%20name=%22value%22%3E%3Cshadow%0A%20%20%20%20%20%20%20%20type=%22text%22%20id=%229!*Kaa-LsYFxh)!4rBJD%22%3E%3Cfield%0A%20%20%20%20%20%20%20%20name=%22TEXT%22%3E70%3C/field%3E%3C/shadow%3E%3Cblock%20type=%22text%22%0A%20%20%20%20%20%20%20%20id=%22LI+*MC%7BINfjI%25l44K=Yd%22%3E%3Cfield%0A%20%20%20%20%20%20%20%20name=%22TEXT%22%3E100%3C/field%3E%3C/block%3E%3C/value%3E%3Cvalue%20name=%22itemName%22%3E%3Cshadow%0A%20%20%20%20%20%20%20%20type=%22oh_item%22%20id=%22+%5BUJ=ZsJcrR%5E!B%25%5BMF;s%22%3E%3Cmutation%0A%20%20%20%20%20%20%20%20itemName=%22Tende_camere%22%20itemLabel=%22Tende%20camere%22%3E%3C/mutation%3E%3Cfield%0A%20%20%20%20%20%20%20%20name=%22itemName%22%3ETende_camere%3C/field%3E%3C/shadow%3E%3C/value%3E%3C/block%3E%3C/statement%3E%3C/block%3E%3C/statement%3E%3C/block%3E%3C/xml%3E%0A%20%20%20%20%20%20type:%20application/javascript%0A%20%20%20%20%20%20script:%20%3E%0A%20%20%20%20%20%20%20%20if%0A%20%20%20%20%20%20%20%20((items.getItem('Vento_Terrazza').history.averageSince(time.ZonedDateTime.now().minusSeconds(5),%0A%20%20%20%20%20%20%20%20'rrd4j'))%20%3E=%20'14')%20%7B%0A%20%20%20%20%20%20%20%20%20%20if%20(items.getItem('Tende_camere').state%20%3C=%20'70')%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20items.getItem('Tende_camere').sendCommand('100');%0A%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20type:%20script.ScriptAction

As it is build the rule now the rollers go up immediately as the wind starts because the average ‘since now minus seconds’ is always higher than my trigger.

The sensor is updated every change it would be even every second and I woul like to get the average once the sensor is updatedfor the 10 seconds after.

Doesn’t work means that if change in the rule with the avarage ‘since now plus x seconds’ nothing happen and my rollers don’t go up at all.

At the end in this way or it go up immediately once the sensor is updated (cause the avarage is obviously higher)or they don’t go up at all.

But there’s is no data in the future. Is your wind sensor psychic and can see the future? That’s what makes no sense. It’s never going to work.

If you have a weather service that reports predicted wind speeds that would be something else, but even there is only going to give you future values on the order of minutes, not seconds. And you can’t use rrd4j for that.

Average since it’s working as expected and designed in this case.

If you need the average for a time period as short as ten seconds, your not going to be able to use average since for this. You’ll have to create a rule that keeps a running average for you or you need to use a time frame of minutes, not seconds.

Finally, you are comparing a number which is what average since returns to a string, which is probably not what you want.

1 Like

Rich thanks but this is not my intention.
My rule’ trigger is the sensor update event and I get the avarage a that time and the x second before where for sure there was no wind because the sensor was sleeping
I want get the average after the updating event.
No in the future.
No prediction. it happens. How long does it last? Is it the case to roll up or that was just a little breeze?
If I can get the avarage and duration my roller can get up if the wind is strong and it last

See this post, maybe it helps.

Hi ,
I think I sorta understood what you are trying to do.
This is a very ugly and not indented or prettified and a simplistic approach mostly just to make it easy to see how you grab 10 values and hold them for use later without having to send to a DB This will take 10 samples of your live windspeed regardless if the wind speed stays at the defined level or even if it goes up or down this will see what happened once every sample interval.
absolutely sure it could be done better and very likely many templates and other examples are much more elegant but it does do exactly what you want.
add this as a inline script to your rule on changed trigger.
If nothing else maybe it gives you some ideas.

var current_windspeed = 1.9; // this would be your item that provides the actual wind speed
var windspeed_too_high = 1; //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 number_of_samples_to_take = 10; //This sets your number of samples  if you change greater then 10 you must add samples and if statments to populate them
var sample_count = 0; //this sets your count back to 0 at start of rule run 
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 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 future_predictor = setInterval(myTimer, 1000); //this is your 1 second timer the 1000 is milliseconds you could change that to a higher of lower value as you see fit 
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;
    sample_count = 1;    
  }
else if(current_windspeed < windspeed_too_high)
{
  console.info('windspeed was not high enough to start measurement cycle ' + current_windspeed );
}  
function myTimer() // this incremments your sample count based on your intraval.
{
  sample_count = sample_count + 1;



if(sample_count == 1)
  {
     windspeed_sample_1 = current_windspeed;
    
    console.warn('this is windspeed at intraval 1 '+ windspeed_sample_1 );
    console.warn('this is sample_count '+ sample_count );
  }
if(sample_count == 2)
  {
     windspeed_sample_2 = current_windspeed;
    
    console.warn('this is windspeed at intraval 2 '+ windspeed_sample_2 );
    console.warn('this is sample_count '+ sample_count );
  }
if(sample_count == 3)
  {
     windspeed_sample_3 = current_windspeed;
    
    console.warn('this is windspeed at intraval 3 '+ windspeed_sample_3 );
    console.warn('this is sample_count '+ sample_count );
  }
if(sample_count == 4)
  {
     windspeed_sample_4 = current_windspeed;
    
    console.warn('this is windspeed at intraval 4 '+ windspeed_sample_4 );
    console.warn('this is sample_count '+ sample_count );
  }
if(sample_count == 5)
  {
     windspeed_sample_5 = current_windspeed;
    
    console.warn('this is windspeed at intraval 5 '+ windspeed_sample_5 );
    console.warn('this is sample_count '+ sample_count );
  }
if(sample_count == 6)
  {
     windspeed_sample_6 = current_windspeed;
    
    console.warn('this is windspeed at intraval 6 '+ windspeed_sample_6 );
    console.warn('this is sample_count '+ sample_count );
  }
if(sample_count == 7)
  {
     windspeed_sample_7 = current_windspeed;
    
    console.warn('this is windspeed at intraval 7 '+ windspeed_sample_7 );
    console.warn('this is sample_count '+ sample_count );
  }
if(sample_count == 8)
  {
     windspeed_sample_8 = current_windspeed;
    
    console.warn('this is windspeed at intraval 8 '+ windspeed_sample_8 );
    console.warn('this is sample_count '+ sample_count );
  }
if(sample_count == 9)
  {
     windspeed_sample_9 = current_windspeed;
    
    console.warn('this is windspeed at intraval 9 '+ windspeed_sample_9 );
    console.warn('this is sample_count '+ sample_count );
  }
if(sample_count == 10)
  {
     windspeed_sample_10 = current_windspeed;
    
    console.warn('this is windspeed at intraval 10 '+ windspeed_sample_10 );
    console.warn('this is sample_count '+ sample_count );
  }
    
  if(sample_count == number_of_samples_to_take)
    {
      clearInterval(future_predictor);
      
      windspeed_monitor_cycle_active = 0;
    }
 

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);
console.info('this is sum '+ windspeed_sample_sum );
console.info('this is 10 second average '+ Wind_10_second_average );
console.debug('this is sample_count '+ sample_count );

if(Wind_10_second_average >= windspeed_too_high)
  {
    console.warn('wind is to high  '+ Wind_10_second_average );
    // action to close shutter
  }
else
  {
    console.info('wind not high  '+ Wind_10_second_average );
    //No action required    
  }

};

hope it helps
Edit I changed this because it was not correctly using interval…
EDIT2 better version in a later post.

@justaoldman 's approach is probably your best bet. If your timelines were in the minutes instead of seconds, @moody_blue 's approach would work.

Here are the problems with using persistence for this.

  • when there is no wind, there is no entries saved to the database at all or, in the case of rrd4j the last reported wind is going to be saved every minute. So if you time is too short to calculate the average you’ll either get the current wind speed or the average of the current wind speed and the last reported wind speed, even if that was hours ago.

  • rrd4j isn’t going to work well with a time in mere seconds anyway, the time bins it’s stores values in are too large

  • values are saved to the database in parallel with the triggering of the rule. It’s unlikely the most recent value that triggered the rule will have actually been saved to the database yet when the rule runs

@justaoldman 's approach could be made simpler by using a running average so you don’t need all those Items. But either way, you’ll need to make sure to account for the zero values when the sensor doesn’t report anything.

Thank you to all for your help.

I’ll try to build my wind trigger rule waiting a second update from sensor in x second before roll the blinds up.
Could be affordable and easier?
Cron strategy with timer?

Either cron or based on events would probably work, but I’m either case you’ll need to handle the fact that your sensor doesn’t report anytime when there is no wind so you’ll have to add something to tell when the wind speed is zero. Maybe expire?

I have just pasted your code as inline script to test it and let you know.
What is supposed to be my sensor trigger based on Item update or change?
And what is the command for action in case of wind too high ?

Thank you

Thank you Rich.
For sure the problem is over my little experience and scripting knowledge.

Hi,
you stated you have a wind speed item if you use a on change event then it will fire the rule.
if the wind speed is greater then whatever you decide is a wind speed too high value it will start sampling the wind speed item every 1 sec for 10 samples. if you create a generic item (switch) that is on off (1 is on 0 is off ) and set a condition on your rule to not run again if the switch is on it will not fire the rule with inline script again if the wind speed onchanged event occurs any more (even if it changed 10 times during those 10 seconds) we only want the rule to run one time during that 10 second interval of sampling. till all 10 sample values are collected and averaged. The wind speed may continue changing during that 10 seconds and your wind speed values may be different for each sample but since each sample is a get of the current wind speed item the script does not care about more on change events till 10 samples of windspeed are collected. once the 10 samples are complete it will set the (generic switch back to off ) and it resets for next event cycle. The reason I chose to set 10 separate items to collect is if during that 10 seconds if one value does go to 0 then the math will still add value of 0 plus any other number values so the math function remains valid. I did average after 10 samples too avoid a 0 value because well average is a division math function and would blow up because you cannot divide by zero. since we know the first sample will be some number value greater then 0 because you would not want it to trigger for “no wind” then we know the final sum no matter what will be some thing more then 0 and the average will work fine.
The command for action would be what every item you have that “closes the roll shutter”.
edit: Also reason I say used on changed is if you have a windspeed that is fluctuating between .2 and .8 and you wind_too_high is set at .9 then you will check for each change to see if wind speed is picking up. but not start collecting samples till your current_windspeed is equal to or greater then your_wind_too_high value. this may cause the rule to kick off more often but since very first check is the compare it will exit very quickly and should not be too expensive. You should also add another condition to only allow the rule to run if the roller shutter is in open state as well. This would prevent the rule from running anytime roller shutter is already closed.