Skip to content

Battery destroying web sockets can be fixed: let the user configure per-server WebSocket ping frequency #6208

@Rudd-O

Description

@Rudd-O

Home Assistant Android app version(s): Latest stable APK published thru Github as of today.

Android version(s): GOS 20251227

Device model(s): Pixel 9 Pro

Home Assistant version: 2025-12-1

Description of problem, include YAML if issue is related to notifications:

The code here

// play ping pong to ensure we have a connection and server changes are handled.

ensures that jobs execute every 30 seconds, if there are any.

There is always at least one job: send ping to mother ship.

This wrecks the battery (and nickels-and-dimes roaming data) for users of the app who have a persistent connection opened to the server (mainly the Minimal version of the app). The device effectively cannot sleep when it has to send a ping every 30 seconds.

My former primary Android device, a Pixel 6 Pro which sits unused now and whose only app now is HA Companion Minimal, shows over 59% battery consumption just for that app. And that's on Wi-Fi! If I were to still be using this device through 5G + VPN, it would be much more (it was!).

I understand there might be reasons why shitty middleboxes would want to wreck established TCP sessions unless one of both sides is nagging the web socket constantly. But a 30 second interval between pings is, frankly, ludicrous:

 user  ~  SIGINT  cat /proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established 
432000
# this means the default NAT / conntrack timeout on Linux is *5 days*.

I think the fix here can take one of two forms:

  1. Raise this to a reasonable value like 15 minutes.
  2. Allow this to be configured client-side, under server settings, right next to the radio button that allows the user to select persistent connection (id est, web socket).
  3. (Best) some combination of both.
  4. Hasten the merging of NTFY (here and here) so websocket doesn't need to change but can remain an option for AC-powered devices like wall mounted displays. Although consider this: if reducing pings and wake states can get those devices to save e.g. 20 W every hour, and there are a million such devices in the world, that's a solid 20 megawatts saved every hour. That's 20 Koenigsegg Regeras running for an hour.

Either way, the fix should schedule the ping in a separate thread or coroutine, to prevent waking up the device every 30 seconds when no ping is supposed to occur.

indicates this is where the ping is actually triggered. Most optimally, if there are no jobs, nothing should happen at all, so the Android scheduler lets the app sleep comfily and the device stays low-power.

I will leave this decision in your capable hands. Just please do not wreck our batteries. There is no good reason to ask the Android OS to schedule execution of the HA app, and have the HA app send a packet, every thirty seconds. I just got done losing a phone due to it discharging rapidly... 50% of which was HA Companion Minimal every day.

It would be wise to explain to users of this setting I'm requesting -- directly on the app, with a link to documentation -- that raising the ping interval can carry consequences for HA users of frontend proxies such as NginX, where https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_read_timeout should probably be raised or NginX will think that the server connection (HA's side of the Web socket) has gone AWOL and shut it down. There is even a trick for NginX to autoraise this value when websocket:

 map $http_upgrade $connection_upgrade {
     default upgrade;
     '' close;
 }
 map $http_upgrade $proxy_read_timeout {
     default 86400;
     '' 65;
 }
 server {
     proxy_read_timeout $proxy_read_timeout;
     ....
 }

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions