Metadata-Version: 2.4
Name: apsystems2mqtt
Version: 0.1.0
Summary: Exports data from the local API of APsystems EZ1-M inverters to MQTT
Author: Manuel Stocker
Author-email: Manuel Stocker <mensi@mensi.ch>
License-Expression: Apache-2.0
License-File: LICENSE
Requires-Dist: apsystems-ez1>=2.1.0
Requires-Dist: click>=8.1
Requires-Dist: paho-mqtt>=2.1
Requires-Python: >=3.12
Project-URL: Homepage, https://github.com/mensi/apsystems2mqtt
Description-Content-Type: text/markdown

# apsystems2mqtt

Reads output metrics, operating state, and alarms from an APsystems EZ1-M
microinverter's local REST API and publishes them to MQTT periodically.
Optionally subscribes to a topic to control the inverter's max power limit.

## Usage

```
uv run apsystems2mqtt run --inverter_host 192.168.1.50 --mqtt_hostname mqtt.local
```

Published topics (under `--topic_prefix`, default `apsystems2mqtt`):

- `<prefix>/output` - power/energy readings (`p1`, `e1`, `te1`, `p2`, `e2`, `te2`, totals)
- `<prefix>/state` - `{"online": bool, "powered_on": bool}` (`powered_on` omitted while offline)
- `<prefix>/alarm` - off-grid and short-circuit alarm flags

The inverter powers itself off at night when there's no sunlight, and stops
responding to requests. This is expected: the CLI publishes `{"online":
false}` to `<prefix>/state` and keeps retrying on every poll, but only logs a
warning the first time it goes offline and then once every 6 hours while it
stays offline, followed by a single info log once it comes back.

With `--enable_power_control`, the CLI also subscribes to
`<prefix>/max_power/set` (plain integer watts payload) and applies the value
to the inverter:

- Values below the inverter's minimum (30W) turn the inverter off instead,
  since the device doesn't support setting a limit that low.
- Values at or above the minimum turn the inverter on (if it wasn't already)
  and set the limit, publishing the confirmed value to `<prefix>/max_power`.
- Since each change is written to the inverter's flash, applies are
  debounced: at most one apply every `--max_power_update_interval` seconds
  (default 300), using the most recently received value, and skipped
  entirely if it's unchanged from what was last applied.
- With `--max_power_limit`, every requested limit is capped to that many
  watts before being applied - useful when the grid operator or local
  regulations cap allowed output below the device's own max_power (800W).
  This also lowers the Home Assistant `number` entity's slider max, when
  `--homeassistant` is used.
- At startup, and again whenever the inverter comes back online after being
  offline, the CLI reads back the inverter's currently configured max power
  (`getMaxPower`) and publishes it to `<prefix>/max_power` - so consumers
  like Home Assistant's `number` entity show the actual current value
  instead of "Unknown" before the first change is made through this
  application.

With `--homeassistant --homeassistant_device_id <id>`, the CLI publishes
[Home Assistant MQTT discovery](https://www.home-assistant.io/integrations/mqtt/#mqtt-discovery)
config for the inverter's output/energy readings and alarms as `sensor`/
`binary_sensor` entities, all pointing back at the existing `<prefix>/output`
and `<prefix>/alarm` topics via `value_template` - no new telemetry topics are
introduced. Entity availability is tied to `<prefix>/state`'s `online` flag,
so entities go unavailable in Home Assistant whenever the inverter is
offline. If `--enable_power_control` is also set, a `number` entity (power
limit) and a `switch` entity (on/off) are added as well, both writing to the
existing `<prefix>/max_power/set` topic - the switch's `ON`/`OFF` payloads
are translated to the last non-zero limit seen (or the inverter's max power
if none yet) and `0` respectively. Discovery configs are published (retained)
each time the CLI connects to the broker. Use `--homeassistant_prefix` to
override Home Assistant's discovery topic prefix (default `homeassistant`).

To remove previously published discovery entities from Home Assistant, run
`uv run apsystems2mqtt clear-homeassistant` with the same
`--topic_prefix`/`--enable_power_control`/`--homeassistant_device_id`/
`--homeassistant_prefix` values used with `run` - it publishes an empty,
retained message to each discovery config topic and exits.

Run `uv run apsystems2mqtt run --help` for all options, or
`uv run apsystems2mqtt generate-systemd` (with the same flags as `run`) to
print a systemd unit file for deployment.

## Development

The project uses `uv`. Tests can for example be run with:

```
uv run pytest
```
