Battery Level Status

A dynamic standalone widget that will present the minimum battery level of all your batteries along with each individual battery’s level as a separate row in a list.

Optionally, batteries above a certain level can be hidden so the only ones you see are those that are low. By default all the batteries are shown.

The level the icon and color changes between green (default 60), orange (default 30), and red can be configured through the optional parameters.

Screenshots

Changelog

Version 0.2

  • Removed the outer oh-list card to get better alignment.

Version 0.1

  • initial release

Resources

uid: rlk_battery_status
tags: []
props:
  parameters:
    - context: item
      filterCriteria:
        - name: type
          value: Group
      description: Group:Number:MIN Item that aggregates all the battery levels
      label: Minimum Battery Level Item
      name: minLevel
      required: true
      type: TEXT
    - description: Maximum percentage to show in the widget
      label: Max Percent
      name: max
      required: false
      type: INTEGER
      defaultValue: 100
      min: 0
      max: 100
    - description: The percentage above which green is used
      label: Green Level
      name: green
      type: INTEGER
      defaultValue: 60
      min: 0
      max: 100
    - description: The percentage above which orange is used
      label: Orange Level
      name: orange
      type: INTEGER
      defaultValue: 30
      min: 0
      max: 100
  parameterGroups: []
timestamp: Oct 28, 2021, 10:52:35 AM
component: oh-list-card
config:
  title: '="Minimum Battery Level: " + ((items[props.minLevel].displayState === undefined) ? items[props.minLevel].state : items[props.minLevel].displayState)'
slots:
  default:
    - component: oh-repeater
      config:
        fragment: true
        for: item
        sourceType: itemsInGroup
        groupItem: =props.minLevel
        filter: Number.parseFloat(items[loop.item.name].state) <= props.max
      slots:
        default:
          - component: oh-list-item
            config:
              icon: '=(Number.parseFloat(loop.item.state) > props.green) ? "f7:battery_100" : (Number.parseFloat(loop.item.state) > props.orange) ? "f7:battery_25" : "f7:battery_0"'
              iconColor: '=(Number.parseFloat(loop.item.state) > props.green) ? "green" : (Number.parseFloat(loop.item.state) > props.orange) ? "orange" : "red"'
              title: =loop.item.label
              item: =loop.item.name
              badge: "=(loop.item.displayState === undefined) ? loop.item.state : loop.item.displayState"
              badgeColor: '=(Number.parseFloat(loop.item.state) > props.green) ? "green" : (Number.parseFloat(loop.item.state) > props.orange) ? "orange" : "red"'

9 Likes

Nice Widget. Thanks for sharing. I would remove the wrapping oh-list part from your template which would result in a optimized left alignment.

Is there a convinient way to order items by value? I am not aware of such a feature. Time to start working on a metadata based group ordering like suggested in Sort group item by string by bjoernbrings · Pull Request #2123 · openhab/openhab-core · GitHub.

1 Like

I’ll give that a try.

Not that I’m aware of. It appears that the repreater widget does manage to sort them based on alphabetical order of the labels. But I couldn’t find a way to sort them any other way.

If you include fetchMetadata: widgetOrder in the repeater’s config they will be ordered based on this metadata (“Default Widget Order Index”). I’ve been made aware that there’s a bug in that comparator function so indexes are compared as strings, so it goes like this:
-1 < 0 < 1 < 10 < 11 < 12 < … < 2 < 20 < …
You won’t run a problem until you use indexes < 10 and => 10 at the time.

AFAIR there’s nothing available to sort by state.

Hi
I get this error trying to install
I’m using Metric and region Sweden, 24h clock

I just Copy/Paste the YAML to a widget, and its working :slight_smile:
Thought I let you know…

EDIT: I just noticed that it is on more than this one, so not an error with this widget
should move this to the proper place, sorry

2021-10-30 10:14:08.759 [ERROR] [munity.CommunityUIWidgetAddonHandler] - Unable to parse YAML: Cannot deserialize value of type `java.util.Date` from String "Oct 28, 2021, 10:52:35 AM": not a valid representation (error: Failed to parse Date value 'Oct 28, 2021, 10:52:35 AM': Unparseable date: "Oct 28, 2021, 10:52:35 AM")

 at [Source: (StringReader); line: 37, column: 12] (through reference chain: org.openhab.core.ui.components.RootUIComponent["timestamp"])

2021-10-30 10:14:08.764 [ERROR] [munity.CommunityUIWidgetAddonHandler] - Widget from marketplace is invalid: Unable to parse YAML

@ysc Thanks for the hint. But a little bit too much effort for my use case. I thought more or less about a dynamically ordering based on the item state. I am already working on a solution. Give me some days to create a PR.

@nisseDILLIGAF I have the similar problem in my environment. I already opened an issue to track it:

1 Like

@rlkoshak thx for this widget! For the badge text, you use badge: "=(loop.item.displayState === undefined) ? loop.item.state : loop.item.displayState", but as far as I know displayState is not supported in a loop? Or am I doing something wrong?
In the header text, displayState is working fine.

I couldn’t say except that it works for me. However, there is no displayState if you’ve not populated the Item’s State Description metadata with a pattern.

And in that case that line of code will choose the state instead of the displayState. So even if the displayState were not supported, which wouldn’t make much sense, it should still work and show you the Item’s state. If it’s not working something else must be wrong.

A State Description metadata is indeed needed to use displayState, but displayState seems not usable in a loop. I already noticed this before, but since I saw it in your code, I though there was another way.

In a normal component (eg oh-list-card), the items show me a state and displayState
In a oh-repeater and with the use of a loop, I get name, label and state

For me, this different behavior is not very clear.
In this case I can just add a % in the widget (loop.item.state + ' %' ), but it would be nice if we can use displayState

Apologies for a simple question. I have created the widget. How do I add the items to the widget itself on a page?

i’ve used displayState in a repeater many times and never had a problem. I’m not sure why you are seeing anything differently.

Click on the black widget editing icon above the widget and select “Configure Widget”. Set the properties called for. One will be a Group with all the Battery Items as members.

Thanks Rich. Appreciated.

I am getting NULL for minimum battery level. Is there something I need to configure to fix this part?
Screen Shot 2021-11-20 at 1.12.01 pm

Did you define the Group with the MIN aggregation function? If so has any of its members been updated since adding the aggregation function? Are all members of the Group a Number type Item.

That that was it Rich. I didn’t even know you could, thanks for the pointer!

One other question, to round the number values to 1 decimal place. I have added a Metadata stateDescription and added %.1f to the Pattern field. But it does not seem to be working? Is there something simple I am missing?

value: " "
config:
  pattern: "%.1f"
  step: "1"
  min: "1"
  max: "100"

It might be related the behavior that @wars is seeing. I don’t have an explanation nor a suggestion yet.

Has this something to do with this? Formatting date/time of a label-item (within a list-card-widget in a page) with YAML - #32 by ysc

I knew we had a discussion before :grin:

It could be based on the binding the readings come from. All my battery levels I care about come from MQTT so I wouldn’t have noticed this issue here.

Mine are also coming from MQTT, all my items have a state description ("%s %%"), but none of them are showing in the widget… I actually have this issue with all my widgets where a repeater is included.

Then that thread doesn’t apply. The issue in that thread you linked to is when the binding supplies a state description which sometimes overrides the State Description metadata. The MQTT binding doesn’t do this.

In my case the values from the GPS binding are displaying rounded to a whole number where as the values coming from the iCloud binding are coming through with 15 decimal places, a little more accurate than needed for battery levels.

I might run the raw values through a rule every 10mins and display a proxy item.

Thanks for your help!