[APP][Pro] Solis Hybrid Inverter (v0.1.56 - Test)

Solis Hybrid Inverter — local monitoring & control for Homey

Hi all :waving_hand:

I’ve been building a Homey app that talks directly to a Solis hybrid inverter over your local network — no cloud, no SolisCloud account, no internet dependency. It reads everything in real time over Modbus TCP, and lets Homey control charging, discharging, work mode and grid export.

What it does

Monitoring

Solar production, battery power & state of charge, grid power, home load, voltages, temperature and work mode
Three separate devices — Inverter, Battery and Grid — so the Homey Energy dashboard gets the right roles (production / home battery / grid import‑export)
A grid‑limiting indicator that tells you when the grid is throttling your production (e.g. volt‑watt overvoltage curtailment), instead of leaving you guessing why output dropped

Control

Force charge / discharge the battery, set work mode and reserve SOC (backup reserve)
Hold the battery straight from a Flow — a new Battery discharge blocked / allowed action stops the pack draining during cheap or medium price hours (the grid carries the house and the charge is kept), then releases it during the expensive peak so self‑use spends your stored energy exactly when it’s worth most. Solar can still top the battery up while discharge is blocked, and it needs no optimiser — any price app that can tell cheap from expensive drives it.
A “Limit solar output” switch you can flip from any Flow — e.g. throttle production when prices go negative — plus a separate set/clear grid‑export limit and a soft inverter on/off
Feed the app your whole‑home data: Report grid power (a P1 meter reading, + import / − export) and Report EV power, so it knows true house load and stays EV‑aware
Follow‑the‑sun triggers that recommend an EV charging current to soak up surplus solar
30 Flow cards in total (8 triggers, 5 conditions, 17 actions)

How it connects — a wired RS485 gateway

The app connects through a small wired RS485‑to‑Ethernet gateway on the inverter’s data‑logger (COM) port. I deliberately moved off the stock Solis WiFi stick — for real control it just doesn’t hold up (more on that below). With the wired gateway, Homey is the sole Modbus master: charge/discharge holds indefinitely, and nothing leaves your LAN. The manual has a full step‑by‑step wiring guide, with photos and a pinout.

▎ Only one Modbus master can talk to the inverter at a time, so don’t run a second controller against it in parallel.

Requirements & hardware

A Solis hybrid inverter + a wired RS485‑to‑Ethernet gateway with a Modbus TCP‑to‑RTU mode (e.g. Waveshare RS485 TO ETH), reachable on your LAN with a fixed IP
Homey Pro
Developed and tested on an S6‑EH3P10K2‑H with a Pylontech battery. Reports from other Solis hybrids very welcome

A few recipes in the manual

Negative‑price “don’t feed in” — absorb surplus into the battery, then stop exporting
Save the battery for expensive hours — hold its charge while power is cheap or mid‑priced, then let it cover the house only into the price peak, driven by any Homey price app (Tibber, Frank, EPEX…), no optimiser needed
True home consumption by combining a P1 meter with the inverter’s AC power

Status

Now in beta on the Test track. Reading is solid; grid‑charge and discharge are field‑proven. The remaining control writes are verified against Solis’s official register map but still being field‑tested — so keep an eye on your inverter after the first commands, and report anything odd.

:open_book: Manual: Solis Hybrid Inverter for Homey — User Manual
:backhand_index_pointing_right: Install (beta): Solis Hybrid Inverter | Homey

Unofficial community app — not affiliated with or endorsed by Solis / Ginlong. Feedback, testers and register reports from other models are hugely appreciated :folded_hands:

Design notes: why local Modbus, and why I ditched the WiFi stick

Decision 1 — Local Modbus, not the cloud. Solis offers a cloud API (SolisCloud). It’s the easy path: no wiring, works from anywhere. But for real‑time battery control it’s the wrong tool:

Latency and rate limits. Cloud round‑trips are seconds, and the API is throttled. A price optimiser that re‑evaluates the battery setpoint every few seconds simply can’t live on a cloud API.
Reliability. If your internet, Solis’s servers, or the API has a bad day, your battery control goes with it. I didn’t want my home energy strategy depending on someone else’s uptime.
Keeping it at home. The stock WiFi stick continuously reports to SolisCloud, which runs on the manufacturer’s servers overseas. That’s not a knock on Solis — it’s just not what we want for a home setup: our energy data and the control loop should stay on our own network. A local Modbus link keeps everything in the house.

So the app speaks Modbus TCP locally, on the LAN, with no cloud in the loop — reads and writes.

Decision 2 — Skip the Solis WiFi stick (the “data logger”). The stick plugs into the COM port and pushes data to SolisCloud, and it can also expose Modbus locally — so the tempting option was to just talk Modbus to the stick and leave everything as‑is. I tried that first. It doesn’t hold up for control:

It’s a single Modbus “slot.” It’s really there to serve SolisCloud and only lets one client talk at a time, so you’re constantly contending with its own cloud traffic.
It reverts to the cloud. In practice the stick periodically flips back to its SolisCloud MQTT job and wedges local writes after ~13 minutes. Invisible for monitoring; fatal for a control loop that needs to hold a battery setpoint — the inverter would silently drift back to self‑use mid‑dispatch.
No persistent session. The inverter’s real‑time dispatch (forced charge/discharge) is guarded by a watchdog and drops the moment the control socket closes. The stick’s behaviour made a stable, held‑open session impossible.

The fix: a wired RS485‑to‑Ethernet gateway. I pulled the WiFi stick and wired a small Waveshare RS485‑TO‑ETH adapter straight onto the inverter’s COM/RS485 port, running it as a transparent Modbus TCP↔RTU gateway. Now:

Homey is the sole Modbus master — no cloud, no stick, no second controller fighting for the bus.
The ~13‑minute ceiling is gone — local charge/discharge holds indefinitely (proven with 25 minutes of steady 5 kW dispatch, and in daily use since).
A persistent socket stays open during control holds, so the dispatch watchdog stays happy.
Nothing leaves the LAN — with the stick gone, the inverter no longer phones home at all; the whole loop is local by construction.

The trade‑offs I accepted (fair to be upfront):

You give up (or wire around) SolisCloud. With the stick removed, the Solis phone app / cloud monitoring goes away unless you re‑add a logger elsewhere. For me, Homey is the monitoring and control surface now — a feature, not a loss.
It’s a hardware change. You’re wiring an adapter into the inverter’s COM port — a bit of DIY, and something to weigh re: warranty/support with your installer.
Single‑master discipline. Because only one thing can be Modbus master, the app serialises every request onto one connection. You can’t also run, say, a separate Home Assistant Modbus poller against the same inverter — pick one master.

A couple of Solis‑specific quirks had to be handled in code (reads must be small contiguous blocks; the “enable dispatch” register has to be the very last write, or a companion write resets it). Nothing exotic, but it’s why direct Modbus is more than “just point at the port.”

Why it was worth it. The payoff is a fully local, cloud‑independent control loop that reliably drives the battery — charge on cheap/solar‑surplus power, discharge into the evening price peak — and keeps driving it without timing out or fighting the cloud. That reliability is the whole foundation the price optimiser is built on, and none of it would be trustworthy on the WiFi stick. Local Modbus over a wired RS485 gateway, with Homey as the only master, beats the convenient stick/cloud path for anything involving real control — you trade a bit of wiring and the stock cloud app for a rock‑solid, private, indefinite control channel that stays entirely on your own network.

:bell: What’s new

Latest

Hold the battery from a Flow — a new Battery discharge blocked / allowed action. Block it during cheap or medium price hours so the grid carries the house and the pack keeps its charge; allow it during the expensive peak so self‑use spends the battery on the house. Solar still charges it while blocked, and it needs no optimiser — any Homey price app that knows cheap from expensive drives it. Perfect for “keep my battery until prices are high.”

Earlier highlights (v0.1.40)

Charging & grid protection

Smarter solar‑surplus charging. When topping the battery up from excess solar, the app now trims the charge to hold your true grid at ~0 — it won’t pull from the grid to charge, and it won’t starve your PV. Previously it could quietly import a kW or so while “charging from solar.”
New grid‑protection guard. Set your main‑fuse rating (phases + amps per phase) in the device settings, and the app caps a battery grid‑charge so the battery and a simultaneously‑charging EV can’t together exceed your connection and trip the main breaker. Real‑time, battery‑side, re‑evaluated continuously.
Battery‑hold. When the pack is near‑full and not in a planned discharge, the app stops native self‑use from draining it for small/cheap loads — the grid covers those and the pack stays ready.
SOC floor. A hard minimum state‑of‑charge you set; the battery is never discharged below it.
Reserved SOC in settings (new in v0.1.40). You can now set the battery’s reserved charge (backup reserve) straight from the device settings, alongside the existing Flow action.

New Flow inputs

Report grid power — feed a whole‑home P1 meter reading (+ import / − export) so the app knows true house load for self‑consumption and the grid guard.
Report EV power — feed your EV charger’s power so the app is EV‑aware (keeps the EV out of the house‑load maths and inside the grid guard).

Reliability

Control dispatch now holds indefinitely over the wired RS485 gateway (the old ~13‑minute drop is gone).
Various control‑stability fixes.

Register reports from other Solis hybrid models are very welcome :folded_hands:

:bell: What’s new

Latest

Hold the battery from a Flow — a new Battery discharge blocked / allowed action. Block it during cheap or medium price hours so the grid carries the house and the pack keeps its charge; allow it during the expensive peak so self‑use spends the battery on the house. Solar still charges it while blocked, and it needs no optimiser — any Homey price app that knows cheap from expensive drives it. Perfect for “keep my battery until prices are high.”

Earlier highlights (v0.1.40)

Charging & grid protection

Smarter solar‑surplus charging. When topping the battery up from excess solar, the app now trims the charge to hold your true grid at ~0 — it won’t pull from the grid to charge, and it won’t starve your PV. Previously it could quietly import a kW or so while “charging from solar.”
New grid‑protection guard. Set your main‑fuse rating (phases + amps per phase) in the device settings, and the app caps a battery grid‑charge so the battery and a simultaneously‑charging EV can’t together exceed your connection and trip the main breaker. Real‑time, battery‑side, re‑evaluated continuously.
Battery‑hold. When the pack is near‑full and not in a planned discharge, the app stops native self‑use from draining it for small/cheap loads — the grid covers those and the pack stays ready.
SOC floor. A hard minimum state‑of‑charge you set; the battery is never discharged below it.
Reserved SOC in settings (new in v0.1.40). You can now set the battery’s reserved charge (backup reserve) straight from the device settings, alongside the existing Flow action.

New Flow inputs

Report grid power — feed a whole‑home P1 meter reading (+ import / − export) so the app knows true house load for self‑consumption and the grid guard.
Report EV power — feed your EV charger’s power so the app is EV‑aware (keeps the EV out of the house‑load maths and inside the grid guard).

Reliability

Control dispatch now holds indefinitely over the wired RS485 gateway (the old ~13‑minute drop is gone).
Latency and rate limits. Cloud round‑trips are seconds, and the API is throttled. A price optimiser that re‑evaluates the battery setpoint every few seconds simply can’t live on a cloud API.
Reliability. If your internet, Solis’s servers, or the API has a bad day, your battery control goes with it. I didn’t want my home energy strategy depending on someone else’s uptime.
Keeping it at home. The stock WiFi stick continuously reports to SolisCloud, which runs on the manufacturer’s servers overseas. That’s not a knock on Solis — it’s just not what we want for a home setup: our energy data and the control loop should stay on our own network. A local Modbus link keeps everything in the house.

So the app speaks Modbus TCP locally, on the LAN, with no cloud in the loop — reads and writes.

Decision 2 — Skip the Solis WiFi stick (the “data logger”). The stick plugs into the COM port and pushes data to SolisCloud, and it can also expose Modbus locally — so the tempting option was to just talk Modbus to the stick and leave everything as‑is. I tried that first. It doesn’t hold up for control:

It’s a single Modbus “slot.” It’s really there to serve SolisCloud and only lets one client talk at a time, so you’re constantly contending with its own cloud traffic.
It reverts to the cloud. In practice the stick periodically flips back to its SolisCloud MQTT job and wedges local writes after ~13 minutes. Invisible for monitoring; fatal for a control loop that needs to hold a battery setpoint — the inverter would silently drift back to self‑use mid‑dispatch.
No persistent session. The inverter’s real‑time dispatch (forced charge/discharge) is guarded by a watchdog and drops the moment the control socket closes. The stick’s behaviour made a stable, held‑open session impossible.

The fix: a wired RS485‑to‑Ethernet gateway. I pulled the WiFi stick and wired a small Waveshare RS485‑TO‑ETH adapter straight onto the inverter’s COM/RS485 port, running it as a transparent Modbus TCP↔RTU gateway. Now:

Homey is the sole Modbus master — no cloud, no stick, no second controller fighting for the bus.
The ~13‑minute ceiling is gone — local charge/discharge holds indefinitely (proven with 25 minutes of steady 5 kW dispatch, and in daily use since).
A persistent socket stays open during control holds, so the dispatch watchdog stays happy.
Nothing leaves the LAN — with the stick gone, the inverter no longer phones home at all; the whole loop is local by construction.

The trade‑offs I accepted (fair to be upfront):

You give up (or wire around) SolisCloud. With the stick removed, the Solis phone app / cloud monitoring goes away unless you re‑add a logger elsewhere. For me, Homey is the monitoring and control surface now — a feature, not a loss.
It’s a hardware change. You’re wiring an adapter into the inverter’s COM port — a bit of DIY, and something to weigh re: warranty/support with your installer.
Single‑master discipline. Because only one thing can be Modbus master, the app serialises every request onto one connection. You can’t also run, say, a separate Home Assistant Modbus poller against the same inverter — pick one master.

A couple of Solis‑specific quirks had to be handled in code (reads must be small contiguous blocks; the “enable dispatch” register has to be the very last write, or a companion write resets it). Nothing exotic, but it’s why direct Modbus is more than “just point at the port.”

Hi Remco,

Nice initiative!

Might be very obvious, but I assume it doesn’t work with a cheap-ass datalogger like the S3-WIFI-ST ?

An S2-WL-ST model is most probably the one and only suitable datalogger for use with Modbus TCP connections?

I think it should work as well. The fundamental part is that the Modbus to TCP can only work with one client, so if you disable that client (your EMS probably) Homey can take over. There is a safety switch in the settings of the app currently to prevent writing, but in the end you would need that, as Homey will be the only possible client when activated. And I guess control would be needed.
I started this little project as have received an EMS from NZU (Nederlandse zonnepanelen unie) and I would like more control. So developing against a physical setup, but can be used with other types and setups.

You would want to figure out the IP address of the datalogger.

Best regards,

Remco

Thanks, IP address is known.
I would have to disable the cloud connection, no other devices connected.
I’ll give it a go.

actually, I believe the TCP Modbus just overrules the cloud connection. So it might not even be necessary to disable it. So after the Modbus has cleared again the cloud connection should start back working. I can’t check myself as I have no cloud account.

It only allows connections to port 80. Tried several unit ID’s as well (0, 1, 2, 10 etc).

I’ve disconnected every cloud connection I could think of.

Found a datalogger setting to increase the max. nº of simultaneous connections, I’ve set it to 6. Dunno if that has any influence

could you check if port 8899 is open?

nc -vz [ip of stick] 8899

so:

nc -vz 192.x.x.x 8899

this is some other protocol I can port maybe.

Hi Remco

Solis Modbus TCP/IP only works via the S2-WL-ST datalogger. Modbus TCP/IP does not work with other models. Not even with a firmware update.

As long as a Modbus connection is open, the cloud connection does not work. If you disconnect the Modbus connection, data is sent to the Solis cloud again.

ID 1 is the default. You can assign a different ID to an inverter if you have multiple inverters on one datalogger. You need a special cable for this, but it is more expensive than another datalogger. So, for two inverters, it is not worthwhile.

Hello Remco,

Thank you for this great app!

I have 1 question

Is it possible to see at what % the reserve Soc is set in the dashboard? I can’t find it

Hi Mickey,

To be honest I have evolved the app quite drastically:

When I set out to let Homey not just read my Solis S6 hybrid but actually control it (battery charge/discharge for price-based optimisation), I hit a fork in the road pretty quickly. Here are the choices we had to make and why.

Decision 1 — Local Modbus, not the cloud

Solis offers a cloud API (SolisCloud). It’s the easy path: no wiring, works from anywhere. But for real-time battery control it’s the wrong tool:

  • Latency and rate limits. Cloud round-trips are seconds, and the API is throttled. A price optimiser that re-evaluates the battery setpoint every few seconds simply can’t live on a cloud API.
  • Reliability. If your internet, Solis’s servers, or the API has a bad day, your battery control goes with it. I didn’t want my home energy strategy depending on someone else’s uptime.
  • Keeping it at home. The stock WiFi stick continuously reports to SolisCloud, which runs on the manufacturer’s servers overseas. That’s not meant as a knock on Solis — it’s simply not what we’re after for a home setup: we’d prefer our energy data and the control loop to stay on our own network rather than travel to a cloud abroad. A local Modbus link keeps everything in the house.

So the app speaks Modbus TCP locally, on the LAN, with no cloud in the loop. Reads and writes.

Decision 2 — Skip the Solis WiFi stick (the “data logger”)

This is the less obvious one. The Solis inverter ships with a WiFi “stick” (the data logger) that plugs into the COM port and pushes data to SolisCloud. It can also expose Modbus locally — so the tempting option was to just talk Modbus to the stick and leave everything as-is.

I tried that first. It doesn’t hold up for control:

  • The stick is a single Modbus “slot.” It’s really there to serve SolisCloud, and it only lets one client talk at a time. So you’re constantly contending with the stick’s own cloud traffic.
  • It reverts to the cloud. In practice the stick periodically flips back to its SolisCloud MQTT job and wedges local writes after ~13 minutes. For monitoring that’s invisible; for a control loop that needs to hold a battery setpoint, it’s fatal — the inverter would silently drift back to self-use mid-dispatch.
  • No persistent session. The inverter’s real-time dispatch (forced charge/discharge) is guarded by a watchdog and drops the moment the control socket closes. The stick’s behaviour made a stable, held-open session impossible.

The solution: a wired RS485-to-Ethernet gateway. I pulled the WiFi stick and wired a small Waveshare RS485-TO-ETH adapter straight onto the inverter’s COM/RS485 port, running it as a transparent Modbus TCP↔RTU gateway. Now:

  • Homey is the sole Modbus master. Nothing else — no cloud, no stick, no second controller — is fighting for the bus.
  • The ~13-minute ceiling is gone. Local charge/discharge now holds indefinitely (proven with 25 minutes of steady 5 kW dispatch, and in daily use since).
  • A persistent socket stays open during control holds, so the inverter’s dispatch watchdog stays happy.
  • Nothing leaves the LAN. As a bonus, with the stick gone the inverter no longer phones home at all — the whole loop is local by construction.

The trade-offs we accepted

This isn’t free, and it’s fair to be upfront:

  • You give up (or wire around) SolisCloud. With the stick removed, the Solis phone app / cloud monitoring goes away unless you re-add a logger elsewhere. For me, Homey is the monitoring and control surface now, so that’s a feature, not a loss.
  • It’s a hardware change. You’re wiring an adapter into the inverter’s COM port — a bit of DIY, and something to consider re: warranty/support with your installer.
  • Single-master discipline. Because only one thing can be Modbus master, the app is careful to serialise every request onto one connection. You can’t also run, say, a separate Home Assistant Modbus poller against the same inverter at the same time — pick one master.
  • A couple of Solis-specific quirks had to be handled in code (e.g. reads must be small contiguous blocks, and the “enable dispatch” register has to be the very last write, or a companion write resets it). Nothing exotic, but it’s why direct Modbus is more than “just point at the port.”

Why it was worth it

The payoff is a fully local, cloud-independent control loop that can reliably drive the battery — charge on cheap/solar-surplus power, discharge into the evening price peak — and keep driving it without timing out or fighting the cloud. That reliability is the whole foundation the price optimiser is built on. None of it would be trustworthy on the WiFi stick.

Local Modbus over a wired RS485 gateway, with Homey as the only master, beats the convenient WiFi-stick/cloud path for anything involving real control — you trade a bit of wiring and the stock cloud app for a rock-solid, private, indefinite control channel that stays entirely on your own network.