Add companion device battery percentage to status bar #126

Closed
opened 2026-10-05 01:58:36 +02:00 by adam · 11 comments
Owner

The local companion device reports battery voltage via get_bat() but it's only visible in the debug endpoint. This adds a battery indicator to the status bar.

Follows the existing task patterns (same structure as telemetry collect). Polls get_bat() every 60s, caches on radio_manager, included in the health payload via WebSocket broadcasts.

Voltage-to-percentage uses the Meshtastic default OCV table from src/power.h. 0 mV is treated as USB powered / no battery.

Working on a PR for this.

The local companion device reports battery voltage via get_bat() but it's only visible in the debug endpoint. This adds a battery indicator to the status bar. Follows the existing task patterns (same structure as telemetry collect). Polls get_bat() every 60s, caches on radio_manager, included in the health payload via WebSocket broadcasts. Voltage-to-percentage uses the Meshtastic default OCV table from src/power.h. 0 mV is treated as USB powered / no battery. Working on a PR for this. <!-- github-sync-id:4241053088 -->
adam closed this issue 2026-10-05 01:58:36 +02:00
Author
Owner

Hmm, isn't your companion device always plugged in? What's the value of a battery percentage?

Hmm, isn't your companion device always plugged in? What's the value of a battery percentage? <!-- github-comment-id:4225991242 -->
Author
Owner

Not always plugged in. Solar-powered companions, portable setups with RemoteTerm on a phone, or a battery-powered node sitting somewhere without USB. You want to know when it needs a charge or a battery swap.

It seems that MeshCore doesn't expose a charging state, so we can only report the current battery level from voltage, not whether it's actively charging :<

Not always plugged in. Solar-powered companions, portable setups with RemoteTerm on a phone, or a battery-powered node sitting somewhere without USB. You want to know when it needs a charge or a battery swap. It seems that MeshCore doesn't expose a charging state, so we can only report the current battery level from voltage, not whether it's actively charging :< <!-- github-comment-id:4226056954 -->
Author
Owner

For reference, the OCV table used for voltage-to-percentage conversion comes from Meshtastic's firmware:

https://github.com/meshtastic/firmware/blob/master/src/power.h#L18

4190mV = 100%
4050mV =  90%
3990mV =  80%
3890mV =  70%
3800mV =  60%
3720mV =  50%
3630mV =  40%
3530mV =  30%
3420mV =  20%
3300mV =  10%
3100mV =   0%
For reference, the OCV table used for voltage-to-percentage conversion comes from Meshtastic's firmware: https://github.com/meshtastic/firmware/blob/master/src/power.h#L18 ``` 4190mV = 100% 4050mV = 90% 3990mV = 80% 3890mV = 70% 3800mV = 60% 3720mV = 50% 3630mV = 40% 3530mV = 30% 3420mV = 20% 3300mV = 10% 3100mV = 0% ``` <!-- github-comment-id:4226067966 -->
Author
Owner

Yeah, I was gonna say, I can see my USB-powered radio reporting "battery_mv": 3911. What I would be open to is exposing it via an optional "Frontend Tunable" from settings to show up in the status bar. Let me cherry-pick some in-progress work for you that will be helpful (this data is already fetched and stored).

Yeah, I was gonna say, I can see my USB-powered radio reporting `"battery_mv": 3911`. What I *would* be open to is exposing it via an optional "Frontend Tunable" from settings to show up in the status bar. Let me cherry-pick some in-progress work for you that will be helpful (this data is already fetched and stored). <!-- github-comment-id:4226073594 -->
Author
Owner

Makes total sense, didn't consider that. Happy to adapt this to a frontend tunable. Will wait for your cherry-pick.

Worth noting for later: Meshtastic handles this at the firmware level with dedicated charging detection (PMU status registers, GPIO charge pins, VBUS detect). Until MeshCore exposes something similar, we can only go by raw voltage, which doesn't tell us if a battery is actually present.

Makes total sense, didn't consider that. Happy to adapt this to a frontend tunable. Will wait for your cherry-pick. Worth noting for later: Meshtastic handles this at the firmware level with dedicated charging detection (PMU status registers, GPIO charge pins, VBUS detect). Until MeshCore exposes something similar, we can only go by raw voltage, which doesn't tell us if a battery is actually present. <!-- github-comment-id:4226132364 -->
Author
Owner

Okay bringing in 3bd756ee4e actually got uglier than I really wanted but it's tolerable. This exposes the battery voltage and other vital stats for the frontend via the radio status websocket. So, I'd be open to you just having a toggle for show battery percentage or voltage, BUT, if you were feeling fancy, something that could be fun would be a token-based customizable status bar. Something like {status_dot} {radio_status_string} {radio_name} {radio_pub_key} would replicate what we have now, but you could do {status_dot} {radio_battery_voltage}mV noise@{radio_noise_floor}dBm or something like that. Feel free to keep your implementation simpler if you'd prefer, and fair warning for something big like a status bar customization I'll probably have lots of notes/tweaks, but could be cool.

Okay bringing in 3bd756ee4e2ece7f21a0714f0008fe4f0daa9c27 actually got uglier than I really wanted but it's tolerable. This exposes the battery voltage and other vital stats for the frontend via the radio status websocket. So, I'd be open to you just having a toggle for show battery percentage or voltage, BUT, if you were feeling fancy, something that could be fun would be a token-based customizable status bar. Something like `{status_dot} {radio_status_string} {radio_name} {radio_pub_key}` would replicate what we have now, but you could do `{status_dot} {radio_battery_voltage}mV noise@{radio_noise_floor}dBm` or something like that. Feel free to keep your implementation simpler if you'd prefer, and fair warning for something big like a status bar customization I'll probably have lots of notes/tweaks, but could be cool. <!-- github-comment-id:4226335002 -->
Author
Owner

You're giving me new ideas, now I can't stop thinking anymore 😂

You're giving me new ideas, now I can't stop thinking anymore 😂 <!-- github-comment-id:4226412926 -->
Author
Owner

Let's make the customizable status bar a separate issue, I'll tackle that next week if you want. For now I'll do the simple battery toggle.

Let's make the customizable status bar a separate issue, I'll tackle that next week if you want. For now I'll do the simple battery toggle. <!-- github-comment-id:4226437853 -->
Author
Owner

Sounds good to me! yeah I love lots of ideas; I just like having issues beforehand because I feel so bad when someone spends a bunch of time building only for my answer to be "no" or "not like that". But yeah consider the voltage mv/percent (I like the idea of them being separate but combinable e.g. between the two checkboxes you could have "3829mV", "97% (2829mV)", or "97%", maybe with a little battery icon or something; idk.

Sounds good to me! yeah I love lots of ideas; I just like having issues beforehand because I feel so bad when someone spends a bunch of time building only for my answer to be "no" or "not like that". But yeah consider the voltage mv/percent (I like the idea of them being separate but combinable e.g. between the two checkboxes you could have "3829mV", "97% (2829mV)", or "97%", maybe with a little battery icon or something; idk. <!-- github-comment-id:4226446024 -->
Author
Owner

If you don't mind, ill use a little help from an LLM for the typescript part, I am more of a backend guy 😅

EDIT: of course I test and check everything myself

If you don't mind, ill use a little help from an LLM for the typescript part, I am more of a backend guy 😅 EDIT: of course I test and check everything myself <!-- github-comment-id:4226466088 -->
Author
Owner

The repository is built for LLM friendliness -- all I ask is that you lay eyes on the code and use the LLM as a force multiplier not just for code production, but code testing and review (and the review of its own tests; sick to death of 27 new tests for a one line change 😜) .

The repository is built for LLM friendliness -- all I ask is that you lay eyes on the code and use the LLM as a force multiplier not just for code production, but code testing and review (and the review of its own tests; sick to death of 27 new tests for a one line change 😜) . <!-- github-comment-id:4226898737 -->
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: adam/Remote-Terminal-for-MeshCore#126