OH3 item/widget: switch with multiple buttons?

Sure. :wink:

Thatā€™s the current look, slightly modified to grey stepper controls:

ā€¦ and the widget code:

uid: Thermostat-Control
tags: []
props:
  parameters:
    - description: Thermostat to control
      label: Description
      name: Title
      required: false
      type: TEXT
    - context: item
      description: Das Item fĆ¼r die gemessene Temperatur
      label: Ist Temperature Item
      name: tempItem
      required: true
      type: TEXT
    - context: command
      description: Unterer Preset
      label: Temperatur kalt
      name: tempKalt
      required: true
      type: TEXT
    - context: command
      description: Normaler Preset
      label: Temperatur normal
      name: tempNorm
      required: true
      type: TEXT
    - context: command
      description: Oberer Preset
      label: Temperatur warm
      name: tempWarm
      required: true
      type: TEXT
    - context: item
      description: Das Item mit dem die Solltemperatur eingestellt wird
      label: Setpoint Item
      name: setpointItem
      required: true
      type: TEXT
timestamp: Feb 5, 2021, 1:04:45 PM
component: f7-card
config:
  outline: false
  noBorder: false
  padding: true
  noShadow: false
  style:
    --f7-card-margin-horizontal: 5px
    --f7-card-content-padding-vertical: 0px
    --f7-card-content-padding-horizontal: 16px
    --f7-card-border-radius: 15px
    --f7-card-box-shadow: 0px 5px 10px rgba(0,0,0,0.15)
    --f7-card-header-font-size: 14px
    --f7-card-header-font-weight: 600
slots:
  content:
    - component: oh-label-card
      config:
        noShadow: true
        trendItem: =(props.tempItem)
        action: analyzer
        actionAnalyzerItems: =[props.tempItem,props.setpointItem]
        item: =(props.tempItem)
        title: =(props.Title)
        icon: f7:thermometer
        actionAnalyzerCoordSystem: time
        vertical: false
    - component: oh-stepper-card
      config:
        noShadow: true
        color-theme: gray
        item: =(props.setpointItem)
        large: false
        autorepeat: true
        fill: false
        noBorder: true
        raised: true
        small: true
        round: true
        min: =(props.tempKalt-1)
        max: =(props.tempWarm+1)
        step: 0.5
    - component: f7-row
      config:
        class:
          - padding-bottom
          - padding-right
      slots:
        default:
          - component: f7-col
            slots:
              default:
                - component: oh-button
                  config:
                    title: Kalt
                    action: command
                    actionItem: =(props.setpointItem)
                    actionCommand: =(props.tempKalt)
                    iconF7: thermometer_snowflake
                    iconColor: blue
                    textColor: blue
                    text: min
          - component: f7-col
            slots:
              default:
                - component: oh-button
                  config:
                    title: Normal
                    action: command
                    actionItem: =(props.setpointItem)
                    actionCommand: =(props.tempNorm)
                    iconF7: thermometer
                    iconColor: orange
                    textColor: orange
                    text: ok
          - component: f7-col
            slots:
              default:
                - component: oh-button
                  config:
                    title: Warm
                    action: command
                    actionItem: =(props.setpointItem)
                    actionCommand: =(props.tempWarm)
                    iconF7: thermometer_sun
                    iconColor: red
                    textColor: red
                    text: max
5 Likes

I love this widget due to its simplicity and good responsiveness. I have added a window icon to the thermostat that displays when a window is open. This works fine for one window.

config:
        visible: "=props.kontaktItem1 ? true : false"
        icon: "=(items[props.kontaktItem1].state === 'OPEN') ? 'window-open' : 'window-closed'"
        style:
          position: absolute
          bottom: 20%
          left: 95%
          transform: translate(-50%,-50%)
          width: 10%
          height: 20%

But how can I connect the icon to the states of more than one window? What is the syntax for an OR condition on the icon line.

icon: "=(items[props.kontaktItem1].state === 'OPEN') ? 'window-open' : 'window-closed'"

I tried something like this:

icon: "=((items[props.kontaktItem1].state === 'OPEN') && (items[props.kontaktItem2].state === 'OPEN')) ? 'window-open' : 'window-closed'"

Itā€™s probably something dead stupid, but Iā€™m not getting it at the moment. I been reading descriptions on conditional (ternary) operator, but I think Iā€™m just missing something easy.

Any help would be greatly appreciated.

Rob

Hi Rob,

you are pretty closeā€¦ Do you want an AND condition or an OR condition. Your try is an AND oneā€¦

This is what i use for an AND one as an example:

color: "=themeOptions.dark === 'light' && Number.parseFloat(items[props.itemDown].state.split(' ')[0]) < 150 ? 'red' : themeOptions.dark === 'light' && Number.parseFloat(items[props.itemUp].state.split(' ')[0]) < 35 ? 'red' : themeOptions.dark === 'dark' ? 'white' : 'black'"

for OR just do this in your example:

icon: "=((items[props.kontaktItem1].state === 'OPEN') ? 'window-open' : (items[props.kontaktItem2].state === 'OPEN')) ? 'window-open' : 'window-closed'"

Hey thanks, that was the solution to my problem. As a hobby programmer, I often find the right approach, but often also get caught out by silly syntax mistakes. Itā€™s nice to know thereā€™s help just round the corner.

Rob

Can you show please where exactly you add this code in the widget, to show the windows state?
Thanks
Nikos

Thanks alot for this great widget !

really nice widget!!! is it possible to highlight the selected heat mode somehow, like the black border in this screenshot, or nicer :wink:
image

The obvious solution might be the raised-option of oh-button:

- component: oh-button
                  config:
                    title: Kalt
                    action: command
                    actionItem: =(props.setpointItem)
                    actionCommand: =(props.tempKalt)
                    iconF7: thermometer_snowflake
                    iconColor: blue
                    textColor: blue
                    text: min
                    raised: "=(items[props.setPointItem].state == props.tempKalt) ? 'true' : 'false'"

Unfortunately, the dynamic check of the current state does not work yetā€¦ :frowning:

image

From a usability point of view Iā€™d suggest to have all buttons raised except the selected one.
If something is raised, it can be clicked. If not it has already been selected.
This way it stays consistent with the temperature buttons above.

Fully agree of course.

I just wanted to answer the question of @powerpolly and make him aware of the raised option which is almost exactly what he was asking for :wink:

Personally, I still do prefer the simpler design without that additional raised effect.

btw.: Any clue why:

raised: "=(items[props.setPointItem].state == props.tempKalt) ? 'true' : 'false'"

Is not getting updated dynamically when the setpoint item changes?

Maybe ā€œraisedā€ is only evaluated once when displaying the button. Could be by design or might be a small bug, I havenā€™t tried it yet. Did you try rotating the device ? I expect that the button will get rendered again and will reflect the property state.

No, this seems not to be the case :wink:

After some investigation it turned out, that my comparision was simply wrong.
Iā€™ve checked with the ā€œwidget expression testerā€ in the developer sidebar and noticed finally, that comparing the props.tempKalt etc. with the item state is a bad idea, because:

items[props.setPointItem] evaluates to:

{ "state": "17 Ā°C", "displayState": "17.0" }

Therefore, comparing the preset temps with the displayState (instead of ā€˜stateā€™) solved this:

raised: =(items[props.setpointItem].displayState != props.tempKalt )

Disadvantage is, that the preset temperatures in the widget config need to match exactly the stateDescription metadata for the setpoint items, %.1f in my case to trigger the conditional clauses in the widgetā€¦

According to @powerpolly 's question, Iā€™ve updated the widget to reflect the selected preset temperature:

image

Important to make it work properly is to set the preset temperatures in the widget config exactly as the will appear in the displayState. Means if your displayState is %.1f , then the preset should be for example 17.0 and not just 17 :wink:

Here is the updated widget code:

uid: Thermostat-Control
tags: []
props:
  parameters:
    - description: Thermostat to control
      label: Description
      name: Title
      required: false
      type: TEXT
    - context: item
      description: Das Item fĆ¼r die gemessene Temperatur
      label: Ist Temperature Item
      name: tempItem
      required: true
      type: TEXT
    - context: command
      description: Unterer Preset
      label: Temperatur kalt
      name: tempKalt
      required: true
    - context: command
      description: Normaler Preset
      label: Temperatur normal
      name: tempNorm
      required: true
    - context: command
      description: Oberer Preset
      label: Temperatur warm
      name: tempWarm
      required: true
    - context: item
      description: Das Item mit dem die Solltemperatur eingestellt wird
      label: Setpoint Item
      name: setpointItem
      required: true
      type: TEXT
timestamp: Jan 8, 2022, 3:58:24 PM
component: f7-card
config:
  outline: false
  noBorder: false
  padding: true
  noShadow: false
  style:
    --f7-card-margin-horizontal: 5px
    --f7-card-content-padding-vertical: 0px
    --f7-card-content-padding-horizontal: 16px
    --f7-card-border-radius: 15px
    --f7-card-box-shadow: 0px 5px 10px rgba(0,0,0,0.15)
    --f7-card-header-font-size: 14px
    --f7-card-header-font-weight: 600
slots:
  content:
    - component: oh-label-card
      config:
        noShadow: true
        trendItem: =(props.tempItem)
        action: analyzer
        actionAnalyzerItems: =[props.tempItem,props.setpointItem]
        item: =(props.tempItem)
        title: =(props.Title)
        icon: f7:thermometer
        actionAnalyzerCoordSystem: time
        vertical: false
    - component: oh-stepper-card
      config:
        noShadow: true
        color-theme: gray
        item: =(props.setpointItem)
        large: false
        autorepeat: true
        fill: false
        noBorder: true
        raised: true
        small: true
        round: true
        min: =(props.tempKalt-1)
        max: =(props.tempWarm+1)
        step: 0.5
    - component: f7-row
      config:
        class:
          - padding-bottom
      slots:
        default:
          - component: f7-segmented
            config:
              colorTheme: gray
              strong: false
              style:
                width: 100%
              round: true
              raised: true
              outline: true
              class:
                - segmented-round
            slots:
              default:
                - component: oh-button
                  config:
                    title: Kalt
                    action: command
                    actionItem: =props.setpointItem
                    actionCommand: =props.tempKalt
                    iconF7: thermometer_snowflake
                    iconColor: '=(items[props.setpointItem].displayState == props.tempKalt) ? "white" : "blue"'
                    textColor: '=(items[props.setpointItem].displayState == props.tempKalt) ? "white" : "blue"'
                    text: min
                    round: true
                    small: true
                    active: =(items[props.setpointItem].displayState == props.tempKalt )
                - component: oh-button
                  config:
                    title: Normal
                    action: command
                    actionItem: =props.setpointItem
                    actionCommand: =props.tempNorm
                    iconF7: thermometer
                    iconColor: '=(items[props.setpointItem].displayState == props.tempNorm) ? "white" : "orange"'
                    textColor: '=(items[props.setpointItem].displayState == props.tempNorm) ? "white" : "orange"'
                    text: ok
                    round: true
                    small: true
                    active: =(items[props.setpointItem].displayState == props.tempNorm )
                - component: oh-button
                  config:
                    title: Warm
                    action: command
                    actionItem: =props.setpointItem
                    actionCommand: =props.tempWarm
                    iconF7: thermometer_sun
                    iconColor: '=(items[props.setpointItem].displayState == props.tempWarm) ? "white" : "red"'
                    textColor: '=(items[props.setpointItem].displayState == props.tempWarm) ? "white" : "red"'
                    text: max
                    round: true
                    small: true
                    active: =(items[props.setpointItem].displayState == props.tempWarm)
1 Like

so great! many thanks! Iā€™m still learning how to code those widget, not always easy for a non-programmerā€¦

I wasnā€™t happy with the raised design for the presetsā€¦therefore changed back to a flat version for the preset buttons while still highlighting which preset the current setpoint temperature is matching currently:

Here is the code:

uid: Thermostat-Control
tags: []
props:
  parameters:
    - description: Thermostat to control
      label: Description
      name: Title
      required: false
      type: TEXT
    - context: item
      description: Das Item fĆ¼r die gemessene Temperatur
      label: Ist Temperature Item
      name: tempItem
      required: true
      type: TEXT
    - context: command
      description: Unterer Preset
      label: Temperatur kalt
      name: tempKalt
      required: true
    - context: command
      description: Normaler Preset
      label: Temperatur normal
      name: tempNorm
      required: true
    - context: command
      description: Oberer Preset
      label: Temperatur warm
      name: tempWarm
      required: true
    - context: item
      description: Das Item mit dem die Solltemperatur eingestellt wird
      label: Setpoint Item
      name: setpointItem
      required: true
      type: TEXT
timestamp: Jan 8, 2022, 6:21:18 PM
component: f7-card
config:
  outline: false
  noBorder: false
  padding: true
  noShadow: false
  style:
    --f7-card-margin-horizontal: 5px
    --f7-card-content-padding-vertical: 0px
    --f7-card-content-padding-horizontal: 16px
    --f7-card-border-radius: 15px
    --f7-card-box-shadow: 0px 5px 10px rgba(0,0,0,0.15)
    --f7-card-header-font-size: 14px
    --f7-card-header-font-weight: 600
slots:
  content:
    - component: oh-label-card
      config:
        noShadow: true
        trendItem: =(props.tempItem)
        action: analyzer
        actionAnalyzerItems: =[props.tempItem,props.setpointItem]
        item: =(props.tempItem)
        title: =(props.Title)
        icon: f7:thermometer
        actionAnalyzerCoordSystem: time
        vertical: false
    - component: oh-stepper-card
      config:
        noShadow: true
        color-theme: gray
        item: =(props.setpointItem)
        large: false
        autorepeat: true
        fill: false
        noBorder: true
        raised: true
        small: false
        round: true
        min: =(props.tempKalt-1)
        max: =(props.tempWarm+1)
        step: 0.5
    - component: f7-row
      config:
        colorTheme: blue
        class:
          - padding-bottom
      slots:
        default:
          - component: f7-col
            slots:
              default:
                - component: oh-button
                  config:
                    title: Kalt
                    color-theme: blue
                    action: command
                    actionItem: =props.setpointItem
                    actionCommand: =props.tempKalt
                    iconF7: thermometer_snowflake
                    text: min
                    round: true
                    small: true
                    active: =(items[props.setpointItem].displayState == props.tempKalt )
          - component: f7-col
            slots:
              default:
                - component: oh-button
                  config:
                    title: Normal
                    color-theme: orange
                    action: command
                    actionItem: =props.setpointItem
                    actionCommand: =props.tempNorm
                    iconF7: thermometer
                    text: ok
                    round: true
                    small: true
                    active: =(items[props.setpointItem].displayState == props.tempNorm )
          - component: f7-col
            slots:
              default:
                - component: oh-button
                  config:
                    title: Warm
                    color-theme: red
                    action: command
                    actionItem: =props.setpointItem
                    actionCommand: =props.tempWarm
                    iconF7: thermometer_sun
                    text: max
                    round: true
                    small: true
                    active: =(items[props.setpointItem].displayState == props.tempWarm)

5 Likes

Didnā€™t manage to add the window to the widgetā€¦ could you please post your code?

Could somebody maybe give me a heads up on how to add Ā°C to the set temperature element?

Thank you!:slight_smile:

A great Widget. I want add Battery Status and some other Informations but there is not enough space and i dont want see if allways. But i dont want increase the size of then Widget.
So i need a Second Window or something else.

Could i Open a new window If i Push a Button?
I dont know its possible.
Otherwise how could i invisible something when i press a Button? This Button has no Item or something else.
I think i need local variables to change the visible attribute of an other element?