It works great now! Thank you very much! The only thing I noticed was the location prop needs to be one single phrase, with a broken phrase (like a space in between two words) the pop-up won’t show. For me that is no big deal but just wanted to let you know.
It works, good work keep it up
Hi Nico,
fantastic The additions work all well. Now there are nearly all design-options possible.
The “pulsing Corona” is also a very nice feature, which I tested with a toggling switch of my office-lamp.
.
The wish of @Sas_Bibic (Translation) could be another interesting feature to make it more comfortable for users of different languages. But I don’t think that this is only done by changing the “state” to “displayState”.
For the moment I’m lucky with your solution and nosy for what is coming next.
cheers,
Peter
Dear all
Based on this wonderful widget (Thanks Nico)
I try to create widget for personal weather station
Any suggestion are welcome
Hi @Nico_R
Thank you again for your work.Popup menu looks really cool, and heating animation beautiful.
Unfortunately, I observe strange behavior of heating mode icon. On page open it displays default value (thermometer), when I switch to different mode icon switched to assigned to mode (airplane, hand, etc) but then i switch to another page and back to page with widget icon become again basic thermometer.
Widget version is 1.8.1
I am glad. In which German forum did you post it? Just out of interest because I’m from Germany too.
I tried to reproduce the error but didn’t succeed. When I switch between pages the icons stay as defined.
The icons are firmly defined in the code. The states of the string item are defined in the heatingMode array.
The first array key gets the hand_raised icon, the second key gets arrow_2_squarepath icon and the third key gets airplane. If you use more than 3 keys, the key> 3 always gets the thermometer.
Nico
I just thought, as your examples mostly shows “Klima Wohnzimmer”
Here’s the link for German-Forum, or here (may be you have to sign in to see the screen-shots)
@doctor64 I don’t know what kind of Thermostats you have, but my AVM-Fritz-Thermostats are “read-only” in the heating-mode. So if you make a change in the widget it will be set back after some seconds.
Changes are only possible inside the Fritz-Box-Web-UI.
Hi @Nico_R!
Sorry for false alarm, it was my fault. I just by old habit use spaces in heatingMode array, enter this:
AUTOMATIC, MANUAL, BOOST, VACATION
But spaces not ignored here, and of course strings “MANUAL” and " MANUAL" not matched, so default icon drawn.
Then I change array to:
AUTOMATIC,MANUAL,BOOST,VACATION
it start working as intended.
I think it will be common problem for people like me, with background in C or similar languages. I put space after comma by reflex! So i think it will be good to note somewhere what spaces not ignored.
Again, thank you very much for your excellent work!
Just a minor issue, and I not sure it related to Heating widget - i got lots of messages in openhab log like this:
[WARN ] [se.internal.SseItemStatesEventBuilder] - Attempting to send a state update of an item which doesn't exist: undefined
Not sure of root source, but get it when I switch to test page with just one widget - heating. Try to define exampleModeItem, (normally i not use it) and seems like warning message stop appearing.
@fibu-freak I use EQ-3 MAX! Basic thermostats - they modes are controllable from OH binding. Anyway, problem is resolved, thank you for hint. You are right, mode item change state after few seconds - from " MANUAL" to “MANUAL”!
Hi Alex,
as I understand the Array (heatingModeArray) and the corresponding Icons should be used in a certain order to interact with the “heatingModeIcon”. So my order is now MANUAL,AUTOMATIC,VACATION,…whateveryouwant:
MANUAL = handraised - Icon [0]
AUOMATIC = arrow_2_squarepath - Icon [1]
VACATION = airplane - Icon [2]
whateveryouwant = thermometer
Code-Line - 508 : f7: "=props.heatingModeItem ? (items[props.heatingModeItem].state == props.heatingModeArray.split(',')[0] ? 'hand_raised' : items[props.heatingModeItem].state == props.heatingModeArray.split(',')[1] ? 'arrow_2_squarepath' : items[props.heatingModeItem].state == props.heatingModeArray.split(',')[2] ? 'airplane' : 'thermometer') : ''"
As for me the “exampleModeArray” is more comfortable, I made a little change in Line 589:
f7: "=props.exampleModeItem ? (items[props.exampleModeItem].state == props.exampleModeArray.split(',')[0] ? 'thermometer' : items[props.exampleModeItem].state == props.exampleModeArray.split(',')[1] ? 'thermometer_sun' : items[props.exampleModeItem].state == props.exampleModeArray.split(',')[2] ? 'rocket' : items[props.exampleModeItem].state == props.exampleModeArray.split(',')[3] ? 'gauge' : items[props.exampleModeItem].state == props.exampleModeArray.split(',')[4] ? 'gauge_badge_minus' : 'wrench') : ''"
to get some fancy icons (not only “wrench”) for the “modes” I’m using there:
The Modes are:
…but the “WINDOW_OPEN” is no Option for me (it’s very special in the Binding)
Cheers - Peter
BTW: For the Boost-Mode I used that Icon:
I will improve this area with the next release
The same problem was already present here:
Unfortunately, I was not thoroughly enough in bug fixing sorry!
But now it should work and the error should no longer appear.
Look here in the adapted v1.8.1
@fibu-freak Thank you for helping others here with my mistakes before I can fix these
all the best,
Nico
Hi Nico,
I think there are no errors in your widget, I love it as it is.
It’s only the way to handle it the way you meant.
The warning message:
2021-02-28 13:42:36.771 [WARN ] [e.internal.SseItemStatesEventBuilder] - Attempting to send a state update of an item which doesn't exist: undefined
is from my point of view no error in the widget. I think this message comes up, when your in testing mode (Widgets) and an item which has to be named/assigned in the interaction, isn’t initialized/named/assigned.
I’m still very impressed of your work.
Cheers,
Peter
Hi @fibu-freak,
I’ll spend some time trying to figure root of problems. Looks like i found something, but, unfortunately, I don’t know how to fix it.
For example, we have in code for example item
display: "=props.exampleModeItem ? '' : 'none'"
So if exampleModeItemnot defined it will be not shown on interface. But code still have
action: command
active: "=(items[props.exampleModeItem].state === loop.buttonlabel ? true : false)"
actionCommand: =loop.buttonlabel
actionItem: =props.exampleModeItem
I think what OH engine still trying to access item with name in exampleModeItem variable, and because it is undefined generate a warning.
Hi @doctor64 and @fibu-freak ,
That is not completely right. The error occurs because I refer to an item in expressions which is not defined.
The error is definitely in my code. I’ve tried to ensure it everywhere but quickly forgot in this new lines.
Your guess is completely correct.
I forgot to include the boolean operator in the expressions here.
I have figure the error out and adapt the correct expression in the code.
It must look like:
active: "=props.heatingModeItem ? (items[props.heatingModeItem].state === loop.buttonlabel ? true : false) : ''"
and
actionItem: "=props.heatingModeItem ? props.heatingModeItem : ''"
this for exampleModeItem and heatingModeItem.
The corrected code can be found here without a new tag version.
I hope this solves the bugs and you have fun agian with the widget.
Hi @Nico_R
Thank you very much, last update fixes problem with warnings.
Hello together,
I am facing some issue in the widget with rounding the value of temperature:
The item is defined as shown below:
Number:Temperature SollTemp_Bad "Soll Bad [%.1f °C]" <temperature> (gBadOGThermostat, gTemperature) ["Setpoint", "Temperature"] {channel="knx:device:MDT_IP:MDT_HS4:SollTemp_Bad", stateDescription=""[pattern="%.1f °C"]}
Any idea how to fix this issue.
Thanks in advance!
Hi @snowy
Please share your yaml and the two items set and current temperature.
Maybe then i can help.
The Item definition
Number:Temperature ActualTemp_WZ "Ist Wohnzimmer [%.1f °C]" <temperature> (gLivingroomThermostat, gTemperature) ["Measurement", "Temperature"] {alexa="CurrentTemperature", channel="knx:device:MDT_IP:MDT_HS8:ActualTemp_WZ", stateDescription=""[pattern="%.1f °C"]}
Number:Temperature SollTemp_WZ "Soll Wohnzimmer [%.1f °C]" <temperature> (gLivingroomThermostat, gTemperature) ["Setpoint", "Temperature"] {channel="knx:device:MDT_IP:MDT_HS8:SollTemp_WZ", stateDescription=""[pattern="%.1f °C"]}
This is the YAML:
uid: widget_TestThermostat
tags: []
props:
parameters:
- description: eg. living room
label: location and widget identifier
name: location
required: true
type: TEXT
- description: Visual size of the control in px (default 400px), without a size the design is responsive
label: size [px]
name: size
required: false
type: TEXT
- description: Minimum value
label: minTemp
name: minTemp
required: true
type: TEXT
- description: Maximum value
label: maxTemp
name: maxTemp
required: true
- context: item
description: Item to control
label: Set point Item
name: setPointItem
required: true
type: TEXT
- context: item
description: Item to control
label: Change target value Item
name: changeTargetSwitchItem
required: true
type: TEXT
- context: item
label: Item for current temperature
name: currentPointItem
required: true
type: TEXT
- description: Control item unit eg °C
label: unit
name: unit
required: false
type: TEXT
- description: URL or path to a Image (if you use a local img eg. -> http://local-IP-Adress:8080/static/folder/img.svg )
label: URL or path to image
name: imgUrl
required: false
type: TEXT
advanced: true
- description: Heating mode strings as array eg. AUTO,MANU,OFF. The string will be send to the Heating-Mode-Item [String-Item]
label: Heating Mode Array
name: heatingModeArray
required: false
type: TEXT
advanced: true
- description: Example Mode Strings as Array eg. OFF,ON,BOOST. The string will be send to the Example-Mode-Item [String-Item]
label: Example Mode Array
name: exampleModeArray
required: false
type: TEXT
advanced: true
- context: item
description: Heating Mode Item [String-Item]
label: Heating Mode Item
name: heatingModeItem
required: false
type: TEXT
advanced: true
- context: item
description: Example Mode Item [String-Item] (eg. State of heating valve)
label: Example Mode Item
name: exampleModeItem
required: false
type: TEXT
advanced: true
- context: item
description: Valve Item [Switch-Item] (eg. State of heating valve) for Animation
label: Valve Item
name: valveItem
required: false
type: TEXT
advanced: true
- label: Custom font-size current&set-point marker (eg. 1em)
name: fontSizeMarker
required: false
type: TEXT
groupName: fonts
advanced: true
- label: Custom font-Size center (eg. 2em)
name: fontSizeCenter
required: false
type: TEXT
groupName: fonts
advanced: true
- label: Custom font-Size buttons (eg. 1.8em)
name: fontSizeButtons
required: false
type: TEXT
groupName: fonts
advanced: true
- label: Custom font-Size footer (eg. 1em)
name: fontSizeFooter
required: false
type: TEXT
groupName: fonts
advanced: true
- label: Main-Color Thermostat
name: colorThermostat
required: false
type: TEXT
groupName: colors
advanced: true
- label: Color control ring
name: colorControlRing
required: false
type: TEXT
groupName: colors
advanced: true
- label: Color buttons
name: colorButton
required: false
type: TEXT
groupName: colors
advanced: true
- label: Color center
name: colorCenter
required: false
type: TEXT
groupName: colors
advanced: true
- label: Color Typo
name: colorTypo
required: false
type: TEXT
groupName: colors
advanced: true
- label: Color setPoint Marker
name: colorSetMarker
required: false
type: TEXT
groupName: colors
advanced: true
- label: Color currentPoint Marker
name: colorCurrentMarker
required: false
type: TEXT
groupName: colors
advanced: true
- label: Color bar linear gradient startPoint
name: colorBarStartPoint
required: false
type: TEXT
groupName: colors
advanced: true
- label: Color bar linear gradient endPoint
name: colorBarEndPoint
required: false
type: TEXT
groupName: colors
advanced: true
parameterGroups:
- name: colors
label: Color-Settings
- name: fonts
label: Font-Settings
timestamp: Mar 3, 2021, 9:30:50 PM
component: f7-card
config:
title: "=(props.location) ? 'Klima ' + props.location : ''"
slots:
default:
- component: f7-card-content
slots:
default:
- component: f7-row
config:
resizableFixed: true
resizable-absolute: true
class:
- justify-content-center
slots:
default:
- component: f7-block
config:
class: thermostat
style:
flex-shrink: 0
--f7-block-margin-vertical: 0px
--f7-block-padding-vertical: 0px
--f7-block-padding-horizontal: 0px
padding-left: 0px
padding-top: "=props.size ? props.size + 'px': '100%'"
width: "=props.size ? Number(props.size)+'px' : '100%'"
background: "=props.colorThermostat ? props.colorThermostat : 'var(--f7-toggle-inactive-color)'"
border-radius: 50%
box-sizing: content-box
border: 2px solid rgb(64, 60, 77)
slots:
default:
- component: f7-block
config:
class: bar
style:
margin-top: 0px
position: absolute
width: "=props.size ? (Number(props.size)*0.89) +'px' : '89%'"
height: "=props.size ? (Number(props.size)*0.89) +'px' : '89%'"
top: 50%
left: 50%
transform: translate(-50%, -50%)
border-radius: 50%
slots:
default:
- component: f7-block
config:
class: inner_bar
style:
margin-top: 0
position: absolute
top: 50%
left: 50%
transform: translate(-50%, -50%)
width: "=props.size ? (Number(props.size)*0.86) +'px' : '97%'"
height: "=props.size ? (Number(props.size)*0.86) +'px' : '97%'"
border-radius: 100%
background-color: "=props.colorThermostat ? props.colorThermostat : 'var(--f7-toggle-inactive-color)'"
z-index: 4 !important
slots:
default:
- component: f7-block
config:
style:
background: "='conic-gradient(transparent 0deg 160deg, ' + (props.colorThermostat ? props.colorThermostat : 'var(--f7-toggle-inactive-color)') + ' 160deg 200deg, transparent 200deg 360deg)'"
content: ""
display: block
position: absolute
width: 100%
height: 100%
bottom: "=props.size ? '-7px' : '-7px'"
left: 50%
transform: translate(-50%)
- component: f7-block
config:
class: hold left
style:
margin-top: 0px
position: absolute
width: 100%
height: 100%
clip-path: "=props.size ? 'inset(0px 0px 0px ' + (Number(props.size)*0.89/2) + 'px)' : 'inset(0% 0% 0% 50%)'"
border-radius: 100%
background-color: rgb(58, 55, 73)
slots:
default:
- component: f7-block
config:
class: fill fill1
style:
margin-top: 0px
position: absolute
width: 100%
height: 100%
border-radius: 100%
clip-path: "=props.size ? 'inset(0px ' + (Number(props.size)*0.89/2) + 'px 0px 0px)' : 'inset(0% 50% 0% 0%)'"
background: "=props.colorBarStartPoint && props.colorBarEndPoint ? '-webkit-linear-gradient(top, ' + props.colorBarEndPoint + ' 20%,' + props.colorBarEndPoint + ' 100%)' : '-webkit-linear-gradient(top, rgb(255, 73, 0) 20%,rgb(255, 73, 0) 100%)'"
z-index: 1 !important
transition: transform 0.6s
transform: "=(items[props.setPointItem].state.split(' ')[0] >= (((Number(props.maxTemp) - Number(props.minTemp)) / 2) + Number(props.minTemp)) && items[props.setPointItem].state.split(' ')[0] <= Number(props.maxTemp) ? 'rotate('+(320/(Number(props.maxTemp)-Number(props.minTemp))*(items[props.setPointItem].state.split(' ')[0]-Number(props.minTemp))-160)+'deg)' : (items[props.setPointItem].state.split(' ')[0] > Number(props.maxTemp)) ? 'rotate(180deg)' : '')"
- component: f7-block
config:
class: hold right
style:
margin-top: 0px
position: absolute
width: 100%
height: 100%
clip-path: "=props.size ? 'inset(0px 0px 0px ' + (Number(props.size)*0.89/2) + 'px)' : 'inset(0% 0% 0% 50%)'"
border-radius: 100%
background-color: rgb(58, 55, 73)
z-index: 3 !important
transform: rotate(180deg)
slots:
default:
- component: f7-block
config:
class: fill
style:
margin-top: 0px
position: absolute
width: 100%
height: 100%
border-radius: 100%
z-index: 3 !important
animation: right 1s linear both
transition: transform 0.6s
- component: f7-block
config:
class: fill fill2
style:
position: absolute
margin-top: 0px
width: 100%
height: 100%
border-radius: 50%
z-index: 3 !important
clip-path: "=props.size ? 'inset(0px '+ (Number(props.size)*0.89/2) + 'px 0px 0px)' : 'inset(0% 50% 0% 0%)'"
background: "=props.colorBarStartPoint && props.colorBarEndPoint ? '-webkit-linear-gradient(top, ' + props.colorBarEndPoint + ' 40%,' + props.colorBarStartPoint + ' 100%)' : '-webkit-linear-gradient(top, rgb(255, 73, 0) 40%,rgb(255, 158, 35) 100%)'"
transform: "=(items[props.setPointItem].state.split(' ')[0] <= (((Number(props.maxTemp) - Number(props.minTemp)) / 2) + Number(props.minTemp)) && items[props.setPointItem].state.split(' ')[0] >= Number(props.minTemp) ? 'rotate('+(320/(Number(props.maxTemp)-Number(props.minTemp))*(items[props.setPointItem].state.split(' ')[0]-Number(props.minTemp))+20)+'deg)' : (items[props.setPointItem].state.split(' ')[0] > (((Number(props.maxTemp) - Number(props.minTemp)) / 2) + Number(props.minTemp))) ? 'rotate(180deg)' : '')"
- component: f7-block
config:
class: span
style:
margin-top: 0px
width: "=props.size ? (Number(props.size)*0.89) +'px' : '100%'"
font-weight: "=props.size ? (Number(props.size)*2) +'px' : 'calc(var(--f7-list-item-title-font-weight)*2)'"
position: absolute
bottom: 0px
text-align: center
text-transform: uppercase
font-size: "=props.fontSizeFooter ? props.fontSizeFooter : '1em'"
color: "=props.colorTypo ? props.colorTypo : 'rgb(87, 84, 95)'"
z-index: 99 !important
slots:
default:
- component: Label
config:
text: Heating
- component: f7-block
config:
class: shadow
style:
margin-top: 0px
position: absolute
top: 50%
left: 50%
transform: "=(items[props.setPointItem].state.split(' ')[0] >= Number(props.minTemp) && items[props.setPointItem].state.split(' ')[0] <= Number(props.maxTemp) ? 'translate(-50%, -50%) rotate('+(320/(Number(props.maxTemp)-Number(props.minTemp))*(items[props.setPointItem].state.split(' ')[0]-Number(props.minTemp))-160)+'deg)' : 'translate(-50%, -50%) rotate(0deg)')"
width: "=props.size ? (Number(props.size)*0.0625) +'px' : '6.25%'"
height: 86%
text-align: center
transition: 0.7s ease
animation: shadow 1.4s ease-out both
slots:
default:
- component: f7-block
config:
class: shadow-cube
style:
margin-top: 0px
position: absolute
top: 0
width: "=props.size ? (Number(props.size)*0.0625) +'px' : '100%'"
height: 0px
box-shadow: "=props.size ? '0 0 ' + (Number(props.size)*0.1125) +'px ' + (Number(props.size)*0.0325) + 'px ' + (props.colorSetMarker ? props.colorSetMarker : 'rgba(255, 158, 35, 0.5)'): '0 0 45px 13px rgba(255, 158, 35, 0.5)'"
- component: f7-block
config:
class: markerContainer
style:
pointer-events: none
margin-top: 0px
position: absolute
top: 50%
left: 50%
transform: "=(items[props.currentPointItem].state.split(' ')[0] >= Number(props.minTemp) && items[props.currentPointItem].state.split(' ')[0] <= Number(props.maxTemp) ? 'translate(-50%, -50%) rotate('+(320/(Number(props.maxTemp)-Number(props.minTemp))*(items[props.currentPointItem].state.split(' ')[0]-Number(props.minTemp))-160)+'deg)' : 'translate(-50%, -50%) rotate(0deg)')"
width: "=props.size ? (Number(props.size)*0.1) +'px' : '10%'"
height: 100%
text-align: center
transition: 0.7s ease
opacity: 1
z-index: 99 !important
slots:
default:
- component: f7-block
config:
class: markerCurrent
style:
margin-top: 0px
width: "=props.size ? (Number(props.size)*0.1) +'px' : '100%'"
height: "=props.size ? (Number(props.size)*0.1) +'px' : ''"
padding-top: "=props.size ? '' : '100%'"
background: "=props.colorCurrentMarker ? props.colorCurrentMarker : 'rgb(33, 150, 243)'"
position: absolute
transform: translate(-50%,-50%) rotate(45deg)
left: 50%
top: "=props.size ? (Number(props.size)*0.14) +'px' : '15%'"
border-radius: 0% 50% 50% 50%
box-shadow: 0 0 5px 1px rgb(48, 46, 56)
slots:
default:
- component: f7-block
config:
class: number
style:
margin-top: 0px
position: absolute
top: 50%
left: 50%
transform: translate(-50%, -50%) rotate(-45deg)
text-align: center
slots:
default:
- component: Label
config:
text: =items[props.currentPointItem].state.split(' ')[0]
style:
font-size: "=props.fontSizeMarker ? props.fontSizeMarker : '1em'"
color: white
font-weight: bold
- component: f7-block
config:
class: markerContainer
style:
pointer-events: none
margin-top: 0px
position: absolute
top: 50%
left: 50%
transform: "=(items[props.setPointItem].state.split(' ')[0] >= Number(props.minTemp) && items[props.setPointItem].state.split(' ')[0] <= Number(props.maxTemp) ? 'translate(-50%, -50%) rotate('+(320/(Number(props.maxTemp)-Number(props.minTemp))*(items[props.setPointItem].state.split(' ')[0]-Number(props.minTemp))-160)+'deg)' : 'translate(-50%, -50%) rotate(0deg)')"
width: "=props.size ? (Number(props.size)*0.1) +'px' : '10%'"
height: 100%
text-align: center
transition: 0.7s ease
opacity: 1
z-index: 99 !important
slots:
default:
- component: f7-block
config:
class: markerSet
style:
margin-top: 0px
width: "=props.size ? (Number(props.size)*0.1) +'px' : '100%'"
height: "=props.size ? (Number(props.size)*0.1) +'px' : ''"
padding-top: "=props.size ? '' : '100%'"
background: "=props.colorSetMarker ? props.colorSetMarker : 'rgb(230, 74, 25)'"
position: absolute
transform: translate(-50%,-50%) rotate(-45deg)
left: 50%
top: "=props.size ? (Number(props.size)*Number(-0.0125)) +'px': '-2%'"
border-radius: 50% 50% 50% 0
box-shadow: 0 0 5px 1px rgb(48, 46, 56)
z-index: 100 !important
slots:
default:
- component: f7-block
config:
class: number
style:
margin-top: 0px
position: absolute
top: 50%
left: 50%
transform: translate(-50%, -50%) rotate(45deg)
text-align: center
slots:
default:
- component: Label
config:
text: =items[props.setPointItem].state.split(' ')[0]
style:
font-size: "=props.fontSizeMarker ? props.fontSizeMarker : '1em'"
color: white
font-weight: bold
- component: f7-block
config:
class: center
style:
margin-top: 0px
position: absolute
width: "=props.size ? (Number(props.size)*0.65) +'px' : '65%'"
height: "=props.size ? (Number(props.size)*0.65) +'px' : '65%'"
background: "=props.colorControlRing ? props.colorControlRing : 'rgb(227, 228, 237)'"
top: 50%
left: 50%
transform: translate(-50%, -50%)
border-radius: 50%
box-shadow: 0px 15px 35px 11px rgba(46, 44, 58,0.60)
slots:
default:
- component: f7-block
config:
class: buttonContainer
style:
display: "=props.heatingModeItem ? '' : 'none'"
margin-top: 0px
position: absolute
top: 50%
left: 50%
transform: "=props.exampleModeItem ? 'translate(-50%, -50%) rotate(30deg)' : 'translate(-50%, -50%)'"
width: "=props.size ? (Number(props.size)*0.15) +'px' : '15%'"
height: 100%
text-align: center
transition: 0.7s ease
opacity: 1
z-index: 99 !important
slots:
default:
- component: oh-button
config:
popoverOpen: ='.' + props.location + '.popoverHeatingMode'
style:
width: 100%
height: 20%
position: absolute
bottom: 0%
left: 50%
transform: translate(-50%)
color: "=props.colorButton ? props.colorButton + ' !important': ''"
slots:
default:
- component: f7-icon
config:
f7: "=props.heatingModeItem ? (items[props.heatingModeItem].state == props.heatingModeArray.split(',')[0] ? 'hand_raised' : items[props.heatingModeItem].state == props.heatingModeArray.split(',')[1] ? 'arrow_2_squarepath' : items[props.heatingModeItem].state == props.heatingModeArray.split(',')[2] ? 'airplane' : 'thermometer') : ''"
style:
font-size: "=props.fontSizeButtons ? props.fontSizeButtons : '2em'"
position: absolute
transform: translate(-50%, -50%)
top: 50%
margin-top: auto
- component: f7-popover
config:
class: =props.location + ' popoverHeatingMode'
slots:
default:
- component: f7-card
config:
noShadow: true
class:
- popover-close
action: variable
actionVariable: myVar
clearVariable: true
actionVariableValue: success
slots:
default:
- component: f7-row
config: {}
slots:
default:
- component: f7-col
slots:
default:
- component: oh-repeater
config:
for: buttonlabel
in: =props.heatingModeArray.split(",")
containerStyle:
width: 100%
slots:
default:
- component: oh-button
config:
color: "=props.colorButton ? props.colorButton : ''"
class: margin
text: =loop.buttonlabel
outline: true
action: command
active: "=props.heatingModeItem ? (items[props.heatingModeItem].state === loop.buttonlabel ? true : false) : ''"
actionCommand: =loop.buttonlabel
actionItem: "=props.heatingModeItem ? props.heatingModeItem : ''"
- component: f7-block
config:
class: buttonContainer
style:
display: "=props.exampleModeItem ? '' : 'none'"
margin-top: 0px
position: absolute
top: 50%
left: 50%
transform: "=props.heatingModeItem ? 'translate(-50%, -50%) rotate(-30deg)' : 'translate(-50%, -50%)'"
width: "=props.size ? (Number(props.size)*0.15) +'px' : '15%'"
height: 100%
text-align: center
transition: 0.7s ease
opacity: 1
z-index: 99 !important
slots:
default:
- component: oh-button
config:
popoverOpen: ='.' + props.location + '.popoverExampleMode'
style:
width: 100%
height: 20%
position: absolute
bottom: 0%
left: 50%
transform: translate(-50%)
color: "=props.colorButton ? props.colorButton + ' !important': ''"
slots:
default:
- component: f7-icon
config:
f7: wrench
style:
font-size: "=props.fontSizeButtons ? props.fontSizeButtons : '2em'"
position: absolute
transform: translate(-50%, -50%)
top: 50%
margin-top: auto
- component: f7-popover
config:
class: =props.location + ' popoverExampleMode'
slots:
default:
- component: f7-card
config:
noShadow: true
class:
- popover-close
action: variable
actionVariable: myVar
clearVariable: true
actionVariableValue: success
slots:
default:
- component: f7-row
config: {}
slots:
default:
- component: f7-col
slots:
default:
- component: oh-repeater
config:
for: buttonlabel
in: =props.exampleModeArray.split(",")
containerStyle:
width: 100%
slots:
default:
- component: oh-button
config:
color: "=props.colorButton ? props.colorButton : ''"
class: margin
text: =loop.buttonlabel
outline: true
action: command
active: "=props.exampleModeItem ? (items[props.exampleModeItem].state === loop.buttonlabel ? true : false) : ''"
actionCommand: =loop.buttonlabel
actionItem: "=props.exampleModeItem ? props.exampleModeItem : ''"
- component: oh-button
config:
style:
width: 30%
height: 50%
position: absolute
margin-top: 0px
top: 50%
left: 10%
transform: translate(-50%, -50%)
color: "=props.colorButton ? props.colorButton : ''"
action: command
actionItem: =props.changeTargetSwitchItem
actionCommand: OFF
slots:
default:
- component: f7-icon
config:
style:
font-size: "=props.fontSizeButtons ? props.fontSizeButtons : '2em'"
position: absolute
transform: translate(-50%, -50%)
top: 50%
margin-top: auto
f7: arrow_turn_left_down
- component: oh-button
config:
style:
width: 30%
height: 50%
position: relative
margin-top: 0px
top: 50%
left: 90%
transform: translate(-50%, -50%)
color: "=props.colorButton ? props.colorButton : ''"
action: command
actionItem: =props.changeTargetSwitchItem
actionCommand: ON
slots:
default:
- component: f7-icon
config:
style:
font-size: "=props.fontSizeButtons ? props.fontSizeButtons : '2em'"
position: absolute
transform: translate(-50%, -50%)
top: 50%
margin-top: auto
f7: arrow_turn_right_up
- component: f7-block
config:
class: valveAnimation
style:
z-index: -100 !important
pointer-events: none
display: "=(props.valveItem && items[props.valveItem].state == 'ON' )? '' : 'none'"
background: "=props.colorSetMarker ? 'radial-gradient(' + props.colorSetMarker +' 30%, transparent 50%)' : 'radial-gradient(var(--f7-theme-color) 30%, transparent 50%)'"
margin-top: 0px
position: absolute
transform: translate(-50%, -50%)
width: 100%
height: 100%
top: 50%
left: 50%
border-radius: 50%
animation: skeleton-effect-fade 2s linear infinite
- component: f7-block
config:
class: small
style:
z-index: 100 !important
margin-top: 0px
position: absolute
width: "=props.size ? (Number(props.size)*0.375) +'px' : '57.6%'"
height: "=props.size ? (Number(props.size)*0.375) +'px' : '57.6%'"
background: "=props.colorCenter ? props.colorCenter : 'rgb(248, 249, 250)'"
text-align: center
animation: bound-in-small 0.6s ease forwards
top: 50%
left: 50%
transform: translate(-50%, -50%)
border-radius: 50%
box-shadow: 0px 5px 10px 5px rgba(96, 93, 111,0.19)
slots:
default:
- component: f7-block
config:
class: heat
style:
font-size: "=props.size ? (Number(props.size)*0.0375) +'px' : '14px'"
color: "=props.colorTypo ? props.colorTypo : 'rgb(87, 84, 95)'"
font-weight: 300
slots:
default:
- component: Label
config:
text: =props.location
- component: f7-block
config:
class: heat
style:
font-size: "=props.fontSizeCenter ? props.fontSizeCenter : '2em'"
color: "=props.colorTypo ? props.colorTypo : 'rgb(87, 84, 95)'"
font-weight: 300
slots:
default:
- component: Label
config:
text: "=props.unit ? items[props.setPointItem].state.split(' ')[0] + '' + props.unit : items[props.setPointItem].state.split(' ')[0]"
- component: oh-image
config:
url: "=props.imgUrl ? props.imgUrl : 'https://community-openhab-org.s3-eu-central-1.amazonaws.com/original/2X/7/7d388a86c95471f89b1bb911d96d7609a3e3a059.svg'"
style:
position: absolute
transform: translate(-50%)
left: 50%
width: 40%
Hi @snowy
use .displayState
instead of .state
Then for example the line 460 in your yaml looks like:
Now:
text: =items[props.setPointItem].state.split(' ')[0]
After:
text: =items[props.setPointItem].displayState.split(' ')[0]
all the best,
Nico