[OH3] Main UI Examples

Thanks for the 2 color widgets! Very useful.

Where do you all grab the icons? I prefer the ones from materialdesignicons, but I’m missing icons for specific rooms etc.

Another thing I’m looking for is to change the default page. I prefer to set my own (tabbed) page as default. No I always need to click in the left sidebar first.

I downloaded several icons from Free vector icons - SVG, PSD, PNG, EPS & Icon Font - Thousands of free icons as png files and adjusted these with the app paint.net according my needs (paint does not support transparent background but paint.net does).

Changed cell-temp-card to suit my MegaD Wallmount sensors, which have temperature, humidity, lightlevel, co2 and motion sensors inside.


Code for temperature card:

uid: Cell_Temp_Card_2
tags:
  - temperature
  - humidity
  - co
  - motion
props:
  parameters:
    - description: Small title on top of the card
      label: Title
      name: title
      required: false
      type: TEXT
    - description: Icon on top of the card (only f7 icons (without f7:))
      label: Icon
      name: icon
      required: false
      type: TEXT
    - description: Background image name
      label: Background image
      name: bg_image_url
      required: false
      type: TEXT
    - description: in rgba() or HEX or empty
      label: Background Color
      name: bgcolor
      required: false
      type: TEXT
    - context: item
      label: Temperature
      name: temp_item
      required: false
      type: TEXT
    - context: item
      label: Lightlevel
      name: lightlevel_item
      required: false
      type: TEXT
    - context: item
      label: Humidity
      name: humidity_item
      required: false
      type: TEXT
    - context: item
      label: CO
      name: CO_item
      required: false
      type: TEXT
    - context: item
      label: Motion item
      name: motion_item
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Aug 1, 2021, 2:48:53 PM
component: f7-card
config:
  style:
    noShadow: false
    padding: 0
    margin: 5
    border-radius: var(--f7-card-expandable-border-radius)
    box-shadow: 5px 5px 10px 1px rgba(0,0,0,0.1)
    background-color: "=props.bgcolor ? props.bgcolor : ''"
    height: 150px
    background-image: "=props.bg_image_url ? 'url(/static/' + (props.bg_image_url) + ')' : ''"
    background-position: down;
    background-repeat: no-repeat;
    background-size: cover
    background-brightness: 60%
    font-size: medium
    text-shadow: -1px -1px 0 black, 1px -1px 0 black, -1px 1px 0 black, 1px 1px 0 black
slots:
  content:
    - component: f7-card-header
      config:
        style:
          padding: 0
          margin-top: -15px
          min-height: 30px
          justify-content: flex-start
      slots:
        default:
          - component: f7-icon
            config:
              f7: =props.icon
              size: 20
              visible: "=props.icon ? true : false"
          - component: Label
            config:
              text: "=props.title ? props.title : ''"
              style:
                font-size: 18px
                margin-left: 5px
    - component: f7-card-content
      config:
        style:
          padding: 0
          margin-top: 5px
          width: 100%
          justify-content: flex-start
      slots:
        default:
          - component: f7-row
            config:
              visible: "=props.temp_item ? true : false"
              style:
                justify-content: flex-start
            slots:
              default:
                - component: oh-icon
                  config:
                    icon: temperature
                    item: =props.temp_item
                    width: 23
                - component: Label
                  config:
                    text: =items[props.temp_item].state
                    style:
                      margin-left: 5px
                      color: '=(Number.parseFloat(items[props.temp_item].state.split(" ")[0]) > 30) ? "red" : (Number.parseFloat(items[props.temp_item].state.split(" ")[0]) < 10) ? "blue" : "white"'
          - component: f7-row
            config:
              visible: "=props.humidity_item ? true : false"
              style:
                justify-content: flex-start
                z-index: 2
            slots:
              default:
                - component: oh-icon
                  config:
                    icon: humidity
                    item: =props.humidity_item
                    width: 23
                    action: analyser
                    actionAnalyzerItems: =props.humidity_item
                - component: Label
                  config:
                    text: =items[props.humidity_item].state
                    style:
                      color: '=(Number.parseFloat(items[props.humidity_item].state.split(" ")[0]) < 35) ? "red" : (Number.parseFloat(items[props.humidity_item].state.split(" ")[0]) > 75) ? "green" : "white"'
                      margin-left: 5px
          - component: f7-row
            config:
              visible: "=props.lightlevel_item ? true : false"
              style:
                justify-content: flex-start
                z-index: 2
            slots:
              default:
                - component: oh-icon
                  config:
                    icon: sun
                    width: 23
                - component: Label
                  config:
                    text: =items[props.lightlevel_item].state
                    style:
                      color: "=(items[props.lightlevel_item].state < 5) ? 'gray' : 'white'"
                      margin-left: 5px
          - component: f7-row
            config:
              visible: "=props.CO_item ? true : false"
              style:
                justify-content: flex-start
                z-index: 2
            slots:
              default:
                - component: oh-icon
                  config:
                    icon: carbondioxide
                    width: 23
                - component: Label
                  config:
                    text: =items[props.CO_item].state
                    style:
                      color: '=(Number.parseFloat(items[props.CO_item].state.split(" ")[0]) > 1500) ? "red" : (Number.parseFloat(items[props.CO_item].state.split(" ")[0]) > 1000) ? "yellow"'
                      margin-left: 5px
          - component: f7-col
            config:
              visible: "=props.motion_item ? true : false"
              style:
                position: absolute
                top: 0px
                right: 0px
                z-index: 2
            slots:
              default:
                - component: oh-icon
                  config:
                    icon: "=(items[props.motion_item].state === 'ON') ? 'mymotion-on' : 'mymotion-off'"
                    width: 30
                - component: Label
                  config:
                    text: =items[props.motion_item].state
          - component: f7-block
            config:
              style:
                visible: "=props.temp_item ? true : false"
                position: absolute
                top: 10px
                left: 10px
                height: 300px
                width: 100%
                z-index: 1
            slots:
              default:
                - component: oh-trend
                  config:
                    trendItem: =props.temp_item
                    trendGradient:
                      - "#d4220f"
                      - "#cc561e"
                      - "#ef8d32"
                      - "#beca5c"
                    style:
                      --f7-theme-color-bg-color: transparent
                      background: var(--f7-theme-color-bg-color)
                      filter: opacity(60%)
    - component: oh-link
      config:
        actionAnalyzerChartType: day
        action: analyzer
        actionAnalyzerItems: "=props.CO_item ? [props.temp_item, props.humidity_item, props.lightlevel_item, props.CO_item] : (props.lightlevel_item ? [props.temp_item, props.humidity_item, props.lightlevel_item] : (props.humidity_item ? [props.temp_item, props.humidity_item] : [props.temp_item]))"
        actionAnalyzerCoordSystem: time
        style:
          padding: 0
          position: absolute
          left: 0px
          top: 0px
          height: 100%
          width: 100%
          z-index: 3

For Yeelight control with [miio] binding:

uid: Cell_Temp_Card_2
tags:
  - temperature
  - humidity
  - co
  - motion
props:
  parameters:
    - description: Small title on top of the card
      label: Title
      name: title
      required: false
      type: TEXT
    - description: Icon on top of the card (only f7 icons (without f7:))
      label: Icon
      name: icon
      required: false
      type: TEXT
    - description: Background image name
      label: Background image
      name: bg_image_url
      required: false
      type: TEXT
    - description: in rgba() or HEX or empty
      label: Background Color
      name: bgcolor
      required: false
      type: TEXT
    - context: item
      label: Temperature
      name: temp_item
      required: false
      type: TEXT
    - context: item
      label: Lightlevel
      name: lightlevel_item
      required: false
      type: TEXT
    - context: item
      label: Humidity
      name: humidity_item
      required: false
      type: TEXT
    - context: item
      label: CO
      name: CO_item
      required: false
      type: TEXT
    - context: item
      label: Motion item
      name: motion_item
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Aug 1, 2021, 2:48:53 PM
component: f7-card
config:
  style:
    noShadow: false
    padding: 0
    margin: 5
    border-radius: var(--f7-card-expandable-border-radius)
    box-shadow: 5px 5px 10px 1px rgba(0,0,0,0.1)
    background-color: "=props.bgcolor ? props.bgcolor : ''"
    height: 150px
    background-image: "=props.bg_image_url ? 'url(/static/' + (props.bg_image_url) + ')' : ''"
    background-position: down;
    background-repeat: no-repeat;
    background-size: cover
    background-brightness: 60%
    font-size: medium
    text-shadow: -1px -1px 0 black, 1px -1px 0 black, -1px 1px 0 black, 1px 1px 0 black
slots:
  content:
    - component: f7-card-header
      config:
        style:
          padding: 0
          margin-top: -15px
          min-height: 30px
          justify-content: flex-start
      slots:
        default:
          - component: f7-icon
            config:
              f7: =props.icon
              size: 20
              visible: "=props.icon ? true : false"
          - component: Label
            config:
              text: "=props.title ? props.title : ''"
              style:
                font-size: 18px
                margin-left: 5px
    - component: f7-card-content
      config:
        style:
          padding: 0
          margin-top: 5px
          width: 100%
          justify-content: flex-start
      slots:
        default:
          - component: f7-row
            config:
              visible: "=props.temp_item ? true : false"
              style:
                justify-content: flex-start
            slots:
              default:
                - component: oh-icon
                  config:
                    icon: temperature
                    item: =props.temp_item
                    width: 23
                - component: Label
                  config:
                    text: =items[props.temp_item].state
                    style:
                      margin-left: 5px
                      color: '=(Number.parseFloat(items[props.temp_item].state.split(" ")[0]) > 30) ? "red" : (Number.parseFloat(items[props.temp_item].state.split(" ")[0]) < 10) ? "blue" : "white"'
          - component: f7-row
            config:
              visible: "=props.humidity_item ? true : false"
              style:
                justify-content: flex-start
                z-index: 2
            slots:
              default:
                - component: oh-icon
                  config:
                    icon: humidity
                    item: =props.humidity_item
                    width: 23
                    action: analyser
                    actionAnalyzerItems: =props.humidity_item
                - component: Label
                  config:
                    text: =items[props.humidity_item].state
                    style:
                      color: '=(Number.parseFloat(items[props.humidity_item].state.split(" ")[0]) < 35) ? "red" : (Number.parseFloat(items[props.humidity_item].state.split(" ")[0]) > 75) ? "green" : "white"'
                      margin-left: 5px
          - component: f7-row
            config:
              visible: "=props.lightlevel_item ? true : false"
              style:
                justify-content: flex-start
                z-index: 2
            slots:
              default:
                - component: oh-icon
                  config:
                    icon: sun
                    width: 23
                - component: Label
                  config:
                    text: =items[props.lightlevel_item].state
                    style:
                      color: "=(items[props.lightlevel_item].state < 5) ? 'gray' : 'white'"
                      margin-left: 5px
          - component: f7-row
            config:
              visible: "=props.CO_item ? true : false"
              style:
                justify-content: flex-start
                z-index: 2
            slots:
              default:
                - component: oh-icon
                  config:
                    icon: carbondioxide
                    width: 23
                - component: Label
                  config:
                    text: =items[props.CO_item].state
                    style:
                      color: '=(Number.parseFloat(items[props.CO_item].state.split(" ")[0]) > 1500) ? "red" : (Number.parseFloat(items[props.CO_item].state.split(" ")[0]) > 1000) ? "yellow"'
                      margin-left: 5px
          - component: f7-col
            config:
              visible: "=props.motion_item ? true : false"
              style:
                position: absolute
                top: 0px
                right: 0px
                z-index: 2
            slots:
              default:
                - component: oh-icon
                  config:
                    icon: "=(items[props.motion_item].state === 'ON') ? 'mymotion-on' : 'mymotion-off'"
                    width: 30
                - component: Label
                  config:
                    text: =items[props.motion_item].state
          - component: f7-block
            config:
              style:
                visible: "=props.temp_item ? true : false"
                position: absolute
                top: 10px
                left: 10px
                height: 300px
                width: 100%
                z-index: 1
            slots:
              default:
                - component: oh-trend
                  config:
                    trendItem: =props.temp_item
                    trendGradient:
                      - "#d4220f"
                      - "#cc561e"
                      - "#ef8d32"
                      - "#beca5c"
                    style:
                      --f7-theme-color-bg-color: transparent
                      background: var(--f7-theme-color-bg-color)
                      filter: opacity(60%)
    - component: oh-link
      config:
        actionAnalyzerChartType: day
        action: analyzer
        actionAnalyzerItems: "=props.CO_item ? [props.temp_item, props.humidity_item, props.lightlevel_item, props.CO_item] : (props.lightlevel_item ? [props.temp_item, props.humidity_item, props.lightlevel_item] : (props.humidity_item ? [props.temp_item, props.humidity_item] : [props.temp_item]))"
        actionAnalyzerCoordSystem: time
        style:
          padding: 0
          position: absolute
          left: 0px
          top: 0px
          height: 100%
          width: 100%
          z-index: 3

Hi Mike,
can I use the overview without a weather station? If so, how and where do I have to integrate the items? Your overview is exactly to my taste and that’s why I’m trying to recreate it. It would also be cool if I could somehow only see the individual rooms when I clicked on a floor.

Thanks in advance for your support and the great templates.

Greetings Norman

Hey Norman @BlackEagle!

Nice to hear that you like my UI.

We are both German speakers, but I think in this forum it helps everyone if we write in English :slight_smile: The result is then just not always perfect English, but that seems to bother here no one :slight_smile:

You can use the data of the Open weather map binding (use the OneCall API). Here you can find a good tutorial how to add it via the UI.
[OH3] Install & Set-up OpenWeatherMap via UI - Tutorials & Examples / Solutions - openHAB Community

Then you can use these items:

Unfortunately, the lightning and lux values are not available. you can simply remove these two f7-chips from the widget code:

          - component: f7-chip
            config:
              iconF7: sun_min
              text: =items[props.item_ill].displayState
              style:
                margin-bottom: 10px
                font-size: 16px
                --f7-chip-bg-color: rgba(255, 255, 255, 0)
              iconColor: "=themeOptions.dark === 'dark' ? 'white' : 'black'"
              iconSize: 20

and

          - component: f7-chip
            config:
              iconF7: bolt
              text: =items[props.item_strike].state
              style:
                margin-bottom: 10px
                font-size: 16px
                --f7-chip-bg-color: rgba(255, 255, 255, 0)
              iconColor: "=themeOptions.dark === 'dark' ? 'white' : 'black'"
              iconSize: 20

Hi, everyone,
sorry for such simple questions but I’m still brand new to OpenHAB and can’t find my mistake :frowning: Maybe someone can help me here.

I use the Cell_Temp_Card_1 widget from @Integer and have linked this to my item “see pictures”.

If I now click on temperature, no temperature curve appears. But if I look under my settings / items, a history appears to me.




Anyone by any chance has any idea what I’m doing wrong?

Thanks in advance for your support and your templates are really great;) 1000x thanks

Hello,
this screenshots give you an overview of my actual OH3 UI so far. Additionally I have a lot of motion sensors and automations so normally this UI is very rarely used (as it should be in a “Smart Home”). Everything is semantically modeled if useful.

The first screenshot shows the Overview page. Remarkable:

  • “Beleuchtung” is lit up if any of the lights in the apartment is ON (lots of Hue Lightstrips, Bulbs, Filament, etc.). So you can check if any light is turned on with a glance
  • “Verschattung” gets you to a shutter overview page, grouped by rooms as we have more than one shitter per room quite often
  • There is a weather widget I got from this forum
  • Presence is detected by using the iphone presence functionality and an iphone automation to switch an Openhab button visible in HomeKit ON and OFF
  • “Radio” starts a special station on a Echo (using an Alexa Routine), in case of the living room it turns on the Ambeo soundbar (via Logitech Harmony) also and starts the radio station playing synchronously on the living room echo and the FireTV connected to the Ambeo soundbar and sets decend sound volumes

This screenshot shows the light overview page grouped by room. Remarkable:

If you click on a room you see all the lights of a room. Remarkable:

Here you can see some of the lights controlled by OH in the living room (by the way, every light in the apartment can be controlled by OH)

And in the office:

This is the shutter page grouped by rooms with the details for the living room. Remarkable:

  • You see a list view of a shutter group created for this room, not an extra page
  • I created custom widgets for standard shutters. So you can use buttons or a slider for each shutter in one widget
  • For shutters with slats I created a custom widget with extra buttons to move the slats in an transparent position or closed position

This is the logitech harmony widget I found in this forum, called from the overview page:

A list view of all volume sliders of all my Echos and the Ambeo Soundbar, called from the overview page:

All controls for my Ambeo soundbar, controlled by the Harmony remote:

Temperature overview for all rooms (Guestroom does not want to switch to Celsius and continues to show Fahrenheit, I tried all I can, hrgrmpf)

Controls for my Xiamoi S6 vacuum robot, called from the overview page:

All the other pages are created totally automagically by using the semantic classification of the items.
Here are some examples:

Hope you get some inspirations for your own OH3 UI.

All this was created using all the help and inspirations from the folks of this forum. Keep up the good work :slight_smile:

Kind regards

7 Likes

Hey @BlackEagle. Unfortunately the graph is only showing when you add …

  • all 4 items
    or
  • humidity and temperature
    or
  • temperature only

… in the properties.

so. in your case, you added “temperature” and “set temperature”. If you do not have a humidity item and no heating control item (which shows on/off state of the heating), and if you only want to analyze the temperature and set temperature, then you can modify the widget code:

replace this (line 213)

actionAnalyzerItems: "=props.set_temp_item ? [props.temp_item, props.humidity_item, props.set_temp_item, props.heating_item] : (props.humidity_item ? [props.temp_item, props.humidity_item] : [props.temp_item])" 

with this:

actionAnalyzerItems: =[props.temp_item, props.set_temp_item]

best regards
Mike

1 Like

Hey @Integer ,
Thanks for your help. Works great now. :wink:

Overview Page

  • Intended to give a complete overview what devices are running/functions are active
  • If no function is active, no badge is shown.
  • Clicking on a room opens room-specific page

Individual Scenes

  • For every room you can hit the settings button (upper right) and choose a room-individual scene

Room-specific pages
Header-Widged is re-used from overview-page

  • Giving same settings/scene function
  • Going back to overview after clicking

Task System

  • Custom coded task-management
  • Taksks can be triggered via executing a rule → Flexible for input from any other openHAB function
  • Task widget can be customized to link to openHAB pages or urls to always quick-jump to task-relevant topics

2 Likes

Hi together…
My OH3 is running quite well and now I am working on several pages.
First of all: @Integer, thanks for your examples. I am now using a lot of you Main UI and I am still customizing some widgets.

But now, I am still have a problem with the weather-widget. I am using OneCallAPI, too. Channels are running and IconID is working too…
But as you can see: no data

Are there any ideas, what could be wrong?
I am asking myself, if the YAML code has to be a special update for my settings. But it seems, that it should work for everyone, who has installed the OnecallAPI…

Thanks a lot
Christian

Hey @schwoof

How did you generated the items of the OneCallApi? By UI or text based? Please check if they have the correct naming. In my widget I‘m using the english itemnames (for example: OneCallAPIweatherandforecast_ForecastToday_Mintemperature).

If you generate them by (german) UI it will be like: OneCallAPI_MinimaleTemperatur.

Hope this helps
Br

Can you please check the Cell_Light_Card_2?
When i connect the item for color temperatur, my light wont work - colo temperatur only 0-100 not 2000-6500…
When i change the code of min and max the widget doesnt work correctly.
Thanks

I really like the page with the task schedule. Can you give some more information how you managed to do this? Thanks!

Hi, no problem.
I’m on a business trip right now and will share the information at the weekend!

Sorry for the delay :relaxed:

1 Like

The light I use require the value 0 - 100 to select color temperature between cold white and warm white. In your case it seems to be different. To adjust the range to 2000 … 6500 you have to use a offset of 2000 ( 2000 = 0) and 100 steps between 0 … 100 have to be adjusted to the 4500 steps between 2000 and 6500. If your light requires the value 2000 … 6500 multiply the value (0 … 100) by 45 and add 2000.

Hey,

I used UI, but they have the correct “english” name (like yours)
But, I found The reason…
In your widget: OneCallAPIweatherandforecast_ForecastToday_Mintemperature
In my widget: OneCallAPIWeatherandForecast_ForecastToday_Mintemperature

Always the small things… :wink:
Thanks a lot. It’s running now.

But now, I’ve got another “problem”…
I am working on a “trash collection” widget.
It should show me, which kind of trash would be collect the next time.

It looks like this right now:

image

How could I change the bottom line to a good looking date? (like: 26.08.2021)
I made an input at the metadata of the item and it worked for the item but not for the widget…

pattern: %1$td.%1$tm.%1$tY

My YAML code for this:

    - component: f7-block
      config:
        style:
          position: absolute
          bottom: -45px
          left: 16px
          flex-direction: row
      slots:
        default:
          - component: Label
            config:
              text: =items[props.item_date].state
              style:
                font-size: 17px
                font-weight: 600
                margin-left: 0px
                margin-top: 0px

any idea? Thanks a lot

Hi.

Use

text: =items[props.item_date].displayState

This will use the formatted state as I understand it.

Thx… Works. :wink: