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() ![]()
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 ![]()
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.
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
.
Great work. openHAB is awesome.



