Simple light switch widget with icon/image of bulb f.ex is clickable and changing state

Maybee i didn’t searched well, but i didn’t found such a simple widget solution till now…
I want to show only an image of a light bulb or a pump or whatever… in the “off” state… and when hitting this state it turn on and change the image to state “on” and back… i realized something with an image widget with action toogle… but i dont succeed in changing the icons regarding the state…

Switch LedP4L6s "Büro" <light> (gP4KNX) [ "Lighting" ] { channel="knx:device:bridge:D4-1_1_14:D4P4L6s", autoupdate="true", icon="light", mappings='[ON="LightON", OFF="LightOFF"]' }

the icon files LightON.png and LightOFF.png are in the folder “openhab/conf/html” which is equal to “static” i think… but i also put them in “icons/classic” where i put before all my custom icons…but i think its not only this… something might be wrong with the syntax… and if someone has a custom widget with all this features… would be nice…

It will be easier for us to help you if you paste the widget code you have already tried.

i only have used the image widget template…
i have no custom widget… thats what i am looking for…

 - component: oh-image-card
                      config:
                        action: toggle
                        actionItem: LedP4L6s
                        title: Eingang
                        outline: true
                        actionCommand: ON
                        actionCommandAlt: OFF
                        item: LedP4L6s
                        refreshInterval: 1000

OK, there are a few different concepts that you’re getting mixed together here.

A component that just shows an image (a oh-image) or one that shows an image on a pre-styled card (oh-image-card) will only show an image if it is given a url to the image, or the name of an image type item (an item which holds the actual image information as it’s item state). The item you have shown us here, LedP4L6s, is a Switch type item. That means that it’s basic states are ON and OFF. The oh-image-card doesn’t know what ON or OFF mean because those are not images or locations where images can be found.

There are two basic options here and you appear to have tried them both but just need to understand one or two extra pieces in each case to get it right.

Option 1: Create dynamic custom icons and then choose a widget component that will choose the correct icon variant based on the state of a given item. However, your dynamic icon names are not following the set pattern:

and the oh-image-card, as I said above, doesn’t work with icons.

If you’re going to go with this option you will need to fix the icon names and then choose something like an oh-label-card where you can select the icon to use and the state that icon should display:

Note, however: that if you want that state to be dynamic, you will need to understand basic widget expressions:

Option 2: Separate images in the openhab/conf/html folder. This option is where you would use the oh-image-card, but because you want it to access an image based on the /static/name-of-your-image url, you have to fill in the url property of the card:

In this case, you will also need to use a widget expression in that url property because you want a different url if an item state is ON or OFF (see widget expression link above).

Great thanks, i have soluted it with the label-card… its working… i have to play a little bit with output format of text and images…
But next thing is i wanted to use an image of a pump within a custom widget…

uid: VistaPool
tags: []
props:
  parameters:
    - description: Small title on top of the card
      label: Title
      name: title
      required: false
      type: TEXT
    - description: HEX or rgba
      label: Background Color
      name: bgcolor
      required: false
      type: TEXT
    - context: item
      description: Item Pooltemp
      label: Item
      name: item_temp
      required: false
      type: TEXT
    - context: item
      description: Item PH-Wert
      label: Item
      name: item_pHWert
      required: false
      type: TEXT
    - context: item
      description: Item Poolpump
      label: Item
      name: item_pump
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Feb 27, 2023, 11:35:22 AM
component: f7-card
config:
  style:
    background-color: "=props.bgcolor ? props.bgcolor : ''"
    border-radius: var(--f7-card-expandable-border-radius)
    box-shadow: 5px 5px 10px 1px rgba(0,0,0,0.1)
    class:
      - padding: 0px
    height: 150px
    margin-left: 5px
    margin-right: 5px
    noShadow: false
slots:
  content:
    - component: f7-block
      config:
        style:
          display: flex
          flex-direction: row
          left: 16px
          position: absolute
          top: -8px
      slots:
        default:
          - component: oh-icon
            config:
              icon: pool
              style:
                filter: "='invert(' + (themeOptions.dark === 'dark' ? '1' : '0') + ')'"
                height: 28px
                margin-right: 2px
          - component: Label
            config:
              style:
                font-size: 12px
                margin-top: 0px
              text: "=props.title ? props.title : ''"
    - component: f7-block
      config:
        class:
          - text-align-center
        style:
          bottom: -15px
          flex-direction: row
          left: -16px
          position: absolute
          width: 100%
      slots:
        default:
          - component: Label
            config:
              style:
                font-size: 18px
                font-weight: 400
                margin-left: 0px
                margin-top: 0px
              text: =items[props.item_temp].state + '°'
    - component: f7-block
      config:
        class:
          - text-align-center
        style:
          bottom: -42px
          left: -16px
          position: absolute
          width: 100%
      slots:
        default:
          - component: f7-icon
            config:
              f7: thermometer
              size: 30px
    - component: f7-block
      config:
        class:
          - text-align-center
        style:
          bottom: -15px
          flex-direction: row
          left: 32px
          position: absolute
          width: 100%
      slots:
        default:
          - component: Label
            config:
              style:
                font-size: 18px
                font-weight: 400
                margin-left: 0px
                margin-top: 0px
              text: =items[props.item_pHWert].state
    - component: f7-block
      config:
        class:
          - text-align-center
        style:
          bottom: -48px
          left: 32px
          position: absolute
          width: 100%
      slots:
        default:
          - component: oh-icon
            config:
              height: 32px
              icon: phwert
              margin-right: 5px
    - component: f7-block
      config:
        class:
          - text-align-center
        style:
          bottom: -90px
          left: 40px
          position: absolute
          width: 100%
    - component: f7-block
      config:
        class:
          - text-align-center
        style:
          bottom: -95px
          left: 8px
          position: absolute
          width: 100%
      slots:
          default:
          - component: oh-icon
            config:
              height: 48px
              icon: "=items[props.item_pump].state === '0' ? 'pump-off' : 'pump-on'"
              margin-right: 5px
              on-click: =/rest/items/{{props.item_pump}}/toggle
              style:
                cursor: pointer
    - component: f7-block
      config:
        class:
          - text-align-center
        style:
          bottom: -95px
          left: 8px
          position: absolute
          width: 100%
      slots:
        default:
          - component: oh-icon
            config:
              height: 48px
              icon: "=items[props.item_pump].state === '1' ? 'pump-on' : 'pump-off'"
              margin-right: 5px
              style:
                opacity: 0.5

this is the thing:

Type string : NPMode 			[stateTopic="stat/neopool_D7CDB8/NPFiltrationMode", transformationPattern="JSONPATH:$.NPFiltrationMode", commandTopic ="cmnd/neopool_D7CDB8/NPFiltrationMode", 0="MANUAL", 1="AUTO", 2="HEATING", 3="SMART", 4="INTELLIGENT", 13="BACKWASH",refresh=30]
		Type string : NPFilter 			[stateTopic="stat/neopool_D7CDB8/NPFiltration", transformationPattern="JSONPATH:$.NPFiltration", commandTopic="cmnd/neopool_D7CDB8/NPFiltration", 0="Aus", 1="Ein",refresh=30]	

the item

your String NeoPoolFilter	"Filtration [%s]"  						(gPool)	 { channel="mqtt:topic:neopool_D7CDB8:NPFilter"}
String NeoPoolIntervall	"Zeit [%s]"  							(gPool)	 { channel="mqtt:topic:neopool_D7CDB8:NPINTERVAL1"}
Number PoolPumpe 		"PoolPumpe [MAP(3statespoolpump.map):%s]"goes here

the rule:

rule "Poolpumpe Ein/Aus/Off-Auto"
when
    Item PoolPumpe changed
then
	logInfo("Neopool-RULE", "--> PoolPumpe wechselt Status ist " + PoolPumpe)
    switch ((PoolPumpe.state as Number).intValue) {
		case 0 : {NeoPoolMode.sendCommand(0)
				NeoPoolFilter.sendCommand(1)}
        case 1 : {NeoPoolFilter.sendCommand(0)
				NeoPoolMode.sendCommand(1)}
    }
end

the 3statespoolpump.map has now only 2 states… : on and off…
the pump has to be put in manuel mode before switchin on so NeoPoolMode has to be “0” for manuel… and than NeoPoolFilter can be set to “1” to start.
When switching off the pump first NeoPoolFilter is set to “0” = off, and than the system has to be switched back to automode so NeoPoolMode “1” to switch on the filtering to the programmed scheduled times… there are some other filter modees, like f.ex. “2” : heating which i maybe will use later to also start manuel heating… but now its enough to start manual filtering when hitting the icon image pump which has the 2 states pump-on and pump-off… all png’s lying in the icons/classic folder… any ideas?

For this you want to look into the widget actions. Many of the component types, including the oh-icon have a built-in series of possible responses to a click that you can configure; these are the widget actions:

In this case it sounds like the best option for you would be a rule action where you can build the rule to perform the multistep operation that you need and then trigger that rule by clicking on the component.

its already made, that the switch

Number PoolPumpe 		"PoolPumpe [MAP(3statespoolpump.map):%s]"

gets the state on or off… and triggers the rule to do the 2 steps…
but i miss the syntax to integrate it in the custom widget… it would work maybe directly with an oh-label-card… but i miss to integrate it in the above code…

Oh, I understand.

In that case, instead of the rule action you want the toggle action will which send a command to item unless the item already has that state, in which case it will send an alternate command. This is usually the best match for Switch type items. To configure the toggle action you’ll need to set the actionItem , actionCommand, and actionCommandAlt properties. You can read about those in the same link in the post above.

sorry, dont succeed! the icon is shown but nothing happens on-click with my example above.

an icon can not receive that on-click argument or what is the problem… sorry i am playing around since hours… and dont find a solution… reading the manual doesnt help me… no idea how to adapt the code?

thats the widget… and i only want to hit the pump image below to start the pump and show pump-on icon and reverse…

on-click is not a defined property. It has nothing to do with the widget actions. It is not listed in the documentation that I have given you the link for. Actions on a widget are defined by setting the action property and then whatever appropriate secondary properties are needed.

If you need to see an example, then use the page editor to add a label card to a page and configure that card to have a toggle action then switch over to the code tab of the page and look at the yaml that’s been generated for that widget. Alternatively you can use the forum search with “action: toggle” to find many examples of the proper configuration.

The Getting Started tutorial also has several examples of the yaml configuration for actions. If you’re still confused about how to build your widget it never hurts to go back and review those docs:

i created another widget as label-card with a changing icon… working well… but i cannot put it here on that position … i tried already and made something wrong… will try tomorrow again…

i dont succed… also not with the oh-label-card.
i need help in the code not hints to read more docs… maybe i am too stupid to do it but i was hopping here are freaks that can do this and not only hints where maybe find answers…
i also dont find similar code somewhere so its seems to be not so easy…

uid: Pool_widget
tags: []
props:
  parameters:
    - description: Small title on top of the card
      label: Title
      name: title
      required: false
      type: TEXT
    - description: HEX or rgba
      label: Background Color
      name: bgcolor
      required: false
      type: TEXT
    - context: item
      description: Item Pooltemp
      label: Item
      name: item_temp
      required: false
      type: TEXT
    - context: item
      description: Item PH-Wert
      label: Item
      name: item_pHWert
      required: false
      type: TEXT
    - context: item
      description: Item Poolpump
      label: Item
      name: item_pump
      required: false
      type: TEXT
    - context: icon
      description: Icon Poolpump
      label: Icon
      name: icon_pump
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Feb 27, 2023, 9:25:54 PM
component: f7-card
config:
  style:
    background-color: "=props.bgcolor ? props.bgcolor : ''"
    border-radius: var(--f7-card-expandable-border-radius)
    box-shadow: 5px 5px 10px 1px rgba(0,0,0,0.1)
    class:
      - padding: 0px
    height: 150px
    margin-left: 5px
    margin-right: 5px
    noShadow: true
slots:
  content:
    - component: f7-block
      config:
        style:
          display: flex
          flex-direction: row
          left: 16px
          position: absolute
          top: -8px
      slots:
        default:
          - component: oh-icon
            config:
              icon: pool
              style:
                filter: "='invert(' + (themeOptions.dark === 'dark' ? '1' : '0') + ')'"
                height: 28px
                margin-right: 2px
          - component: Label
            config:
              style:
                font-size: 12px
                margin-top: 0px
              text: "=props.title ? props.title : ''"
    - component: f7-block
      config:
        class:
          - text-align-center
        style:
          top: 35px
          left: 10px
          position: absolut
          width: 100%
          noShadow: true
      slots:
        default:
          - component: oh-label-card
            config:
              action: toggle
              actionCommand: ON
              actionItem: =props.item_pump
              icon: =props.icon_pump
              left: 40px
              iconSize: 48
              iconUseState: true
              item: =props.item_pump
              label: " "
              style:
                cursor: pointer
              iconOn:
                - icon: =props.icon_pump + '-on'
                  color: green
              iconOff:
                - icon: =props.icon_pump + '-off'
                  color: red
              labelOn:
              - text: "Pumpe An"
                color: green
              labelOff:
                - text: "Pumpe Aus"
                  color: red
    - component: f7-block
      config:
        class:
          - text-align-center
        style:
          top: 20px
          flex-direction: row
          left: 40px
          position: absolute
          width: 100%
      slots:
        default:
          - component: Label
            config:
              style:
                font-size: 18px
                font-weight: 400
                margin-left: 0px
                margin-top: 0px
              text: =items[props.item_temp].state + '°'
    - component: f7-block
      config:
        class:
          - text-align-center
        style:
          top: 50px
          left: 40px
          position: absolute
          width: 100%
      slots:
        default:
          - component: f7-icon
            config:
              f7: thermometer
              size: 30px
    - component: f7-block
      config:
        class:
          - text-align-center
        style:
          top: 20px
          flex-direction: row
          left: 80px
          position: absolute
          width: 100%
      slots:
        default:
          - component: Label
            config:
              style:
                font-size: 18px
                font-weight: 400
                margin-left: 0px
                margin-top: 0px
              text: =items[props.item_pHWert].state
    - component: f7-block
      config:
        class:
          - text-align-center
        style:
          top: 46px
          left: 80px
          position: absolute
          width: 100%
      slots:
        default:
          - component: oh-icon
            config:
              height: 36px
              icon: phwert
              margin-right: 5px   

the rule and item config is in the upper part of the post… what am i doing wrong??
also would be nice to get of the shadow of the labelcard… but thats the smalles problem…
hope someone can help…

I firmly believe that no one is “too stupid” to work out this kind of situation. It’s easier for some who have put the time in at some other point in their life by learning related material and can translate that experience over to things like OH and it takes longer for others who don’t have that relevant experience.

OH is the same as any process more complex than making a sandwich; you’re not going to be able to do it if you just want to skip to the end and don’t put the time into the fundamentals. Every question you have asked is answered somewhere in the docs, and you have given no indication at any point that you had read the relevant doc pages.

I am going to guess that this is a language translation issue, but do be advised that ‘freaks’ can easily be interpreted as an insulting term. I assume you are not intending to insult the very people you are asking for help.

Your questions included no reference to the help docs such as “I see in the getting started tutorial how to do X, but I don’t understand how to modify this to my situation Y”. The errors you are making indicate to me that you have not read the help docs, and skipping to the end here just doesn’t work. If you have read then docs then you could have indicated that in the question and we could have skipped this part. But, the best way to help you based on the details you were providing was to point you in the right direction with the help docs.

I get it, sometimes the help docs are hard to use. They are organized in a way that makes sense to some people…but not everyone. They outline information in an order that makes sense to some people…but not everyone. They directly answer some questions but expect the reader to extrapolate that answer to other situations. This is true of all help docs everywhere. Yes, the help docs aren’t perfect, but they’re really pretty good, and a lot of very knowledgeable people have volunteered a lot of their time to create something that does answer these very same questions that you have.

You don’t even have to look very far, and you don’t need someone else to write the code for you. You have all pieces you need right here in this thread, you just haven’t put all the right pieces together yet.

Here you have code that should properly display the icon you want based on the state of the pump item:

And here you have code that properly formats all the required information for a toggle action, it was just part of a component that wouldn’t work for your icon requirements:

If you use one of the “card” components you’re going to get that “card” appearance. If you don’t want that appearance then find a more appropriate component to use. In this case, you already have; the code excerpt above uses an oh-icon which will do everything you want: display the icon dynamically by using the expression, not have a card-based outline, and provide for the toggle action of the item.

2 Likes

That is working now…

 - component: oh-icon
            config:
              left: 60%
              height: 64
              icon: '=(items[props.item].state === "OFF") ?  props.icon + "-off" :  props.icon + "-on"'
              action: toggle
              actionItem: =props.item
              actionCommand: ON
              actionCommandAlt: OFF
              iconUseState: true
              item: =props.item
              style:
                cursor: pointer
              labelOn:
                - text: =props.messageon
                  color: green
              labelOff:
                - text: =props.messageoff
                  color: red

but nit showing the text message on and off…

that not! is not changing the state by hitting and not changing the icon!

 - component: oh-icon
            config:
              height: 48px
              icon: '=(items[props.itempump].state === "0") ?  props.iconpump + "-off" :  props.iconpump + "-on"'
              margin-right: 5px
              action: toggle
              outline: true
              actionCommand: ON
              actionCommandAlt: OFF
              actionItem: =props.itempump
              left: 40px
              iconSize: 48
              iconUseState: true
              item: =props.itempump
              style:
                cursor: pointer

it might be easy… ok, maybe a tutorial with lots of simple examples also with the formatting of the layout… i dont succeed in putting a title in the lower example in the middle of the line… only with an absolut position i can move it… its really frustrating how much time you los with such simple shit! in the standard sidemaps. its more restricted all but a lot works out of the box

This is a public and welcoming forum and you need to be more careful with your offensive language. Even if you wish to demonstrate your frustration that sort of language is simply not appropriate here. Please consider editing it out of your post.

It can also be very frustrating when someone asks for help and then refuses the help that is provided.

It seems to me that much of your frustration comes from your assumption that this should be “simple”. Some aspects of this are simple, yes. The yaml format is intended to be easily readable and simple to input. Understanding what the height property of an icon means is simple and intuitive. But what you are attempting to do is very much not simple. You are trying to assemble from an near infinite number of options a compound, complex user interface structure in an open, responsive environment.

This has already been greatly reduced in complexity for you: you are doing dynamic web design only you don’t have to know html, or much javascript, or any of the dozens of other pieces that go into modern web design. If you want truly simple, return to using sitemaps or just add individual cards in the MainUI page editor using the gui wizards. Those are both fine solutions and a lot of work has gone into making them visually appealing out of the box. They are also much simpler because your control and options have been greatly reduced. If you want control and options, that is, if you want to have your own custom widgets in a MainUI interface then you have to change your assumptions and attitude or remain frustrated.

However, because you insist that this should be simple you have neglected to really look at the helpful information I have provided to you. How do I know? For example, I have given you the link to the oh-icon reference page which lists all of the properties you can set for that component. In the code you have just posted, however, you have many instances where you attempt to use properties that do not exist for the oh-icon:

css property - this needs to be set under the style heading

There is no such property for an oh-icon - this is one reason why you are not seeing the text you expect

Also, no such property…

css property - this needs to be set under the style heading

css property - this needs to be set under the style heading. Also, true is not a valid value for outline…

css property - this needs to be set under the style heading

There is no such property for an oh-icon.

In addition to just plain incorrect properties, you are also setting contradictory values for some properties:

This works all on it’s own. It returns the icon name with either the -on or -off suffix. If you do this then you do not need iconUseState which you set…

But if you set iconUseState then you also have to set the state property so that the icon knows what state to use to fetch the dynamic icon.

If you had looked at the oh-icon reference you would know that there is no option for text. This component is only for displaying an icon from one of the available libraries. I originally suggested its use because all you indicated that you wanted to do was display an icon. You made no mention of text. Now you have decided you want text as well on one of the images. That’s fine, that can be done, but you’re going to have to either pick a different component that can handle text and an icon or add the text you want by adding an additional component. How do you know what other components might be more appropriate…you look through the documentation.

I will leave these here because they contain more answers to your questions and I continue to be optimistic that you will come around and help yourself and help us help you…

1 Like

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.