openHAB 5.2 Release discussion

Hi!

I used to get the triggering member in a (JS) rule triggered by a GroupStateUpdatedEvent using

var triggeringItemName = event.raw.event.getMemberName();

After updating to 5.2.1 (not sure if it also happened in 5.2.0) I noticed these errors in the logs:

TypeError: undefined has no such function "getMemberName"

Apparently event.raw.event is undefined so I printed the raw event:

{6.lastStateUpdate=2026-08-05T22:06:17.548653797+02:00[Europe/Amsterdam], ruleUID=8b438a4d8c, 6.state=OFF, 6.event=Group 'Residents_present' updated to OFF through Tom_present}

And I noticed that lastStateUpdate, state and event have ‘6.’ in front of them, so I changed my rule to

var triggeringItemName = event.raw['6.event'].getMemberName()

And it started working again.

Is this expected behavior? I couldn’t find anything about it

Hi,
I’m not familiar with the ‘GroupStateUpdatedEvent’ trigger—perhaps because I haven’t looked into event.raw.event yet.

In Javascipt I use the trigger:
triggers.GroupStateUpdateTrigger('<Groupname>')

I get the name of the triggering item using:
var triggeringItemName = event.itemname;

The triggers and possible event elements are described here: JavaScript Scripting - Automation | openHAB

Thank you for pointing that out! In my rule config I had this group configured as an Item, not as a group!

My (stripped down) rule:

version: 1
rules:
  "8b438a4d8c":
    label: Alarmclock - Android
    actions:
      - id: "2"
        config:
          type: JavaScript
          script: "// see next JS block for readability"
        type: Script
    triggers:

      - id: "6"
        config:
          itemName: Residents_present
        type: ItemUpdated
      




switch(event.eventName){
  case 'ExecutionEvent':
  case 'StartlevelEvent':
    /* snip */
    break;
  case 'TimerEvent':
    /* snip */
    break;
  case 'ItemStateUpdatedEvent':
    /* snip */
    break;
  case 'GroupItemStateChangedEvent': 
    /* snip */
    break;
  case 'GroupStateUpdatedEvent':
    switch(event.itemName.toString()){
      case 'Residents_present':
        try {
          //var triggeringItemName = event.raw.event.getMemberName();
          var triggeringItemName = event.raw['6.event'].getMemberName();
        } catch(e) {
          console.error(e + ' event was: ' + event.raw);
          console.error(e + ' event was: ' + event.raw['6.event'].getMemberName());
        }
        /* snip */
        break;
    }
    break;
  case 'ItemCommandEvent':
    /* snip */
    break;
  default:
    console.log('Unhandled event type: ' + event.eventName);
    break;
}

I will test changing type “ItemUpdated” to ‘MemberUpdated’ And I probably have to change the switch to event.groupname.

[edit]

“the state of a member of an item group is updated”, “This triggers the rule if the state of a member of an item group is updated (even if it does not change).” doesnt seem to trigger on a group of groups. :frowning:

I upgraded to 5.2.1 and am getting a VUE error in one of the Custom widgets i created (and use in quite a few places)

Openhabian : RPI 5 8Gb

Browser Safari and Chrome

the widget displays Blank - was working on 5.1.3

basically it graphs items tagged with the text from the groupTag property and draws a Bar Graph like this)

here is the Widget

version: 1
widgets:
  chart_bar_energy_dynamic:
    tags:
      - KnownConsumer
      - Version:4.1
      - chart
    props:
      parameters:
        - default: Known Consumers
          description: the title for the group
          label: title
          name: title
          required: false
          type: TEXT
        - default: KnownConsumer
          description: the tag for the group
          label: groupTag
          name: groupTag
          required: false
          type: TEXT
        - default: 75%
          description: the vertical position of the chart
          label: chartPosV
          name: chartPosV
          required: false
          type: TEXT
        - default: bar
          description: the type of the chart
          label: chartType
          name: chartType
          required: false
          type: TEXT
          pattern: pie|bar
          options:
            - label: Pie Chart
              value: pie
            - label: Bar Chart
              value: bar
        - default: auto
          description: the height of the chart
          label: chartHeight
          name: chartHeight
          required: false
          type: TEXT
        - default: auto
          description: the Width of the chart
          label: chartWidth
          name: chartWidth
          required: false
          type: TEXT
        - default: auto
          description: the barWidth
          label: barWidth
          name: barWidth
          required: false
        - default: auto
          description: Maximum of y Axis
          label: yMax
          name: yMax
          required: false
        - default: "0"
          description: Minimum of y Axis
          label: yMin
          name: yMin
          required: false
        - default: "-1"
          description: the minimim amount for an item to be included
          label: filterItem
          name: filterItem
          required: false
          type: TEXT
        - default: true
          description: show/Hide Legend
          label: showLegend
          name: showLegend
          required: false
          type: BOOLEAN
        - default: true
          description: show/Hide Legend
          label: showTooltip
          name: showTooltip
          required: false
          type: BOOLEAN
        - default: true
          description: show/Hide minorTick
          label: minorTick
          name: minorTick
          required: false
          type: BOOLEAN
      parameterGroups: []
    component: f7-card
    config:
      style:
        background: =props.background || '#fff'
        border: "=props.border || '1px solid #ccc'"
        border-radius: 8px
        paddingX: 0px
        position: relative
        text-align: center
      titleX: =props.title || ''
    slots:
      content:
        - component: oh-repeater
          config:
            for: energyData
            fragment: true
            itemTags: =props.groupTag
            map: |
              loop.energyData_source
              .filter(item => items[item.name].numericState > props.filterItem)
              .map(item => ({
                value: items[item.name].numericState,
                name: item.label,
                tooltip: items[item.name].displayState
              }))
            sourceType: itemsWithTags
            title: test
          slots:
            default:
              - component: oh-chart-legend
                config:
                  bottom: center
                  data: =loop.energyData.map(d => d.name)
                  left: center
                  orient: horizontal
                  show: true
                  typeX: scroll
              - component: oh-chart
                config:
                  legend:
                    left: left
                    orient: vertical
                    show: true
                  options:
                    color:
                      - "#f28b82"
                      - "#81c995"
                      - "#a7c7e7"
                      - "#fbc687"
                      - "#c9a0dc"
                      - "#9de0e6"
                      - "#f6a3d7"
                      - "#dce775"
                      - "#ffcccb"
                      - "#80cbc4"
                  visible: =loop.energyData_idx == 0
                slots:
                  legend:
                    - component: oh-chart-legend
                      config:
                        data: =loop.energyData.map(d => d.name)
                        left: 5px
                        orient: horizontal
                        show: =Boolean(props.showLegend)
                        top: 0
                        typeX: scroll
                  legendx:
                    - component: oh-chart-legend
                      config:
                        bottom: 0
                        data: =loop.energyData.map(d => d.name)
                        left: center
                        orient: horizontal
                        show: true
                        type: scroll
                  series:
                    - component: oh-data-series
                      config:
                        barWidth: =props.barWidth
                        centerX:
                          - 50%
                          - =props.chartPosV
                        colorBy: data
                        data: =loop.energyData
                        endAngleX: 360
                        height: =props.chartHeight
                        itemStyleX:
                          borderRadius: 5
                        label:
                          formatter: = (params) => `${params.data.tooltip}`
                          show: =props.showTooltip
                        labelLayoutX:
                          moveOverlap: shiftY
                          x: 131,
                        labelLine:
                          show: =props.showTooltip
                        legend:
                          show: true
                          visibile: true
                        padAngleX: 5
                        radiusX:
                          - 40%
                          - 70%
                        roseTypeX: radius
                        startAngleX: =props.startAngle
                        type: =props.chartType
                        width: =props.chartWidth
                  tooltip:
                    - component: oh-chart-tooltip
                      config:
                        orient: vertical
                        show: true
                        trigger: axis
                  xAxis:
                    - component: oh-category-axis
                      config:
                        axisLabel:
                          color: black
                          rotate: 45
                          show: true
                        axisLine:
                          show: true
                        axisPointer:
                          show: true
                        axisTick:
                          interval: 1
                          lineStyle:
                            opacity: 1
                          show: false
                        data: =loop.energyData.map(d => d.name)
                        gridIndex: 0
                        show: true
                  yAxis:
                    - component: oh-value-axis
                      config:
                        axisLabel:
                          align: right
                          margin: 23
                          show: true
                          verticalAlign: bottom
                        axisLine:
                          onZero: true
                          show: true
                        axisTick:
                          length: 40
                        gridIndex: 0
                        inverse: false
                        max: =props.yMax
                        min: =props.yMin
                        minorTick:
                          length: 20
                          show: =props.minorTick
                        offset: 0
                        scale: false
                        show: true
                        splitNumber: 10
                        startValue: 0

here is the events from the Web Inspector for Safari

TypeError: undefined is not an object (evaluating 'n3.getCoordSysModel().coordinateSystem')
(anonymous function) — install-DjaDxCMg.js:1888
(anonymous function) — dist-BwcFgzK9.js:6991
forEach
I — dist-BwcFgzK9.js:154
(anonymous function) — dist-BwcFgzK9.js:6989
(anonymous function) — install-DjaDxCMg.js:1885
(anonymous function) — dist-BwcFgzK9.js:7056
I — dist-BwcFgzK9.js:156
(anonymous function) — dist-BwcFgzK9.js:7055
update — dist-BwcFgzK9.js:9984:97
(anonymous function) — dist-BwcFgzK9.js:9717
(anonymous function) — dist-BwcFgzK9.js:16246
In — vue.runtime.esm-bundler-BusZxOMj.js:914
z — vue.runtime.esm-bundler-BusZxOMj.js:921
w2 — vue.runtime.esm-bundler-BusZxOMj.js:873
Xn — vue.runtime.esm-bundler-BusZxOMj.js:984
oe2 — vue.runtime.esm-bundler-BusZxOMj.js:2563:96
s3 — vue.runtime.esm-bundler-BusZxOMj.js:2533
run — vue.runtime.esm-bundler-BusZxOMj.js:191
j2 — vue.runtime.esm-bundler-BusZxOMj.js:2515
ne2 — vue.runtime.esm-bundler-BusZxOMj.js:2501:136
v2 — vue.runtime.esm-bundler-BusZxOMj.js:2408
k2 — vue.runtime.esm-bundler-BusZxOMj.js:2485
ee2 — vue.runtime.esm-bundler-BusZxOMj.js:2468:246
w2 — vue.runtime.esm-bundler-BusZxOMj.js:2434
v2 — vue.runtime.esm-bundler-BusZxOMj.js:2408
s3 — vue.runtime.esm-bundler-BusZxOMj.js:2535
run — vue.runtime.esm-bundler-BusZxOMj.js:191
runIfDirty — vue.runtime.esm-bundler-BusZxOMj.js:206
In — vue.runtime.esm-bundler-BusZxOMj.js:914
$n — vue.runtime.esm-bundler-BusZxOMj.js:1007

This also needs to be done on most of the other classes in OHRT (e.g. Gatekeeper, LoopingTimer, etc.) so I would ideally likely to find a way to implement this once, perhaps in utils.newTimer() or some other utils function.

But this discussion needs to me moved over to another thread and/or an issue on the OHRT repo (GitHub - rkoshak/openhab-rules-tools: Library functions, classes, and examples to reuse in the development of new Rules. · GitHub).

I’m a little cautious about key collisions in the shared cache but there are ways we can deal with that.

Another approach would be to rebuild the Object on the other side (i.e. new TimerMgr(cache.shared.get(‘myTimer’)) which recognizes that it’s been javafied and rebuilds the Object using the data in the cached Object. But that imposes extra work on the end user.

Indeed, that has always been the case. That’s why in some of the rules languages there is support for a “DescendentItemStateUpdated” which includes the members of subgroups. JS Scripting only supports the core sert of triggers though. You’ll need to create a separate trigger for each subgroup or create a Group with all the Items as a member instead of subgroups.

Ah I didn’t know :slight_smile: anyway, triggering on an ItemUpdated event linked to a group still works and it shows up as a GroupStateUpdatedEvent. The only different thing is event.raw['6.event] instead of event.raw.event since updating. My code/rule works as intended I just have a feeling the 6. is not supposed to be there?

@florian-h05 - apologies for tagging you but let me know if I must create an issue

I saw this in your widget:

Shouldn’t it say visible: true ?

hi @uk59821 yes thanks for picking that up - I changed this now but no effect (and it was working under 5.1.3 (I beleive the default is true anyway- so this would have been ignored ) and that was only for the legend: so really did not make an impact its still blank

Your widget breaking might either be a consequence of more strict validation, however it won’t harm to have a look at it in the dev server with a proper stack trace. Probably create an issue and note in the title that a custom widget broke.

Thanks, i have done so, Custom Widget for a bar chart only displays a blank screen after upgrade to 5.2.1 · Issue #4441 · openhab/openhab-webui · GitHub

That might indeed be the case here.
When the TimerMgr instance gets put into the shared cache, is should get javaified automatically. I wonder a bit that the code doesn’t throw an error at that point because it should reject javaifying functions 

Anyway, passing false as third parameter when putting something into the shared cache will disable the automatic javaify. Similarly, for get, you can provide a third param false to disable automatic jsify.

Yes, it is. openHAB 5.2 reverts a change that removed the (numeric) prefixes in the first place. Probably this should have been noted as a breaking change.

That triggers the rule when the state of the Group Item itself is updated. It will only work with Group Items that have a type and a function.

But the event won’t tell you which Item that’s a member of the Group caused the update. event.itemName will be there name of the Group Item.

Normally you shouldn’t be using event.raw in the first place. Just about everything you could possible need from the event is part of event itself. See JavaScript Scripting - Automation | openHAB. Every piece of information that is carried by every type of trigger is broken out and converted to a JS friendly format for you.

The only reason I can think of to use event.raw is if you are using a GenericTrigger, which is a very advanced trigger which requires deep knowledge of the event bus and how to parse out the raw payload.

So if you need to change your rules anyway consider updating them to use the already parsed out fields instead.

But then if it’s indeed used by different rules the user is back to potentially getting multi-threaded exceptions, right? I still think I should try to fix this in the library so they work with javaify and jsify.

But I didn’t know about the third option which is good to know. I’ve one rule that used to throw a warning because I was using the shared cache to share a value between the condition and the action. I need to test that rule and potentially use that third parameter. It’s all the same rule so there is no chance of a multi-threaded problem.

Yes. Fixing it in the library would be preferable then.
I think there might be not a lot of concurrency in that specific case so it worked fine without running into multi threaded access exceptions.

It’s not in the README, only in the JSDoc. We should probably add it to the README, and also document javaify and jsify there.

I think the memberName might be missing, have to check that.

I agree! but I couldn’t find any other way to accomplish what I have now. Since a group of groups trigger isn’t supported and imho creating separate triggers for every group member defeats the purpose of a group. (I also use “dynamic” groups elsewhere). For now my solution works and I’m aware that it is unsupported and might break with the next update.

      console.log(event.memberName);

outputs ‘undefined’ on a group assigned to a itemtrigger.

My problem is the “reloadAllModelsOfType” routine gets executed on every change of an item file. Many rules are then blocked for several minutes and items gets timed-out.

I discussed my problem here https://community.openhab.org/t/excessive-recompiling-on-almost-every-touch-of-item-and-sometimes-rules/169997/20

My question. Is this itented behaviour or do I have somewhere have a configurationproblem in my DSL rules or items.

What can I do about it.

Running OH5.2 on a Windows machine.

For me the maximum number of decimal places in an oh-time-series chart is not taken into account for values greater than 3. When setting the parameter to 4 only three digits are shown.

version: 1
pages:
  electricityForecastPricePerUnit:
    tags:
      - Preis
      - Strom
      - Vorhersge
    props:
      parameters: []
      parameterGroups: []
    component: oh-chart-page
    config:
      formatterMaxDecimalPlaces: 4
      future: 0.75
      label: Strompreis - Vorhersage
      period: 12h
    slots:
      series:
        - component: oh-time-series
          config:
            ...

When using a custom formatter for labels and tooltips the fourth digits are always zero.

This appears to be the behavior that has always been in place. There used to be technical reasons see below why this was necessary but this behavior has been in place since OH 1.4 at least. I don’t know if that’s evidence for or against it being the intended behavior but there used to be enough problems with this behavior on RPi 2s back then (which were the minimum supported hardware) that people complained about it and tried all sorts of workarounds (no of which would apply to this specific problem). I imagine if it could easily be changed it would have been changed back then.

  • Run on different hardware with a better CPU.
  • Try using YAML or managed rules which do not appear to have this behavior (though I could be wrong).
  • Use a language other than Rules DSL, all of which are much more efficient when loaded and parsed.
  • File an issue and hope it gets changed.

IIRC, the technical reason why all the rules need to be reloaded is as follows.

When any .items file is modified, every Item defined in that file get deleted and recreated anew. (Note this is true for all DSL files as I understand it).

When an Item is deleted and created anew it exists as a new Object in OH.

The Items you can so conveniently reference by name in Rules DSL (e.g. MyItem.sendCommand(ON)) get injected into the rule at load time.

Therefore, if the rules were not reloaded, the Objects injected into your rules become stale and disconnected from the new Object. I think you can still send commands and post updates, but that stale Object will not be receiving updates. You can’t call MyObject.state and get the most recent state.

OH has no knowledge as to which Items are references in the code of which rules. Often it cannot know this information (a simple search is not sufficient). So to make sure no Item becomes stale in any rule, all rules must be reloaded.

I believe the other rules languages do not have this problem because they access the Items through the Item registry. They pull the Items on demand instead of having them injected at load time.

But I don’t know if that means they are not reloaded the same as DSL rules. Generally, the other languages, particularly JS, jRuby, and Python are much more efficient in loading and parsing even on low powered hardware.

Thank You Rich for the clarification. I understand now the reason for DSL recompile.

The thing that bothers me though is I never had real problems with this issue. Since 5.2 this seems to be introduced. There must be an explanation for this.

I don’t like the idea to solve software issues with more powerfull hardware. Thats why I like to know the reason of this new behavior.

Someone can look through the PRs on Rules DSL. A number of changes were made to what is available in rules, bringing Rules DSL much closer to parity with what the other rules languages allow (e.g. access to Item metadata just to name one). Perhaps that was the straw that broke the camel’s back for your machine. Or some other change is making parsing Rules DSL just that much harder for your CPU to handle. Someone would have to hook a profiler up to OH and figure out where the bottleneck is.

Loading all the rules on changes to .items files has always been there so that has always been happening and nothing new.

I suspect using YAML instead of .rules files might help. Even if the script actions remain Rules DSL, there will be about 10-15% reduction in the amount of Rules DSL code to parse which might put you back under the threshold that causes the problem. But I can’t say for sure.