Skip to content

About

Matter bridge for a Solarman-compatible logger

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

solarman-matter

Exposes a solar inverter as a Matter device on your local network.

The inverter is read through its Solarman data logger, on your own network. There is no cloud account, no API key and no call quota: the bridge speaks to the logger directly, and keeps working when the internet does not.

Each inverter is published as a Solar Power device with a composed Electrical Sensor endpoint, so controllers such as Home Assistant show the generated power and the lifetime production without a custom integration.

Install

Get a .deb or a tarball from the releases page, for x86_64 or arm64. The binary is self-contained: no runtime, no node_modules, no files beside it.

sudo dpkg -i solarman-matter_0.1.0_linux_amd64.deb
solarman-matter
tar xf solarman-matter_Linux_x86_64.tar.gz
./solarman-matter

Requirements

  • A Solarman data logger on the same network as the bridge, the kind that ships with Deye, Sofar and similar string inverters.
  • Bun 1.4 or later, to run from source.

Setup

Find the logger on your network. It answers on port 8899, and its status page is on port 80. Give it a fixed address in your router, so it does not move.

Copy .env.example to .env and put the address in SOLARMAN_LOCAL_HOSTS.

bun install
bun start

Then open http://localhost:8080 for the pairing code.

The web page

The page shows the pairing code and what each inverter last reported: the power now, the production today and the lifetime total.

There is nothing to choose. You listed the inverters when you wrote their addresses in the configuration, so all of them are bridged.

Configuration

Variable Required Default Meaning
SOLARMAN_LOCAL_HOSTS yes Logger addresses, comma separated.
SOLARMAN_LOCAL_USER no admin Logger web login.
SOLARMAN_LOCAL_PASSWORD no admin Logger web password.
SOLARMAN_POLL_INTERVAL no 30 Seconds between reads.
SOLARMAN_WEB_PORT no 8080 Port of the web page.
SOLARMAN_STATE_FILE no next to Matter data Remembers the serial behind each address.
MATTER_PASSCODE no 20202021 Commissioning passcode.
MATTER_DISCRIMINATOR no 3840 Commissioning discriminator.
MATTER_PORT no 5540 Matter UDP port.

Every setting this bridge owns is prefixed, because bare names such as LOCAL_HOSTS collide with other tools. A real environment variable always wins over the .env file, so an old export can hide the file without a warning.

How it works

The logger speaks Solarman V5 on port 8899, which wraps Modbus RTU. The bridge asks it for holding registers 59 to 112, the telemetry block of the Deye string profile, and writes the values into Matter.

Register Matter attribute
80, 81 activePower
63, 64 cumulativeEnergyExported
73 voltage
76 activeCurrent
79 frequency

A plant exports energy, so the production feeds the exported side of the meter, not the imported one.

Register 60 holds the production of today. It resets each night, so it cannot feed a cumulative attribute; the page shows it, and Matter gets the lifetime total instead. Your controller can derive the day from that.

Only Modbus function 3, read holding registers, is ever sent. Nothing in the bridge can change a setting on the logger or the inverter.

Nights

The logger is powered by the inverter, which is powered by the sun, so it disappears every night. That is not a fault:

  • The Matter device stays, marked unreachable. A controller that dropped the device each evening would lose its history.
  • Everything measured at that instant is published as zero: the power, the voltage, the current and the frequency. An inverter whose logger is dark is generating nothing, and a controller that adds power up over time would turn the last watts of the day into a whole night of production that never happened.
  • The lifetime total is kept, because it is not measured at an instant. A total that fell to zero every evening would read as a meter that had been replaced.
  • The device is named after the inverter serial, not the address, so it survives a logger that DHCP moved. The serial is asked of the logger once and written to the state file.
  • A first run started after dark therefore has no serial to publish. The inverter appears at first light, and every run after that is immediate.

A logger that is unreachable in daylight, because of a network fault rather than the dark, is reported the same way. The readings then understate the plant until it answers again, which is the safer of the two mistakes.

Controllers

An inverter is a Solar Power device with an Electrical Sensor child endpoint. What a controller makes of that differs.

Home Assistant reads the electrical sensor and shows the power, the lifetime production, the voltage, the current and the frequency.

Apple Home needs iOS and tvOS 27 or later, and the hub decides, not the phone: an iPhone on 27 paired to an Apple TV on 26 still behaves like 26. Apple added the Electrical Sensor device type in 27, where it feeds the Home app energy tab. Before 27 it is not recognised at all, and the inverter shows as a generic tile with a single value.

Apple has no solar device type, in 27 or any earlier release, so the tile itself stays generic. Only the readings move to the right place.

State

The Matter fabric and node state live in ~/.matter/solarman-matter. The serial behind each address is in ~/.matter/solarman-matter-inverters.json.

Clearing the pairings

Remove the bridge in your controller first. That deletes the fabric on both sides.

If the controller entry is gone or stuck, factory reset the bridge. Stop it first: erasing the state under a running bridge leaves the old fabric in memory, and the pairing code does not come back. bun run reset refuses while the bridge runs.

bun run reset
bun start

The bridge then prints a new pairing code, on the page and in the log. Your controller keeps a dead entry for the old bridge, so remove it by hand.

Limits

  • Production only. Batteries, meters, grid import and household consumption are not exposed.
  • The first AC phase only. The registers carry three, and a single-phase inverter reports zero for the other two, which Matter cannot tell apart from a real zero.
  • No DC strings. The logger reports volts, amps and watts for each string, but the Matter electrical sensor describes an AC meter.
  • One Matter device per inverter. A plant with several is not added up.
  • The register map is the Deye string profile. Hybrid and battery inverters answer a different one and are untested.
  • The web page has no authentication. Keep it on a trusted network.
  • Apple Home shows the readings only from iOS and tvOS 27, and never labels the device as solar. See Controllers.

Development

bun start          # run from source
bun test src       # run the tests
bun run typecheck  # tsc --noEmit
bun run build      # compile a binary for this machine

Releases are built by GoReleaser with the Bun builder, which runs bun build --compile for linux-x64 and linux-arm64. Push a tag to release:

git tag -a v0.1.0 -m v0.1.0
git push origin v0.1.0

The web page is inlined in src/page.ts so the binary stays a single file. Edit it there.

Credits

The Solarman V5 client is the one from electrify, where it was checked against the Solarman cloud and reported the same values, to the digit.

About

Matter bridge for a Solarman-compatible logger

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages