Hello community! I’m trying to build a universal Rollershutter widget for every rollershutter model.
This is the first release, so there could be some bugs or options to be fine tuned, so feel free to tell me what are issues you will find.
This widget looks into “Model” scheme, find some defined tags (described below) and automatically show/hide widget options.
This widget is the first of the package of widgets that i would like to distribute. My idea is to develope a set of universal widgets suitable for everyone and usable for different brand devices.
Version 2.0 need some more settings, like creating 3 more items to make scheduler working.
Follow these steps to enable scheduler:
- Create from the UI “Items” → “textual definition”:
Group gRollershuttersBathroom "Rollershutters Bathroom"
Switch AutomationRollershutterBathroom "Automation Rollershutter Bathroom" <switch> (gRollershuttersBathroom) [Control,Level]
DateTime ClosureRollershutterBathroomWeekly "Closure Rollershutter Bathroom Weekly" <time> (gRollershuttersBathroom) [Point,Timestamp] {stateDescription=" "[pattern= "%1$tH:%1$tM", readOnly= "true"]}
DateTime OpeningRollershutterBathroomWeekly "Opening Rollershutter Bathroom Weekly" <time> (gRollershuttersBathroom) [Point,Timestamp] {stateDescription=" "[pattern= "%1$tH:%1$tM", readOnly= "true"]}
- Then go to Developer tools –>API Explorer–>Items–>PUT (updates the state of an item)–>TRY IT OUT
Insert the name of the item:
- ClosureRollershutterBathroomWeekly
as “valid state” put 00:00
same fo the other item:
- OpeningRollershutterBathroomWeekly
Now create the rule, setting it properly with your Rollershutter item:
For automatic opening:
configuration: {}
triggers:
- id: "1"
configuration:
itemName: OpeningRollershutterBathroomWeekly
type: timer.DateTimeTrigger
conditions:
- inputs: {}
id: "3"
configuration:
offset: 0
type: ephemeris.WeekdayCondition
- inputs: {}
id: "4"
configuration:
itemName: AutomationRollershutterBathroom
state: ON
operator: =
type: core.ItemStateCondition
- inputs: {}
id: "5"
configuration:
itemName: TapparellaBagno_RollerShutter (change this with your rollershutter item name)
state: "0"
operator: "!="
type: core.ItemStateCondition
actions:
- inputs: {}
id: "2"
configuration:
itemName: TapparellaBagno_RollerShutter (change this with your rollershutter item name)
command: UP
type: core.ItemCommandAction
For automatic closure:
configuration: {}
triggers:
- id: "1"
configuration:
itemName: ClosureRollershutterBathroomWeekly
type: timer.DateTimeTrigger
conditions:
- inputs: {}
id: "3"
configuration:
offset: 0
type: ephemeris.WeekdayCondition
- inputs: {}
id: "4"
configuration:
itemName: AutomationRollershutterBathroom
state: ON
operator: =
type: core.ItemStateCondition
- inputs: {}
id: "5"
configuration:
itemName: TapparellaBagno_RollerShutter (change this with your rollershutter item name)
state: "100"
operator: "!="
type: core.ItemStateCondition
actions:
- inputs: {}
id: "2"
configuration:
itemName: TapparellaBagno_RollerShutter (change this with your rollershutter item name)
command: DOWN
type: core.ItemCommandAction
Then repeat above steps for each of your rollershutters.
Screenshots
Version 2
- Enhanced version of the Universal rollershutter Widget
Changelog
- Added the slider to control rollershutter better
- Moved preset buttons to the “Control” block
- Added the scheduler setting (thanks to Timepicker widget) with on/off switch to enable/disable scheduler
- Chart visible only when button is pressed
- Changed layout of control buttons to vertical style.
- General recolor (Thanks to @Fabrizio_Valtorta)
Version 0.1
- initial release
Changelog
- changed the YAML to be suitable for single rollershutter item
- fixed missing translation in english
Resources
uid: Universal Rollershutter Card
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: 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: Nov 7, 2022, 8:19:09 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: '=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.groupItem
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.groupItem
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.groupItem
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.groupItem
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.groupItem
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.groupItem
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
A very big thank to @Fabrizio_Valtorta and @Jeevs for help and feedbacks from all test done!