[OH3] - MAP transformations for GUI based config with custom formatting?

Tags: #<Tag:0x00007f4342669450> #<Tag:0x00007f4342669388>

Hi guys,

I’m in the process of switching to OH3, including a switch from file based config to GUI/jsondb based config. And just now I’m a bit stymied by how to apply MAP transformations…

I found in this post that I can configure value transformations in the GUI via /Add Metadata/State Description/Pattern in the format <transformation service>(<myFile>.map):%s. But since the value is formatted as float (1.0) instead of integer (1), I would like to apply formatting before transforming the value.
According to the Java formatter class syntax (link in chapter Items/State Presentation), that should be done by using %d instead of %s. But it doesn’t work, instead I get the following error message:

Failed transforming the state '3.0' on item 'PowerOpenhab_SignalStrength' with pattern 'MAP(hm_qos.map):%d': Cannot format state '3.0' to format '%d'

And yes, the Map add-on is running, it works with %s and the easy way out would be to just change my transformation file so that I can match against 3.0 instead of 3.
But I would like to understand why the formatting is not working…

On a side note:

  • the chapter Transformation does not mention transformation for GUI based configs
  • it does link to section Profiles in chapter Items, but this section doesn’t explain profile based transformations at all
  • the brief documentation for MAP does mention how to use profiles for transformation - for text based configs

Yep. The MAP transformation always returns a string, it doesn’t matter if it looks like “3.0” it’s still a string. You cannot format a string with %d.

Note that the %s/%d we are talking about here in the ‘pattern’ is applied to the output of the transformation.

There are not many other ways out. Don’t forget you can match to “3.0” AND “3” in different MAP lines.

How does your Item get updated, should you be “integerizing” it at the source?

I’m not so sure about that, for MAP(hm_qos.map):%s I get the following error:

Could not transform '3.0' with the file 'hm_qos.map' : Target value not found in map for '3.0'

For me that looks like the %s / %d part is applied first, causing the first error Cannot format state '3.0' to format '%d', because my chosen format can not be applied to the item state.
When I use %s the item state is accepted and the error message is only complaining that the value 3.0 can not be found in my transformation file.

The source is an Number item, so %d should work - but it seems like the transformation step gets the state as an string :thinking:

Just to make sure that I’m not overlooking something stupid - here is the JSON code for channel, item and transformation:

        {
          "acceptedItemType": "Number",
          "kind": "STATE",
          "uid": {
            "segments": [
              "homematic",
              "HM-ES-PMSw1-Pl-DN-R1",
              "ccu",
              "OEQ1976802",
              "0#SIGNAL_STRENGTH"
            ],
            "uid": "homematic:HM-ES-PMSw1-Pl-DN-R1:ccu:OEQ1976802:0#SIGNAL_STRENGTH"
          },
          "channelTypeUID": {
            "segments": [
              "system",
              "signal-strength"
            ],
            "uid": "system:signal-strength"
          },
          "label": "Signal Strength",
          "configuration": {
            "properties": {}
          },
          "properties": {},
          "defaultTags": [],
          "autoUpdatePolicy": "DEFAULT"
        }

channel

  "PowerOpenhab_SignalStrength": {
    "class": "org.openhab.core.items.ManagedItemProvider$PersistedItem",
    "value": {
      "groupNames": [
        "PowerOpenhab"
      ],
      "itemType": "Number:Dimensionless",
      "tags": [
        "Point"
      ],
      "label": "Signal Strength",
      "category": "QualityOfService"
    }
  }

item

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

transformation

So channel provides a state of type Number, the item is of type Number, but the transformation does not accept %d to provide a integer decimal?

The key observation, yes.
Whatever the Item type, the transformation is fed the “toString” version of its state.
The Item type no longer matters now, and the transformation output is always a string as well.

There’s a twist for failed transformations …

Alternative story - when a transformation fails e.g.no MAP match, it passes the original untransformed input to the output.
So Item state is passed to MAP as a string “3.0”, lookup fails, a string “3.0” arrives for the formatter to process. Format %d fails and complains because it can’t handle the string, format %s works on a string (but the failed MAP complains).

I think the format fail is a drop-dead ERROR; the MAP lookup fail is a carry-on WARN (because you do get a string of some kind)

If your Item state is really decimal i.e. 3.1 is possible, you might look into the SCALE transformation, which is more numerically minded than the string-matching MAP.

2 Likes