Solar Forecast & Production Chart

A minialistic widget displaying forecasted and actual solar production for the current week.
Forecasted and actual values are displayed using a bullet-style bar chart.

The data is retrieved from persistence, with both Item and persistence service configurable per series.
Additionally, series colors and labels can be customised.

Changelog

The git history serves as a changelog: History for UI/widgets/florianh-widgetset/solarForecast.yaml - florian-h05/openhab-conf · GitHub

Resources

https://raw.githubusercontent.com/florian-h05/openhab-conf/refs/heads/main/UI/widgets/florianh-widgetset/solarForecast.yaml

Really like this and have a version running now on my set up, however for me it would be more useful if it could show a rolling 7 days and not always start from Monday as this would display more useful historic data. I cannot see how this could be adjusted for that though, is it possible?

Have changed it to

chartType: dynamic

and

period: 6D

but cannot see how to not always start on a Monday, but the ‘last’ bar being the current day.

Thanks

That doesn’t work (yet). oh-category-axis only supports hour, day, week, month & year, and week always starts on Monday or Sunday.

@florian-h05 Thank you for this cool and useful widget.

I have a minor issue with the forecast values. Not sure if it is related to the widget or the aggregated data. The forecast value for Sunday is not shown. IIRC the aggregation function last (Latest) is used.

I did some small changes in the code to satisfy my needs. If you need to look into my widget code feel free to ask.

last is used for the actual value, for the forecast, max is used. Did you try out other aggregation functions?

Always curious to see what other people change in my widgets :wink:

I will test a different aggregation function other than last on next Sunday.

To clarify: The forcast service delivers values for up to two days (today and tomorrow). On Monday I can see todays (Mondays) forecast value and tomorrows (Tuesdays) forecast value. Until Saturday the widget shows data like described. On Sunday I do not see the todays (Sundays) value, the column remains empty.

Here is my code.

editable: true
uid: solarForecast
tags:
  - chart
props:
  parameters:
    - context: item
      description: Item for forecasted energy (stored in persistence)
      label: Item
      name: forecastItem
      required: true
      type: TEXT
      groupName: forecast
    - context: persistenceService
      description: Persistence service for forecasted energy Item
      label: Persistence Service
      name: forecastService
      required: false
      type: TEXT
      groupName: forecast
    - default: last
      description: Aggregation function for forecasted energy Item
      label: Aggregation Funktion
      name: forecastAggregationFunction
      required: false
      type: TEXT
      groupName: forecast
      options:
        - label: Average
          value: average
        - label: Sum
          value: sum
        - label: Minimum
          value: min
        - label: Maximum
          value: max
        - label: First (earliest)
          value: first
        - label: Last (latest)
          value: last
        - label: Difference of firsts
          value: diff_first
        - label: Difference of lasts
          value: diff_last
    - context: item
      description: Item for actual energy produced (stored in persistence)
      label: Item
      name: actualItem
      required: true
      type: TEXT
      groupName: actual
    - context: persistenceService
      description: Persistence service for actual energy Item
      label: Persistence Service
      name: actualService
      required: false
      type: TEXT
      groupName: actual
    - default: last
      description: Aggregation function for actual energy Item
      label: Aggregation Funktion
      name: actualAggregationFunction
      required: false
      type: TEXT
      groupName: actual
      options:
        - label: Average
          value: average
        - label: Sum
          value: sum
        - label: Minimum
          value: min
        - label: Maximum
          value: max
        - label: First (earliest)
          value: first
        - label: Last (latest)
          value: last
        - label: Difference of firsts
          value: diff_first
        - label: Difference of lasts
          value: diff_last
    - default: kWh
      description: Y-Axis Unit
      name: yAxisName
      required: false
      type: TEXT
    - default: 250px
      description: Height of the widget (any CSS height value supported, but
        <code>px</code> is recommended)
      label: Height
      name: height
      required: false
      type: TEXT
      groupName: appearance
    - default: Forecast
      description: Chart label (will be displayed in the legend and on tooltip hover)
        for forecasted production
      label: Forecast Label
      name: forecastLabel
      required: false
      type: TEXT
      groupName: appearance
    - default: Actual
      description: Chart label (will be displayed in the legend and on tooltip hover)
        for actual produced energy
      label: Actual Label
      name: actualLabel
      required: false
      type: TEXT
      groupName: appearance
    - context: color
      default: "#ff9800"
      description: Color for produced energy bar
      name: colorProduced
      required: false
      type: TEXT
      groupName: appearance
    - context: color
      default: "#999999"
      description: Color for forecasted energy bar (light mode)
      name: colorForecastLight
      required: false
      type: TEXT
      groupName: appearance
    - context: color
      default: "#e0e0e0"
      description: Color for forecasted energy bar (dark mode)
      name: colorForecastDark
      required: false
      type: TEXT
      groupName: appearance
  parameterGroups:
    - name: forecast
      label: Forecasted Production
    - name: actual
      label: Actual Production
    - name: appearance
      label: Appearance
timestamp: May 18, 2026, 8:28:18 PM
component: oh-context
config:
  constants:
    aggregateDimension1: isoWeekday
    backgroundColor: "=themeOptions.dark === 'dark' ? '#1c1c1d' : '#fff'"
  functions:
    forecastFormatter: "=(params) => Number(params.value[1]) ?
      Number(params.value[1]).toFixed(3).toString(). replace('.',',') : ''"
    producedFormatter: =(params) => Number(params.value[1]).toFixed(3).toString().replace('.',',')
    tooltipFormatter: =(value, index) =>
      Number(value).toFixed(3).toString().replace('.', ',') + ' ' +
      props.yAxisName
slots:
  default:
    - component: f7-card
      config:
        style:
          border-radius: var(--f7-card-expandable-border-radius)
          box-shadow: 5px 5px 10px 1px rgba(0,0,0,0.1)
          margin-left: 5px
          margin-right: 5px
      slots:
        content:
          - component: oh-chart
            config:
              chartType: isoWeek
              height: =props.height
              options:
                backgroundColor: =const.backgroundColor
              periodVisible: false
            slots:
              grid:
                - component: oh-chart-grid
                  config:
                    bottom: 30
                    containLabel: true
                    left: 5
                    right: 5
                    top: 10
              legend:
                - component: oh-chart-legend
                  config:
                    bottom: 0
                    show: true
              series:
                - component: oh-aggregate-series
                  config:
                    aggregationFunction: =props.forecastAggregationFunction
                    barWidth: 50%
                    dimension1: =const.aggregateDimension1
                    item: =props.forecastItem
                    itemStyle:
                      color: "=themeOptions.dark === 'dark' ? props.colorForecastDark :
                        props.colorForecastLight"
                    label:
                      color: "=themeOptions.dark === 'dark' ? props.colorForecastDark :
                        props.colorForecastLight"
                      formatter: =fn.forecastFormatter
                      position: top
                      show: true
                    name: =props.forecastLabel + ' (in ' + props.yAxisName + ')'
                    service: =props.forecastService
                    type: bar
                    noItemState: true
                - component: oh-aggregate-series
                  config:
                    aggregationFunction: =props.actualAggregationFunction
                    barGap: -60%
                    barWidth: 50%
                    dimension1: =const.aggregateDimension1
                    item: =props.actualItem
                    itemStyle:
                      color: =props.colorProduced
                    label:
                      color: =props.colorProduced
                      formatter: =fn.producedFormatter
                      position: top
                      show: true
                    name: =props.actualLabel + ' (in ' + props.yAxisName + ')'
                    service: =props.actualService
                    type: bar
                    noItemState: true
              tooltip:
                - component: oh-chart-tooltip
                  config:
                    show: true
                    trigger: axis
                    valueFormatter: =fn.tooltipFormatter
              xAxis:
                - component: oh-category-axis
                  config:
                    axisLine:
                      show: false
                    axisTick:
                      show: false
                    categoryType: week
                    weekdayFormat: short
              yAxis:
                - component: oh-value-axis
                  config:
                    axisLabel:
                      show: false
                    splitLine:
                      show: false

I tried to use a different aggregation (max) function today. This is working.

last does not work with forecast values.

The widget used max for forecasted and last for actual values, see my message above.
I do not really understand what you’ve changed then.

No problem. I will explain it.

I changed your original widget code because I like to use different aggregation functions other than yours for my charts. I am using last for aggregation of forecast energy values and diff_last for energy production.

At the moment I have the slight feeling that there is an issue with the aggregation of forecast values when using the aggregation function last. Not only in the widget but in charts too. On Sundays the aggregated value of Sunday is not shown in a chart with dimension isoWeekday.

// edit: When using the aggregation function max in my setup the value for Sunday is shown.

Do you know have an idea what I am facing? If not please ask again.

What openHAB version do you use? 5.2 M4 contains a number of fixes for chart aggregation functions.
Charts and charting in widgets is the same thing, there is no difference besides where it is displayed in.

I am using OH 5.2.0.M4.