kirbownz/electrolux-to-mqtt

By kirbownz

Updated 18 days ago

Integrate Electrolux to MQTT / Home Assistant

Image
Integration & delivery
0

10K+

kirbownz/electrolux-to-mqtt repository overview

Electrolux to MQTT / Home Assistant

Latest Stable Latest Beta Docker Pulls Active Users

CI/CD Pipeline Status GitLab Last Commit GitLab Issues GitLab Merge Requests

Quality Gate Status Bugs Code Smells Coverage Duplicated Lines (%)

A robust TypeScript bridge for controlling Electrolux appliances via MQTT and Home Assistant. Features automatic discovery, dynamic appliance management, and a modular architecture for easy extensibility.

Features

  • Automatic Home Assistant Discovery - Zero-configuration MQTT Climate integration
  • Dynamic Appliance Detection - Automatically detects added/removed appliances
  • Modular Architecture - Easy to extend with new appliance models
  • Secure Token Management - Automatic OAuth token refresh
  • Production Ready - Comprehensive error handling and graceful shutdown
  • Well Tested - Unit tests with >95% coverage
  • Docker Ready - Multi-platform Docker images (amd64/arm64)
  • Update Notifications - Periodically check for newer releases and optionally push-notify you via https://ntfy.sh/ webhook.
  • Anonymous Telemetry - Every ~15 minutes (independent of the version-check interval), sends the app version, update channel (stable/beta), OS name and version, CPU architecture, and connected-appliance model id(s) and count to a self-hosted Aptabase instance. It also sends a stable per-install id — a one-way SHA-256 hash of your Electrolux username (never the username itself or any credential) — so the same install can be counted over a rolling ~24h (26h) window without revealing who you are. Aptabase additionally derives an approximate country from the request IP. Opt out by setting E2M_TELEMETRY_ENABLED=false. This is a personal project maintained in my free time, and knowing the active user count helps me gauge how much effort to invest in it.

Relevant links:

Supported Appliances

ModelTypeNotes
Electrolux Comfort 600Portable Air ConditionerFull support: climate modes, fan speed, swing, sleep mode, temperature control

Unknown models that report as a portable air conditioner will use the Comfort 600 implementation as a fallback. If you have a different Electrolux appliance and would like support added, please open an issue.

Prerequisites

  1. Sign up/sign in into Electrolux for Developer
  2. Create a new API Key and copy the value
  3. Start the container by following one of the instructions listed below

Configuration options

All configuration can be provided via environment variables or via config.yml file. If a config.yml file is present, it will be used and environment variables will be ignored.

Example config.yml file is included in the repository and can be used as a template.

All environment variables

For detailed descriptions and reasoning behind each option, see the comments in config.example.yml.

VariableDescriptionDefaultRequired
MQTT_URLMQTT broker URL (mqtt:// or mqtts://)Yes
MQTT_USERNAMEMQTT broker usernameYes
MQTT_PASSWORDMQTT broker passwordYes
ELECTROLUX_API_KEYElectrolux API keyYes
ELECTROLUX_USERNAMEElectrolux account emailYes
ELECTROLUX_PASSWORDElectrolux account passwordYes
ELECTROLUX_COUNTRY_CODETwo-letter uppercase country codeYes
MQTT_TOPIC_PREFIXMQTT topic prefixelectrolux_No
MQTT_CLIENT_IDMQTT client identifierelectrolux-comfort600No
MQTT_RETAINRetain MQTT messagesfalseNo
MQTT_QOSMQTT QoS level (0, 1, or 2)2No
ELECTROLUX_REFRESH_INTERVALState polling interval in seconds (10–3600)30No
ELECTROLUX_APPLIANCE_DISCOVERY_INTERVALAppliance discovery interval in seconds (60–3600)300No
ELECTROLUX_RENEW_TOKEN_BEFORE_EXPIRYMinutes before token expiry to refresh (5–715)60No
ELECTROLUX_COMMAND_STATE_DELAY_SECONDSSeconds to wait after a command before re-polling state (5–300)30No
ELECTROLUX_APPLIANCE_REMOVAL_GRACE_PERIOD_MINUTESMinutes an appliance must be continuously absent before cleanup (1–1440)30No
ELECTROLUX_API_TIMEOUT_SECONDSHTTP request timeout in seconds for Electrolux API calls (1–120)25No
HOME_ASSISTANT_AUTO_DISCOVERYEnable HA MQTT auto-discoverytrueNo
HOME_ASSISTANT_REVERT_STATE_ON_REJECTIONImmediately revert HA state on rejected commandsfalseNo
HA_BIRTH_REPUBLISHRe-publish discovery config + state when HA comes online (birth message)trueNo
HA_STATUS_TOPICMQTT topic HA publishes its birth/will message tohomeassistant/statusNo
HA_BIRTH_PAYLOADPayload that signals HA is onlineonlineNo
LOG_LEVELLog level (silent/fatal/error/warn/info/debug/trace)infoNo
LOGGING_SHOW_CHANGESLog state changestrueNo
LOGGING_IGNORED_KEYSComma-separated keys to ignore in change logsNo
LOGGING_SHOW_VERSION_NUMBERShow version in log prefixtrueNo
LOGGING_SKIP_CACHE_LOGGINGSuppress cache debug logstrueNo
LOGGING_SHOW_TIMESTAMPShow timestamps in logstrueNo
VERSION_CHECK_INTERVALUpdate check interval in seconds (60–86400)3600No
VERSION_CHECK_NOTIFY_GRACE_PERIODMinimum age (seconds) a release must reach before you are notified (0–604800)3600No
VERSION_CHECK_NTFY_WEBHOOK_URLntfy.sh webhook URL for update notificationsNo
VERSION_CHECK_UPDATE_CHANNELstable skips pre-release builds; beta includes them. Omit to use the image default: :next images are built with beta, :latest images with stable. Set only to override the image default.image-bakedNo
HEALTH_CHECK_ENABLEDEnable file-based health check for Docker HEALTHCHECKtrueNo
HEALTH_CHECK_FILE_PATHPath to health check file/tmp/e2m-healthNo
HEALTH_CHECK_UNHEALTHY_RESTART_MINUTESMinutes of API failure before container self-restarts45No
E2M_TELEMETRY_ENABLEDSend anonymous telemetry (version, channel, OS, arch, appliance models/count) to self-hosted Aptabase. Opt out with false.trueNo

But how to start?!

Choose one of the following methods and open the details.

Using docker with config.yml
I choose you!
  1. Copy config.example.yml as config.yml:
    cp config.example.yml config.yml
    
  2. Modify the config.yml accordingly and save changes:
    code config.yml
    
  3. Run:
    docker pull kirbownz/electrolux-to-mqtt:latest
    docker run --rm -v ./config.yml:/app/config.yml:ro --name electrolux-to-mqtt kirbownz/electrolux-to-mqtt:latest
    
Using docker with environmental variables
I choose you!
docker pull kirbownz/electrolux-to-mqtt:latest
docker run --rm \
  # Mandatory variables \
  -e MQTT_URL=mqtt://192.168.1.1:1883 \
  -e MQTT_USERNAME=mqtt-user \
  -e MQTT_PASSWORD=mqtt-password \
  -e ELECTROLUX_API_KEY=electrolux-api-key \
  -e [email protected] \
  -e ELECTROLUX_PASSWORD=electrolux-password \
  -e ELECTROLUX_COUNTRY_CODE=FI \
  # Optional variables \
  # -e MQTT_TOPIC_PREFIX=electrolux_ \
  # -e MQTT_CLIENT_ID=electrolux-comfort600 \
  # -e MQTT_RETAIN=false \
  # -e MQTT_QOS=2 \
  # -e ELECTROLUX_REFRESH_INTERVAL=30 \
  # -e ELECTROLUX_APPLIANCE_DISCOVERY_INTERVAL=300 \
  # -e ELECTROLUX_RENEW_TOKEN_BEFORE_EXPIRY=60 \
  # -e ELECTROLUX_COMMAND_STATE_DELAY_SECONDS=30 \
  # -e ELECTROLUX_APPLIANCE_REMOVAL_GRACE_PERIOD_MINUTES=30 \
  # -e ELECTROLUX_API_TIMEOUT_SECONDS=25 \
  # -e HOME_ASSISTANT_AUTO_DISCOVERY=true \
  # -e HOME_ASSISTANT_REVERT_STATE_ON_REJECTION=false \
  # -e HA_BIRTH_REPUBLISH=true \
  # -e HA_STATUS_TOPIC=homeassistant/status \
  # -e HA_BIRTH_PAYLOAD=online \
  # -e LOG_LEVEL=info \
  # -e LOGGING_SHOW_CHANGES=true \
  # -e LOGGING_IGNORED_KEYS=networkInterface,totalRuntime \
  # -e LOGGING_SHOW_VERSION_NUMBER=true \
  # -e LOGGING_SKIP_CACHE_LOGGING=true \
  # -e LOGGING_SHOW_TIMESTAMP=true \
  # -e VERSION_CHECK_INTERVAL=3600 \
  # -e VERSION_CHECK_NOTIFY_GRACE_PERIOD=3600 \
  # -e VERSION_CHECK_NTFY_WEBHOOK_URL=https://ntfy.sh/vB66ozQaRiqhTE9j \ # Register your own at https://ntfy.sh/
  # -e VERSION_CHECK_UPDATE_CHANNEL=stable \                                   # image default (omit unless pinning)
  # -e HEALTH_CHECK_ENABLED=true \
  # -e HEALTH_CHECK_FILE_PATH=/tmp/e2m-health \
  # -e HEALTH_CHECK_UNHEALTHY_RESTART_MINUTES=45 \
  # -e E2M_TELEMETRY_ENABLED=true \
  --name electrolux-to-mqtt kirbownz/electrolux-to-mqtt:latest
Using docker compose
I choose you!
  1. Copy docker-compose.example.yml as docker-compose.yml:
    cp docker/docker-compose.example.yml docker-compose.yml
    
  2. Modify the docker-compose.yml accordingly and save changes:
    code docker-compose.yml
    
  3. Run:
    docker compose down ; docker compose up --pull always -d
    
Using Portainer
I choose you!
  1. Add new Stack
  2. Give it a name, e.g. electrolux-to-mqtt
  3. Select Web editor, copy the following variables and make changes accordingly, finally press Deploy the stack:
services:
  electrolux-to-mqtt:
    image: kirbownz/electrolux-to-mqtt:latest
    mem_limit: 128mb
    memswap_limit: 256mb
    restart: unless-stopped
    volumes:
      - "/etc/localtime:/etc/localtime:ro"
      - "/etc/timezone:/etc/timezone:ro"
    environment:
      # Mandatory variables
      - MQTT_URL=mqtt://192.168.1.1:1883
      - MQTT_USERNAME=mqtt-user
      - MQTT_PASSWORD=mqtt-password
      - ELECTROLUX_API_KEY=electrolux-api-key
      - [email protected]
      - ELECTROLUX_PASSWORD=electrolux-password
      - ELECTROLUX_COUNTRY_CODE=FI
      # Optional variables (uncomment as needed)
      # - MQTT_TOPIC_PREFIX=electrolux_
      # - MQTT_CLIENT_ID=electrolux-comfort600
      # - MQTT_RETAIN=false
      # - MQTT_QOS=2
      # - ELECTROLUX_REFRESH_INTERVAL=30
      # - ELECTROLUX_APPLIANCE_DISCOVERY_INTERVAL=300
      # - ELECTROLUX_RENEW_TOKEN_BEFORE_EXPIRY=60
      # - ELECTROLUX_COMMAND_STATE_DELAY_SECONDS=30
      # - ELECTROLUX_APPLIANCE_REMOVAL_GRACE_PERIOD_MINUTES=30
      # - ELECTROLUX_API_TIMEOUT_SECONDS=25
      # - HOME_ASSISTANT_AUTO_DISCOVERY=true
      # - HOME_ASSISTANT_REVERT_STATE_ON_REJECTION=false
      # - HA_BIRTH_REPUBLISH=true
      # - HA_STATUS_TOPIC=homeassistant/status
      # - HA_BIRTH_PAYLOAD=online
      # - LOG_LEVEL=info
      # - LOGGING_SHOW_CHANGES=true
      # - LOGGING_IGNORED_KEYS=networkInterface,totalRuntime
      # - LOGGING_SHOW_VERSION_NUMBER=true
      # - LOGGING_SKIP_CACHE_LOGGING=true
      # - LOGGING_SHOW_TIMESTAMP=true
      # - VERSION_CHECK_INTERVAL=3600
      # - VERSION_CHECK_NOTIFY_GRACE_PERIOD=3600
      # - VERSION_CHECK_NTFY_WEBHOOK_URL=https://ntfy.sh/vB66ozQaRiqhTE9j # Register your own at https://ntfy.sh/
      # - VERSION_CHECK_UPDATE_CHANNEL=stable                              # image default (omit unless pinning)
      # - HEALTH_CHECK_ENABLED=true
      # - HEALTH_CHECK_FILE_PATH=/tmp/e2m-health
      # - HEALTH_CHECK_UNHEALTHY_RESTART_MINUTES=45
      # - E2M_TELEMETRY_ENABLED=true

Beta / pre-release channel

Pre-release (beta) builds are published to the :next Docker tag on every push to the next branch. Betas follow Home Assistant's CalVer scheme YYYY.M.MICRObN (e.g. 2026.6.0b1). Each beta changelog covers only the changes since the previous release (stable or beta).

:next and :latest are separate images built with different update channel defaults baked in:

  • :latest — built with stable channel baked in; only notifies about stable releases.
  • :next — built with beta channel baked in; notifies about both beta and stable releases.

This means the correct channel is always active regardless of what version number is running — even if :next temporarily carries a promoted-stable version (e.g. 2026.6.4, no bN), it still defaults to the beta channel.

I want to try the beta channel!

Note: Pre-release builds may contain unfinished features or bugs. Use :latest for production.

To use the beta channel, replace :latest with :next in your setup:

docker:

docker pull kirbownz/electrolux-to-mqtt:next
docker run --rm -v ./config.yml:/app/config.yml:ro --name electrolux-to-mqtt kirbownz/electrolux-to-mqtt:next

docker-compose / Portainer: change the image: line:

image: kirbownz/electrolux-to-mqtt:next

When running the :next image, the update channel defaults automatically to beta — no extra configuration needed. Override with VERSION_CHECK_UPDATE_CHANNEL=stable (env var) or updateChannel: stable in config.yml under versionCheck: to pin to the stable channel.

Release notes for each beta are available on the GitLab releases page.

Developing locally

I want to fix it myself!!

Either running natively locally:

# Copy config.example.yml
cp config.example.yml config.yml

# Modify as needed
code config.yml

# Make sure you have the correct toolchain (Node.js etc. — pinned in mise.toml)
# If you don't have mise installed, follow https://mise.jdx.dev/getting-started.html
mise install

# Install correct pnpm version if not installed already
corepack enable
corepack install

# Install the dependencies
pnpm install

# Run the app in development mode
pnpm dev

..or if you want to use Docker instead:

# Make a copy of the docker-compose.local.example.yml
cp docker/docker-compose.local.example.yml docker/docker-compose.local.yml

# Modify as needed
code docker/docker-compose.local.yml

# Run the stack (automatically uses Node version from .nvmrc)
NODE_VERSION=$(cat .nvmrc) docker compose -f docker/docker-compose.local.yml down ; NODE_VERSION=$(cat .nvmrc) docker compose -f docker/docker-compose.local.yml up --build

# Or if you have pnpm installed:
pnpm dev:docker
But how to run tests?!

This project includes comprehensive unit tests to ensure reliability:

# Run all tests
pnpm test

# To run E2E tests (including version-checker E2E):
pnpm test:e2e

# You can override the ntfy notification topic for E2E tests with:
E2M_NTFY_TOPIC=yourtopic pnpm test:e2e
# If not set, the default topic is `vB66ozQaRiqhTE9j`.

# Run tests in watch mode (auto-rerun on changes)
pnpm test:watch

Viewing the changelog

The CHANGELOG.md is baked into the Docker image at /app/CHANGELOG.md. To extract it from a running container:

# Auto-detect the container name (assumes it contains "electrolux-to-mqtt")
docker cp $(docker ps --filter name=electrolux-to-mqtt --format '{{.Names}}' | head -1):/app/CHANGELOG.md ./CHANGELOG.md

# Or specify the container name explicitly
docker cp <container-name>:/app/CHANGELOG.md ./CHANGELOG.md

cat CHANGELOG.md

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for detailed guidelines on:

  • Adding support for new appliance models
  • Development setup and workflow
  • Code style and testing requirements
  • Submitting merge requests

Home Assistant automation examples

Please read HOME_ASSISTANT.md for more details.

Epilogue

Inspired by — and thanks to — Dannyyy for the Electrolux to MQTT repository. I kept running into issues with various other implementations, and often had to wait a while for fixes, so I decided to build my own on top of the public Electrolux API.

Tag summary

Content type

Image

Digest

sha256:63676f49a

Size

39.7 MB

Last updated

18 days ago

docker pull kirbownz/electrolux-to-mqtt