Put each condition before its statement. Split long sentences. Use one term for each concept. Replace the description of possible checklist changes with a statement of the present behavior.
5.7 KiB
River 2 measurements
River 2 models with serial prefixes R601 and R603 use packet version 2.
Encryption is separate from the packet version. The tested River 2 uses Type 7
encryption, not Type 1. River 3 uses a separate decoder.
bmspy/ecoflow_river2.py contains the binary layouts, numeric decoder, and
measurement rules. bmspy/ecoflow_bt.py handles Bluetooth transport and
resets the decoder's source priorities before each connection.
bmspy/ecoflow_snapshot.py defines the shared EcoFlow snapshot.
Normal snapshot
A snapshot contains the latest received measurements. Missing measurements stay absent. These field names are also used by River 3, but each model has its own rules for interpreting the device reports.
| Field | Meaning |
|---|---|
ef_input_power_watts |
Total device input power, W. |
ef_output_power_watts |
Total device output power, W. |
bms_temperature_celsius |
Battery temperature at sensor 1, °C. Versions before this rename wrote bms_temperature_celcius. |
bms_capacity_charge_ratio |
Battery charge as a ratio from 0 to 1. |
ef_remaining_time_minutes |
General remaining-time estimate, minutes. |
ef_charge_remaining_time_minutes |
Charging-time estimate from the energy management module, minutes. |
ef_discharge_remaining_time_minutes |
Discharging-time estimate from the energy management module, minutes. |
bms_charge_is_charging |
Whether battery-side power flows into the battery. |
bms_charge_is_discharging |
Whether battery-side power flows out of the battery. |
ef_charge_state |
Numeric device state code. Observed R601 values are 0 for idle, 1 for charging, and 2 for discharging. |
ef_missing_measurements |
Text. Required reports that the server collection did not receive, or empty text for a complete collection. |
The server collection requires the PD, EMS, and BMS heartbeats from River 2. From River 3 it requires battery charge, total input and output power, battery power, one battery temperature, and both time estimates. Receipt counts, not the value, so an unavailable estimate still completes the collection.
Input power alone does not indicate battery charging. The device can supply an AC load without charging its battery. Do not apply River 2 state-code meanings to River 3.
Reported fields available to clients
Clients also receive every complete field from the five known heartbeat layouts. A heartbeat is a periodic report from a device module. The field names use these prefixes:
| Report | Prefix | Example |
|---|---|---|
| Device (PD) | ef_river2_pd_ |
ef_river2_pd_usb1_watts |
| Energy management (EMS) | ef_river2_ems_ |
ef_river2_ems_max_charge_soc |
| Battery management (BMS) | ef_river2_bms_ |
ef_river2_bms_cycles |
| Inverter (INV) | ef_river2_inv_ |
ef_river2_inv_inv_out_vol |
| Solar controller (MPPT) | ef_river2_mppt_ |
ef_river2_mppt_in_watts |
These fields appear in EcoFlowSnapshot.items(), socket responses, and client
snapshots. InfluxDB and Prometheus export them alongside the normal measurements.
Prometheus adds fields that first arrive after the exporter starts.
Numeric fields use BMSScalarField.raw_value and the units from the layout.
They retain reported state codes, zero values, and unavailable-time codes such as
5999. They do not replace the normal measurements or their interpretation rules.
For example, ef_river2_pd_soc uses percent, while bms_capacity_charge_ratio
uses a ratio from 0 to 1.
Byte fields use BMSInfoField.info with a 0x hexadecimal string.
This includes version, reserved, and other byte fields omitted by the text decoder.
Bytes beyond the last complete field use the same format under
<prefix>trailing_bytes. Their meanings remain unknown.
Each field retains its latest received value for the snapshot.
Shorter firmware reports do not erase earlier trailing fields or create zero values
for missing fields. A snapshot can therefore combine values from different reports.
A rejected report leaves the earlier decoded fields unchanged and adds
<prefix>decode_error. The next accepted report removes that error.
The ef_pkt_<src>_<cmdset>_<cmdid> field always retains the latest raw payload.
Source priority and units
Within each connection, charge percentage prefers the precise battery-management reading, then the precise energy-management reading, then an integer reading. Later integer packets cannot overwrite a precise reading. New readings from the preferred source still update the snapshot.
R601 pack voltage and current use volts and signed amps. Cell voltages and current limits use millivolts and milliamps. Unverified inverter configuration fields have no unit labels in diagnostics.
The normal snapshot omits negative, all-ones, and 5999 time estimates. R601
samples report 5999 for inactive directions, but it can also mean an unknown
or capped estimate. Diagnostics retain these raw values. Other estimates remain
unchanged. This rule does not apply to River 3.
Diagnostic collection
The diagnostic script waits for valid PD, EMS, and BMS reports. These are periodic reports from the device, energy management, and battery management modules. Empty or truncated reports do not count. Inverter (INV) and solar-controller (MPPT) reports are optional and do not delay completion.
Raw packet keys include the source module: ef_pkt_<src>_<cmdset>_<cmdid>.
If different modules share a command number, this still keeps their reports
separate. Watch mode also shows optional reports and unclassified packets.
Live R601 checks cover idle, charging, and discharging operation. Automated tests use synthetic packets. These results apply to River 2.
See the README for setup and commands.