An open API service indexing awesome lists of open source software.

https://github.com/orangecoding/tibber-ha-mqtt

A robust bridge that subscribes to your Tibber Pulse real-time energy feed and publishes measurements as MQTT sensors to Home Assistant, with automatic device discovery.
https://github.com/orangecoding/tibber-ha-mqtt

home-assistant homeassistant mqtt tibber tibberpulse

Last synced: 10 days ago
JSON representation

A robust bridge that subscribes to your Tibber Pulse real-time energy feed and publishes measurements as MQTT sensors to Home Assistant, with automatic device discovery.

Awesome Lists containing this project

README

          


tibber-ha-mqtt


Logo


A robust bridge that subscribes to your Tibber Pulse real-time energy feed and publishes measurements as MQTT sensors to Home Assistant, with automatic device discovery.


Tests
Docker

## Prerequisites

- Node.js 22 or later
- Yarn
- A [Tibber Pulse](https://tibber.com/en/store/produkt/pulse) device connected to your meter
- An MQTT broker reachable from this machine (e.g. Mosquitto)
- Home Assistant with the [MQTT integration](https://www.home-assistant.io/integrations/mqtt/) enabled

## Getting your Tibber API token

1. Open a browser and go to **[developer.tibber.com/settings/access-token](https://developer.tibber.com/settings/access-token)**
2. Log in with your Tibber account
3. Click **"Create new token"** and give it a name (e.g. `tibber-ha-mqtt`)
4. Copy the token -- you will paste it into `.env` as `TIBBER_TOKEN`

> Your token grants full read access to your Tibber account. Keep it secret and never commit it to git.

## Setup

```bash
# 1. Clone the repo
git clone https://github.com/your-user/tibber-ha-mqtt.git
cd tibber-ha-mqtt

# 2. Install dependencies
yarn inst

# 3. Create your config file
cp .env.example .env

# 4. Fill in your token and MQTT broker URL
# Open .env in your editor and set TIBBER_TOKEN and MQTT_URL
```

## Configuration

All configuration lives in `.env`. Copy `.env.example` for a fully annotated template.

| Variable | Required | Default | Description |
| ------------------------ | -------- | --------- | ----------------------------------------------------------------- |
| `TIBBER_TOKEN` | Yes | -- | Your Tibber personal access token |
| `TIBBER_HOME_ID` | Yes | -- | Your Tibber home ID (find it at developer.tibber.com/explorer) |
| `MQTT_URL` | Yes | -- | MQTT broker URL (`mqtt://host:port`) |
| `MQTT_USERNAME` | No | -- | MQTT username if your broker requires auth |
| `MQTT_PASSWORD` | No | -- | MQTT password if your broker requires auth |
| `NTFY_URL` | No | -- | ntfy topic URL for failure alerts |
| `STALE_DATA_TIMEOUT_MS` | No | `300000` | Reconnect if no data received for this long (ms) |
| `ALERT_COOLDOWN_MS` | No | `1800000` | Minimum gap between same-type alerts (ms) |
| `RECONNECT_MAX_DELAY_MS` | No | `300000` | Maximum backoff delay between reconnect attempts (ms) |
| `LOG_LEVEL` | No | `info` | Log verbosity: `trace`, `debug`, `info`, `warn`, `error`, `fatal` |

### Enabling and disabling sensors

Each `SENSOR_*` line in `.env` controls one Home Assistant sensor. Comment a line out to disable it:

```dotenv
SENSOR_POWER=true # enabled
SENSOR_CURRENT_L1=false # disabled
# SENSOR_VOLTAGE_L1=true # also disabled (commented out)
```

### Removing sensors from Home Assistant

Every time the bridge starts it actively manages all known sensor topics on the broker:

- **Enabled sensors** get their discovery payload published (retained), so HA creates or updates those entities.
- **Disabled sensors** get an empty retained message published, which removes the old retained payload from the broker and tells HA to delete those entities.

This means disabling a sensor in `.env` and restarting the bridge is enough -- HA will drop that entity automatically within a few seconds.

**Full reset** -- if you want to remove every Tibber entity from HA and start completely fresh, run:

```bash
yarn reset
```

This publishes an empty retained message to every discovery topic (enabled and disabled alike). After it completes, restart the bridge normally and only the sensors enabled in `.env` will be re-created.

## Running

```bash
yarn start
```

## Running with Docker

The image is published to the GitHub Container Registry and runs on both `amd64` and `arm64` (e.g. Raspberry Pi).

### 1. Create your `.env` file

The container reads all configuration from an env file. Start from the template:

```bash
cp .env.example .env
# Then open .env and fill in at minimum:
# TIBBER_TOKEN=...
# TIBBER_HOME_ID=...
# MQTT_URL=mqtt://192.168.1.x:1883
```

See the [Configuration](#configuration) section for all available variables.

### 2. Run with Docker Compose (recommended)

Place your `.env` file in the same directory as `docker-compose.yml`, then run:

```bash
docker compose up -d
```

Docker Compose automatically picks up the `.env` from that directory (via the `env_file: .env` line in the compose file) and passes all variables into the container. The container restarts automatically if it crashes.

To follow logs:

```bash
docker compose logs -f
```

### 3. Run with Docker CLI

If you prefer to run the container directly without Compose:

```bash
docker run -d \
--name tibber-ha-mqtt \
--env-file /path/to/your/.env \
--restart unless-stopped \
ghcr.io/orangecoding/tibber-ha-mqtt:latest
```

Replace `/path/to/your/.env` with the absolute path to your env file. The `--env-file` flag must point to the file on the **host** machine -- it is not copied into the image.

## Sensors

All sensors are published under the **Tibber Energy Source** device in Home Assistant.

Sensors marked with `*` are meter-dependent -- they may have no value if your electricity meter does not report that measurement.

**Instantaneous power**

| `.env` key | Sensor name | Unit | Description |
| ---------------------------------- | ------------------------- | ---- | --------------------------------------------- |
| `SENSOR_POWER` | Power | W | Grid consumption right now |
| `SENSOR_POWER_PRODUCTION` | Power Production | W | Grid export right now (e.g. solar) `*` |
| `SENSOR_POWER_REACTIVE` | Power Reactive | kvar | Reactive power drawn from grid right now `*` |
| `SENSOR_POWER_PRODUCTION_REACTIVE` | Power Production Reactive | kvar | Reactive power exported to grid right now `*` |
| `SENSOR_POWER_FACTOR` | Power Factor | -- | Ratio of real to apparent power, 0.0-1.0 `*` |

**Daily min / average / max** (reset at midnight)

| `.env` key | Sensor name | Unit | Description |
| ----------------------------- | -------------------- | ---- | ------------------------------------------------ |
| `SENSOR_AVERAGE_POWER` | Average Power | W | Average grid consumption since midnight |
| `SENSOR_MIN_POWER` | Min Power | W | Lowest instantaneous consumption since midnight |
| `SENSOR_MAX_POWER` | Max Power | W | Highest instantaneous consumption since midnight |
| `SENSOR_MIN_POWER_PRODUCTION` | Min Power Production | W | Lowest instantaneous export since midnight `*` |
| `SENSOR_MAX_POWER_PRODUCTION` | Max Power Production | W | Highest instantaneous export since midnight `*` |

**Accumulated energy** (reset at midnight / top of each hour)

| `.env` key | Sensor name | Unit | Description |
| ------------------------------------------ | --------------------------------- | ---- | ----------------------------------------- |
| `SENSOR_ACCUMULATED_CONSUMPTION` | Accumulated Consumption | kWh | Total drawn from grid since midnight |
| `SENSOR_ACCUMULATED_PRODUCTION` | Accumulated Production | kWh | Total exported to grid since midnight |
| `SENSOR_ACCUMULATED_CONSUMPTION_LAST_HOUR` | Accumulated Consumption Last Hour | kWh | Drawn from grid since the last full hour |
| `SENSOR_ACCUMULATED_PRODUCTION_LAST_HOUR` | Accumulated Production Last Hour | kWh | Exported to grid since the last full hour |

**Cost** (requires an active Tibber power deal; otherwise no value)

| `.env` key | Sensor name | Description |
| --------------------------- | ------------------ | ---------------------------------------------------------------- |
| `SENSOR_ACCUMULATED_COST` | Accumulated Cost | Electricity cost since midnight, VAT included (account currency) |
| `SENSOR_ACCUMULATED_REWARD` | Accumulated Reward | Production reward earned since midnight (account currency) |

**Per-phase measurements** `*`

| `.env` key | Sensor name | Unit | Description |
| ------------------- | ----------- | ---- | ------------------ |
| `SENSOR_CURRENT_L1` | Current L1 | A | Current on phase 1 |
| `SENSOR_CURRENT_L2` | Current L2 | A | Current on phase 2 |
| `SENSOR_CURRENT_L3` | Current L3 | A | Current on phase 3 |
| `SENSOR_VOLTAGE_L1` | Voltage L1 | V | Voltage on phase 1 |
| `SENSOR_VOLTAGE_L2` | Voltage L2 | V | Voltage on phase 2 |
| `SENSOR_VOLTAGE_L3` | Voltage L3 | V | Voltage on phase 3 |

**Device and meter state**

| `.env` key | Sensor name | Unit | Description |
| ------------------------------- | ---------------------- | ---- | ---------------------------------------------------------- |
| `SENSOR_SIGNAL_STRENGTH` | Signal Strength | dBm | Tibber Pulse signal strength `*` |
| `SENSOR_LAST_METER_CONSUMPTION` | Last Meter Consumption | kWh | Electricity meter all-time import total (never resets) `*` |
| `SENSOR_LAST_METER_PRODUCTION` | Last Meter Production | kWh | Electricity meter all-time export total (never resets) `*` |

## Failure alerting

Set `NTFY_URL` in `.env` to receive push notifications when the bridge loses connectivity:

```dotenv
NTFY_URL=https://ntfy.sh/my-private-topic-12345
```

Three alert categories are tracked independently with a 30-minute cooldown each:

- **tibber-disconnect** -- Tibber WebSocket connection lost after multiple retries
- **mqtt-disconnect** -- MQTT broker unreachable
- **stale-data** -- No measurements received within the timeout window

To receive alerts on your phone, install the [ntfy app](https://ntfy.sh/) and subscribe to the same topic.

## Running as a systemd service

Create `/etc/systemd/system/tibber-ha-mqtt.service`:

```ini
[Unit]
Description=Tibber MQTT Bridge
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=YOUR_USERNAME
WorkingDirectory=/path/to/tibber-ha-mqtt
ExecStart=/usr/bin/node src/index.js
Restart=always
RestartSec=10
EnvironmentFile=/path/to/tibber-ha-mqtt/.env
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
```

Then enable and start it:

```bash
sudo systemctl daemon-reload
sudo systemctl enable tibber-ha-mqtt
sudo systemctl start tibber-ha-mqtt

# Check logs
sudo journalctl -u tibber-ha-mqtt -f
```

## Running with Docker

```bash
docker run -d \
--name tibber-ha-mqtt \
--restart unless-stopped \
--env-file .env \
node:22-alpine \
sh -c "yarn inst && yarn start"
```

## Development

```bash
# Run tests
yarn test

# Lint
yarn lint

# Format
yarn format
```