Echart problem with oh-aggregate-series

There is some very odd behaviour when using echart with oh-aggregate-series.

“years”:

  • start is 2026 - datepicker shows Jan 1st 2026, numbers look alright
  • arrow left: 2025 - datepicker shows Jan 1st 2025, numbers look alright
  • arrow left: 2024 - datepicker shows Jan 2nd 2025,no numbers in Jan, wrong numbers in Dec → pick other date e.g. Jan 1st or Jan 3rd → bars in Jan appear and Dec is updated
  • arrow left: 2023 - datepicker shows Jan 1st 2023, numbers look alright
  • arrow right: 2024 - datepicker shows Jan 1st 2024, numbers look alright
  • arrow right: still shows 2024 - datepicker shows Dec 31 2024, numbers are mostly 2025 (Jan and Dec not correct) → pick date in 2025 e.g. Jan 1st 2025 → year now shows 2025 and Jan/Dec are updated correctly
  • arrow right: 2026 - datepicker shows Jan 1st 2026, numbers look alright

chart_year_1

“months”:

  • start is March 2026 - datepicker shows March 1st 2026, numbers look alright
  • arrow left: shows Jan 2026 instead of Feb 2026 - datepicker shows Jan 29th 2026 with no data that day, however timeline stretches until “31st”, even though Feb just has 28 days
    → pick date in Feb e.g. Feb 1st 2026 → month now shows Feb 2026 with 28 days - numbers look alright.
  • arrow left: Jan 2026 - datepicker shows Jan 1st 2026, numbers look alright
  • arrow right: shows still Jan 2026 instead of Feb 2026 - data shown for 28 days with 29-31 empty - datepicker shows Jan 31th 2026
    → pick date in Feb e.g. Feb 1st 2026 → month now shows Feb 2026 with 28 days - numbers look alright.
  • arrow right: March 2026 - no data March 1-3 - datepicker shows March 3rd
    → click datepicker → data for March 1-3 appear

chart_month_1

“weeks”:

I show the current week (ISOweek is Mon-Sun). Today is Sat Mar 28th → no data should be shown on Sunday, however the chart shows 27/6kWh.
Monday that week was 23rd March, however datepicker shows March 22nd, which was Sunday last week. In “month March 2026 it becomes obvious that 27/6kWh is from Sunday 22nd March.

chart_week_1

Yaml used - the widget code is quite long - made for 4 oh-aggregate-series:

uid: Chart_1_Fullscreen
tags: []
props:
  parameters:
    - description: Unique identifier for the Popup when more than one ChartPopupButton
        is used in a widget
      label: Popup ID
      name: popupId
      required: false
      type: TEXT
    - description: Chart title
      label: Title
      name: Title
      required: false
      type: TEXT
    - context: item
      description: Item for Aggregate Series 1
      label: Aggregate Series 1
      name: itemSeries1
      required: true
      type: TEXT
    - description: Label of Series 1
      label: Label Series 1
      name: labelSeries1
      required: false
      type: TEXT
    - description: Color of Series 1
      label: Color Series 1
      name: colorSeries1
      required: false
      type: TEXT
    - description: Persistence service for Series 1
      label: Persistence Service 1
      name: persistenceService1
      required: false
      type: TEXT
      options:
        - value: rrd4j
        - value: influxdb
    - context: item
      description: Item for Aggregate Series 2
      label: Aggregate Series 2
      name: itemSeries2
      required: true
      type: TEXT
    - description: Label of Series 2
      label: Label Series 2
      name: labelSeries2
      required: false
      type: TEXT
    - description: Color of Series 2
      label: Color Series 2
      name: colorSeries2
      required: false
      type: TEXT
    - description: Persistence service for Series 2
      label: Persistence Service 2
      name: persistenceService2
      required: false
      type: TEXT
      options:
        - value: rrd4j
        - value: influxdb
    - context: item
      description: Item for Aggregate Series 3
      label: Aggregate Series 3
      name: itemSeries3
      required: true
      type: TEXT
    - description: Label of Series 3
      label: Label Series 3
      name: labelSeries3
      required: false
      type: TEXT
    - description: Color of Series 3
      label: Color Series 3
      name: colorSeries3
      required: false
      type: TEXT
    - description: Persistence service for Series 3
      label: Persistence Service 3
      name: persistenceService3
      required: false
      type: TEXT
      options:
        - value: rrd4j
        - value: influxdb
    - context: item
      description: Item for Aggregate Series 4
      label: Aggregate Series 4
      name: itemSeries4
      required: true
      type: TEXT
    - description: Label of Series 4
      label: Label Series 4
      name: labelSeries4
      required: false
      type: TEXT
    - description: Color of Series 4
      label: Color Series 4
      name: colorSeries4
      required: false
      type: TEXT
    - description: Persistence service for Series 4
      label: Persistence Service 4
      name: persistenceService4
      required: false
      type: TEXT
      options:
        - value: rrd4j
        - value: influxdb
    - label: "Select Default Chart Option: YEAR/MONTH/WEEK/DAY"
      name: defaultChartOption
      required: false
      type: TEXT
      options:
        - label: Tag
          value: day
        - label: Woche
          value: week
        - label: Monat
          value: month
        - label: Jahr
          value: year
  parameterGroups: []
timestamp: Mar 25, 2026, 11:52:50 PM
component: f7-page
config:
  style:
    --f7-navbar-height: 44px
    background: var(--f7-card-bg-color)
    height: 100vh
slots:
  default:
    - component: f7-navbar
      config:
        style:
          --f7-navbar-bg-color: var(--f7-page-bg-color)
          --f7-navbar-border-color: var(--f7-card-outline-border-color)
          --f7-navbar-font-size: 16px
          --f7-navbar-link-color: var(--f7-theme-color)
          --f7-navbar-text-color: var(--f7-theme-color)
      slots:
        left:
          - component: oh-button
            config:
              iconF7: chevron_left
              popupClose: ='.popupChart_' + props.popupId
              style:
                background: transparent
                border: none
                box-shadow: none
                color: var(--f7-theme-color)
                margin-left: 0px
                padding-left: 0px
        title:
          - component: Label
            config:
              style:
                color: "=themeOptions.dark === 'light' ? 'black' : 'white'"
                font-size: 20px
              text: =props.Title
    - component: oh-chart
      config:
        chartType: year
        height: calc(100vh - var(--f7-navbar-height) - 48px - env(safe-area-inset-top) -
          env(safe-area-inset-bottom))
        visible: =(!!props.itemSeries1 && !props.itemSeries2) && ((vars.chartoptions ||
          props.defaultChartOption) === 'year')
      slots:
        grid:
          - component: oh-chart-grid
            config:
              right: 15%
        legend:
          - component: oh-chart-legend
            config:
              bottom: 15
              orient: horizontal
              show: true
        series:
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries1
              dimension1: month
              item: =props.itemSeries1
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(0).toLocaleString('de-DE')
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries1].unit
                  show: true
                symbol: none
              name: =props.labelSeries1
              service: =props.persistenceService1
              type: bar
        xAxis:
          - component: oh-category-axis
            config:
              categoryType: year
              monthFormat: short
              weekdayFormat: default
              name: " "
        yAxis:
          - component: oh-value-axis
            config:
              axisLabel:
                formatter: =v => Number(v).toLocaleString('de-DE')
              name: =items[props.itemSeries1].unit
    - component: oh-chart
      config:
        chartType: month
        height: calc(100vh - var(--f7-navbar-height) - 48px - env(safe-area-inset-top) -
          env(safe-area-inset-bottom))
        visible: =(!!props.itemSeries1 && !props.itemSeries2) && ((vars.chartoptions ||
          props.defaultChartOption) === 'month')
      slots:
        grid:
          - component: oh-chart-grid
            config:
              right: 15%
        legend:
          - component: oh-chart-legend
            config:
              bottom: 15
              orient: horizontal
              show: true
        series:
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries1
              dimension1: date
              item: =props.itemSeries1
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(0).toLocaleString('de-DE')
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries1].unit
                  show: true
                symbol: none
              name: =props.labelSeries1
              service: =props.persistenceService1
              type: bar
        xAxis:
          - component: oh-category-axis
            config:
              categoryType: month
              monthFormat: short
              weekdayFormat: default
              name: " "
        yAxis:
          - component: oh-value-axis
            config:
              axisLabel:
                formatter: =v => Number(v).toLocaleString('de-DE')
              name: =items[props.itemSeries1].unit
    - component: oh-chart
      config:
        chartType: week
        height: calc(100vh - var(--f7-navbar-height) - 48px - env(safe-area-inset-top) -
          env(safe-area-inset-bottom))
        visible: =(!!props.itemSeries1 && !props.itemSeries2) && ((vars.chartoptions ||
          props.defaultChartOption) === 'week')
      slots:
        grid:
          - component: oh-chart-grid
            config:
              right: 15%
        legend:
          - component: oh-chart-legend
            config:
              bottom: 15
              orient: horizontal
              show: true
        series:
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries1
              dimension1: isoWeekday
              item: =props.itemSeries1
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(0).toLocaleString('de-DE')
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries1].unit
                  show: true
                symbol: none
              name: =props.labelSeries1
              service: =props.persistenceService1
              type: bar
        xAxis:
          - component: oh-category-axis
            config:
              categoryType: week
              monthFormat: short
              weekdayFormat: short
              name: " "
        yAxis:
          - component: oh-value-axis
            config:
              axisLabel:
                formatter: =v => Number(v).toLocaleString('de-DE')
              name: =items[props.itemSeries1].unit
    - component: oh-chart
      config:
        chartType: day
        height: calc(100vh - var(--f7-navbar-height) - 48px - env(safe-area-inset-top) -
          env(safe-area-inset-bottom))
        visible: =(!!props.itemSeries1 && !props.itemSeries2) && ((vars.chartoptions ||
          props.defaultChartOption) === 'day')
      slots:
        grid:
          - component: oh-chart-grid
            config:
              right: 15%
        legend:
          - component: oh-chart-legend
            config:
              bottom: 15
              orient: horizontal
              show: true
        series:
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries1
              dimension1: hour
              item: =props.itemSeries1
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(1).toLocaleString('de-DE')
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries1].unit
                  show: true
                symbol: none
              name: =props.labelSeries1
              service: =props.persistenceService1
              type: bar
        xAxis:
          - component: oh-category-axis
            config:
              categoryType: day
              monthFormat: short
              weekdayFormat: short
              name: " "
        yAxis:
          - component: oh-value-axis
            config:
              axisLabel:
                formatter: =v => Number(v).toLocaleString('de-DE')
              name: =items[props.itemSeries1].unit
    - component: oh-chart
      config:
        chartType: year
        height: calc(100vh - var(--f7-navbar-height) - 48px - env(safe-area-inset-top) -
          env(safe-area-inset-bottom))
        visible: =(!!props.itemSeries2 && !props.itemSeries3) && ((vars.chartoptions ||
          props.defaultChartOption) === 'year')
      slots:
        grid:
          - component: oh-chart-grid
            config:
              right: 15%
        legend:
          - component: oh-chart-legend
            config:
              bottom: 15
              orient: horizontal
              show: true
        series:
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries1
              dimension1: month
              item: =props.itemSeries1
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(0).toLocaleString('de-DE')
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries1].unit
                  show: true
                symbol: none
              name: =props.labelSeries1
              service: =props.persistenceService1
              type: bar
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries2
              dimension1: month
              item: =props.itemSeries2
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(0)
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries2].unit
                  show: true
                symbol: none
              name: =props.labelSeries2
              service: =props.persistenceService2
              type: bar
        xAxis:
          - component: oh-category-axis
            config:
              categoryType: year
              monthFormat: short
              weekdayFormat: short
              name: " "
        yAxis:
          - component: oh-value-axis
            config:
              axisLabel:
                formatter: =v => Number(v).toLocaleString('de-DE')
              name: =items[props.itemSeries1].unit
    - component: oh-chart
      config:
        chartType: month
        height: calc(100vh - var(--f7-navbar-height) - 48px - env(safe-area-inset-top) -
          env(safe-area-inset-bottom))
        visible: =(!!props.itemSeries2 && !props.itemSeries3) && ((vars.chartoptions ||
          props.defaultChartOption) === 'month')
      slots:
        grid:
          - component: oh-chart-grid
            config:
              right: 15%
        legend:
          - component: oh-chart-legend
            config:
              bottom: 15
              orient: horizontal
              show: true
        series:
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries1
              dimension1: date
              item: =props.itemSeries1
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(0).toLocaleString('de-DE')
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries1].unit
                  show: true
                symbol: none
              name: =props.labelSeries1
              service: =props.persistenceService1
              type: bar
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries2
              dimension1: date
              item: =props.itemSeries2
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(0)
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries2].unit
                  show: true
                symbol: none
              name: =props.labelSeries2
              service: =props.persistenceService2
              type: bar
        xAxis:
          - component: oh-category-axis
            config:
              categoryType: month
              monthFormat: short
              weekdayFormat: default
              name: " "
        yAxis:
          - component: oh-value-axis
            config:
              axisLabel:
                formatter: =v => Number(v).toLocaleString('de-DE')
              name: =items[props.itemSeries1].unit
    - component: oh-chart
      config:
        chartType: week
        height: calc(100vh - var(--f7-navbar-height) - 48px - env(safe-area-inset-top) -
          env(safe-area-inset-bottom))
        visible: =(!!props.itemSeries2 && !props.itemSeries3) && ((vars.chartoptions ||
          props.defaultChartOption) === 'week')
      slots:
        grid:
          - component: oh-chart-grid
            config:
              right: 15%
        legend:
          - component: oh-chart-legend
            config:
              bottom: 15
              orient: horizontal
              show: true
        series:
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries1
              dimension1: isoWeekday
              item: =props.itemSeries1
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(0).toLocaleString('de-DE')
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries1].unit
                  show: true
                symbol: none
              name: =props.labelSeries1
              service: =props.persistenceService1
              type: bar
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries2
              dimension1: isoWeekday
              item: =props.itemSeries2
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(0)
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries2].unit
                  show: true
                symbol: none
              name: =props.labelSeries2
              service: =props.persistenceService2
              type: bar
        xAxis:
          - component: oh-category-axis
            config:
              categoryType: week
              monthFormat: short
              weekdayFormat: short
              name: " "
        yAxis:
          - component: oh-value-axis
            config:
              axisLabel:
                formatter: =v => Number(v).toLocaleString('de-DE')
              name: =items[props.itemSeries1].unit
    - component: oh-chart
      config:
        chartType: day
        height: calc(100vh - var(--f7-navbar-height) - 48px - env(safe-area-inset-top) -
          env(safe-area-inset-bottom))
        visible: =(!!props.itemSeries2 && !props.itemSeries3) && ((vars.chartoptions ||
          props.defaultChartOption) === 'day')
      slots:
        grid:
          - component: oh-chart-grid
            config:
              right: 15%
        legend:
          - component: oh-chart-legend
            config:
              bottom: 15
              orient: horizontal
              show: true
        series:
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries1
              dimension1: hour
              item: =props.itemSeries1
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(1).toLocaleString('de-DE')
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries1].unit
                  show: true
                symbol: none
              name: =props.labelSeries1
              service: =props.persistenceService1
              type: bar
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries2
              dimension1: hour
              item: =props.itemSeries2
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(1)
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries2].unit
                  show: true
                symbol: none
              name: =props.labelSeries2
              service: =props.persistenceService2
              type: bar
        xAxis:
          - component: oh-category-axis
            config:
              categoryType: day
              monthFormat: short
              weekdayFormat: short
              name: " "
        yAxis:
          - component: oh-value-axis
            config:
              axisLabel:
                formatter: =v => Number(v).toLocaleString('de-DE')
              name: =items[props.itemSeries1].unit
    - component: oh-chart
      config:
        chartType: year
        height: calc(100vh - var(--f7-navbar-height) - 48px - env(safe-area-inset-top) -
          env(safe-area-inset-bottom))
        visible: =(!!props.itemSeries3 && !props.itemSeries4) && ((vars.chartoptions ||
          props.defaultChartOption) === 'year')
      slots:
        grid:
          - component: oh-chart-grid
            config:
              right: 15%
        legend:
          - component: oh-chart-legend
            config:
              bottom: 15
              orient: horizontal
              show: true
        series:
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries1
              dimension1: month
              item: =props.itemSeries1
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(0).toLocaleString('de-DE')
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries1].unit
                  show: true
                symbol: none
              name: =props.labelSeries1
              service: =props.persistenceService1
              type: bar
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries2
              dimension1: month
              item: =props.itemSeries2
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(0)
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries2].unit
                  show: true
                symbol: none
              name: =props.labelSeries2
              service: =props.persistenceService2
              type: bar
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries3
              dimension1: month
              item: =props.itemSeries3
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(0)
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries3].unit
                  show: true
                symbol: none
              name: =props.labelSeries3
              service: =props.persistenceService3
              type: bar
        xAxis:
          - component: oh-category-axis
            config:
              categoryType: year
              monthFormat: short
              weekdayFormat: short
              name: " "
        yAxis:
          - component: oh-value-axis
            config:
              axisLabel:
                formatter: =v => Number(v).toLocaleString('de-DE')
              name: =items[props.itemSeries1].unit
    - component: oh-chart
      config:
        chartType: month
        height: calc(100vh - var(--f7-navbar-height) - 48px - env(safe-area-inset-top) -
          env(safe-area-inset-bottom))
        visible: =(!!props.itemSeries3 && !props.itemSeries4) && ((vars.chartoptions ||
          props.defaultChartOption) === 'month')
      slots:
        grid:
          - component: oh-chart-grid
            config:
              right: 15%
        legend:
          - component: oh-chart-legend
            config:
              bottom: 15
              orient: horizontal
              show: true
        series:
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries1
              dimension1: date
              item: =props.itemSeries1
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(0).toLocaleString('de-DE')
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries1].unit
                  show: true
                symbol: none
              name: =props.labelSeries1
              service: =props.persistenceService1
              type: bar
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries2
              dimension1: date
              item: =props.itemSeries2
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(0)
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries2].unit
                  show: true
                symbol: none
              name: =props.labelSeries2
              service: =props.persistenceService2
              type: bar
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries3
              dimension1: date
              item: =props.itemSeries3
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(0)
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries3].unit
                  show: true
                symbol: none
              name: =props.labelSeries3
              service: =props.persistenceService3
              type: bar
        xAxis:
          - component: oh-category-axis
            config:
              categoryType: month
              monthFormat: short
              weekdayFormat: short
              name: " "
        yAxis:
          - component: oh-value-axis
            config:
              axisLabel:
                formatter: =v => Number(v).toLocaleString('de-DE')
              name: =items[props.itemSeries1].unit
    - component: oh-chart
      config:
        chartType: week
        height: calc(100vh - var(--f7-navbar-height) - 48px - env(safe-area-inset-top) -
          env(safe-area-inset-bottom))
        visible: =(!!props.itemSeries3 && !props.itemSeries4) && ((vars.chartoptions ||
          props.defaultChartOption) === 'week')
      slots:
        grid:
          - component: oh-chart-grid
            config:
              right: 15%
        legend:
          - component: oh-chart-legend
            config:
              bottom: 15
              orient: horizontal
              show: true
        series:
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries1
              dimension1: isoWeekday
              item: =props.itemSeries1
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(0).toLocaleString('de-DE')
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries1].unit
                  show: true
                symbol: none
              name: =props.labelSeries1
              service: =props.persistenceService1
              type: bar
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries2
              dimension1: isoWeekday
              item: =props.itemSeries2
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(0)
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries2].unit
                  show: true
                symbol: none
              name: =props.labelSeries2
              service: =props.persistenceService2
              type: bar
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries3
              dimension1: isoWeekday
              item: =props.itemSeries3
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(0)
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries3].unit
                  show: true
                symbol: none
              name: =props.labelSeries3
              service: =props.persistenceService3
              type: bar
        xAxis:
          - component: oh-category-axis
            config:
              categoryType: week
              monthFormat: short
              weekdayFormat: short
              name: " "
        yAxis:
          - component: oh-value-axis
            config:
              axisLabel:
                formatter: =v => Number(v).toLocaleString('de-DE')
              name: =items[props.itemSeries1].unit
    - component: oh-chart
      config:
        chartType: day
        height: calc(100vh - var(--f7-navbar-height) - 48px - env(safe-area-inset-top) -
          env(safe-area-inset-bottom))
        visible: =(!!props.itemSeries3 && !props.itemSeries4) && ((vars.chartoptions ||
          props.defaultChartOption) === 'day')
      slots:
        grid:
          - component: oh-chart-grid
            config:
              right: 15%
        legend:
          - component: oh-chart-legend
            config:
              bottom: 15
              orient: horizontal
              show: true
        series:
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries1
              dimension1: hour
              item: =props.itemSeries1
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(1)
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries1].unit
                  show: true
                symbol: none
              name: =props.labelSeries1
              service: =props.persistenceService1
              type: bar
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries2
              dimension1: hour
              item: =props.itemSeries2
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(1)
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries2].unit
                  show: true
                symbol: none
              name: =props.labelSeries2
              service: =props.persistenceService2
              type: bar
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries3
              dimension1: hour
              item: =props.itemSeries3
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(1)
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries3].unit
                  show: true
                symbol: none
              name: =props.labelSeries3
              service: =props.persistenceService3
              type: bar
        xAxis:
          - component: oh-category-axis
            config:
              categoryType: day
              monthFormat: short
              weekdayFormat: short
              name: " "
        yAxis:
          - component: oh-value-axis
            config:
              axisLabel:
                formatter: =v => Number(v).toLocaleString('de-DE')
              name: =items[props.itemSeries1].unit
    - component: oh-chart
      config:
        chartType: year
        height: calc(100vh - var(--f7-navbar-height) - 48px - env(safe-area-inset-top) -
          env(safe-area-inset-bottom))
        visible: =!!props.itemSeries4 && ((vars.chartoptions ||
          props.defaultChartOption) === 'year')
      slots:
        grid:
          - component: oh-chart-grid
            config:
              right: 15%
        legend:
          - component: oh-chart-legend
            config:
              bottom: 15
              orient: horizontal
              show: true
        series:
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries1
              dimension1: month
              item: =props.itemSeries1
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(0).toLocaleString('de-DE')
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries1].unit
                  show: true
                symbol: none
              name: =props.labelSeries1
              service: =props.persistenceService1
              type: bar
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries2
              dimension1: month
              item: =props.itemSeries2
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(0)
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries2].unit
                  show: true
                symbol: none
              name: =props.labelSeries2
              service: =props.persistenceService2
              type: bar
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries3
              dimension1: month
              item: =props.itemSeries3
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(0)
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries3].unit
                  show: true
                symbol: none
              name: =props.labelSeries3
              service: =props.persistenceService3
              type: bar
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries4
              dimension1: month
              item: =props.itemSeries4
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(0)
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries4].unit
                  show: true
                symbol: none
              name: =props.labelSeries4
              service: =props.persistenceService4
              type: bar
        xAxis:
          - component: oh-category-axis
            config:
              categoryType: year
              monthFormat: short
              weekdayFormat: short
              name: " "
        yAxis:
          - component: oh-value-axis
            config:
              axisLabel:
                formatter: =v => Number(v).toLocaleString('de-DE')
              name: =items[props.itemSeries1].unit
    - component: oh-chart
      config:
        chartType: month
        height: calc(100vh - var(--f7-navbar-height) - 48px - env(safe-area-inset-top) -
          env(safe-area-inset-bottom))
        visible: =!!props.itemSeries4 && ((vars.chartoptions ||
          props.defaultChartOption) === 'month')
      slots:
        grid:
          - component: oh-chart-grid
            config:
              right: 15%
        legend:
          - component: oh-chart-legend
            config:
              bottom: 15
              orient: horizontal
              show: true
        series:
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries1
              dimension1: date
              item: =props.itemSeries1
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(0).toLocaleString('de-DE')
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries1].unit
                  show: true
                symbol: none
              name: =props.labelSeries1
              service: =props.persistenceService1
              type: bar
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries2
              dimension1: date
              item: =props.itemSeries2
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(0)
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries2].unit
                  show: true
                symbol: none
              name: =props.labelSeries2
              service: =props.persistenceService2
              type: bar
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries3
              dimension1: date
              item: =props.itemSeries3
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(0)
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries3].unit
                  show: true
                symbol: none
              name: =props.labelSeries3
              service: =props.persistenceService3
              type: bar
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries4
              dimension1: date
              item: =props.itemSeries4
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(0)
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries4].unit
                  show: true
                symbol: none
              name: =props.labelSeries4
              service: =props.persistenceService4
              type: bar
        xAxis:
          - component: oh-category-axis
            config:
              categoryType: month
              monthFormat: short
              weekdayFormat: short
              name: " "
        yAxis:
          - component: oh-value-axis
            config:
              axisLabel:
                formatter: =v => Number(v).toLocaleString('de-DE')
              name: =items[props.itemSeries1].unit
    - component: oh-chart
      config:
        chartType: week
        height: calc(100vh - var(--f7-navbar-height) - 48px - env(safe-area-inset-top) -
          env(safe-area-inset-bottom))
        visible: =!!props.itemSeries4 && ((vars.chartoptions ||
          props.defaultChartOption) === 'week')
      slots:
        grid:
          - component: oh-chart-grid
            config:
              right: 15%
        legend:
          - component: oh-chart-legend
            config:
              bottom: 15
              orient: horizontal
              show: true
        series:
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries1
              dimension1: isoWeekday
              item: =props.itemSeries1
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(0).toLocaleString('de-DE')
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries1].unit
                  show: true
                symbol: none
              name: =props.labelSeries1
              service: =props.persistenceService1
              type: bar
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries2
              dimension1: isoWeekday
              item: =props.itemSeries2
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(0)
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries2].unit
                  show: true
                symbol: none
              name: =props.labelSeries2
              service: =props.persistenceService2
              type: bar
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries3
              dimension1: isoWeekday
              item: =props.itemSeries3
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(0)
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries3].unit
                  show: true
                symbol: none
              name: =props.labelSeries3
              service: =props.persistenceService3
              type: bar
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries4
              dimension1: isoWeekday
              item: =props.itemSeries4
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(0)
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries4].unit
                  show: true
                symbol: none
              name: =props.labelSeries4
              service: =props.persistenceService4
              type: bar
        xAxis:
          - component: oh-category-axis
            config:
              categoryType: week
              monthFormat: short
              weekdayFormat: short
              name: " "
        yAxis:
          - component: oh-value-axis
            config:
              axisLabel:
                formatter: =v => Number(v).toLocaleString('de-DE')
              name: =items[props.itemSeries1].unit
    - component: oh-chart
      config:
        chartType: day
        height: calc(100vh - var(--f7-navbar-height) - 48px - env(safe-area-inset-top) -
          env(safe-area-inset-bottom))
        visible: =!!props.itemSeries4 && ((vars.chartoptions ||
          props.defaultChartOption) === 'day')
      slots:
        grid:
          - component: oh-chart-grid
            config:
              right: 15%
        legend:
          - component: oh-chart-legend
            config:
              bottom: 15
              orient: horizontal
              show: true
        series:
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries1
              dimension1: hour
              item: =props.itemSeries1
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(1)
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries1].unit
                  show: true
                symbol: none
              name: =props.labelSeries1
              service: =props.persistenceService1
              type: bar
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries2
              dimension1: hour
              item: =props.itemSeries2
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(1)
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries2].unit
                  show: true
                symbol: none
              name: =props.labelSeries2
              service: =props.persistenceService2
              type: bar
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries3
              dimension1: hour
              item: =props.itemSeries3
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(1)
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries3].unit
                  show: true
                symbol: none
              name: =props.labelSeries3
              service: =props.persistenceService3
              type: bar
          - component: oh-aggregate-series
            config:
              aggregationFunction: diff_last
              color: =props.colorSeries4
              dimension1: hour
              item: =props.itemSeries4
              label:
                formatter: =v => Number.parseFloat(v.data[1]).toFixed(1)
                position: top
                show: true
              markLine:
                animation: false
                data:
                  - type: average
                label:
                  formatter: =v => Number.parseFloat(v.value).toFixed(0) + ' ' +
                    items[props.itemSeries4].unit
                  show: true
                symbol: none
              name: =props.labelSeries4
              service: =props.persistenceService4
              type: bar
        xAxis:
          - component: oh-category-axis
            config:
              categoryType: day
              monthFormat: short
              weekdayFormat: short
              name: " "
        yAxis:
          - component: oh-value-axis
            config:
              axisLabel:
                formatter: =v => Number(v).toLocaleString('de-DE')
              name: =items[props.itemSeries1].unit
    - component: f7-segmented
      config:
        class:
          - button-raised
          - margin-left
          - margin-right
          - margin-bottom-half
        style:
          --f7-button-border-radius: 4px
          --f7-button-font-size: 14px
          --f7-button-font-weight: 300
          --f7-button-outline-border-width: 1px
          --f7-button-padding-horizontal: 0px
          --f7-button-padding-vertical: 0px
          --f7-button-text-color: "=themeOptions.dark === 'light' ? 'black' : 'white'"
          box-shadow: 1px 1px 7px 1px rgba(0,0,0,0.1)
          padding: 0px 1px 1px 1px
        visible: true
      slots:
        default:
          - component: oh-button
            config:
              action: variable
              actionVariable: chartoptions
              actionVariableValue: day
              text: Tag
          - component: oh-button
            config:
              action: variable
              actionVariable: chartoptions
              actionVariableValue: week
              text: Woche
          - component: oh-button
            config:
              action: variable
              actionVariable: chartoptions
              actionVariableValue: month
              text: Monat
          - component: oh-button
            config:
              action: variable
              actionVariable: chartoptions
              actionVariableValue: year
              text: Jahr

Is there something wrong with the widget code or is there a problem with echart?
Thanks!

[edit]: added missing GIF for “months”

What is your openHAB version?

5.1.3 stable

I would expect the behaviour you described to be linked to the issue that Charts: Fix add/subtract period doesn't account for different month lenghts by florian-h05 · Pull Request #3958 · openhab/openhab-webui · GitHub fixed.

Can you try upgrading Main UI to the latest build of the backporting branch?

See Bundle Management | openHAB. The artefact is:
JFrog

Is it just to copy the artifact (org.openhab.ui-5.1.4.jar) to the addons folder?

No, dropping the JAR won’t work.
I linked to the docs, there it is described.

This way via console?

openhab> bundle:update 228 https://openhab.jfrog.io/ui/native/sandbox-release/org/openhab/ui/bundles/org.openhab.ui/5.1.4/org.openhab.ui-5.1.4.jar

If yes, how to roll back? Do I need to find the 5.1.3 release build and bundle:update again?

Sorry for asking this, but it’s the first time doing this with the UI - so far only binding snapshots via addons folder….

Yes

Use bundle:list 228 -l and save the location in a text file. You can use that location to get the original bundle back.

                           _   _     _     ____  
   ___   ___   ___   ___  | | | |   / \   | __ ) 
  / _ \ / _ \ / _ \ / _ \ | |_| |  / _ \  |  _ \ 
 | (_) | (_) |  __/| | | ||  _  | / ___ \ | |_) )
  \___/|  __/ \___/|_| |_||_| |_|/_/   \_\|____/ 
       |_|       5.1.3 - Release Build

Use '<tab>' for a list of available commands
and '[cmd] --help' for help on a specific command.
To exit, use '<ctrl-d>' or 'logout'.

openhab> bundle:list 228 -l                                                                                                                                               
START LEVEL 100 , List Threshold: 50
 ID │ State  │ Lvl │ Version │ Name
────┼────────┼─────┼─────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
228 │ Active │  80 │ 5.1.3   │ openHAB UI :: Bundles :: Main UI

@florian-h05

It seems the command didn’t work - there is no location info.

Would you please provide me the rollback link here? That would be very helpful.
I would feel much more comfortable with the rollback Link before starting the update to 5.1.4.

Thank you!

[edit]:

Repository Path:	
libs-release/org/openhab/ui/bundles/org.openhab.ui/5.1.3/org.openhab.ui-5.1.3.jar

Is this the correct source? What is the full link?

@florian-h05

This command crashed my UI. The UI doesn’t load any longer. openhab restart doesn’t help either.

openhab> bundle:list 228                                                                                                                                                  
START LEVEL 81 , List Threshold: 50
 ID │ State  │ Lvl │ Version │ Name
────┼────────┼─────┼─────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
228 │ Active │  80 │         │ mvn:org.openhab.ui.bundles/org.openhab.ui/5.1.3

Console still shows 5.1.3 - this is very odd.

[edit]
It seems not just the UI crashed but also the rules stopped working…
Anything I can do to recover? e.g. manually replace a file somewhere?

[edit2]
I restored openhab backup and luckily UI is back.
I think I will resume testing when the UI fixes are available in a release build.
Will this be OH5.2?

It‘s listed on the JFrog artefact you sent:

https://openhab.jfrog.io/artifactory/libs-release/org/openhab/ui/bundles/org.openhab.ui/5.1.3/org.openhab.ui-5.1.3.jar

The issue might have been that the 5.1.4 artefact wasn‘t available when you tried, at least at the moment it isn‘t. I didn‘t notice that before, I think this might be related to the sandbox-release-job on Jenkins

The fix will be available with 5.1.4 once that is released.

@florian-h05

By when will 5.1.4 be released? Roughly…

There is no schedule.
It depends on the number of backported fixes and how critical they are.
But I think I’ll propose creating a new patch release in the next weeks.

1 Like

@florian-h05
I upgraded to 5.1.4 this evening.

As you mentioned - this update solved the following problems:

… and

The following problems are still there:

Here you with the current weekly chart - the datepicker stated April 12 which was Sunday last week, however this week started with Mon April13. Datepicker should state 13.April 2026 and no bars should be shown on Sunday.

Another strange problem appeared… it was probably there before 5.1.4…

Whenever you select the next time window in the future - eg 2027 or Mai 2026 or next week or tomorrow, there is almost always a bar and if not a bar, there are “0” values e.g. in the first month, the first hour, etc.

Let me know in case you would want some more data.