IoTaWatt
IoTaWatt is an open-source WiFi energy monitor (ESP8266 + ADS1115 ADC) with up to 14 CT channels plus a voltage reference channel. The driver polls the device's local HTTP API and publishes the live readings to GEM zones you map to its inputs and named outputs — one zone per channel, which you create.
Prerequisites
- IoTaWatt firmware 02_07_05 or newer (the
/statusJSON shape stabilized at this revision). - Device on the same LAN as GEM with a static or reserved IP.
- The voltage reference channel calibrated against an actual outlet. Without a calibrated voltage reference, every power reading will be wrong (most commonly: 0 W everywhere).
- One CT clamp per measured circuit, properly oriented (arrow toward the load).
Setup
- Find the IoTaWatt IP from your router or the device's captive-portal-style setup page. Confirm
http://<ip>/statusreturns JSON in a browser. - On the Devices page choose System → Devices → Add Device and pick the driver
iotawatt.ip— the LAN address.port— 80 unless you changed it in IoTaWatt's WiFi config.username/password— only if you set an admin password on the IoTaWatt under Configuration → Device → Admin Password. Most installs run open on a trusted VLAN.
- Run the
get_inputscommand. The response is the list of physical CT channels you configured in IoTaWatt — each has aname,Watts,Vrms,Hz,pf,Irms. - Run
get_outputs. These are the named expressions you defined in IoTaWatt (e.g.Main = input_1 + input_2). - Create the zones yourself — the driver does not auto-create them. Unlike some metered integrations (SPAN, WattBox), IoTaWatt does not discover channels into zones or build a subsystem for you; it only publishes readings to zones that already exist. Add one zone per input or output you want to track, under Zones, each bound to this IoTaWatt device:
- Subsystem — a default GEM install ships a Power subsystem (
power); use it. (The driver hintsenergy, so the zone editor only pre-selects a subsystem if one namedenergyalready exists — the stock install has none, so choose Power yourself, or create anenergysubsystem under Subsystems if you'd rather keep IoTaWatt channels separate.) - Address — the channel name exactly as IoTaWatt reports it; the match is case-sensitive. Copy it from the
get_inputs/get_outputsoutput.- Bare name (e.g.
Main) — the driver looks for a matching input first, then an output. input:Mainoroutput:Main— explicit prefix; use it when the same name exists on both an input and an output.
- Bare name (e.g.
- Subsystem — a default GEM install ships a Power subsystem (
- Adjust
status_intervalif needed. IoTaWatt comfortably serves 1 s polling; 5-10 s is plenty for dashboards and reduces ESP8266 load.
Attribute Reference
Device attributes
| Attribute | Required | Type | Default | Notes |
|---|---|---|---|---|
ip | yes | string | — | LAN IP / hostname of the IoTaWatt. |
port | no | int | 80 | HTTP port. |
username | no | string | — | HTTP basic auth username. Set only if a password is configured. Usually admin. |
password | no | string (secure) | — | HTTP basic auth password. |
status_interval | no | int (ms) | 10000 | Poll frequency for /status. |
Zone attributes
| Attribute | Notes |
|---|---|
address | IoTaWatt channel name. input:Name or output:Name for disambiguation. |
channel_kind | Auto-set to input or output on first poll. |
Zone state attributes (published by the polling loop)
| Attribute | Type | Unit |
|---|---|---|
watts | float | W (signed; negative = wrong-side CT) |
volts | float | V (RMS) |
hz | float | Hz |
pf | float | power factor (0..1) |
amps | float | A (RMS) |
watt_hours | float | Wh (running total since IoTaWatt reboot) |
Commands
| Name | Args | Notes |
|---|---|---|
get_status | — | Raw /status?stats=yes&inputs=yes&outputs=yes&device=yes JSON. |
get_inputs | — | Physical CT channels. Use this to seed input zones. |
get_outputs | — | Named expressions. Use this to seed output zones. |
get_channel | address | One channel by name (or input:Name / output:Name). |
query | select, begin, end | Historical query. select is the IoTaWatt series expression (e.g. Main.watts) — the driver automatically prepends a local-ISO timestamp column, so pass just the data series. begin / end are IoTaWatt time strings (s-1h, s, y, etc.). Returns the parsed series JSON. |
Known Limitations
watt_hourson/statusis a running counter since the last IoTaWatt reboot. For daily / monthly totals, use thequerycommand against IoTaWatt's historical series (it stores.logfiles locally).- Read-only — IoTaWatt has no relay outputs and the driver intentionally does not expose
/edit(config-write) endpoints. - A CT clamped on the wrong side of the breaker reads negative watts. The driver passes the sign through unchanged so the integrator can spot it; correct it by flipping the clamp or inverting that input in IoTaWatt config (Configuration → Inputs → Reverse).
- Voltage channel name defaults to
Voltage. If renamed, voltage reads still flow through under whatever name you used — the driver simply publishes them on the corresponding zone. - mDNS discovery (
_iotawatt._tcp) is supported by the firmware but not yet auto-discovered by GEM. - IoTaWatt does not yet feed the generic energy dashboards — the Power Flow and Top Circuits widgets (see Power Management). Those widgets light up automatically only for integrations that have been tagged for them, and IoTaWatt has not been tagged yet. The readings still land on each zone, so you can put them on zone tiles or a custom widget, chart them under History, and use them in triggers and reports.
Troubleshooting
| Symptom | Likely cause / fix |
|---|---|
| Connection state stays false | http://<ip>/status returns 401? Set username / password on the device. If the page won't load at all, check IP and that the IoTaWatt is online (web UI at /). |
get_inputs returns empty | Firmware older than 02_07_05 — upgrade. |
| A zone never updates / shows no readings | Its Address must match an IoTaWatt input or output name exactly (case-sensitive), and the zone must be bound to this IoTaWatt device. Re-run get_inputs / get_outputs, copy the name verbatim, or prefix it with input: / output:. |
| Every channel reads 0 W | Voltage reference is uncalibrated or wrong channel. In IoTaWatt → Configuration → Inputs, set the voltage channel to a CT clamped on an outlet whose voltage you can verify (~120 V NA / 230 V EU). |
| One channel reads negative | CT is reversed. Flip the clamp on the breaker or check the Reverse box on that input in IoTaWatt config. |
| Polling falls behind / 5xx | Lower status_interval. The ESP8266 has limited concurrency — 1s polling from multiple consumers (GEM + dashboard) can saturate it. |