Deye hybrid inverter (Modbus V118)
Register map(s) for this device, each at the trust rung it earned. Addresses are 0-based
as on the wire. Word order and scaling are confirmed at the hardware-verified rung and at no rung below it.
interop-verified
Read + decoded cleanly over a real network vs an independent third-party Modbus test server (transport and framing; reads are remapped into the server's register window, so the map's own addresses are NOT exercised). Does NOT prove word order/scaling against the actual device.
| point | address (0-based) | type | scale | unit |
| run_state | 59 | U16 | 1 | |
| day_active_power_wh | 60 | I16 | 0.1 | 0.1kWh |
| day_reactive_power_wh | 61 | I16 | 0.1 | 0.1kVarh |
| today_gen_power_wh | 62 | U16 | 0.1 | 0.1kWh |
| total_active_power_wh | 63 | U32LE | 0.1 | 0.1kWh |
| day_batt_charge_power_wh | 70 | U16 | 0.1 | 0.1V |
| day_batt_discharge_power_wh | 71 | U16 | 0.1 | 0.1V |
| day_grid_buy_power_wh | 76 | U16 | 0.1 | 0.1A |
| day_grid_sell_power_wh | 77 | U16 | 0.1 | 0.1A |
| grid_frequency | 79 | U16 | 0.01 | 0.01Hz |
| day_load_power_wh | 84 | U16 | 0.1 | 0.1VA |
| total_load_power_wh | 85 | U32LE | 0.1 | 0.1VA |
| radiator_temperature | 90 | I16 | 0.1 | 0.1℃ |
| igbt_temperature | 91 | I16 | 0.1 | 0.1℃ |
| grid_side_voltage_l1_n | 150 | U16 | 0.1 | 0.1V |
| grid_side_voltage_l2_n | 151 | U16 | 0.1 | 0.1V |
| grid_side_current_l1 | 160 | I16 | 0.01 | 0.01A |
| grid_side_current_l2 | 161 | I16 | 0.01 | 0.01A |
| grid_power | 169 | I16 | 1 | 1W |
| load_side_total_power | 178 | I16 | 1 | 1W |
| battery_temperature | 182 | I16 | 0.1 | 0.1℃ |
| battery_voltage | 183 | U16 | 0.01 | 0.01V |
| battery_capacity | 184 | U16 | 1 | 1% |
| battery_status | 185 | U16 | 1 | |
| pv1_input_power | 186 | U16 | 1 | 1W |
| pv2_input_power | 187 | U16 | 1 | 1W |
| battery_output_power | 190 | I16 | 1 | 1W |
| battery_output_current | 191 | I16 | 0.01 | 0.01A |
link settings as documented (unverified): RTU; default 9600 8??; FC 03,16; RS232 or RS485
bench facts as documented (unverified)
| connector | RS232 or RS485 |
| max registers/read | 125 |
| model register | 0 |
| serial register | 3 |
| firmware register | 13 |
| doc revision | V117 |
field reports — community-sourced, unverified (checked 2026-06-11)
- Deye-SUN-5K-SG03LP1 reading times out when more than 16 registers are requested at once, requiring smaller register ranges. [source]
- Some Modbus TCP gateways (e.g., PUSR USR-DR134) fail when requesting the standard 125 registers per request, requiring a max_size limit of 120. [source]
- The battery temperature sensor (register 182) has a scaling offset of 1000 (e.g., 1200 represents 20.0 °C), which was incorrectly decoded in some integrations (showing 75°C instead of 25°C). [source]
- The internal RTC clock drifts massively (up to 10 minutes per day), causing scheduled charging/discharging windows to shift unless synced frequently via external automation. [source]
- Undocumented register 205 ('Empty_V') acts as the battery voltage level corresponding to 0% SOC. If battery voltage drops below this value, the SOC instantly drops to 0%. [source]
- confirmed: comms: baud_rates: [9600], default_baud: 9600, framing: ['RTU'], function_codes: [3, 16], notes: 'RS232 or RS485' — confirmed by Deye user manuals and community integrations (e.g., kbialek/deye-inverter-mqtt, kellerza/sunsynk)
- confirmed: facts: doc_revision: 'V117', identification: firmware_register: '13', model_register: '0', serial_register: '3' — confirmed by Deye Modbus RTU protocol documents (V115, V118) where register 0 is Device Type, register 3 is Serial Number (SN byte 01), and register 13 is Slave MCU Version
- confirmed: physical: connector: 'RS232 or RS485' — confirmed by Deye user manuals and community wiring guides
- confirmed: quirks: max_read_registers: 125 — confirmed by standard Modbus RTU limits and Deye integration discussions
- confirmed: Register map summary (run_state @ 59, day_active_power_wh @ 60, today_gen_power_wh @ 62, total_active_power_wh @ 63, day_batt_charge_power_wh @ 70, day_batt_discharge_power_wh @ 71, day_grid_buy_power_wh @ 76, day_grid_sell_power_wh @ 77, grid_frequency @ 79, day_load_power_wh @ 84, total_load_power_wh @ 85, radiator_temperature @ 90, igbt_temperature @ 91, grid_side_voltage_l1_n @ 150, grid_side_voltage_l2_n @ 151, grid_side_current_l1 @ 160, grid_side_current_l2 @ 161, grid_power @ 169, load_side_total_power @ 178, battery_temperature @ 182, battery_voltage @ 183, battery_capacity @ 184, battery_status @ 185, pv1_input_power @ 186, pv2_input_power @ 187, battery_output_power @ 190, battery_output_current @ 191) — confirmed by kellerza/sunsynk single_phase.py definitions and Deye Modbus RTU protocol documents
The trust ladder
Each rung states what it proved and what it did not. Gray until proven; green is earned by hardware only.
- generated — A prompt produced it. Unproven — anyone can regenerate this.
- structure-verified — Decode path is structurally sound (addresses, widths, finite values). Does NOT prove word order or scaling.
- interop-verified — Read + decoded cleanly over a real network vs an independent third-party Modbus test server (transport and framing; reads are remapped into the server's register window, so the map's own addresses are NOT exercised). Does NOT prove word order/scaling against the actual device.
- simulator-verified — Decoded correctly against a protocol emulator seeded with known-true values — catches word-order/scaling errors vs the emulator, not the physical device.
- hardware-verified x1 — Matched a real device with operator-attested readings as ground truth — the only rung that confirms word order + scaling on the wire.