How to change a widget color using the state of a RGB Led item?

Can anyone suggest a simple way to change the color of a colorpicker widget, using the actual color of a RGB stripe.
I tried using this YAML code, but the widget is alwais white

component: oh-colorpicker-cell
config:
action: toggle
actionCommand: ON
actionCommandAlt: OFF
actionItem: Led_Switch
color: =(items.LEDRGB_Color.state)
icon: colorpicker
item: LEDRGB_Color
on: =(items.Led_Switch.state == ‘ON’)
stateAsHeader: true
title: Color
slots: null

I think I should do some sort of “translation” from the LEDRGB_Color.state.
Can I use a JS function into the YAML code? Has anyone some example to start with?

  • Platform information:
    • Hardware: Raspberry 2B
    • OS: _OpenHabian
    • openHAB version: 3.2.0

Welcome to the forums.

Unfortunately, particularly with a cell widget, this is going to be very difficult. I won’t say “impossible”, but off the top of my head, I can’t see a way to make it work.

The real issue here is that the way the cells are built, color is not a direct conduit to the background of the element. The value of color gets concatenated into a class name that is applied to the cell (e.g., bg-color-green) which then gets styled via some default f7 styling from there. So color only accepts the colors names that are listed in the f7 theme docs.

You could inject css directly into the widget via the stylesheet property to override the f7 class stylings, but I believe the stylesheet property only accepts static text so you couldn’t import the item state into that css.

I haven’t spent a lot of time working with color states, so there may be a workaround. I’m just not aware of one.

I want to do this too.

My best guess was something like

component: f7-card
config:
  title: =items[props.item].state.split(",")[0]
  content: test
  style:
    background: hsl(items[props.item].state.split(",")[0], 100%, 50%)

items[props.item].state.split(",")[0] extracts the correct number from the color item,
and hsl(0.0,100%,50%) works,
but the above yaml doesn’t work.

This works as a very coarse approximation

background: '=(items[props.item].state.split(",")[0] >= 360-30) ? "hsl(0,100%,50%)" :
      (items[props.item].state.split(",")[0] >= 300-30) ? "hsl(300,100%,50%)" : 
      (items[props.item].state.split(",")[0] >= 240-30) ? "hsl(270,100%,50%)" : 
      (items[props.item].state.split(",")[0] >= 180-30) ? "hsl(180,100%,50%)" : 
      (items[props.item].state.split(",")[0] >= 120-30) ? "hsl(120,100%,50%)" : 
      (items[props.item].state.split(",")[0] >= 60-30) ? "hsl(60,100%,50%)" : 
      (items[props.item].state.split(",")[0] >= 0) ? "hsl(0,100%,50%)" : 
      "white"'

The original request was about an oh-cell where the background style won’t get applied properly, so unfortunately this won’t work for the original poster.

You’re close to getting this to work, there are just a few pieces to tweak. If you’re going to call an item state, then the property has to be an expression (the parses has to know to evaluate it instead of just keeping it as a string), so it has to start with an =. Then you just have to remember that you are trying to build a string with the item’s value inserted in the middle of it. So the rest of the expression has to be made up of string literals (must be in quotes). So the final form should look something like this:

background: ='hsl(' + items[props.item].state.split(",")[0] + ', 100%, 50%)'
1 Like

Wow! Thank you!
Yes that works as expected.

Sorry for hijacking the thread.

I’m actually trying to put this into an IF expression, and I can’t seem to apply the above learning.
I’m doing something wrong with ’ and ". I have tried a few variations without success.

I get as far as -

color: '=((items[props.bright].state > 0 || items[props.bright].state == "ON") && items[props.colorMode].state != "ON") ? "yellow": 
  ((items[props.bright].state > 0 || items[props.bright].state == "ON") && items[props.colorMode].state == "ON") ? "hsl(" + items[props.colorSel].state.split(",")[0] + ", 100%, 50%)" : 
  "gray"'

Can you see where my mistake is?

ok. This seems to work

component: f7-card
config:
  title: =items[props.colorSel].state.split(",")[0]
  content: test
  style:
    background: '=((items[props.bright].state > 0 || items[props.bright].state == "ON") && items[props.colorMode].state != "ON") ? "yellow":
      ((items[props.bright].state > 0 || items[props.bright].state == "ON") && items[props.colorMode].state == "ON") ? "hsl(" + items[props.colorSel].state.split(",")[0] + ", 100%, 50%)" : 
      "gray"'

But the same code doesn’t work when trying to apply it to the color of an f7 icon burried in a more complex widget.
The relevant lines start at line 100.

component: f7-card
config:
  backdrop: true
  class:
    - card-expandable-animate-width
  expandable: true
  style:
    background: '=(items[props.bright].state > 0 || items[props.bright].state == "ON") ? "linear-gradient(to bottom, hsla(48, 90%, 54%, 1), hsla(48, 90%, 95%, 1), 10% , hsla(0, 0%, 100%, 1) )": "white"'
    height: 170px
    margin: 5px
    margin-top: 10px
  swipeToClose: true
slots:
  default:
    - component: oh-button
      config:
        class:
          - cell-open-button
          - card-opened-fade-out
        color: gray
        iconF7: ellipsis
        iconSize: 30px
        style:
          padding-bottom: 40px
          padding-right: 15px
          padding-top: 10px
          position: absolute
          right: 0
          top: 0
          z-index: 999
    - component: f7-card-content
      config:
        style:
          padding-top: 30px
          width: 100%
      slots:
        default:
          - component: f7-icon
            config:
              color: '=((items[props.bright].state > 0 || items[props.bright].state == "ON") && items[props.colorMode].state != "ON") ? "yellow":
                ((items[props.bright].state > 0 || items[props.bright].state == "ON") && items[props.colorMode].state == "ON") ? "hsl(" + items[props.colorSel].state.split(",")[0] + ", 100%, 50%)" :
                "gray"'
              material: lightbulb
              size: '=(items[props.bright].state > 0 || items[props.bright].state == "ON") ? "110px": "90px"'
              style:
                opacity: '=(items[props.bright].state > 0 || items[props.bright].state == "ON") ? "100%": "10%"'
                position: absolute
                right: '=(items[props.bright].state > 0 || items[props.bright].state == "ON") ? "-5px": "0px"'
                top: '=(items[props.bright].state > 0 || items[props.bright].state == "ON") ? "45px": "60px"'
          - component: oh-button
            config:
              class:
                - card-opened-fade-in
                - cell-close-button
                - card-close
              color: black
              iconF7: xmark_circle_fill
              iconSize: 30px
              style:
                padding-bottom: 35px
                padding-top: 10px
                position: absolute
                right: 0
                top: 0
                z-index: 999
          - component: oh-link
            config:
              action: toggle
              actionCommand: '=(props.sbright) ? items[props.sbright].state: "ON"'
              actionCommandAlt: OFF
              actionItem: =props.bright
              class:
                - card-prevent-open
              style:
                height: 100%
                left: 0
                position: absolute
                top: 0
                width: 100%
                z-index: 0
          - component: f7-block
            config:
              class:
                - no-padding
              style:
                height: 200px
                margin: 0px
            slots:
              default:
                - component: f7-row
                  config:
                    style:
                      flex-wrap: nowrap
                      height: 65px
                      white-space: nowrap
                      width: auto
                  slots:
                    default:
                      - component: f7-col
                        slots:
                          default:
                            - component: Label
                              config:
                                style:
                                  font-weight: 600
                                  overflow: hidden
                                  text-overflow: ellipsis
                                  white-space: nowrap
                                text: =props.location
                            - component: f7-chip
                              config:
                                color: '=(items[props.bright].state > 0) ? "yellow": (items[props.bright].state == "ON") ? "yellow": "gray"'
                                text: '=(items[props.bright].state > 0) ? items[props.bright].state + " %": (items[props.bright].state == "ON") ? "ON": "OFF"'
                - component: f7-row
                  config:
                    class:
                      - justify-content-flex-start
                    style:
                      flex-wrap: nowrap
                      height: auto
                      white-space: nowrap
                  slots:
                    default:
                      - component: f7-icon
                        config:
                          color: '=(items[props.motion].state == "OFF" && items[props.motionOnOff].state == "ON") ? "blue" : (items[props.motion].state == "ON") ? "red" : (items[props.motionOnOff].state == "OFF") ? "gray" : "gray"'
                          f7: dot_radiowaves_right
                          size: 20px
                          style:
                            margin-right: 5px
                          visible: '=(props.motionOnOff) ? "true": "false"'
                      - component: f7-icon
                        config:
                          color: '=(items[props.oTtimer].state > 0 && (items[props.bright].state == 0 || items[props.bright].state == "OFF")) ? "blue": (items[props.oTtimer].state > 0 && (items[props.bright].state > 0 || items[props.bright].state != "OFF")) ? "red": "gray"'
                          f7: timer
                          size: 20px
                          style:
                            margin-right: 5px
                          visible: '=(props.oTtimer) ? "true": "false"'
                - component: f7-row
                  config:
                    style:
                      height: auto
                      overflow: hidden
                      width: 100%
                    visible: '=(props.illum) ? "true": "false"'
                  slots:
                    default:
                      - component: f7-col
                        config:
                          style:
                            align-self: flex-end
                            flex-wrap: nowrap
                        slots:
                          default:
                            - component: f7-row
                              config:
                                class:
                                  - justify-content-flex-start
                                style:
                                  flex-wrap: nowrap
                                  margin-top: 5px
                              slots:
                                default:
                                  - component: f7-icon
                                    config:
                                      color: yellow
                                      f7: light_max
                                      size: 18px
                                      style:
                                        margin-left: 0px
                                        margin-top: 0px
                                  - component: Label
                                    config:
                                      style:
                                        color: gray
                                        font-size: 12px
                                        margin-left: 8px
                                        overflow: hidden
                                        text-overflow: ellipsis
                                        white-space: nowrap
                                      text: =items[props.illum].state
                - component: f7-row
                  config:
                    style:
                      height: 20px
                      overflow: hidden
                      width: 100%
                    visible: '=(props.illumt) ? "true": "false"'
                  slots:
                    default:
                      - component: f7-col
                        config:
                          style:
                            align-self: flex-end
                            flex-wrap: nowrap
                        slots:
                          default:
                            - component: f7-row
                              config:
                                class:
                                  - justify-content-flex-start
                                style:
                                  flex-wrap: nowrap
                                  margin-top: 5px
                              slots:
                                default:
                                  - component: f7-icon
                                    config:
                                      color: '=((Number.parseFloat(items[props.illumt].state.split(" ")[0])) < (Number.parseFloat(items[props.illum].state.split(" ")[0]))) ? "gray": (items[props.motionOnOff].state == "OFF") ? "gray": "green"'
                                      f7: increase_indent
                                      size: 18px
                                      style:
                                        margin-left: 0px
                                        margin-top: 0px
                                  - component: Label
                                    config:
                                      style:
                                        color: gray
                                        font-size: 12px
                                        margin-left: 8px
                                        overflow: hidden
                                        text-overflow: ellipsis
                                        white-space: nowrap
                                      text: =items[props.illumt].state
          - component: f7-block
            config:
              class:
                - card-prevent-open
                - card-content-padding
            slots:
              default:
                - component: oh-list
                  config:
                    class:
                      - padding
                  slots:
                    default:
                      - component: oh-toggle-item
                        config:
                          actionCommand: '=(props.sbright) ? items[props.sbright].state: "ON"'
                          actionCommandAlt: OFF
                          color: yellow
                          icon: f7:power
                          item: =props.bright
                          title: On/Off
                      - component: oh-stepper-item
                        config:
                          autorepeat: true
                          autorepeatDynamic: true
                          color: '=(items[props.bright].state > 0) ? "yellow" : "gray"'
                          fill: true
                          icon: oh:slider
                          iconUseState: true
                          item: =props.bright
                          max: 100
                          min: 0
                          round: true
                          small: true
                          title: Brightness
                          visible: '=(props.sbright) ? "true": "false"'
                      - component: oh-stepper-item
                        config:
                          autorepeat: true
                          autorepeatDynamic: true
                          color: blue
                          fill: true
                          icon: oh:slider
                          iconUseState: true
                          item: =props.sbright
                          max: 100
                          min: 0
                          round: true
                          small: true
                          title: Scene Brightness
                          visible: '=(props.sbright) ? "true": "false"'
                      - component: oh-list-item
                        config:
                          action: toggle
                          actionCommand: ON
                          actionCommandAlt: OFF
                          actionItem: =props.motionOnOff
                          badge: '=(items[props.motionOnOff].state == "ON" && (Number.parseFloat(items[props.illumt].state.split(" ")[0])) >= (Number.parseFloat(items[props.illum].state.split(" ")[0]))) ? "AUTO": (items[props.motionOnOff].state == "OFF") ? "OFF": (items[props.motionOnOff].state == "ON" && (Number.parseFloat(items[props.illumt].state.split(" ")[0])) < (Number.parseFloat(items[props.illum].state.split(" ")[0]))) ? "TOO BRIGHT": (items[props.motionOnOff].state == "ON") ? "AUTO": items[props.motionOnOff].displayState'
                          badge-color: '=(items[props.motionOnOff].state == "ON" && (Number.parseFloat(items[props.illumt].state.split(" ")[0])) >= (Number.parseFloat(items[props.illum].state.split(" ")[0])) && items[props.motion].state == "OFF") ? "blue": (items[props.motionOnOff].state == "OFF") ? "black": (items[props.motionOnOff].state == "ON" && (Number.parseFloat(items[props.illumt].state.split(" ")[0])) < (Number.parseFloat(items[props.illum].state.split(" ")[0]))) ? "yellow": (items[props.motion].state == "ON" && items[props.motionOnOff].state == "ON" && (Number.parseFloat(items[props.illumt].state.split(" ")[0])) < (Number.parseFloat(items[props.illum].state.split(" ")[0]))) ? "green": "red"'
                          icon: f7:dot_radiowaves_right
                          title: Motion detection
                          visible: '=(props.motionOnOff) ? "true": "false"'
                      - component: oh-stepper-item
                        config:
                          autorepeat: true
                          autorepeatDynamic: true
                          color: '=(items[props.motionOnOff].state == "ON") ? "blue": "gray"'
                          fill: true
                          footer: in Minutes
                          icon: f7:timer
                          item: =props.mtimer
                          max: 600
                          min: 1
                          round: true
                          small: true
                          title: Motion Timer
                          visible: "=(props.mtimer) ? true: false"
                      - component: oh-stepper-item
                        config:
                          autorepeat: true
                          autorepeatDynamic: true
                          color: '=(Number.parseFloat(items[props.illumt].state.split(" ")[0])) < (Number.parseFloat(items[props.illum].state.split(" ")[0])) ? "gray": (items[props.motionOnOff].state == "OFF") ? "gray": "green"'
                          fill: true
                          footer: '=(Number.parseFloat(items[props.illumt].state.split(" ")[0])) < (Number.parseFloat(items[props.illum].state.split(" ")[0])) ? "Currently " + items[props.illum].state + " - Too bright" : "Currently " + items[props.illum].state'
                          icon: f7:light_max
                          item: =props.illumt
                          max: 600
                          round: true
                          small: true
                          title: lux Threshold
                          visible: "=(props.illumt) ? true: false"
                      - component: oh-stepper-item
                        config:
                          autorepeat: true
                          autorepeatDynamic: true
                          color: '=(items[props.oTtimer].state == "0") ? "gray": "blue"'
                          fill: true
                          footer: in Minutes
                          icon: f7:timer
                          item: =props.oTtimer
                          max: 600
                          min: 0
                          round: true
                          small: true
                          title: Auto Off
                          visible: "=(props.oTtimer) ? true: false"
                      - component: oh-list-item
                        config:
                          action: toggle
                          actionCommand: ON
                          actionCommandAlt: OFF
                          actionItem: =props.colorMode
                          badge: =items[props.colorMode].displayState
                          badge-color: blue
                          footer: RGB or White
                          icon: oh:colorwheel
                          title: Colour Mode
                          visible: "=(props.colorMode) ? true: false"
                      - component: oh-colorpicker-item
                        config:
                          icon: oh:colorwheel
                          item: =props.colorSel
                          modules:
                            - hue-slider
                          title: Color Select
                          visible: '=(items[props.colorMode].state == "ON") ? "true": "false"'

On further experimenting, it seems I can’t apply hsl, rgb, or web# colors to the f7-icon component, only word colors eg red, blue etc
The expression wasn’t the problem.

*Update
Got it.
For the f7-icon component, the color: line has to be in style:, not config:

When using the widget editor, remember that you can always press ctrl + space to get a list of all the config options for a component when you’re on an options line.

One other small note:

Works only because you are comparing the brightness state to 0. The items object always returns a string, which can often lead to unexpected results when using > or <. For the best results you should convert that to a number for numerical comparisons:

Number(items[props.bright].state) > 0
1 Like

Thanks for all that. It’s working well now.