Room Card with status overview

full data

The room card widget provides a quick overview for many states in one room and is fully configurable.
You can use a background image and you may use a header.
Color scheme and opacity is fully configurable for the columns.

This widget is part of my personal custom developed widget set, which is available on GitHub: openhab-conf/UI/widgets at main · florian-h05/openhab-conf · GitHub.

Data displayed

The widget can display up to three columns of data, each data field can and has to be configured:

  1. Humidity and illumination
  2. Current temperature, target temperature (in braces), heating & cooling state
  3. Lights state (on/off + number of lights on), windows/doors (for each open/closed + number of open), one or two blinds position, speaker state

The widget was inspired by the cards of the location tab and credits for the basic concept go to @Integer at [OH3] Main UI Examples - #22 by Integer.

Screenshots

minimalistic

Changelog

The git history can be seen as a changelog: History for UI/widgets/florianh-widgetset/roomCard.yaml - florian-h05/openhab-conf · GitHub.

Resources

https://github.com/florian-h05/openhab-conf/raw/main/UI/widgets/florianh-widgetset/roomCard.yaml

4 Likes

Line 254 (actual temperature) should be

“=(items[props.temp].displayState ? items[props.temp].displayState : items[props.temp].state) + (props.settemp ? ’ (’ + items[props.settemp].state + ‘)’ : ‘’)”

instead of

“=(items[props.temp].displayState) + (props.settemp ? ’ (’ + items[props.settemp].displayState + ‘)’ : ‘’)”

in case of using innogy thermostat, but maybe on all other thermostats as well

@Andy_Eichhorst
Thanks for that tip.

I had no problems only using displayState, but yeah, sometimes displayState is not available, so I updated the whole widget to always fall back to state when displayState is not available.

1 Like

Hi Florian, all

I like your widget. Interesting for me to learn yaml code.

I do have a question on your last lines of code. Instead of opening a new “page” (which I could do of course) I would like to use the semantic model functionality like the one form the the standard “label cell” to open a group popup Item (actionGroupPopupItem) instead.

what I did was to replace your last lines of code se below.

Your stuff :

 - component: oh-link
      config:
        action: navigate
        actionPage: ='page:' + props.page
        style:
          height: 125px
          left: 0px
          position: absolute
          top: 0px
          width: 100%
        visible: "=props.page ? true : false"

with my idea of using your “page” property to show the group as popup

- component: oh-link
      config:
        action: group
        actionGroupPopupItem: props.page
        expandable: false
        item: props.page
        stateAsHeader: true
        title: props.page

But when I hover over the room card unfortunately the mouse pointer is not changing to a “hand” indicating that you can even “click the card”. despite the fact the nothing is happening :frowning:

I am not a developer just an advanced OH user currently migrating from OH2.5 to v3.4 and learning on how to use the new pages concept…,If you have an idea let me know

I think I found an example from AndrasU : Widgets
which does the trick.

If I understand correctly in addition to the props: parameters: he added a props: parameterGroups function which allows in the UI config to select the “group” function and then from the sematic model you select the group you want to have displayed as button popup (without the need to create an additional page) .

  parameterGroups:
    - name: buttonAction
      context: action
      label: Action
      description: Action to start

with a subsequent oh-button action

 - component: oh-button
      config:
        actionPropsParameterGroup: buttonAction
        fill: false
        style:
          width: 100%
          height: 100%
          no-border: true
          background: '=(props.backgroundImageUrl) ? "url(" + props.backgroundImageUrl + ")" : (props.colorCodeTop_d) ? (props.colorCodeTop_d) : "#AFDFFF"'
          background-size: cover
        class:
          - no-padding

The design of the card itself is as everyone wants to configure but I quite like it…
So thanks Andras, I am learning ervery day

bkumio

Yes, thats quite practical. Most of my widgets actually use the action configuration via the parameter group in the UI, but my room card doesn‘t as I only use pages with it‘s action.

I would do it as following, but I guess it does the same as your modification:

    - name: widgetAction
      context: action
      label: Action settings
      description: Action to perform when the widget is clicked
    - component: oh-link
      config:
        actionPropsParameterGroup: widgetAction
        style:
          height: 125px
          left: 0px
          position: absolute
          top: 0px
          width: 100%

@bkumio BTW: I have a full custom widgetset, you can find it on GitHub: openhab-conf/UI/widgets at main · florian-h05/openhab-conf · GitHub.

Hello!
Great widget! Is there a chance that you add custom items ex. item one … /icon off … / icon on ?
I would add TV/PS4/AV or NestHub.

Unfortunately I‘ve no idea how to do that: dynamically adding custom items with custom icons. If you have an idea, please let me know.
Note that you can install from the marketplace and then modify the widget to your needs.

Yes! I mod it!

I added:
TV
Settop box (android/sattelite etc.)
Changed speaker icon to hifi speaker ( home cinema)
Console
Google speaker

Should or can I post it here?

1 Like

Feel free to post here if you want to, I will see if I add those to the widget. (Note that I cannot add all icons/Items that people use, because then the widget would end up getting huge. I mean, everyone can add anything he wants to to the widget and further customize it.)

My „problem“ with the hifispeaker icon is, that there is no icon version to display the off state. How do you handle that state? Hide the icon?
Same goes for the console icon.

I just add next items and icons. I don’t have binds so it isn’t displayed.
For ON state i use filled (black) icons for OFF white ones.

uid: roomCard_max
tags:
  - community.openhab.org
  - florianh-widgetset
props:
  parameters:
    - description: Title to display in upper right corner
      label: Header
      name: text_header
      required: false
      type: TEXT
    - description: web address of background image
      label: Background image
      name: image
      required: false
      type: TEXT
    - default: black
      description: HEX, rgba or name, e.g. white or black
      label: Background color
      name: bgcolor
      required: true
      type: TEXT
    - default: "0.6"
      description: decimal, e.g. 0.6
      label: Background opacity
      name: bgopacity
      required: true
      type: TEXT
    - default: white
      description: icon & text color, e.g. black or white
      label: Icon & text color
      name: color
      required: true
      type: TEXT
    - description: Page which will be navigated to
      label: Page ID
      name: page
      required: false
    - context: item
      description: item/group for light(s)
      label: Light(s) item
      name: light
      required: false
      type: TEXT
    - context: item
      description: Group:Number:COUNT(ON) item for numbers of lights on
      label: Number of lights on
      name: lights_number
      required: false
      type: TEXT
    - context: item
      description: item for windows(s)
      label: Window(s) item
      name: window
      required: false
      type: TEXT
    - context: item
      description: Group:Number:COUNT(CLOSED) item for numbers of windows open
      label: Number of windows open
      name: windows_number
      required: false
      type: TEXT
    - context: item
      description: item for temperature
      label: Temperature item
      name: temp
      required: false
      type: TEXT
    - context: item
      description: item for set temperature
      label: Set temperature item
      name: settemp
      required: false
      type: TEXT
    - context: item
      description: item for blinds
      label: Blind(s) item
      name: blinds
      required: false
      type: TEXT
    - context: item
      description: item for blinds
      label: Blind 2 item
      name: blinds2
      required: false
      type: TEXT
    - context: item
      description: item for heating state
      label: Heating state item
      name: heating
      required: false
      type: TEXT
    - context: item
      description: item for cooling state
      label: Cooling state item
      name: cooling
      required: false
      type: TEXT
    - context: item
      description: item for humidity
      label: Humidity item
      name: humidity
      required: false
      type: TEXT
    - context: item
      description: item for illuminance
      label: Illuminance item
      name: illuminance
      required: false
      type: TEXT
    - context: item
      description: item for door state(s)
      label: Door state(s)
      name: door_state
      required: false
      type: TEXT
    - context: item
      description: item for door lock(s)
      label: Door lock(s)
      name: door_lock
      required: false
      type: TEXT
    - context: item
      description: Item for garagedoor state(s)
      label: Garagedoor state(s)
      name: garagedoor_state
      required: false
      type: TEXT
    - context: item
      description: item for TV
      label: TV(s) item
      name: tv
      required: false
      type: TEXT
    - context: item
      description: item for TV Box
      label: TV Box item
      name: tvbox
      required: false
      type: TEXT
    - context: item
      description: item for speaker(s)
      label: Speaker(s) item
      name: speaker
      required: false
      type: TEXT
    - context: item
      description: item for gaming console
      label: Gaming console
      name: console
      required: false
      type: TEXT
    - context: item
      description: item for Google speaker
      label: Google speaker
      name: google_speaker
      required: false
      type: TEXT
timestamp: Jan 28, 2023, 9:14:40 PM
component: f7-card
config:
  style:
    --f7-chip-bg-color: rgba(255, 255, 255, 0.0)
    --f7-chip-height: 22px
    --f7-chip-padding-horizontal: 10px
    --f7-chip-text-color: =props.color
    background-image: ='url(' + props.image + ')'
    background-position: center
    background-size: cover
    border-radius: var(--f7-card-expandable-border-radius)
    box-shadow: 5px 5px 10px 1px rgba(0,0,0,0.1)
    class:
      - padding: 0px
    height: 130px
    margin-left: 5px
    margin-right: 5px
    noShadow: false
slots:
  content:
    - component: f7-block
      config:
        style:
          background: =props.bgcolor
          border-radius: 7px
          opacity: =props.bgopacity
          position: absolute
          right: 16px
          top: -5px
        visible: "=props.text_header ? true : false"
      slots:
        default:
          - component: Label
            config:
              style:
                color: =props.color
                font-size: 20px
                font-weight: 600
                margin-left: 0px
                margin-top: 0px
              text: =props.text_header
    - component: f7-block
      config:
        style:
          background: =props.bgcolor
          border-radius: 7px
          bottom: -75px
          left: 16px
          opacity: =props.bgopacity
          position: absolute
      slots:
        default:
          - component: f7-chip
            config:
              iconColor: =props.color
              iconF7: "=items[props.light].state == 'ON' ? 'lightbulb_fill' : 'lightbulb_slash'"
              iconSize: 18
              text: "=props.lights_number ? ((items[props.light].state == 'ON') ? items[props.lights_number].state : '') : ''"
              visible: "=props.light ? true : false"
          - component: f7-chip
            config:
              visible: "=props.garagedoor_state ? true : false"
            slots:
              media:
                - component: oh-icon
                  config:
                    icon: "=items[props.garagedoor_state].state === 'CLOSED' ? 'mygaragedoor-closed' : 'mygaragedoor-open'"
                    iconSize: 24
                    style:
                      height: 24px
          - component: f7-chip
            config:
              visible: "=props.door_state ? true : false"
            slots:
              media:
                - component: oh-icon
                  config:
                    icon: "=items[props.door_state].state === 'CLOSED' ? 'door-closed' : 'door-open'"
                    iconSize: 24
                    style:
                      height: 24px
          - component: f7-chip
            config:
              text: "=(items[props.window].state == 'OPEN') ? (props.windows_number ? items[props.windows_number].state : '') : ''"
              visible: "=props.window ? true : false"
            slots:
              media:
                - component: oh-icon
                  config:
                    icon: "=items[props.window].state === 'CLOSED' ? 'window-closed' : 'window-open'"
                    iconSize: 24
                    style:
                      height: 24px
          - component: f7-chip
            config:
              iconColor: =props.color
              iconF7: "=items[props.door_lock].state === 'ON' ? 'lock_open' : 'lock'"
              iconSize: 18
              visible: "=props.door_lock ? true : false"
          - component: f7-chip
            config:
              iconColor: =props.color
              iconF7: arrow_up_arrow_down
              iconSize: 18
              text: "=props.blinds2 ? items[props.blinds].state + ' | ' + items[props.blinds2].displayState : items[props.blinds].displayState"
              visible: "=props.blinds ? true : false"
          - component: f7-chip
            config:
              iconColor: =props.color
              iconF7: "=items[props.tv].state === 'ON' ? 'tv_fill' : 'tv'"
              iconSize: 18
              visible: "=props.tv ? true : false"
          - component: f7-chip
            config:
              iconColor: =props.color
              iconF7: "=items[props.tvbox].state === 'ON' ? 'ticket_fill' : 'ticket'"
              iconSize: 18
              visible: "=props.tvbox ? true : false"
          - component: f7-chip
            config:
              iconColor: =props.color
              iconF7: "=items[props.speaker].state === 'ON' ? 'hifispeaker_fill' : 'hifispeaker'"
              iconSize: 18
              visible: "=props.speaker ? true : false"
          - component: f7-chip
            config:
              iconColor: =props.color
              iconF7: "=items[props.console].state === 'ON' ? 'gamecontroller_fill' : 'gamecontroller'"
              iconSize: 18
              visible: "=props.console ? true : false"
          - component: f7-chip
            config:
              iconColor: =props.color
              iconF7: "=items[props.google_speaker].state === 'ON' ? 'logo_google' : 'nosign'"
              iconSize: 18
              visible: "=props.google_speaker ? true : false"
    - component: f7-block
      config:
        style:
          background: =props.bgcolor
          border-radius: 7px
          bottom: -45px
          left: 16px
          opacity: =props.bgopacity
          position: absolute
      slots:
        default:
          - component: f7-chip
            config:
              iconColor: =props.color
              iconF7: thermometer
              iconSize: 18
              text: "=(items[props.temp].displayState ? items[props.temp].displayState : items[props.temp].state) +  (props.settemp ? ' (' + (items[props.settemp].displayState ? items[props.settemp].displayState : items[props.settemp].state) + ')' : '')"
              visible: "=props.temp ? true : false"
          - component: f7-chip
            config:
              iconColor: =props.color
              iconF7: flame
              iconSize: 18
              visible: "=props.heating ? items[props.heating].state === 'ON' : false"
          - component: f7-chip
            config:
              iconColor: =props.color
              iconF7: circle_grid_hex
              iconSize: 18
              visible: "=props.cooling ? items[props.cooling].state === 'ON' : false"
    - component: f7-block
      config:
        style:
          background: =props.bgcolor
          border-radius: 7px
          bottom: -15px
          left: 16px
          opacity: =props.bgopacity
          position: absolute
      slots:
        default:
          - component: f7-chip
            config:
              iconColor: =props.color
              iconF7: drop
              iconSize: 18
              text: "=items[props.humidity].displayState ? items[props.humidity].displayState : items[props.humidity].state"
              visible: "=props.humidity ? true : false"
          - component: f7-chip
            config:
              iconColor: =props.color
              iconF7: sun_min
              iconSize: 18
              text: "=items[props.illuminance].displayState ? items[props.illuminance].displayState : items[props.illuminance].state"
              visible: "=props.illuminance ? true : false"
    - component: oh-link
      config:
        action: navigate
        actionPage: ='page:' + props.page
        style:
          height: 125px
          left: 0px
          position: absolute
          top: 0px
          width: 100%
        visible: "=props.page ? true : false"

roomcardmax

Do you know how I can hide icons? It could be interesting.

Is there a possibility that click on the widget navigates to location ex. Livingroom ?

IMO the other way (black for off, on for white) makes more sense, but that’s up to you :wink: You can modify the widget in any way you want.

Yes, the widget actually already does this for all icons if the corresponding Item is not set.

Just set the visible parameter of the f7-chip to an expression like:

"=items[props.someitem].state === 'ON' ? true : false"

This will display the icon if the Item defined in the someitem property has the state ON and hide the icon for all other Item states. Note that for the existing f7-chips you need to extend the expression because it already covers the case that an Item property is not set.

AFAIK no, there is no way to navigate to the auto-generated page of a semantic location (if you mean that).