sma2mqtt discovers SMA solar devices on a local network, decodes Sunny Home Manager and inverter data, and publishes normalized values to MQTT. It combines multicast discovery, HTTP device bootstrap, SMA Speedwire/UDP polling, bundled object metadata, and configurable publication throttling.
SMALighthousejoins the configured SMA multicast group and periodically sends discovery packets.- Each discovered address is represented by an
SMADeviceactor. - A device first attempts HTTPS/HTTP bootstrap to learn its name, object metadata, translations, and supported object IDs.
- Inverters are polled over SMA UDP; Sunny Home Manager OBIS announcements are decoded directly from multicast.
- Values are normalized and published below the configured MQTT base topic.
HTTP bootstrap failure does not stop UDP discovery. Bundled metadata and translations provide a fallback when device-specific resources cannot be loaded.
- Swift 6.3 or later for source builds
- macOS 15 or iOS 18 for the declared Apple library platforms, or Linux through the container build
- Network reachability to the SMA devices and MQTT broker
- SMA multicast access, by default
239.12.255.254:9522
Multicast is local-network scoped. Container networking must expose the relevant interface and UDP traffic; a default bridged network often cannot receive LAN multicast without additional configuration.
The GitHub Container Registry workflow publishes linux/amd64 and linux/arm64 images:
latestandmainfrommain;developmentfrom the development branch/tag and development prerelease tags;betafrom beta tags/prereleases;- semantic-version tags such as
3.3.1from matching Git tags.
Attach the container to a network that can reach the SMA multicast group and the broker:
docker run --rm \
--name sma2mqtt \
--network host \
--env INVERTER_PASSWORD \
ghcr.io/jollyjinx/sma2mqtt:latest \
sma2mqtt \
--mqtt-servername 127.0.0.1 \
--basetopic smaSet INVERTER_PASSWORD in the environment before running. --network host is a typical Linux setup; select an equivalent network appropriate for Docker Desktop, Apple’s container CLI, or a dedicated VLAN.
To build locally:
docker build . --file sma2mqtt.product.dockerfile --tag sma2mqtt
docker run --rm --network host --env INVERTER_PASSWORD sma2mqttThe image defines sma2mqtt as its default command rather than as an entrypoint. If you append options after the image name, repeat the executable name first, as in the registry example above.
swift build
swift run sma2mqtt --help
swift run sma2mqtt \
--mqtt-servername mqtt \
--basetopic smaRelease builds default to log level notice and base topic sma/. Debug builds default to debug and example/sma/. A trailing slash in the supplied base topic is normalized.
Run sma2mqtt --help for the authoritative option list. Important settings include:
| Option | Default | Purpose |
|---|---|---|
--mqtt-servername |
mqtt |
MQTT broker hostname |
--mqtt-port |
1883 |
MQTT broker port |
--mqtt-username |
mqtt |
MQTT username |
--basetopic |
sma/ in release |
Prefix for published topics |
--emit-interval |
1.0 seconds |
Minimum interval between publications for one topic |
--mqtt-unchanged-publish-interval |
15.0 seconds |
Heartbeat interval for unchanged non-retained values; 0 republishes after each emit interval |
--bind-address |
0.0.0.0 |
Local interface address used for SMA UDP sockets |
--mcast-address |
239.12.255.254 |
SMA multicast group |
--mcast-port |
9522 |
SMA multicast receive/send port |
--interesting-paths-and-values |
Selected power, yield, battery paths | Repeated path:seconds query selections |
--json-output |
off | Also print publication envelopes as JSON lines to stdout |
The inverter password resolves in this order:
--inverter-passwordINVERTER_PASSWORD0000
Prefer the environment variable for deployments so the password is not exposed in a process argument.
Pass --interesting-paths-and-values repeatedly with path:interval values. The interval controls how often that logical path is queried, in seconds. To discover all paths supported by a device, use a broad selection such as:
swift run sma2mqtt --interesting-paths-and-values '*:600'Device-specific HTTP metadata can promote a better object ID for a path while retaining UDP fallback IDs for devices that expose a different mapping.
- Changed values publish after the minimum emit interval.
- Unchanged, non-retained values publish as a heartbeat after the unchanged interval.
- Unchanged retained values remain suppressed because the broker already stores them.
- A reconnect resets publication history so current retained values can be sent again.
- Topics observed with multi-value array payloads retain their array shape on later single-value updates.
--json-output mirrors accepted publications to stdout; it does not disable MQTT delivery.
SIGUSR1cycles log levelsdebug -> trace -> info -> debugand then dumps lighthouse state.SIGUSR2dumps lighthouse and device state without changing the level.
For example:
kill -USR2 "$(pgrep -x sma2mqtt)"--mqtt-passwordis parsed, but the currentMQTTPublisherdiscards it and configures an empty broker password. Password-authenticated MQTT is therefore not supported by this revision.--bind-portis parsed, butSMALighthousecurrently ignores it and listens on--mcast-port.- Multicast, live inverter login, and MQTT delivery require environment-specific integration testing; the default tests do not contact hardware or a broker.
- The Docker build resolves the newest dependency versions allowed by
Package.swiftbecause it does not copy a lockfile. Container and local dependency graphs can therefore differ. build.shis a host-specific legacy launcher with an inline password placeholder, Docker Hub image name, and dedicatedservice16network. Review it before use; prefer explicit deployment configuration.
swift package dump-package
swift build
swift test
swift build -c release --product sma2mqttThe default suite covers packet decoding/generation, object metadata, query fallback behavior, MQTT publication gating, payload shape stability, password precedence, and signal-level cycling. Live-device tests are opt-in:
SMA_INTEGRATION_TESTS=1 swift test
swift test -- --pcap-file /path/to/fixture.pcapOnly enable integration tests on a network containing the expected SMA devices. See AI/ARCHITECTURE.md and AI/OPERATIONS.md before changing runtime behavior. The reverse-engineering notes in SMA Protocol.md are observational and may be incomplete.
ghcrupload.sh publishes one tag for the local architecture using Apple’s container CLI, or a joined amd64/arm64 image with --all-arch and Docker Buildx. It reads the GHCR token from a macOS Keychain item; see the script header and --help before use. Publishing changes external state and is not part of ordinary validation.
sma2mqtt is available under the MIT License.
