# SRNE charge/discharge scheduling registers (self-decoded, #67)

## Summary

We self-decoded the SRNE ASP48120SH3 settings registers (V1.7 protocol PDF + a live read-scan of the pilot inverter, firmware v925, 2026-08-09). The key result: **time-of-use charge/discharge scheduling is implemented and writable**, even though real-time active-power dispatch is not. This is the arbitrage lever, and it is not firmware-blocked.

Aaron's SRNE email (2026-08-03) reported that `0xE047-0xE04D` (timed charge/discharge MAX POWER) and `0xE400/E401/E402` (grid active/PF/reactive power) return Modbus "Illegal data address" on our firmware. That is confirmed. But those are a different feature (instantaneous power dispatch). The actual **time-window schedule registers `0xE026-0xE032` are RW and implemented.**

## Charge / discharge schedule registers (RW, hour*256 + minute)

| Register | Function | Live value | Decoded |
|---|---|---|---|
| 0xE026 | 1-section charge start | 0 | 00:00 |
| 0xE027 | 1-section charge stop | 1536 | 06:00 |
| 0xE028 / 0xE029 | 2-section charge start / stop | 0 / 0 | unused |
| 0xE02A / 0xE02B | 3-section charge start / stop | 0 / 0 | unused |
| 0xE02D / 0xE02E | 1-section discharge start / stop | 0 / 0 | unused |
| 0xE02F / 0xE030 | 2-section discharge start / stop | 0 / 0 | unused |
| 0xE031 / 0xE032 | 3-section discharge start / stop | 0 / 0 | unused |

Encoding: value = hour * 256 + minute. Max 5947 (23*256 + 59 = 23:59). So `1536 = 6*256 + 0 = 06:00`.

Current live config: charge window 1 = 00:00 to 06:00 (off-peak), no scheduled discharge. To do TOU arbitrage, set a discharge window over the peak (18:00 to 24:00 = start 4608, stop 6144-ish, i.e. 24:00 as 23:59 = 6143 or 0).

RTC / current time: `0xE034` (year+month) `0xE035` (day+hour) `0xE036` (minute+second) RW; read via `0x020C/020D`. The inverter's clock must be correct for the schedule to fire at the right wall-clock time - verify it.

## Mode / priority registers (RW)

| Register | Function | Live | Notes |
|---|---|---|---|
| 0xE204 | Output priority | 3 | 0/1/2 documented (2 = hybrid, mains+PV, PV preferred); reads 3 on this unit |
| 0xE20F | Charge priority | (def 2) | 0-3 |
| 0xE216 | Start charge time (hour) | 1 | 01:00, "valid for some custom model" |
| 0xE217 | Start discharge time (hour) | 12 | 12:00, "valid for some custom model" |
| 0xE205 | Mains charge current limit | 80 | x0.1 A? doc says A; range 0-100 |
| 0xE20A | Maximum charge current | 80 | 0-150 |

## Full settings decode (0xE001-0xE039, from V1.7 + live)

Voltage/battery: E002 nominal capacity, E003 system voltage (48), E004 battery type, E005 over-voltage (15.0V), E006 limited-charge (14.4V), E007 equalize, E008 boost/overcharge, E00A boost-return (13.2V-ish), E00B over-discharge-return, E00C under-voltage warn, E00D over-discharge (load cut), E00E limited-discharge, E00F discharge-cutoff SoC (5%), E01B mains-switching voltage, E022 inverter-switching voltage. Times: E010 over-discharge delay (s), E011 equalize time, E012 boost time (min), E023 equalize timeout. The 8 settings the OpenEMS write feature (#53) uses are a subset: E00F, E01C, E01D, E01E, E01F, E020, E205, E20A.

## NOT implemented on this firmware (Illegal data address, confirmed live)

`0xE047-0xE049` timed discharge max power, `0xE04A-0xE04C` timed charge max power, `0xE04D` timed charge source, `0xE400` grid active-power set, `0xE401` PF, `0xE402` reactive, `0xE42A` battery grid participation, `0xE42C` zero-export. So OpenEMS-style instantaneous power dispatch is not available; TOU scheduling is the achievable control.

## What this unlocks for NFE

TOU arbitrage via scheduling: set the charge window to off-peak (already 00:00-06:00) and add a discharge window over the peak tariff, using `0xE026-0xE032`. All RW, all validated readable live. Next: a careful readback-verified live write test of one discharge window (write, verify, restore), then integrate scheduled writes (guarded, like #53) so NFE can shift the battery by tariff without a site visit.

## Method / traceability

Live read-scan via mbpoll (edge + nfe-monitor stopped to free the RS485 bus), firmware v925, 2026-08-09. Decoded against `SRNE_Hybrid_Inverter_MODBUS_protocol_V1.7.pdf` (repo: NFE/CUSTOM_CODE/srne-products). Related: register map (page 126), mbpoll reference (page 125), safe settings write (page 128, #53). Issue logger #67.