Hi,
works perfectly!
Thanks a lot for your help!
Hi,
works perfectly!
Thanks a lot for your help!
With v3.4 there is an @ operator available which shows displayState if available and state if not available.
@(items[props.status])
It helped tidying up my widgets😀
mmm i’ve tried different ways but it doesn’t work for me
i’m running OH snapshot 4.0.0
can you tell me why?
thanks a lot!
- component: Label
config:
style:
color: black
margin-left: 2px
z-index: 98
text: @(items[props.opstateItem])
Does it not need to be
text: =@(items[props.opstateItem])
I’m currently on stable 3.3.0
i’ve tried but the state is reported as “-”.
that item should have both state and displayState…
Yes, that is correct.
And you need to have minimum version 3.4 M6.
actually i’m testing on 4.0.0 snapshot and still doesn’t work for me
You should not include the items
object. The @
operator (and the @@
operator which forces just the state instead of the displayState
) acts directly on the item name string. So, in this case:
text: =@(props.opstateItem)
As always,great answer and also great explanation.
Thank you so much Justin!
Technically those are the 2 equivalences:
@<name> <=> items[<name>].displayState !== undefined ? items[<name>].displayState : items[<name>].state
@@<name> <=> items[<name>].state
@
et @@
are unary operators so due to their precedences parentheses may be useful, but not always.
For instance @props.itemName
alone is fine, but beware of the differences between:
@@itemsPrefix + '_Suffix` <=> items[itemsPrefix].state + '_Suffix'
and
@@(itemsPrefix + '_Suffix`) <=> items[itemsPrefix + '_Suffix'].state
Hi Andras,
many thanks for you Examples, especially the room Card. Quite useful as I was searching for a card that could open a group action…
bkumio
Finally I feel comfortable enough to post my example so far. Have had some great inspiration from @Integer and @BG56 but I’m also inspired by the great design of @Dimitris in the new main widget topic. Thank you all.
I really like the simpleness of the Apple Home app and I try to copy that part, too. When Items are off they are semi-transparent and when one they become white. In some cases I will enable them to become a special color, for example the AlarmPartitionStatus may become red when there is an alarm.
The LightControl widget can be collapsed and expanded by clicking on the title and depending on the set properties will display a slider to dim, two sliders for dim and white tone or will display the color control with three sliders and a set of pre-defined colors.
My HarmonyControl will show the current activity when on and it then also features an off button. It can be expanded when off, but it automatically expanded when on.
I’m currently working on a new widget for displaying status from the thermostate and a player widget for my future Chromecast.
Would you mind sharing the code of your widgets ?
Sure!
LightControl:
uid: LightControl
tags: []
props:
parameters:
- description: Header icon
label: Icon
name: iconHeader
required: false
type: TEXT
groupName: header
- description: Header text
label: Header
name: header
required: false
type: TEXT
groupName: header
- context: item
description: Item to control on/off
label: Item ON OFF
name: itemSwitch
required: true
type: TEXT
groupName: setup
- context: item
description: Item to control brightness
label: Item brightness
name: itemBrightness
required: false
type: TEXT
groupName: setup
- context: item
description: Item to control color temperature
label: Item light temperature
name: itemLightTemperature
required: false
type: TEXT
groupName: setup
- context: item
description: Item to control color
label: Item light color
name: itemColor
required: false
type: TEXT
groupName: setup
parameterGroups:
- name: header
description: Widget general settings
- name: setup
description: Widget specific settings
timestamp: Dec 29, 2022, 10:55:04 PM
component: f7-card
config:
style:
background-color: "=items[props.itemSwitch].state === 'ON' ? 'rgba(255, 255, 255, 1)' : 'rgba(34, 34, 34, 0.3)'"
border-radius: 15px
box-shadow: 0px 0px
margin: 5px 5px
slots:
content:
- component: f7-row
config:
style:
justify-content: left
slots:
default:
- component: oh-image
config:
url: ='/static/icons/' + props.iconHeader + '.svg'
style:
height: 25px
margin-right: 10px
filter: '=items[props.itemSwitch].state === "ON" ? "brightness(1)" : "brightness(0) invert(1)"'
visible: "=props.iconHeader ? true : false"
- component: Label
config:
text: "=props.header ? props.header : 'Set header title'"
style:
font-size: var(--f7-card-header-font-size)
font-weight: var(--f7-card-header-font-weight)
color: '=items[props.itemSwitch].state === "ON" ? "black" : "white"'
--f7-list-item-after-text-color: '=items[props.itemSwitch].state === "ON" ? "black" : "white"'
- component: oh-toggle
config:
item: =props.itemSwitch
style:
position: absolute
top: 20px
right: 20px
z-index: 100
--f7-toggle-active-color: "#F8BB00"
--f7-toggle-inactive-color: "#ccc"
- component: oh-link
config:
action: variable
actionVariable: visiblePart
actionVariableValue: "=vars.visiblePart === true ? false : true"
style:
position: absolute
top: 0
left: 0
height: 55px
width: 100%
actionPosition: center
- component: f7-row
config:
style:
justify-content: center
margin-top: 25px
visible: =vars.visiblePart === true && props.itemBrightness !== Null
slots:
default:
- component: oh-slider
config:
item: =props.itemBrightness
min: 0
max: 100
style:
width: calc(100% - 20px)
--f7-range-bar-size: 10px
--f7-range-bar-border-radius: 8px
--f7-range-knob-size: 20px
--f7-range-knob-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3)
- component: f7-row
config:
style:
justify-content: center
margin-top: 10px
visible: =vars.visiblePart === true && props.itemLightTemperature !== Null
slots:
default:
- component: oh-slider
config:
item: =props.itemLightTemperature
min: 0
max: 100
style:
width: calc(100% - 20px)
--f7-range-bar-size: 10px
--f7-range-bar-border-radius: 10px
--f7-range-knob-size: 20px
--f7-range-bar-active-bg-color: transparent
--f7-range-bar-bg-color: linear-gradient(to right, rgba(215, 226, 255), rgba(224, 238, 238),rgba(255, 215, 44, 0.5),rgba(255, 215, 44, 0.8))
--f7-range-knob-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3)
--f7-range-label-text-color: black
- component: f7-row
config:
style:
justify-content: center
margin-top: 10px
--f7-range-bar-size: 10px
--f7-range-bar-border-radius: 10px
--f7-range-knob-size: 20px
--f7-range-bar-active-bg-color: transparent
--f7-range-bar-bg-color: linear-gradient(to right, rgba(246,158,81,0.8), rgba(246,158,81,0))
--f7-range-knob-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3)
--f7-range-label-text-color: black
--f7-color-picker-slider-size: 10px
--f7-color-picker-slider-knob-size: 20px
width: 100%
visible: =vars.visiblePart === true && props.itemColor !== Null
slots:
default:
- component: oh-colorpicker
config:
color: red
label: true
item: =props.itemColor
modules:
- hsb-sliders
- component: f7-row
config:
style:
justify-content: center
margin-top: 10px
visible: =vars.visiblePart === true && props.itemColor !== Null
slots:
default:
- component: oh-button
config:
iconColor: yellow
iconF7: app_fill
iconSize: 25
action: command
actionItem: =props.itemColor
actionCommand: 60,100,100
style:
padding: 0px 5px
height: 35px
background: transparent
- component: oh-button
config:
iconColor: orange
iconF7: app_fill
iconSize: 25
action: command
actionItem: =props.itemColor
actionCommand: 30,100,100
style:
padding: 0px 5px
height: 35px
background: transparent
- component: oh-button
config:
iconColor: deeporange
iconF7: app_fill
iconSize: 25
action: command
actionItem: =props.itemColor
actionCommand: 15,100,100
style:
padding: 0px 5px
height: 35px
background: transparent
- component: oh-button
config:
iconColor: red
iconF7: app_fill
iconSize: 25
action: command
actionItem: =props.itemColor
actionCommand: 0,100,100
style:
padding: 0px 5px
height: 35px
background: transparent
- component: oh-button
config:
iconColor: purple
iconF7: app_fill
iconSize: 25
action: command
actionItem: =props.itemColor
actionCommand: 300,100,100
style:
padding: 0px 5px
height: 35px
background: transparent
- component: oh-button
config:
iconColor: blue
iconF7: app_fill
iconSize: 25
action: command
actionItem: =props.itemColor
actionCommand: 240,100,100
style:
padding: 0px 5px
height: 35px
background: transparent
- component: oh-button
config:
iconColor: lightblue
iconF7: app_fill
iconSize: 25
action: command
actionItem: =props.itemColor
actionCommand: 180,100,100
style:
padding: 0px 5px
height: 35px
background: transparent
- component: oh-button
config:
iconColor: green
iconF7: app_fill
iconSize: 25
action: command
actionItem: =props.itemColor
actionCommand: 120,100,100
style:
padding: 0px 5px
height: 35px
background: transparent
SimpleSwitch:
uid: SimpleSwitch
tags: []
props:
parameters:
- description: Header icon
label: Icon
name: iconHeader
required: false
type: TEXT
groupName: header
- description: Header text
label: Header
name: header
required: false
type: TEXT
groupName: header
- context: item
description: Item to control on/off
label: Item
name: itemSwitch
required: false
type: TEXT
groupName: setup
parameterGroups:
- name: header
description: Widget general settings
- name: setup
description: Widget specific settings
timestamp: Dec 29, 2022, 10:55:19 PM
component: f7-card
config:
style:
background-color: "=items[props.itemSwitch].state === 'ON' ? 'rgba(255, 255, 255, 1)' : 'rgba(34, 34, 34, 0.3)'"
border-radius: 15px
box-shadow: 0px 0px
margin: 5px 5px
slots:
content:
- component: f7-row
config:
style:
justify-content: left
slots:
default:
- component: oh-image
config:
url: ='/static/icons/' + props.iconHeader + '.svg'
style:
height: 25px
margin-right: 10px
filter: '=items[props.itemSwitch].state === "ON" ? "brightness(1)" : "brightness(0) invert(1)"'
visible: "=props.iconHeader ? true : false"
- component: Label
config:
text: "=props.header ? props.header : 'Set header title'"
style:
font-size: var(--f7-card-header-font-size)
font-weight: var(--f7-card-header-font-weight)
color: '=items[props.itemSwitch].state === "ON" ? "black" : "white"'
--f7-list-item-after-text-color: '=items[props.itemSwitch].state === "ON" ? "black" : "white"'
- component: f7-row
config:
style:
justify-content: center
margin-top: 25px
slots:
default:
- component: oh-toggle
config:
item: =props.itemSwitch
style:
--f7-toggle-active-color: "#F8BB00"
--f7-toggle-inactive-color: "#ccc"
Let me double check my HarmonyControl first before I post it here. Want to make sure that it’s fully functioning
Very nice! Looks like the one i’ve made too
I will take from your widget, the preset line colors,i forgot to add that could be useful.
Thanks!
Here is the code for the Harmony widget:
uid: HarmonyControl
tags: []
props:
parameters:
- description: Header icon
label: Icon
name: iconHeader
required: false
type: TEXT
groupName: header
- description: Header text
label: Header
name: header
required: false
type: TEXT
groupName: header
- context: item
description: Item to control Harmony
label: Item current activity
name: itemCurrentActivity
required: true
type: TEXT
groupName: setup
- description: 'Use JSON format [{"label": "Label", "icon": "Icon", "command": "Command to send"}, ...}]'
label: Activities
name: activities
required: true
type: TEXT
groupName: setup
parameterGroups:
- name: header
description: Widget general settings
- name: setup
description: Widget specific settings
timestamp: Jan 8, 2023, 10:53:50 PM
component: f7-card
config:
style:
background-color: "=items[props.itemCurrentActivity].state !== 'PowerOff' ? 'rgba(255, 255, 255, 1)' : 'rgba(34, 34, 34, 0.3)'"
border-radius: 15px
box-shadow: 0px 0px
margin: 5px 5px
slots:
content:
- component: f7-row
config:
style:
justify-content: left
slots:
default:
- component: oh-image
config:
url: ='/static/icons/' + props.iconHeader + '.svg'
style:
height: 25px
margin-right: 10px
filter: '=items[props.itemCurrentActivity].state !== "PowerOff" ? "brightness(1)" : "brightness(0) invert(1)"'
visible: "=props.iconHeader ? true : false"
- component: Label
config:
text: "=props.header ? props.header : 'Set header title'"
style:
font-size: var(--f7-card-header-font-size)
font-weight: var(--f7-card-header-font-weight)
color: '=items[props.itemCurrentActivity].state !== "PowerOff" ? "black" : "white"'
--f7-list-item-after-text-color: '=items[props.itemCurrentActivity].state !== "PowerOff" ? "black" : "white"'
- component: oh-link
config:
action: command
actionItem: =props.itemCurrentActivity
actionCommand: PowerOff
actionFeedback: Uitgeschakeld
style:
position: absolute
top: 20px
right: 20px
z-index: 100
visible: "=items[props.itemCurrentActivity].state !== 'PowerOff' ? true : false"
slots:
default:
- component: oh-image
config:
url: ='/static/icons/power-off.svg'
style:
height: 18px
- component: oh-link
config:
action: variable
actionVariable: visiblePart
actionVariableValue: "=vars.visiblePart === true ? false : true"
style:
position: absolute
top: 0
left: 0
height: 55px
width: 100%
actionPosition: center
- component: f7-row
config:
style:
justify-content: left
margin-top: 10px
margin-bottom: 10px
slots:
default:
- component: f7-chip
config:
text: "=items[props.itemCurrentActivity].state === 'PowerOff' ? 'Uitgeschakeld' : items[props.itemCurrentActivity].state"
style:
background-color: "=items[props.itemCurrentActivity].state !== 'PowerOff' ? '#F8BB00' : '#8c8c8c'"
color: "#fff"
margin-left: 35px
font-size: 10px
height: 18px
- component: f7-row
config:
visible: "=items[props.itemCurrentActivity].state !== 'PowerOff' || vars.visiblePart === true ? true : false"
style:
margin-top: 20px
class:
- text-align-center
slots:
default:
- component: oh-repeater
config:
for: activity
sourceType: array
fragment: true
in: '=JSON.parse(props.activities)'
slots:
default:
- component: f7-col
config:
slots:
default:
- component: oh-link
config:
action: command
actionItem: =props.itemCurrentActivity
actionCommand: =loop.activity.command
actionFeedback: =loop.activity.label + " gestart"
slots:
default:
- component: oh-image
config:
url: ='/static/icons/' + loop.activity.icon + '.svg'
style:
height: 18px
- component: f7-row
config:
visible: "=items[props.itemCurrentActivity].state !== 'PowerOff' || vars.visiblePart === true ? true : false"
style:
margin-top: 10px
class:
- text-align-center
slots:
default:
- component: oh-repeater
config:
for: activity
sourceType: array
fragment: true
in: '=JSON.parse(props.activities)'
slots:
default:
- component: f7-col
config:
slots:
default:
- component: oh-link
config:
action: command
actionItem: =props.itemCurrentActivity
actionCommand: =loop.activity.command
actionFeedback: =loop.activity.label + " gestart"
slots:
default:
- component: Label
config:
text: =loop.activity.label
style:
font-size: 11px
color: '=items[props.itemCurrentActivity].state !== "PowerOff" ? "black" : "white"'
And I’ve got an ‘appliance’ widget as well. I use it in conjunction with the HomeConnect binding to display dishwasher and washing machine status.
uid: ApplianceStatus
tags: []
props:
parameters:
- description: Header icon
label: Icon
name: iconHeader
required: false
type: TEXT
groupName: header
- description: Header text
label: Header
name: header
required: false
type: TEXT
groupName: header
- context: item
description: select item for operation state
label: Item
name: operationState
required: false
type: TEXT
groupName: setup
- context: item
description: select item for active program
label: Item
name: activeProgram
required: false
type: TEXT
groupName: setup
- context: item
description: select item for remaining time
label: Item
name: remainingTime
required: false
type: TEXT
groupName: setup
- context: item
description: select item for progress
label: Item
name: progress
required: false
type: TEXT
groupName: setup
- context: item
description: select item for temperature
label: Item
name: temperature
required: false
type: TEXT
groupName: setup
- context: item
description: select item for spinspeed
label: Item
name: spinSpeed
required: false
type: TEXT
groupName: setup
parameterGroups:
- name: header
description: Widget general settings
- name: setup
description: Widget specific settings
timestamp: Jan 8, 2023, 10:12:11 PM
component: f7-card
config:
style:
background-color: "=items[props.operationState].state === 'Run' ? 'rgba(255, 255, 255, 1)' : 'rgba(34, 34, 34, 0.3)'"
border-radius: 15px
box-shadow: 0px 0px
margin: 5px 5px
slots:
content:
- component: f7-row
config:
style:
justify-content: left
slots:
default:
- component: oh-image
config:
url: ='/static/icons/' + props.iconHeader + '.svg'
style:
height: 25px
margin-right: 10px
filter: '=items[props.operationState].state === "Run" ? "brightness(1)" : "brightness(0) invert(1)"'
visible: "=props.iconHeader ? true : false"
- component: Label
config:
text: "=props.header ? props.header : 'Set header title'"
style:
font-size: var(--f7-card-header-font-size)
font-weight: var(--f7-card-header-font-weight)
color: '=items[props.operationState].state === "Run" ? "black" : "white"'
- component: f7-row
config:
style:
justify-content: left
margin-top: 10px
margin-bottom: 10px
slots:
default:
- component: f7-chip
config:
text: =items[props.operationState].displayState
style:
background-color: "=items[props.operationState].state === 'Run' ? '#F8BB00' : '#8c8c8c'"
color: "#fff"
margin-left: 35px
font-size: 10px
height: 18px
- component: f7-row
config:
visible: "=items[props.operationState].state === 'Run' ? true : false"
style:
justify-content: left
slots:
default:
- component: f7-chip
config:
style:
--f7-chip-bg-color: rgba(255, 255, 255, 0)
text: =items[props.activeProgram].state
iconColor: black
iconF7: info_circle
iconSize: 17
- component: f7-chip
config:
visible: =items[props.temperature]
style:
--f7-chip-bg-color: rgba(255, 255, 255, 0)
text: =items[props.temperature].displayState
- component: f7-chip
config:
visible: =items[props.spinSpeed]
style:
--f7-chip-bg-color: rgba(255, 255, 255, 0)
text: =items[props.spinSpeed].displayState
- component: f7-row
config:
visible: "=items[props.operationState].state === 'Run' ? true : false"
style:
justify-content: left
slots:
default:
- component: f7-chip
config:
style:
--f7-chip-bg-color: rgba(255, 255, 255, 0)
text: "='Resterende tijd: ' + items[props.remainingTime].state"
iconColor: black
iconF7: clock
iconSize: 17
- component: f7-chip
config:
style:
--f7-chip-bg-color: rgba(255, 255, 255, 0)
text: "='Voortgang: ' + (items[props.progress].displayState === 'undefined') ? items[props.progress].displayState : items[props.progress].displayState"
iconColor: black
iconF7: percent
iconSize: 17
Feel free to use or modify them as you wish. This weeks project: thermostat ‘status’ widget to display what my heating actor is doing (per room).
Anything to show already ?
Not yet actually… I’m still thinking about what exactly to display (related to what my KNX actor has available) and how to visualize. Also I don’t have airco or cooling so it’s only for heating.
I’ll also share my Main UI. It all started with the ‘room’ widgets which were from the beginning of OH3 I think. Afterwards I added additional widgets for turning on lights, dimmers…and tried to create or modify other ones:
Main screen
Additional window when pressing the wheel on the Media widget
Example when clicking on a room:
Example of the charts pages which opens when clicking on one of the numbers in the Energy widget:
Some random widget for checking devices etc (they are all filled by items which gets their values via rules):
eye
icon in the widgets above will show all items, without my specific filter (eg I only show batteries % below 40%, I only show GitHub releases of the last 15 days…) The list
icons shows the complete content of the group without any formatting