Skip to content

feat: battery-aware reconnect backoff to prevent battery drain#405

Open
ramparte wants to merge 4 commits into
QuantumEntangledAndy:masterfrom
ramparte:battery-aware-backoff
Open

feat: battery-aware reconnect backoff to prevent battery drain#405
ramparte wants to merge 4 commits into
QuantumEntangledAndy:masterfrom
ramparte:battery-aware-backoff

Conversation

@ramparte
Copy link
Copy Markdown

Problem

Battery-powered Reolink cameras (Argus series, E1 Outdoor, Go Plus, etc.) suffer severe battery drain when neolink is running. The root cause: when a battery camera is asleep, neolink retries the connection every 5 seconds (the current fixed backoff cap), each time waking the camera via the P2P relay. At ~240 wake-ups per hour per camera, this drains batteries in days instead of weeks.

The 15-second stream-info polling loop (get_stream_info) compounds the problem — it queries cameras that never change their stream capabilities, keeping the connection warm even when idle_disconnect is set.

Solution

A new battery_camera = true config option per camera that activates three battery-saving behaviors:

1. Exponential backoff with 1-hour cap

When battery_camera = true, the reconnect delay grows exponentially: 50ms → 100ms → 200ms → ... → 1 hour cap, instead of the fixed 5s cap. This matches the reality that sleeping battery cameras may not wake for long periods — there is no point hammering the relay every 5 seconds.

2. Stream-info poll disabled

The 15-second get_stream_info loop is gated behind !battery_camera. Stream capabilities are queried once at startup and cached. For battery cameras, these capabilities never change at runtime, so periodic polling is pure waste.

3. Auto-enable idle_disconnect

If battery_camera = true and idle_disconnect is not explicitly set, it defaults to true so the connection drops when no RTSP client is viewing.

Config

[[cameras]]
name = "front_door"
battery_camera = true
username = "admin"
password = "****"
uid = "XXXXXXXXXX"

For non-battery cameras, nothing changes. The default is battery_camera = false, preserving the existing 5-second reconnect behavior.

Changes

  • src/config.rs: Add battery_camera field (default false)
  • src/common/neocam.rs: Propagate battery_camera to NeoInstance, auto-enable idle_disconnect
  • src/common/camthread.rs: Exponential backoff (1hr cap) when battery_camera is true
  • src/rtsp/mod.rs: Gate stream-info poll behind !battery_camera, query once at startup instead

85 lines added, 6 removed across 4 files.

Testing

Tested with 6 battery/solar Reolink cameras (Argus 3 Pro, Go Plus with cellular, solar-powered variants). Neolink starts cleanly, RTSP bridge works, and cameras are no longer hammered with reconnect attempts while sleeping.

CI fixes (bonus)

Also included:

  • Fixed Windows CI by downloading GStreamer MSIs directly (choco gstreamer package is unreliable — gstreamer.freedesktop.org now blocks automated downloads with anti-bot challenges, but the MSI URLs still work)
  • Dropped deprecated macos-12 runner from CI matrix (stuck in queue permanently)

Addresses #204, #241, #334.

Sam Schillace added 4 commits April 17, 2026 13:37
Battery cameras (Reolink Argus, E1 Outdoor, etc.) suffer severe battery
drain when neolink retries connections every 5 seconds indefinitely.
Each retry wakes the camera via the relay, draining batteries at ~240
wake-ups per hour per camera.

Changes:
- Add `battery_camera` config option per camera (`battery_camera = true`)
- True exponential backoff for battery cameras: 50ms → doubling → 1hr cap
  (vs the fixed 5s cap that causes the drain)
- Disable 15-second stream-info poll for battery cameras; query once at
  startup since stream capabilities don't change at runtime
- Auto-enable `idle_disconnect` for battery cameras so the connection
  drops when no RTSP client is viewing

Example config:
  [[cameras]]
  name = "front_door"
  battery_camera = true
  username = "admin"
  password = "****"
  uid = "XXXXXXXXXX"

Fixes QuantumEntangledAndy#204, addresses discussions QuantumEntangledAndy#241 and QuantumEntangledAndy#334.
The pinned versions (gstreamer 1.24.2, protoc 24.2.0, openssl 1.1.1.2100)
are no longer available on Chocolatey, causing all Windows CI builds to
fail at the 'Install Windows deps' step. Remove version pins to use
latest available packages.
Bypasses the unreliable choco gstreamer package by downloading MSIs
directly from gstreamer.freedesktop.org. Also avoids the macOS-12
runner that's stuck in queue (deprecated).
- Download GStreamer MSIs directly from gstreamer.freedesktop.org
  instead of using unreliable choco gstreamer/gstreamer-devel packages
- Drop macOS-12 from CI matrix (deprecated, stuck in queue)
- Set PKG_CONFIG_PATH for Windows builds
- Remove macos-12 artifact references from release job
@surfzoid
Copy link
Copy Markdown

Hi, good job.
Since a long time @QuantumEntangledAndy isn't come. Somewhere we re launch activity around sdcard functionality #396 , pherhaps yu should use the "new" activ fork https://github.com/lorek123/neolink

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants