openHAB 5.2 Release discussion

OK, if that’s the source, the issue definitely needs to be made on openhab-core.

If it works with other persistence services, it’s likely InfluxDB specific so it would go to openHAB-addons.

I think the reason is that it’s not a function, it’s an object. And, objects gets converted into Java maps. I don’t know how JavaScript has hacked the “functions” into such an object, but they are probably pretty broken after being converted to map and back to object again.

Unless you changed that, there’s no third parameter for javaify(). The reason is that I couldn’t see the point, because any JS object that is put on the shared cache and retrieved by a different rule will throw the multithreaded exception. I still cannot understand how using the shared cache for this can be useful.

A third parameter can very easily be added also for javaify(), but for that to have any point, there must exist a situation where this will actually work. I’m still confused about exactly what situation that is - is it for sharing among JSRules created by the same file, so that they share the context? It’s the only situation where I can sort of imagine that it could work…

But, we went through all kind of hoops to make sure that the unprefixed entries should still also exist in JS. Why isn’t that the case here?

By the way, the prefixes aren’t numeric, they are the ID of the module. They can be anything, but MainUI doesn’t allow editing the IDs in the “Design” tab, and when they aren’t specified, they are assigned numeric values starting with 1. You can however set them to something meaningful in the “Code” tab.

As said above, I don’t think that parameter exists for javaify() (it does for jsify(), but sharing between a condition and an action within the same rule, is an example of a situation where it would make sense to let the JS object through to the cache - so perhaps the third parameter should be added also for javaify(). It’s a bit of a slippery slope though, because I bet that it’s not long before we start seeing multithreaded exceptions again everywhere once AIs figure out that it’s possible to skip javaify() :wink:

edit: I took a look in the code, and something wasn’t properly thought through here I think. We do the _collapseInputMap() thing, but the result isn’t actually exposed :upside_down_face:

By adding this somewhere in _getTriggeredData():

data.input = input;

…it should be possible to do event.input.event.getMemberName().

We reverted a change that removed the prefixes = added the prefixes back.

But, that wasn’t what we actually “did” (even though it seems like that was the net result as it is now):

  • We reverted the change in core, because it led to loss of data
  • To shield JS users from yet another “breaking change”, we moved the prefix removal to the JS helper library

This is what I thought I did when I wrote this, so I’m kind of surprised to see this affecting the users now:

But, the reason is clear when looking at the code, we build the collapsed map/object, but it’s never assigned anywhere.

TimrMgr is a Class. That class defines both members and methods. After javaification the methods are gone.

const { time } = require('openhab');
const helpers = require('./helpers');

/**
 * Implements a manager for Timers with a simple interface. Once built, call
 * check to create a timer or to reschedule the timer if it exists. Options
 * exist to call a function when the timer expires, when the timer already
 * exists, and a boolean to determine if the timer is rescheduled or not.
 */
class TimerMgr {

  /**
   * Constructor
   */
  constructor() {
    // Stores the timer and the functions:
    // - timer: timer Object
    // - notFlapping: function to call when timer expires
    // - flapping: function to call when check is called and timer already exists
    this.timers = {};
  }

  /**
   * Function to call when null was passed for the func or flappingFunc.
   */
  #noop() {
    // do nothing
  }

  /**
   * If there is no timer associated with key, create one to expire at when and
   * call func (or #noop if func is null).
   * If there is a timer already associted with key, if reschedule is not
   * supplied or it's false cancel the timer. If reschedule is true, reschedule
   * the timer using when.
   * If there is a timer already associated with key, if a flappingFunc is
   * provided, call it.
   * @param {string} key the identifier of the timer in the TimerMgr instance
   * @param {*} when any representation of time of duration, see time.toZDT
   * @param {function} func function to call when the timer expires
   * @param {boolean} [reschedule=false] optional flag, when present and true rescheudle the timer if it already exists
   * @param {function} [flappingFunc] optional function to call when the timer already exists
   * @param {string} [name] timer name displayed in openHAB
   * @param {boolean}[recreate=false] optional flag, when present and true the timer will be recreated with the new values instead of cancelled, evaluated after reschedule
   */
  check(key, when, func, reschedule, flappingFunc, name, recreate) {
    const timeout = time.toZDT(when);

    // timer exists
    if (key in this.timers) {
      if (reschedule) {
        this.timers[key]['timer'].reschedule(timeout);
      }
      else {
        this.cancel(key);
      }
      if (flappingFunc) {
        flappingFunc();
      }
      if (recreate) {
        this.check(key, when, func, reschedule, flappingFunc, name, false);
      }
    }

    // timer doesn't already exist, create a new one
    else {
      var timer = helpers.createTimer(when, () => {
        // Call the passed in func when the timer expires.
        if (key in this.timers && 'notFlapping' in this.timers[key]) {
          this.timers[key]['notFlapping']();
        }
        // Clean up the timer from the manager.
        if (key in this.timers) {
          delete this.timers[key];
        }
      }, name, key);
      this.timers[key] = {
        'timer': timer,
        'flapping': flappingFunc,
        'notFlapping': (func) ? func : this.#noop
      };
    }
  }

  /**
   * @param {*} key name of the timer
   * @returns {boolean} true if there is a timer assocaited with key
   */
  hasTimer(key) {
    return key in this.timers;
  }
	
  /**
   * @param {*} key name of the timer
   * @returns {Duration} of time left in the timer function
   * or null if timer does not exist
   */
  getTimerDuration(key) {
    if (key in this.timers) {
      return time.Duration.between(time.toZDT(), time.toZDT(this.timers[key].timer.getExecutionTime()));
    }

    return null;
  }

  /**
   * If there is a timer assocaited with key, cancel it.
   * @param {*} key name of the timer
   */
  cancel(key) {
    if (key in this.timers) {
      this.timers[key]['timer'].cancel();
      delete this.timers[key];
    }
  }

  /**
   * Cancels all existing timers. Any timer that is actively running or
   * has just terminated will be skipped and cleaned up in the _notFlapping
   * method.
   */
  cancelAll() {
    for (var key in this.timers) {
      var t = this.timers[key]['timer'];
      if (!t.hasTerminated() && !t.isRunning()) {
        this.cancel(key);
      }
      delete this.timers[key];
    }
  }
}

/**
 * The TimerMgr handles the book keeping to manage a bunch of timers identified
 * with a unique key.
 */
function getTimerMgr () {
    return new TimerMgr();
}

module.exports = {
  TimerMgr,
  getTimerMgr
}

helpers.createTimer() creates an OH Java Timer.

I understand that, what I meant to say is that JS isn’t object-oriented and doesn’t really have classes, so they have “retrofitted” classes into a system that doesn’t really support it. I’m thus guessing that a class is still an “object” to typeof. Here is the check that spits functions out:

So, if typeof had encountered a function, an error would have been thrown. I tried to look it up now on Google, but I don’t trust its answer to be correct. According to it, the “object” itself is stored as a function with the constructor, but the rest of the methods are stored under object.prototype. I don’t know what to make of that, all I can say is that typeof can’t say function, or it would have been rejected. My guess is that all the stuff under object.prototype simply vanishes when it’s converted to a Java map.

It must end up being treated like a “normal object”, that’s the only way it makes sense to see what we see:

Maybe better to split that (usefull) discussion into a seperate thread or continue on Github. It seems a topic on its own.

Today i installed the 5.2.1 update in my production environment and happy to share that the log was as clear as it never has been and everything went real smooth.

The current version of OHRT in main should address the issues preventing the Objects from being shared between rules by passing or the shared cache. I’m still testing and would appreciate feedback before cutting a new version. You can text by cloning the repo over $OH_CONF/automation/js/node_modules/openhab_rules_tools.

You need to pass a key and the shared cache when you create the Object and on the receiving side also pass the same key and shared cache and the Timer will be built with the same data. It’s all Java so there are no multithreaded issues.

Done. Note that it’s $OPENHAB_CONF/automation/js/node_modules/openhab_rules_tools/. I suppose the now created .git/ and .github/ subdirectories are no problem?

The only thing I’m not really sure of, is how to test this?

The extra folders are no problem.

Restart OH and watch your logs for errors, particular when a rule you know uses the library runs. Nothing more is required.

A new version of OHRT has been published. I cannot guarantee it’s compatible with versions of OH prior to 5.2.1, but it should be OK. It’s untested though.

Upgrade in all the usual ways.

If you are passing any OHRT Object between rules either through runRule or the cache.shared, you need to slightly change how you do that.

If you are sharing through the cahce.shared, create the new Object by passing a unique key and cache.shared as the last two arguments to the constructor. You do this everywhere you use this Object. The OHRT class deals with interacting with the cache.shared for you.

If you are passing the Object in runRule, just like with the cache.shared you need to pass in a unique key and cache.shared when you create the Object. In the call to runRule, just pass the key and in the called rule, instantiate a new instance of the Object passing in that key and cache.shared. Again, all the interactions with the shared cache are handled for you.

You cannot put the OHRT Objects into the cache.shared nor pass them in runRule directly.

Everywhere the OHRT classes are used “normally” without sharing between rules will work unchanged. Strictly speaking you no longer need to store them in the cache any longer but if you do it doesn’t hurt anything.

After update from 5.1.4 to 5.2.1 Log error

openhab.log

2026-08-18 11:46:44.239 [WARN ] [e.internal.VoiceManagerConfiguration] - No configuration description found for system:voice, unable to apply defaults!

What do I need to tweak to make this warning go away?

audio.config

:org.apache.felix.configadmin.revision:=L"10"
defaultSink="enhancedjavasound"
defaultSource="javasound"
felix.fileinstall.filename="file:/R:/servers/openhab/userdata/etc/org.openhab.audio.cfg"
service.bundleLocation="?"
service.pid="org.openhab.audio"

voice.config

:org.apache.felix.configadmin.revision:=L"17"
cacheSizeTTS="10241"
conversationHistoryLimit="50"
defaultHLI="rulehli"
defaultKS="rustpotterks"
defaultSTT="voskstt"
defaultTTS="pipertts"
defaultVoice="pipertts:kristina-medium-en_US"
enableCacheTTS=B"true"
felix.fileinstall.filename="file:/R:/servers/openhab/userdata/etc/org.openhab.voice.cfg"
implicitItemPermission="READ_WRITE"
keyword="angel"
listeningItem="voice_command_listen"
listeningMelody="A\ O:100\ A':50"
maxTextLengthCacheTTS="250"
service.bundleLocation="?"
service.pid="org.openhab.voice"

Nothing, it has to be fixed in the code.

I run Openhab 5.2.1 and have a problem on the following page.

The month values of “Jahr-1” (green), Jahr-2 (blue) and Jahr-3 are no longer displayed. They should be displayed as “line” while the month values of the current year are displayed as “bar”.

The values of “Jahr-1”, “Jahr-2” and “Jahr-3” are also not displayed in the “data table” as it was in the older Openhab versions.

… even when I change the year (with button in top right) the values are displayed

The values are loaded by the following widget (line 592 - last “oh-chart” in the widget - “chartType: year”):

version: 1
widgets:
  Card_Verbrauch:
    tags:
      - BG
    props:
      parameters:
        - description: A text prop
          label: Prop 1
          name: prop1
          required: false
          type: TEXT
        - context: item
          description: Strom Verbrauch
          label: Item
          name: prop_itemVerbrauch
          required: false
          type: TEXT
        - context: item
          description: Strom Verbrauch Jahr
          label: Item
          name: prop_itemVerbrauchJahr
          required: false
          type: TEXT
        - context: item
          description: Strom Monatserwartung
          label: Item
          name: prop_itemkWh20xxMonatserwartung
          required: false
          type: TEXT
        - context: item
          description: Strom Monatdurchschnitt
          label: Item
          name: prop_itemkWh20xxMonatsdurchschnitt
          required: false
          type: TEXT
        - context: item
          description: Temperatur Item
          label: Item
          name: prop_itemTemperatur
          required: false
          type: TEXT
      parameterGroups: []
    component: f7-card
    config:
      backdrop: false
      class:
        - no-padding
      expandable: false
      style:
        --f7-theme-color: var(--f7-text-color)
        border-radius: var(--f7-card-expandable-border-radius)
        box-shadow: var(--f7-card-expandable-box-shadow)
        height: 515px
        margin-bottom: 0px
        margin-left: 0px
        margin-right: 0px
        margin-top: 0px
        width: 100%
      swipeToClose: false
    slots:
      default:
        - component: f7-segmented
          config:
            class: segmented-round
            style:
              bottom: -15px
              height: 30px
              left: 0px
              position: absolute
              width: 100%
              z-index: 2
          slots:
            default:
              - component: oh-button
                config:
                  action: variable
                  actionVariable: varPeriod
                  actionVariableValue: year
                  iconSize: 20px
                  outline: true
                  style:
                    --f7-button-bg-color: "=(vars.varPeriod == 'year' || vars.varPeriod == undefined) ? 'transparent' : '#f0f0f0' "
                    --f7-button-hover-bg-color: "#e7f3fe"
                    --f7-button-pressed-bg-color: "#9dcefb"
                    height: 100%
                    width: 100%
                  text: Jahr
                  textColor: "=(vars.varPeriod == 'year' || vars.varPeriod == undefined) ? 'red' : 'black'  "
                  visible: true
              - component: oh-button
                config:
                  action: variable
                  actionVariable: varPeriod
                  actionVariableValue: total
                  iconSize: 20px
                  outline: true
                  style:
                    --f7-button-bg-color: "=(vars.varPeriod == 'total') ? 'transparent' : '#f0f0f0' "
                    --f7-button-hover-bg-color: "#e7f3fe"
                    --f7-button-pressed-bg-color: "#9dcefb"
                    height: 100%
                    width: 100%
                  text: ∑ Jahre
                  textColor: "=(vars.varPeriod == 'total' ) ? 'red' : 'black'  "
                  visible: true
              - component: oh-button
                config:
                  action: variable
                  actionVariable: varPeriod
                  actionVariableValue: month
                  iconSize: 20px
                  outline: true
                  style:
                    --f7-button-bg-color: "=(vars.varPeriod == 'month')  ? 'transparent' : '#f0f0f0' "
                    --f7-button-hover-bg-color: "#e7f3fe"
                    --f7-button-pressed-bg-color: "#9dcefb"
                    height: 100%
                    width: 100%
                  text: Monat
                  textColor: "=(vars.varPeriod == 'month' ) ? 'red' :   'black'  "
              - component: oh-button
                config:
                  action: variable
                  actionVariable: varPeriod
                  actionVariableValue: week
                  iconSize: 20px
                  outline: true
                  style:
                    --f7-button-bg-color: "=(vars.varPeriod == 'week' ) ? 'transparent' : '#f0f0f0' "
                    --f7-button-hover-bg-color: "#e7f3fe"
                    --f7-button-pressed-bg-color: "#9dcefb"
                    height: 100%
                    width: 100%
                  text: Woche
                  textColor: "=(vars.varPeriod == 'week' ) ? 'red' : 'black'  "
              - component: oh-button
                config:
                  action: variable
                  actionVariable: varPeriod
                  actionVariableValue: day
                  iconSize: 20px
                  outline: true
                  style:
                    --f7-button-bg-color: "=(vars.varPeriod == 'day' ) ? 'transparent' : '#f0f0f0' "
                    --f7-button-hover-bg-color: "#e7f3fe"
                    --f7-button-pressed-bg-color: "#9dcefb"
                    height: 100%
                    width: 100%
                  text: Tag
                  textColor: "=(vars.varPeriod == 'day' ) ? 'red' : 'black'"
        - component: oh-chart
          config:
            height: 100%
            options:
              backgroundColor: transparent
            sidebar: false
            visible: "=vars.varPeriod == 'total'  ? true : false"
          slots:
            grid:
              - component: oh-chart-grid
                config:
                  height: 70%
                  includeLabels: true
                  left: 70
                  right: 70
                  show: false
                  top: 60
            legend:
              - component: oh-chart-legend
                config:
                  bottom: 25px
                  left: center
                  orient: horizontal
                  show: true
                  width: 600
            series:
              - component: oh-data-series
                config:
                  avoidLabelOverlap: true
                  center:
                    - 50%
                    - 70%
                  data:
                    - label:
                        backgroundColor: "#F6F8FC"
                        borderColor: "#8C8D8E"
                        borderRadius: 4
                        borderWidth: 1
                        formatter: |-
                          {c|{c} kWh/Jahr
                          472 kWh/Monat
                          15.5 kWh/Tag}
                        padding: 2
                        rich:
                          c:
                            color: "#4C5058"
                            fontSize: 12
                            fontWeight: bold
                            lineHeight: 20
                        show: true
                      name: "2023"
                      value: =items.Strom2023.state
                    - label:
                        backgroundColor: "#F6F8FC"
                        borderColor: "#8C8D8E"
                        borderRadius: 4
                        borderWidth: 1
                        formatter: |-
                          {c|{c} kWh/Jahr
                          468 kWh/Monat
                          15.3 kWh/Tag}
                        padding: 2
                        rich:
                          c:
                            color: "#4C5058"
                            fontSize: 12
                            fontWeight: bold
                            lineHeight: 20
                        show: true
                      name: "2024"
                      value: =items.Strom2024.state
                    - label:
                        backgroundColor: "#F6F8FC"
                        borderColor: "#8C8D8E"
                        borderRadius: 4
                        borderWidth: 1
                        formatter: |-
                          {c|{c} kWh/Jahr
                          488 kWh/Monat
                          16.0 kWh/Tag}
                        padding: 2
                        rich:
                          c:
                            color: "#4C5058"
                            fontSize: 12
                            fontWeight: bold
                            lineHeight: 20
                        show: true
                      name: "2025"
                      value: =items.Strom2025.state
                    - label:
                        backgroundColor: "#F6F8FC"
                        borderColor: "#8C8D8E"
                        borderRadius: 4
                        borderWidth: 1
                        formatter: "{c|{c} kWh/Jahr}"
                        padding: 2
                        rich:
                          c:
                            color: "#4C5058"
                            fontSize: 12
                            fontWeight: bold
                            lineHeight: 20
                        show: true
                      name: "2026"
                      value: =items.Strom2026.state
                  endAngle: 360
                  labelLine:
                    length: 20
                  radius:
                    - 25%
                    - 55%
                  startAngle: 180
                  type: pie
            title:
              - component: oh-chart-title
                config:
                  left: 170px
                  show: true
                  text: Strom-Jahresvergleich
                  top: 0
            tooltip:
              - component: oh-chart-tooltip
                config:
                  show: true
        - component: oh-chart
          config:
            chartType: isoWeek
            height: 100%
            options:
              backgroundColor: transparent
            sidebar: true
            visible: "=vars.varPeriod == 'week' ? true : false"
          slots:
            grid:
              - component: oh-chart-grid
                config:
                  height: 70%
                  includeLabels: true
                  left: 70
                  right: 70
                  show: false
                  top: 70
            legend:
              - component: oh-chart-legend
                config:
                  bottom: 25px
                  left: 70
                  orient: horizontal
                  show: true
                  width: 600
            series:
              - component: oh-aggregate-series
                config:
                  aggregationFunction: diff_last
                  color: red
                  dimension1: isoWeekday
                  gridIndex: 0
                  id: 0
                  item: =props.prop_itemVerbrauch
                  label:
                    formatter: =v=>Number.parseFloat(v.data[1]).toFixed(1) + " kWh"
                    show: false
                  markLine:
                    data:
                      - label:
                          backgroundColor: red
                          formatter: "{c} kWh"
                          padding: 2
                          position: end
                          shom: true
                        type: average
                  name: Strom-Verbrauch
                  type: bar
                  xAxisIndex: 0
                  yAxisIndex: 0
              - component: oh-aggregate-series
                config:
                  aggregationFunction: average
                  color: "#673AB7"
                  dimension1: isoWeekday
                  gridIndex: 0
                  id: 1
                  item: =props.prop_itemTemperatur
                  lineStyle:
                    type: dashed
                    width: 2
                  name: Temperatur
                  step: middle
                  symbol: circle
                  symbolSize: 5
                  type: line
                  xAxisIndex: 0
                  yAxisIndex: 1
            tooltip:
              - component: oh-chart-tooltip
                config:
                  confine: true
                  show: true
                  trigger: axis
            xAxis:
              - component: oh-category-axis
                config:
                  categoryType: week
                  gridIndex: 0
                  monthFormat: short
                  nameGap: 22
                  nameLocation: center
                  weekdayFormat: short
            yAxis:
              - component: oh-value-axis
                config:
                  axisLabel:
                    formatter: "{value} kWh"
                  gridIndex: 0
                  nameGap: 40
                  nameLocation: center
              - component: oh-value-axis
                config:
                  axisLabel:
                    formatter: "{value} °C"
                  gridIndex: 0
                  nameGap: 40
                  nameLocation: center
                  scale: true
                  show: true
        - component: oh-chart
          config:
            chartType: month
            height: 100%
            options:
              backgroundColor: transparent
            sidebar: true
            visible: "=vars.varPeriod == 'month' ? true : false"
          slots:
            calendar: []
            grid:
              - component: oh-chart-grid
                config:
                  height: 70%
                  includeLabels: true
                  left: 70
                  right: 70
                  show: false
                  top: 70
            legend:
              - component: oh-chart-legend
                config:
                  bottom: 25px
                  left: 70
                  orient: horizontal
                  show: true
                  width: 600
            series:
              - component: oh-aggregate-series
                config:
                  aggregationFunction: diff_last
                  color: red
                  dimension1: date
                  gridIndex: 0
                  id: 0
                  item: =props.prop_itemVerbrauch
                  label:
                    formatter: =v=>Number.parseFloat(v.data[1]).toFixed(1) + " kWh"
                    show: false
                  markLine:
                    data:
                      - label:
                          backgroundColor: red
                          formatter: "{c} kWh"
                          padding: 2
                          position: end
                          shom: true
                        type: average
                  markPoint:
                    data:
                      - name: min
                        type: min
                      - name: max
                        type: max
                  name: Strom-Verbrauch
                  type: bar
                  xAxisIndex: 0
                  yAxisIndex: 0
              - component: oh-aggregate-series
                config:
                  aggregationFunction: average
                  color: "#673AB7"
                  dimension1: date
                  gridIndex: 0
                  id: 1
                  item: =props.prop_itemTemperatur
                  lineStyle:
                    type: dashed
                    width: 2
                  name: Temperatur
                  step: middle
                  symbol: circle
                  symbolSize: 5
                  type: line
                  xAxisIndex: 0
                  yAxisIndex: 1
            tooltip:
              - component: oh-chart-tooltip
                config:
                  confine: true
                  show: true
                  trigger: axis
            xAxis:
              - component: oh-category-axis
                config:
                  categoryType: month
                  gridIndex: 0
                  monthFormat: short
                  nameGap: 22
                  nameLocation: center
                  weekdayFormat: short
            yAxis:
              - component: oh-value-axis
                config:
                  axisLabel:
                    formatter: "{value} kWh"
                  gridIndex: 0
                  nameGap: 40
                  nameLocation: center
              - component: oh-value-axis
                config:
                  axisLabel:
                    formatter: "{value} °C"
                  gridIndex: 0
                  nameGap: 40
                  nameLocation: center
                  scale: true
        - component: oh-chart
          config:
            chartType: day
            height: 100%
            options:
              backgroundColor: transparent
            sidebar: true
            visible: "=vars.varPeriod == 'day' ? true : false"
          slots:
            calendar: []
            grid:
              - component: oh-chart-grid
                config:
                  height: 70%
                  includeLabels: true
                  left: 70
                  right: 70
                  show: false
                  top: 70
            legend:
              - component: oh-chart-legend
                config:
                  bottom: 25px
                  left: 70
                  orient: horizontal
                  show: true
                  width: 600
            series:
              - component: oh-aggregate-series
                config:
                  aggregationFunction: diff_last
                  color: red
                  dimension1: hour
                  gridIndex: 0
                  id: 0
                  item: =props.prop_itemVerbrauch
                  label:
                    formatter: =v=>Number.parseFloat(v.data[1]).toFixed(1) + " kWh"
                    show: false
                  markLine:
                    data:
                      - label:
                          backgroundColor: red
                          formatter: "{c} kWh"
                          padding: 2
                          position: end
                          shom: true
                        type: average
                  markPoint:
                    data:
                      - name: min
                        type: min
                      - name: max
                        type: max
                  name: Strom-Verbrauch
                  type: bar
                  xAxisIndex: 0
                  yAxisIndex: 0
              - component: oh-aggregate-series
                config:
                  aggregationFunction: average
                  color: "#673AB7"
                  dimension1: hour
                  gridIndex: 0
                  id: 1
                  item: =props.prop_itemTemperatur
                  lineStyle:
                    type: dashed
                    width: 2
                  name: Temperatur
                  step: middle
                  symbol: circle
                  symbolSize: 5
                  type: line
                  xAxisIndex: 0
                  yAxisIndex: 1
            tooltip:
              - component: oh-chart-tooltip
                config:
                  confine: true
                  show: true
                  trigger: axis
            xAxis:
              - component: oh-category-axis
                config:
                  categoryType: day
                  gridIndex: 0
                  monthFormat: short
                  nameGap: 22
                  nameLocation: center
                  weekdayFormat: short
            yAxis:
              - component: oh-value-axis
                config:
                  axisLabel:
                    formatter: "{value} kWh"
                  gridIndex: 0
                  nameGap: 40
                  nameLocation: center
              - component: oh-value-axis
                config:
                  axisLabel:
                    formatter: "{value} °C"
                  gridIndex: 0
                  nameGap: 40
                  nameLocation: center
                  scale: true
        - component: oh-chart
          config:
            chartType: year
            height: 100%
            options:
              backgroundColor: transparent
            periodVisible: true
            sidebar: false
            visible: "(=vars.varPeriod == 'year' || vars.varPeriod == undefined) ? true : false"
          slots:
            calendar: []
            grid:
              - component: oh-chart-grid
                config:
                  height: 70%
                  includeLabels: true
                  left: 75
                  right: 75
                  show: false
                  top: 70
            legend:
              - component: oh-chart-legend
                config:
                  bottom: 25px
                  left: 25
                  orient: horizontal
                  show: true
                  width: 600
            series:
              - component: oh-aggregate-series
                config:
                  aggregationFunction: average
                  color: yellow
                  dimension1: month
                  gridIndex: 0
                  item: =props.prop_itemVerbrauchJahr
                  lineStyle:
                    width: 4
                  markLine:
                    data:
                      - label:
                          backgroundColor: yellow
                          formatter: "{c} kWh"
                          padding: 2
                          position: middle
                          shom: true
                        symbol: none
                        type: average
                  name: Jahr-3
                  noBoundary: true
                  offsetAmount: 3
                  offsetUnit: year
                  service: inmemory
                  step: middle
                  type: line
                  xAxisIndex: 0
                  yAxisIndex: 0
              - component: oh-aggregate-series
                config:
                  aggregationFunction: average
                  color: "#007AFF"
                  dimension1: month
                  gridIndex: 0
                  item: =props.prop_itemVerbrauchJahr
                  lineStyle:
                    width: 4
                  markLine:
                    data:
                      - label:
                          backgroundColor: "#007AFF"
                          formatter: "{c} kWh"
                          padding: 2
                          position: start
                          shom: true
                        symbol: none
                        type: average
                  name: Jahr-2
                  noBoundary: true
                  offsetAmount: 2
                  offsetUnit: year
                  service: inmemory
                  step: middle
                  type: line
                  xAxisIndex: 0
                  yAxisIndex: 0
              - component: oh-aggregate-series
                config:
                  aggregationFunction: average
                  color: "#009688"
                  dimension1: month
                  gridIndex: 0
                  item: =props.prop_itemVerbrauchJahr
                  lineStyle:
                    width: 4
                  markLine:
                    data:
                      - label:
                          backgroundColor: "#009688"
                          formatter: "{c} kWh"
                          padding: 2
                          position: middle
                          shom: true
                        symbol: none
                        type: average
                  name: Jahr-1
                  noBoundary: true
                  offsetAmount: 1
                  offsetUnit: year
                  service: inmemory
                  step: middle
                  type: line
                  xAxisIndex: 0
                  yAxisIndex: 0
              - component: oh-aggregate-series
                config:
                  aggregationFunction: average
                  color: red
                  dimension1: month
                  gridIndex: 0
                  id: 0
                  item: =props.prop_itemVerbrauchJahr
                  markLine:
                    data:
                      - label:
                          backgroundColor: red
                          formatter: "{c} kWh"
                          padding: 2
                          shom: true
                        symbol: circle
                        type: average
                  name: Jahr
                  noBoundary: true
                  service: inmemory
                  type: bar
                  xAxisIndex: 0
                  yAxisIndex: 0
              - component: oh-aggregate-series
                config:
                  aggregationFunction: average
                  color: red
                  dimension1: month
                  gridIndex: 0
                  item: =props.prop_itemkWh20xxMonatserwartung
                  lineStyle:
                    width: 2
                  markPoint:
                    data:
                      - name: max
                        type: max
                  name: Monatserwartung
                  noBoundary: true
                  service: inmemory
                  symbol: arrow
                  symbolSize: 20
                  type: line
                  xAxisIndex: 0
                  yAxisIndex: 0
              - component: oh-aggregate-series
                config:
                  aggregationFunction: average
                  color: red
                  dimension1: month
                  gridIndex: 0
                  item: =props.prop_itemkWh20xxMonatsdurchschnitt
                  lineStyle:
                    width: 2
                  markLine:
                    data:
                      - label:
                          backgroundColor: red
                          formatter: "{c} kWh"
                          padding: 2
                          shom: true
                        symbol: circle
                        type: average
                  name: Monat-Ø
                  noBoundary: true
                  service: inmemory
                  type: line
                  xAxisIndex: 0
                  yAxisIndex: 0
            title:
              - component: oh-chart-title
                config:
                  left: 170px
                  show: true
                  subtext: "2023: 5664 kWh  -  2024: 5614 kWh"
                  top: 0
            toolbox:
              - component: oh-chart-toolbox
                config:
                  left: 10
                  presetFeatures:
                    - restore
                    - dataView
                    - magicType
                  show: true
                  top: 8
            tooltip:
              - component: oh-chart-tooltip
                config:
                  confine: true
                  show: true
                  trigger: axis
            xAxis:
              - component: oh-category-axis
                config:
                  categoryType: year
                  gridIndex: 0
                  monthFormat: short
                  nameGap: 20
                  nameLocation: center
            yAxis:
              - component: oh-value-axis
                config:
                  axisLabel:
                    formatter: "{value} kWh"
                  gridIndex: 0
                  nameGap: 30
                  nameLocation: center
              - component: oh-value-axis
                config:
                  axisLabel:
                    formatter: "{value} °C"
                  gridIndex: 0
                  nameGap: 40
                  nameLocation: center
                  scale: true

As far as I remember it was working in Openhab 5.1.x.

Please help to find the error.

And a fix is on the way: Charts: Fix oh-aggregate-series offset (comparison) series being empty by Ltty · Pull Request #4452 · openhab/openhab-webui · GitHub

After having upgraded my OH 5.1.4 on Docker to 5.2.1 the Java heap memory seems to keep stable in a normal range. Before I always had a system hang up after several days or needed to restart manually.

Thank you for that stabilization!:+1:

Regards Christoph

I was able to get better memory usage and performance by switching from Temurin to to Openjdk when I updated from Debian 12 to 13. Not sure what the container uses but the jdk/jre may matter.

I only updated the version. Don’t know what changed inside the docker image.

just upgraded from 4.3 to 5.2.1:

  • One of the smoothest upgrades I’ve ever had (just one reboot)
  • UI feels a lot snappier
  • some Rules react a lot faster

Thanks to everyone involved :folded_hands:.

Great work. openHAB is awesome.