Skip to content

Repository files navigation

Jura Connect — Home Assistant Integration

CI hacs_custom

Home Assistant integration for WiFi-connected JURA coffee machines (S8, EB, TT237W series). Built on the reverse-engineered jura-connect library — talks directly to the machine's WiFi dongle on TCP/51515. No cloud, no vendor account.

Requires jura_connect>=0.14.0. The integration ships the Python dependency declaration; Nix users get it pinned via the flake input.

Features

Setup

  • Auto-discovery on the local network (UDP broadcast first, with a TCP /24 fallback for firmwares like TT237W that don't reply to UDP); manual IP entry is always available.
  • One-shot pairing — press OK on the machine once, the integration persists the resulting auth-hash on the config entry and reconnects silently afterwards.
  • Per-machine profiles — pick your model from a dropdown of 89 known JURA variants (S8 EB, ENA 8, Z8, …). The profile drives the names of alerts, brew counters, and machine settings. Auto-detected from the UDP broadcast's article number when available.

Sensors (main device-card section)

  • Status — overall machine state derived from the active-alert bits.
  • Brew <recipe> — one sensor per recipe the machine reports (espresso, coffee, cappuccino, macchiato, americano, …). Set is discovered from the machine; names from the profile when configured.
  • Brew total — lifetime brews across all recipes.
  • Service <kind> level — cleaning, descale, filter change — the percent-to-next-service indicators (0–100 %).
  • Setting <name> — current value of each machine setting (language, hardness, auto-off, units, …); item-driven settings surface as the friendly catalogue name, sliders as the integer value.

Binary sensors

  • Alert <name> — one entity per status bit (fill water, no beans, empty grounds, drip tray, milk warning, heating up, coffee ready, …). Problem-class alerts live in the main view; running and informational bits move to the diagnostic section.

Configuration controls (CONFIG section)

  • select.* entities for switch / combobox / item-slider settings (language, units, auto-off delay, milk rinsing, frother instructions, …). Writes are validated against the profile before any TCP session opens, so invalid values surface a clear "klingon is not a recognised value. Allowed: german=01, english=02, …" message rather than a backend error.
  • number.* entities for step-slider settings (currently water hardness on EF1091) with the min/max/step pulled from the profile XML.

Diagnostics (collapsed by default)

  • Machine type — the EF code + friendly name (e.g. S8 (EB) with machine_type=EF1091 on attributes).
  • Connectivity — the canonical "is the machine reachable right now" signal (binary_sensor with device_class=connectivity). Wire automations against this rather than the per-entity available flag.
  • Cycles <kind> — the six maintenance counters (cleaning, descale, filter change, cappu rinse, coffee rinse, cappu clean).
  • Running / informational binary sensors (heating up, coffee ready, welcome, please wait, …).

Resilience

Entities keep showing their last value when the machine is offline — JURA dongles sleep regularly and v0.1 caused dashboards to flash with every failed poll. The connectivity binary sensor is the single source of truth for reachability.

Languages

Entity names use Home Assistant's native per-user translations, so each client sees them in its own UI language. English ships in strings.json (mirrored to translations/en.json); German (de) is fully translated in translations/de.json. The dynamic Brew <recipe> and Setting <name> entities translate their prefix and keep the machine-supplied name as a placeholder. To add a language, copy translations/de.json to translations/<lang>.json and translate the name values.

Lovelace brew card

The repo ships a companion dashboard card (www/jura-brew-card.js): status pill, Product picker, Strength / Water / Temperature sliders and a Brew button in one card. Copy the file to your HA config/www/ directory and register it as a module dashboard resource pointing at /local/jura-brew-card.js. HA serves /local/* with a 31-day Cache-Control, so append a version query (?v=<md5>) and bump it on every card update, or browsers keep serving the stale copy.

type: custom:jura-brew-card
machine: kaffeebert   # optional — see below
  • Zero-config: with no options the card auto-discovers the brew + status entities; with several machines it picks the first (alphabetically) and logs a warning.
  • machine: pinning matches by slug token, not exact prefix: machine: kaffeebert resolves a machine whose entities drifted apart in the entity registry (e.g. brew entities under select.kuche_kaffeebert_brew_* while connectivity kept binary_sensor.kaffeebert_connectivity). A pinned machine never borrows another machine's entities; exact per-entity options (product:, connectivity:, …) always win over auto-resolution.
  • Offline handling: the binary_sensor.<machine>_connectivity entity is the reachability signal. When it is off (or the status sensor is unavailable), the card shows a grey Offline pill plus a "brewing unavailable" note, and disables the sliders and the Brew button — a retained last_press timestamp on the brew button is not treated as "online".

Services

Service Description
jura.force_update Poll the machine immediately
jura.lock_screen Lock the front-panel display
jura.unlock_screen Unlock the front-panel display
jura.brew Brew a product by name, or a raw recipe payload
jura.clean Start coffee-system cleaning cycle (~5 min)
jura.descale Start descaling cycle (30+ min, requires descaler)
jura.filter_change Run water-filter change procedure
jura.cappu_rinse Rinse the milk system
jura.cappu_clean Clean the milk system (requires cleaning tablet)
jura.power_off Put the machine into standby (TT237W ignores this)
jura.restart Reboot the WiFi dongle
jura.cancel Cancel the current process/brew
jura.skip_quality_step Skip the current quality-assistant step (scope: one/all)
jura.milk_cooler_status Read the milk-cooler temperature (response)
jura.restart_dongle Reboot the WiFi dongle (library-gated variant)
jura.special_counters Read special-function counters (response)

All services accept entity_id (any Jura entity) or config_entry_id to target a specific machine. Brewing returns the raw command result as the service response.

Destructive registry entries that can lock you out of the machine (skip-quality-step, set-pin, set-ssid, set-password, raw) are deliberately not exposed as HA services. Use the upstream jura-connect CLI if you need them.

Installation

HACS (recommended)

  1. In HACS → Integrations → ⋮ → Custom repositories, add https://github.com/makefu/jura-connect-hass as type Integration.
  2. Install Jura Connect from the list.
  3. Restart Home Assistant.

Manual

Copy custom_components/jura/ into your Home Assistant config/custom_components/ directory and restart.

Configuration

  1. Settings → Devices & Services → Add Integration → Jura Connect.
  2. Choose Search for machines on the network (recommended) or Enter the IP address manually. Discovery shows a progress spinner; empty results route to manual entry.
  3. When prompted, press OK on the coffee machine to accept the pairing. The pairing dialog shows a spinner with a timeout of 60 seconds. The resulting auth-hash is persisted to the config entry; subsequent reconnects skip the on-machine confirmation.
  4. Pick your machine model from the dropdown. Auto-detection pre-selects the right entry when the WiFi dongle replied to UDP discovery (the broadcast carries the article number, which maps to an EF code via the bundled catalogue). Otherwise choose your model — for example S8 (EB) [EF1091] — or pick Use baseline (no profile) for a generic EF536 fallback. Models without a profile won't get per-recipe brew counters or machine-setting entities.

Example automations

Wake me up with espresso (gated on reachability and water)

alias: Morning espresso
trigger:
  - platform: time
    at: "07:00:00"
condition:
  - condition: state
    entity_id: binary_sensor.jura_connectivity
    state: "on"
  - condition: state
    entity_id: binary_sensor.jura_alert_fill_water
    state: "off"
action:
  - service: jura.brew
    target:
      entity_id: sensor.jura_status
    data:
      recipe: "01"

Notify when cleaning is due

alias: Coffee machine needs cleaning
trigger:
  - platform: numeric_state
    entity_id: sensor.jura_service_cleaning_level
    above: 95
action:
  - service: notify.mobile_app
    data:
      message: "Cleaning cycle due — service level {{ states('sensor.jura_service_cleaning_level') }}%"

Reduce auto-off delay at night

alias: Power-saving overnight
trigger:
  - platform: time
    at: "22:00:00"
action:
  - service: select.select_option
    target:
      entity_id: select.jura_setting_auto_off
    data:
      option: "15min"

(Exact entity_id slugs depend on your machine's host / conn-id — check the device page after setup.)

Development

See AGENTS.md for the full development guide. TL;DR:

nix develop -c pytest tests/ -v
nix develop -c ruff check
nix build
./result/bin/jura-connect-ha --version

Acknowledgements

  • jura-connect — the reverse-engineered protocol library this integration wraps. Most of the heavy lifting (handshake, status decoding, command registry, per-machine XML catalogue) lives upstream.
  • The J.O.E. (Jura Operating Experience) Android app, from which the WiFi protocol was originally derived.

About

home-assistant addon for jura wifi coffee machines

Topics

Resources

Stars

15 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages