The name with prefix should be:
items[props.itemPrefix + StationName]
instead of
items[props.itemPrefix + localStationName]
This way you can have multiple widgets, one for local, another for some other location, etc.
The name with prefix should be:
items[props.itemPrefix + StationName]
instead of
items[props.itemPrefix + localStationName]
This way you can have multiple widgets, one for local, another for some other location, etc.
Hey @JimT thanks for your feedback - you are right and this would be valid for all the used item names as they all have the ‘local’ part in front of it. (I initially used the item-names from the docs and haven’t thought about the ideal naming at this stage). Even if this is just a naming thing and shouldn’t influence the functionality at all.
I’ll correct that (and adding the pre-defined model informations) tonight, when the last christmas events are over
Hey,
I am having some trouble with the configuration of the widget.
I was wondering, if you could post your yaml for comparison.
The thing I am most interested in is how to actually set a new name for “Daily” or “hourly” and how to set the images. Both might be related because somehow it doesn’t set the new value.
Do I have to set the Boolean value from false to true or where to write the actual word?
PS: I am also German so it might be quite convenient for me to just copycat right away I don’t do programming that often.
Welcome @2relativ
If you mean the above shown variant from @oh11 - he posted his YAML in the post below the image
You can set the localized namings for ‘daily’ and ‘hourly’ in the widget-configuration.
Thanks! That helped. I thought it must be hardcoded. Didn’t even think about the widget configuration. I am still testing the new OH3 version so cheers, mate!
The next iteration of the weather widget:
Backgroundfiles (example):
Imagefiles: zug_sunrise_sw.jpg (without TimeOfDay change)
zug_sunrise_sw_MORNING.jpg
zug_sunrise_sw_DAY.jpg
zug_sunrise_sw_EVENING.jpg
…
uid: weather_card
tags: []
props:
parameters:
- description: <b>Optional prefix</b> for item names.
label: Item prefix
name: itemPrefix
required: false
type: TEXT
groupName: general
- description: The number of hours you want to forecast <b>(<u>default:</u> 11)</b>
label: Number of hours to forecast
name: forecastHours
required: false
type: TEXT
groupName: general
- description: The number of days you want to forecast <b>(<u>default:</u> 5)</b>
label: Number of days to forecast
name: forecastDays
required: false
type: TEXT
groupName: general
- label: Background image-url
name: backgroundUrl
required: false
type: TEXT
groupName: general
- description: Background blur
label: Intensity of the background-blur (0 - 10)
name: backgroundBlur
required: false
type: TEXT
groupName: general
- description: Acitvate 24-hour clock-format <b>(<u>default:</u> 12-hour clock-format)</b>
label: 24h clock-format
name: dateFormat
required: false
type: BOOLEAN
groupName: general
- description: Acitvate Sun-Indicator <b>(<u>default:</u> no)</b>
label: Sun-Indicator
name: sunIndicator
required: false
type: BOOLEAN
groupName: general
- description: Item for extra Information eg. local Temperature Sensor
label: Information Item (optional)
name: itemInform
required: false
type: TEXT
groupName: general
advanced: true
- description: Alternative title for 'Hourly' within the segmented control <b>(<u>default:</u> Hourly)</b>
label: Alternative text for 'Hourly'
name: wordingForecastHours
required: false
type: TEXT
groupName: wording
advanced: true
- description: Alternative title for 'Daily' within the segmented control <b>(<u>default:</u> Daily)</b>
label: Alternative text for 'Daily'
name: wordingForecastDays
required: false
type: TEXT
groupName: wording
advanced: true
- description: Alternative title for 'Precipitation' within the segmented control <b>(<u>default:</u> Daily)</b>
label: Alternative text for 'Precipitation'
name: wordingForecastPrecib
required: false
type: TEXT
groupName: wording
advanced: true
- description: Alternative text for 'Now' in the hourly-forecast & precipitation-forecast tab
label: Translation 'Now'
name: wordingNow
required: false
type: TEXT
groupName: wording
advanced: true
- description: Alternative text for 'Today' in the daily-forecast tab
label: Translation 'Today'
name: wordingToday
required: false
type: TEXT
groupName: wording
advanced: true
- description: Alternative text for 'Feel' in the feel-temperature display
label: Translation 'Feel'
name: wordingFeel
required: false
type: TEXT
groupName: wording
advanced: true
- description: Alternative text for 'h' as Hour in the timeline (z.B. Uhr)
label: Translation 'h'
name: wordingHour
required: false
type: TEXT
groupName: wording
advanced: true
- description: Enable Times of Day feature for background image
label: item 'Times of Day'
name: itemTimesOfDay
required: false
type: TEXT
groupName: wording
advanced: true
parameterGroups:
- name: general
label: General settings
- name: wording
label: Wording
timestamp: Dec 25, 2020, 8:57:06 PM
component: f7-card
config:
class:
- padding
style:
background-image: "='url(' + props.backgroundUrl.substring(0, (props.backgroundUrl.length -4)) + ((props.itemTimesOfDay === undefined || items[props.itemTimesOfDay].state === 'NULL') ? '' : '_' + items[props.itemTimesOfDay].state) + props.backgroundUrl.substr(-4) + ')'"
background-size: cover
background-repeat: no-repeat
background-position: 100% 100%
border-radius: 20px
overflow: hidden
-ms-user-select: none
-moz-user-select: none
-webkit-user-select: none
user-select: none
--weather-card-color: 255,255,255
--weather-card-text-color: rgba(var(--weather-card-color),1)
slots:
default:
- component: f7-block
config:
class:
- no-padding
- no-margin
style:
background-color: rgba(255,255,255,.15)
backdrop-filter: ='blur(' + props.backgroundBlur + 'px)'
width: 100%
height: 100%
position: absolute
top: 0
left: 0
border-radius: 20px
- component: f7-row
slots:
default:
- component: f7-col
config:
class: col-80
style:
z-index: 999
slots:
default:
- component: Label
config:
text: "=items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'StationName'].state"
style:
color: var(--weather-card-text-color)
font-size: 26px
line-height: 32px
white-space: nowrap
overflow: hidden
text-overflow: ellipsis
text-shadow: -1px 1px 1px hsl(0,0%,66%)
- component: Label
config:
text: =dayjs().format("DD. MMMM YYYY")
style:
color: var(--weather-card-text-color)
font-size: 12px
white-space: nowrap
overflow: hidden
text-overflow: ellipsis
text-shadow: -1px 1px 1px hsl(0,0%,66%)
- component: f7-icon
config:
f7: "=(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '01d') ? 'sun_max_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '01n') ? 'moon_stars_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '02d') ? 'cloud_sun_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '02n') ? 'cloud_moon_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '03d') ? 'cloud_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '03n') ? 'cloud_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '04d') ? 'cloud_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '04n') ? 'cloud_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '09d') ? 'cloud_heavyrain_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '09n') ? 'cloud_heavyrain_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '10d') ? 'cloud_sun_rain_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '10n') ? 'cloud_moon_rain_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '11d') ? 'cloud_sun_bolt_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '11n') ? 'cloud_moon_bolt_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '13d') ? 'cloud_snow_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '13n') ? 'cloud_snow_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '50d') ? 'cloud_fog_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '50n') ? 'cloud_fog_fill' : '?'"
size: 60
class:
- align-content-center
style:
color: rgba(var(--weather-card-color),.9)
padding-top: 5px
padding-bottom: 5px
- component: Label
config:
text: "=items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Current_Condition'].state"
style:
color: var(--weather-card-text-color)
font-size: 16px
line-height: 21px
white-space: nowrap
overflow: hidden
text-overflow: ellipsis
text-shadow: -1px 1px 1px hsl(0,0%,66%)
- component: f7-col
config:
class: col-20
style:
z-index: 999
text-align: center
width: fit-content
overflow: hidden
slots:
default:
- component: Label
config:
text: "=(props.itemPrefix === undefined) ? Math.round(items.localCurrent_Temperature.state.split(' ')[0]) + '°' : Math.round(items[props.itemPrefix + 'Current_Temperature'].state.split(' ')[0])+'°'"
style:
color: var(--weather-card-text-color)
font-size: 58px
line-height: 58px
font-weight: 100
text-shadow: -1px 1px 1px hsl(0,0%,66%)
white-space: nowrap
overflow: hidden
text-overflow: ellipsis
- component: Label
config:
text: "=(props.itemPrefix === undefined) ? 'gefühlt: ' + Math.round(items.localCurrent_Apparenttemperature.state.split(' ')[0]) +'°' : ((props.wordingFeel === undefined) ? 'Feel: ' : props.wordingFeel + ': ') + Math.round(items[props.itemPrefix + 'Current_Apparenttemperature'].state.split(' ')[0]) +'°'"
style:
color: var(--weather-card-text-color)
font-size: 21px
font-weight: 100
text-shadow: -1px 1px 1px hsl(0,0%,66%)
white-space: nowrap
overflow: hidden
text-overflow: ellipsis
- component: Label
config:
text: "=(props.itemPrefix === undefined) ? Math.round(items.localCurrent_Humidity.state.split(' ')[0])+'% ' : Math.round(items[props.itemPrefix + 'Current_Humidity'].state.split(' ')[0]) + '% ' + Math.round(items[props.itemPrefix + 'Current_Windspeed'].state.split(' ')[0]) + 'km/h'"
style:
color: var(--weather-card-text-color)
font-size: 21px
font-weight: 100
text-shadow: -1px 1px 1px hsl(0,0%,66%)
white-space: nowrap
overflow: hidden
text-overflow: ellipsis
- component: Label
config:
text: "=(props.itemInform === undefined) ? '' : items[props.itemInform].state "
style:
color: var(--weather-card-text-color)
font-size: 16px
font-weight: 100
text-shadow: -1px 1px 1px hsl(0,0%,66%)
white-space: nowrap
overflow: hidden
text-overflow: ellipsis
- component: f7-segmented
config:
strong: true
textColor: white
class: margin-top
style:
--f7-segmented-strong-button-active-box-shadow: 0px 4px 0px -1px white
--f7-segmented-strong-button-active-text-color: rgba(var(--weather-card-color),1)
--f7-button-text-color: rgba(var(--weather-card-color),.5)
--f7-segmented-strong-text-color: rgba(var(--weather-card-color),.5)
--f7-segmented-strong-padding: 3px
--f7-button-active-text-color: rgba(var(--weather-card-color),1)
--f7-button-raised-box-shadow: none
--f7-segmented-strong-button-active-bg-color: transparent
--f7-button-border-radius: 0
border-bottom: 3px solid rgba(var(--weather-card-color),.5)
background: transparent
z-index: 999
slots:
default:
- component: oh-button
config:
text: "=(props.wordingForecastHours === undefined) ? 'Hourly' : props.wordingForecastHours"
color: var(--weather-card-text-color)
active: =vars.tab === 'hourly_forecast'
action: variable
actionVariable: tab
actionVariableValue: hourly_forecast
- component: oh-button
config:
text: "=(props.wordingForecastHours === undefined) ? 'Daily' : props.wordingForecastDays"
color: var(--weather-card-text-color)
active: =vars.tab === 'daily_forecast'
action: variable
actionVariable: tab
actionVariableValue: daily_forecast
- component: oh-button
config:
text: "=(props.wordingForecastPrecib === undefined) ? 'Precipitation' : props.wordingForecastPrecib"
color: var(--weather-card-text-color)
active: =vars.tab === 'precip_forecast'
action: variable
actionVariable: tab
actionVariableValue: precip_forecast
- component: f7-swiper
config:
visible: =!vars.tab || vars.tab === 'hourly_forecast'
navigation: true
class:
- padding-top
params:
initalSlide: 0
runCallbacksOnInit: true
grabCursor: true
observer: true
observeSlideChildren: true
updateOnWindowResize: true
spaceBetween: 5
mousewheel: true
keyboard: true
watchOverflow: true
breakpoints:
"0":
slidesPerView: 1
"240":
slidesPerView: 2
"320":
slidesPerView: 3
"480":
slidesPerView: 4
"640":
slidesPerView: 5
style:
--swiper-navigation-size: 30px
--swiper-navigation-color: var(--weather-card-text-color)
slots:
default:
- component: oh-repeater
config:
sourceType: range
for: hour
rangeStart: 0
rangeStop: "=(props.forecastHours === undefined) ? 11 : Number(props.forecastHours)"
fragment: true
slots:
default:
- component: f7-swiper-slide
config:
id: =loop.hour_idx
expandable: true
style:
background: "=(props.sunIndicator === true) ? ((dayjs().add(loop.hour,'hour').format() >= items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + (dayjs().add(loop.hour,'hour').startOf('day').format() === dayjs().startOf('day').format() ? 'Today' : (dayjs().add(loop.hour,'hour').startOf('day').format() === dayjs().startOf('day').add(1,'day').format() ? 'Tomorrow' : 'Day2')) + '_Sunrise'].state && dayjs().add(loop.hour,'hour').format() <= items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + (dayjs().add(loop.hour,'hour').startOf('day').format() === dayjs().startOf('day').format() ? 'Today' : (dayjs().add(loop.hour,'hour').startOf('day').format() === dayjs().startOf('day').add(1,'day').format() ? 'Tomorrow' : 'Day2')) + '_Sunset'].state) ? 'rgba(44,130,201,.15)' : 'rgba(190,144,212,.15)') : 'none'"
border-radius: 5px
slots:
default:
- component: f7-row
config:
class:
- justify-content-center
- align-items-center
slots:
default:
- component: Label
config:
text: "=(loop.hour === 0) ? ((props.wordingNow === undefined) ? 'Now' : props.wordingNow) : ((props.dateFormat === false) ? dayjs().add(loop.hour,'hour').startOf('hour').format('h A') : dayjs().add(loop.hour,'hour').startOf('hour').format('HH') + ((props.wordingHour === undefined) ? ' h' : ' ' + props.wordingHour))"
style:
color: var(--weather-card-text-color)
font-size: 18px
font-weight: 600
- component: f7-col
config:
class:
- justify-content-center
- align-items-center
- text-align-center
slots:
default:
- component: f7-icon
config:
f7: "=(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + '' + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0')) + '_Iconid'].state === '01d') ? 'sun_max_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + '' + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0')) + '_Iconid'].state === '01n') ? 'moon_stars_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + '' + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0')) + '_Iconid'].state === '02d') ? 'cloud_sun_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + '' + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0')) + '_Iconid'].state === '02n') ? 'cloud_moon_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + '' + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0')) + '_Iconid'].state === '03d') ? 'cloud_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + '' + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0')) + '_Iconid'].state === '03n') ? 'cloud_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + '' + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0')) + '_Iconid'].state === '04d') ? 'cloud_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + '' + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0')) + '_Iconid'].state === '04n') ? 'cloud_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + '' + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0')) + '_Iconid'].state === '09d') ? 'cloud_heavyrain_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + '' + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0')) + '_Iconid'].state === '09n') ? 'cloud_heavyrain_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + '' + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0')) + '_Iconid'].state === '10d') ? 'cloud_sun_rain_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + '' + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0')) + '_Iconid'].state === '10n') ? 'cloud_moon_rain_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + '' + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0')) + '_Iconid'].state === '11d') ? 'cloud_sun_bolt_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + '' + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0')) + '_Iconid'].state === '11n') ? 'cloud_moon_bolt_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + '' + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0')) + '_Iconid'].state === '13d') ? 'cloud_snow_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + '' + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0')) + '_Iconid'].state === '13n') ? 'cloud_snow_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + '' + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0')) + '_Iconid'].state === '50d') ? 'cloud_fog_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + '' + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0')) + '_Iconid'].state === '50n') ? 'cloud_fog_fill' : ''"
size: 40
style:
padding-right: 5px
color: var(--weather-card-text-color)
- component: Label
config:
text: "=Math.round(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + '' + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0')) + '_Temperature'].state.split(' ')[0]) + '° ' + Math.round(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + '' + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0')) + '_Windspeed'].state.split(' ')[0]) + 'km/h'"
style:
font-size: 18px
font-weight: 400
color: var(--weather-card-text-color)
- component: f7-swiper
config:
visible: =vars.tab === 'daily_forecast'
navigation: true
class:
- padding-top
params:
initalSlide: 0
grabCursor: true
observer: true
spaceBetween: 1
observeSlideChildren: true
updateOnWindowResize: true
watchOverflow: true
mousewheel: true
keyboard: true
breakpoints:
"0":
slidesPerView: 1
"210":
slidesPerView: "=(props.forecastDays === undefined) ? 2 : ((props.forecastDays < 2) ? Math.round(Number(props.forecastDays) + 1) : 2)"
"320":
slidesPerView: "=(props.forecastDays === undefined) ? 3 : ((props.forecastDays < 3) ? Math.round(Number(props.forecastDays) + 1) : 3)"
"480":
slidesPerView: "=(props.forecastDays === undefined) ? 4 : ((props.forecastDays < 4) ? Math.round(Number(props.forecastDays) + 1) : 4)"
"640":
slidesPerView: "=(props.forecastDays === undefined) ? 5 : ((props.forecastDays < 5) ? Math.round(Number(props.forecastDays) + 1) : 5)"
style:
--swiper-navigation-size: 30px
--swiper-navigation-color: var(--weather-card-text-color)
slots:
default:
- component: oh-repeater
config:
sourceType: range
for: day
rangeStart: 0
rangeStop: "=(props.forecastDays === undefined) ? 5 : Number(props.forecastDays)"
fragment: true
slots:
default:
- component: f7-swiper-slide
config:
class:
- text-align-center
slots:
default:
- component: f7-row
config:
class:
- justify-content-center
- align-items-center
slots:
default:
- component: Label
config:
text: "=(loop.day === 0) ? ((props.wordingToday === undefined) ? 'Today' : props.wordingToday) : dayjs().add(loop.day,'day').startOf('day').format('dddd')"
style:
color: var(--weather-card-text-color)
font-size: 18px
font-weight: 600
- component: f7-icon
config:
class:
- align-center
f7: "=(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '01d') ? 'sun_max_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '01n') ? 'moon_stars_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '02d') ? 'cloud_sun_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '02n') ? 'cloud_moon_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '03d') ? 'cloud_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '03n') ? 'cloud_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '04d') ? 'cloud_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '04n') ? 'cloud_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '09d') ? 'cloud_heavyrain_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '09n') ? 'cloud_heavyrain_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '10d') ? 'cloud_sun_rain_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '10n') ? 'cloud_moon_rain_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '11d') ? 'cloud_sun_bolt_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '11n') ? 'cloud_moon_bolt_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '13d') ? 'cloud_snow_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '13n') ? 'cloud_snow_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '50d') ? 'cloud_fog_fill' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '50n') ? 'cloud_fog_fill' : '?'"
size: 40
style:
color: var(--weather-card-text-color)
- component: f7-row
config:
class:
- justify-content-center
slots:
default:
- component: Label
config:
text: "=Math.round(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + ((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + (loop.day_idx))) + '_Maxtemperature'].state.split(' ')[0]) +'°'"
style:
font-size: 18px
font-weight: 400
color: var(--weather-card-text-color)
- component: Label
config:
text: /
style:
color: rgba(var(--weather-card-color),.5)
font-size: 18px
- component: Label
config:
text: "=Math.round(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + ((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + (loop.day_idx))) + '_Mintemperature'].state.split(' ')[0]) +'°'"
style:
font-size: 18px
font-weight: 400
color: rgba(var(--weather-card-color),.75)
- component: f7-swiper
config:
visible: =vars.tab === 'precip_forecast'
navigation: true
class:
- padding-top
params:
initalSlide: 0
runCallbacksOnInit: true
grabCursor: true
observer: true
observeSlideChildren: true
updateOnWindowResize: true
spaceBetween: 5
mousewheel: true
keyboard: true
watchOverflow: true
breakpoints:
"0":
slidesPerView: 1
"240":
slidesPerView: 2
"320":
slidesPerView: 3
"480":
slidesPerView: 4
"640":
slidesPerView: 5
style:
--swiper-navigation-size: 30px
--swiper-navigation-color: var(--weather-card-text-color)
slots:
default:
- component: oh-repeater
config:
sourceType: range
for: hour
rangeStart: 0
rangeStop: "=(props.forecastHours === undefined) ? 11 : Number(props.forecastHours)"
fragment: true
slots:
default:
- component: f7-swiper-slide
config:
id: =loop.hour_idx
expandable: true
style:
background: "=(props.sunIndicator === true) ? ((dayjs().add(loop.hour,'hour').format() >= items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + (dayjs().add(loop.hour,'hour').startOf('day').format() === dayjs().startOf('day').format() ? 'Today' : (dayjs().add(loop.hour,'hour').startOf('day').format() === dayjs().startOf('day').add(1,'day').format() ? 'Tomorrow' : 'Day2')) + '_Sunrise'].state && dayjs().add(loop.hour,'hour').format() <= items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + (dayjs().add(loop.hour,'hour').startOf('day').format() === dayjs().startOf('day').format() ? 'Today' : (dayjs().add(loop.hour,'hour').startOf('day').format() === dayjs().startOf('day').add(1,'day').format() ? 'Tomorrow' : 'Day2')) + '_Sunset'].state) ? 'rgba(44,130,201,.15)' : 'rgba(190,144,212,.15)') : 'none'"
border-radius: 5px
slots:
default:
- component: f7-row
config:
class:
- justify-content-center
- align-items-center
slots:
default:
- component: Label
config:
text: "=(loop.hour === 0) ? ((props.wordingNow === undefined) ? 'Now' : props.wordingNow) : ((props.dateFormat === false) ? dayjs().add(loop.hour,'hour').startOf('hour').format('h A') : dayjs().add(loop.hour,'hour').startOf('hour').format('HH') + ((props.wordingHour === undefined) ? ' h' : ' ' + props.wordingHour))"
style:
color: var(--weather-card-text-color)
font-size: 18px
font-weight: 600
- component: f7-col
config:
class:
- justify-content-center
- align-items-center
- text-align-center
slots:
default:
- component: f7-icon
config:
f7: "=(Math.round(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0') + '_Precipprobability'].state.split(' ')[0] ) >= 50 ) ? 'umbrella_fill' : 'umbrella' "
size: 40
style:
padding-right: 5px
color: var(--weather-card-text-color)
- component: Label
config:
text: "=Math.round(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0') + '_Precipprobability'].state.split(' ')[0] ) +'%'"
style:
font-size: 18px
font-weight: 400
color: var(--weather-card-text-color)
component: widget:weather_card
config:
backgroundUrl: http://10.5.0.90:8080/static/zug_sunrise_sw.jpg
sunIndicator: true
itemTimesOfDay: TimeOfDay
dateFormat: true
wordingToday: Heute
wordingNow: Jetzt
wordingForecastDays: Täglich
wordingFeel: gefühlt
backgroundBlur: "0"
wordingForecastPrecib: Niederschlag
wordingHour: Uhr
itemPrefix: OneCallAPIweatherandforecast_
wordingForecastHours: Stündlich
item: OneCallAPIweatherandforecast
itemInform: GenericMQTTThing_BME680Temperatur
The “Time of day” Funktion gabe me an idea. Is it possible to set backgrounds according to the weather? That would be really cool. Also: I hope your widget becomes an official feature! Looks really great and is promising.
Hey @2relativ
this is what I did here
It sets/changes the background image depending on the current weather (the conditionIconID to be explicit) - it isn’t a fotorealistic one in that case, as it’s another style there.
The expression is kinda long, but you could change it and reuse it in any other widget-style:
"=(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'localCurrentIconId'].state === '01d') ? '' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'localCurrentIconId'].state === '01n') ? '' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'localCurrentIconId'].state === '02d') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '02.svg)' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'localCurrentIconId'].state === '02n') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '02.svg)' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'localCurrentIconId'].state === '03d') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '03.svg)' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'localCurrentIconId'].state === '03n') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '03.svg)' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'localCurrentIconId'].state === '04d') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '04.svg)' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'localCurrentIconId'].state === '04n') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '04.svg)' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'localCurrentIconId'].state === '09d') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '09.svg)' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'localCurrentIconId'].state === '09n') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '09.svg)' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'localCurrentIconId'].state === '10d') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '10.svg)' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'localCurrentIconId'].state === '10n') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '10.svg)' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'localCurrentIconId'].state === '11d') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '11.svg)' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'localCurrentIconId'].state === '11n') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '11.svg)' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'localCurrentIconId'].state === '13d') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '13.svg)' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'localCurrentIconId'].state === '13n') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '13.svg)' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'localCurrentIconId'].state === '50d') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '50.svg)' : (items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'localCurrentIconId'].state === '50n') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '50.svg)' : '?'"
This already looks really great.
I really love the way the weawow android app is displaying weather info
Just thought I’d share it here maybe we can take parts from its display style for this widget.
Take a look in the YAML (line 120):
Change
"items[props.itemTimesOfDay].state"
to
items[props.itemPrefix) + 'CurrentIconId'].state
However, as @RGroll wrote, this is already implemented as an symbol.
@salexes: I think that the graphics can be implemented via a “widget action”. I’ll try it.
Does this version also support sunrise & sunset popup? If yes, then I did simething wrong Everything else is working! Thanks a lot for this/these widget(s)!
If anyone is also using Darksky here a customized version of @oh11 's version. Due to Darksky does not provide the correct icon-id’s like set in the code but provide’s already the Base64 icon I modified it to use them instead.
uid: weather_card
tags: []
props:
parameters:
- description: <b>Optional prefix</b> for item names.
label: Item prefix
name: itemPrefix
required: false
type: TEXT
groupName: general
- description: The number of hours you want to forecast <b>(<u>default:</u> 11)</b>
label: Number of hours to forecast
name: forecastHours
required: false
type: TEXT
groupName: general
- description: The number of days you want to forecast <b>(<u>default:</u> 5)</b>
label: Number of days to forecast
name: forecastDays
required: false
type: TEXT
groupName: general
- label: Background image-url
name: backgroundUrl
required: false
type: TEXT
groupName: general
- description: Background blur
label: Intensity of the background-blur (0 - 10)
name: backgroundBlur
required: false
type: TEXT
groupName: general
- description: Acitvate 24-hour clock-format <b>(<u>default:</u> 12-hour clock-format)</b>
label: 24h clock-format
name: dateFormat
required: false
type: BOOLEAN
groupName: general
- description: Acitvate Sun-Indicator <b>(<u>default:</u> no)</b>
label: Sun-Indicator
name: sunIndicator
required: false
type: BOOLEAN
groupName: general
- description: Alternative title for 'Hourly' within the segmented control <b>(<u>default:</u> Hourly)</b>
label: Alternative text for 'Hourly'
name: wordingForecastHours
required: false
type: TEXT
groupName: wording
advanced: true
- description: Alternative title for 'Daily' within the segmented control <b>(<u>default:</u> Daily)</b>
label: Alternative text for 'Daily'
name: wordingForecastDays
required: false
type: TEXT
groupName: wording
advanced: true
- description: Alternative title for 'Precipitation' within the segmented control <b>(<u>default:</u> Daily)</b>
label: Alternative text for 'Precipitation'
name: wordingForecastPrecib
required: false
type: TEXT
groupName: wording
advanced: true
- description: Alternative text for 'Now' in the hourly-forecast & precipitation-forecast tab
label: Translation 'Now'
name: wordingNow
required: false
type: TEXT
groupName: wording
advanced: true
- description: Alternative text for 'Today' in the daily-forecast tab
label: Translation 'Today'
name: wordingToday
required: false
type: TEXT
groupName: wording
advanced: true
- description: Alternative text for 'Feel' in the feel-temperature display
label: Translation 'Feel'
name: wordingFeel
required: false
type: TEXT
groupName: wording
advanced: true
- description: Alternative text for 'h' as Hour in the timeline (z.B. Uhr)
label: Translation 'h'
name: wordingHour
required: false
type: TEXT
groupName: wording
advanced: true
parameterGroups:
- name: general
label: General settings
- name: wording
label: Wording
timestamp: Jan 2, 2021, 11:43:54 AM
component: f7-card
config:
class:
- padding
style:
background-image: ='url(' + props.backgroundUrl + ')'
background-size: cover
background-repeat: no-repeat
background-position: 100% 100%
border-radius: 20px
overflow: hidden
-ms-user-select: none
-moz-user-select: none
-webkit-user-select: none
user-select: none
--weather-card-color: 255,255,255
--weather-card-text-color: rgba(var(--weather-card-color),1)
slots:
default:
- component: f7-block
config:
class:
- no-padding
- no-margin
style:
background-color: rgba(255,255,255,.15)
backdrop-filter: ='blur(' + props.backgroundBlur + 'px)'
width: 100%
height: 100%
position: absolute
top: 0
left: 0
border-radius: 20px
- component: f7-row
slots:
default:
- component: f7-col
config:
class: col-80
style:
z-index: 999
slots:
default:
- component: Label
config:
text: "=items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'localStationName'].state"
style:
color: var(--weather-card-text-color)
font-size: 26px
line-height: 32px
white-space: nowrap
overflow: hidden
text-overflow: ellipsis
text-shadow: -1px 1px 1px hsl(0,0%,66%)
- component: Label
config:
text: =dayjs().format("DD. MMMM YYYY")
style:
color: var(--weather-card-text-color)
font-size: 12px
white-space: nowrap
overflow: hidden
text-overflow: ellipsis
text-shadow: -1px 1px 1px hsl(0,0%,66%)
- component: oh-image
config:
item: "=((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Current_Icon'"
visible: "=(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Current_Icon'].state.toString() != 'NULL')"
class:
- align-content-center
style:
color: rgba(var(--weather-card-color),.9)
padding-top: 5px
padding-bottom: 5px
width: 100px
height: 100px
- component: oh-image
config:
url: '/static/weather/unknown.png'
visible: "=(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Current_Icon'].state === 'NULL')"
class:
- align-content-center
style:
color: rgba(var(--weather-card-color),.9)
padding-top: 5px
padding-bottom: 5px
width: 100px
height: 100px
- component: Label
config:
text: "=items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Current_Condition'].state"
style:
color: var(--weather-card-text-color)
font-size: 16px
line-height: 21px
white-space: nowrap
overflow: hidden
text-overflow: ellipsis
text-shadow: -1px 1px 1px hsl(0,0%,66%)
- component: f7-col
config:
class: col-20
style:
z-index: 999
text-align: center
width: fit-content
overflow: hidden
slots:
default:
- component: Label
config:
text: "=(props.itemPrefix === undefined) ? Math.round(items.localCurrent_Temperature.state.split(' ')[0]*10)/10+'°' : Math.round(items[props.itemPrefix + 'Current_Temperature'].state.split(' ')[0]*10)/10+'°'"
style:
color: var(--weather-card-text-color)
font-size: 58px
line-height: 58px
font-weight: 100
text-shadow: -1px 1px 1px hsl(0,0%,66%)
white-space: nowrap
overflow: hidden
text-overflow: ellipsis
- component: Label
config:
text: "=(props.itemPrefix === undefined) ? 'gefühlt: ' + Math.round(items.localCurrent_Apparenttemperature.state.split(' ')[0]) +'°' : ((props.wordingFeel === undefined) ? 'Feel: ' : props.wordingFeel + ': ') + Math.round(items[props.itemPrefix + 'Current_Apparenttemperature'].state.split(' ')[0]) +'°'"
style:
color: var(--weather-card-text-color)
font-size: 21px
font-weight: 100
text-shadow: -1px 1px 1px hsl(0,0%,66%)
white-space: nowrap
overflow: hidden
text-overflow: ellipsis
- component: Label
config:
text: "=(props.itemPrefix === undefined) ? Math.round(items.localCurrent_Humidity.state.split(' ')[0])+'% ' : Math.round(items[props.itemPrefix + 'Current_Humidity'].state.split(' ')[0]) + '% ' + Math.round(items[props.itemPrefix + 'Current_Windspeed'].state.split(' ')[0]) + 'km/h'"
style:
color: var(--weather-card-text-color)
font-size: 21px
font-weight: 100
text-shadow: -1px 1px 1px hsl(0,0%,66%)
white-space: nowrap
overflow: hidden
text-overflow: ellipsis
- component: f7-segmented
config:
strong: true
textColor: white
class: margin-top
style:
--f7-segmented-strong-button-active-box-shadow: 0px 4px 0px -1px white
--f7-segmented-strong-button-active-text-color: rgba(var(--weather-card-color),1)
--f7-button-text-color: rgba(var(--weather-card-color),.5)
--f7-segmented-strong-text-color: rgba(var(--weather-card-color),.5)
--f7-segmented-strong-padding: 3px
--f7-button-active-text-color: rgba(var(--weather-card-color),1)
--f7-button-raised-box-shadow: none
--f7-segmented-strong-button-active-bg-color: transparent
--f7-button-border-radius: 0
border-bottom: 3px solid rgba(var(--weather-card-color),.5)
background: transparent
z-index: 999
slots:
default:
- component: oh-button
config:
text: "=(props.wordingForecastHours === undefined) ? 'Hourly' : props.wordingForecastHours"
color: var(--weather-card-text-color)
active: =vars.tab === 'hourly_forecast'
action: variable
actionVariable: tab
actionVariableValue: hourly_forecast
- component: oh-button
config:
text: "=(props.wordingForecastHours === undefined) ? 'Daily' : props.wordingForecastDays"
color: var(--weather-card-text-color)
active: =vars.tab === 'daily_forecast'
action: variable
actionVariable: tab
actionVariableValue: daily_forecast
- component: oh-button
config:
text: "=(props.wordingForecastPrecib === undefined) ? 'Precipitation' : props.wordingForecastPrecib"
color: var(--weather-card-text-color)
active: =vars.tab === 'precip_forecast'
action: variable
actionVariable: tab
actionVariableValue: precip_forecast
- component: f7-swiper
config:
visible: =!vars.tab || vars.tab === 'hourly_forecast'
navigation: true
class:
- padding-top
params:
initalSlide: 0
runCallbacksOnInit: true
grabCursor: true
observer: true
observeSlideChildren: true
updateOnWindowResize: true
spaceBetween: 5
mousewheel: true
keyboard: true
watchOverflow: true
breakpoints:
"0":
slidesPerView: 1
"240":
slidesPerView: 2
"320":
slidesPerView: 3
"480":
slidesPerView: 4
"640":
slidesPerView: 5
style:
--swiper-navigation-size: 30px
--swiper-navigation-color: var(--weather-card-text-color)
slots:
default:
- component: oh-repeater
config:
sourceType: range
for: hour
rangeStart: 0
rangeStop: "=(props.forecastHours === undefined) ? 11 : Number(props.forecastHours)"
fragment: true
slots:
default:
- component: f7-swiper-slide
config:
id: =loop.hour_idx
expandable: true
style:
background: "=(props.sunIndicator === true) ? ((dayjs().add(loop.hour,'hour').format() >= items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + (dayjs().add(loop.hour,'hour').startOf('day').format() === dayjs().startOf('day').format() ? 'Today' : (dayjs().add(loop.hour,'hour').startOf('day').format() === dayjs().startOf('day').add(1,'day').format() ? 'Tomorrow' : 'Day2')) + '_Sunrise'].state && dayjs().add(loop.hour,'hour').format() <= items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + (dayjs().add(loop.hour,'hour').startOf('day').format() === dayjs().startOf('day').format() ? 'Today' : (dayjs().add(loop.hour,'hour').startOf('day').format() === dayjs().startOf('day').add(1,'day').format() ? 'Tomorrow' : 'Day2')) + '_Sunset'].state) ? 'rgba(44,130,201,.15)' : 'rgba(190,144,212,.15)') : 'none'"
border-radius: 5px
slots:
default:
- component: f7-row
config:
class:
- justify-content-center
- align-items-center
slots:
default:
- component: Label
config:
text: "=(loop.hour === 0) ? ((props.wordingNow === undefined) ? 'Now' : props.wordingNow) : ((props.dateFormat === false) ? dayjs().add(loop.hour,'hour').startOf('hour').format('h A') : dayjs().add(loop.hour,'hour').startOf('hour').format('HH') + ((props.wordingHour === undefined) ? ' h' : ' ' + props.wordingHour))"
style:
color: var(--weather-card-text-color)
font-size: 18px
font-weight: 600
- component: f7-col
config:
class:
- justify-content-center
- align-items-center
- text-align-center
slots:
default:
- component: oh-image
config:
item: "=((props.itemPrefix === undefined) ? '' : props.itemPrefix) + '' + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0')) + '_Icon'"
visible: "=(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + '' + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0')) + '_Icon'].state != 'NULL')"
style:
padding-right: 5px
color: var(--weather-card-text-color)
width: 50px
height: 50px
- component: oh-image
config:
url: '/static/weather/unknown.png'
visible: "=(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + '' + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0')) + '_Icon'].state === 'NULL')"
style:
padding-right: 5px
color: var(--weather-card-text-color)
width: 50px
height: 50px
- component: Label
config:
text: "=Math.round(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + '' + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0')) + '_Temperature'].state.split(' ')[0]) + '° ' + Math.round(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + '' + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0')) + '_Windspeed'].state.split(' ')[0]) + 'km/h'"
style:
font-size: 18px
font-weight: 400
color: var(--weather-card-text-color)
- component: f7-swiper
config:
visible: =vars.tab === 'daily_forecast'
navigation: true
class:
- padding-top
params:
initalSlide: 0
grabCursor: true
observer: true
spaceBetween: 1
observeSlideChildren: true
updateOnWindowResize: true
watchOverflow: true
mousewheel: true
keyboard: true
breakpoints:
"0":
slidesPerView: 1
"210":
slidesPerView: "=(props.forecastDays === undefined) ? 2 : ((props.forecastDays < 2) ? Math.round(Number(props.forecastDays) + 1) : 2)"
"320":
slidesPerView: "=(props.forecastDays === undefined) ? 3 : ((props.forecastDays < 3) ? Math.round(Number(props.forecastDays) + 1) : 3)"
"480":
slidesPerView: "=(props.forecastDays === undefined) ? 4 : ((props.forecastDays < 4) ? Math.round(Number(props.forecastDays) + 1) : 4)"
"640":
slidesPerView: "=(props.forecastDays === undefined) ? 5 : ((props.forecastDays < 5) ? Math.round(Number(props.forecastDays) + 1) : 5)"
style:
--swiper-navigation-size: 30px
--swiper-navigation-color: var(--weather-card-text-color)
slots:
default:
- component: oh-repeater
config:
sourceType: range
for: day
rangeStart: 0
rangeStop: "=(props.forecastDays === undefined) ? 5 : Number(props.forecastDays)"
fragment: true
slots:
default:
- component: f7-swiper-slide
config:
class:
- text-align-center
slots:
default:
- component: f7-row
config:
class:
- justify-content-center
- align-items-center
slots:
default:
- component: Label
config:
text: "=(loop.day === 0) ? ((props.wordingToday === undefined) ? 'Today' : props.wordingToday) : dayjs().add(loop.day,'day').startOf('day').format('dddd')"
style:
color: var(--weather-card-text-color)
font-size: 18px
font-weight: 600
- component: oh-image
config:
class:
- align-center
item: "=((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + ((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx)) + '_Icon'"
visible: "=(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + ((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx)) + '_Icon'].state != 'NULL')"
style:
color: var(--weather-card-text-color)
width: 50px
height: 50px
- component: oh-image
config:
class:
- align-center
url: '/static/weather/unknown.png'
visible: "=(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + ((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx)) + '_Icon'].state === 'NULL')"
style:
color: var(--weather-card-text-color)
width: 50px
height: 50px
- component: f7-row
config:
class:
- justify-content-center
slots:
default:
- component: Label
config:
text: "=Math.round(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + ((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + (loop.day_idx))) + '_Maxtemperature'].state.split(' ')[0]) +'°'"
style:
font-size: 18px
font-weight: 400
color: var(--weather-card-text-color)
- component: Label
config:
text: /
style:
color: rgba(var(--weather-card-color),.5)
font-size: 18px
- component: Label
config:
text: "=Math.round(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + ((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + (loop.day_idx))) + '_Mintemperature'].state.split(' ')[0]) +'°'"
style:
font-size: 18px
font-weight: 400
color: rgba(var(--weather-card-color),.75)
- component: f7-swiper
config:
visible: =vars.tab === 'precip_forecast'
navigation: true
class:
- padding-top
params:
initalSlide: 0
runCallbacksOnInit: true
grabCursor: true
observer: true
observeSlideChildren: true
updateOnWindowResize: true
spaceBetween: 5
mousewheel: true
keyboard: true
watchOverflow: true
breakpoints:
"0":
slidesPerView: 1
"240":
slidesPerView: 2
"320":
slidesPerView: 3
"480":
slidesPerView: 4
"640":
slidesPerView: 5
style:
--swiper-navigation-size: 30px
--swiper-navigation-color: var(--weather-card-text-color)
slots:
default:
- component: oh-repeater
config:
sourceType: range
for: hour
rangeStart: 0
rangeStop: "=(props.forecastHours === undefined) ? 11 : Number(props.forecastHours)"
fragment: true
slots:
default:
- component: f7-swiper-slide
config:
id: =loop.hour_idx
expandable: true
style:
background: "=(props.sunIndicator === true) ? ((dayjs().add(loop.hour,'hour').format() >= items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + (dayjs().add(loop.hour,'hour').startOf('day').format() === dayjs().startOf('day').format() ? 'Today' : (dayjs().add(loop.hour,'hour').startOf('day').format() === dayjs().startOf('day').add(1,'day').format() ? 'Tomorrow' : 'Day2')) + '_Sunrise'].state && dayjs().add(loop.hour,'hour').format() <= items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + (dayjs().add(loop.hour,'hour').startOf('day').format() === dayjs().startOf('day').format() ? 'Today' : (dayjs().add(loop.hour,'hour').startOf('day').format() === dayjs().startOf('day').add(1,'day').format() ? 'Tomorrow' : 'Day2')) + '_Sunset'].state) ? 'rgba(44,130,201,.15)' : 'rgba(190,144,212,.15)') : 'none'"
border-radius: 5px
slots:
default:
- component: f7-row
config:
class:
- justify-content-center
- align-items-center
slots:
default:
- component: Label
config:
text: "=(loop.hour === 0) ? ((props.wordingNow === undefined) ? 'Now' : props.wordingNow) : ((props.dateFormat === false) ? dayjs().add(loop.hour,'hour').startOf('hour').format('h A') : dayjs().add(loop.hour,'hour').startOf('hour').format('HH') + ((props.wordingHour === undefined) ? ' h' : ' ' + props.wordingHour))"
style:
color: var(--weather-card-text-color)
font-size: 18px
font-weight: 600
- component: f7-col
config:
class:
- justify-content-center
- align-items-center
- text-align-center
slots:
default:
- component: oh-image
config:
_f7: "=(Math.round(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0') + '_Precipprobability'].state.split(' ')[0] ) >= 50 ) ? 'umbrella_fill' : 'umbrella' "
url: "=(Math.round(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0') + '_Precipprobability'].state.split(' ')[0] ) >= 50 ) ? '/static/weather/rain.png' : '/static/weather/lightrain.png' "
style:
padding-right: 5px
color: var(--weather-card-text-color)
width: 50px
height: 50px
- component: Label
config:
text: "=Math.round(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0') + '_Precipprobability'].state.split(' ')[0] ) +'%'"
style:
font-size: 18px
font-weight: 400
color: var(--weather-card-text-color)
For the “static” rain icon in the icon tab and for unknown weather icon i’ve created a folder “weather” inside the “html” folder where you can place a “rain.png, lightrain.png, unknown.png”
Here an enhanced version with settings tab to switch between local or internet data (only current temp and wind as my own station readings)
uid: weather_card
tags: []
props:
parameters:
- description: <b>Optional prefix</b> for item names.
label: Item prefix
name: itemPrefix
required: false
type: TEXT
groupName: undefined
- description: Optional Station name
label: Station name
name: station_name
required: false
type: TEXT
groupName: location
advanced: false
- description: The number of hours you want to forecast <b>(<u>default:</u> 11)</b>
label: Number of hours to forecast
name: forecastHours
required: false
type: TEXT
groupName: general
- description: The number of days you want to forecast <b>(<u>default:</u> 5)</b>
label: Number of days to forecast
name: forecastDays
required: false
type: TEXT
groupName: general
- label: Background image-url
name: backgroundUrl
required: false
type: TEXT
groupName: general
- description: Background blur
label: Intensity of the background-blur (0 - 10)
name: backgroundBlur
required: false
type: TEXT
groupName: general
- description: Acitvate 24-hour clock-format <b>(<u>default:</u> 12-hour clock-format)</b>
label: 24h clock-format
name: dateFormat
required: false
type: BOOLEAN
groupName: general
- description: Acitvate Sun-Indicator <b>(<u>default:</u> no)</b>
label: Sun-Indicator
name: sunIndicator
required: false
type: BOOLEAN
groupName: general
- description: Alternative title for 'Hourly' within the segmented control <b>(<u>default:</u> Hourly)</b>
label: Alternative text for 'Hourly'
name: wordingForecastHours
required: false
type: TEXT
groupName: wording
advanced: true
- description: Alternative title for 'Daily' within the segmented control <b>(<u>default:</u> Daily)</b>
label: Alternative text for 'Daily'
name: wordingForecastDays
required: false
type: TEXT
groupName: wording
advanced: true
- description: Alternative title for 'Precipitation' within the segmented control <b>(<u>default:</u> Daily)</b>
label: Alternative text for 'Precipitation'
name: wordingForecastPrecib
required: false
type: TEXT
groupName: wording
advanced: true
- description: Alternative text for 'Now' in the hourly-forecast & precipitation-forecast tab
label: Translation 'Now'
name: wordingNow
required: false
type: TEXT
groupName: wording
advanced: true
- description: Alternative text for 'Today' in the daily-forecast tab
label: Translation 'Today'
name: wordingToday
required: false
type: TEXT
groupName: wording
advanced: true
- description: Alternative text for 'Feel' in the feel-temperature display
label: Translation 'Feel'
name: wordingFeel
required: false
type: TEXT
groupName: wording
advanced: true
- description: Alternative text for 'h' as Hour in the timeline (z.B. Uhr)
label: Translation 'h'
name: wordingHour
required: false
type: TEXT
groupName: wording
advanced: true
parameterGroups:
- name: location
label: Location
- name: general
label: General settings
- name: wording
label: Wording
timestamp: Jan 2, 2021, 4:35:38 PM
component: f7-card
config:
class:
- padding
style:
background-image: ='url(' + props.backgroundUrl + ')'
background-size: cover
background-repeat: no-repeat
background-position: 100% 100%
border-radius: 20px
overflow: hidden
-ms-user-select: none
-moz-user-select: none
-webkit-user-select: none
user-select: none
--weather-card-color: 255,255,255
--weather-card-text-color: rgba(var(--weather-card-color),1)
slots:
default:
- component: f7-block
config:
class:
- no-padding
- no-margin
style:
background-color: rgba(255,255,255,.15)
backdrop-filter: ='blur(' + props.backgroundBlur + 'px)'
width: 100%
height: 100%
position: absolute
top: 0
left: 0
border-radius: 20px
- component: f7-row
slots:
default:
- component: f7-col
config:
class: col-80
style:
z-index: 999
slots:
default:
- component: Label
config:
text: "=(props.station_name === undefined) ? items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'localStationName'].state : props.station_name"
style:
color: var(--weather-card-text-color)
font-size: 26px
line-height: 32px
white-space: nowrap
overflow: hidden
text-overflow: ellipsis
text-shadow: -1px 1px 1px hsl(0,0%,66%)
- component: Label
config:
text: =dayjs().format("DD. MMMM YYYY")
style:
color: var(--weather-card-text-color)
font-size: 12px
white-space: nowrap
overflow: hidden
text-overflow: ellipsis
text-shadow: -1px 1px 1px hsl(0,0%,66%)
- component: oh-image
config:
item: "=((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Current_Icon'"
visible: "=(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Current_Icon'].state.toString() != 'NULL')"
class:
- align-content-center
style:
color: rgba(var(--weather-card-color),.9)
padding-top: 5px
padding-bottom: 5px
width: 100px
height: 100px
- component: oh-image
config:
url: /static/weather/unknown.png
visible: "=(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Current_Icon'].state === 'NULL')"
class:
- align-content-center
style:
color: rgba(var(--weather-card-color),.9)
padding-top: 5px
padding-bottom: 5px
width: 100px
height: 100px
- component: Label
config:
text: "=items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Current_Condition'].state"
style:
color: var(--weather-card-text-color)
font-size: 16px
line-height: 21px
white-space: nowrap
overflow: hidden
text-overflow: ellipsis
text-shadow: -1px 1px 1px hsl(0,0%,66%)
- component: f7-col
config:
class: col-20
style:
z-index: 999
text-align: center
width: fit-content
overflow: hidden
slots:
default:
- component: Label
config:
text: "=(vars.loc_net === false || vars.loc_net === undefined) ? (Math.round(items.Wetterstation_Temp.state) + '°') :(props.itemPrefix === undefined) ? Math.round(items.localCurrent_Temperature.state.split(' ')[0]*10)/10+'°' : Math.round(items[props.itemPrefix + 'Current_Temperature'].state.split(' ')[0]*10)/10+'°'"
style:
color: var(--weather-card-text-color)
font-size: 58px
line-height: 58px
font-weight: 100
text-shadow: -1px 1px 1px hsl(0,0%,66%)
white-space: nowrap
overflow: hidden
text-overflow: ellipsis
- component: Label
config:
text: "=(vars.loc_net === false || vars.loc_net === undefined) ? (props.wordingFeel + ': ' + Math.round(13.12 + 0.6215 * items.Wetterstation_Temp.state + (0.3965 * items.Wetterstation_Temp.state - 11.37) * Math.pow(items.Wetterstation_Wind.state, 0.16)) + '°') : ((props.itemPrefix === undefined) ? 'gefühlt: ' + Math.round(items.localCurrent_Apparenttemperature.state.split(' ')[0]) +'°' : ((props.wordingFeel === undefined) ? 'Feel: ' : props.wordingFeel + ': ') + Math.round(items[props.itemPrefix + 'Current_Apparenttemperature'].state.split(' ')[0]) +'°')"
style:
color: var(--weather-card-text-color)
font-size: 21px
font-weight: 100
text-shadow: -1px 1px 1px hsl(0,0%,66%)
white-space: nowrap
overflow: hidden
text-overflow: ellipsis
- component: Label
config:
text: "=(vars.loc_net === false || vars.loc_net === undefined) ? ((props.itemPrefix === undefined) ? Math.round(items.localCurrent_Humidity.state.split(' ')[0])+'% ' : Math.round(items[props.itemPrefix + 'Current_Humidity'].state.split(' ')[0]) + '% ' + Math.round(items.Wetterstation_Wind.state) + 'km/h') : (props.itemPrefix === undefined) ? Math.round(items.localCurrent_Humidity.state.split(' ')[0])+'% ' : Math.round(items[props.itemPrefix + 'Current_Humidity'].state.split(' ')[0]) + '% ' + Math.round(items[props.itemPrefix + 'Current_Windspeed'].state.split(' ')[0]) + 'km/h'"
style:
color: var(--weather-card-text-color)
font-size: 21px
font-weight: 100
text-shadow: -1px 1px 1px hsl(0,0%,66%)
white-space: nowrap
overflow: hidden
text-overflow: ellipsis
- component: Label
config:
text: "=(vars.loc_net === false || vars.loc_net === undefined) ? 'Lokal' : 'Internet'"
style:
color: var(--weather-card-text-color)
font-size: 10px
font-weight: 100
text-shadow: -1px 1px 1px hsl(0,0%,66%)
white-space: nowrap
overflow: hidden
text-overflow: ellipsis
- component: f7-segmented
config:
strong: true
textColor: white
class: margin-top
style:
--f7-segmented-strong-button-active-box-shadow: 0px 4px 0px -1px white
--f7-segmented-strong-button-active-text-color: rgba(var(--weather-card-color),1)
--f7-button-text-color: rgba(var(--weather-card-color),.5)
--f7-segmented-strong-text-color: rgba(var(--weather-card-color),.5)
--f7-segmented-strong-padding: 3px
--f7-button-active-text-color: rgba(var(--weather-card-color),1)
--f7-button-raised-box-shadow: none
--f7-segmented-strong-button-active-bg-color: transparent
--f7-button-border-radius: 0
border-bottom: 3px solid rgba(var(--weather-card-color),.5)
background: transparent
z-index: 999
slots:
default:
- component: oh-button
config:
text: "=(props.wordingForecastHours === undefined) ? 'Hourly' : props.wordingForecastHours"
color: var(--weather-card-text-color)
active: =vars.tab === 'hourly_forecast'
action: variable
actionVariable: tab
actionVariableValue: hourly_forecast
- component: oh-button
config:
text: "=(props.wordingForecastHours === undefined) ? 'Daily' : props.wordingForecastDays"
color: var(--weather-card-text-color)
active: =vars.tab === 'daily_forecast'
action: variable
actionVariable: tab
actionVariableValue: daily_forecast
- component: oh-button
config:
text: "=(props.wordingForecastPrecib === undefined) ? 'Precipitation' : props.wordingForecastPrecib"
color: var(--weather-card-text-color)
active: =vars.tab === 'precip_forecast'
action: variable
actionVariable: tab
actionVariableValue: precip_forecast
- component: oh-button
config:
iconF7: gear_alt
iconSize: 20px
color: var(--weather-card-text-color)
active: =vars.tab === 'settings'
action: variable
actionVariable: tab
actionVariableValue: settings
- component: f7-swiper
config:
visible: =!vars.tab || vars.tab === 'hourly_forecast'
navigation: true
class:
- padding-top
params:
initalSlide: 0
runCallbacksOnInit: true
grabCursor: true
observer: true
observeSlideChildren: true
updateOnWindowResize: true
spaceBetween: 5
mousewheel: true
keyboard: true
watchOverflow: true
breakpoints:
"0":
slidesPerView: 1
"240":
slidesPerView: 2
"320":
slidesPerView: 3
"480":
slidesPerView: 4
"640":
slidesPerView: 5
style:
--swiper-navigation-size: 30px
--swiper-navigation-color: var(--weather-card-text-color)
slots:
default:
- component: oh-repeater
config:
sourceType: range
for: hour
rangeStart: 0
rangeStop: "=(props.forecastHours === undefined) ? 11 : Number(props.forecastHours)"
fragment: true
slots:
default:
- component: f7-swiper-slide
config:
id: =loop.hour_idx
expandable: true
style:
background: "=(props.sunIndicator === true) ? ((dayjs().add(loop.hour,'hour').format() >= items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + (dayjs().add(loop.hour,'hour').startOf('day').format() === dayjs().startOf('day').format() ? 'Today' : (dayjs().add(loop.hour,'hour').startOf('day').format() === dayjs().startOf('day').add(1,'day').format() ? 'Tomorrow' : 'Day2')) + '_Sunrise'].state && dayjs().add(loop.hour,'hour').format() <= items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + (dayjs().add(loop.hour,'hour').startOf('day').format() === dayjs().startOf('day').format() ? 'Today' : (dayjs().add(loop.hour,'hour').startOf('day').format() === dayjs().startOf('day').add(1,'day').format() ? 'Tomorrow' : 'Day2')) + '_Sunset'].state) ? 'rgba(44,130,201,.15)' : 'rgba(190,144,212,.15)') : 'none'"
border-radius: 5px
slots:
default:
- component: f7-row
config:
class:
- justify-content-center
- align-items-center
slots:
default:
- component: Label
config:
text: "=(loop.hour === 0) ? ((props.wordingNow === undefined) ? 'Now' : props.wordingNow) : ((props.dateFormat === false) ? dayjs().add(loop.hour,'hour').startOf('hour').format('h A') : dayjs().add(loop.hour,'hour').startOf('hour').format('HH') + ((props.wordingHour === undefined) ? ' h' : ' ' + props.wordingHour))"
style:
color: var(--weather-card-text-color)
font-size: 18px
font-weight: 600
- component: f7-col
config:
class:
- justify-content-center
- align-items-center
- text-align-center
slots:
default:
- component: oh-image
config:
item: "=((props.itemPrefix === undefined) ? '' : props.itemPrefix) + '' + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0')) + '_Icon'"
visible: "=(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + '' + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0')) + '_Icon'].state != 'NULL')"
style:
padding-right: 5px
color: var(--weather-card-text-color)
width: 50px
height: 50px
- component: oh-image
config:
url: /static/weather/unknown.png
visible: "=(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + '' + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0')) + '_Icon'].state === 'NULL')"
style:
padding-right: 5px
color: var(--weather-card-text-color)
width: 50px
height: 50px
- component: Label
config:
text: "=Math.round(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + '' + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0')) + '_Temperature'].state.split(' ')[0]) + '° ' + Math.round(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + '' + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0')) + '_Windspeed'].state.split(' ')[0]) + 'km/h'"
style:
font-size: 18px
font-weight: 400
color: var(--weather-card-text-color)
- component: f7-swiper
config:
visible: =vars.tab === 'daily_forecast'
navigation: true
class:
- padding-top
params:
initalSlide: 0
grabCursor: true
observer: true
spaceBetween: 1
observeSlideChildren: true
updateOnWindowResize: true
watchOverflow: true
mousewheel: true
keyboard: true
breakpoints:
"0":
slidesPerView: 1
"210":
slidesPerView: "=(props.forecastDays === undefined) ? 2 : ((props.forecastDays < 2) ? Math.round(Number(props.forecastDays) + 1) : 2)"
"320":
slidesPerView: "=(props.forecastDays === undefined) ? 3 : ((props.forecastDays < 3) ? Math.round(Number(props.forecastDays) + 1) : 3)"
"480":
slidesPerView: "=(props.forecastDays === undefined) ? 4 : ((props.forecastDays < 4) ? Math.round(Number(props.forecastDays) + 1) : 4)"
"640":
slidesPerView: "=(props.forecastDays === undefined) ? 5 : ((props.forecastDays < 5) ? Math.round(Number(props.forecastDays) + 1) : 5)"
style:
--swiper-navigation-size: 30px
--swiper-navigation-color: var(--weather-card-text-color)
slots:
default:
- component: oh-repeater
config:
sourceType: range
for: day
rangeStart: 0
rangeStop: "=(props.forecastDays === undefined) ? 5 : Number(props.forecastDays)"
fragment: true
slots:
default:
- component: f7-swiper-slide
config:
class:
- text-align-center
slots:
default:
- component: f7-row
config:
class:
- justify-content-center
- align-items-center
slots:
default:
- component: Label
config:
text: "=(loop.day === 0) ? ((props.wordingToday === undefined) ? 'Today' : props.wordingToday) : dayjs().add(loop.day,'day').startOf('day').format('dddd')"
style:
color: var(--weather-card-text-color)
font-size: 18px
font-weight: 600
- component: oh-image
config:
class:
- align-center
item: "=((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + ((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx)) + '_Icon'"
visible: "=(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + ((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx)) + '_Icon'].state != 'NULL')"
style:
color: var(--weather-card-text-color)
width: 50px
height: 50px
- component: oh-image
config:
class:
- align-center
url: /static/weather/unknown.png
visible: "=(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + ((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx)) + '_Icon'].state === 'NULL')"
style:
color: var(--weather-card-text-color)
width: 50px
height: 50px
- component: f7-row
config:
class:
- justify-content-center
slots:
default:
- component: Label
config:
text: "=Math.round(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + ((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + (loop.day_idx))) + '_Maxtemperature'].state.split(' ')[0]) +'°'"
style:
font-size: 18px
font-weight: 400
color: var(--weather-card-text-color)
- component: Label
config:
text: /
style:
color: rgba(var(--weather-card-color),.5)
font-size: 18px
- component: Label
config:
text: "=Math.round(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + ((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + (loop.day_idx))) + '_Mintemperature'].state.split(' ')[0]) +'°'"
style:
font-size: 18px
font-weight: 400
color: rgba(var(--weather-card-color),.75)
- component: f7-swiper
config:
visible: =vars.tab === 'precip_forecast'
navigation: true
class:
- padding-top
params:
initalSlide: 0
runCallbacksOnInit: true
grabCursor: true
observer: true
observeSlideChildren: true
updateOnWindowResize: true
spaceBetween: 5
mousewheel: true
keyboard: true
watchOverflow: true
breakpoints:
"0":
slidesPerView: 1
"240":
slidesPerView: 2
"320":
slidesPerView: 3
"480":
slidesPerView: 4
"640":
slidesPerView: 5
style:
--swiper-navigation-size: 30px
--swiper-navigation-color: var(--weather-card-text-color)
slots:
default:
- component: oh-repeater
config:
sourceType: range
for: hour
rangeStart: 0
rangeStop: "=(props.forecastHours === undefined) ? 11 : Number(props.forecastHours)"
fragment: true
slots:
default:
- component: f7-swiper-slide
config:
id: =loop.hour_idx
expandable: true
style:
background: "=(props.sunIndicator === true) ? ((dayjs().add(loop.hour,'hour').format() >= items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + (dayjs().add(loop.hour,'hour').startOf('day').format() === dayjs().startOf('day').format() ? 'Today' : (dayjs().add(loop.hour,'hour').startOf('day').format() === dayjs().startOf('day').add(1,'day').format() ? 'Tomorrow' : 'Day2')) + '_Sunrise'].state && dayjs().add(loop.hour,'hour').format() <= items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'Forecast' + (dayjs().add(loop.hour,'hour').startOf('day').format() === dayjs().startOf('day').format() ? 'Today' : (dayjs().add(loop.hour,'hour').startOf('day').format() === dayjs().startOf('day').add(1,'day').format() ? 'Tomorrow' : 'Day2')) + '_Sunset'].state) ? 'rgba(44,130,201,.15)' : 'rgba(190,144,212,.15)') : 'none'"
border-radius: 5px
slots:
default:
- component: f7-row
config:
class:
- justify-content-center
- align-items-center
slots:
default:
- component: Label
config:
text: "=(loop.hour === 0) ? ((props.wordingNow === undefined) ? 'Now' : props.wordingNow) : ((props.dateFormat === false) ? dayjs().add(loop.hour,'hour').startOf('hour').format('h A') : dayjs().add(loop.hour,'hour').startOf('hour').format('HH') + ((props.wordingHour === undefined) ? ' h' : ' ' + props.wordingHour))"
style:
color: var(--weather-card-text-color)
font-size: 18px
font-weight: 600
- component: f7-col
config:
class:
- justify-content-center
- align-items-center
- text-align-center
slots:
default:
- component: oh-image
config:
_f7: "=(Math.round(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0') + '_Precipprobability'].state.split(' ')[0] ) >= 50 ) ? 'umbrella_fill' : 'umbrella' "
url: "=(Math.round(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0') + '_Precipprobability'].state.split(' ')[0] ) >= 50 ) ? '/static/weather/rain.png' : '/static/weather/lightrain.png' "
style:
padding-right: 5px
color: var(--weather-card-text-color)
width: 50px
height: 50px
- component: Label
config:
text: "=Math.round(items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'ForecastHours' + (loop.hour_idx+1).toString().padStart(2,'0') + '_Precipprobability'].state.split(' ')[0] ) +'%'"
style:
font-size: 18px
font-weight: 400
color: var(--weather-card-text-color)
- component: f7-swiper
config:
visible: =vars.tab === 'settings'
navigation: true
class:
- padding-top
params:
initalSlide: 0
runCallbacksOnInit: true
grabCursor: true
observer: true
observeSlideChildren: true
updateOnWindowResize: true
spaceBetween: 5
mousewheel: true
keyboard: true
watchOverflow: true
breakpoints:
"0":
slidesPerView: 1
"240":
slidesPerView: 2
"320":
slidesPerView: 3
"480":
slidesPerView: 4
"640":
slidesPerView: 5
style:
--swiper-navigation-size: 30px
--swiper-navigation-color: var(--weather-card-text-color)
slots:
default:
- component: f7-swiper-slide
config:
expandable: true
slots:
default:
- component: f7-row
config:
class:
- justify-content-center
- align-items-center
slots:
default:
- component: Label
config:
text: Datenquelle
style:
color: var(--weather-card-text-color)
font-size: 18px
font-weight: 600
- component: f7-col
config:
class:
- justify-content-center
- align-items-center
- text-align-center
slots:
default:
- component: f7-col
slots:
default:
- component: f7-row
slots:
default:
- component: f7-col
config:
outline: true
style:
width: "50"
slots:
default:
- component: oh-toggle
config:
variable: loc_net
style:
margin-top: 10px
slots: {}
- component: Label
config:
text: "=(vars.loc_net === true) ? 'Internet' : 'Lokal'"
textColor: white
style:
margin-top: 10px
font-size: 18px
font-weight: 400
color: var(--weather-card-text-color)
Maybe if someone is searching for Windchill calculation (in km/h and °C): Here you go:
Math.round(13.12 + 0.6215 * Temp + (0.3965 * Temp- 11.37) * Math.pow(Wind, 0.16))
Amazing work!
Just try to use the OneCall version with the standard item imported exactly as posted (only adjusting the channel info); API is working I able to see the values for each item.
The Issue is with the Widget, most part of the information is shown correct, the only problem with precipitation items, see image:
Any clue why the precipitation appear as undefined?
Let me know if you need any additional information.
Thanks in advance.
BR
Hey @Joselh
thanks for giving the widget a try!
Could you please have a look into the UI item configuration of one of the ForecastHour-items http://YOURIP:8080/#!/settings/items/localForecastHour2PrecipProb and check if you get a valid item-state there? And if yes, which value is shown there?
I also recognized that your station name in the top-right is ‘NULL’ - is this for demo purposes? Normaly it should show the name of the city, where your weather-station is located. But this information isn’t available in the OneCall API.
Do you created all things that I mentioned above? Including this one:
Thing weather-and-forecast local "Local Weather And Forecast" [location="YOURLOCATION", forecastDays=4]
If yes, what is the item-state of localStationName
Many thanks Rainer!
Station Name works Perfect!
Regarding precipitation, here is the item requested:
As you can see, it’s defined with the current value to 0.0%
Thanks in advance for your support.
BR
Jose
No problemo and thanks for the hint. It seems, that something is messed up in my setup due to the frequent updates from earlier versions I did. As an easy fix you could do the following:
Search for the line:
text: "=items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'localForecastHour' + Math.round(loop.hour_idx+1) + 'PrecipProb'].displayState + '%'"
and replace it with:
text: "=items[((props.itemPrefix === undefined) ? '' : props.itemPrefix) + 'localForecastHour' + Math.round(loop.hour_idx+1) + 'PrecipProb'].state"
It slightly changes the format of the output, which shouldn’t bother too much, I hope.
And if you’re willed to help me one more time, it would be awesome if you could create a custom widget with this content and making me a screenshot with the output?! Thanks in advance!
Further more it would nice to know, if you used the UI to create the items or if you used textfiles?
uid: test
component: f7-card
config:
content: "='State: ' + items.localForecastHour2PrecipProb.state + ' | displayState: ' + items.localForecastHour2PrecipProb.displayState"
Thank you very much!
Many Thanks Raimer,
your proposed Fix is working without any issue, precipitation is showed correctly!!
Items were created from textual definition, too many items to do it by hand.
Here you have the requested Screenshot:
Many thanks for your support!! let me know if you need any additional test from my side.
Thanks for your great widget
Happy New Year
BR
Jose
Hii folks
any ideas on how we can create a line chart with the forecast temperatures? I am not sure, but the chart pages in OH3 might not suppor this. What i am thinking about is a line chart plotting all the forecast temperatures at a given instant in time vs. plotting historical values of an item against a time series (which i know is possible).
something like the line graph in salexes’ post