[OH3] Main UI Examples

Thank you @rlkoshak for your advice … I have corrected the YAML code

1 Like

Sorry @Badmojo and thank you for your advice - I have corrected the YAML code

1 Like

Hi, could you correct the code for Cell_Shutter_Card_1A as it is the same as Cell_Shutter_Card_1 at the moment? Thank you.
P.S.: Is it possible to replace the default widgets of OH3 with self made widgets to change 'em all at once e.g. for all your hue color lights?

P.P.S.: Nice Widgets :slight_smile:

Sorry! I have the YAML coede for Cell_Shutter_Card_1A corrected

If you use the same widget parameters you can easily replace widgets within pages by editing the widget name within the code of the page

Hi,

Thnx for the correction. Your replace idea works in pages. But I collect items in groups, and list the groups in a pop up in the UI. Is there a way to change the default list widget for all the items at once, and not changing the standard list widget for every item of the group?

Kind regards

Daniel

The only way to do this is to create a custom widget under Developer Tools. Then you need to apply that custom widget to each Item as Item Metadata. Later, if you change the custom widget it will apply the changes to all of the Items that use that widget.

In your case you need to change the default list widget. See Example Custom List Widgets for further discussion and OH 3 Tips and Tricks and some ways you could apply the metadata to the Items through the REST API more efficiently than through clicking through the UI. Though, once you’ve created your custom widget, it’s usually just a couple clicks to apply it to an Item.

I have a compact 3-day weather forecast Cell widget which I would like to open a detailed 6-day extended weather forecast widget.

How should I configure the 3-day forecast widget to display the 6-day forecast widget when tapped / clicked?

Ok,

thanks for the reply. But so the answer is “no”…

Hey Bernhard @BG56! Thank you for sharing your solution! Looks very interesting with the badges inside the bulb icons. :ok_hand:

Will definitely give it a try in my widgets :+1:

I have the same issue while using Grid Layout.
Any solution for this problem?

No, unfortunately not yet, the grid layout seems to display the widgets differently.

@BG56 Great widgets! Thanks for sharing! Have you included the YAML for the “Luftungsprogramm auswahlen” widget in one of your posts? I don’t think I can see it though I might have missed it.

I haven’t shared the widget for “Lüftungsprogramm auswählen”. I’ll share it when I’m back from vacations in about a week.

1 Like

For @higgers and others who are interested in the YAML for “Lüftungsprogramm auswählen”
image
I designed a widget with four buttons with which you can select one of four options (the text of the buttons are parameters of the widget)

uid: Cell_Button_4
props:
  parameters:
    - label: Header
      name: text_header
      required: false
      type: TEXT
    - description: icon name without ".png", located in static/icons/ folder
      label: Icon
      name: iconimage
      required: false
      type: TEXT
    - label: Button 1
      name: Button1
      required: false
      type: TEXT
    - label: Button 2
      name: Button2
      required: false
      type: TEXT
    - label: Button 3
      name: Button3
      required: false
      type: TEXT
    - label: Button 4
      name: Button4
      required: false
      type: TEXT
    - context: item
      label: Item
      name: item
      required: false
      type: TEXT
    - label: Backgroundcolor
      name: bgcolor
      required: false
      type: TEXT
timestamp: Jul 13, 2021, 1:41:57 PM
component: f7-card
config:
  style:
    noShadow: false
    class:
      - padding: 0px
    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: 100px
    margin-left: 5px
    margin-right: 5px
slots:
  default:
    - component: Label
      config:
        text: '=(props.text_header) ? props.text_header : "Header"'
        style:
          padding-bottom: 0px
          padding-top: 10px
          margin-top: 0px
          margin-left: 50px
          font-size: 17px
          font-weight: 600
    - component: f7-card-content
      slots:
        default:
          - component: f7-segmented
            config:
              raised: true
              round: false
              strong: false
            slots:
              default:
                - component: oh-button
                  config:
                    text: '=(props.Button1) ? props.Button1 : "Option1"'
                    actionItem: =props.item
                    actionCommand: 1
                    action: command
                    active: "=(items[props.item].state === '1') ? true : false"
                - component: oh-button
                  config:
                    text: '=(props.Button2) ? props.Button2 : "Option2"'
                    actionItem: =(props.item)
                    actionCommand: 2
                    action: command
                    active: "=(items[props.item].state === '2') ? true : false"
                - component: oh-button
                  config:
                    text: '=(props.Button3) ? props.Button3 : "Option3"'
                    actionItem: =(props.item)
                    actionCommand: 3
                    action: command
                    active: "=(items[props.item].state === '3') ? true : false"
                - component: oh-button
                  config:
                    text: '=(props.Button4) ? props.Button4 : "Option4"'
                    actionItem: =(props.item)
                    actionCommand: 4
                    action: command
                    active: "=(items[props.item].state === '4') ? true : false"
    - component: oh-image
      config:
        url: ='/static/icons/' + props.iconimage + '.png'
        style:
          position: absolute
          left: 10px
          top: 10px
          height: 25px
          opacity: 0.7
        visible: "=props.iconimage ? true : false"

I use this widget to select the intensity of the ventilation in my house (low, normal, high, 30 minutes high). In my specific context option4 (button4) fall back to option2 after 30 minutes with the following rule:

triggers:
  - id: "1"
    configuration:
      itemName: Lueftungsprogramm
    type: core.ItemCommandTrigger
conditions: []
actions:
  - inputs: {}
    id: "2"
    configuration:
      type: application/vnd.openhab.dsl.rule
      script: >-
        if(receivedCommand == 1) {Lueftungsstufe.sendCommand(1)} // niedrige Lüftungsstufe - Nacht- / Abwesenheit-Lüftung

        if(receivedCommand == 2) {Lueftungsstufe.sendCommand(2)} // normale Lüftungsstufe - Tag-Lüftung

        if(receivedCommand == 3) {Lueftungsstufe.sendCommand(3)} // hohe Lüftungsstufe - Party-Lüftung 

        if(receivedCommand == 4) {                               // 30 Min hohe Lüftungsstufe - Party-Kurz-Lüftung
            Lueftungsstufe.sendCommand(3) 
            createTimer(now.plusMinutes(30)) [|
        	    	Lueftungsprogramm.sendCommand(2)
        	    ]
        }
    type: script.ScriptAction

with OH3.0 I used the following code within the widget to display a icon from folder /etc/openhab/html/icons

    - component: oh-image
      config:
        url: ='static/icons/' + props.iconimage + '.png'

a slash was missing at the start of the relative url. OH3.1 does no longer accept this. You have to start the relative url with slash.

    - component: oh-image
      config:
        url: ='/static/icons/' + props.iconimage + '.png'

If you use my posted widgets you have to adjust the YAML code of these widgets whenever “oh-image” is used. Ihave corrected the code in my posts

Hello,
@Integer
thank you for sharing your widgets, I love the overlay.

unfortunately, I got a tricky error with the temperature widget.
I can’t explain it to me.
The Error is, that the Humidity is randomly shown in the widget → the item works correctly and fine → I build the same item into the overview page as you did.
At the overview page, the humidity is constantly shown → only in the widget its get a bit buggy


On the screenshots, u can see, that the overview page is displaying correctly while the widget is randomly shown the percentage → in this case it’s showing no humidity…
Maybe u got a hint for me on how to solve this problem ?

Hey Christian! I am honored that you are using my widgets :slight_smile:

Unfortunately, I’m having the same problem as you right now after upgrading to 3.1.

Strange for me is that, like you, it only affects the humidity. I suspect that this is somehow related to the item type “Number:Dimensionless”. If I change the Item-Type to “Number” then it works again.
"State Description" → “Pattern”: %.0f %% I already had in Number:Dimensionless, I left it like that in Number type.

Both widgets (Card_room and Cell_Temp_Card) uses the “displayState” property of the item. Maybe anyone can explain, why Number:Dimensionless is not working with Pattern %.0f %%?

Cell_Temp_Card_1

=items[props.humidity_item].displayState

Card_room_12

=items[props.humidity].displayState

Have no problems with humidity display, using

text: =items[props.humidity_item].state

Item defined like this:

  "state": "34.02 %",
  "stateDescription": {
    "pattern": "%.1f %%",
    "readOnly": true,
    "options": []
  },
  "editable": true,
  "type": "Number:Dimensionless",
  "name": "WallmountFamilyRoom_Humidity",
  "label": "Влажность",
  "category": "humidity",
  "tags": [
    "Measurement",
    "Humidity"
  ],

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