Problem
CommonCLI.cpp already supports get/set adc.multiplier as a generic text
command (see handleCommand(), ~line 749-761 and ~895-901), and several board
classes (e.g. PromicroBoard, HeltecV4Board) already implement
setAdcMultiplier() / getAdcMultiplier() overrides.
However, this only actually works over the raw-text serial CLI used by
Repeater / Room Server firmware, where meshcore-cli sends the literal
string "set adc.multiplier <value>" down the wire and the firmware parses
it directly.
Companion firmware (BLE / USB, used by the mobile app and by meshcore-cli
in companion mode) uses a structured binary protocol with a fixed opcode per
setting instead of a free-text CLI passthrough. For example:
GET_TUNING_PARAMS (0x2b) returns a fixed 9-byte struct containing only
rx_delay (4 bytes) and airtime_factor (4 bytes) — no room for an ADC
multiplier.
- There is no generic "send raw CLI string over BLE" opcode that would let a
companion client reach the existing CommonCLI.cpp text handler.
As a result, meshcli get/set adc.multiplier against a Companion device
falls through to the case _: default in meshcore_cli.py, which treats it
as a user-defined "custom var" (GET_CUSTOM_VARS / SET_CUSTOM_VAR,
0x28/0x29) — a completely different mechanism intended for
set_custom_var(key, value). This produces Unknown var adc.multiplier
even though the firmware itself fully supports the setting.
Impact
DIY / community boards with hand-soldered voltage dividers (e.g. fakeTec /
ProMicro, and presumably others without a factory-calibrated divider) have
no way to runtime-calibrate battery voltage reading while running
Companion firmware. The only workaround today is a full firmware rebuild
with a hardcoded #define ADC_MULTIPLIER, reflash via DFU, and repeat for
every recalibration.
Suggested fix (open to alternatives)
Extend the existing tuning-params opcode pair (GET_TUNING_PARAMS /
SET_TUNING_PARAMS, 0x2b / 0x15) to include a 4-byte float adc_multiplier
field alongside rx_delay and airtime_factor, wire it through to
board->getAdcMultiplier() / setAdcMultiplier() in the companion firmware
command handler, and bump RESP_CODE_TUNING_PARAMS payload size accordingly
(with a length/version check for backward compatibility with older
companion apps).
Alternatively, a new dedicated opcode pair could be added instead of
extending an existing struct, if that's preferred for protocol
compatibility reasons.
Companion library/CLI side changes would follow once the firmware protocol
is agreed (tracked separately in meshcore_py / meshcore-cli).
Reproduction
- Flash any Companion firmware to a board with
setAdcMultiplier()
implemented (e.g. ProMicro_companion_radio_ble).
- Connect via
meshcore-cli over BLE.
- Run
get adc.multiplier → Unknown var adc.multiplier.
- Compare with a Repeater build of the same board:
get adc.multiplier
works correctly there.
Happy to help test on ProMicro/fakeTec hardware, and to help implement once
the approach is agreed.
Problem
CommonCLI.cppalready supportsget/set adc.multiplieras a generic textcommand (see
handleCommand(), ~line 749-761 and ~895-901), and several boardclasses (e.g.
PromicroBoard,HeltecV4Board) already implementsetAdcMultiplier()/getAdcMultiplier()overrides.However, this only actually works over the raw-text serial CLI used by
Repeater / Room Server firmware, where
meshcore-clisends the literalstring
"set adc.multiplier <value>"down the wire and the firmware parsesit directly.
Companion firmware (BLE / USB, used by the mobile app and by
meshcore-cliin companion mode) uses a structured binary protocol with a fixed opcode per
setting instead of a free-text CLI passthrough. For example:
GET_TUNING_PARAMS(0x2b) returns a fixed 9-byte struct containing onlyrx_delay(4 bytes) andairtime_factor(4 bytes) — no room for an ADCmultiplier.
companion client reach the existing
CommonCLI.cpptext handler.As a result,
meshcli get/set adc.multiplieragainst a Companion devicefalls through to the
case _:default inmeshcore_cli.py, which treats itas a user-defined "custom var" (
GET_CUSTOM_VARS/SET_CUSTOM_VAR,0x28/0x29) — a completely different mechanism intended for
set_custom_var(key, value). This producesUnknown var adc.multipliereven though the firmware itself fully supports the setting.
Impact
DIY / community boards with hand-soldered voltage dividers (e.g. fakeTec /
ProMicro, and presumably others without a factory-calibrated divider) have
no way to runtime-calibrate battery voltage reading while running
Companion firmware. The only workaround today is a full firmware rebuild
with a hardcoded
#define ADC_MULTIPLIER, reflash via DFU, and repeat forevery recalibration.
Suggested fix (open to alternatives)
Extend the existing tuning-params opcode pair (
GET_TUNING_PARAMS/SET_TUNING_PARAMS, 0x2b / 0x15) to include a 4-byte floatadc_multiplierfield alongside
rx_delayandairtime_factor, wire it through toboard->getAdcMultiplier()/setAdcMultiplier()in the companion firmwarecommand handler, and bump
RESP_CODE_TUNING_PARAMSpayload size accordingly(with a length/version check for backward compatibility with older
companion apps).
Alternatively, a new dedicated opcode pair could be added instead of
extending an existing struct, if that's preferred for protocol
compatibility reasons.
Companion library/CLI side changes would follow once the firmware protocol
is agreed (tracked separately in meshcore_py / meshcore-cli).
Reproduction
setAdcMultiplier()implemented (e.g.
ProMicro_companion_radio_ble).meshcore-cliover BLE.get adc.multiplier→Unknown var adc.multiplier.get adc.multiplierworks correctly there.
Happy to help test on ProMicro/fakeTec hardware, and to help implement once
the approach is agreed.