Hello,
i’ve seen a number of examples calculating daily forecast min/max temp values based on the 3 hour forecast values already but in addition wanted to have one daily weather status as icon/text for today and tomorrow.
I also use item definitions and grouping to parse values and added a logic to rate weather status based on weather condition ID’s. Unfortunately they are not min/max so i needed to group them first from best to worst or in weather terms clear to thunderstorms:
- Group 800: Clear
- Group 80x: Clouds
- Group 3xx: Drizzle
- Group 5xx: Rain
- Group 6xx: Snow
- Group 7xx: Atmosphere
- Group 2xx: Thunderstorm
- 200: Thunderstorm|thunderstorm with light rain
- 201: Thunderstorm|thunderstorm with rain
- 202: Thunderstorm|thunderstorm with heavy rain
- 210: Thunderstorm|light thunderstorm
- 221: Thunderstorm|ragged thunderstorm
- 230: Thunderstorm|thunderstorm with light drizzle
- 231: Thunderstorm|thunderstorm with drizzle
- 232: Thunderstorm|thunderstorm with heavy drizzle
- 211: Thunderstorm|thunderstorm
- 212: Thunderstorm|heavy thunderstorm
weather.items
DateTime LocalWeatherAndForecast_Current_LetzteMessung {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:current#time-stamp"}
String LocalWeatherAndForecast_Today_WetterlageID
String LocalWeatherAndForecast_Tomorrow_WetterlageID
DateTime WeatherForecast_Hours03 (gWeatherForecastTime) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours03#time-stamp"}
DateTime WeatherForecast_Hours06 (gWeatherForecastTime) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours06#time-stamp"}
DateTime WeatherForecast_Hours09 (gWeatherForecastTime) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours09#time-stamp"}
DateTime WeatherForecast_Hours12 (gWeatherForecastTime) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours12#time-stamp"}
DateTime WeatherForecast_Hours15 (gWeatherForecastTime) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours15#time-stamp"}
DateTime WeatherForecast_Hours18 (gWeatherForecastTime) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours18#time-stamp"}
DateTime WeatherForecast_Hours21 (gWeatherForecastTime) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours21#time-stamp"}
DateTime WeatherForecast_Hours24 (gWeatherForecastTime) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours24#time-stamp"}
DateTime WeatherForecast_Hours27 (gWeatherForecastTime) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours27#time-stamp"}
DateTime WeatherForecast_Hours30 (gWeatherForecastTime) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours30#time-stamp"}
DateTime WeatherForecast_Hours33 (gWeatherForecastTime) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours33#time-stamp"}
DateTime WeatherForecast_Hours36 (gWeatherForecastTime) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours36#time-stamp"}
DateTime WeatherForecast_Hours39 (gWeatherForecastTime) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours39#time-stamp"}
DateTime WeatherForecast_Hours42 (gWeatherForecastTime) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours42#time-stamp"}
DateTime WeatherForecast_Hours45 (gWeatherForecastTime) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours45#time-stamp"}
DateTime WeatherForecast_Hours48 (gWeatherForecastTime) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours48#time-stamp"}
Number:Temperature WeatherForecast_Hours03_Temp (gWeatherForecastTemp) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours03#temperature"}
Number:Temperature WeatherForecast_Hours06_Temp (gWeatherForecastTemp) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours06#temperature"}
Number:Temperature WeatherForecast_Hours09_Temp (gWeatherForecastTemp) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours09#temperature"}
Number:Temperature WeatherForecast_Hours12_Temp (gWeatherForecastTemp) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours12#temperature"}
Number:Temperature WeatherForecast_Hours15_Temp (gWeatherForecastTemp) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours15#temperature"}
Number:Temperature WeatherForecast_Hours18_Temp (gWeatherForecastTemp) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours18#temperature"}
Number:Temperature WeatherForecast_Hours21_Temp (gWeatherForecastTemp) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours21#temperature"}
Number:Temperature WeatherForecast_Hours24_Temp (gWeatherForecastTemp) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours24#temperature"}
Number:Temperature WeatherForecast_Hours27_Temp (gWeatherForecastTemp) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours27#temperature"}
Number:Temperature WeatherForecast_Hours30_Temp (gWeatherForecastTemp) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours30#temperature"}
Number:Temperature WeatherForecast_Hours33_Temp (gWeatherForecastTemp) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours33#temperature"}
Number:Temperature WeatherForecast_Hours36_Temp (gWeatherForecastTemp) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours36#temperature"}
Number:Temperature WeatherForecast_Hours39_Temp (gWeatherForecastTemp) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours39#temperature"}
Number:Temperature WeatherForecast_Hours42_Temp (gWeatherForecastTemp) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours42#temperature"}
Number:Temperature WeatherForecast_Hours45_Temp (gWeatherForecastTemp) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours45#temperature"}
Number:Temperature WeatherForecast_Hours48_Temp (gWeatherForecastTemp) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours48#temperature"}
String WeatherForecast_Hours03_ID (gWeatherForecastID) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours03#condition-id"}
String WeatherForecast_Hours06_ID (gWeatherForecastID) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours06#condition-id"}
String WeatherForecast_Hours09_ID (gWeatherForecastID) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours09#condition-id"}
String WeatherForecast_Hours12_ID (gWeatherForecastID) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours12#condition-id"}
String WeatherForecast_Hours15_ID (gWeatherForecastID) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours15#condition-id"}
String WeatherForecast_Hours18_ID (gWeatherForecastID) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours18#condition-id"}
String WeatherForecast_Hours21_ID (gWeatherForecastID) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours21#condition-id"}
String WeatherForecast_Hours24_ID (gWeatherForecastID) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours24#condition-id"}
String WeatherForecast_Hours27_ID (gWeatherForecastID) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours27#condition-id"}
String WeatherForecast_Hours30_ID (gWeatherForecastID) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours30#condition-id"}
String WeatherForecast_Hours33_ID (gWeatherForecastID) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours33#condition-id"}
String WeatherForecast_Hours36_ID (gWeatherForecastID) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours36#condition-id"}
String WeatherForecast_Hours39_ID (gWeatherForecastID) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours39#condition-id"}
String WeatherForecast_Hours42_ID (gWeatherForecastID) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours42#condition-id"}
String WeatherForecast_Hours45_ID (gWeatherForecastID) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours45#condition-id"}
String WeatherForecast_Hours48_ID (gWeatherForecastID) {channel="openweathermap:weather-and-forecast:<binding-bridge-ID>:local:forecastHours48#condition-id"}
Note: you will have to replace with your weather bridge binding ID, e.g. “12ab34c5”.
weather.rules
rule "Wetter Update"
when
System started or
Item LocalWeatherAndForecast_Current_LetzteMessung changed
then
if ((LocalWeatherAndForecast_Current_LetzteMessung!=NULL)) {
Thread::sleep(25) //wait until all weather items are properly updated
var today_min = 50|°C
var today_max = -50|°C
var tomorrow_min = 50|°C
var tomorrow_max = -50|°C
val String todaystr = now.toString.substring(0,10)
val String tomorrowstr = (now.plusHours(24)).toString.substring(0,10)
//Today's min/max temperature
gWeatherForecastTime.members.filter[f | f.state.toString.substring(0,10)==todaystr].forEach[wtime | {
var wtemp = gWeatherForecastTemp.members.findFirst[j | j.name == wtime.name.toString + "_Temp"]
if (wtemp.state != NULL) {
if ((wtemp.state) < today_min) {
today_min = wtemp.state
}
if ((wtemp.state) > today_max) {
today_max = wtemp.state
}
}
}
]
//Tomorrow's min/max temperature
gWeatherForecastTime.members.filter[f | f.state.toString.substring(0,10)==tomorrowstr].forEach[wtime | {
var wtemp = gWeatherForecastTemp.members.findFirst[j | j.name == wtime.name.toString + "_Temp"]
if (wtemp.state != NULL) {
if ((wtemp.state) < tomorrow_min) {
tomorrow_min = wtemp.state
}
if ((wtemp.state) > tomorrow_max) {
tomorrow_max = wtemp.state
}
}
}
]
//Today's "worst" weather condition
var Number wID_num // loop variable for today's forecast Weather Condition ID
var Number wIDmax_num = 0 // day's worst weather condition ID
gWeatherForecastTime.members.filter[f | f.state.toString.substring(0,10)==todaystr].forEach[wtime | {
var wID = gWeatherForecastID.members.findFirst[j | j.name == wtime.name.toString + "_ID"]
if (wID.state != NULL) {
// logInfo("wetterMinMax", "ID item " + wID.toString)
wID_num = Integer::parseInt(wID.state.toString)
// check forecast categories in order of worst priority to assign "worst" weather condition ID
// heavy thunderstorm and thunderstorm
if (wID_num == 212) { // no matter what current max value is assign worst ID immediately
wIDmax_num = wID_num
}
else if (wID_num == 211) { // unless ID not 212 then assign 2nd worst immediately
if (wIDmax_num != 212) {
wIDmax_num = wID_num
}
}
// all other thunderstorms
else if ((wID_num >= 200) && (wID_num < 233)) {
if ((wIDmax_num != 211) && (wIDmax_num != 212)) {
if (wIDmax_num <233) { // if max ID is a Thunderstorm already (but not severe) assign max of Thunderstorm
wIDmax_num=Math::max(wIDmax_num, wID_num)
}
else { // else assign Thunderstorm ID
wIDmax_num = wID_num
}
}
}
// all other weather conditions except clear and cloudy
else if ((wID_num >= 300) && (wID_num < 782)) {
if ((wIDmax_num >=800) || (wIDmax_num ==0)) { // if max ID is clear/cloudy or not used before assign condition ID
wIDmax_num = wID_num
}
else { // else assign max of condition ID
wIDmax_num=Math::max(wIDmax_num, wID_num)
}
}
// clear and cloudy conditions
else if ((wID_num >= 800) && (wID_num < 805)) {
if ((wIDmax_num >=800) || (wIDmax_num ==0)) { // if max ID is clear/cloudy already or not used before assign max of condition ID
wIDmax_num=Math::max(wIDmax_num, wID_num)
}
}
}
}
]
if (wIDmax_num == 0) { // late in a day WeatherForecast_Hours03 could be pointing to the following day already therefore do not update
logInfo("wetter Update", "TodayMaxWetterlageID=0, not updating")
}
else {
LocalWeatherAndForecast_Today_WetterlageID.postUpdate(wIDmax_num.toString)
}
//Tomorrow's "worst" weather condition
wIDmax_num = 0
gWeatherForecastTime.members.filter[f | f.state.toString.substring(0,10)==tomorrowstr].forEach[wtime | {
var wID = gWeatherForecastID.members.findFirst[j | j.name == wtime.name.toString + "_ID"]
if (wID.state != NULL) {
wID_num = Integer::parseInt(wID.state.toString)
// check forecast categories in order of worst priority to assign "worst" weather condition ID
// heavy thunderstorm and thunderstorm
if (wID_num == 212) { // no matter what current max value is assign worst ID immediately
wIDmax_num = wID_num
}
else if (wID_num == 211) { // unless ID not 212 then assign 2nd worst immediately
if (wIDmax_num != 212) {
wIDmax_num = wID_num
}
}
// all other thunderstorms
else if ((wID_num >= 200) && (wID_num < 233)) {
if ((wIDmax_num != 211) && (wIDmax_num != 212)) {
if (wIDmax_num <233) { // if max ID is a Thunderstorm already (but not severe) assign max of Thunderstorm
wIDmax_num=Math::max(wIDmax_num, wID_num)
}
else { // else assign Thunderstorm ID
wIDmax_num = wID_num
}
}
}
// all other weather conditions except clear and cloudy
else if ((wID_num >= 300) && (wID_num < 782)) {
if ((wIDmax_num >=800) || (wIDmax_num ==0)) { // if max ID is clear/cloudy assign condition ID
wIDmax_num = wID_num
}
else { // else assign max of condition ID
wIDmax_num=Math::max(wIDmax_num, wID_num)
}
}
// clear and cloudy conditions
else if ((wID_num >= 800) && (wID_num < 805)) {
if ((wIDmax_num >=800) || (wIDmax_num ==0)) { // only if max ID is clear/cloudy already assign max of condition ID
wIDmax_num=Math::max(wIDmax_num, wID_num)
}
}
}
}
]
if (wIDmax_num == 0) { // late in a day WeatherForecast_Hours03 could be pointing to the following day already therefore do not update
logInfo("wetter Update", "TomorrowMaxWetterlageID=0, not updating")
}
else {
LocalWeatherAndForecast_Tomorrow_WetterlageID.postUpdate(wIDmax_num.toString)
}
// update your items based on today_min, today_max, tomorrow_min, tomorrow_max
// e.g. GATEWAYEXTRAS_1_WetterPrognosetempmin.sendCommand(today_min as Number)
// or WeatherFctToday.postUpdate(Math::round((today_min as Number).doubleValue).toString + "°C - " + Math::round((today_max as Number).doubleValue).toString + "°C")
//
// LocalWeatherAndForecast_Today_WetterlageID and LocalWeatherAndForecast_Tomorrow_WetterlageID contain the weather forecast condition ID
I use a map file to display the weather text and dynamic icons for the graphic, e.g.
Text item=LocalWeatherAndForecast_Today_WetterlageID label="Heute [MAP(wetter.map):%s]"
Text item=LocalWeatherAndForecast_Tomorrow_WetterlageID label="Morgen [MAP(wetter.map):%s]"
Hope this helps,
Dirk