Repository navigation
Feature request: native local Deye/Solarman support and safe migration from SK #5501
Description
Is your feature request related to a problem? Please describe.
Please consider explicit native support for local Deye inverters exposed through
Home Assistant's Solarman integration, with a documented path from existing
inverter_type: SK configurations.
The local-control problem is already reported in #3895: Predbat can calculate a
plan while the Deye six-row Time of Use (ToU) table does not reliably express it,
leading users to add another HA automation as a translator. This issue tracks
the broader adoption, compatibility and commissioning requirements, not a
duplicate report of that specific failure.
Draft implementation: #5497. A dedicated adoption issue was missing when that
PR was opened; this issue supplies the tracking and maintainer-design discussion.
The proposed local DEYE profile is distinct from DeyeCloud and must not change
existing SK behaviour or imply that every Deye model/firmware is supported.
Describe the solution you'd like
A native, opt-in local adapter owned by Predbat's existing inverter executor,
without another planner, competing HA control automation, cloud dependency or
additional hardware polling loop.
The current proposal in #5497 provides:
- Explicit mappings for all six ToU rows: SOC, discharge-power ceiling and
charging source. Native windows are virtual; all rows express the current
control intent while their physical boundaries remain unchanged. - Validation of distinct, ordered boundaries and supported operating settings;
reject inconsistent configurations rather than silently rewrite them. - Demand, full-rate grid charge and an explicitly commissioned hold contract,
plus bounded per-period discharge power and existing manual SOC floors. - Disabled-by-default control, read-only guards, source-disable interlocks,
bounded retries and visible failures. - An isolated shadow path that exercises the actual translator without calling
physical services. Timetable repair or hold commissioning in a simulation is
labelled as a hypothesis, not a completed physical operation. - Honest acknowledgement semantics: an HA state match is observed, not proof
that the physical inverter applied the setting. Solarman can expose optimistic
post-write states. Control entities echo Predbat's own writes on Deye/Fox/Enphase, so write read-back can't detect external changes #4636 describes a related distinction for cloud components;
it is context, not evidence of an identical implementation in local Solarman.
Adoption and promotion gates
These are proposed requirements for maintainer discussion, not a claim of approval:
- Agree the local adapter/profile boundary and naming relative to
SKand
DeyeCloud, including a clear supported and unsupported feature list. - Review the native control mapping and disabled-path compatibility tests;
no new global capability override or regression for existing inverter profiles. - Publish a tested model/firmware/Solarman compatibility matrix and entity
requirements, including numeric step sizes and timestamp limitations. - Physically validate charge, demand, hold/PV behaviour, limited discharge,
all six rows, target changes and midnight transitions on supported equipment. - Document safe migration from
SK: entity mapping, coherent table
boundaries, existing current/SOC/export limits, sole controller and rollback.
Do not blindly reuse a grid-charge-start entity as a discharge reserve. - Document behaviour when Predbat/HA stops, telemetry is unavailable or a
write is rejected. The present immediate-control proposal can leave the last
physical table in place; shadow tests do not establish an independent watchdog. - Complete upstream CI/review and commissioning evidence before describing
this experimental adapter as generally adopted support.
Global current limits, BMS/shutdown protections, export policy, operating modes
and EV relays must not be silently rewritten as part of local-adapter adoption.
Electrical topology and capacity remain installation-specific commissioning
questions, not conclusions derived from nominal ratings or simulation.
Describe alternatives you've considered
- Keep using
SKwith custom service templates: preserves existing setups but
does not provide a dedicated six-row contract or migration guidance. - Add another HA automation to translate plans: a reported workaround in Deye via Solarman: Predbat computes best charge plan but does not apply TOU correctly #3895,
but adds a separate control owner and is not the native integration requested. - Use Deye Cloud: a different transport and capability model; not a substitute
for local Solarman support.
Additional context
- Implementation and sanitised software/shadow evidence: feat: add experimental local Deye ToU adapter and isolated preview #5497.
- Local ToU problem report: Deye via Solarman: Predbat computes best charge plan but does not apply TOU correctly #3895 (not automatically closed by this tracking issue).
- Related time-entity granularity discussion: Snap select-based charge/discharge time entities to valid step size (SA/Solar Assistant, Deye) #4947.
- Separate import-diagnostic PR: Add configurable whole-site import diagnostics (no enforcement) #5486.
- Separate joint EV/home-battery planning request and shadow PR: Joint cost-aware EV and home-battery scheduling under a site import limit #5490 / feat: experimental native joint EV and home battery planning #5498.
Those features do not constitute adoption of the local inverter adapter and
should remain independently reviewable.
The local combined shadow trial keeps the existing physical controller in charge.
Physical commissioning and general firmware compatibility have not been
established. Passing local tests is not upstream acceptance; the PR remains draft
and its upstream workflow currently requires approval. No private configuration,
credentials, device identifiers or raw household captures are attached.
Activity
springfall2008 commentedon Oct 12, 2026
🤖 This is an automated first-pass triage — a maintainer will review before any action is taken.
Classification:
enhancement— a feature request for a native, opt-in local Deye/Solarman adapter plus a documented migration path frominverter_type: SK. The ticket reads as the tracking/adoption issue for the design discussion, not a bug report.Not a duplicate. No open or closed issue/PR tracks local Solarman/Deye support. #3895 reports the underlying ToU-write problem on an
SK-profile setup and stays open separately, as the body itself notes — this ticket is not duplicating it.What I checked against current main (d6985b6):
inverter_type: SK(the Sunsynk profile, local control via HA entities — the path Deye via Solarman: Predbat computes best charge plan but does not apply TOU correctly #3895 uses) and the DEYE Cloud component (deye.DeyeAPI, components.py). The docs cover DeyeCloud only; there is no local Solarman/Deye profile on main, so the gap this issue describes is real.Related: #3895 (ToU writes not reliably applied over Solarman on SK), #4947 (select-based charge/discharge time entities are not snapped to a valid step size — affects SA/Deye time writes; an in-repo snapper precedent exists in
alphaess_const.py'ssnap_time_grid()), and #4636 (state matches can be echoes of Predbat's own writes — the "observed, not proof" distinction this issue already adopts).No priority set, as this is a feature request; no component label applied, as the repo's label set has no Deye/Solarman label.
gcoan commentedon Oct 12, 2026
@arturonaredorather than add a native new inverter type for Deye, I suggest it would be better and more flexible to just add support for Deye date/time formats then the inverter can be supported as a custom type (with example apps.ysml and setup instructions), but also that config can be used for any other future inverter.
Hard coding inverter types in predbat isn't the way we generally extend the inverter pool any more as it locks any fixes into core releases. Using custom inverter types is more flexible
arturonaredo commentedon Oct 12, 2026
@gcoan Thanks, I agree with the configuration-driven direction. My inverter is a SUN-16K-SG01LP1-EU, connected locally through Home Assistant/Solarman.
My concern is that “custom” should not mean every user independently maintains their own implementation. Predbat already has both the documented
inverter_type+inverter:custom-definition mechanism and a sharedtemplates/directory. Could we build on those with a reusable, documented Deye/Solarman template maintained in the repository, rather than a collection of private configurations?The split I have in mind is:
Longer term, I would favour moving the declarative parts of the existing built-in inverter definitions towards the same shared-profile approach, incrementally and preserving existing
inverter_typeconfigurations. That need not block this contribution, and vendor-specific protocol/control logic would still require code where appropriate.Would a shared Deye/Solarman template plus the smallest necessary generic core changes be the preferred direction for reshaping #5497? My goal is for fixes and improvements to benefit everyone using that integration, not just my installation.
gcoan commentedon Oct 12, 2026
absolutely, that was what I was thinking of
yes please, the smallest set of core changes to enable predbat to talk correctly to your inverter, update the inverter setup 'custom type' documentation to include it, then add a new Deye section to the inverter setup and provide a template for others to use. This is the way we have done a lot of the newer inverter types (Tesla, Luxpower, Sigenergy, Solax, etc)
Cheers
arturonaredo commentedon Oct 12, 2026
Implemented the shared-template direction in #5505 and closed the superseded #5497 (its branch is retained). The replacement starts from upstream v9.3.8: a shared Deye/Solarman custom profile, setup/custom-type documentation, and 138 lines of opt-in generic core support for ordered HA-observed service sequences. No new branded core adapter. All 345 registered test groups, all pre-commit hooks and the docs build pass locally. The PR is draft: HA observations are not physical confirmation, and hold/export/power control plus the separate joint-apply compatibility work are explicitly not claimed. No live installation was changed.
arturonaredo commentedon Oct 13, 2026
Shared-template field evidence — 13 October 2026
Following the shared custom-profile direction agreed here, #5505 is now operating on my SUN-16K-SG01LP1-EU through local HA/Solarman. This supersedes the initial development-only status; the implementation is the shared YAML plus generic observed service sequences, not the superseded branded adapter in #5497.
There is HA-observed evidence of both grid charging and demand operation:
Charging, read-only offGrid, target 59% on every rowDemand, read-only off, no reported error; latest cycle 10:30Disabled, target 10% on every rowThe earlier accepted command/observation receipt was cross-checked against HA recorder. Battery SOC was 30%, then recorded 31% at 23:04:30 UTC, consistent with grid charging. These power samples are not simultaneous calibrated measurements and do not prove the eventual target was reached.
At the later check: HA 2026.10.1 / Solarman 26.01.31. The installed generic service-sequence implementation matches public PR head
4546443fby AST comparison; the shared profile and service definitions also match after entity-prefix resolution. The full newly rebased tree was not deployed: this is the earlier combined installation using the same template/control implementation.The exact public template head passed 346/346 standalone test groups. I also reran
service_sequences,deye_solarman_templateandexecute: 3/3 groups, no skips. These exercise the real shared YAML/native entrypoints with synthetic HA, including all six rows, ordering, idempotence, failure barriers, retry and Monitor/read-only. Full provenance, test links and reproduction commands are in the existing consolidated PR report.Scope of “working”: observed charge/demand operation on this installation. HA observations are not independent hardware acknowledgement or general firmware certification. Hold/freeze, export/power control, outage recovery and physical EV operation remain outside this evidence. No new device actions, configuration changes, restarts or faster polling were used to collect it; no private captures, configuration or identifiers are attached. Upstream CI for this head still needs maintainer approval.
gcoan commentedon Oct 14, 2026
@arturonaredo thanks for the PR, I've had a read through, can't comment on the code changes in detail, that will be for Trefor to review, but the shape of what's there looks OK.
My comments are principally on the documentation:
sorry there is a lot of comments, it looks good work, the introduction of explicit verify of config is a good idea and a useful addition. My main feeling is you need to make it more user-friendly the doc, easier for new users to read and understand what is happening
Cheers
arturonaredo commentedon Oct 14, 2026
Thank you for the detailed review @gcoan !! Let me elaborate a response for you!
arturonaredo commentedon Oct 14, 2026
Thanks again @gcoan for the detailed documentation review. I have addressed the points below in 17 separate commits on #5505, including a Quick start. This update changes the documentation, example configuration and its regression assertions; it does not change the inverter's runtime service routing.
1. Inverter list order
Moved Deye/Solarman alongside DEYE Cloud in the alphabetical list, leaving GivTCP first. Commit f2d5ad0.
2. Testing on my installation
Yes: grid charging and normal self-consumption have been used on my SUN-16K-SG01LP1-EU through local Solarman, with HA observations and recorded telemetry. I replaced the confusing blanket statement with that evidence and its scope. I am not claiming validation of every Deye model/firmware or failure recovery. Commit 5f7b075.
3. Commands versus observations
Both are automatic Predbat operations. The table now separates what Predbat sends from what it checks in HA. It disables the six sources, checks them, sets/checks the six targets, then enables/checks Grid. A failed phase stops the remaining sequence. All programs receive the current command because the inverter selects its active program by time; this is not six future forecast slots. Commit 4aee8e0.
4. SoC spelling
Changed the Deye prose and template comments to SoC, without renaming actual entity IDs or configuration keys. Commit 227bbdb.
5. Disabled and manual prerequisites
Separated Charging sources and required inverter setup from the automatic command table.
Disableddisables that program's grid/generator charging source, not the inverter or all battery activity. The documentation explicitly lists the work mode, ToU, Program Power/current and protection settings the user must configure or verify outside Predbat. It does not prescribe universal battery/BMS limits. Commit 74951bb.6. Physical time settings
The current template requires an enabled six-program schedule covering the complete day, including the overnight wrap. These are six physical boundaries, not one 00:00–23:59 start/end pair. The user configures/checks them on the inverter or through Solarman; Predbat's start/end sensors are internal bookkeeping and must not be mapped onto two of those six controls.
Solarman exposes writable time entities, but this template does not initialise them, and the verified sequence implementation currently does not support
time.set_value. Automatic initialisation would need a separately implemented/tested extension. Commit 3cfb1ca.7. Replace rather than merge
Changed the instructions to back up the existing file, replace the shipped GivTCP example with the complete Deye template, and configure the user's rates/forecasts/car there. The instructions explicitly say not to combine inverter profiles. Commit 3788df2.
8. Other automatic controllers
That is now stated directly. Other automatic writers must be disabled before enabling Predbat control; monitoring-only readers are distinguished from competing controllers. The template does not disable those systems itself. Commit df59097.
9. Control charge and discharge
Replaced the prohibition with the supported mode and reason: Control charge supports grid charging and normal discharge to household loads. Scheduled forced export is not implemented by this template. Selecting the additional mode still uses the same profile, but does not add a missing discharge-start/export-control capability. I have not removed the limitation or claimed forced export works. Commit 2209b14.
10. Verified service sequences
Added the motivation and a comparison with traditional service templates.
repeat: trueresends traditional calls but does not verify state. Verified sequences check observed final values on each invocation, avoid unnecessary writes and wait between changed steps.repeat/alwaysare not accepted in verified entries. HA read-back remains an observation, not independent hardware confirmation. Commit 6f1329f.11. Charge freeze fallback
I checked both the v9.4.0 upstream implementation and its tests. The distinction is:
charge_stop_servicecharge_start_serviceThe docs now explain both cases, rather than implying one universal fallback. These runtime methods are unchanged from upstream by this PR. Stopping charging alone is not a guarantee of a physical battery hold. Commit cee5be6.
12. Discharge freeze fallback
Confirmed against the same upstream code/tests: an explicit discharge freeze first stops charging, then uses the freeze hook or
discharge_stop_servicewhen that hook is absent. Ordinary export reaching its target stops discharge without invoking a freeze. The docs also distinguish absent hooks from configured empty lists and explain the separate idle-export stop fallback. No routing behaviour was changed. Commit 4de6ca3.13. has_service_api
Confirmed that the Python implementation does not consult this flag. Removed it from the new template and custom-profile example, and retained a short compatibility note explaining that True/False has no effect: the configured service hooks determine the service calls. Commit f5b4fa0.
14. Complete apps.yaml template
Expanded the file with currency, hybrid modelling, load-history/horizon/scaling settings, optional PV forecast and rate examples, optional per-car inputs, notifications and watch-list examples based on the standard configuration.
template: trueremains, cars default to zero, and no other inverter/controller is activated. The user still needs to supply actual entities, tariffs and installed limits. Added regression assertions for the complete blank template. Commit 7adf0e2.15. YAML anchors
Added an explanation:
&disable_sourcesnames a YAML mapping;*disable_sourcesreuses it. The anchored entry is still a real step in its original list. This is resolved during YAML loading, not a Predbat subroutine. Commit 4fa29be.16. YAML merge
Added its fully expanded equivalent.
<<reuses the service/entity/verification fields, while the explicitoption: "Grid"replacesDisabled. The resulting step enables Grid; it does not call a separate disable routine. Commit 6efbafe.17. Easier first-time setup
Added a Quick start before the detailed explanation: Solarman, replacing the default template, configuring rates/forecasts/car inputs, preparing the inverter, removing competing writers, then Monitor and a checked Control charge cycle. The detailed limitations and service reference remain available below it. Commit eff7231.
Validation
These checks do not extend the one-installation field evidence to other inverter models, forced export or outage recovery. Current-head upstream CI run 38654234995 reports
action_requiredand awaits maintainer approval; local tests are not an upstream CI pass.I hope this way of giving you a reply helps!
gcoan commentedon Oct 14, 2026
thanks for your commits and extensive replies, I'll take a fresh look at the draft PR
yaml anchors, never seen them before. Learn something new