Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Basic Homie device that publishes sensor data (temperature, humidity, air pressu

### simple-tree-device

A parent/child device TREE over one MQTT connection: a root `distribution-enclosure` (`panel-1`) with circuit and BESS children and a MID grandchild, all sharing the root's single connection. It shows building the tree inside one `with root.state_transition():` (so the root publishes one INIT->READY for the whole tree, not one per child), a settable property on a child whose `/set` routes back over the shared connection, and the per-device topics each tree node publishes under. Reach for this over `simple-device` when you need to model a device that contains sub-devices. `--check` builds the tree, logs its structure, and exits (it works even with the broker down, since connect is asynchronous).
A parent/child device TREE over one MQTT connection: a root `distribution-enclosure` (`panel-1`) with circuit and BESS children and a MID grandchild, all sharing the root's single connection. It shows building the tree inside one `with root.state_transition():` (so the root publishes one INIT->READY for the whole tree, not one per child), a settable property on a child whose `/set` routes back over the shared connection, and the per-device topics each tree node publishes under. Reach for this over `simple-device` when you need to model a device that contains sub-devices. `--check` builds the tree, logs the root and its direct children, and exits (it works even with the broker down, since connect is asynchronous).

```bash
./simple-tree-device --config /path/to/broker-cfg.json
Expand All @@ -23,7 +23,7 @@ A parent/child device TREE over one MQTT connection: a root `distribution-enclos

### utility-meter

Publishes a single eBus utility-meter device (`energy.ebus.device.utility-meter`, per the Electrification Bus `data-models/utility-meter.md`, v0.3) with the data model's capabilities: the required `info` / `meter` / `status` plus the optional `grid` / `doe` / `price` / `demand` / `power-quality` a meter publishes when it has the signal. The `doe` and `price` capabilities are `json` properties (`doe/import-limit`/`export-limit`, `price/import-price`/`export-price`), each a JSON array of time-windowed objects that advertises its schema as a `$format` JSONSchema; enum properties advertise their allowed values via `$format`. A local HTTP endpoint stands in for the utility's out-of-band backhaul for runtime doe/price updates, validating each posted body against the property's `$format` before publish (install the `validation` extra to enable it: `pip install 'ebus-sdk[validation]'`).
Publishes a single eBus utility-meter device (`energy.ebus.device.utility-meter`, per the Electrification Bus `devices/utility-meter.md`, written against v0.3 of that data model) with the data model's capabilities: the required `info` / `meter` / `status` plus the optional `grid` / `doe` / `price` / `demand` / `power-quality` a meter publishes when it has the signal. The `doe` and `price` capabilities are `json` properties (`doe/import-limit`/`export-limit`, `price/import-price`/`export-price`), each a JSON array of time-windowed objects that advertises its schema as a `$format` JSONSchema; enum properties advertise their allowed values via `$format`. A local HTTP endpoint stands in for the utility's out-of-band backhaul for runtime doe/price updates, validating each posted body against the property's `$format` before publish (install the `validation` extra to enable it: `pip install 'ebus-sdk[validation]'`).

```bash
./utility-meter --config ./utility-meter-cfg.example.json --broker-config /path/to/broker-cfg.json
Expand Down Expand Up @@ -105,15 +105,17 @@ Bridges eBus/Homie devices to Home Assistant MQTT discovery (the reverse of the
./ha-discovery-bridge --keep-running # leave it up for a real HA to consume
```

No broker handy? A throwaway local one works: `mosquitto -c <(printf 'listener 1883 127.0.0.1\nallow_anonymous true\n')`, then run with no `--config`.
No broker handy? A throwaway local one works: `printf 'listener 1883 127.0.0.1\nallow_anonymous true\n' > /tmp/mosquitto.conf && mosquitto -c /tmp/mosquitto.conf`, then run with no `--config`. (mosquitto 2.x refuses a process-substitution path such as `-c <(...)`.)

## Configuration

All examples accept broker configuration via:
`simple-device`, `simple-tree-device`, `simple-controller`, and `ha-discovery-bridge` accept broker configuration via:

1. **Command line**: `--config /path/to/broker-cfg.json`
2. **Environment variable**: `EBUS_BROKER_CFG=/path/to/broker-cfg.json`

`utility-meter` takes the broker config as `-b` / `--broker-config` (its `--config` is the meter config), also defaulting to `EBUS_BROKER_CFG`. `simple-span-controller` builds its own config from the panel serial number, password, and mDNS.

### Broker Config Format

```json
Expand Down
2 changes: 1 addition & 1 deletion examples/ha-discovery-bridge
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
"""Bridge eBus/Homie devices to Home Assistant MQTT discovery (SDK-dn4).
"""Bridge eBus/Homie devices to Home Assistant MQTT discovery.

End-to-end demonstration and self-check for `ebus_sdk.ha.HaDiscoveryBridge`,
against a REAL broker but WITHOUT needing a running Home Assistant. It:
Expand Down
4 changes: 3 additions & 1 deletion examples/simple-tree-device
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,9 @@ def build_tree(mqtt_cfg: dict, logger: logging.Logger) -> homie.Device:
def main() -> None:
parser = argparse.ArgumentParser(description="Example parent/child Homie device tree")
parser.add_argument("-c", "--config", help="Path to broker config JSON (or set EBUS_BROKER_CFG env var)")
parser.add_argument("--check", action="store_true", help="Build the tree, log its structure, and exit")
parser.add_argument(
"--check", action="store_true", help="Build the tree, log the root and its direct children, and exit"
)
args = parser.parse_args()

config_file = args.config or os.environ.get("EBUS_BROKER_CFG")
Expand Down
21 changes: 12 additions & 9 deletions examples/utility-meter
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
utility-meter — eBus utility-meter publisher reference implementation.

Publishes a single eBus utility-meter device
(`energy.ebus.device.utility-meter`, per `data-models/utility-meter.md`
in the Electrification Bus specification, v0.3) to an MQTT broker, exposing
(`energy.ebus.device.utility-meter`, per `devices/utility-meter.md` in the
Electrification Bus specification, written against v0.3 of that data model)
to an MQTT broker, exposing
the data model's capabilities: the required `info`, `meter`, and `status`,
plus the optional `grid`, `doe`, `price`, `demand`, and `power-quality` a
meter publishes when it has the signal. The `doe` and `price` json properties
Expand Down Expand Up @@ -38,7 +39,7 @@ Meter measurements (`meter/active-power`, etc.) are synthesised from a config
file — this is a publisher reference, not a metrology device.

Usage:
./utility-meter --config /path/to/meter-cfg.json
./utility-meter --config /path/to/meter-cfg.json --broker-config /path/to/broker-cfg.json

See `utility-meter-cfg.example.json` for the config schema.
"""
Expand Down Expand Up @@ -70,7 +71,7 @@ DEFAULT_BROKER_CFG_ENV = "EBUS_BROKER_CFG"
# eBus utility-meter device type per the data model.
DEVICE_TYPE = "energy.ebus.device.utility-meter"

# Capability node types (the eBus utility-meter data model, v0.3: three MUST
# Capability node types (devices/utility-meter.md, v0.3: three MUST
# capabilities plus five optional ones a meter publishes when it has the signal).
CAPABILITY_INFO = "energy.ebus.capability.info"
CAPABILITY_METER = "energy.ebus.capability.meter"
Expand Down Expand Up @@ -156,9 +157,10 @@ class UtilityMeter:
Knows nothing about MQTT — the adapter below translates this state to
Homie/eBus topics.

Values change via `set_doe_*` methods (driven by the HTTP DOE endpoint)
and via `tick()` (driven by a periodic thread that simulates meter
measurement updates). Subscribers register callbacks via
Values change via `set_doe_*` methods (driven by the HTTP DOE endpoint).
A periodic thread also calls `tick()`, which is an unimplemented stub, so
meter measurements stay at their configured values. Subscribers register
callbacks via
`add_property_on_change_callback`.
"""

Expand Down Expand Up @@ -433,7 +435,8 @@ class UtilityMeterAdapter:
Translates a UtilityMeter to a Homie 5 device on the eBus broker.

Creates one root device of type `energy.ebus.device.utility-meter` with
four capability nodes (`info`, `meter`, `status`, `doe`). Each Homie
eight capability nodes (`info`, `meter`, `status`, `grid`, `doe`, `price`,
`demand`, `power-quality`). Each Homie
property is mirrored from the corresponding UtilityMeter property via a
callback.
"""
Expand Down Expand Up @@ -778,7 +781,7 @@ def main():
"--tick-interval",
type=float,
default=5.0,
help="Synthetic-update interval seconds (default: 5.0).",
help="Interval in seconds for tick(), currently an unimplemented stub (default: 5.0).",
)
args = parser.parse_args()

Expand Down
Loading