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