Icons not showing correct icon by name OH3

Hi,
I am using OH3 and have installed the BOM addon so I can get the weather for Australia.

It is working well but I have an issue if the forecasticon variable the addon uses gets set to light-shower then the icon I get is the standard light bulb icon and not the light-shower icon I have loaded into /etc/openhab/icons/classic

The icon files do exist in the /etc/openhab/icons/classic directory and have the correct permissions set.

All the other icons work. If the forecasticon variable is set to sunny then I get the sunny icon, if set to cloudy I get the cloudy icon etc.

I am trying to get the light-showers icon to work on the overview page. The code I am using is:
="oh:"+(items.BOM_Day1_ForecastIcon.state)

I tried to use the metatdata State Description to maybe put a pattern that would remove the dash from the name light-shower and turn it into lightshower and then I could have that as a file name in the icons directory.

Is there a way I can get the correct icon to show up as the icons change all the time as they are the weather icons for the day.

As I said before all the other icons work but I think because the icon I want to use starts with the word light then I get the lightbulb icon instead of rain clouds.

Thanks in advance.

I have come a bit further.
I had to install the map transformation addon.

I then created a bom.map file and added:
light-shower=lightshower

Then I added metadata State Description in the pattern field:
MAP(bom.map):%s

Now the display shows lightshower (without the dash, which is what I need I think) so I can create a lighshower.png icon and see what icon shows up.

BUT now I have another problem. I cannot use an expression to get the name without the dash in it.
If I use this: =“oh:”+(items.BOM_Day5_ForecastIcon.state)
I get oh:light-shower

If I use this:
=“oh:”+(items.BOM_Day5_ForecastIcon.displayState)
I get oh:undefined

My question now is how do I get an expression that can get the mapped variable (without the dash)

So close!

Hyphens are prohibited in icon filenames, except as part of a dynamic icon set. The icon picker uses it as a special character. You’ll have to rename to light_shower or something, and change whatever does the selection.

Note that icon selection is based on raw Item states. Transforming a state for display has no effect. You’ll need to do the transform before it gets put into the Item.

I figured that might be the case. Problem is the name comes from the weather site. It isn’t chosen by me.

Any idea of an easy way to do this?
I have 7 items this will affect as I want the 7 day forecast.

I just need an on the fly find and replace off the data has a dash in it.

I am only using JavaScript as well. NO DSL.

Either that or I just don’t have icons when there is light rain. :smiley: or mostly-sunny days.

I guess a rule when updated I convert the triggering item of they contain a dash. There must be a JavaScript way to do this?

It’s early here. I will look at it today as well.

Thanks

I have progressed a bit further.
I have created a group and added the 7 items I want to change the names of in that group.
I created a rule that the state of a member has been updated.
Then I refresh the load of the BOM addon and this gets the data from the weather site.
I have logging enabled and I can see I am getting the event.item name and state etc of all 7 items. That part works.

The part I cannot get to work is how to find a dash in the state so I can post an update and replace the dash with an underscore. I want to use Javascript. I have done this before in DSL but I want to see if I can do it in Javascript

Thanks

Add a profile with a JS transformation to replace the “-” with " " or “_”.

Where’s this string coming from? Can you apply a transform at the binding channel? You certainly can add a transform profile to the channel-Item link, no rule required.

javascript replace() looks like a useful tool.

I have found how to do it in JavaScript. Straight after I replied to you.

Here is how I did it:
itemRegistry.getItem(event.itemName).getState().toString().replace(/-/g, ‘_’)

Here is the results in the log file:
2021-02-16 09:34:55.241 [INFO ] [org.openhab.rule.66aec2a87b ] - BOM_Day1_ForecastIcon shower
2021-02-16 09:34:55.250 [INFO ] [org.openhab.rule.66aec2a87b ] - BOM_Day2_ForecastIcon shower
2021-02-16 09:34:55.254 [INFO ] [org.openhab.rule.66aec2a87b ] - BOM_Day3_ForecastIcon shower
2021-02-16 09:34:55.256 [INFO ] [org.openhab.rule.66aec2a87b ] - BOM_Day4_ForecastIcon shower
2021-02-16 09:34:55.258 [INFO ] [org.openhab.rule.66aec2a87b ] - BOM_Day5_ForecastIcon mostly_sunny
2021-02-16 09:34:55.260 [INFO ] [org.openhab.rule.66aec2a87b ] - BOM_Day6_ForecastIcon mostly_sunny
2021-02-16 09:34:55.264 [INFO ] [org.openhab.rule.66aec2a87b ] - BOM_Day7_ForecastIcon light_shower
2021-02-16 09:34:55.594 [INFO ] [nhab.binding.bom.internal.BomHandler] - Successfully processed city/down/district forecast data.

Now to figure out how to not make it go into an update loop as the data is being changed and the rule runs if the data changes.

So far so good,

Yes I can transform the name BUT I cannot get the displayState to work.
I have cracked how to do it and it is failry simple and I don’t get a data loop.
Here is how I did it.

Created a group. Put all the items in the group that I want to be converted if they have dashes in the state.

Created a rule.
Trigger: when a member of the group changed

Action in javascript and it is just one line of code:

events.postUpdate(itemRegistry.getItem(event.itemName).getName(), itemRegistry.getItem(event.itemName).getState().toString().replace(/-/g, ‘_’));

Hopefully this will come in handy for someone else.
Bonus is if any other states have dashes in them I just add them to the group.

Thanks for your help and suggestions.

This really seems like a very round about way to achieve this. Even the JavaScript is overwrought.

You use the name to pull the Item from the registry in order to get the name. Just use the name. And you don’t need to pull an Item from the registry to get its state. Use the items dict.

events.postUpdate(event.itemName, items[event.itemName].toString().replace(/-/g, '_'));

Depending on how the rule is triggered, this will result in an infinite loop. If you use a changed trigger the rule will trigger one extra unnecessary time. If the rule is triggered using received command than you are OK. But if you use received update it will loop and loop forever.

But a rule is really not the appropriate way to implement this. The hierarchy for solving a problem like this is:

  1. solve it at the source
  2. transformation at the Thing/Channel
  3. transformation using a Profile on the link between the Channel and the Item
  4. write a rule

Only move down the list if a given step is impossible. In this case 3 is very much possible. You’d create a JavaScript transformation along the lines of:

(function(i) {
    return i.replace(/-/g, '_');
})(input)

Then apply a transform JS profile to the link between the Channel and the Item and

  • you never run the risk of an infinite loop if the trigger is chosen poorly
  • you never run the transformation more often then necessary if the trigger is chosen poorly or received command isn’t possible
  • transformations over all are more efficient than rules and in this case the transformation is even shorter than the rule if you count characters

What doesn’t work? Display state doesn’t have anything to do with the icon. What breaks if you use the transform Profile?

Here is the code in code fence:
‘’'triggers:

  • id: “1”
    configuration:
    groupName: gReomveDash
    type: core.GroupStateChangeTrigger
    conditions: []
    actions:

  • inputs: {}
    id: “2”
    label: Strip the dashes out and replace with underscores.
    configuration:
    type: application/javascript
    script: >
    //This contains things that I have found that work in javascript

    //More information here: https://openhab-scripters.github.io/openhab-helper-libraries/Guides/But%20How%20Do%20I.html
    
    
    //need below to log to openhab.log file
    
    var logger = Java.type('org.slf4j.LoggerFactory').getLogger('org.openhab.rule.' + ctx.ruleUID);
    
    //below is if you are going to use the ececute command
    
    var Exec = Java.type("org.openhab.core.model.script.actions.Exec");
    
    //below is also neede for the execute command
    
    var Duration = Java.type("java.time.Duration");
    
    
    
    events.postUpdate(itemRegistry.getItem(event.itemName).getName(), itemRegistry.getItem(event.itemName).getState().toString().replace(/-/g, '_'));
    
    
    logger.info(itemRegistry.getItem(event.itemName).getName() + " " + itemRegistry.getItem(event.itemName).getState().toString().replace(/-/g, '_'));
    

    type: script.ScriptAction
    ‘’’

Three back ticks for code fences.

```

You are using single quotes

'''

Strange I am using the back tick top left hand of keyboard.

I couldn’t use the transform beacuse I want to show the icon on the overview page.
In the icon field I have this:
=“oh:”+(items.BOM_Day1_ForecastIcon.state)
Which works unless there is a dash in the name. This was the original issue. It showed a lightbulb if the icon state was light-shower
I did put map to change the display of the item but that didn’t work either as I couldn’t use:
=“oh:”+(items.BOM_Day1_ForecastIcon.displayState)
SO I figured the easiest way is to just change the data coming in as that is out of my control because it is coming from the weather site.

It seems to work.No loops. This only runs every hour.

But that what a transformation profile does. It sits between the Channel and the Item and transforms the value before it ever gets to your Item so by the time it gets to the Item it has the ‘_’ instead of ‘-’.

This has nothing to do with State Description metadata or transformation for display.

If you use the transform Profile with the above JS, your ="oh:"+(items.BOM_Day1_ForecastIcon.state) expression will work because the Item will never get a state that includes ‘-’.

I think I am missing something here.
Can you show me in a screenshot how I would do the profile bit.
I am not using any files I am doing all of this via the GUI.
I would feel better if I didn’t need to use a rule .
Thanks

Not at the moment but I can tell you where to look.

Navigate to the Item. Click on the Link. That will open a new page showing the link between the Item and the Channel. At the bottom you can select from among several Profiles. One of them will be transform where you can define a transformation which will apply to the data as it passed from the Channel to the Item.

You’ll need to put the JS above into a .js file in the /etc/openhab/transform folder though. As with .persist files, openHAB doesn’t yet support defining certain transforms through the UI.

Also, the JavaScript transformation is a separate addon you’ll need to install.

This is all I see:

I have a JS profile.
I have selected that for the item.
I have created in the transforms folder a file called dashreplace.js In that file is:

    return i.replace(/-/g,'_');
})(input)

The item state at the moment is light-shower

In the overview page for the icon it have:

="oh:"+(items.BOM_Day7_ForecastIcon.state)

The icon is still a lightbulb and not light_shower icon.

I must still be missing something.

That’s not valid, unpaired brackets. Think you’ve missed a line out.

Did you install the Javascript transformation service ? This is an add-on.

YAY it worked.
There is one bit you have to do. Restart openhab after installing the JS transformation.

THANK YOU SOOOOOO MUCH! That is brilliant.

I am learning so much. At least now I have a find and replace Javascript I can use somewhere.

There is a lot to learn.