Skip to content

Comments

Add battery chemistry and power state monitoring for repeaters#135

Draft
rsp2k wants to merge 6 commits intozjs81:mainfrom
rsp2k:feature/repeater-battery-chemistry
Draft

Add battery chemistry and power state monitoring for repeaters#135
rsp2k wants to merge 6 commits intozjs81:mainfrom
rsp2k:feature/repeater-battery-chemistry

Conversation

@rsp2k
Copy link
Contributor

@rsp2k rsp2k commented Feb 7, 2026

Summary

  • Add per-repeater battery chemistry setting for accurate percentage estimates
  • Support firmware-reported chemistry detection (companion: byte 11, repeater: byte 60)
  • Add "no battery" option for wall-powered devices
  • Add power state monitoring with USB/Solar/Charging detection and input voltage display
  • Protocol bytes: 60=chemistry, 61=power_state flags, 62-63=input_mv

Power State Display

  • USB icon (blue) when USB connected
  • Solar icon (orange) when solar connected
  • Charging icon (green) when charging
  • Input voltage shown when external power detected

Test plan

  • Verify firmware chemistry detection with lock icon
  • Verify user-configurable dropdown for devices without firmware support
  • Verify battery percentage recalculates on chemistry change
  • Verify Power Source row displays icons correctly (tested on simulated firmware)
  • Verify backward compatibility (row hidden on older firmware)

Addresses #116

rsp2k added 6 commits February 7, 2026 03:36
- Add per-repeater battery chemistry setting (NMC, LiFePO4, LiPo)
- Create shared battery_utils.dart for voltage-to-percentage calculation
- Support optional firmware-reported chemistry (protocol extension at byte 60)
- Show lock icon when chemistry is firmware-reported, dropdown when user-configurable
- Add l10n string for "Battery Type" label

Addresses zjs81#116
- Detect optional chemistry byte at offset 11 in BATT_AND_STORAGE response
- Prefer firmware-reported chemistry over user setting
- Use shared battery_utils.dart for percentage calculation
- Log chemistry type when detected

Extends battery chemistry feature to companion radio in addition to repeaters.
- Rename NMC to LiPo as standard for dev boards
- Add 'none' option for external power (wall-powered devices)
- Add lead acid support (12V solar/off-grid setups)
- Protocol: 0x00=none, 0x01=lipo, 0x02=lifepo4, 0x03=leadacid
- Add migration for old stored values (nmc/liion -> lipo)
- Make return type nullable for 'none' chemistry
- Hide battery type row when chemistry is 'none' (redundant with N/A)
- Fix text overflow with Flexible + ellipsis
- Shorten label to "No Battery" for cleaner display
- Add Battery Settings dialog showing current voltage/percentage
- User chemistry selection now overrides firmware default
- Show "Device default: X" hint only for meaningful firmware values
- Fix battery percent calculation to use user setting as primary
- Shorten label from "Battery Chemistry" to "Type"
Parse and display power source information from protocol extension bytes:
- USB connection status (blue icon)
- Solar connection status (orange icon)
- Charging indicator (green icon)
- Input voltage display

Protocol bytes: frame[61]=power_state flags, frame[62-63]=input_mv (LE uint16)
Backward compatible: row hidden when firmware doesn't send extension bytes.
@rsp2k rsp2k changed the title Add configurable battery chemistry for repeaters Add battery chemistry and power state monitoring for repeaters Feb 7, 2026
@446564
Copy link
Collaborator

446564 commented Feb 15, 2026

I love the idea but this recreates some existing functionality that should be pulled out into a helper and reused to remain consistent.

String _batteryChemistryForDevice() {
final deviceId = _device?.remoteId.toString();
if (deviceId == null || _appSettingsService == null) return 'nmc';
return _appSettingsService!.batteryChemistryForDevice(deviceId);
}
int _estimateBatteryPercent(int millivolts, String chemistry) {
final range = _batteryVoltageRange(chemistry);
final minMv = range.$1;
final maxMv = range.$2;
if (millivolts <= minMv) return 0;
if (millivolts >= maxMv) return 100;
return (((millivolts - minMv) * 100) / (maxMv - minMv)).round();
}
(int, int) _batteryVoltageRange(String chemistry) {
switch (chemistry) {
case 'lifepo4':
return (2600, 3650);
case 'lipo':
return (3000, 4200);
case 'nmc':
default:
return (3000, 4200);
}
}
List<Message> getMessages(Contact contact) {

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