My Custom Widgets causing Warnings

Hi,

when using MainUI with my android app I get warnings in the logs when calling certain pages which use custom widgets with generated Item names.

This is one of the warnings from the logs:

[WARN ] [e.internal.SseItemStateEventBuilder] - Attempting to send a state update of an item which doesn't exist: Light-Color

which is right in some kind of way…

Because they don’t exist in the way they’re searched:

Light-Color, Light-Switch

the item names are created by the widget like “PrefixRoomSuffix” e.g. LightBedroomColor or similar…

my widgets yaml code often does something like:

actionItem: =(props.prefix+items[props.selected].state+props.suffix2)

my props.selected definition looks like this:

    - context: item
      description: Item for Room
      label: Room Item
      name: selected
      required: true
      type: TEXT

but while my widgets are running without errors, I keep getting this warnings in my logs…

any ideas how to prevent this? for me it seems openhab is struggling to get the selected roomname or playername or similar referred by the props.selected name?!?

Don’t get me wrong, it’s not a big problem to me, but I would like to avoid that from happening :wink:

If any further info is needed I hope I can provide it :wink:

Try something like this:

actionitem: =(props.selected)?(props.prefix+items[props.selected].state+props.suffix2):““

Might contain typo as I cannot test

thanks a lot for your support Oliver :wink:

I changed my code and added (props.selected)? but this does not stop the warnings…

so I changed it back…

edit: I tried this a second time - now its functioning… maybe a typo on my side :flushed:

Oh nooo…

this seemed to remove the warnings, but I had very strange behavior and had to remove it…

If I add this like you mentioned it breaks the usage of the combined itemname creation I use.
The items aren’t found after using your code…

Then please provide more Information so that we understand, what is happening behind the scenes so that wie can find the appropriate code or solution

this is my complete widget code (one of them)…

uid: LightControl
tags:
  - card
props:
  parameters:
    - description: Title for the widget
      label: Static Title
      name: title
      required: false
      type: TEXT
    - context: item
      description: Item for gLights
      label: gLights Item
      name: g_lights
      required: true
      type: TEXT
    - context: item
      description: Item for Ceiling White
      label: Ceiling White Item
      name: ceiling_white
      required: true
      type: TEXT
    - context: item
      description: Item for LightScene
      label: LightScene Item
      name: lightscene
      required: true
      type: TEXT
    - description: LightScene Options to select from (comma seperated)
      label: LightScene Action Options
      name: lightsceneoptions
      required: true
      type: TEXT
    - context: item
      description: Item for Room
      label: Room Item
      name: selected
      required: true
      type: TEXT
    - description: Room Options to select from (comma seperated)
      label: Room Action Options
      name: roomoptions
      required: true
      type: TEXT
    - description: Prefix
      label: Room Prefix
      name: prefix
      required: true
      type: TEXT
    - description: Suffix 1
      label: Room Suffix 1
      name: suffix1
      required: true
      type: TEXT
    - description: Suffix 2
      label: Room Suffix 2
      name: suffix2
      required: true
      type: TEXT
  parameterGroups: []
timestamp: Oct 7, 2024, 3:33:42 PM
component: f7-card
config:
  style:
    max-width: 640px
    padding: 1em
slots:
  default:
    - component: f7-row
      slots:
        default:
          - component: f7-col
            slots:
              default:
                - component: oh-knob-cell
                  config:
                    action: toggle
                    actionCommand: ON
                    actionCommandAlt: OFF
                    actionItem: =props.g_lights
                    color: "=(items[props.g_lights].state === 'ON') ? 'yellow' : 'black'"
                    commandInterval: 500
                    expandable: false
                    footer: "=(items[props.g_lights].state === 'OFF') ? 'OFF' : 'ON'"
                    icon: "=(items[props.g_lights].state === 'OFF') ? 'f7:lightbulb_slash' :
                      'f7:lightbulb_fill'"
                    iconColor: "=(items[props.g_lights].state === 'ON') ? 'yellow' : 'red'"
                    on: (items[props.g_lights].state === 'ON')
                    releaseOnly: true
                    responsive: true
                    title: All Lights
    - component: f7-row
      slots:
        default:
          - component: f7-col
            slots:
              default:
                - component: oh-knob-cell
                  config:
                    action: options
                    actionItem: =props.lightscene
                    actionOptions: =props.lightsceneoptions
                    color: "=(items[props.lightscene].state !== 'OFF') ? 'black' : 'gray'"
                    expandable: false
                    footer: =items[props.lightscene].state
                    icon: iconify:mdi:lamps
                    iconColor: "=(items[props.lightscene].state !== 'OFF') ? 'yellow' : 'black'"
                    on: (items[props.lightscene].state !== 'OFF')
                    responsive: true
                    title: Light Scene
          - component: f7-col
            slots:
              default:
                - component: oh-knob-cell
                  config:
                    action: toggle
                    actionCommand: ON
                    actionCommandAlt: OFF
                    actionItem: =props.ceiling_white
                    color: "=(items[props.ceiling_white].state !== 'ON') ? 'black' : 'yellow'"
                    expandable: false
                    footer: "=(items[props.ceiling_white].state === 'OFF') ? 'LIGHT SCENE' :
                      'WHITE'"
                    icon: "=(items[props.ceiling_white].state === 'OFF') ?
                      'iconify:mdi:ceiling-light-outline' :
                      'iconify:mdi:ceiling-light'"
                    iconColor: "=(items[props.ceiling_white].state !== 'OFF') ? 'yellow' : 'gray'"
                    on: (items[props.ceiling_white].state !== 'OFF')
                    responsive: true
                    title: Ceiling Light
    - component: f7-row
      slots:
        default:
          - component: f7-col
            slots:
              default:
                - component: oh-knob-cell
                  config:
                    action: options
                    actionFeedback: =items[props.selected].state
                    actionItem: =props.selected
                    actionOptions: =props.roomoptions
                    color: "=(items[props.selected].state !== 'OFF') ? 'black' : 'gray'"
                    expandable: false
                    footer: =items[props.selected].state
                    icon: iconify:mdi:house
                    iconColor: "=(items[props.selected].state !== 'OFF') ? 'yellow' : 'black'"
                    on: (items[props.selected].state !== 'OFF')
                    responsive: true
                    title: Selected Room
    - component: f7-row
      config:
        style:
          max-height: 200px
      slots:
        default:
          - component: f7-col
            config:
              style:
                width: 50%
            slots:
              default:
                - component: oh-colorpicker-card
                  config:
                    item: =props.prefix+items[props.selected].state+props.suffix1
                    modules:
                      - wheel
                    noshadow: false
                    outline: false
                    title: =items[props.selected].state+" Ceiling"
          - component: f7-col
            config:
              style:
                width: 50%
            slots:
              default:
                - component: oh-knob-cell
                  config:
                    action: toggle
                    actionCommand: ON
                    actionCommandAlt: OFF
                    actionItem: =props.prefix+items[props.selected].state+props.suffix2
                    color: black
                    commandInterval: 500
                    expandable: false
                    footer: "=(items[(props.prefix+items[props.selected].state+props.suffix2)].state
                      === 'OFF') ? 'OFF' : 'ON'"
                    icon: "=(items[(props.prefix+items[props.selected].state+props.suffix2)].state
                      === 'OFF') ? 'f7:lightbulb_slash' : 'f7:lightbulb_fill'"
                    iconColor: "=(items[(props.prefix+items[props.selected].state+props.suffix2)].s\
                      tate === 'ON') ? 'yellow' : 'gray'"
                    releaseOnly: true
                    responsive: true
                    style:
                      padding: 30px
                    title: Power
    - component: f7-row
      config: {}
      slots:
        default:
          - component: f7-col
            config: {}
            slots:
              default:
                - component: oh-knob-cell
                  config:
                    action: group
                    actionGroupPopupItem: ="g"+items[props.selected].state+"Lights"
                    actionItem: =props.selected
                    color: black
                    expandable: false
                    icon: iconify:mdi:ceiling-light-multiple
                    iconColor: yellow
                    item: ="g"+items[props.selected].state+"Lights"
                    responsive: true
                    title: ="Additional "+items[props.selected].state+" Lights"

when I change it to your code, my android app throws an error when trying to use the “Power Button”

i’ve made a screenshot:

I only changed this part:

...
                    actionItem: =(props.prefix+items[props.selected].state+props.suffix2)
...
                    title: Power

You are right. In fact it’s not a problem at all which is why it is given a WARN level and not an ERROR level. That said, I agree if it happens frequently it can make sifting through logs for actual information more difficult.

If you take a look at the warning, however, there’s a clue how to fix it:

[WARN ] ... an item which doesn't exist: Light-Color

Your naming scheme doesn’t include a - in it anywhere, so that part is what’s being added by your expression. That is consistent with the way the items object works in the widget expressions. items is not just a simple dictionary returning values when they exist and undefined when they don’t. Any time items would return an undefined or null (js not OH ‘NULL’ state) it returns - instead. So when you see Light-Color in the warning that means items[props.selected] is not returning a state that you expect.

So, you still want to test for a value before creating the item name string in your expression, but you are not testing whether props.selected exists, you want to test whether items[props.selected].state returns an actual value or -:

actionItem: =(items[props.selected].state != '-')?(props.prefix+items[props.selected].state+props.suffix2):('')

In the long run, however, since props.selected is a value that you control (i.e., have manually configured) you should also try to work out why this item, if it exists at all, is giving some invalid state response. The test solution above effectively masks the problem, but it would be even better for page loading speeds and long term stability to avoid the situation entirely, if possible.

Hi Justin,

thanks for the detailed review!

I think I understood all of this - my problem is that props.selected is bound to a valid string-item with a valid text-string in it which represents the room. The widget is working so far… but I don’t really get why js can’t get the state of a valid item.

Your fix (and the previous from Oliver) are adressing the problem when the props item is empty - but that seems always the case although it is not… and I can’t understand why…

but I will try what changes if I try your fix for the “-”…

edit:
ok I tried your code, but the warnings still appear, after using your code it seems they are only shown once not everytime I enter the widgets page… but after closing and restarting the android app the warnings reappear!??

even if this don’t fixes the problem completely it reduces the amount of appearances in the logs a lot :wink:

I can think of a few possibilities here:

  1. This assumption: “a valid string-item with a valid text-string in it which represents the room” The existence of this item is less likely to be an issue unless you are doing something strange with dynamically created items, so the assumption that the item state always contains the name of a valid item should be looked into. How is this item set? Do you persist the value of this item? If you do persist it, is it restored on startup?

  2. The exact same warning is produced no matter what widget encounters the warning. Are there any other widgets that might also check an items with the prefix + suffix pattern? If so, you need to change those widget expressions as well. Are you sure it is the same warning and not a warning about some other item that cannot be found? It can sometimes be pretty difficult to track down all the places where a such a non-existent item call can be made.

The fact the you see the pattern where the warning appears when you start the android app leads me to think the issue is more liekly to be #2.

Not sure if this might help

actionitem: =(props.prefix+items[props.selected].state+props.suffix2) || ""

another try

actionitem: =(items[props.selected])?(props.prefix+items[props.selected].state+props.suffix2):""

If the Item wouldn’t be present all the time my widget would fail regularly which isn’t the case. But everything is working fine all the time except from the warnings… so for me it seems OH can handle the combined items but js is missing the middle part… I don’t really understand how this can be…

All my items are persisted on change with influxDB and on startup mapDB is used

Yes I have this in mind… the warning is always the same, the variable part is replaced with a “-”
and prefix and suffix varies…

edit:
thanks Oliver you answered while I was answering Justin’s post :sweat_smile:

I will have a look at your new code…

thanks a ton to both of you!