earn-e-p1
Async Python library for communicating with EARN-E P1 energy meters via UDP.
The EARN-E P1 meter reads a smart meter's P1 port and broadcasts real-time energy data via UDP on the local network. This library listens for those broadcasts and provides parsed device data.
Installation
pip install earn-e-p1
Usage
Persistent listener
For long-running applications (e.g., Home Assistant integrations) that need continuous updates:
import asyncio
from earn_e_p1 import EarnEP1Listener, EarnEP1Device
def on_update(device: EarnEP1Device, raw: dict) -> None:
print(f"Power: {device.data.get('power_delivered')} kW")
print(f"Serial: {device.serial}")
async def main() -> None:
listener = EarnEP1Listener()
listener.register("192.168.1.100", callback=on_update)
await listener.start()
try:
await asyncio.sleep(3600) # listen for 1 hour
finally:
await listener.stop()
asyncio.run(main())
The listener supports multiple devices — call register() for each device IP. Packets are demultiplexed by source IP and each device maintains its own merged state.
Discover devices
Find EARN-E devices on the network:
from earn_e_p1 import discover
devices = await discover(timeout=10)
for device in devices:
print(f"Found {device.host} (serial: {device.serial})")
Validate a specific host
Check if a specific IP is an EARN-E device:
from earn_e_p1 import validate
device = await validate("192.168.1.100", timeout=10)
if device:
print(f"Confirmed: {device.serial}")
Discover/validate while a listener is running
If a listener is already active, use the instance methods to avoid port conflicts:
# Discover using the active socket
devices = await listener.discover(timeout=10)
# Validate using the active socket
device = await listener.validate("192.168.1.100", timeout=10)
Data Model
The callback receives two arguments:
device(EarnEP1Device) — accumulated device state with merged data from all packetsraw(dict) — the raw packet as received
@dataclass
class EarnEP1Device:
host: str # Device IP address
serial: str | None = None # Serial number (set once from first full telegram)
model: str | None = None # Device model
sw_version: str | None = None # Firmware version
data: dict[str, Any] = field(...) # Merged sensor data from all packets
seen_packet_types: set[PacketType] = field(...) # Packet types seen so far
The device sends two types of UDP broadcasts:
| Type | Keys | Frequency |
|---|---|---|
| Realtime | power_delivered, power_returned, voltage_l1, current_l1 (plus voltage_l2/l3, current_l2/l3 on 3-phase meters) |
~1s |
| Full telegram | energy_delivered_tariff1/2, energy_returned_tariff1/2, gas_delivered, wifiRSSI, serial, model, swVersion |
~1min |
The library merges all packets into device.data, so it always contains the latest value for every key.
Each type always carries every key the meter supports, so a 1-phase meter never sends voltage_l2/voltage_l3 and an electricity-only meter never sends gas_delivered. device.data_complete becomes True once a packet of every type has been seen. From then on device.data holds the meter's complete key set, and any key still missing is one this meter does not report.
License
MIT
Release files for earn-e-p1 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| earn_e_p1-0.3.0.tar.gz | 21.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| earn_e_p1-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 28.9 kB
Release files / earn_e_p1-0.3.0.tar.gz
| Download URL | earn_e_p1-0.3.0.tar.gz |
|---|---|
| Size | 21.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
cbf158067f7aa9ffb4faf0a3f38f1aac8df6ba27edaa565463b2a70189ebc98e
|
|
BLAKE2b-256 checksum How to use checksums |
6f88205d116e4ecc1baa2c8ce4c2cf94ad02de758107fac648bbae522235b6cb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.
Transparency logRelease files / earn_e_p1-0.3.0-py3-none-any.whl
| Download URL | earn_e_p1-0.3.0-py3-none-any.whl |
|---|---|
| Size | 7.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
40ca32edd1cd6b5570dee53012056e66ed58bcf0252e7cb951264d72e8f93f0c
|
|
BLAKE2b-256 checksum How to use checksums |
2bb6e8c58eb12fbd46df65927a5627c657286106593ccdb97218c95fb60754de
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 10, 2026.
Transparency log