Most of the large examples the with code like Yannick’s keypad widget and Rainer’s weather widget are being posted to Add-ons → UI.
I’ve really not spend much time on my UI yet beyond just trying to figure things out, so I don’t have much that is pretty. Most of my time has been spent with setting the default widgets on Items to make the automatically populated tabs look and work as I want them to.
But I do have a few functional widgets that were created with a lot of help from Yannick and Rainer.
This one is a simple widget that I set as the default stand alone widget for the Garage door Equipment. It combines the status of the door’s reed sensor and acts as an action widget so I can trigger the opener.
I was able to configure this completely through the form without editing the YAML.
value: " "
config:
actionCommand: ON
item: Large_Garagedoor_Sensor
actionItem: Large_Garagedoor_Opener
icon: oh:garagedoor
action: command
label: '=(items.Large_Garagedoor_Sensor.state == "OPEN") ? "open" : "closed"'
title: Large Garage Door Opener
iconUseState: true
This is an accordion widget showing the online status of my home automation devices. It was a pretty bruit force affair but the big trick was getting it to do more than just two levels. You can see here that there’s three levels. I built this before learning about properties and even now I don’t understand loops (am I saying that right?) which might make it a little less bruit force. But for now it’s copy/paste/edit the Item names/repeat type widget. Not really reusable but I’ll post it here for an example.
uid: servicesStatus
tags:
- nested
- accordion
- list
timestamp: Jan 7, 2021, 11:07:06 AM
component: oh-list-card
config:
accordionList: true
title: All Services Status
footer: Online status of home automation related services
slots:
default:
- component: oh-list-item
config:
title: All Services
subtitle: When OFF one or more services are offline
badge: '=(items.ServiceStatuses.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.ServiceStatuses.state === "ON") ? "green" : "red"'
slots:
accordion:
- component: oh-list
config:
accordionList: true
class:
- margin-left
slots:
default:
- component: oh-list-item
config:
title: argus
subtitle: Home automation server
badge: '=(items.vArgus_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vArgus_Status.state === "ON") ? "green" : "red"'
slots:
accordion:
- component: oh-list
config:
accordionList: true
class:
- margin-left
slots:
default:
- component: oh-list-item
config:
title: Mosquitto
badge: '=(items.vMosquitto_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vMosquitto_Status.state === "ON") ? "green" : "red"'
- component: oh-list-item
config:
title: Portainer Agent
badge: '=(items.vArgus_Portainer_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vArgus_Portainer_Status.state === "ON") ? "green" : "red"'
- component: oh-list-item
config:
title: cerberos
subtitle: Garage sensors and controller
badge: '=(items.vCerberos_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vCerberos_Status.state === "ON") ? "green" : "red"'
- component: oh-list-item
config:
title: fafnir
subtitle: NAS Server
badge: '=(items.vFafnir_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vFafnir_Status.state === "ON") ? "green" : "red"'
slots:
accordion:
- component: oh-list
config:
accordionList: true
class:
- margin-left
slots:
default:
- component: oh-list-item
config:
title: OMV Service
badge: '=(items.vOMV_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vOMV_Status.state === "ON") ? "green" : "red"'
- component: oh-list-item
config:
title: OMV NFS
badge: '=(items.vOMV_NFS_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vOMV_NFS_Status.state === "ON") ? "green" : "red"'
- component: oh-list-item
config:
title: OMV Timemachine
badge: '=(items.vOMV_AFP_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vOMV_AFP_Status.state === "ON") ? "green" : "red"'
- component: oh-list-item
config:
title: huginn
subtitle: Virtual Desktop
badge: '=(items.vHuginn_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vHuginn_Status.state === "ON") ? "green" : "red"'
slots:
accordion:
- component: oh-list
config:
accordionList: true
class:
- margin-left
slots:
default:
- component: oh-list-item
config:
title: Portainer Server
badge: '=(items.vHuginn_Portainer_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vHuginn_Portainer_Status.state === "ON") ? "green" : "red"'
- component: oh-list-item
config:
title: hydra
subtitle: Doors and windows sensors
badge: '=(items.vHydra_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vHydra_Status.state === "ON") ? "green" : "red"'
- component: oh-list-item
config:
title: manticore
subtitle: NUT and BT bridge
badge: '=(items.vManticore_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vManticore_Status.state === "ON") ? "green" : "red"'
- component: oh-list-item
config:
title: medusa
subtitle: Media services
badge: '=(items.vMedusa_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vMedusa_Status.state === "ON") ? "green" : "red"'
slots:
accordion:
- component: oh-list
config:
accordionList: true
class:
- margin-left
slots:
default:
- component: oh-list-item
config:
title: Calibre
badge: '=(items.vCalibre_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vCalibre_Status.state === "ON") ? "green" : "red"'
- component: oh-list-item
config:
title: Elasticsearch
badge: '=(items.vElasticsearch_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vElasticsearch_Status.state === "ON") ? "green" : "red"'
- component: oh-list-item
config:
title: GitLab
badge: '=(items.vGit_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vGit_Status.state === "ON") ? "green" : "red"'
- component: oh-list-item
config:
title: Guacamole
badge: '=(items.vGuacamole_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vGuacamole_Status.state === "ON") ? "green" : "red"'
- component: oh-list-item
config:
title: NextCloud
badge: '=(items.vNextcloud_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vNextcloud_Status.state === "ON") ? "green" : "red"'
- component: oh-list-item
config:
title: Plex Media Server
badge: '=(items.vPlex_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vPlex_Status.state === "ON") ? "green" : "red"'
- component: oh-list-item
config:
title: Portainer
badge: '=(items.vMedusa_Portainer_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vMedusa_Portainer_Status.state === "ON") ? "green" : "red"'
- component: oh-list-item
config:
title: PostgreSQL
badge: '=(items.vPostgreSQL_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vPostgreSQL_Status.state === "ON") ? "green" : "red"'
- component: oh-list-item
config:
title: Redis
badge: '=(items.vRedis_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vRedis_Status.state === "ON") ? "green" : "red"'
- component: oh-list-item
config:
title: norns
subtitle: Dad's openHAB server
badge: '=(items.vNorns_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vNorns_Status.state === "ON") ? "green" : "red"'
slots:
accordion:
- component: oh-list
config:
accordionList: true
class:
- margin-left
slots:
default:
- component: oh-list-item
config:
title: Dad's openHAB
badge: '=(items.vDads_openHAB_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vDads_openHAB_Status.state === "ON") ? "green" : "red"'
- component: oh-list-item
config:
title: Devices
subtitle: Individual Devices
badge: '=(items.DeviceStatuses.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.DeviceStatuses.state === "ON") ? "green" : "red"'
slots:
accordion:
- component: oh-list
config:
accordionList: true
class:
- margin-left
slots:
default:
- component: oh-list-item
config:
title: GalaxyNote TinyCam Service
badge: '=(items.vGalaxyNote_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vGalaxyNote_Status.state === "ON") ? "green" : "red"'
- component: oh-list-item
config:
title: HestiaPi
badge: '=(items.vHestiaPi_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vHestiaPi_Status.state === "ON") ? "green" : "red"'
- component: oh-list-item
config:
title: MBR Sensors
badge: '=(items.vMBR_Sensors_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vMBR_Sensors_Status.state === "ON") ? "green" : "red"'
- component: oh-list-item
config:
title: MBR Shelly 1
badge: '=(items.vMBR_Shelly_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vMBR_Shelly_Status.state === "ON") ? "green" : "red"'
- component: oh-list-item
config:
title: Nate's NR Sensors
badge: '=(items.vNateBR_Sensors_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vNateBR_Sensors_Status.state === "ON") ? "green" : "red"'
- component: oh-list-item
config:
title: Orbi AP
badge: '=(items.vOrbi_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vOrbi_Status.state === "ON") ? "green" : "red"'
- component: oh-list-item
config:
title: Orbi Satellite AP
badge: '=(items.vOrbi_Satellite_Status.state === "ON") ? "ONLINE" : "OFFLINE"'
badgeColor: '=(items.vOrbi_Satellite_Status.state === "ON") ? "green" : "red"'
I’ve a similar widget for my battery statuses but it’s only two levels deep so was easier to create.
In the future I think I’ll experiment with visibility instead of using a roll up status like this. So the widget would only show the summary status when everything is online. When something is offline I’ll show just those services. But even then, for a status like this I probably don’t even need a widget. I can get the same information from the automatiaclly generated cards. In fact, I’ve set most of the default list widgets to show the little badge instead of text. I’ll probably start playing with visibility too to hide those that are online.
Finally, as an example custom widget I want to use as an example in the Getting Started Tutorial I build a Chromecast widget.
It still needs some work with the spacing and whatnot but it’s close enough to use as the example. I might even just let messing with the spacing and padding and such become an exercise for the student. ;-D
This one I made as a custom widget and set up properties to give it a prefix for the Item names. Then I was careful to use a consistent naming scheme after that. I add that custom widget and set the properties on the Chromecast Equipment Item and then I can add from the model and have it pop right up.
uid: chromecast_widget
tags: []
props:
parameters:
- description: How all the Items associated with this chromecast starts
label: Item prefix
name: prefix
required: false
type: TEXT
- description: Title for the widget
label: Static Title
name: title
required: false
parameterGroups: []
timestamp: Jan 12, 2021, 4:03:10 PM
component: f7-card
config:
title: =props.title
slots:
default:
- component: f7-row
slots:
default:
- component: oh-image
config:
item: =props.prefix+"_Image"
style:
width: 100%
height: auto
- component: f7-row
config:
class:
- justify-content-left
slots:
default:
- component: f7-col
slots:
default:
- component: Label
config:
class:
- text-align-center
text: =items[props.prefix+"_MediaArtist"].state
- component: f7-col
slots:
default:
- component: Label
config:
class:
- text-align-center
text: =items[props.prefix+"_MediaTitle"].state
- component: f7-row
config:
class:
- padding-top
- padding-bottom
slots:
default:
- component: f7-col
slots:
default:
- component: oh-player-controls
config:
item: =props.prefix+"_MediaControl"
- component: f7-col
slots:
default:
- component: oh-slider
config:
item: =props.prefix+"_Volume"
min: 0
max: 100
step: 10
unit: "%"
label: true
- component: oh-button
config:
text: Stop
iconF7: stop
fill: true
color: red
action: command
actionCommand: ON
actionFeedback: Media Stopped
actionItem: =props.prefix+"_Stop"
class:
- margin-top
- component: f7-row
config:
class:
- justify-content-center
slots:
default:
- component: Label
config:
text: =items[props.prefix+"_App"].state
So, as you can see, I’ve been focusing more on the how to do things than on making something pretty. Eventually I’ll get to working on that but I need to get the rest of the Getting Started Tutorial published first.