you can use it already
@rubenfuser
I have zigbee controlled blinds and I am using zigbee2mqtt.
This the topic output:
zigbee2mqtt/blind2 {“last_seen”:“2023-07-30T18:39:54+10:00”,“linkquality”:156,“motor_speed”:true,“position”:100,“running”:false,“state”:“OPEN”}
This widget is really good and I use one widget for each blind but I couldn’t work out how you could use the up, down and stop buttons AND also use the 25, 40, 50, 75, 90 with only one item.
Did you only use 1 item to achieve both controls?
I created 2 items for each blind. 1 for the rollershutter type of item and 1 for the position.
Here is the code I changed it to
uid: Remote_blind_control
tags: []
props:
parameters:
- context: Text
description: Title of the card
label: Title
name: rollerTitle
required: false
type: TEXT
- context: item
description: Rollershutter Item
label: Rollershutter Item
name: groupItem
required: true
type: TEXT
- context: item
description: Rollershutter position
label: Rollershutter Position
name: blindposition
required: true
type: TEXT
- context: item
description: Enable Schedule
label: Enable Schedule Item
name: EnableSchedule
required: false
type: TEXT
- context: item
description: Opening Time
label: Opening Time Item
name: OpeningTimeItem
required: false
type: TEXT
- context: item
description: Closure Time
label: Closure Time Item
name: ClosureTimeItem
required: false
type: TEXT
timestamp: Jul 30, 2023, 10:02:31 AM
component: f7-card
config:
style:
background: '=themeOptions.dark === "dark" ? "rgb(40, 40, 40)" : "rgb(240, 240, 240)"'
border-radius: var(--f7-card-expandable-border-radius)
box-shadow: 5px 5px 15px 1px rgba(0,0,0,0.3)
margin-left: 5px
margin-right: 5px
slots:
default:
- component: f7-card-content
config:
style:
position: relative
z-index: 3
slots:
default:
- component: f7-row
config:
style:
margin-bottom: -10px
margin-left: 0px
margin-right: 0px
slots:
default:
- component: f7-col
config:
style:
margin-left: 0px
margin-right: 0px
width: 60px
slots:
default:
- component: oh-icon
config:
height: 50px
icon: iconify:ic:twotone-roller-shades
style:
color: orange
- component: f7-col
config:
style:
margin-left: 60px
margin-right: 0px
position: absolute
width: 80%
slots:
default:
- component: f7-row
slots:
default:
- component: Label
config:
style:
color: '=themeOptions.dark === "dark" ? "white" : "black"'
font-size: 15px
font-weight: 500
text: =props.rollerTitle
- component: f7-row
config:
style:
align-items: right
display: flex
flex-direction: row
slots:
default:
- component: f7-chip
config:
style:
background: orange
color: black
font-weight: 500
text: '=items[props.groupItem].state == "100" || items[props.groupItem].displayState == "100" ? "Closed" : items[props.groupItem].state == "0" || items[props.groupItem].displayState == "0" ? "Open" : items[props.groupItem].state + "% closed" || items[props.groupItem].displayState + "% closed"'
- component: f7-col
config:
style:
margin-left: 0px
margin-right: 0px
width: 26px
slots:
default:
- component: oh-link
config:
action: command
actionCommand: UP
actionItem: =props.groupItem
iconColor: orange
iconF7: arrow_up_circle
iconSize: 28
style:
background: '=themeOptions.dark === "dark" ? "rgb(40, 40, 40)" : "rgb(240, 240, 240)"'
z-index: 98
- component: oh-link
config:
action: command
actionCommand: STOP
actionItem: =props.groupItem
iconF7: stop_circle
iconSize: 28
style:
background: '=themeOptions.dark === "dark" ? "rgb(40, 40, 40)" : "rgb(240, 240, 240)"'
z-index: 98
- component: oh-link
config:
action: command
actionCommand: DOWN
actionItem: =props.groupItem
iconColor: orange
iconF7: arrow_down_circle
iconSize: 28
style:
background: '=themeOptions.dark === "dark" ? "rgb(40, 40, 40)" : "rgb(240, 240, 240)"'
z-index: 98
- component: f7-card-content
config:
class: align-items-center alignt-text-center justify-content-center
style:
margin-left: 15px
margin-right: 15px
position: relative
z-index: 2
visible: =(vars.PresetVisible) == true
slots:
default:
- component: f7-row
slots:
default:
- component: oh-slider
config:
color: orange
item: =props.blindposition
max: 100
min: 0
step: "1"
style:
background: trasparent
color: black
font-size: 13px
- component: f7-row
config:
style:
margin-top: 15px
slots:
default:
- component: oh-button
config:
action: command
actionCommand: 25
actionItem: =props.blindposition
round: true
style:
background: '=items[props.groupItem].state >= "20" && items[props.groupItem].state <= "30" ? "orange" : "rgb(210, 210, 210)"'
color: black
z-index: 98
text: 25
- component: oh-button
config:
action: command
actionCommand: 40
actionItem: =props.blindposition
round: true
style:
background: '=items[props.groupItem].state >= "35" && items[props.groupItem].state <= "45" ? "orange" : "rgb(210, 210, 210)"'
color: black
z-index: 98
text: 40
- component: oh-button
config:
action: command
actionCommand: 50
actionItem: =props.blindposition
round: true
style:
background: '=items[props.groupItem].state >= "45" && items[props.groupItem].state <= "55" ? "orange" : "rgb(210, 210, 210)"'
color: black
z-index: 98
text: 50
- component: oh-button
config:
action: command
actionCommand: 75
actionItem: =props.blindposition
round: true
style:
background: '=items[props.groupItem].state >= "70" && items[props.groupItem].state <= "80" ? "orange" : "rgb(210, 210, 210)"'
color: black
z-index: 98
text: 75
- component: oh-button
config:
action: command
actionCommand: 90
actionItem: =props.blindposition
round: true
style:
background: '=items[props.groupItem].state >= "85" && items[props.groupItem].state <= "95" ? "orange" : "rgb(210, 210, 210)"'
color: black
z-index: 98
text: 90
- component: f7-card-content
config:
class: display-flex align-items-center alignt-text-center justify-content-center
style:
margin-left: 0px
margin-right: 0px
margin-top: -10px
position: relative
z-index: 1
visible: =(vars.ScheduleVisible) == true
slots:
default:
- component: f7-row
config:
style:
width: 300px
slots:
default:
- component: f7-col
config:
style:
width: 100px
slots:
default:
- component: f7-row
slots:
default:
- component: f7-col
config:
style:
width: 100px
slots:
default:
- component: Label
config:
style:
font-size: 15px
text-align: center
text-decoration: underline
text-underline-offset: 4px
text: Opening Time
- component: f7-row
slots:
default:
- component: f7-col
config:
style:
width: 40px
slots:
default:
- component: f7-row
config:
style:
height: 30px
text-align: center
slots:
default:
- component: oh-button
config:
action: command
actionCommand: =(dayjs(items[props.OpeningTimeItem].state).add(1, 'hour').format('YYYY-MM-DDTHH:mm:ss.ZZ'))
actionItem: =(props.OpeningTimeItem)
style:
--f7-button-text-color: orange
font-family: u2400
font-size: 100%
width: 40px
text: ▲
- component: f7-row
config:
style:
height: 30px
slots:
default:
- component: Label
config:
style:
font-size: 15px
text-align: center
width: 40px
text: "=(((items[props.OpeningTimeItem].state === 'NULL') || !props.OpeningTimeItem) ? '?': props.timeFormat == '12h' ? dayjs(items[props.OpeningTimeItem].state).format('hh'): dayjs(items[props.OpeningTimeItem].state).format('HH'))"
- component: f7-row
config:
style:
height: 30px
text-align: center
slots:
default:
- component: oh-button
config:
action: command
actionCommand: =(dayjs(items[props.OpeningTimeItem].state).add(-1, 'hour').format('YYYY-MM-DDTHH:mm:ss.ZZ'))
actionItem: =(props.OpeningTimeItem)
style:
--f7-button-text-color: orange
font-family: u2400
font-size: 100%
width: 40px
text: ▼
- component: f7-col
config:
style:
width: 20px
slots:
default:
- component: f7-row
config:
style:
height: 30px
text-align: center
slots:
default:
- component: Label
config:
style:
font-size: 15px
text-align: center
width: 20px
text: ""
- component: f7-row
config:
style:
height: 30px
slots:
default:
- component: Label
config:
style:
font-size: 15px
text-align: center
width: 20px
text: ":"
- component: f7-row
config:
style:
height: 30px
text-align: center
slots:
default:
- component: Label
config:
style:
font-size: 15px
text-align: center
width: 20px
text: ""
- component: f7-col
config:
style:
width: 40px
slots:
default:
- component: f7-row
config:
style:
height: 30px
text-align: center
slots:
default:
- component: oh-button
config:
action: command
actionCommand: =(dayjs(items[props.OpeningTimeItem].state).add(1, 'minute').format('YYYY-MM-DDTHH:mm:ss.ZZ'))
actionItem: =(props.OpeningTimeItem)
style:
--f7-button-text-color: orange
font-family: u2400
font-size: 100%
width: 40px
text: ▲
- component: f7-row
config:
style:
height: 30px
slots:
default:
- component: Label
config:
style:
font-size: 15px
text-align: center
width: 40px
text: "=(((items[props.OpeningTimeItem].state === 'NULL') || !props.OpeningTimeItem) ? '?': dayjs(items[props.OpeningTimeItem].state).format('mm'))"
- component: f7-row
config:
style:
height: 30px
text-align: center
slots:
default:
- component: oh-button
config:
action: command
actionCommand: =(dayjs(items[props.OpeningTimeItem].state).add(-1, 'minute').format('YYYY-MM-DDTHH:mm:ss.ZZ'))
actionItem: =(props.OpeningTimeItem)
style:
--f7-button-text-color: orange
font-family: u2400
font-size: 100%
width: 40px
text: ▼
- component: f7-col
config:
style:
width: 100px
slots:
default:
- component: f7-row
slots:
default:
- component: f7-col
config:
style:
width: 100px
slots:
default:
- component: Label
config:
style:
font-size: 15px
text-align: center
text-decoration: underline
text-underline-offset: 4px
text: Closure Time
- component: f7-row
slots:
default:
- component: f7-col
config:
style:
width: 40px
slots:
default:
- component: f7-row
config:
style:
height: 30px
text-align: center
slots:
default:
- component: oh-button
config:
action: command
actionCommand: =(dayjs(items[props.ClosureTimeItem].state).add(1, 'hour').format('YYYY-MM-DDTHH:mm:ss.ZZ'))
actionItem: =(props.ClosureTimeItem)
style:
--f7-button-text-color: orange
font-family: u2400
font-size: 100%
width: 40px
text: ▲
- component: f7-row
config:
style:
height: 30px
slots:
default:
- component: Label
config:
style:
font-size: 15px
text-align: center
width: 40px
text: "=(((items[props.ClosureTimeItem].state === 'NULL') || !props.ClosureTimeItem) ? '?': props.timeFormat == '12h' ? dayjs(items[props.ClosureTimeItem].state).format('hh'): dayjs(items[props.ClosureTimeItem].state).format('HH'))"
- component: f7-row
config:
style:
height: 30px
text-align: center
slots:
default:
- component: oh-button
config:
action: command
actionCommand: =(dayjs(items[props.ClosureTimeItem].state).add(-1, 'hour').format('YYYY-MM-DDTHH:mm:ss.ZZ'))
actionItem: =(props.ClosureTimeItem)
style:
--f7-button-text-color: orange
font-family: u2400
font-size: 100%
width: 40px
text: ▼
- component: f7-col
config:
style:
width: 20px
slots:
default:
- component: f7-row
config:
style:
height: 30px
text-align: center
slots:
default:
- component: Label
config:
style:
font-size: 15px
text-align: center
width: 20px
text: ""
- component: f7-row
config:
style:
height: 30px
slots:
default:
- component: Label
config:
style:
font-size: 15px
text-align: center
width: 20px
text: ":"
- component: f7-row
config:
style:
height: 30px
text-align: center
slots:
default:
- component: Label
config:
style:
font-size: 15px
text-align: center
width: 20px
text: ""
- component: f7-col
config:
style:
width: 40px
slots:
default:
- component: f7-row
config:
style:
height: 30px
text-align: center
slots:
default:
- component: oh-button
config:
action: command
actionCommand: =(dayjs(items[props.ClosureTimeItem].state).add(1, 'minute').format('YYYY-MM-DDTHH:mm:ss.ZZ'))
actionItem: =(props.ClosureTimeItem)
style:
--f7-button-text-color: orange
font-family: u2400
font-size: 100%
width: 40px
text: ▲
- component: f7-row
config:
style:
height: 30px
slots:
default:
- component: Label
config:
style:
font-size: 15px
text-align: center
width: 40px
text: "=(((items[props.ClosureTimeItem].state === 'NULL') || !props.ClosureTimeItem) ? '?': dayjs(items[props.ClosureTimeItem].state).format('mm'))"
- component: f7-row
config:
style:
height: 30px
text-align: center
slots:
default:
- component: oh-button
config:
action: command
actionCommand: =(dayjs(items[props.ClosureTimeItem].state).add(-1, 'minute').format('YYYY-MM-DDTHH:mm:ss.ZZ'))
actionItem: =(props.ClosureTimeItem)
style:
--f7-button-text-color: orange
font-family: u2400
font-size: 100%
width: 40px
text: ▼
- component: f7-card-content
config:
class: align-items-center alignt-text-center justify-content-center
style:
margin-bottom: -50px
margin-left: 15px
margin-right: 15px
margin-top: -50px
position: relative
z-index: 0
visible: =(vars.ChartVisible) == true
slots:
default:
- component: oh-chart
config:
chartType: day
options:
backgroundColor: transparent
periodVisible: false
slots:
grid:
- component: oh-chart-grid
config:
containLabel: false
series:
- component: oh-time-series
config:
barWidth: 1
color: orange
gridIndex: 0
item: =props.groupItem
type: bar
xAxisIndex: 0
yAxisIndex: 0
xAxis:
- component: oh-time-axis
config:
axisPointer:
show: false
gridIndex: 0
yAxis:
- component: oh-value-axis
config:
gridIndex: 0
min: 0
name: " % closed"
- component: f7-card-footer
config:
style:
background: rgb(245, 218, 137)
border-radius: 0 0 10px 10px
height: auto
slots:
default:
- component: f7-block
config:
style:
bottom: 3px
display: flex
left: 0
position: absolute
slots:
default:
- component: oh-button
config:
action: variable
actionVariable: PresetVisible
actionVariableValue: =! (vars.PresetVisible)
slots:
default:
- component: oh-icon
config:
icon: iconify:mdi:window-shutter-auto
style:
color: "=(vars.PresetVisible ? 'rgb(255, 128, 0)' : 'rgb(106, 106, 106)')"
width: 25px
- component: oh-button
config:
action: variable
actionVariable: ScheduleVisible
actionVariableValue: =! (vars.ScheduleVisible)
slots:
default:
- component: oh-icon
config:
icon: iconify:akar-icons:clock
style:
color: "=(vars.ScheduleVisible ? 'rgb(255, 128, 0)' : 'rgb(106, 106, 106)')"
width: 25px
- component: oh-toggle
config:
color: green
item: =props.EnableSchedule
style:
--f7-toggle-height: 20px
--f7-toggle-inactive-color: red
--f7-toggle-width: 40px
margin-left: 7px
margin-top: -2px
z-index: 98
visible: =(vars.ScheduleVisible) == true
- component: oh-button
config:
action: variable
actionVariable: ChartVisible
actionVariableValue: =! (vars.ChartVisible)
slots:
default:
- component: oh-icon
config:
icon: iconify:ant-design:bar-chart-outlined
style:
color: "=(vars.ChartVisible ? 'rgb(255, 128, 0)' : 'rgb(106, 106, 106)')"
width: 25px
Here is just the first part of the things code as I have 7 blinds on this thing:
UID: mqtt:topic:mqttbroker:0cb7d742b7
label: Blinds 1 - 7
thingTypeUID: mqtt:topic
configuration: {}
bridgeUID: mqtt:broker:mqttbroker
location: Lounge
channels:
- id: blind1control
channelTypeUID: mqtt:rollershutter
label: Blind 1 control
description: ""
configuration:
commandTopic: zigbee2mqtt/blind1/set
stateTopic: zigbee2mqtt/blind1
transformationPattern: JSONPATH:$.position
off: CLOSE
on: OPEN
- id: blind1position
channelTypeUID: mqtt:number
label: Blind 1 position
description: ""
configuration:
commandTopic: zigbee2mqtt/blind2/set/position
min: 0
stateTopic: zigbee2mqtt/blind2
transformationPattern: JSONPATH:$.position
max: 100
Blind control item is a rollershutter
Blind position is a number
Other than that it works well.
Thanks for the share as there is no way I would work out all of the coding you have done.
Hi! Yes i have made this widget based on my Bticino rollershutter,and use 1 item that support % and also UP & Down commands.
I never know zigbee work different than mine (or mine different from all other ;))
Hopefully the changes I made that are correct. I just changed bits until it worked.
The widget also works well with group items for the position and UP DOWN so all the blinds move.
Again, thanks. It is a great widget. I like it very much.
I changed this line:
text: '=items[props.groupItem].state == "100" || items[props.groupItem].displayState == "100" ? "Closed" : items[props.groupItem].state == "0" || items[props.groupItem].displayState == "0" ? "Open" : items[props.groupItem].state + "% closed" || items[props.groupItem].displayState + "% closed"'
so the percentage would show up when I used a group to control the blinds. This way I don’t need to set up a displayState to get the correct decimal places.
Works well so far.
to
text: '=Math.round(items[props.groupItem].state) == "100" ? "Closed" : Math.round(items[props.groupItem].state) == "0" ? "Open" : Math.round(items[props.blindposition].state) + "% closed"'
Wow! If you want to pm me the full code i will stick it to the top of the page (if the widget keeps the same look/settings of mine with your updated code
Here is my latest attempt: It uses 2 items. one for control UP/DOWN and one for position 0-100
and you can can put those into a group and use that group to control all the blinds in that group.
Also I don’t use and have not tried the scheduling part of the widget.
uid: Remote_blind_control
tags: []
props:
parameters:
- context: Text
description: Title of the card
label: Title
name: rollerTitle
required: false
type: TEXT
- context: item
description: Rollershutter Item
label: Rollershutter Item
name: groupItem
required: true
type: TEXT
- context: item
description: Rollershutter position
label: Rollershutter Position
name: blindposition
required: true
type: TEXT
- context: item
description: Enable Schedule
label: Enable Schedule Item
name: EnableSchedule
required: false
type: TEXT
- context: item
description: Opening Time
label: Opening Time Item
name: OpeningTimeItem
required: false
type: TEXT
- context: item
description: Closure Time
label: Closure Time Item
name: ClosureTimeItem
required: false
type: TEXT
timestamp: Aug 7, 2023, 10:02:11 PM
component: f7-card
config:
style:
background: '=themeOptions.dark === "dark" ? "rgb(40, 40, 40)" : "rgb(240, 240, 240)"'
border-radius: var(--f7-card-expandable-border-radius)
box-shadow: 5px 5px 15px 1px rgba(0,0,0,0.3)
margin-left: 5px
margin-right: 5px
slots:
default:
- component: f7-card-content
config:
style:
position: relative
z-index: 3
slots:
default:
- component: f7-row
config:
style:
margin-bottom: -10px
margin-left: 0px
margin-right: 0px
slots:
default:
- component: f7-col
config:
style:
margin-left: 0px
margin-right: 0px
width: 60px
slots:
default:
- component: oh-icon
config:
height: 50px
icon: iconify:ic:twotone-roller-shades
style:
color: orange
- component: f7-col
config:
style:
margin-left: 60px
margin-right: 0px
position: absolute
width: 80%
slots:
default:
- component: f7-row
slots:
default:
- component: Label
config:
style:
color: '=themeOptions.dark === "dark" ? "white" : "black"'
font-size: 15px
font-weight: 500
text: =props.rollerTitle
- component: f7-row
config:
style:
align-items: right
display: flex
flex-direction: row
slots:
default:
- component: f7-chip
config:
style:
background: orange
color: black
font-weight: 500
text: '=Math.round(items[props.groupItem].state) == "100" ? "Closed" : Math.round(items[props.groupItem].state) == "0" ? "Open" : Math.round(items[props.blindposition].state) + "% closed"'
- component: f7-col
config:
style:
margin-left: 0px
margin-right: 0px
width: 26px
slots:
default:
- component: oh-link
config:
action: command
actionCommand: UP
actionItem: =props.groupItem
iconColor: orange
iconF7: arrow_up_circle
iconSize: 28
style:
background: '=themeOptions.dark === "dark" ? "rgb(40, 40, 40)" : "rgb(240, 240, 240)"'
z-index: 98
- component: oh-link
config:
action: command
actionCommand: STOP
actionItem: =props.groupItem
iconF7: stop_circle
iconSize: 28
style:
background: '=themeOptions.dark === "dark" ? "rgb(40, 40, 40)" : "rgb(240, 240, 240)"'
z-index: 98
- component: oh-link
config:
action: command
actionCommand: DOWN
actionItem: =props.groupItem
iconColor: orange
iconF7: arrow_down_circle
iconSize: 28
style:
background: '=themeOptions.dark === "dark" ? "rgb(40, 40, 40)" : "rgb(240, 240, 240)"'
z-index: 98
- component: f7-card-content
config:
class: align-items-center alignt-text-center justify-content-center
style:
margin-left: 15px
margin-right: 15px
position: relative
z-index: 2
visible: =(vars.PresetVisible) == true
slots:
default:
- component: f7-row
slots:
default:
- component: oh-slider
config:
color: orange
item: =props.blindposition
max: 100
min: 0
step: "1"
style:
background: trasparent
color: black
font-size: 13px
- component: f7-row
config:
style:
margin-top: 15px
slots:
default:
- component: oh-button
config:
action: command
actionCommand: 25
actionItem: =props.blindposition
round: true
style:
background: '=items[props.groupItem].state >= "20" && items[props.groupItem].state <= "30" ? "orange" : "rgb(210, 210, 210)"'
color: black
z-index: 98
text: 25
- component: oh-button
config:
action: command
actionCommand: 40
actionItem: =props.blindposition
round: true
style:
background: '=items[props.groupItem].state >= "35" && items[props.groupItem].state <= "45" ? "orange" : "rgb(210, 210, 210)"'
color: black
z-index: 98
text: 40
- component: oh-button
config:
action: command
actionCommand: 50
actionItem: =props.blindposition
round: true
style:
background: '=items[props.groupItem].state >= "45" && items[props.groupItem].state <= "55" ? "orange" : "rgb(210, 210, 210)"'
color: black
z-index: 98
text: 50
- component: oh-button
config:
action: command
actionCommand: 75
actionItem: =props.blindposition
round: true
style:
background: '=items[props.groupItem].state >= "70" && items[props.groupItem].state <= "80" ? "orange" : "rgb(210, 210, 210)"'
color: black
z-index: 98
text: 75
- component: oh-button
config:
action: command
actionCommand: 90
actionItem: =props.blindposition
round: true
style:
background: '=items[props.groupItem].state >= "85" && items[props.groupItem].state <= "95" ? "orange" : "rgb(210, 210, 210)"'
color: black
z-index: 98
text: 90
- component: f7-card-content
config:
class: display-flex align-items-center alignt-text-center justify-content-center
style:
margin-left: 0px
margin-right: 0px
margin-top: -10px
position: relative
z-index: 1
visible: =(vars.ScheduleVisible) == true
slots:
default:
- component: f7-row
config:
style:
width: 300px
slots:
default:
- component: f7-col
config:
style:
width: 100px
slots:
default:
- component: f7-row
slots:
default:
- component: f7-col
config:
style:
width: 100px
slots:
default:
- component: Label
config:
style:
font-size: 15px
text-align: center
text-decoration: underline
text-underline-offset: 4px
text: Opening Time
- component: f7-row
slots:
default:
- component: f7-col
config:
style:
width: 40px
slots:
default:
- component: f7-row
config:
style:
height: 30px
text-align: center
slots:
default:
- component: oh-button
config:
action: command
actionCommand: =(dayjs(items[props.OpeningTimeItem].state).add(1, 'hour').format('YYYY-MM-DDTHH:mm:ss.ZZ'))
actionItem: =(props.OpeningTimeItem)
style:
--f7-button-text-color: orange
font-family: u2400
font-size: 100%
width: 40px
text: ▲
- component: f7-row
config:
style:
height: 30px
slots:
default:
- component: Label
config:
style:
font-size: 15px
text-align: center
width: 40px
text: "=(((items[props.OpeningTimeItem].state === 'NULL') || !props.OpeningTimeItem) ? '?': props.timeFormat == '12h' ? dayjs(items[props.OpeningTimeItem].state).format('hh'): dayjs(items[props.OpeningTimeItem].state).format('HH'))"
- component: f7-row
config:
style:
height: 30px
text-align: center
slots:
default:
- component: oh-button
config:
action: command
actionCommand: =(dayjs(items[props.OpeningTimeItem].state).add(-1, 'hour').format('YYYY-MM-DDTHH:mm:ss.ZZ'))
actionItem: =(props.OpeningTimeItem)
style:
--f7-button-text-color: orange
font-family: u2400
font-size: 100%
width: 40px
text: ▼
- component: f7-col
config:
style:
width: 20px
slots:
default:
- component: f7-row
config:
style:
height: 30px
text-align: center
slots:
default:
- component: Label
config:
style:
font-size: 15px
text-align: center
width: 20px
text: ""
- component: f7-row
config:
style:
height: 30px
slots:
default:
- component: Label
config:
style:
font-size: 15px
text-align: center
width: 20px
text: ":"
- component: f7-row
config:
style:
height: 30px
text-align: center
slots:
default:
- component: Label
config:
style:
font-size: 15px
text-align: center
width: 20px
text: ""
- component: f7-col
config:
style:
width: 40px
slots:
default:
- component: f7-row
config:
style:
height: 30px
text-align: center
slots:
default:
- component: oh-button
config:
action: command
actionCommand: =(dayjs(items[props.OpeningTimeItem].state).add(1, 'minute').format('YYYY-MM-DDTHH:mm:ss.ZZ'))
actionItem: =(props.OpeningTimeItem)
style:
--f7-button-text-color: orange
font-family: u2400
font-size: 100%
width: 40px
text: ▲
- component: f7-row
config:
style:
height: 30px
slots:
default:
- component: Label
config:
style:
font-size: 15px
text-align: center
width: 40px
text: "=(((items[props.OpeningTimeItem].state === 'NULL') || !props.OpeningTimeItem) ? '?': dayjs(items[props.OpeningTimeItem].state).format('mm'))"
- component: f7-row
config:
style:
height: 30px
text-align: center
slots:
default:
- component: oh-button
config:
action: command
actionCommand: =(dayjs(items[props.OpeningTimeItem].state).add(-1, 'minute').format('YYYY-MM-DDTHH:mm:ss.ZZ'))
actionItem: =(props.OpeningTimeItem)
style:
--f7-button-text-color: orange
font-family: u2400
font-size: 100%
width: 40px
text: ▼
- component: f7-col
config:
style:
width: 100px
slots:
default:
- component: f7-row
slots:
default:
- component: f7-col
config:
style:
width: 100px
slots:
default:
- component: Label
config:
style:
font-size: 15px
text-align: center
text-decoration: underline
text-underline-offset: 4px
text: Closure Time
- component: f7-row
slots:
default:
- component: f7-col
config:
style:
width: 40px
slots:
default:
- component: f7-row
config:
style:
height: 30px
text-align: center
slots:
default:
- component: oh-button
config:
action: command
actionCommand: =(dayjs(items[props.ClosureTimeItem].state).add(1, 'hour').format('YYYY-MM-DDTHH:mm:ss.ZZ'))
actionItem: =(props.ClosureTimeItem)
style:
--f7-button-text-color: orange
font-family: u2400
font-size: 100%
width: 40px
text: ▲
- component: f7-row
config:
style:
height: 30px
slots:
default:
- component: Label
config:
style:
font-size: 15px
text-align: center
width: 40px
text: "=(((items[props.ClosureTimeItem].state === 'NULL') || !props.ClosureTimeItem) ? '?': props.timeFormat == '12h' ? dayjs(items[props.ClosureTimeItem].state).format('hh'): dayjs(items[props.ClosureTimeItem].state).format('HH'))"
- component: f7-row
config:
style:
height: 30px
text-align: center
slots:
default:
- component: oh-button
config:
action: command
actionCommand: =(dayjs(items[props.ClosureTimeItem].state).add(-1, 'hour').format('YYYY-MM-DDTHH:mm:ss.ZZ'))
actionItem: =(props.ClosureTimeItem)
style:
--f7-button-text-color: orange
font-family: u2400
font-size: 100%
width: 40px
text: ▼
- component: f7-col
config:
style:
width: 20px
slots:
default:
- component: f7-row
config:
style:
height: 30px
text-align: center
slots:
default:
- component: Label
config:
style:
font-size: 15px
text-align: center
width: 20px
text: ""
- component: f7-row
config:
style:
height: 30px
slots:
default:
- component: Label
config:
style:
font-size: 15px
text-align: center
width: 20px
text: ":"
- component: f7-row
config:
style:
height: 30px
text-align: center
slots:
default:
- component: Label
config:
style:
font-size: 15px
text-align: center
width: 20px
text: ""
- component: f7-col
config:
style:
width: 40px
slots:
default:
- component: f7-row
config:
style:
height: 30px
text-align: center
slots:
default:
- component: oh-button
config:
action: command
actionCommand: =(dayjs(items[props.ClosureTimeItem].state).add(1, 'minute').format('YYYY-MM-DDTHH:mm:ss.ZZ'))
actionItem: =(props.ClosureTimeItem)
style:
--f7-button-text-color: orange
font-family: u2400
font-size: 100%
width: 40px
text: ▲
- component: f7-row
config:
style:
height: 30px
slots:
default:
- component: Label
config:
style:
font-size: 15px
text-align: center
width: 40px
text: "=(((items[props.ClosureTimeItem].state === 'NULL') || !props.ClosureTimeItem) ? '?': dayjs(items[props.ClosureTimeItem].state).format('mm'))"
- component: f7-row
config:
style:
height: 30px
text-align: center
slots:
default:
- component: oh-button
config:
action: command
actionCommand: =(dayjs(items[props.ClosureTimeItem].state).add(-1, 'minute').format('YYYY-MM-DDTHH:mm:ss.ZZ'))
actionItem: =(props.ClosureTimeItem)
style:
--f7-button-text-color: orange
font-family: u2400
font-size: 100%
width: 40px
text: ▼
- component: f7-card-content
config:
class: align-items-center alignt-text-center justify-content-center
style:
margin-bottom: -50px
margin-left: 15px
margin-right: 15px
margin-top: -50px
position: relative
z-index: 0
visible: =(vars.ChartVisible) == true
slots:
default:
- component: oh-chart
config:
chartType: day
options:
backgroundColor: transparent
periodVisible: false
slots:
grid:
- component: oh-chart-grid
config:
containLabel: false
series:
- component: oh-time-series
config:
barWidth: 1
color: orange
gridIndex: 0
item: =props.groupItem
type: bar
xAxisIndex: 0
yAxisIndex: 0
xAxis:
- component: oh-time-axis
config:
axisPointer:
show: false
gridIndex: 0
yAxis:
- component: oh-value-axis
config:
gridIndex: 0
min: 0
name: " % closed"
- component: f7-card-footer
config:
style:
background: rgb(245, 218, 137)
border-radius: 0 0 10px 10px
height: auto
slots:
default:
- component: f7-block
config:
style:
bottom: 3px
display: flex
left: 0
position: absolute
slots:
default:
- component: oh-button
config:
action: variable
actionVariable: PresetVisible
actionVariableValue: =! (vars.PresetVisible)
slots:
default:
- component: oh-icon
config:
icon: iconify:mdi:window-shutter-auto
style:
color: "=(vars.PresetVisible ? 'rgb(255, 128, 0)' : 'rgb(106, 106, 106)')"
width: 25px
- component: oh-button
config:
action: variable
actionVariable: ScheduleVisible
actionVariableValue: =! (vars.ScheduleVisible)
slots:
default:
- component: oh-icon
config:
icon: iconify:akar-icons:clock
style:
color: "=(vars.ScheduleVisible ? 'rgb(255, 128, 0)' : 'rgb(106, 106, 106)')"
width: 25px
- component: oh-toggle
config:
color: green
item: =props.EnableSchedule
style:
--f7-toggle-height: 20px
--f7-toggle-inactive-color: red
--f7-toggle-width: 40px
margin-left: 7px
margin-top: -2px
z-index: 98
visible: =(vars.ScheduleVisible) == true
- component: oh-button
config:
action: variable
actionVariable: ChartVisible
actionVariableValue: =! (vars.ChartVisible)
slots:
default:
- component: oh-icon
config:
icon: iconify:ant-design:bar-chart-outlined
style:
color: "=(vars.ChartVisible ? 'rgb(255, 128, 0)' : 'rgb(106, 106, 106)')"
width: 25px
I don’t use the scheduling part of your widget so I removed that part.
Here is a picture showing when the widget is expanded to show the position selector and when the time open/close graph is selected.
Here is the code:
uid: Remote_blind_control_notimer
tags: []
props:
parameters:
- context: Text
description: Title of the card
label: Title
name: rollerTitle
required: false
type: TEXT
- context: item
description: Rollershutter Item
label: Rollershutter Item
name: groupItem
required: true
type: TEXT
- context: item
description: Rollershutter position
label: Rollershutter Position
name: blindposition
required: true
type: TEXT
timestamp: Aug 20, 2023, 9:44:57 AM
component: f7-card
config:
style:
background: '=themeOptions.dark === "dark" ? "rgb(40, 40, 40)" : "rgb(255, 255, 210)"'
border-radius: var(--f7-card-expandable-border-radius)
box-shadow: 5px 5px 15px 1px rgba(0,0,0,0.3)
margin-left: 5px
margin-right: 5px
slots:
default:
- component: f7-card-content
config:
style:
position: relative
z-index: 3
slots:
default:
- component: f7-row
config:
style:
margin-bottom: -10px
margin-left: 0px
margin-right: 0px
slots:
default:
- component: f7-col
config:
style:
margin-left: 0px
margin-right: 0px
width: 60px
slots:
default:
- component: oh-icon
config:
height: 50px
icon: iconify:ic:twotone-roller-shades
style:
color: orange
- component: f7-col
config:
style:
margin-left: 60px
margin-right: 0px
position: absolute
width: 80%
slots:
default:
- component: f7-row
slots:
default:
- component: Label
config:
style:
color: '=themeOptions.dark === "dark" ? "white" : "black"'
font-size: 15px
font-weight: 500
text: =props.rollerTitle
- component: f7-row
config:
style:
align-items: right
display: flex
flex-direction: row
slots:
default:
- component: f7-chip
config:
style:
background: orange
color: black
font-weight: 500
text: '=Math.round(items[props.groupItem].state) == "100" ? "Open" : Math.round(items[props.groupItem].state) == "0" ? "Closed" : Math.round(items[props.blindposition].state) + "% open"'
- component: f7-col
config:
style:
margin-left: 0px
margin-right: 0px
width: 26px
slots:
default:
- component: oh-link
config:
action: command
actionCommand: UP
actionItem: =props.groupItem
iconColor: orange
iconF7: arrow_up_circle
iconSize: 28
style:
background: '=themeOptions.dark === "dark" ? "rgb(40, 40, 40)" : "rgb(240, 240, 240)"'
z-index: 98
- component: oh-link
config:
action: command
actionCommand: STOP
actionItem: =props.groupItem
iconF7: stop_circle
iconSize: 28
style:
background: '=themeOptions.dark === "dark" ? "rgb(40, 40, 40)" : "rgb(240, 240, 240)"'
z-index: 98
- component: oh-link
config:
action: command
actionCommand: DOWN
actionItem: =props.groupItem
iconColor: orange
iconF7: arrow_down_circle
iconSize: 28
style:
background: '=themeOptions.dark === "dark" ? "rgb(40, 40, 40)" : "rgb(240, 240, 240)"'
z-index: 98
- component: f7-card-content
config:
class: align-items-center alignt-text-center justify-content-center
style:
margin-left: 15px
margin-right: 15px
position: relative
z-index: 2
visible: =(vars.PresetVisible) == true
slots:
default:
- component: f7-row
slots:
default:
- component: oh-slider
config:
color: orange
item: =props.blindposition
max: 100
min: 0
step: "1"
style:
background: trasparent
color: black
font-size: 13px
- component: f7-row
config:
style:
margin-top: 15px
slots:
default:
- component: oh-button
config:
action: command
actionCommand: 25
actionItem: =props.blindposition
round: true
style:
background: '=items[props.groupItem].state >= "20" && items[props.groupItem].state <= "30" ? "orange" : "rgb(210, 210, 210)"'
color: black
z-index: 98
text: 25
- component: oh-button
config:
action: command
actionCommand: 40
actionItem: =props.blindposition
round: true
style:
background: '=items[props.groupItem].state >= "35" && items[props.groupItem].state <= "45" ? "orange" : "rgb(210, 210, 210)"'
color: black
z-index: 98
text: 40
- component: oh-button
config:
action: command
actionCommand: 50
actionItem: =props.blindposition
round: true
style:
background: '=items[props.groupItem].state >= "45" && items[props.groupItem].state <= "55" ? "orange" : "rgb(210, 210, 210)"'
color: black
z-index: 98
text: 50
- component: oh-button
config:
action: command
actionCommand: 75
actionItem: =props.blindposition
round: true
style:
background: '=items[props.groupItem].state >= "70" && items[props.groupItem].state <= "80" ? "orange" : "rgb(210, 210, 210)"'
color: black
z-index: 98
text: 75
- component: oh-button
config:
action: command
actionCommand: 90
actionItem: =props.blindposition
round: true
style:
background: '=items[props.groupItem].state >= "85" && items[props.groupItem].state <= "95" ? "orange" : "rgb(210, 210, 210)"'
color: black
z-index: 98
text: 90
- component: f7-card-content
config:
class: align-items-center alignt-text-center justify-content-center
style:
margin-bottom: -50px
margin-left: 15px
margin-right: 15px
margin-top: -50px
position: relative
z-index: 0
visible: =(vars.ChartVisible) == true
slots:
default:
- component: oh-chart
config:
chartType: day
options:
backgroundColor: transparent
periodVisible: false
slots:
grid:
- component: oh-chart-grid
config:
containLabel: false
series:
- component: oh-time-series
config:
barWidth: 1
color: orange
gridIndex: 0
item: =props.groupItem
type: bar
xAxisIndex: 0
yAxisIndex: 0
xAxis:
- component: oh-time-axis
config:
axisPointer:
show: false
gridIndex: 0
yAxis:
- component: oh-value-axis
config:
gridIndex: 0
min: 0
name: " % closed"
- component: f7-card-footer
config:
style:
background: rgb(245, 218, 137)
border-radius: 0 0 10px 10px
height: auto
slots:
default:
- component: f7-block
config:
style:
bottom: 3px
display: flex
left: 0
position: absolute
slots:
default:
- component: oh-button
config:
action: variable
actionVariable: PresetVisible
actionVariableValue: =! (vars.PresetVisible)
slots:
default:
- component: oh-icon
config:
icon: iconify:mdi:window-shutter-auto
style:
color: "=(vars.PresetVisible ? 'rgb(255, 128, 0)' : 'rgb(106, 106, 106)')"
width: 25px
- component: oh-button
config:
action: variable
actionVariable: ChartVisible
actionVariableValue: =! (vars.ChartVisible)
slots:
default:
- component: oh-icon
config:
icon: iconify:ant-design:bar-chart-outlined
style:
color: "=(vars.ChartVisible ? 'rgb(255, 128, 0)' : 'rgb(106, 106, 106)')"
width: 25px
Thanks again. Such a good widget I use it every morning to open and close my 7 binds (zigbee and RF control 240V)
I added an icon line to your widget so the blinds icon is “animated”. IE they show the blind position as an icon.
I replaced this:
- component: oh-icon
config:
height: 50px
icon: iconify:ic:twotone-roller-shades
with this:
- component: oh-icon
config:
height: 50px
icon: =(items[props.blindposition].state > 89)?('blinds-90'):(items[props.blindposition].state > 79)?('blinds-80'):(items[props.blindposition].state > 69)?('blinds-70'):(items[props.blindposition].state > 59)?('blinds-60'):(items[props.blindposition].state > 49)?('blinds-50'):(items[props.blindposition].state > 39)?('blinds-40'):(items[props.blindposition].state > 29)?('blinds-30'):(items[props.blindposition].state > 19)?('blinds-20'):(items[props.blindposition].state > 9)?('oh:blinds-10'):('oh:blinds-0')
It looks like this now:
It is still a good widget…thanks again.
in first draft of the widget i’ve used those icons…but looks a little “out of widget style”, so i preferred to use inconify colored icons and put the % level near
Fair enough. If there were variable other style of icons I would use those.
It is still a good widget though.