Calculate average, min, max from the same group

Since is it is not possible anymore to get the temperature of the next days using a freeAPI of OpenWeatherMap I want to calculate the values myself. Therfore I have created groups which combines, depending of the time of today, the temperatures from the 3 hours forecast.

|umber:Temperature|Weather_OWM_Temperature_Tomorrow_AVG "Temperature tomorrow AVG [%.1f %unit%]" <temperature> (gOpenWeatherMap)|
|---|---|
|Number:Temperature|Weather_OWM_Temperature_Tomorrow_MIN "Temperature tomorrow MIN  [%.1f %unit%]" <temperature> (gOpenWeatherMap)|
|Number:Temperature|Weather_OWM_Temperature_Tomorrow_MAX "Temperature tomorrow MAX  [%.1f %unit%]" <temperature> (gOpenWeatherMap)|
|Number:Temperature|Weather_OWM_Temperature_Day2_AVG "Temperature DAY2 AVG [%.1f %unit%]" <temperature> (gOpenWeatherMap)|
|Number:Temperature|Weather_OWM_Temperature_Day2_MIN "Temperature DAY2 MIN  [%.1f %unit%]" <temperature> (gOpenWeatherMap)|
|Number:Temperature|Weather_OWM_Temperature_Day2_MAX "Temperature DAY2 MAX  [%.1f %unit%]" <temperature> (gOpenWeatherMap)|
|Number:Temperature|Weather_OWM_Temperature_Day3_AVG "Temperature DAY3 AVG [%.1f %unit%]" <temperature> (gOpenWeatherMap)|
|Number:Temperature|Weather_OWM_Temperature_Day3_MIN "Temperature DAY3 MIN  [%.1f %unit%]" <temperature> (gOpenWeatherMap)|
|Number:Temperature|Weather_OWM_Temperature_Day3_MAX "Temperature DAY3 MAX  [%.1f %unit%]" <temperature> (gOpenWeatherMap)|


Group:Number:AVG gOWM03 "Temperature Group day 1 - 0-3 hours [%s]" (gOpenWeatherMap)
Group:Number:AVG gOWM06 "Temperature Group day 1 - 3-6 hours [%s]" (gOpenWeatherMap)
Group:Number:AVG gOWM09 "Temperature Group day 1 - 6-9 hours [%s]" (gOpenWeatherMap)
Group:Number:AVG gOWM12 "Temperature Group day 1 - 9-12 hours [%s]" (gOpenWeatherMap)
Group:Number:AVG gOWM15 "Temperature Group day 1 - 12-15 hours [%s]" (gOpenWeatherMap)
Group:Number:AVG gOWM18 "Temperature Group day 1 - 15-18 hours [%s]" (gOpenWeatherMap)
Group:Number:AVG gOWM21 "Temperature Group day 1 - 18-21 hours [%s]" (gOpenWeatherMap)
Group:Number:AVG gOWM24 "Temperature Group day 1 - 21-24 hours [%s]" (gOpenWeatherMap)
Group:Number:AVG gOWM27 "Temperature Group day 2 - 0-3 hours [%s]" (gOpenWeatherMap)
Group:Number:AVG gOWM30 "Temperature Group day 2 - 3-6 hours [%s]" (gOpenWeatherMap)
Group:Number:AVG gOWM33 "Temperature Group day 2 - 6-9 hours [%s]" (gOpenWeatherMap)
Group:Number:AVG gOWM36 "Temperature Group day 2 - 9-12 hours [%s]" (gOpenWeatherMap)
Group:Number:AVG gOWM39 "Temperature Group day 2 - 12-15 hours [%s]" (gOpenWeatherMap)
Group:Number:AVG gOWM42 "Temperature Group day 2 - 15-18 hours [%s]" (gOpenWeatherMap)
Group:Number:AVG gOWM45 "Temperature Group day 2 - 18-21 hours [%s]" (gOpenWeatherMap)
Group:Number:AVG gOWM48 "Temperature Group day 2 - 21-24 hours [%s]" (gOpenWeatherMap)
Group:Number:AVG gOWM51 "Temperature Group day 3 - 3 hours [%s]" (gOpenWeatherMap)
Group:Number:AVG gOWM54 "Temperature Group day 3 - 6 hours [%s]" (gOpenWeatherMap)
Group:Number:AVG gOWM57 "Temperature Group day 3 - 9 hours [%s]" (gOpenWeatherMap)
Group:Number:AVG gOWM60 "Temperature Group day 3 - 12 hours [%s]" (gOpenWeatherMap)
Group:Number:AVG gOWM63 "Temperature Group day 3 - 15 hours [%s]" (gOpenWeatherMap)
Group:Number:AVG gOWM66 "Temperature Group day 3 - 18 hours [%s]" (gOpenWeatherMap)
Group:Number:AVG gOWM69 "Temperature Group day 3 - 21 hours [%s]" (gOpenWeatherMap)
Group:Number gOWM72 "Temperature Group day 3 - 24 hours [%s]" (gOpenWeatherMap)

Number:Temperature		Weather_OWM_Temp2_8		"Temperature 1_1 [%.1f %unit%]" <temperature>	(gOpenWeatherMap, gOWM72, gOWM69, gOWM66, gOWM63, gOWM60, gOWM57, gOWM54, gOWM51)	{channel="openweathermap:weather-and-forecast:api:weatherStellendam:forecastHours72#temperature"}
Number:Temperature		Weather_OWM_Temp2_7		"Temperature 1_2 [%.1f %unit%]" <temperature>	(gOpenWeatherMap, gOWM27, gOWM72, gOWM69, gOWM66, gOWM63, gOWM60, gOWM57, gOWM54)	{channel="openweathermap:weather-and-forecast:api:weatherStellendam:forecastHours69#temperature"}
Number:Temperature		Weather_OWM_Temp2_6		"Temperature 1_3 [%.1f %unit%]" <temperature>	(gOpenWeatherMap, gOWM30, gOWM27, gOWM72, gOWM69, gOWM66, gOWM63, gOWM60, gOWM57)	{channel="openweathermap:weather-and-forecast:api:weatherStellendam:forecastHours66#temperature"}
Number:Temperature		Weather_OWM_Temp2_5		"Temperature 1_4 [%.1f %unit%]" <temperature>	(gOpenWeatherMap, gOWM33, gOWM30, gOWM27, gOWM72, gOWM69, gOWM66, gOWM63, gOWM60)	{channel="openweathermap:weather-and-forecast:api:weatherStellendam:forecastHours63#temperature"}
Number:Temperature		Weather_OWM_Temp2_4 	"Temperature 1_5 [%.1f %unit%]" <temperature>	(gOpenWeatherMap, gOWM36, gOWM33, gOWM30, gOWM27, gOWM72, gOWM69, gOWM66, gOWM63)	{channel="openweathermap:weather-and-forecast:api:weatherStellendam:forecastHours60#temperature"}
Number:Temperature		Weather_OWM_Temp2_3		"Temperature 1_6 [%.1f %unit%]" <temperature>	(gOpenWeatherMap, gOWM39, gOWM36, gOWM33, gOWM30, gOWM27, gOWM72, gOWM69, gOWM66)	{channel="openweathermap:weather-and-forecast:api:weatherStellendam:forecastHours57#temperature"}
Number:Temperature		Weather_OWM_Temp2_2		"Temperature 1_7 [%.1f %unit%]" <temperature>	(gOpenWeatherMap, gOWM42, gOWM39, gOWM36, gOWM33, gOWM30, gOWM27, gOWM72, gOWM69)	{channel="openweathermap:weather-and-forecast:api:weatherStellendam:forecastHours54#temperature"}
Number:Temperature		Weather_OWM_Temp2_1		"Temperature 1_8 [%.1f %unit%]" <temperature>	(gOpenWeatherMap, gOWM45, gOWM42, gOWM39, gOWM36, gOWM33, gOWM30, gOWM27, gOWM72)	{channel="openweathermap:weather-and-forecast:api:weatherStellendam:forecastHours51#temperature"}


Number:Temperature		Weather_OWM_Temp1_8		"Temperature 1_1 [%.1f %unit%]" <temperature>	(gOpenWeatherMap, gOWM48, gOWM45, gOWM42, gOWM39, gOWM36, gOWM33, gOWM30, gOWM27)	{channel="openweathermap:weather-and-forecast:api:weatherStellendam:forecastHours48#temperature"}
Number:Temperature		Weather_OWM_Temp1_7		"Temperature 1_2 [%.1f %unit%]" <temperature>	(gOpenWeatherMap, gOWM06, gOWM48, gOWM45, gOWM42, gOWM39, gOWM36, gOWM33, gOWM30)	{channel="openweathermap:weather-and-forecast:api:weatherStellendam:forecastHours45#temperature"}
Number:Temperature		Weather_OWM_Temp1_6		"Temperature 1_3 [%.1f %unit%]" <temperature>	(gOpenWeatherMap, gOWM06, gOWM03, gOWM48, gOWM45, gOWM42, gOWM39, gOWM36, gOWM33)	{channel="openweathermap:weather-and-forecast:api:weatherStellendam:forecastHours42#temperature"}
Number:Temperature		Weather_OWM_Temp1_5		"Temperature 1_4 [%.1f %unit%]" <temperature>	(gOpenWeatherMap, gOWM09, gOWM06, gOWM03, gOWM48, gOWM45, gOWM42, gOWM39, gOWM36)	{channel="openweathermap:weather-and-forecast:api:weatherStellendam:forecastHours39#temperature"}
Number:Temperature		Weather_OWM_Temp1_4 	"Temperature 1_5 [%.1f %unit%]" <temperature>	(gOpenWeatherMap, gOWM12, gOWM09, gOWM06, gOWM03, gOWM48, gOWM45, gOWM42, gOWM39)	{channel="openweathermap:weather-and-forecast:api:weatherStellendam:forecastHours36#temperature"}
Number:Temperature		Weather_OWM_Temp1_3		"Temperature 1_6 [%.1f %unit%]" <temperature>	(gOpenWeatherMap, gOWM15, gOWM12, gOWM09, gOWM06, gOWM03, gOWM48, gOWM45, gOWM42)	{channel="openweathermap:weather-and-forecast:api:weatherStellendam:forecastHours33#temperature"}
Number:Temperature		Weather_OWM_Temp1_2		"Temperature 1_7 [%.1f %unit%]" <temperature>	(gOpenWeatherMap, gOWM18, gOWM15, gOWM12, gOWM09, gOWM06, gOWM03, gOWM48, gOWM45)	{channel="openweathermap:weather-and-forecast:api:weatherStellendam:forecastHours30#temperature"}
Number:Temperature		Weather_OWM_Temp1_1		"Temperature 1_8 [%.1f %unit%]" <temperature>	(gOpenWeatherMap, gOWM21, gOWM18, gOWM15, gOWM12, gOWM09, gOWM06, gOWM03, gOWM48)	{channel="openweathermap:weather-and-forecast:api:weatherStellendam:forecastHours27#temperature"}

Number:Temperature		Weather_OWM_Temp0_8		"Temperature 0_8 [%.1f %unit%]" <temperature>	(gOpenWeatherMap, gOWM24, gOWM21, gOWM18, gOWM15, gOWM12, gOWM09, gOWM06, gOWM03 )	{channel="openweathermap:weather-and-forecast:api:weatherStellendam:forecastHours24#temperature"}
Number:Temperature		Weather_OWM_Temp0_7		"Temperature 0_7 [%.1f %unit%]" <temperature>	(gOpenWeatherMap, gOWM24, gOWM21, gOWM18, gOWM15, gOWM12, gOWM09, gOWM06 )	{channel="openweathermap:weather-and-forecast:api:weatherStellendam:forecastHours21#temperature"}
Number:Temperature		Weather_OWM_Temp0_6		"Temperature 0_6 [%.1f %unit%]" <temperature>	(gOpenWeatherMap, gOWM24, gOWM21, gOWM18, gOWM15, gOWM12, gOWM09 )	{channel="openweathermap:weather-and-forecast:api:weatherStellendam:forecastHours18#temperature"}
Number:Temperature		Weather_OWM_Temp0_5		"Temperature 0_5 [%.1f %unit%]" <temperature>	(gOpenWeatherMap, gOWM24, gOWM21, gOWM18, gOWM15, gOWM12 )	{channel="openweathermap:weather-and-forecast:api:weatherStellendam:forecastHours15#temperature"}
Number:Temperature		Weather_OWM_Temp0_4		"Temperature 0_4 [%.1f %unit%]" <temperature>	(gOpenWeatherMap, gOWM24, gOWM21, gOWM18, gOWM15 )	{channel="openweathermap:weather-and-forecast:api:weatherStellendam:forecastHours12#temperature"}
Number:Temperature		Weather_OWM_Temp0_3		"Temperature 0_3 [%.1f %unit%]" <temperature>	(gOpenWeatherMap, gOWM24, gOWM21, gOWM18 )	{channel="openweathermap:weather-and-forecast:api:weatherStellendam:forecastHours09#temperature"}
Number:Temperature		Weather_OWM_Temp0_2		"Temperature 0_2 [%.1f %unit%]" <temperature>	(gOpenWeatherMap, gOWM24, gOWM21 )	{channel="openweathermap:weather-and-forecast:api:weatherStellendam:forecastHours06#temperature"}
Number:Temperature		Weather_OWM_Temp0_1		"Temperature 0_1 [%.1f %unit%]" <temperature>	(gOpenWeatherMap, gOWM24 )  {channel="openweathermap:weather-and-forecast:api:weatherStellendam:forecastHours03#temperature"}

Using a rule I get, depending on the time of the day the average temperature of the next days

rule "test rule"

when
    Item Weather_OWM_Forecast_Time1_1 changed or
    System started
then

// get hours from date
 var Number vCurrentHour=now.getHourOfDay()
 logInfo("Huidig uur  ", ":"+vCurrentHour) 

// divide hours by 3, to define case
  val int vCaseSelect=(vCurrentHour/3).intValue
 logInfo("Case select number  ", ":"+vCaseSelect) 

// do the case thing
switch(vCaseSelect) {
		case 1 : {
            logInfo("Case select number  ", "1 wordt uitgevoerd") 
            postUpdate(Weather_OWM_Temperature_Tomorrow_AVG, gOWM03.state as Number)
            postUpdate(Weather_OWM_Temperature_Day2_AVG, gOWM27.state as Number)
            postUpdate(Weather_OWM_Temperature_Day3_AVG, gOWM51.state as Number)

            }
		case 2 : {
            logInfo("Case select number  ", "2 wordt uitgevoerd") 
            postUpdate(Weather_OWM_Temperature_Tomorrow_AVG, gOWM06.state as Number)
            postUpdate(Weather_OWM_Temperature_Day2_AVG, gOWM30.state as Number)
            postUpdate(Weather_OWM_Temperature_Day3_AVG, gOWM54.state as Number)

        }    
        case 3 : {
            logInfo("Case select number  ", "3 wordt uitgevoerd") 
            postUpdate(Weather_OWM_Temperature_Tomorrow_AVG, gOWM09.state as Number)
            postUpdate(Weather_OWM_Temperature_Day2_AVG, gOWM33.state as Number)
            postUpdate(Weather_OWM_Temperature_Day3_AVG, gOWM57.state as Number)

        }
        case 4 : {
            logInfo("Case select number  ", "4 wordt uitgevoerd") 
            postUpdate(Weather_OWM_Temperature_Tomorrow_AVG, gOWM12.state as Number)
            postUpdate(Weather_OWM_Temperature_Day2_AVG, gOWM36.state as Number)
            postUpdate(Weather_OWM_Temperature_Day3_AVG, gOWM60.state as Number)

        }
        case 5 : {
            logInfo("Case select number  ", "5 wordt uitgevoerd") 
            postUpdate(Weather_OWM_Temperature_Tomorrow_AVG, gOWM15.state as Number)
            postUpdate(Weather_OWM_Temperature_Day2_AVG, gOWM39.state as Number)
            postUpdate(Weather_OWM_Temperature_Day3_AVG, gOWM63.state as Number)

        }
        case 6 : {
            logInfo("Case select number  ", "6 wordt uitgevoerd") 
            postUpdate(Weather_OWM_Temperature_Tomorrow_AVG, gOWM18.state as Number)
            postUpdate(Weather_OWM_Temperature_Day2_AVG, gOWM42.state as Number)
            postUpdate(Weather_OWM_Temperature_Day3_AVG, gOWM66.state as Number)

        }
        case 7 : {
            logInfo("Case select number  ", "7 wordt uitgevoerd") 
            postUpdate(Weather_OWM_Temperature_Tomorrow_AVG, gOWM21.state as Number)
            postUpdate(Weather_OWM_Temperature_Day2_AVG, gOWM45.state as Number)
            postUpdate(Weather_OWM_Temperature_Day3_AVG, gOWM69.state as Number)
        }
        case 8 : {
            logInfo("Case select number  ", "8 wordt uitgevoerd") 
            postUpdate(Weather_OWM_Temperature_Tomorrow_AVG, gOWM24.state as Number)
            postUpdate(Weather_OWM_Temperature_Day2_AVG, gOWM48.state as Number)
            postUpdate(Weather_OWM_Temperature_Day3_AVG, gOWM72.state as Number)

        }
     }
end

As you see, it got the AVG value automatically from the item definition. From the same group I want to extract the MIN and MAX value. I could define new groups to do that, but that would triple my number of defined items.

So my question is: Is it possible to calculate the MIN, MAX and AVERAGE from the same group using a function.

I found the post of @rlkoshak: Design Pattern: Working with Groups in Rules, and I experimented (unsuccesful) using reduce to calculate the average. It’s unclear for me if I have to define the variables in the rule. But even is this works, could I also define a function to find the min and max, or is the best way to go ahead to define all the items ?

No, it only makes sense to have one function defined in a Group because a Group can only have one state. There is nowhere to store the results of the other functions.

val sum = MyGroup.members.map[ state as Number ].reduce[ sum, temp | sum + temp ]
val avg = sum / MyGroup.members.size

You don’t define any variables except the one that holds the result. The rest are arguments to the lambda so putting them before the | defines them.

Min should be something like

val min = MyGroup.members.map[ state as Number ]. reduce[ m, t | if(t < m) t else m ]
1 Like

Thanks a lot for your quick advice. I have got my rules working now:

val sum = gOWM03.members.map[ state as Number ].reduce[ sum, temp | sum + temp ]
val min = gOWM03.members.map[ state as Number ].reduce[ min, temp | if(temp < min) temp else min ]
val max = gOWM03.members.map[ state as Number ].reduce[ max, temp | if(temp > max) temp else max ]

val avg = sum / gOWM03.members.size
postUpdate(Weather_OWM_Temperature_Tomorrow_AVG, avg)
postUpdate(Weather_OWM_Temperature_Tomorrow_MIN, min)
postUpdate(Weather_OWM_Temperature_Tomorrow_MAX, max)

However, If I need to calculate it this way for all the different cases AND three days it’s quicker and cleaner to define the different groups for MIN and MAX calculation. Anyhow, I have learned to succesful use the group function, I will probably need it on other case to.

Thanks again @rlkoshak

1 Like