Skip to content

Add guarded SRNE settings write infrastructure - #21

Merged
tushabe merged 6 commits into
mainfrom
agent/story-53-srne-safe-write-infrastructure
Aug 6, 2026
Merged

Add guarded SRNE settings write infrastructure#21
tushabe merged 6 commits into
mainfrom
agent/story-53-srne-safe-write-infrastructure

Conversation

@tushabe

@tushabe tushabe commented Aug 3, 2026

Copy link
Copy Markdown

What changed

  • add a disabled-by-default safety gate for SRNE FC16 settings writes
  • expose the live-validated readable SoC and charge-current settings
  • write only when the requested value differs from current state
  • clamp configured targets to supported bounds
  • require a live-verified inverter state before queuing a write
  • verify each write after a fresh post-write readback and prevent automatic retries after an error or mismatch
  • add unit tests for no-op, successful verification, delayed readback, and mismatch behavior

Story boundary

This is the first implementation slice of settings story #53. Remaining OpenEMS#53 work includes rollback context, stale/fault/transition gates and tests, exact FC16 integration coverage, auditing, and validated schedule-block support.

The PR intentionally excludes ambiguous mode/source-priority writes and all DFxx commands. Guarded inverter ON/OFF and sleep/run commands are tracked separately in #57; immediate source transfer is OpenEMS#56; managed power control is OpenEMS#55.

Why

This establishes safe settings-write infrastructure while keeping control disabled unless an operator explicitly enables it.

Validation

./gradlew :io.openems.edge.ess.srne:check

@tushabe
tushabe requested a review from arindahills August 3, 2026 15:46

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 914cad00c1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

tushabe and others added 4 commits August 3, 2026 19:11
…ry continuous rating

Review follow-ups on the guarded settings-write path (Aaron offline):

- SafeWriteHandler: queueIfChanged runs on the Edge cycle thread while
  onExecute/verify fire on the Modbus bridge worker thread; the mutable
  state/target had no synchronization, so transitions were not guaranteed
  visible across threads. Make the four methods synchronized.

- Current-limit settings (stopChargeCurrent, acChargeCurrentLimit,
  maxChargeCurrentLimit) were clamped to 120A. The SR-SE10B (205Ah LFP)
  continuous max charge/discharge is 100A; 120A is only the 3-second peak
  (datasheet SRNE_SE series V1.5). Cap at 100A via a named constant so a
  configured continuous limit can never exceed the battery rating.

Signed-off-by: arindahills <293051436+arindahills@users.noreply.github.com>

@arindahills arindahills left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the guarded settings-write infrastructure. Solid, safety-first design: gate off by default, controlEnabled && machineState.isVerified() required before any write, write-only-if-different, clamp-to-bounds, post-write readback verification, and no auto-retry after a FAILED. Well tested.

Aaron is offline, so rather than leave blocking comments I've pushed two fixes directly to this branch. Details below, with what's fixed vs. what I'd leave for the OpenEMS#53 follow-ups.

Pushed to this branch

1. SafeWriteHandler thread-safety. queueIfChanged runs on the Edge cycle thread (run()), while onExecute and verify fire on the Modbus bridge worker thread (task execute callback + read-back channel callback). state/target were plain fields with no synchronization, so a transition on one thread wasn't guaranteed visible to the other (a real cross-thread visibility bug in a safety component). Made the four public methods synchronized so transitions are atomic and visible. Behaviour unchanged; existing tests still pass.

2. Current-limit ceiling 120A → 100A (battery safety). stopChargeCurrent, acChargeCurrentLimit, and maxChargeCurrentLimit clamped to 0..120. Per the SR-SE10B (205Ah LFP) datasheet (SRNE_SE series V1.5): continuous max charge/discharge is 100A; 120A is only the 3-second peak. A continuous limit setting must cap at the continuous rating, otherwise an operator could configure a 120A continuous limit above what the battery allows. Replaced the magic 120 with a named, datasheet-cited constant MAX_BATTERY_CURRENT_A = 100. (SoC registers stay 0..100, correct.)

Verified, no change needed

Read-back freshness. I flagged that verify() might act on a pre-write reading, but on closer look the Modbus bridge runs tasks serially, so the read-back that fires after onExecute physically post-dates the write — it's fresh. No change; the guarantee holds.

Suggested follow-ups for OpenEMS#53 (not blocking this slice)

  • AWAITING_READBACK has no timeout. If the LOW-priority read-back never delivers a fresh value, a handler stays awaiting forever (write happened, never confirmed). Not dangerous (no repeat write) and it's within OpenEMS#53's "stale/fault/transition gates" — just flagging it's currently unbounded.
  • VERIFIED is terminal. A handler never writes again for the life of the component instance, so continuous drift-correction only happens if a config change re-activates the component (which it does — no @Modified, so a config update triggers deactivate/activate → fresh handlers). Acceptable for settings (vs. control set-points); worth a comment noting the re-activation dependency.
  • Silent clamp. When a configured target is clamped, nothing signals it (operator sets 150, gets 100, sees VERIFIED). A debug log / status channel would help once control is enabled at site.
  • aggregateWriteState ranks by enum.ordinal() while State is an OptionsEnum with distinct getValue()s — reordering the enum would silently change aggregation. Rank on explicit precedence.

Net: safe to merge as disabled infrastructure once CI is green. The two blockers before controlEnabled is ever turned on at site (thread-safety and the 100A ceiling) are handled in this branch.

@tushabe
tushabe merged commit 81b12aa into main Aug 6, 2026
3 checks passed
@tushabe
tushabe deleted the agent/story-53-srne-safe-write-infrastructure branch August 6, 2026 06:58
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