UI Widget: Weather

Hi @RGroll

Thank you. That is pretty much what I wanted. I managed to get a bit further during the day today after I took out all the variables and just had flat text to try and understand what was happening.

I see now that the indentation makes all the difference. Also had just realized that I needed the columns and was battling with that.

Will go through the suggested docs and see if I can understand better.

Always appreciate your work.

1 Like

Hi @RGroll

I think understand the rows, columns etc now. I would have battled forever without your help. The alignment was clearly my biggest issue.

Can you point me to a resource for the different style components etc?

For example: z-index: 999 etc.

I have an issue now that on my Android Mobile the Current Temp is “behind” the SUN? So not clearly visible. Trying to fix that.

Cheers
mark

Hey @Mark_VG

glad it helped you. There are tons and tons of ressources regarding css properties - this is nothing OH-specific.

Regarding the z-index, you can find some information here for example.
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/Adding_z-index

I personally like the explanation of css stuff from this site:

To fix the “Sun problem” you have to set the z-index of the image-component, to a lower value than the one from the Label component which shows the current temp - something like:

YAML with min/max values (and a lower z-index)
uid: weatherPopup_extended_uv_feel_min_max
tags:
  - weather
  - popup
  - daily forecast
  - OpenWeatherMap
  - extended
props:
  parameters:
    - description: <b>Optional prefix</b> for item names.
      label: Item prefix
      name: itemPrefix
      required: false
      type: TEXT
      groupName: general
    - description: <b>Additional prefix</b> for item names that belongs to another Things channel (valid for 'StationName' as it might differ)
      label: Additional item prefix
      name: itemPrefix2
      required: false
      type: TEXT
      groupName: general
      advanced: true
    - description: The number of hours you want to forecast (<u>default:</u> <b>12</b>)
      label: Number of hours to forecast
      name: forecastHours
      required: false
      type: TEXT
      groupName: general
    - description: The number of days you want to forecast (<u>default:</u> <b>3</b>)
      label: Number of days to forecast
      name: forecastDays
      required: false
      type: TEXT
      groupName: general
    - description: Activate day & night Indication on hourly forecast (background color & sunrise / sunset indicator icon)
      label: Show sunrise & sunset
      name: sunIndicator
      required: false
      type: BOOLEAN
      groupName: general
    - description: Acitvate 24-hour clock-format (<u>default:</u> <b>12-hour clock-format</b>)
      label: 24h clock-format
      name: dateFormat
      required: false
      type: BOOLEAN
      groupName: general
    - description: Add suffix to the timestamp
      label: Custom timestamp suffix
      name: timestampSuffix
      required: false
      type: TEXT
      groupName: general
    - description: Overwrite the location header
      label: Location title
      name: locationTitle
      required: false
      type: TEXT
      groupName: general
    - description: Folder where you stored your weather-images (<u>default:</u> <b>/static/files/weather_img/</b>)
      label: Image folder
      name: imageFolder
      required: false
      type: TEXT
      groupName: images
    - description: Select a local sight as a centered image (preferably *.svg with the <b>image-content aligned at the bottom</b>)
      label: Local sight image-name
      name: localSightImg
      required: false
      type: TEXT
      groupName: images
    - description: Select a global background-image which will be visible on daytime
      label: Global background image (day-cycle)
      name: globalBackgroundDayImg
      required: true
      type: TEXT
      groupName: images
    - description: Select a global background-image which will be visible on nighttime
      label: Global background image (night-cycle)
      name: globalBackgroundNightImg
      required: true
      type: TEXT
      groupName: images
    - description: Disable background images (local sight & background-image)
      label: Disable local-sight image
      name: disableLocalSightBg
      required: false
      type: BOOLEAN
      groupName: images
      advanced: true
    - description: Alternative title for 'x-hour forecast' within the segmented control, where x gets replaced by the number of hours automatically. (<u>default:</u> <b>-hour forecast</b>)
      label: Translation 'x-hour forecast'
      name: wordingForecastHours
      required: false
      type: TEXT
      groupName: wording
    - description: Alternative title for 'x-day forecast' within the segmented control, where x gets replaced by the number of days automatically. (<u>default:</u> <b>-day forecast</b>)
      label: Translation 'x-day forecast'
      name: wordingForecastDays
      required: false
      type: TEXT
      groupName: wording
    - description: Alternative title for 'Now' in the 12-hour forecast tab
      label: Translation 'Now'
      name: wordingNow
      required: false
      type: TEXT
      groupName: wording
    - description: Alternative title for 'Today' in the 3-day-forecast tab
      label: Translation 'Today'
      name: wordingToday
      required: false
      type: TEXT
      groupName: wording
    - description: Alternative text for 'Sunrise at' in the icon-tooltip (only visible if you've activated the day & night indication)
      label: Translation 'Sunrise at'
      name: wordingSunrise
      required: false
      type: TEXT
      groupName: wording
    - description: Alternative text for 'Sunset at' in the icon-tooltip (only visible if you've activated the day & night indication)
      label: Translation 'Sunset at'
      name: wordingSunset
      required: false
      type: TEXT
      groupName: wording
  parameterGroups:
    - name: general
      label: General settings
      description: All settings which are related to the usage of this widget
    - name: images
      label: Image settings
    - name: wording
      label: Language settings
      description: Set alternative wordings
timestamp: Mar 4, 2021, 2:42:29 PM
component: f7-page
config:
  style:
    background: "=(dayjs().format() >= items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'ForecastToday_Sunrise'].state && dayjs().format() < items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'ForecastToday_Sunset'].state) ? 'linear-gradient(to bottom, #355b8e, #c0d4f0)' : 'repeat-x radial-gradient(white, rgba(255,255,255,.2) 2px, transparent 5px) 50px 0px/420px 420px, repeat-x radial-gradient(white, rgba(255,255,255,.2) 2px, transparent 5px) 10px 0px/650px 650px, repeat-x radial-gradient(white, rgba(255,255,255,.2) 2px, transparent 5px) 200px 0px/450px 450px, repeat-x radial-gradient(white, rgba(255,255,255,.2) 2px, transparent 5px) 200px 80px/350px 350px, repeat-x radial-gradient(white, rgba(255,255,255,.2) 2px, transparent 5px) 0px 0px/260px 260px, repeat-x radial-gradient(white, rgba(255,255,255,.15) 1px, transparent 3px) 50px 0px/200px 200px, repeat-x radial-gradient(white, rgba(255,255,255,.1) 2px, transparent 4px) 130px 0px/250px 100px, repeat-x radial-gradient(rgba(255,255,255,.4), rgba(255,255,255,.1) 2px, transparent 1px) 50px 0px/150px 50px, repeat-x radial-gradient(white, rgba(255,255,255,.2) 1px, transparent 2px) 50px 0px/280px 480px, repeat-x radial-gradient(white, rgba(255,255,255,.2) 1px, transparent 2px) 70px 0px/180px 350px, repeat-x radial-gradient(white, rgba(255,255,255,.1) 1px, transparent 1px) 80px 0px/200px 120px, repeat-x radial-gradient(white, rgba(255,255,255,.1) 2px, transparent 2px) 100px 0px/200px 180px, repeat-x radial-gradient(white, rgba(255,255,255,.1) 1px, transparent 5px) 100px 0px/350px 600px, linear-gradient(to bottom,#413D8F 0%,#CE9FC8 100%)'"
    background-repeat: repeat-x
    -ms-user-select: none
    -moz-user-select: none
    -webkit-user-select: none
    user-select: none
    overflow: hidden
    --f7-page-navbar-offset: none
    --f7-page-toolbar-top-offset: none
    --f7-page-subnavbar-offset: none
    --f7-page-searchbar-offset: none
    --f7-page-content-extra-padding-top: none
    --f7-page-toolbar-bottom-offset: none
    --f7-page-content-extra-padding-bottom: none
    --f7-theme-color: none
    --f7-bars-bg-color: none
    --f7-bars-border-color: none
    --f7-navbar-shadow-image: none
    --f7-navbar-text-color: white
    --f7-bars-text-color: white
    --f7-navbar-link-color: white
    --f7-navbar-bg-color-rgb: none
    --f7-bars-bg-color-rgb: none
    --f7-bars-translucent-opacity: none
    --f7-bars-translucent-blur: none
    backdrop-filter: none
    --f7-button-border-radius: 0
    --weather-condition-icon-size: 30px
    --weather-label-text-transform: normal
    --weather-font-size-xsmall: 14px
    --weather-font-size-small: 16px
    --weather-font-size-medium: 18px
    --weather-font-size-hero: 91px
    --weather-font-color-main: white
    --weather-forecast-location-font-color: rgba(255,255,255,.7)
    --weather-forecast-text-shadow-light: 2px 2px rgba(0,0,0,.15)
    --weather-forecast-text-shadow-strong: 2px 2px rgba(0,0,0,.35)
    --weather-forecast-font-color-light: rgba(0,0,0,.35)
    --weather-forecast-font-color: rgba(0,0,0,.7)
slots:
  default:
    - component: Label
      config:
        text: "=!props.locationTitle ? items[(!props.itemPrefix2 ? (!props.itemPrefix ? '' : props.itemPrefix) : props.itemPrefix2) + 'StationName'].state : props.locationTitle"
        class:
          - text-align-right
          - padding-right
        style:
          text-overflow: ellipsis
          overflow: hidden
          line-height: var(--f7-navbar-link-line-height,var(--f7-navbar-height))
          font-size: var(--weather-font-size-xsmall)
          color: var(--weather-forecast-location-font-color)
          text-shadow: var(--weather-forecast-text-shadow-light)
          text-transform: uppercase
    - component: f7-block
      config:
        text-align: center
        class:
          - no-margin
          - no-padding
          - text-align-center
      slots:
        default:
          - component: f7-row
            config:
              class:
                - display-flex
                - justify-content-space-between
            slots:
              default:
                - component: f7-col
                  config:
                    class:
                      - display-flex
                      - align-self-center
                      - align-items-flex-end
                      - flex-direction-column
                  slots:
                    default:
                      - component: Label
                        config:
                          text: "=(!props.itemPrefix) ? Math.round(items.Current_Temperature.state.split(' ')[0]) + '°' : Math.round(items[props.itemPrefix + 'Current_Temperature'].state.split(' ')[0]) + '°'"
                          style:
                            font-size: var(--weather-font-size-hero)
                            font-weight: lighter
                            line-height: var(--weather-font-size-hero)
                            color: var(--weather-font-color-main)
                            text-shadow: var(--weather-forecast-text-shadow-strong)
                            white-space: nowrap
                            overflow: hidden
                            text-overflow: ellipsis
                            z-index: 99
                - component: f7-col
                  config:
                    class:
                      - display-flex
                      - align-self-center
                      - align-items-flex-start
                      - flex-direction-column
                    style:
                      font-size: var(--weather-font-size-medium)
                      font-weight: lighter
                      color: var(--weather-font-color-main)
                      text-shadow: var(--weather-forecast-text-shadow-strong)
                      z-index: 99
                  slots:
                    default:
                      - component: Label
                        config:
                          text: "Min: 21°C"
                      - component: Label
                        config:
                          text: "Max: 30°C"
          - component: Label
            config:
              text: "=(!props.itemPrefix) ? items.Current_Apparenttemperature.state : 'Feels Like: ' + items[props.itemPrefix + 'Current_Apparenttemperature'].state "
              style:
                font-size: var(--weather-font-size-medium)
                text-shadow: var(--weather-forecast-text-shadow-strong)
                color: var(--weather-font-color-main)
                text-overflow: ellipsis
                white-space: nowrap
                overflow: hidden
                z-index: 999
          - component: Label
            config:
              text: "=(!props.itemPrefix) ? items.Current_Condition.state : items[props.itemPrefix + 'Current_Condition'].state"
              style:
                font-size: var(--weather-font-size-medium)
                text-shadow: var(--weather-forecast-text-shadow-strong)
                color: var(--weather-font-color-main)
                text-overflow: ellipsis
                white-space: nowrap
                overflow: hidden
                z-index: 999
          - component: Label
            config:
              text: "=(!props.itemPrefix) ? items.UVIndex.state : 'UV Index: ' + items[props.itemPrefix + 'UVIndex'].state "
              style:
                font-size: var(--weather-font-size-medium)
                text-shadow: var(--weather-forecast-text-shadow-strong)
                color: var(--weather-font-color-main)
                text-overflow: ellipsis
                white-space: nowrap
                overflow: hidden
                z-index: 999
    - component: f7-block
      config:
        class:
          - no-margin
          - no-padding
        style:
          background: "=(items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '01d') ? '' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '01n') ? '' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '02d') ? 'no-repeat top center/750px url(' + ((!props.imageFolder) ? '/static/files/weather_img/' : props.imageFolder) + '02.svg)' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '02n') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '02.svg)' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '03d') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '03.svg)' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '03n') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '03.svg)' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '04d') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '04.svg)' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '04n') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '04.svg)' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '09d') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '09.svg)' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '09n') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '09.svg)' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '10d') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '10.svg)' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '10n') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '10.svg)' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '11d') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '11.svg)' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '11n') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '11.svg)' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '13d') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '13.svg)' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '13n') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '13.svg)' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '50d') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '50.svg)' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Current_Iconid'].state === '50n') ? 'no-repeat top center/750px url(' + ((props.imageFolder === undefined) ? '/static/files/weather_img/' : props.imageFolder) + '50.svg)' : '?'"
          height: 100%
          width: 100%
          position: absolute
          top: 0
          left: 0
          right: 0
    - component: oh-image
      config:
        url: "=(dayjs().format() >= items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'ForecastToday_Sunrise'].state && dayjs().format() < items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'ForecastToday_Sunset'].state ) ? ((!props.imageFolder) ? '/static/files/weather_img/' : props.imageFolder) + 'sun.svg' : ((!props.imageFolder) ? '/static/files/weather_img/' : props.imageFolder) + 'moon.svg'"
        style:
          width: 100%
          max-width: 150px
          min-width: 70px
          position: absolute
          top: 5px
          left: -50px
          z-index: 91
    - component: f7-block
      config:
        style:
          overflow: hidden
          position: absolute
          bottom: 105px
          width: 100%
          height: 100%
          z-index: -1
      slots:
        default:
          - component: oh-image
            config:
              visible: =!props.disableLocalSightBg
              url: "=(dayjs().format() >= items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'ForecastToday_Sunrise'].state && dayjs().format() < items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'ForecastToday_Sunset'].state ) ? ((!props.imageFolder) ? '/static/files/weather_img/' : props.imageFolder) + props.globalBackgroundDayImg : ((!props.imageFolder) ? '/static/files/weather_img/' : props.imageFolder) + props.globalBackgroundNightImg"
              style:
                position: absolute
                bottom: 0
                right: 0
                left: 0
                margin-right: auto
                margin-left: auto
                width: 100%
                min-width: 800px
                max-width: 1200px
    - component: oh-image
      config:
        visible: =!props.disableLocalSightBg
        url: "=((!props.imageFolder) ? '/static/files/weather_img/' : props.imageFolder) + props.localSightImg"
        style:
          position: absolute
          bottom: 138px
          right: 0
          left: 0
          margin-right: auto
          margin-left: auto
          width: 100%
          min-width: 150px
          max-width: 280px
          z-index: 1
    - component: f7-block
      config:
        class:
          - text-align-center
          - align-content-bottom
          - no-margin
        style:
          border-top: 60px solid white
          border-image-source: "='url(' + ((!props.imageFolder) ? '/static/files/weather_img/' : props.imageFolder) + 'bottom_mask-white.svg' + ')'"
          -moz-border-image-source: "='url(' + ((!props.imageFolder) ? '/static/files/weather_img/' : props.imageFolder) + 'bottom_mask-white.svg' + ')'"
          -webkit-border-image-source: "='url(' + ((!props.imageFolder) ? '/static/files/weather_img/' : props.imageFolder) + 'bottom_mask-white.svg' + ')'"
          -o-border-image-source: "='url(' + ((!props.imageFolder) ? '/static/files/weather_img/' : props.imageFolder) + 'bottom_mask-white.svg' + ')'"
          -webkit-appearance: none
          border-image-slice: 100% 0 0 0
          border-image-width: 1 0 0 0
          position: absolute
          bottom: 0
          left: 0
          width: 100%
      slots:
        default:
          - component: f7-block
            config:
              class:
                - no-margin
                - no-padding
              style:
                position: absolute
                left: 0
                bottom: 0
                height: calc(100% + 2px)
                width: 100%
                background: white
                -webkit-box-shadow: 10px 10px 10px 20px white
                -moz-box-shadow: 10px 10px 10px 20px white
                box-shadow: 10px 10px 10px 20px white
          - component: f7-segmented
            config:
              strong: true
              style:
                --f7-segmented-strong-button-active-box-shadow: 0 4px 0px -2px gray
                --f7-segmented-strong-button-font-color: gray
                --f7-segmented-strong-bg-color: white
                z-index: 999
            slots:
              default:
                - component: oh-button
                  config:
                    text: '=(!props.wordingForecastHours && !props.forecastHours) ? "12-hour forecast" : (props.wordingForecastHours && !props.forecastHours) ? 12 + props.wordingForecastHours : (!props.wordingForecastHours && props.forecastHours) ? props.forecastHours + "-hour forecast" : props.forecastHours + props.wordingForecastHours'
                    active: =!vars.tab || vars.tab === 'hourly_forecast'
                    action: variable
                    actionVariable: tab
                    actionVariableValue: hourly_forecast
                    style:
                      color: '=(vars.tab === "daily_forecast") ? "lightgray" : "black"'
                - component: oh-button
                  config:
                    text: '=(!props.wordingForecastDays && !props.forecastDays) ? "3-day forecast" : (props.wordingForecastDays && !props.forecastDays) ? 3 + props.wordingForecastDays : (!props.wordingForecastDays && props.forecastDays) ? props.forecastDays + "-day forecast" : props.forecastDays + props.wordingForecastDays'
                    active: =vars.tab === 'daily_forecast'
                    action: variable
                    actionVariable: tab
                    actionVariableValue: daily_forecast
                    style:
                      color: '=(!vars.tab || vars.tab === "hourly_forecast") ? "lightgray" : "black"'
          - component: f7-swiper
            config:
              visible: =!vars.tab || vars.tab === 'hourly_forecast'
              navigation: true
              class:
                - padding-top
                - padding-bottom
              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: "=(!props.forecastHours) ? 2 : ((props.forecastHours < 2) ? Math.round(Number(props.forecastHours) + 1) : 2)"
                  "320":
                    slidesPerView: "=(!props.forecastHours) ? 3 : ((props.forecastHours < 3) ? Math.round(Number(props.forecastHours) + 1) : 3)"
                  "480":
                    slidesPerView: "=(!props.forecastHours) ? 4 : ((props.forecastHours < 4) ? Math.round(Number(props.forecastHours) + 1) : 4)"
                  "640":
                    slidesPerView: "=(!props.forecastHours) ? 5 : ((props.forecastHours < 5) ? Math.round(Number(props.forecastHours) + 1) : 5)"
              style:
                --swiper-navigation-size: 20px
                --swiper-navigation-color: gray
            slots:
              default:
                - component: oh-repeater
                  config:
                    sourceType: range
                    for: hour
                    rangeStart: 0
                    rangeStop: "=(!props.forecastHours) ? 12 : Number(props.forecastHours)"
                    fragment: true
                  slots:
                    default:
                      - component: f7-swiper-slide
                        config:
                          style:
                            background: "=(props.sunIndicator === true) ? ((dayjs().add(loop.hour,'hour').format() >= items[((!props.itemPrefix) ? '' : 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) ? '' : 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-icon
                              config:
                                visible: "=(dayjs().add(loop.hour,'hour').startOf('hour').format() === dayjs(items[((!props.itemPrefix) ? '' : 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).startOf('hour').format() && props.sunIndicator === true)"
                                f7: sun_max_fill
                                color: black
                                size: 17px
                                tooltip: "=((!props.wordingSunrise) ? 'Sunrise at ' : props.wordingSunrise + ' ') + ((!props.dateFormat) ? dayjs(items[((!props.itemPrefix) ? '' : 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).format('h:mm A') : dayjs(items[((!props.itemPrefix) ? '' : 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).format('H:mm')+' h') + '<br><b>' + dayjs(items[((!props.itemPrefix) ? '' : 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).fromNow() + '</b>'"
                                style:
                                  position: absolute
                                  right: 3px
                                  top: 3px
                                  cursor: pointer
                                  z-index: 9999
                            - component: f7-icon
                              config:
                                visible: "=(dayjs().add(loop.hour,'hour').startOf('hour').format() === dayjs(items['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).startOf('hour').format() && props.sunIndicator === true)"
                                f7: moon_fill
                                color: black
                                size: 17px
                                tooltip: "=((!props.wordingSunset) ? 'Sunset at ' : props.wordingSunset + ' ') + ((!props.dateFormat) ? dayjs(items[((!props.itemPrefix) ? '' : 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).format('h:mm A') : dayjs(items[((!props.itemPrefix) ? '' : 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).format('H:mm') + ' h') + '<br><b>' + dayjs(items[((!props.itemPrefix) ? '' : 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).fromNow() + '</b>'"
                                style:
                                  position: absolute
                                  right: 3px
                                  top: 3px
                                  cursor: pointer
                                  z-index: 9999
                            - component: f7-row
                              config:
                                class:
                                  - justify-content-center
                              slots:
                                default:
                                  - component: Label
                                    config:
                                      text: "=(loop.hour === 0) ? ((!props.wordingNow) ? 'Now' : props.wordingNow) : ((!props.dateFormat) ? dayjs().add(loop.hour,'hour').startOf('hour').format('h A') : dayjs().add(loop.hour,'hour').startOf('hour').format('H')) + (!props.timestampSuffix ? '' : ' ' + props.timestampSuffix)"
                                      style:
                                        font-weight: 400
                                        color: var(--weather-forecast-font-color)
                                        text-transform: var(--weather-label-text-transform)
                            - component: f7-row
                              config:
                                class:
                                  - justify-content-center
                                  - align-items-center
                              slots:
                                default:
                                  - component: f7-icon
                                    config:
                                      f7: "=(items[((!props.itemPrefix) ? '' : props.itemPrefix) + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + ((loop.hour_idx+1 < 10 ? '0'+(loop.hour_idx+1) : loop.hour_idx+1))) + '_Iconid'].state === '01d') ? 'sun_max' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + ((loop.hour_idx+1 < 10 ? '0'+(loop.hour_idx+1) : loop.hour_idx+1))) + '_Iconid'].state === '01n') ? 'moon_stars' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + ((loop.hour_idx+1 < 10 ? '0'+(loop.hour_idx+1) : loop.hour_idx+1))) + '_Iconid'].state === '02d') ? 'cloud_sun' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + ((loop.hour_idx+1 < 10 ? '0'+(loop.hour_idx+1) : loop.hour_idx+1))) + '_Iconid'].state === '02n') ? 'cloud_moon' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + ((loop.hour_idx+1 < 10 ? '0'+(loop.hour_idx+1) : loop.hour_idx+1))) + '_Iconid'].state === '03d') ? 'cloud' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + ((loop.hour_idx+1 < 10 ? '0'+(loop.hour_idx+1) : loop.hour_idx+1))) + '_Iconid'].state === '03n') ? 'cloud' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + ((loop.hour_idx+1 < 10 ? '0'+(loop.hour_idx+1) : loop.hour_idx+1))) + '_Iconid'].state === '04d') ? 'cloud' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + ((loop.hour_idx+1 < 10 ? '0'+(loop.hour_idx+1) : loop.hour_idx+1))) + '_Iconid'].state === '04n') ? 'cloud' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + ((loop.hour_idx+1 < 10 ? '0'+(loop.hour_idx+1) : loop.hour_idx+1))) + '_Iconid'].state === '09d') ? 'cloud_heavyrain' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + ((loop.hour_idx+1 < 10 ? '0'+(loop.hour_idx+1) : loop.hour_idx+1))) + '_Iconid'].state === '09n') ? 'cloud_heavyrain' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + ((loop.hour_idx+1 < 10 ? '0'+(loop.hour_idx+1) : loop.hour_idx+1))) + '_Iconid'].state === '10d') ? 'cloud_sun_rain' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + ((loop.hour_idx+1 < 10 ? '0'+(loop.hour_idx+1) : loop.hour_idx+1))) + '_Iconid'].state === '10n') ? 'cloud_moon_rain' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + ((loop.hour_idx+1 < 10 ? '0'+(loop.hour_idx+1) : loop.hour_idx+1))) + '_Iconid'].state === '11d') ? 'cloud_sun_bolt' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + ((loop.hour_idx+1 < 10 ? '0'+(loop.hour_idx+1) : loop.hour_idx+1))) + '_Iconid'].state === '11n') ? 'cloud_moon_bolt' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + ((loop.hour_idx+1 < 10 ? '0'+(loop.hour_idx+1) : loop.hour_idx+1))) + '_Iconid'].state === '13d') ? 'cloud_snow' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + ((loop.hour_idx+1 < 10 ? '0'+(loop.hour_idx+1) : loop.hour_idx+1))) + '_Iconid'].state === '13n') ? 'cloud_snow' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + ((loop.hour_idx+1 < 10 ? '0'+(loop.hour_idx+1) : loop.hour_idx+1))) + '_Iconid'].state === '50d') ? 'cloud_fog' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + ((loop.hour_idx+1 < 10 ? '0'+(loop.hour_idx+1) : loop.hour_idx+1))) + '_Iconid'].state === '50n') ? 'cloud_fog' : ''"
                                      size: var(--weather-condition-icon-size)
                                      style:
                                        padding-right: 5px
                                        color: var(--weather-forecast-font-color)
                                  - component: Label
                                    config:
                                      text: "=Math.round(items[((!props.itemPrefix) ? '' : props.itemPrefix) + ((loop.hour === 0) ? 'Current' : 'ForecastHours' + ((loop.hour_idx+1 < 10 ? '0'+(loop.hour_idx+1) : loop.hour_idx+1))) + '_Temperature'].state.split(' ')[0]) + '°'"
                                      style:
                                        font-size: var(--weather-font-size-small)
                                        font-weight: 700
                                        color: var(--weather-forecast-font-color)
                            - component: f7-row
                              config:
                                class:
                                  - justify-content-center
                                  - align-items-center
                              slots:
                                default:
                                  - component: f7-icon
                                    config:
                                      f7: umbrella
                                      size: 15
                                      style:
                                        color: var(--weather-forecast-font-color-light)
                                        padding-right: 3px
                                  - component: Label
                                    config:
                                      text: "=Math.round(items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'ForecastHours' + ((loop.hour_idx+1 < 10 ? '0'+(loop.hour_idx+1) : loop.hour_idx+1)) + '_Precipprobability'].state.split(' ')[0]) + '%'"
                                      style:
                                        font-size: var(--weather-font-size-small)
                                        font-weight: 400
                                        color: var(--weather-forecast-font-color-light)
          - component: f7-swiper
            config:
              visible: =vars.tab === 'daily_forecast'
              navigation: true
              class:
                - padding-top
                - padding-bottom
              params:
                initalSlide: 0
                grabCursor: true
                observer: true
                spaceBetween: 5
                observeSlideChildren: true
                updateOnWindowResize: true
                watchOverflow: true
                mousewheel: true
                keyboard: true
                breakpoints:
                  "0":
                    slidesPerView: 1
                  "210":
                    slidesPerView: "=(!props.forecastDays) ? 2 : ((props.forecastDays < 2) ? Math.round(Number(props.forecastDays) + 1) : 2)"
                  "480":
                    slidesPerView: "=(!props.forecastDays) ? 3 : ((props.forecastDays < 3) ? Math.round(Number(props.forecastDays) + 1) : 3)"
                  "640":
                    slidesPerView: "=(!props.forecastDays) ? 4 : ((props.forecastDays < 4) ? Math.round(Number(props.forecastDays) + 1) : 4)"
              style:
                --swiper-navigation-size: 20px
                --swiper-navigation-color: gray
            slots:
              default:
                - component: oh-repeater
                  config:
                    sourceType: range
                    for: day
                    rangeStart: 0
                    rangeStop: "=(!props.forecastDays) ? 3 : Number(props.forecastDays)"
                    fragment: true
                  slots:
                    default:
                      - component: f7-swiper-slide
                        config: {}
                        slots:
                          default:
                            - component: f7-row
                              config:
                                class:
                                  - justify-content-center
                                  - align-items-center
                              slots:
                                default:
                                  - component: Label
                                    config:
                                      text: "=(loop.day === 0) ? ((!props.wordingToday) ? 'Today' : props.wordingToday) : dayjs().add(loop.day,'day').startOf('day').format('dddd')"
                                      style:
                                        color: var(--weather-forecast-font-color)
                                        text-transform: var(--weather-label-text-transform)
                            - component: f7-icon
                              config:
                                f7: "=(items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '01d') ? 'sun_max' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '01n') ? 'moon_stars' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '02d') ? 'cloud_sun' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '02n') ? 'cloud_moon' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '03d') ? 'cloud' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '03n') ? 'cloud' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '04d') ? 'cloud' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '04n') ? 'cloud' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '09d') ? 'cloud_heavyrain' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '09n') ? 'cloud_heavyrain' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '10d') ? 'cloud_sun_rain' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '10n') ? 'cloud_moon_rain' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '11d') ? 'cloud_sun_bolt' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '11n') ? 'cloud_moon_bolt' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '13d') ? 'cloud_snow' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '13n') ? 'cloud_snow' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '50d') ? 'cloud_fog' : (items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Forecast' + (((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + loop.day_idx))) + '_Iconid'].state === '50n') ? 'cloud_fog' : '?'"
                                size: var(--weather-condition-icon-size)
                                style:
                                  color: var(--weather-forecast-font-color)
                            - component: f7-row
                              config:
                                class:
                                  - justify-content-center
                              slots:
                                default:
                                  - component: Label
                                    config:
                                      text: "=Math.round(items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Forecast' + ((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + (loop.day_idx))) + '_Maxtemperature'].state.split(' ')[0])+'°'"
                                      style:
                                        font-size: var(--weather-font-size-small)
                                        font-weight: 700
                                        color: var(--weather-forecast-font-color)
                                  - component: Label
                                    config:
                                      text: ""
                                      style:
                                        color: rgba(0,0,0,.2)
                                  - component: Label
                                    config:
                                      text: "=Math.round(items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Forecast' + ((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + (loop.day_idx))) + '_Mintemperature'].state.split(' ')[0])+'°'"
                                      style:
                                        font-size: var(--weather-font-size-small)
                                        font-weight: 700
                                        color: var(--weather-forecast-font-color-light)

Hi @RGroll

Once again , thanks for all the help. I am however clearly missing the basics with the F7 grids stuff.

Firstly battling to see how that ties in to the OH3 implementation… But also seem to have an issue with the alignments again.

I have been trying to add features to your PopupWidget#2 to get a grasp of the layout etc, and am now stuck with the following:

I have added the Sunrise and Sunset icons and times. This is done using columns (4 ), but then I saw your one suggestion that this may work better as just a row with the icon and text in a line?

So tried to implement that above the values shown - all I get however is a space created and nothing displays (so I think I must have messed up the alignment, but just can’t fix it.

Widget.txt (50.2 KB)

What I have "added is the following:

          - component: f7-block
            config:
              class:
                - padding
              slots:
                default:
                  - component: f7-row
                    config:
                      style:
                        flex-wrap: nowrap
                        z-index: 999
                    slots:
                      default:
                        - component: f7-icon
                          config:
                            f7: sunrise
                            size: 30
                            color: white
                            class:
                              - padding-right
                  - component: Label
                    config:
                      text: "Test Text"
                      style:
                        color: var(--weather-font-color-main)
                        font-size: 18px
                        line-height: 30px
                        text-align: left
                        white-space: nowrap
                        overflow: hidden
                        text-overflow: ellipsis

My end goal is to have two columns in two rows with Today and Tomorrow with eh Sunrise and Sunset for each day.

Can you see what I have done wrong?

Thanks
Mark

Hi,

these are very nice widgets great work… I am using the weathercard widget. It works fine except the Icon dont show off did someone else have problems with the Icons?

1 Like

Hey @Faruk

thank you!

Which icons do you mean? All of them? Did you linked the additional iconId channels which will show up when you check the “Show advanced” box on the top right of your channel overview, like mentioned here for example?

1 Like

thx i just overread it that someone else had the same problem. Now it is shown all of the items.

1 Like

@RGroll for the weather icon, I use this:

f7: =items[props.weather_prefix + 'Current_Iconid'].displayState

Using the MAP for the format string:

String Weather_Current_Iconid "[MAP(weathericon-f7.map):%s]" {channel="openweathermap:onecall:bridge:local:current#icon-id"}

weathericon-f7.map:

01d=sun_max_fill
01n=moon_stars_fill
02d=cloud_sun_fill
02n=cloud_moon_fill
03d=cloud_fill
03n=cloud_fill
04d=cloud_fill
04n=cloud_fill
09d=cloud_heavyrain_fill
09n=cloud_heavyrain_fill
10d=cloud_sun_rain_fill
10n=cloud_moon_rain_fill
11d=cloud_sun_bolt_fill
11n=cloud_moon_bolt_fill
13d=cloud_snow_fill
13n=cloud_snow_fill
50d=cloud_fog_fill
50n=cloud_fog_fill

This would work, yes.

It requires to manipulate the items metadata apart from the default settings to the system during the creation of the items via the UI and adding extra informations with the transformation map , which I left out on purpose to make this widget as beginner-friendly as its curently possible.

Hi @RGroll

Thanks for all your help so far.

I notice I am getting the following errors is my openhab.log file using the stock Weather popup #2 (extended) widget.

2021-03-31 08:33:34.472 [WARN ] [e.internal.SseItemStatesEventBuilder] - Attempting to send a state update of an item which doesn't exist: undefined
2021-03-31 08:34:11.314 [WARN ] [e.internal.SseItemStatesEventBuilder] - Attempting to send a state update of an item which doesn't exist: undefined
2021-03-31 08:34:23.965 [WARN ] [e.internal.SseItemStatesEventBuilder] - Attempting to send a state update of an item which doesn't exist: undefined
2021-03-31 08:34:52.613 [WARN ] [e.internal.SseItemStatesEventBuilder] - Attempting to send a state update of an item which doesn't exist: undefined
2021-03-31 08:35:24.470 [WARN ] [e.internal.SseItemStatesEventBuilder] - Attempting to send a state update of an item which doesn't exist: undefined
2021-03-31 08:35:24.674 [WARN ] [e.internal.SseItemStatesEventBuilder] - Attempting to send a state update of an item which doesn't exist: undefined
2021-03-31 08:35:24.674 [WARN ] [e.internal.SseItemStatesEventBuilder] - Attempting to send a state update of an item which doesn't exist: ForecastToday_Sunset
2021-03-31 08:35:24.690 [WARN ] [e.internal.SseItemStatesEventBuilder] - Attempting to send a state update of an item which doesn't exist: ForecastTomorrow_Sunset
2021-03-31 08:35:24.690 [WARN ] [e.internal.SseItemStatesEventBuilder] - Attempting to send a state update of an item which doesn't exist: WeatherAtHome_ForecastHours26_Iconid
2021-03-31 08:35:24.690 [WARN ] [e.internal.SseItemStatesEventBuilder] - Attempting to send a state update of an item which doesn't exist: WeatherAtHome_ForecastHours26_Temperature
2021-03-31 08:35:24.690 [WARN ] [e.internal.SseItemStatesEventBuilder] - Attempting to send a state update of an item which doesn't exist: WeatherAtHome_ForecastHours26_Precipprobability

Errors occur every time I access the Widget.

The items exist (other than the Hour26 - I have the Widget configured for 25 hours.

It appears that the Sunset feature is working well, see screen shot.


Any suggestions that I can look at?

I have seen that the “Attempting to send a state update of an item which doesn’t exist: undefined” messages can be a result of some widgets?

Many Thanks
Mark

awesome widget :slight_smile:

I just implemented it and have 2 questions.

For me the lower right values on the card are not formatted correctly like on you screenshots.
image
Why could I not see the pipe separator?

For the Pop Ups… I tried to edit the item prefix directly in the widget code but this wont work.
I just didn’t get it where to acutally they should be edited as the props are not editable like when adding the card.

best

Hey @shorty707

thanks!

This is a known (and strange) artifact on the first save of a widget and the unicode symbols I used as an replacement for the space before and after the pipe.

I’ve updated the repo with a fix for this (I hope). So you could either use the new code or do it easily for yourself if you replace the value of the text parameter in line 363 and 677 with '=" | "'


There are lots of dependencies inside the expressions which could easily be messed up. Its definetely recommended to use the widget configuration.


I’m not 100% sure if I understand you correct here, but I think you would like to open the weather popup widget when you click on the weather card widget?

If yes, you have to click on the Code tab while you’re editing the page and add the widget configuration parameters to the page manually (as theres a bug with the action settings for custom widgets):

                    - component: widget:weatherCard
                      config:
                        itemPrefix: OneCallAPIweatherandforecast_
                        locationTitle: Some city
                        widget_action: popup
                        widget_actionModal: widget:weatherPopup
                        widget_actionModalConfig:
                          itemPrefix: OneCallAPIweatherandforecast_
                          forecastHours: "12"
                          forecastDays: "3"
                          sunIndicator: true
                          locationTitle: YourCity

You could also use any of the standard elements, like a Label card

…Select Configure Widget → Inside the seen selection you’ve to choose Open Popup as Action, the desired weather popup as Modal Page or Widget and then click on Modal component configuration to set the widgets parameter.

image

Hope it helps

thanks
that explained it.
I played more with the widgets and 2 more things came to my mind.

I added the things and items per files.
Discovery then finds 2 more things automatically.
image
should I also add them via the things file?

  1. If I use the same UI on multiple devices I see that for the smallest screens (smartphone) the responsive design comes to its limits :slight_smile:
    Is it possible to make it even “more responsive” that it fits for a mobile screen (portrait mode)?
    I saw the “advanced option”: Mobile optimized … but this is not optimal as I want to use the same UI for large and small screens … and it actually also looks a little distorted.
    My “small screen” is btw. not sooo small with 6,67″ (2400 x 1080, 20:9 ratio)
    image

best

How did you implemented the Rain Radar?

1 Like

Hey @RGroll ,

trying to get these very beautilful widgets to work.

I’ve got the free OneCall API key with which I think that I should be able to have forecast data for the next 4 days.
Forecast for “hours” and “Days 1,2,3” are working fine, just the last day always shows NaN / NaN.

Thing “One Call API weather and forecast” is set with 4d/13h - same is done in the weather card as well as the weather popup widget.

I added the 172(!) items several times from UI as well as via “Add Items from Textual Definition” (source) - always the same result.

What is wrong?

Hi first thanks for the widget, i used the card widget and i found it cool.

Only issue i had so far is that the widget stop partially stop refreshing after sometimes : hourly forecast and all other forecast are not refreshing if i do not change the tab.
Anyone having the issue or an idea how this can be solved.

Great work with this widget!

If you want to display windirection by use of an arrow, I use this component:

                              - component: f7-icon
                                config:
                                  f7: location_north_fill
                                  size: 24
                                  style:
                                    transform: "=(('Rotate(') + (Math.round(Math.round(items[((!props.itemPrefix) ? '' : props.itemPrefix) + 'Forecast' + ((loop.day === 0) ? 'Today' : ((loop.day === 1) ? 'Tomorrow' : 'Day' + (loop.day_idx))) + '_Winddirection'].state.split(' ')[0])) - 180) )+ ('deg)')"
                                    color: var(--weather-card-text-color)
                                    text-shadow: var(--weather-text-shadow-strong)
                                    padding-top: 5px
                                    padding-bottom: 5px
1 Like

Dear @RGroll, how can i add background temperature trendline to this widget? I mean where can I insert the code:

     - component: oh-trend
      config:
        trendItem: Forecast_Current_Apparenttemperature
        trendGradient:
         - "#aa2b1d"
         - "#cc561e"
         - "#ef8d32"
         - "#beca5c"
      style:
        --f7-theme-color-bg-color: transparent
        background: var(--f7-theme-color-bg-color)
        filter: opacity(90%)
        position: absolute
        width: 100%
        height: 100%
        top: 0px
        left: 0px
        z-index: 0                       

Is there any editor which can help me with widgets design?

Great idea!

Here’s another iteration on your arrow rotation code I which I also distinguish between NULL state (meaning variable wind direction), UNDEF state (item not found or other error), plus an extra label item which renders the 32-point windrose wind direction as name:

- component: f7-icon
  config:
    f7: >-
      =
      (! Number.isFinite(Number.parseFloat(items[
        (props.itemPrefix ? props.itemPrefix : '') + 'Current_WindDirection'
      ].state))) ? 'question_circle' : 'location_north_fill'
    size: 24
    style:
      transform: >-
        =(! Number.isFinite(Number.parseFloat(items[
          (props.itemPrefix ? props.itemPrefix : '') + 'Current_WindDirection'
        ].state))) ? 'Rotate(0 deg)' : (
          'Rotate(' +
          Math.round(
            Number.parseFloat(items[
              (props.itemPrefix ? props.itemPrefix : '') + 'Current_WindDirection'
        ].state) - 180.0)
        + 'deg)' )
      color: var(--weather-card-text-color)
      text-shadow: var(--weather-text-shadow-strong)
      padding-top: 5px
      padding-bottom: 5px

Windrose name label:

- component: Label
  config:
    text: >-
      =items[
        (props.itemPrefix ? props.itemPrefix : '') + 'Current_WindDirection'
      ].state == 'NULL' ? 'Var.' :
      (Number.isFinite(Number.parseFloat(items[
        (props.itemPrefix ? props.itemPrefix : '') + 'Current_WindDirection'
      ].state))) ? 
      ([
        "N", "NbE", "NNE", "NEbN", "NE", "NEbE", "ENE", "EbN",
        "E", "EbS", "ESE", "SEbE", "SE", "SEbS", "SSE", "SbE",
        "S", "SbW", "SSW", "SWbS", "SW", "SWbW", "WSW", "WbS",
        "W", "WbN", "WNW", "NWbW", "NW", "NWbN", "NNW", "NbW",
      ])[ Math.floor( (1 + Number.parseFloat(items[
        (props.itemPrefix ? props.itemPrefix : '') + 'Current_WindDirection'
      ].state) / 360.0 * 2 * 32) / 2) % 32 ]
      : 'not defined'
    class:
      - no-padding-top
    style:
      font-size: var(--weather-normal-font-size)
      text-shadow: .5px .5px var(--weather-text-shadow-color)
      color: var(--weather-font-color)
      white-space: nowrap
      overflow: hidden
      text-overflow: ellipsis

hello, I followed all the steps of the guide but the widget looks like this, why? where am I


wrong?