List and card widgets for displaying battery voltages and alternatively binary battery low-level switch items. Useful for maintenance overview pages.
Screenshots
Changelog
Version 1.0
- initial release (voltage, lowlevel, voltage-repeater, lowlevel-repeater)
Usage
Generally straightforward.
- The voltage list item expects a Number item formatted as a voltage, so a typed item
- The low-level list item expects a Switch type, where OFF is “okay” and ON is “battery low”
You will need to adjust some formatting lines if you want the labels to look nice, specifically in the repeater widgets.
For example, I use:
label: =( ('' + loop.member.name) .replace(/^HMRT/, '') .replace(/_Battery$/,
'') .replace(/([a-z])([A-Z])/g, '$1 $2')
.replace(/([A-Za-z])([0-9])/g, '$1 $2') )
to reformat item names called eg. HMRTMasterBedroom1_Battery into Master Bedroom 1 because my item labels for the battery items are not very descriptive (they just say “Battery state”). If you have descriptive labels, maybe replace this (and similar) with a simple loop.member.label instead.
Known issues
- The expressions that evaluate the opacity of the “cells” in the battery indicators is a bit messy, and I think there are still some peculiarities in there.
Resources
Version 1.0
YAML: Voltage listitem
uid: battery-voltage-listitem
tags:
- battery
props:
parameters:
- label: Voltage item
name: item
required: true
type: TEXT
context: item
- label: Left label text (optional)
name: label
required: false
type: TEXT
- label: Minimum voltage (default 2.5)
name: minV
required: false
type: TEXT
- label: Maximum voltage (default 3.0)
name: maxV
required: false
type: TEXT
- label: Green threshold (default 2.7)
name: greenV
required: false
type: TEXT
- label: Yellow threshold (default midpoint)
name: yellowV
required: false
type: TEXT
timestamp: Dec 27, 2025, 9:35:41 PM
component: f7-list-item
config:
title: =props.label || (items[props.item] && items[props.item].label) || props.item
style:
align-items: center
padding-top: 6px
padding-bottom: 6px
--f7-list-item-title-white-space: nowrap
--f7-list-item-title-overflow: hidden
--f7-list-item-title-text-overflow: ellipsis
slots:
after:
- component: f7-block
config:
style:
margin: 0
padding: 0
width: 100%
height: 30px
position: relative
overflow: visible
background: transparent
background-color: transparent
slots:
default:
- component: f7-block
config:
style:
margin: 0
padding: 0
width: 100px
height: 30px
position: relative
overflow: hidden
border: 2px solid var(--f7-text-color)
border-radius: 7px
box-sizing: border-box
background: transparent
background-color: transparent
slots:
default:
- component: f7-block
config:
style:
margin: 0
padding: 3px
width: 100%
height: 100%
display: flex
gap: 3px
box-sizing: border-box
align-items: stretch
justify-content: space-between
background: transparent
background-color: transparent
slots:
default:
- component: f7-block
config:
style:
margin: 0
padding: 0
flex: 1
height: 100%
min-width: 0
border-radius: 4px
background: =( ( (Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) && (Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) <= (Number(props.minV)||2.5)) &&
'var(--f7-color-red)' ) || (
(Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) && (Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) < (Number(props.greenV)||2.7)) &&
'var(--f7-color-yellow)' ) || (
(Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) && 'var(--f7-color-green)' ) ||
'var(--f7-color-gray)' )
opacity: =( ( (Number((''+(items[props.item] && (items[props.item].displayState
||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) &&
(Math.round(Math.max(0,Math.min(1,(Number((''+(items[props.item]
&& (items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])-(Number(props.minV)||2.5))/((Number(props.maxV)||3.0)-(Number(props.minV)||2.5))))*5)
>= 1) && 0.9 ) || 0.12 )
- component: f7-block
config:
style:
margin: 0
padding: 0
flex: 1
height: 100%
min-width: 0
border-radius: 4px
background: =( ( (Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) && (Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) <= (Number(props.minV)||2.5)) &&
'var(--f7-color-red)' ) || (
(Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) && (Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) < (Number(props.greenV)||2.7)) &&
'var(--f7-color-yellow)' ) || (
(Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) && 'var(--f7-color-green)' ) ||
'var(--f7-color-gray)' )
opacity: =( ( (Number((''+(items[props.item] && (items[props.item].displayState
||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) &&
(Math.round(Math.max(0,Math.min(1,(Number((''+(items[props.item]
&& (items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])-(Number(props.minV)||2.5))/((Number(props.maxV)||3.0)-(Number(props.minV)||2.5))))*5)
>= 2) && 0.9 ) || 0.12 )
- component: f7-block
config:
style:
margin: 0
padding: 0
flex: 1
height: 100%
min-width: 0
border-radius: 4px
background: =( ( (Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) && (Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) <= (Number(props.minV)||2.5)) &&
'var(--f7-color-red)' ) || (
(Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) && (Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) < (Number(props.greenV)||2.7)) &&
'var(--f7-color-yellow)' ) || (
(Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) && 'var(--f7-color-green)' ) ||
'var(--f7-color-gray)' )
opacity: =( ( (Number((''+(items[props.item] && (items[props.item].displayState
||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) &&
(Math.round(Math.max(0,Math.min(1,(Number((''+(items[props.item]
&& (items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])-(Number(props.minV)||2.5))/((Number(props.maxV)||3.0)-(Number(props.minV)||2.5))))*5)
>= 3) && 0.9 ) || 0.12 )
- component: f7-block
config:
style:
margin: 0
padding: 0
flex: 1
height: 100%
min-width: 0
border-radius: 4px
background: =( ( (Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) && (Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) <= (Number(props.minV)||2.5)) &&
'var(--f7-color-red)' ) || (
(Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) && (Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) < (Number(props.greenV)||2.7)) &&
'var(--f7-color-yellow)' ) || (
(Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) && 'var(--f7-color-green)' ) ||
'var(--f7-color-gray)' )
opacity: =( ( (Number((''+(items[props.item] && (items[props.item].displayState
||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) &&
(Math.round(Math.max(0,Math.min(1,(Number((''+(items[props.item]
&& (items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])-(Number(props.minV)||2.5))/((Number(props.maxV)||3.0)-(Number(props.minV)||2.5))))*5)
>= 4) && 0.9 ) || 0.12 )
- component: f7-block
config:
style:
margin: 0
padding: 0
flex: 1
height: 100%
min-width: 0
border-radius: 4px
background: =( ( (Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) && (Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) <= (Number(props.minV)||2.5)) &&
'var(--f7-color-red)' ) || (
(Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) && (Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) < (Number(props.greenV)||2.7)) &&
'var(--f7-color-yellow)' ) || (
(Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) && 'var(--f7-color-green)' ) ||
'var(--f7-color-gray)' )
opacity: =( ( (Number((''+(items[props.item] && (items[props.item].displayState
||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) &&
(Math.round(Math.max(0,Math.min(1,(Number((''+(items[props.item]
&& (items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])-(Number(props.minV)||2.5))/((Number(props.maxV)||3.0)-(Number(props.minV)||2.5))))*5)
>= 5) && 0.9 ) || 0.12 )
- component: f7-block
config:
style:
position: absolute
left: 0
right: 0
top: 0
bottom: 0
display: flex
align-items: center
justify-content: center
margin: 0
padding: 0
font-weight: 700
font-size: 13px
color: var(--f7-text-color)
pointer-events: none
z-index: 2
slots:
default:
- component: Label
config:
text: =(''+((items[props.item] && (items[props.item].displayState ||
items[props.item].state)) || ''))
- component: f7-block
config:
style:
position: absolute
left: 98px
top: 8px
width: 6px
height: 14px
border-radius: 4px
border: 2px solid var(--f7-text-color)
box-sizing: border-box
background: white
background-color: white
margin: 0
padding: 0
YAML: Low Level listitem
uid: battery-voltage-listitem
tags:
- battery
props:
parameters:
- label: Voltage item
name: item
required: true
type: TEXT
context: item
- label: Left label text (optional)
name: label
required: false
type: TEXT
- label: Minimum voltage (default 2.5)
name: minV
required: false
type: TEXT
- label: Maximum voltage (default 3.0)
name: maxV
required: false
type: TEXT
- label: Green threshold (default 2.7)
name: greenV
required: false
type: TEXT
- label: Yellow threshold (default midpoint)
name: yellowV
required: false
type: TEXT
timestamp: Dec 27, 2025, 9:35:41 PM
component: f7-list-item
config:
title: =props.label || (items[props.item] && items[props.item].label) || props.item
style:
align-items: center
padding-top: 6px
padding-bottom: 6px
--f7-list-item-title-white-space: nowrap
--f7-list-item-title-overflow: hidden
--f7-list-item-title-text-overflow: ellipsis
slots:
after:
- component: f7-block
config:
style:
margin: 0
padding: 0
width: 100%
height: 30px
position: relative
overflow: visible
background: transparent
background-color: transparent
slots:
default:
- component: f7-block
config:
style:
margin: 0
padding: 0
width: 100px
height: 30px
position: relative
overflow: hidden
border: 2px solid var(--f7-text-color)
border-radius: 7px
box-sizing: border-box
background: transparent
background-color: transparent
slots:
default:
- component: f7-block
config:
style:
margin: 0
padding: 3px
width: 100%
height: 100%
display: flex
gap: 3px
box-sizing: border-box
align-items: stretch
justify-content: space-between
background: transparent
background-color: transparent
slots:
default:
- component: f7-block
config:
style:
margin: 0
padding: 0
flex: 1
height: 100%
min-width: 0
border-radius: 4px
background: =( ( (Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) && (Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) <= (Number(props.minV)||2.5)) &&
'var(--f7-color-red)' ) || (
(Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) && (Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) < (Number(props.greenV)||2.7)) &&
'var(--f7-color-yellow)' ) || (
(Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) && 'var(--f7-color-green)' ) ||
'var(--f7-color-gray)' )
opacity: =( ( (Number((''+(items[props.item] && (items[props.item].displayState
||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) &&
(Math.round(Math.max(0,Math.min(1,(Number((''+(items[props.item]
&& (items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])-(Number(props.minV)||2.5))/((Number(props.maxV)||3.0)-(Number(props.minV)||2.5))))*5)
>= 1) && 0.9 ) || 0.12 )
- component: f7-block
config:
style:
margin: 0
padding: 0
flex: 1
height: 100%
min-width: 0
border-radius: 4px
background: =( ( (Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) && (Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) <= (Number(props.minV)||2.5)) &&
'var(--f7-color-red)' ) || (
(Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) && (Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) < (Number(props.greenV)||2.7)) &&
'var(--f7-color-yellow)' ) || (
(Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) && 'var(--f7-color-green)' ) ||
'var(--f7-color-gray)' )
opacity: =( ( (Number((''+(items[props.item] && (items[props.item].displayState
||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) &&
(Math.round(Math.max(0,Math.min(1,(Number((''+(items[props.item]
&& (items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])-(Number(props.minV)||2.5))/((Number(props.maxV)||3.0)-(Number(props.minV)||2.5))))*5)
>= 2) && 0.9 ) || 0.12 )
- component: f7-block
config:
style:
margin: 0
padding: 0
flex: 1
height: 100%
min-width: 0
border-radius: 4px
background: =( ( (Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) && (Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) <= (Number(props.minV)||2.5)) &&
'var(--f7-color-red)' ) || (
(Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) && (Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) < (Number(props.greenV)||2.7)) &&
'var(--f7-color-yellow)' ) || (
(Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) && 'var(--f7-color-green)' ) ||
'var(--f7-color-gray)' )
opacity: =( ( (Number((''+(items[props.item] && (items[props.item].displayState
||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) &&
(Math.round(Math.max(0,Math.min(1,(Number((''+(items[props.item]
&& (items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])-(Number(props.minV)||2.5))/((Number(props.maxV)||3.0)-(Number(props.minV)||2.5))))*5)
>= 3) && 0.9 ) || 0.12 )
- component: f7-block
config:
style:
margin: 0
padding: 0
flex: 1
height: 100%
min-width: 0
border-radius: 4px
background: =( ( (Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) && (Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) <= (Number(props.minV)||2.5)) &&
'var(--f7-color-red)' ) || (
(Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) && (Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) < (Number(props.greenV)||2.7)) &&
'var(--f7-color-yellow)' ) || (
(Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) && 'var(--f7-color-green)' ) ||
'var(--f7-color-gray)' )
opacity: =( ( (Number((''+(items[props.item] && (items[props.item].displayState
||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) &&
(Math.round(Math.max(0,Math.min(1,(Number((''+(items[props.item]
&& (items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])-(Number(props.minV)||2.5))/((Number(props.maxV)||3.0)-(Number(props.minV)||2.5))))*5)
>= 4) && 0.9 ) || 0.12 )
- component: f7-block
config:
style:
margin: 0
padding: 0
flex: 1
height: 100%
min-width: 0
border-radius: 4px
background: =( ( (Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) && (Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) <= (Number(props.minV)||2.5)) &&
'var(--f7-color-red)' ) || (
(Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) && (Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) < (Number(props.greenV)||2.7)) &&
'var(--f7-color-yellow)' ) || (
(Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) && 'var(--f7-color-green)' ) ||
'var(--f7-color-gray)' )
opacity: =( ( (Number((''+(items[props.item] && (items[props.item].displayState
||
items[props.item].state))).replace(',','.').split('
')[0]) === Number((''+(items[props.item] &&
(items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])) &&
(Math.round(Math.max(0,Math.min(1,(Number((''+(items[props.item]
&& (items[props.item].displayState ||
items[props.item].state))).replace(',','.').split('
')[0])-(Number(props.minV)||2.5))/((Number(props.maxV)||3.0)-(Number(props.minV)||2.5))))*5)
>= 5) && 0.9 ) || 0.12 )
- component: f7-block
config:
style:
position: absolute
left: 0
right: 0
top: 0
bottom: 0
display: flex
align-items: center
justify-content: center
margin: 0
padding: 0
font-weight: 700
font-size: 13px
color: var(--f7-text-color)
pointer-events: none
z-index: 2
slots:
default:
- component: Label
config:
text: =(''+((items[props.item] && (items[props.item].displayState ||
items[props.item].state)) || ''))
- component: f7-block
config:
style:
position: absolute
left: 98px
top: 8px
width: 6px
height: 14px
border-radius: 4px
border: 2px solid var(--f7-text-color)
box-sizing: border-box
background: white
background-color: white
margin: 0
padding: 0
YAML: Voltage repeater
uid: battery-voltage-group-repeater
tags:
- battery
props:
parameters:
- context: item
label: Group item name (required)
name: groupItem
required: true
type: TEXT
- context: Title
label: Card Title text
name: cardTitle
required: false
type: TEXT
- label: Minimum voltage (default 2.5)
name: minV
required: false
type: TEXT
- label: Maximum voltage (default 3.0)
name: maxV
required: false
type: TEXT
- label: Green threshold (default 2.7)
name: greenV
required: false
type: TEXT
- label: Yellow threshold (default midpoint)
name: yellowV
required: false
type: TEXT
timestamp: Dec 28, 2025, 10:18:42 AM
component: oh-list-card
config:
title: =props.cardTitle
slots:
default:
- component: oh-repeater
config:
for: member
sourceType: itemsInGroup
groupItem: =props.groupItem
slots:
default:
- component: widget:battery-voltage-listitem
config:
item: =loop.member.name
label: =( ('' + loop.member.name) .replace(/^HMRT/, '') .replace(/_Battery$/,
'') .replace(/([a-z])([A-Z])/g, '$1 $2')
.replace(/([A-Za-z])([0-9])/g, '$1 $2') )
minV: =props.minV
maxV: =props.maxV
greenV: =props.greenV
yellowV: =props.yellowV
YAML: Low Level repeater
uid: battery-lowlevel-group-repeater
tags:
- battery
props:
parameters:
- context: item
label: Group item name (required)
name: groupItem
required: true
type: TEXT
- label: Card Title
name: cardTitle
required: false
type: TEXT
parameterGroups: []
timestamp: Dec 27, 2025, 9:52:00 PM
component: oh-list-card
config:
title: =props.cardTitle
slots:
default:
- component: oh-repeater
config:
for: member
sourceType: itemsInGroup
groupItem: =props.groupItem
filter: "!loop.member.name.includes('HMRT')"
slots:
default:
- component: widget:battery-low-switch-listitem
config:
item: =loop.member.name
label: "=( 'Window: ' +
loop.member.name.replace(/^TFK/,'').replace(/_battery$/,'').rep\
lace(/_(ONLY|HIGH|LOW)$/,' - $1').replace(/_/g,'
').replace(/([a-z])([A-Z])/g,'$1 $2').replace(/(\\D)(\\d+)/g,'$1
$2').replace(/ - ONLY$/,' - Only').replace(/ - HIGH$/,' -
High').replace(/ - LOW$/,' - Low') )"

