StateDisplay MAP not working for some items

Hi all. I have an issue with OH3 MAP transformations I don’t really understand…

I have a bunch of thermostats from different manufacturers which report different strings for their current operation mode. To be able to use them with the dynamic heater control icon, I convert them to percent numbers as following:

String TSOG1Kuche_ModusdesHeizkorperreglers "TS OG1 Küche Modus" <Heating> ( TSOG1Kuche ) [ "Status", "Temperature" ] {
    channel="avmfritz:FRITZ_DECT_301:192_168_100_1:099950441610:radiator_mode" [
      function="thermostat_modus_itemlink.map",
      profile="transform:MAP"
    ],
    listWidget="widget:ts_temperaturemode",
    stateDescription=" " [
      pattern="MAP(thermostat_modus_widget.map):%s"
    ]
}

String TSOG1WC_CurrentHeatingMode "TS OG1 WC Modus" <heating> ( TSOG1WC ) [ "Status", "Temperature" ] {
    channel="somfytahoma:valveheatingsystem:5c9e9e2952:ede130d7-5912-482f-9f4b-ff9f4bc0ebae:current_heating_mode" [
      function="thermostat_modus_itemlink.map",
      profile="transform:MAP"
    ],
    listWidget="widget:ts_temperaturemode",
    stateDescription=" " [
      pattern="MAP(thermostat_modus_widget.map):%s"
    ]
}

The thermostat_modus_itemlink.map defines the numbers that each operating mode should represent:

! AVM thermostats
OFF=0
BOOST=100
COMFORT=100
ECO=40
WINDOW_OPEN=40
ON=100
! somfy thermostats
frostprotection=0
away=40
eco=70
comfort=100

This part works fine, all thermostats show up with a number instead of a string for their operation mode.

For convenient state reading, I apply another MAP transformation for the StateDescription:

0=Aus
40=Spar
70=Eco
100=An

For the somfy thermostat, this works in the UI, state is “Aus”:
grafik

But for the AVM thermostats (all of them), it shows “undefined”:
grafik

In the item popup, it shows “0” as operation mode and the correct icon:
grafik

I don’t understand why it is working for somfy, but not for AVM. Why do the AVM thermostats show “undefined”? Both use the same 2 transforms and the same widget…

I already did about 2 hours of research, but could not find any clue.

Big thanks in advance for any insight :ok_hand:

BTW: The different map files for the channel link and the state description are a result of some of my trials to fix this. Both were one file at the beginning, when I suspected the MAP may be confused if it finds its target result as a source in the map also. But didn’t help obviously.

Maybe add for testing a default value to your map, to see if the issue is really based on the map transformation or maybe more related to your widget itself and you are searching the issue at the wrong place

Did so - added “=DoesnotworkChannel” to the first map, “=DoesnotworkStatus” to the second map. Still shows up as “undefined” :frowning: It is an issue with the StateDisplay map, but what exactly? As said, all thermostats use the same map and the same widget.

If it’s still showing undefined my understanding is, that the issue is with the widget or the configuration of the widget. If you would completely remove the map you should still get the undefined issue.

Maybe there is a typo somewhere and therefore the item within the failing widget cannot be found…

What’s your widget code? Any messages in the log file?

I fail to understand why it works for the somy with the same map and the same widget as for the AVM where it does not work :frowning:

uid: ts_temperaturemode
tags:
  - heating
  - mode
  - temperature
props:
  parameters:
    - description: Used as the label for the widget.
      label: Title
      name: title
      required: false
      type: TEXT
    - context: item
      description: An item to control
      label: Item
      name: item
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Aug 2, 2022, 6:03:04 PM
component: oh-label-item
config:
  icon: oh:Heating
  iconUseState: true
  item: =props.item
  title: =props.title

Not sure what I miss here, but in your screenshot you are showing a widget with footer and 3 items (temperature setpoint, mode & battery) but in your widget code you miss the footer and only have 1 item included.

Do you have any other widgets defined?

Ah - my fault, still learning about OH object model… Wrong widget.

The Overview widget for the working thermostat:

component: oh-label-card
config:
  action: group
  actionGroupPopupItem: TSOG1WC
  footer: =items.TSOG1WC_CurrentHeatingMode.displayState + "\nBatt. " + items.TSOG1WC_Batterieladung.state + "%"
  icon: "= ( items.TSOG1WCMonitoring_Temperature.state.split( ' ' )[0]  < 18 ) ? 'f7:thermometer_snowflake' : ( items.TSOG1WCMonitoring_Temperature.state.split( ' ' )[0] > 25 ) ? 'f7:thermometer_sun' : 'f7:thermometer'"
  iconColor: "= ( items.TSOG1WCMonitoring_Temperature.state.split( ' ' )[0] < 19 ) ? 'blue' : ( items.TSOG1WCMonitoring_Temperature.state.split( ' ' )[0] > 27 ) ? 'red' : ( items.TSOG1WCMonitoring_Temperature.state.split( ' ' )[0] > 23 ) ? 'orange' : ( items.TSOG1WCMonitoring_Temperature.state.split( ' ' )[0] > 21 ) ? 'yellow' : 'green'"
  iconUseState: false
  item: TSOG1WCMonitoring_Temperature
  title: OG1 WC
  trendItem: TSOG1WCMonitoring_Temperature
slots: null

The same code for the non working thermostat:

component: oh-label-card
config:
  action: group
  actionGroupPopupItem: TSOG1Kuche
  footer: =items.TSOG1Kuche_ModusdesHeizkorperreglers.displayState + "\nBatt. " + items.TSOG1Kuche_Batterieladung.state + "%"
  icon: "= ( items.TSOG1Kuche_Temperature.state.split( ' ' )[0]  < 18 ) ? 'f7:thermometer_snowflake' : ( items.TSOG1Kuche_Temperature.state.split( ' ' )[0] > 25 ) ? 'f7:thermometer_sun' : 'f7:thermometer'"
  iconColor: "= ( items.TSOG1Kuche_Temperature.state.split( ' ' )[0] < 19 ) ? 'blue' : ( items.TSOG1Kuche_Temperature.state.split( ' ' )[0] > 27 ) ? 'red' : ( items.TSOG1Kuche_Temperature.state.split( ' ' )[0] > 23 ) ? 'orange' : ( items.TSOG1Kuche_Temperature.state.split( ' ' )[0] > 21 ) ? 'yellow' : 'green'"
  item: TSOG1Kuche_Temperature
  title: OG1 Küche
  trendItem: TSOG1Kuche_Temperature

(Sorry about confusion, I am a windows/powershell guy and quite new to OH)

DisplayState is only available if it’s different to state.

I would change the code to use items.TSOG1Kuche_ModusdesHeizkorperreglers.state to see what’s the real state of the item and why it does not have a display state.

Used the Widgets expression tester to get item properties. The raw channel state is a string of either “frostprotection” (for Somfy TSOG1WC) or “OFF” (for AVM TSOG1Kuche). This goes through a channel link MAP transformation to 0. So both items now have the same state value 0.

But for the AVM channel, this state does not transform to a displayState what it does for the Somfy channel.
grafik

grafik

Why are the AVM items missing the displayState property? Both are defined the exact same way with the exact same settings for both channel link and display state.

Still scratching my head… :face_with_head_bandage:

Is there any way of increased logging for specific items or for the map/stateDescription transformation?

Please have a look here:

Some bindings bring their own transformations and map files are ignored
instead using a map file, the described workaround of to manually add your transformation into the options of the state description.

Might work, but does not explain the issue. I am running OH on a Synology for “production” and on a PC for testing. All of the above is from the testing where it does not work. On Production, where it’s currently not defined in .items but in the UI, it DOES work. Let’s stick to the same 2 items in JSONDB:

  "stateDescription:TSOG1Kuche_ModusdesHeizkorperreglers": {
    "class": "org.openhab.core.items.Metadata",
    "value": {
      "key": {
        "segments": [
          "stateDescription",
          "TSOG1Kuche_ModusdesHeizkorperreglers"
        ],
        "uid": "stateDescription:TSOG1Kuche_ModusdesHeizkorperreglers"
      },
      "value": " ",
      "configuration": {
        "pattern": "MAP(thermostat_modus.map):%s"
      }
    }
  },
  "stateDescription:TSOG1WC_CurrentHeatingMode": {
    "class": "org.openhab.core.items.Metadata",
    "value": {
      "key": {
        "segments": [
          "stateDescription",
          "TSOG1WC_CurrentHeatingMode"
        ],
        "uid": "stateDescription:TSOG1WC_CurrentHeatingMode"
      },
      "value": " ",
      "configuration": {
        "pattern": "MAP(thermostat_modus.map):%s"
      }
    }
  },

Using this, the AVM items do correctly map to “Aus” when the channel map transforms OFF to 0.
grafik

Dunno if that’s of any value, though. It works using JSONDB, it does not work using .items?

Items defined via text file vs. defined via mainui should theoretically work the same. But as item files are more legacy and mainui newer, I can only guess that there are two different implementations and therefore you see two different behaviors in a very special case.

What’s happening of you unlink the channel and just have the item standalone? That would prove of the issue is related to the binding …

Maybe worth to log a bug in this case

In theory, theory and practice are the same. In practice, there are differences :smiley:

I’m willing to file a bug if I can define exactly how to reproduce - which I can’t. I have ony this 1 specific thing type which shows this behavior, and I cannot expect any dev to have the same one. Or can I?

If I remove the channel from the item, I immediately get the expected result:
grafik

Which reverts to losing its displayState after re-inserting the channel into the .items file.

…I hate it - why has it always to hit me? :smiley:

BTW: Thanks alot for your participation in my seemingly singular one-person problem :+1:

This would support the behavior described in the other topic, that a map file is ignored if the binding is also providing some out of the box state description / mapping.
As per the other topic a workaround would be to manually add the mapping into the options instead of using a map file.

Maybe that’s fixed for mainui items but not for text file items.

No worries regarding your issue.
Aren’t these issues the more interesting ones compared to other questions where people just did not read the documentation?

ACK that these are the interesting issues. But I am not interested in issues at all :joy: I still hope one of the gurus here will kick in and give an explanation.

And if I want to file a bug - where should I? Is it an issue in the core? In the binding itself? In item channel bindings? In the map transformation? I’m still a newbie to OH at all, so I really need advice on how to proceed further properly. I’ve seen too many people acting the wrong way, I don’t want to accompany them :sunglasses:

I have to pull this up again - it is still “not” working with 3.4.0. To recap:

I have several thermostats. They report their operating mode (home/away/eco and so on) through different strings. Different for different manufacturers, too. To be able to use the dynamic OH heater control icon, I need numbers, not strings. And to have a nice display in the UI, I need strings, not numbers :slight_smile:

So I came up with a transform. The channel link has a simple map transform to get a numer, eg:

ECO=70

This works fine both in MainUI and through a .things/.items file. Now in the widget, the arriving value for the item’s state is not ECO anymore, but 70. This allows me to use the dynamic OH heater control icon.

The item itself uses a stateDescription metadata:

MAP(thermostat_modus.map):%s

Since we feed in 70, it should now resolve back to

70=Eco

And the widget should show “Eco”:

=items.TSOG1Essen_ModusdesHeizkorperreglers.displayState

This works perfectly for all thermostats from one manufacturer (Somfy), but for NONE of those from AVM when using .things/.items. The result in the widged is “Undefined”, and if I examine through dev scrachtpad, I get:

grafik

If I examine a working thermostat:

grafik

(Which is the expected result, obviously)

For the sake of completeness, here are the .items definitions for both of these thermostats:

String TSOG1Essen_ModusdesHeizkorperreglers "TS OG1 Essen Modus" <Heating> ( TSOG1Essen ) [ "Status", "Temperature" ] {
    channel="avmfritz:FRITZ_DECT_301:192_168_100_1:099950388533:radiator_mode" [
      function="thermostat_modus.map",
      profile="transform:MAP"
    ],
    listWidget="widget:ts_temperaturemode",
    stateDescription=" " [
      pattern="MAP(thermostat_modus.map):%s"
    ]
String TSOG1Wohn_CurrentHeatingMode "TS OG1 Wohn Modus" <temperature> ( TSOG1Wohn ) [ "Status", "Temperature" ] {
    channel="somfytahoma:valveheatingsystem:5c9e9e2952:f79e8ce2-98b8-4a49-963b-f5c0544ad08e:current_heating_mode" [
      function="thermostat_modus.map",
      profile="transform:MAP"
    ],
    listWidget="widget:ts_temperaturemode",
    stateDescription=" " [
      pattern="MAP(thermostat_modus.map):%s"
    ]
}

The first one (AVM) does not work, the second (Somfy) works. I completely fail to see any differences between those 2 items or between their channel links or widget definitions.

WHY??? As said above, it correctly transforms the operating mode strings to a number correctly with both manufacturers, but it does transform back to a string only with Somfy and NOT with AVM. Scratching my head for hours now…

Edit: I already tried replacing <Heating> with <temperature>, but to no luck…

I would check metadata.
Some channels force-feed a binding defined metadata ‘state presentation’ to an Item as you link it.
Stuff like a list of allowed state options, for example. (which your transformed states will not be on)

The force-feeding is a one time event, you should be able to edit/delete unwanted metadata.

How do I check metadata? If i look into the ItemChannelLink.json, I see

  "TSOG1Essen_ModusdesHeizkorperreglers -\u003e avmfritz:FRITZ_DECT_301:192_168_100_1:099950388533:radiator_mode": {
    "class": "org.openhab.core.thing.link.ItemChannelLink",
    "value": {
      "channelUID": {
        "segments": [
          "avmfritz",
          "FRITZ_DECT_301",
          "192_168_100_1",
          "099950388533",
          "radiator_mode"
        ],
        "uid": "avmfritz:FRITZ_DECT_301:192_168_100_1:099950388533:radiator_mode"
      },
      "configuration": {
        "properties": {
          "function": "thermostat_modus.map",
          "profile": "transform:MAP"
        }
      },
      "itemName": "TSOG1Essen_ModusdesHeizkorperreglers"
    }
  },
  "TSOG1Wohn_CurrentHeatingMode -\u003e somfytahoma:valveheatingsystem:5c9e9e2952:f79e8ce2-98b8-4a49-963b-f5c0544ad08e:current_heating_mode": {
    "class": "org.openhab.core.thing.link.ItemChannelLink",
    "value": {
      "channelUID": {
        "segments": [
          "somfytahoma",
          "valveheatingsystem",
          "5c9e9e2952",
          "f79e8ce2-98b8-4a49-963b-f5c0544ad08e",
          "current_heating_mode"
        ],
        "uid": "somfytahoma:valveheatingsystem:5c9e9e2952:f79e8ce2-98b8-4a49-963b-f5c0544ad08e:current_heating_mode"
      },
      "configuration": {
        "properties": {
          "function": "thermostat_modus.map",
          "profile": "transform:MAP"
        }
      },
      "itemName": "TSOG1Wohn_CurrentHeatingMode"
    }
  },

Which to me looks the same as in the .items file. The Metadata.json for both thermostats is also identical - defining a listWidget (the same for both) and a value widget (also the same). And if defined by MainUI, it works as expected. If defined through .items, it does not.

I don’t know where to look next. And of course would appreciate any hint or direction :slight_smile: