Skip to main content

Async API client and CLI for MieleLogic laundry systems

Project description

MieleLogic Home Assistant Integration

MieleLogic is a Home Assistant custom integration for MieleLogic laundry rooms. It makes it easier to bring your shared laundry machines into Home Assistant if your building already uses MieleLogic.

Usage

To start, add this repository to HACS:

Open HACS in My Home Assistant

Add this repository manually in HACS:

  1. Navigate to "HACS" in your Home Assistant web interface.
  2. Under the "⋮" actions menu in the top corner, choose "Custom repositories".
  3. Add https://github.com/soupglasses/mielelogic-ha as a repository in the "Integration" category.
  4. After a short bit, searching for "MieleLogic" should show the integration from this repository.
  5. Press "MieleLogic" and choose "Download".
  6. Restart Home Assistant.
  7. Navigate to "Settings" -> "Devices & services" -> "Add integration".
  8. Search for "MieleLogic".
  9. Enter your MieleLogic username, password, and country (Denmark or Norway).

Home Assistant should now create entities for your machines. Further information is available below, including example automations.

Development Setup

This project uses uv for dependency management and poe for task running.

Quick Start

# Activate the project environment
source .venv/bin/activate
# or
source .envrc

# Install dependencies and set up pre-commit hooks
poe setup

# Run tests
poe test
poe test-ha

# Other useful commands
poe console   # Interactive Python shell with project loaded
poe lint      # Check code style
poe format    # Auto-format code
poe build     # Build distribution packages

poe test runs the library test suite from the shared development environment. Tests marked with @pytest.mark.network opt back in to real network access for that test only.

poe test-ha runs the Home Assistant integration tests from tests/custom_components/mielelogic in the same shared development environment.

Working On HA

The Home Assistant integration code lives in custom_components/mielelogic/. Its tests live in tests/custom_components/mielelogic/.

The rest of the test suite is split by package:

  • tests/mielelogic_cli/ for CLI coverage
  • tests/mielelogic_api/ for the API client library
  • tests/custom_components/mielelogic/ for the Home Assistant integration

For one-off HA commands, run them from the shared environment:

pytest tests/custom_components/mielelogic
poe develop

poe develop runs Home Assistant against .ha-dev-config and restarts it when files change under custom_components/mielelogic/ or mielelogic_api/. For local development it copies the integration into .ha-dev-config and removes the production PyPI requirement from that copied manifest, because the dev venv already installs the repo editable. Use scripts/develop --once when you want a single foreground HA run without the watcher.

Normal setup installs both the library and HA tooling into the same .venv:

uv sync

Then use the usual task wrappers:

poe test
poe test-ha
poe develop

Packaging and Releases

The Python client library is published to PyPI as mielelogic-api while keeping the import path mielelogic_api.

The Home Assistant integration depends on that published package through custom_components/mielelogic/manifest.json, so Home Assistant OS must be able to install the exact released version from PyPI.

Maintainer release flow:

  1. Ensure custom_components/mielelogic/manifest.json pins the intended mielelogic-api==X.Y.Z release.
  2. Create and push the matching git tag vX.Y.Z.
  3. GitHub Actions builds and publishes the package to PyPI using trusted publishing.

Authentication Note

MieleLogic's internal OAuth2 lifecycle is seemingly not long-lived: tokens are invalidated aggressively, so sessions do not remain valid indefinitely. Meaning that this project cannot use the Home Assistant's native OAuth2 flow by default, since it expects long-lived stable tokens.

Requirements

Automations

The integration exposes three entities per machine — a status sensor, a time-remaining sensor, and a "mine" binary sensor — designed to work together cleanly in automations.

Entity overview

Entity Type Example states / value
sensor.<machine>_status Enum idle, busy, running, reserved, booked, closed, disabled
sensor.<machine>_time_remaining Duration (min) 28, 5, null (unavailable when idle/closed/disabled)
binary_sensor.<machine>_mine Boolean on (started/reserved by me), off

Status state meanings:

  • idle — machine is free
  • busy — running, started by someone else
  • running — running, started by you (transaction detected within 10 min window)
  • reserved — currently reserved by you
  • booked — currently reserved by someone else
  • closed / disabled — out of service

The integration detects ownership by correlating your recent transactions (fetched from the API within a 10-minute rolling window) with idle→active state transitions. No transaction check is needed when a machine goes back to idle — that transition always clears the "mine" flag.

Notify when your laundry is done

Trigger on runningidle for any machine you started.

automation:
  - alias: "Laundry done"
    trigger:
      - platform: state
        entity_id:
          - sensor.vask_1_status
          - sensor.tumbler_1_status
        from: "running"
        to: "idle"
    action:
      - service: notify.mobile_app_your_phone
        data:
          title: "Laundry done"
          message: "{{ trigger.to_state.attributes.friendly_name }} has finished."

Notify ~1 minute before a cycle ends

The time_remaining sensor counts down while the machine is running. Trigger when it drops below 2 minutes (API polling resolution means you may not catch exactly 1).

automation:
  - alias: "Laundry almost done"
    trigger:
      - platform: numeric_state
        entity_id:
          - sensor.vask_1_time_remaining
          - sensor.tumbler_1_time_remaining
        below: 2
    condition:
      # Only fire when it is our machine, not someone else's
      - condition: template
        value_template: >
          {{ states('sensor.' ~ trigger.entity_id.split('.')[1].replace('_time_remaining', '_status')) == 'running' }}
    action:
      - service: notify.mobile_app_your_phone
        data:
          title: "Almost done"
          message: >
            {{ trigger.to_state.attributes.friendly_name | replace(' time remaining', '') }}
            finishes in about 1 minute.

Notify when all your machines finish (group trigger)

If you often run washer + dryer simultaneously, wait until both are done before notifying.

automation:
  - alias: "All laundry done"
    mode: single
    trigger:
      - platform: state
        entity_id:
          - sensor.vask_1_status
          - sensor.tumbler_1_status
        from: "running"
        to: "idle"
    condition:
      # Fire only when none of your machines are still running
      - condition: template
        value_template: >
          {% set mine = ['sensor.vask_1_status', 'sensor.tumbler_1_status'] %}
          {{ mine | map('states') | select('eq', 'running') | list | count == 0 }}
    action:
      - service: notify.mobile_app_your_phone
        data:
          title: "All laundry done"
          message: "All your machines have finished."

Check if a machine is booked by someone else before going down

condition:
  - condition: not
    conditions:
      - condition: state
        entity_id: sensor.vask_1_status
        state: "booked"

Legal Disclaimer

This project is an independent, unofficial integration and is not endorsed by, affiliated with, or sponsored by Miele & Cie. KG, its subsidiaries, or MieleLogic. All product names, logos, brands, trademarks, and registered trademarks are property of their respective owners.

Usage is at your own risk!

Trademark Notice

Miele® and MieleLogic® are registered trademarks of their respective owners. This project's use of these names is for identification and reference purposes only and does not imply any endorsement or affiliation.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mielelogic_api-1.0.1.tar.gz (205.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mielelogic_api-1.0.1-py3-none-any.whl (22.6 kB view details)

Uploaded Python 3

File details

Details for the file mielelogic_api-1.0.1.tar.gz.

File metadata

  • Download URL: mielelogic_api-1.0.1.tar.gz
  • Upload date:
  • Size: 205.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for mielelogic_api-1.0.1.tar.gz
Algorithm Hash digest
SHA256 a2590b19bac3f4f82c482bf509934daf4a3a1943089f88d3404a1e157b48f34f
MD5 9c4f92bdfa83c3cd61d716fecd7bdd47
BLAKE2b-256 b2233921a6a5173107de2089dff64602e37b7c08417f931db8c68838c13b8c8a

See more details on using hashes here.

Provenance

The following attestation bundles were made for mielelogic_api-1.0.1.tar.gz:

Publisher: publish.yml on soupglasses/mielelogic-ha

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mielelogic_api-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: mielelogic_api-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 22.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for mielelogic_api-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 195841cb8ed2287b8f49868f67bd306362289cb780a2a14498769e537116ae17
MD5 1edae670e3e59e69f40c0a8e6a3b199b
BLAKE2b-256 293cb3385e7b967a8bfab1e12648f03474dca972e3cfdc08e94d06a540408acf

See more details on using hashes here.

Provenance

The following attestation bundles were made for mielelogic_api-1.0.1-py3-none-any.whl:

Publisher: publish.yml on soupglasses/mielelogic-ha

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page