generated from rmcguire/go-server-with-otel
80 lines
3.4 KiB
Markdown
80 lines
3.4 KiB
Markdown
# econet-exporter 🔥💧
|
|
|
|
An exporter for **Rheem EcoNet / Rheemcloud** water-heater data. It polls the
|
|
Rheem cloud REST API (ClearBlade backend) on an interval and exposes device
|
|
state and usage three ways:
|
|
|
|
- **OTEL metrics** served for Prometheus scraping at `/metrics` (live state +
|
|
energy/water usage, including a dollar-cost metric).
|
|
- A simple **gRPC API** (`ListDevices`, `GetDevice`) with a grpc-gateway REST
|
|
frontend under `/api`.
|
|
- An **MCP tool** (`list_water_heaters`) at `/api/mcp` that wraps the gRPC API.
|
|
|
|
Built on the [go-app framework](https://gitea.libretechconsulting.com/rmcguire/go-app),
|
|
which provides OTEL, the Prometheus endpoint, gRPC + gateway, health checks,
|
|
config/env loading, and graceful shutdown.
|
|
|
|
## ⚙️ Configuration
|
|
|
|
Config merges a YAML file (`-config config.yaml`), environment variables, and
|
|
go-app defaults. Custom fields (see `pkg/config/custom.go`):
|
|
|
|
| Field | Env var | Notes |
|
|
|-------|---------|-------|
|
|
| `econetEmail` | `ECONET_EMAIL` | Rheem account email |
|
|
| `econetPassword` | `ECONET_PASSWORD` | Prefer the env var; keep out of config.yaml |
|
|
| `costPerKWH` | `ECONET_COST_PER_KWH` | **US dollars per kWh** (e.g. `0.18` = 18¢), not cents |
|
|
| `pollInterval` | `ECONET_POLL_INTERVAL` | How often device state + daily energy/water usage are re-fetched over REST (default `1m`) |
|
|
|
|
Everything under the go-app `AppConfig` (logging, otel, http, grpc) is also
|
|
env-overridable with `APP_*` variables — see `env-sample`.
|
|
|
|
## 🚀 Running
|
|
|
|
```sh
|
|
export ECONET_EMAIL=you@example.com ECONET_PASSWORD=... ECONET_COST_PER_KWH=0.14
|
|
go run . -config config.yaml
|
|
```
|
|
|
|
Then:
|
|
- `curl localhost:8080/metrics | grep econet_`
|
|
- `curl localhost:8080/api/v1alpha1/devices` (REST via grpc-gateway)
|
|
- `grpcurl -plaintext localhost:8081 econet.v1alpha1.EconetService/ListDevices`
|
|
- MCP: point a client at `http://localhost:8080/api/mcp`
|
|
|
|
## 📊 Metrics
|
|
|
|
Per-device gauges labeled `econet.serial`, `econet.device_id`,
|
|
`econet.friendly_name`: `econet_setpoint_fahrenheit`, `econet_connected`,
|
|
`econet_running` (adds a `running_state` label naming the active stage, e.g.
|
|
`compressor-running` / `element-running` / `idle`), `econet_enabled`,
|
|
`econet_away`, `econet_hot_water_availability_percent`, `econet_alert_count`,
|
|
`econet_wifi_signal_db`, `econet_mode` (enum: `1` for the current mode, `0`
|
|
otherwise, via a `mode` label), `econet_device_info` (adds
|
|
`type`/`generic_type`/`mode`).
|
|
Polled usage: `econet_energy_usage_kwh`, `econet_water_usage_gallons`,
|
|
`econet_energy_cost_dollars`.
|
|
|
|
> Note: `econet_wifi_signal_db` is only delivered over Rheem's MQTT push stream,
|
|
> which this exporter does not use — it stays at `0`.
|
|
|
|
## 📂 Project Structure
|
|
- `proto/econet/v1alpha1/` - Protobuf definitions (source).
|
|
- `api/econet/v1alpha1/` - Generated proto, grpc, grpc-gateway code.
|
|
- `pkg/config/` - Custom config merged with go-app configuration.
|
|
- `pkg/econet/` - `EconetService` (owns the REST client + poll ticker) plus:
|
|
- `econetclient/` - minimal EcoNet REST client (auth, devices, usage).
|
|
- `econetgrpc/` - gRPC `EconetService` implementation.
|
|
- `econetmcp/` - MCP server + tools.
|
|
- `econetmetrics/` - OTEL observable gauges.
|
|
- `helm/` - Helm chart for Kubernetes deployment.
|
|
- `.gitea/workflows/` - CI pipelines.
|
|
|
|
## 🛠️ Development
|
|
|
|
- `make proto` - regenerate code from `proto/`.
|
|
- `make schema` - regenerate `contrib/schema.json` from the config struct.
|
|
- `make build` / `make docker` - multi-arch build / image.
|
|
|
|
See `AGENTS.md` for agent-oriented development notes.
|