Hello,
i have made my first custom widget and want to share it with you. I hope you like it.
Maybe you can help improving it, there are some points under construction ![]()
Also tips e.g. regarding best practice are welcome, because the openhab, yaml, javascript world is new to me.
Design goal:
- Widget optimized to be used on mobile phone using opanhab app
- Most important stuff should be available in default state
- Access to all options shall be available.
- Self configuring from model (I loose overview of my items w/o model)
screnshot default state / after pressing lightbulb / after pressing button “LAMPEN”:
Functionality default state:
- lightbulb indicates dimmer value and opens further settings.
- S-Button: Select Scene
- Colorpicker
- On/Off Switch
Configurable:
- card header background image
- card header title
- card header “All lights switch item”. If no item is configured switch is not shown.
Everything else is generated from the model information.
The model must follow the scheme:
- The Hue Room must be an equipment under a location (category: light or colorlight; semantic class: lightbulb)
- The single bulbs in the room must be child equipments of the room equipment (category: light or colorlight; semantic class: lightbulb)
- The items must have default hue names in german (can be adjusted in the widget code).
- Switch and dimmer items have to be setup manually with “_Betrieb” and _“Helligkeit” for each single rgb lightbulb (not for rooms).
- Switch items have to be setup manually with “_Betrieb” for each single rgb lightbulb (not for rooms).
uid: cardLightProps
tags:
- light
- productive
props:
parameters:
- description: Title of the card
label: Card title
name: cardTitle
required: false
type: TEXT
- description: Background image for card header (e.g. url("http://vps-openhab3:8080/static/devices/colorlight.jpg"))
label: Background Image
name: bgImage
required: false
type: TEXT
- description: NOT USED
label: Tags
name: filterTags
required: false
type: TEXT
advanced: true
- context: item
description: Switch item for all ligths. Keep empty to not display all lights switch.
label: All lights switch item
name: allLights
required: false
type: TEXT
advanced: true
- context: item
description: Parent equipment. Keep empty in base card used internally for "lampen" pop-up.
label: Parent equipment
name: parEquip
required: false
type: TEXT
advanced: true
parameterGroups: []
timestamp: Dec 13, 2021, 11:30:27 AM
component: f7-card
slots:
default:
- component: f7-card-header
config:
valign: center
noBorder: true
style:
background-image: =props.bgImage
background-size: cover
background-position: center
height: 42px
--f7-card-header-text-color: rgba(255,255,255)
slots:
default:
- component: Label
config:
text: =props.cardTitle
style:
padding-right: 0px
- component: oh-toggle
config:
item: =props.allLights
visible: "=props.allLights ? true : false"
style:
margin-left: 20px
margin-right: 0px
padding-rigth: 0px
- component: f7-card-content
config:
style:
padding: 0px
margin: 0px
slots:
default:
- component: f7-list
config:
style:
padding-bottom: 1px
margin: 0px
slots:
default:
- component: oh-repeater
config:
fragment: true
for: repItem
sourceType: itemsWithTags
itemTags: Lightbulb
fetchMetadata: semantics
filter: 'props.parEquip ? ((loop.repItem.category == "light" || loop.repItem.category == "colorlight") && loop.repItem.metadata.semantics.config.isPartOf == props.parEquip) : ((loop.repItem.category == "light" || loop.repItem.category == "colorlight") && loop.repItem.metadata.semantics.config.hasLocation)'
slots:
default:
- component: f7-card
slots:
default:
- component: f7-card-header
config:
valign: bottom
noBorder: true
style:
height: 48px
padding-left: 8px
padding-right: 8px
padding-top: 0px
padding-bottom: 4px
slots:
default:
- component: f7-block
config:
class:
- display-flex
- justify-content-left
- align-items-center
style:
padding: 0px
height: 40px
margin: 0px
slots:
default:
- component: oh-icon
config:
icon: "=(items[loop.repItem.name + '_Helligkeit'].state == 0) ? 'slider-0' : ((items[loop.repItem.name + '_Helligkeit'].state <= 10) ? 'slider-10' : ((items[loop.repItem.name + '_Helligkeit'].state <= 20) ? 'slider-20' : ((items[loop.repItem.name + '_Helligkeit'].state <= 30) ? 'slider-30' : ((items[loop.repItem.name + '_Helligkeit'].state <= 40) ? 'slider-40' : ((items[loop.repItem.name + '_Helligkeit'].state <= 50) ? 'slider-50' : ((items[loop.repItem.name + '_Helligkeit'].state <= 60) ? 'slider-60' : ((items[loop.repItem.name + '_Helligkeit'].state <= 70) ? 'slider-70' : ((items[loop.repItem.name + '_Helligkeit'].state <= 80) ? 'slider-80' : ((items[loop.repItem.name + '_Helligkeit'].state <= 90) ? 'slider-90' : ('slider'))))))))))"
width: 32px
action: variable
actionVariable: =visBright + loop.repItem.name
actionVariableValue: "=(vars[visBright + loop.repItem.name] == undefined) ? true : !vars[visBright + loop.repItem.name]"
style:
margin-right: 8px
padding: 0px
- component: Label
config:
text: "=(loop.repItem.metadata.semantics.config.hasLocation ? loop.repItem.metadata.semantics.config.hasLocation : loop.repItem.name.split(loop.repItem.metadata.semantics.config.isPartOf)[1])"
- component: f7-block
config:
class:
- display-flex
- justify-content-right
- align-items-center
style:
padding: 0px
height: 40px
slots:
default:
- component: oh-button
config:
visible: "=((vars[visBright + loop.repItem.name] == undefined) ? true : !vars[visBright + loop.repItem.name]) && (loop.repItem.metadata.semantics.config.hasLocation?true:false)"
text: S
small: false
raised: true
outline: true
item: =loop.repItem.name + "_Szene"
actionItem: =loop.repItem.name + "_Szene"
action: options
style:
height: 32px
width: 32px
margin-right: '=(loop.repItem.category == "colorlight") ? "20px" : "52px"'
- component: oh-colorpicker
config:
openIn: auto
item: =(loop.repItem.category == "colorlight") ? loop.repItem.name + "_Farbe":""
modules:
- hs-spectrum
visible: =(loop.repItem.category == "colorlight") ? true:false
- component: oh-toggle
config:
item: =loop.repItem.name + "_Betrieb"
style:
margin-left: 20px
margin-right: 0px
padding-rigth: 0px
- component: f7-card-content
config:
visible: "=(((vars[visBright + loop.repItem.name] == undefined) ? false : vars[visBright + loop.repItem.name]) || (loop.repItem.metadata.semantics.config.hasLocation?false:true))"
style:
height: auto
slots:
default:
- component: f7-row
slots:
default:
- component: f7-col
config:
style:
padding-left: 0px
padding-right: 0px
class:
- display-flex
- justify-content-space-between
slots:
default:
- component: Label
config:
text: ="Helligkeit:"
min: 0
style:
padding-right: 0px
font-size: 12px
- component: Label
config:
text: =items[loop.repItem.name + "_Helligkeit"].displayState
style:
padding-right: 0px
font-size: 12px
- component: f7-row
slots:
default:
- component: f7-col
config:
class:
- display-flex
- justify-content-center
slots:
default:
- component: oh-slider
config:
item: =loop.repItem.name + "_Helligkeit"
max: 100
step: 1
scale: true
scaleSteps: 5
scaleSubSteps: 5
releaseOnly: false
class:
- margin-bottom
style:
margin-left: 0px
margin-right: 0px
margin-top: 0px
- component: f7-row
config:
visible: =(loop.repItem.metadata.semantics.config.hasLocation?true:false)
style:
height: auto
margin-top: 10px
slots:
default:
- component: f7-col
config:
class:
- display-flex
- justify-content-right
style:
height: auto
margin: 0px
padding: 0px
slots:
default:
- component: oh-button
config:
text: "='Szene: ' + items[loop.repItem.name + '_Szene'].displayState"
item: =loop.repItem.name + "_Szene"
actionItem: =loop.repItem.name + "_Szene"
action: options
small: true
outline: true
raised: true
style:
height: auto
width: inherit
margin-right: 0px
- component: oh-button
config:
text: Lampen
small: true
raised: true
outline: true
action: popup
actionModal: widget:cardLightProps
actionModalConfig:
bgImage: =props.bgImage
cardTitle: ="Licht - " + loop.repItem.metadata.semantics.config.hasLocation.toString()
parEquip: =loop.repItem.name
style:
height: auto
width: 150px
margin-left: 20px
Open Points (Tips/Hints are appreciated.):
- Colorpicker for RGB is very laggy or not responding.
- I need a colorpicker supporting color temperature for the ambient bulbs. It should match the rgb colorpicker design.
- Probably gaps outside of my use case (other hue bulbs, room configurations, other vendor lights, etc)
best regards
Peter
