Add Solplanet hybrid inverter template (SunSpec) - #33044
Conversation
…id, Battery)\n\n- Modbus-RTU (RS485) connection support with configurable baud rate\n- Grid, PV (with curtailment), and Battery usage modes\n- SunSpec compliant (Models 701, 702, 703, 704, 714, 802)\n- Dynamic power calculation from battery voltage (P = U × 30A)\n- Full battery control (normal/hold/charge modes)\n- Curtailment via Model 704 with Model 123 fallback\n\nVerified against KACO Blueplanet Hybrid NH3 SunSpec PICS template
There was a problem hiding this comment.
Hey - I've found 1 issue, and left some high level feedback:
- The
requirements.descriptiontext hardcodes a 9600 baud Modbus-RTU connection, but the template exposes a configurablebaudrateparam (9600/19200/38400); consider updating the description so it aligns with the actual configuration options. - The
modBusDeviceIdparameter name is inconsistent with the other parameter naming (mixed casing vs. lowercase with no camelCase); consider normalizing this to match existing conventions for easier template reuse and discoverability.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The `requirements.description` text hardcodes a 9600 baud Modbus-RTU connection, but the template exposes a configurable `baudrate` param (9600/19200/38400); consider updating the description so it aligns with the actual configuration options.
- The `modBusDeviceId` parameter name is inconsistent with the other parameter naming (mixed casing vs. lowercase with no camelCase); consider normalizing this to match existing conventions for easier template reuse and discoverability.
## Individual Comments
### Comment 1
<location path="templates/definition/meter/kaco-nh3-hybrid.yaml" line_range="118" />
<code_context>
+ power:
+ source: sunspec
+ {{- include "modbus" . | indent 2 }}
+ value: {{ if eq .battery "2" }}714:Prt.2.DCW{{ else }}714:Prt.1.DCW{{ end }} # Model 714 (DC Module - Battery Power)
+ # Prt.1 = Battery 1, Prt.2 = Battery 2 via Model 714 (Multi-Port DC Module)
+ soc:
</code_context>
<issue_to_address>
**issue (bug_risk):** Align the battery parameter type with the comparison to avoid a non-matching condition.
`battery` is defined as a numeric choice (`[1, 2]`), so YAML will parse it as integers, but the template compares it to a string (`"2"`). That condition will never be true, and `Prt.1.DCW` will always be used. Please either make the choices strings (`["1", "2"]`) or compare against an integer (`if eq .battery 2`) so the correct port is selected.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
- Fix hardcoded baud rate in requirements.description to mention configurable options (9600, 19200, 38400) - Normalize parameter naming: modBusDeviceId → modbusdeviceid (lowercase, no camelCase) - Fix battery parameter type mismatch: change choice from [1, 2] to ["1", "2"] for string comparison - Battery selector now correctly uses string comparison (if eq .battery "2") matching the parameter type
…SunSpec Model 802 - Add capacity source: 802:WHRtg (Battery nominal capacity in Wh) - Add minsoc source: 802:SoCMin (Minimum SOC limit % from inverter) - Add maxsoc source: 802:SoCMax (Maximum SOC limit % from inverter) - Remove manual parameter definitions - all values now read from inverter - Parameters automatically sync with inverter settings (no manual configuration needed) - If SoC limits change on inverter, EVCC reads new values automatically
Co-authored-by: andig <cpuidle@gmail.com>
This comment was marked as resolved.
This comment was marked as resolved.
…ve comments - Simplify curtailment switch default case to align with case 100 pattern - Remove inline comments that don't add significant value - Keep core comments for critical logic - Improves code consistency and reduces verbosity - All fixes address Sourcery AI review feedback
|
Template fails test :/ |
|
Yes I have seen that and is trying to rectify.
…________________________________
Fra: andig ***@***.***>
Sendt: Wednesday, 26 August 2026 10:39:43
Til: evcc-io/evcc ***@***.***>
Cc: Lars Hansen ***@***.***>; Author ***@***.***>
Emne: Re: [evcc-io/evcc] Add Kaco NH3 hybrid inverter (PR #33044)
[https://avatars.githubusercontent.com/u/184815?s=20&v=4]andig left a comment (evcc-io/evcc#33044)<#33044 (comment)>
Template fails test :/
—
Reply to this email directly, view it on GitHub<#33044?email_source=notifications&email_token=AQ243QYXRAZIEA5FEBXFEOT5L2O47A5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKNBSGI3TMOJZGM32M4TFMFZW63VGMF2XI2DPOKSWK5TFNZ2KYZTPN52GK4S7MNWGSY3L#issuecomment-5422769937>, or unsubscribe<https://github.com/notifications/unsubscribe-auth/AQ243Q3EQODQX46WLHMCOUD5L2O47AVCNFSNUABFKJSXA33TNF2G64TZHMZDENRTGY4DGMZYHNEXG43VMU5TKMRRGMYTMMRSGI4KC5QC>.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS<https://github.com/notifications/mobile/ios/AQ243Q7PDPFPZT5M36VOOQD5L2O47A5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKNBSGI3TMOJZGM32M4TFMFZW63VGMF2XI2DPOKSWK5TFNZ2KUZTPN52GK4S7NFXXG> and Android<https://github.com/notifications/mobile/android/AQ243Q2GYSB7RT4FF5PDDI35L2O47A5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKNBSGI3TMOJZGM32M4TFMFZW63VGMF2XI2DPOKSWK5TFNZ2K4ZTPN52GK4S7MFXGI4TPNFSA>. Download it today!
You are receiving this because you authored the thread.Message ID: ***@***.***>
|
- Adjust indentation of default block to align with case statements - Follows pattern used in SAX, SENEC, and other hybrid templates - Maintains proper YAML structure for switch/case/default - Fixes go-yaml mapping values error
- Move default block to same indentation level as case items (not under switch) - Verified against fronius-gen24.yaml and enphase-modbus.yaml - Matches the exact pattern used in production templates with sequence+switch - Fixes YAML parsing error
a83e496 to
31fd012
Compare
There was a problem hiding this comment.
Hey - I've found 2 issues
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="templates/definition/meter/kaco-nh3-hybrid.yaml" line_range="33" />
<code_context>
+ description:
+ de: Batteriespeichernummer
+ en: Battery number
+ - preset: battery-params
+render: |
+ type: custom
</code_context>
<issue_to_address>
**issue (bug_risk):** The template declares and renders the generic `battery-params` values, but does not define `capacity`, `minsoc`, or `maxsoc` services backed by SunSpec model 802 (`WHRtg`, `SoCMin`, and `SoCMax`). Consequently, these values are not read or synchronized from the inverter as described; they remain manual template parameters and can be missing or stale.
**Triggers:** When a battery meter is configured without manually supplied battery parameters, or when the inverter's capacity or SoC limits differ from the configured values.
**Suggested fix:** Define the battery parameter services from model 802, applying the required `WHRtg` Wh-to-kWh scale conversion for `capacity`, instead of only including the generic parameter rendering.
</issue_to_address>
### Comment 2
<location path="templates/definition/meter/kaco-nh3-hybrid.yaml" line_range="13" />
<code_context>
+ Der Wechselrichter muss sich im Grid-Feeding Modus befinden.
+ Bei zwei Batteriepaketen (BMS1 + BMS2) je einen Batteriezähler mit Batteriespeichernummer 1 und 2 anlegen.
+ en: |
+ Modbus RTU (RS485) connection. Devices with a dedicated Modbus TCP ethernet port can alternatively use the `solplanet-modbus` template.
+ The inverter must be in grid-feeding mode.
+ With two battery packs (BMS1 + BMS2) add one battery meter each, using battery number 1 and 2.
</code_context>
<issue_to_address>
**issue (review_instructions):** Use consistent capitalization for the proper noun “Ethernet”.
Other template wording should use “Ethernet”, not “ethernet”; please update this sentence to match the established terminology.
<details>
<summary>Review instructions:</summary>
**Path patterns:** `templates/**/*.yaml`
**Instructions:**
Verify that the changes comply to the rules defined in templates/README.md. Also check consistence (wording) with other files inside templates directory.
[Edit this rule](https://app.sourcery.ai/accounts/185524/review-settings?activeTab=review-rules&rule=74ec55f5-149d-4827-9376-6dccef98d305&from_surface=github_bot&intent=review_rules)
</details>
</issue_to_address>Sourcery assessment
Needs a human reviewer. 1 finding to address first, and if the register mappings or write sequence are wrong, the inverter could be curtailed incorrectly or battery control could use the wrong battery pack, reducing production or changing device operation. Reverting stops future writes, but a setting already sent to the inverter may persist and require a subsequent update or manual reset.
Blocking findings: templates/definition/meter/kaco-nh3-hybrid.yaml:33
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
|
@hansenelectric can you please test? |
Thanks for the review. It's my first PR for EVCC (so trying my best). I noticed that the Without batterymode, users cannot:
This functionality was in my original commit. Was this intentional in the refactoring? (I understand this might need testing on Solplanet inverters — but it's working correctly with the Kaco variant using Modbus-RTU) Additionally, regarding the template name: The Kaco NH3 only supports Modbus-RTU |
|
From what saw 802:ChaSt is a read-only field? |
|
Needs the sunspec/read service from #33041 |
Solplanet ASW kH / KACO Blueplanet Hybrid NH3 (Modbus RTU)
Adds a meter template for the Solplanet ASW kH hybrid inverter, also sold as KACO Blueplanet Hybrid NH3 — both are listed as products on the template. Read via SunSpec over Modbus RTU (RS485) as
solplanet-hybrid-sunspec, covering grid, PV and battery usage.What it reads
W,TotWhImp,TotWhExp, per-phase currents/voltages/powerssunspec-maxacpower(120/702)WMaxLimPct/WMaxLimPctEna, with model 123 as fallbackW,SoC,WHRtg,SoCMin,SoCMax,SoCRsvMinThe platform ships with different tracker counts, so the number of MPP trackers is a parameter (
mppt, 2 or 3, default 3) and thecalc/addentries are generated from it. This matters because a missing model 160 block is not a soft failure — the SunSpec plugin resolves every point when it is created and aborts withsunspec model not found, so a hardcoded count would prevent smaller variants from starting at all.Register choices and structure follow the generic SunSpec templates (
sunspec-inverter,sunspec-hybrid-curtailable,sunspec-battery-control), so the device-specific part is just the Modbus slave ID default of 3.Battery
Everything comes from model 802, which describes the battery bank as a whole:
WHRtg(scaled Wh → kWh), min/max SoC fromSoCMin/SoCMax— taken from the nameplate instead of being configured a second timelimitsocwritesSoCRsvMin(min reserve percent), the mechanism used by the genericsunspec-battery-controltemplatebattery-power)An earlier revision exposed the two battery packs as separate meters via the model 714 DC ports. That was dropped: model 802 has a single fixed block per device, so every value except the per-port power is bank-level — two meters would each report the full bank capacity, and evcc sums capacities across battery meters. Model 803 would add per-string SoC, but no per-string capacity or SoC limits, so a genuine per-pack meter is not representable in SunSpec.
Renamed template
The existing
solplanet-modbustemplate is renamed tosolplanet-hybrid-vendor, so the two ways to talk to this hardware are named consistently: SunSpec versus the vendor-specific AISWEI register map. It carriescovers: ["solplanet-modbus"], so existing configurations keep working.Verified against
Open points
batterymodeswitch includingholdchargeinstead of the reserve-SoC path. Not used yet.solplanet-hybrid-vendorcovers the dedicated Modbus TCP port via the vendor-specific AISWEI register map.service:lookup (askostal-plenticore-gen2does viamodbus/read) would need a SunSpec service, which does not exist yet — separate change.