A custom Home Assistant integration for controlling Melitta Barista T/TS Smart and Nivona NICR 6xx / 7xx / 79x / 9xx / 1030 / 1040 plus NIVO 8xxx coffee machines over Bluetooth Low Energy (BLE). Both brands are built on the shared Eugster/Frismag OEM stack, so a single integration drives either. Monitor machine status, brew recipes, adjust settings, trigger maintenance — all from your Home Assistant dashboard.
This release ships an alpha version of the in-HA admin SPA panel + AI Coffee Sommelier — recipe generation goes through any HA conversation agent (OpenAI / Anthropic / Gemini / GigaChat / SmartChain / Ollama), the result is brewable in one tap. See AI Coffee Sommelier (alpha) below.
📖 Documentation site: dzerik.github.io/melitta-barista-ha — BLE architecture, wire protocol, ADRs and changelog with navigation, search, and rendered Mermaid diagrams.
⚠️ Nivona testers wanted. Nivona support (v0.41.0) is shipped as alpha — cryptography and handshake are validated against upstream RE vectors, but the code path has not been live-tested on real Nivona hardware by the maintainer. If you own a NICR 6xx / 7xx / 79x / 9xx / 1030 / 1040 or NIVO 8xxx machine, please try this release and open a GitHub issue with your results (handshake / status / brew / prompts). See Nivona support below for details.
| Model | Type ID | BLE Prefixes | Recipes | Bean Hoppers |
|---|---|---|---|---|
| Barista T Smart | 258 | 8301, 8311, 8401 | 21 | 1 (single) |
| Barista TS Smart | 259 | 8501, 8601, 8604 | 24 | 2 (dual) |
| Family | Representative models | MyCoffee | Strength | Notes |
|---|---|---|---|---|
| 600 | NICR 660 / 670 / 675 / 680 | 1 | 3 | — |
| 700 | NICR 756 / 758 / 759 / 768 / 769 / 778 / 779 / 788 / 789 | 4 | 3 | aroma balance |
| 79x | NICR 790–797, 799 | 4 | 5 | aroma balance |
| 900 | NICR 920 / 930 | 4 | 5 | fluid ml×10 quirk |
| 900-light | NICR 960 / 965 / 970 | 4 | 3 | — |
| 1030 / 1040 | NICR 1030 / 1040 | 4 | 5 | — |
| 8000 | NIVO 8101 / 8103 / 8107 | 4 | 5 | different brew opcode |
The brand and machine model are automatically detected from the BLE advertisement (Melitta prefixes 8xxx… or Nivona, which advertises as either the legacy NIVONA-NNNNNNNNNN----- form, the bare NNNNNNNNNN----- form, or — on newer firmware like NICR 930 — a 15-digit serial without dashes such as 930254000000000) and confirmed via the BLE protocol. Nivona firmware does not expose recipe-editing opcodes, so recipe/freestyle/profile entities are suppressed for Nivona entries.
Status: the Nivona BrandProfile shipped in v0.41.0 is code-complete and cryptographically validated against the upstream reverse-engineering vectors from mpapierski/esp-coffee-bridge, but the maintainer does not own a Nivona machine and cannot verify live BLE interop. The release is marked pre-release on GitHub.
What's validated in software:
- HU handshake verifier against the published vector
FA 48 D1 7B → 7E 6E(upstream NICR 756) - RC4 runtime key
NIV_060616_V10_1*9#3!4$6+4res-?3(recovered fromde.nivona.mobileapp3.8.6) - 7 family capability entries with per-family brew opcode / strength levels / fluid scaling
- Serial-prefix tokenisation for all known model codes (4-char for NIVO 8xxx, 3-char for NICR 6xx/7xx/79x/9xx)
What live-testing should confirm:
- BLE pairing + D-Bus bonding completes
-
HUsession setup succeeds on real hardware -
HXstatus polling returns sensibleprocess/manipulation/progressvalues -
HZcancel-brew works on an active brew -
HYprompt confirmation works (flush / move cup) -
HDregister reset returns ACK -
HIfeature bits either return a payload or time out gracefully (both OK)
How to help:
- Enable HACS Pre-releases (in HACS settings), install this repo, update to v0.41.0.
- Pair your Nivona via the normal config-flow — it should be auto-discovered.
- Open an issue with the model, firmware version, and a log snippet filtered on
melitta_barista.
Crypto and handshake are identical in structure to Melitta; the risk is primarily per-firmware-family quirks in brew payload bytes and stats register IDs.
- Multi-brand, multi-model — Melitta Barista T/TS Smart + Nivona NICR 6xx / 7xx / 79x / 9xx / 1030 / 1040 + NIVO 8xxx (alpha, NICR 930 validated on real hardware) auto-detected from BLE advertisement; model-specific entity filtering per capability
- Real-time status monitoring — machine state, brewing activity, progress percentage, required user actions, and machine prompts via BLE push notifications
- 21 or 24 built-in recipes (Melitta) — select from dropdown and brew with one tap (3 extra recipes on TS model)
- Freestyle recipes (Melitta) — build custom drinks with two configurable components (coffee/milk/water), adjustable intensity, aroma, temperature, shots, and portion sizes
- Reset recipe to factory defaults (Melitta, v0.33.0+) — HD opcode button with auto-refresh of cached recipe attributes
- Confirm machine prompts (v0.34.0+) — dedicated
Confirm Promptbutton +awaiting_confirmationbinary sensor + optional global auto-confirm for soft prompts (move cup, flush); hardware-blocking prompts (fill water, empty trays) remain manual - Maintenance operations — easy clean, intensive clean, descaling, filter insert/replace/remove, evaporating, power off
- Cancel in-flight brew — HZ opcode, one-click cancel during any running process
- Machine settings control — water hardness, brew temperature, auto-off timer, energy saving, auto-bean-select (TS)
- Feature capability read (HI, v0.32.0+) — diagnostic sensor exposes machine capability bits (e.g.
IMAGE_TRANSFER), graceful on firmwares that don't answer - User profiles (Melitta) — read and edit user profile names on the machine
- Cup counters (Melitta) — total + per-recipe statistics, refreshed after each brew completion
- BLE auto-discovery — integration detects your Melitta or Nivona machine automatically
- Encrypted BLE protocol — full Eugster EFLibrary stack (AES customer-key bootstrap + RC4 stream cipher), per-brand HU verifier tables
- 🤖 AI Coffee Sommelier (alpha) — full in-HA admin panel with a Sommelier tab: pick allowed syrups / toppings / milk, mood (multi-select), cup size, dietary, time-of-day-aware occasion, then generate recipes via your chosen conversation agent (OpenAI / Anthropic / Gemini / GigaChat / SmartChain / Ollama). Each recipe arrives with the full step-by-step preparation, dosages and machine-action — all in your HA UI language — and a single ★ to favourite or "Brew this" to run on the machine. See AI Coffee Sommelier (alpha).
- Custom Lovelace card (Melitta only — Nivona not yet supported) — dedicated card available separately: melitta-barista-card
- Standalone PWA (Melitta only — Nivona not yet supported) — full-screen React app for tablets and kiosks: melitta-barista-app
- 29 languages — full localization for all European and Slavic languages
- 🧪 ESP32 BLE emulator (unique) — a companion ESP-IDF firmware that impersonates a real Nivona machine at the BLE layer (ADV, AD00 service, encrypted frames, HU handshake, HX status, HE brew). Lets you develop, pair, and brew against Home Assistant and the official Nivona Android app without any physical machine. Lives in its own repo: dzerik/nivona-ble-emulator.
| # | Recipe | T | TS | # | Recipe | T | TS |
|---|---|---|---|---|---|---|---|
| 1 | Espresso | + | + | 13 | Dead Eye | -- | + |
| 2 | Ristretto | + | + | 14 | Cappuccino | + | + |
| 3 | Lungo | + | + | 15 | Espresso Macchiato | + | + |
| 4 | Espresso Doppio | + | + | 16 | Caffe Latte | + | + |
| 5 | Ristretto Doppio | + | + | 17 | Cafe au Lait | + | + |
| 6 | Cafe Creme | + | + | 18 | Flat White | + | + |
| 7 | Cafe Creme Doppio | + | + | 19 | Latte Macchiato | + | + |
| 8 | Americano | + | + | 20 | Latte Macchiato Extra | + | + |
| 9 | Americano Extra | + | + | 21 | Latte Macchiato Triple | + | + |
| 10 | Long Black | + | + | 22 | Milk | + | + |
| 11 | Red Eye | -- | + | 23 | Milk Froth | + | + |
| 12 | Black Eye | -- | + | 24 | Hot Water | + | + |
Red Eye, Black Eye, and Dead Eye are only available on the Barista TS Smart (dual bean hopper model).
Nivona machines ship with a fixed set of recipes per family (no recipe editing). Selector IDs below are the machine-side byte values used in the brew command.
| Family | Recipes |
|---|---|
| 600 | Espresso, Coffee, Americano, Cappuccino, Frothy Milk, Hot Water |
| 700 | Espresso, Cream, Lungo, Americano, Cappuccino, Latte Macchiato, Milk, Hot Water |
| 79x | Espresso, Coffee, Americano, Cappuccino, Latte Macchiato, Milk, Hot Water |
| 900 / 900-light | Espresso, Coffee, Americano, Cappuccino, Caffè Latte, Latte Macchiato, Hot Milk, Hot Water |
| 1030 | Espresso, Coffee, Americano, Cappuccino, Caffè Latte, Latte Macchiato, Hot Water, Warm Milk, Hot Milk, Frothy Milk |
| 1040 | Espresso, Coffee, Americano, Cappuccino, Caffè Latte, Latte Macchiato, Hot Water, Warm Milk, Frothy Milk |
| 8000 | Espresso, Coffee, Americano, Cappuccino, Caffè Latte, Latte Macchiato, Milk, Hot Water |
Source: per-family recipe tables in brands/nivona.py, ported from the upstream mpapierski/esp-coffee-bridge RE effort.
🟢 The recommended and primary-tested BLE transport for this integration is an ESPHome
bluetooth_proxyon a $10 ESP32 board placed near the machine. That's the path the maintainer develops and tests on; pair / reconnect / handshake / brew protocol logic accumulate test-hours against it day-to-day. The ESP's BLE stack handlespair=Truenatively, sidestepping every BlueZ quirk (D-BusAgent1,No agent available,Authentication failed, headless-Linuxbluetoothdcrashes) that a host-side BLE adapter can run into.
A bare local Bluetooth adapter (Pi onboard BLE, USB dongle, host chipset)
also works and is fully supported — but the local-adapter / BlueZ path
has fewer accumulated test-hours, so quirks land there first. If you're
starting from scratch, the proxy route trades ~$10 of hardware for
noticeably more predictable behaviour. See HCL.md for confirmed
adapter / board combinations and known quirks.
The repo ships a ready-to-flash ESPHome config at
esphome/ble-proxy-xiao-c6.yaml for the
Seeed XIAO ESP32-C6 (the maintainer's reference board). Any ESP32 / S3 /
C3 / C6 with stock bluetooth_proxy works the same way.
If you run Home Assistant Container (Docker) and want to use the host's
local Bluetooth adapter (not an ESPHome proxy), three prerequisites are
often missed and surface as confusing HU handshake timeout /
Authentication failed errors:
-
Install
bluezon the host (the full daemon, not justbluez-obexd):sudo apt update && sudo apt install -y bluez sudo systemctl enable --now bluetooth
Without
bluetoothdrunning on the host, GATT pairing never completes. -
Mount the D-Bus socket into the container. Add to
docker runordocker-compose.yml:volumes: - /run/dbus:/run/dbus:ro
-
Use
--privilegedor grantNET_ADMINcapability, and run with--net=host. These match HA's expected discovery behaviour and let the integration scan + connect over the host BLE stack.
If a previously-attempted machine is stuck, reset its BlueZ cache from the host:
bluetoothctl disconnect <MAC>
bluetoothctl remove <MAC>
# then put the machine in pair mode and re-add the integrationVerified working: NICR 779 on Mac mini (Apple Broadcom BCM2046B1) /
Ubuntu 24.04 / BlueZ 5.72 / HA Container — see HCL.md for the
full hardware list.
- Home Assistant 2024.1 or newer
- BLE transport — one of:
- ESPHome BLE proxy on an ESP32 (recommended; primary tested path —
see above). The proxy sits in the machine's RF neighbourhood and
bridges BLE traffic over Wi-Fi into HA's
bluetoothintegration. - Local Bluetooth adapter — Pi onboard BLE / USB dongle / host
chipset. Supported but less-tested. See
HCL.mdfor adapter-specific notes.
- ESPHome BLE proxy on an ESP32 (recommended; primary tested path —
see above). The proxy sits in the machine's RF neighbourhood and
bridges BLE traffic over Wi-Fi into HA's
- Supported machine — one of:
- Melitta Barista T Smart or Melitta Barista TS Smart (stable)
- Nivona NICR 6xx / 7xx / 79x / 9xx / 1030 / 1040 or NIVO 8xxx (alpha)
- BLE range — for ESPHome proxy: keep the proxy within ~5 m of the machine; for a local adapter: keep the Home Assistant host within ~10 m of the machine, line of sight where possible.
- Open HACS in your Home Assistant instance.
- Go to Integrations and select the three-dot menu in the top right corner.
- Choose Custom repositories.
- Add the repository URL:
https://github.com/dzerik/melitta-barista-ha - Select category Integration and click Add.
- Search for "Melitta Barista Smart & Nivona" in HACS and install it.
- Restart Home Assistant.
- Download the latest release from the GitHub releases page.
- Copy the
custom_components/melitta_baristadirectory into your Home Assistantconfig/custom_components/directory. - Restart Home Assistant.
⚠️ Melitta only. The card currently expects Melitta-only entities (recipe/profile/freestyle selects, named cup counters) and does not yet handle the Nivona entity layout (per-family stats sensors, Nivona recipe select, brew override numbers). Nivona support is on the roadmap for the card project — track via its issue tracker.
A dedicated Lovelace card with recipe buttons, status display, and progress bar is available as a separate repository:
melitta-barista-card -- install via HACS (Frontend > Custom repositories) or manually.
⚠️ Melitta only. Same caveat as the card — the PWA assumes Melitta-shaped entities (Brew / Freestyle / Stats / Service / Settings tabs all wired against Melitta extensionsHC/HJ). Nivona machines will pair via Home Assistant and entities will appear there, but the PWA UI does not yet render them.
A standalone React PWA for controlling the coffee machine is available as a separate project:
melitta-barista-app -- a full-screen progressive web app designed for wall-mounted tablets and kiosk displays.
- Connects to Home Assistant via WebSocket API using a long-lived access token
- Auto-detects the Melitta machine from HA entities
- Five tabs: Brew, Freestyle, Stats, Service, Settings
- Real-time brewing progress with cancel support
- Installable as a PWA on any device (Android, iOS, desktop)
- Dark coffee-themed UI optimized for touch
Browse all available recipes in a grid, list, or carousel view. Quick-access buttons for favorite recipes and user profiles at the top. Select a recipe and tap Brew to start.
Build a custom drink from scratch with two configurable components. Adjust process type, portion size, intensity, aroma, temperature, and shots for each component. A live glass preview updates as you tweak the parameters.
Cup counter dashboard showing total brewed cups and per-recipe statistics with progress bars.
Maintenance operations: easy clean, intensive clean, descaling, evaporating, water filter management, and power off.
Machine configuration: energy saving, auto bean select, rinsing toggle, water hardness, auto-off timer, and brew temperature.
A companion firmware that impersonates a real Nivona coffee machine at the BLE layer — useful for developing, pairing, brewing, and stress-testing without any physical machine. To the best of the maintainer's knowledge, no other open-source Home Assistant coffee-machine integration ships a paired emulator of the hardware it drives.
Repository: dzerik/nivona-ble-emulator (split out of this repo in v0.51.x for independent release cadence; tags emu-v0.2.0 through emu-v0.7.0 carry forward).
What it emulates
- Advertisement: byte-exact ADV + scan response (company ID
0x0319, customer ID0xFFFF, Eugster manufacturer payload, DIS in SR) — discovered by HA and by the official Nivona Android app just like a real machine - GATT: AD00 service with AD01 (write), AD02 (notify), DIS (0x180A) with manufacturer / model / serial
- Protocol: full Eugster/EFLibrary stack — frame parser, RC4 stream cipher, AES customer-key bootstrap, HU handshake with per-brand verifier, HR/HW/HX/HE/HA/HB opcodes
- State: a small FSM ramps
process/progressduring HE brew (3 → 4 → 3 for NIVO 8000, 8 → 11 → 8 for other Nivona families) and emits unsolicited HX notifications
What you get
- End-to-end pair → discover → brew flow against HA with no hardware
- Regression harness for the BLE client, config flow, and brand-aware HX parser
- Ground truth for the multi-brand architecture: because the emulator speaks Nivona on a bench next to a real Melitta, protocol differences cannot silently regress
Supported targets: ESP32-C6 (primary) and ESP32-S3. See the emulator README for build / flash / troubleshooting.
Make sure Bluetooth is enabled on your coffee machine (refer to the machine manual).
- In Home Assistant, go to Settings > Devices & Services > Add Integration.
- Search for Melitta Barista Smart & Nivona.
- If BLE discovery has found your machine, it will appear automatically. Otherwise, you can enter the MAC address manually.
The integration requires BLE pairing (bonding) with your coffee machine. The machine only accepts SMP from a new BLE central when it is explicitly in pairing mode — this is a one-time step per central.
- On the machine, open the Settings menu and navigate to Bluetooth / Connectivity / App connection.
- Enable pairing mode — the BLE icon on the machine should start blinking (path varies by firmware: look for "Pair new device" / "App-Verbindung" / "Reset connection").
- Press Submit in the Home Assistant setup dialog.
- The integration will connect and pair automatically. If the machine shows a confirmation prompt, accept it.
Note: The machine supports only one active BLE connection at a time. Make sure any official manufacturer app (Melitta Connect / Nivona App) is disconnected before pairing with Home Assistant.
If the device is already paired (e.g., via bluetoothctl), the integration detects this and skips the pairing step. Subsequent reconnects do not require pairing mode — only the very first bond does.
If automatic pairing does not work, you can pair manually via SSH on the Home Assistant host:
bluetoothctl
remove F1:2C:72:3F:75:ED # Replace with your machine's MAC address
scan on # Wait for the machine to appear
pair F1:2C:72:3F:75:ED
trust F1:2C:72:3F:75:ED
info F1:2C:72:3F:75:ED # Verify: Paired: yes, Bonded: yes, Trusted: yes
exitThen add the integration in Home Assistant as described above.
Once configured, the integration creates a device with all available entities filtered for your machine model.
| Entity | Description |
|---|---|
| State | Current machine state: Ready, Brewing, Cleaning, Descaling, Off, etc. |
| Activity | Current sub-process: Grinding, Extracting, Steaming, Dispensing Water, Preparing |
| Progress | Brewing or cleaning progress as a percentage |
| Action Required | Required user action: Fill Water, Empty Trays, Brew Unit Removed, Move Cup to Frother, Flush Required |
| Connection | BLE connection status: Connected or Disconnected (diagnostic) |
| Firmware | Firmware version reported by the machine (diagnostic) |
| Features | Machine capability bits from HI response, plus raw byte in attributes (diagnostic, disabled by default) |
| Total Cups | Total brewed count, per-recipe breakdown in attributes (Melitta only) |
| Entity | Description |
|---|---|
| Awaiting Confirmation | on when the machine is showing a user-confirmable prompt (fill water, move cup, flush, etc.) — pairs with the Confirm Prompt button (PROBLEM device class) |
| Entity | Description |
|---|---|
| Recipe | Dropdown selector for all available recipes (21 on T, 24 on TS). |
| Profile | Active user profile selector. |
| Freestyle Process 1 | Component 1 process: coffee, milk, or water. |
| Freestyle Intensity 1 | Component 1 brew intensity. |
| Freestyle Temperature 1 | Component 1 temperature level. |
| Freestyle Shots 1 | Component 1 number of shots. |
| Freestyle Process 2 | Component 2 process: none, coffee, milk, or water. |
| Freestyle Intensity 2 | Component 2 brew intensity. |
| Freestyle Temperature 2 | Component 2 temperature level. |
| Freestyle Shots 2 | Component 2 number of shots. |
| Entity | Brand | Description |
|---|---|---|
| Brew | Melitta | Brew the recipe selected in the Recipe dropdown. Available when machine is Ready and a recipe is selected. |
| Brew Freestyle | Melitta | Brew the custom freestyle recipe using current freestyle parameters. |
| Cancel | both | Cancel the currently running operation (HZ). |
| Confirm Prompt | both | Acknowledge an active machine prompt (move cup, flush, fill water, etc.) via HY. Available only when awaiting_confirmation binary sensor is on. |
| Reset Recipe | Melitta | Reset the currently selected recipe to factory defaults (HD). Available when machine is Ready and a recipe is selected. Recipe cache auto-refreshes. |
| Easy Clean | both | Start the easy clean cycle (configuration). |
| Intensive Clean | both | Start the intensive clean cycle (configuration). |
| Descaling | both | Start the descaling process (configuration). |
| Filter Insert / Replace / Remove | both | Water filter operations (configuration). |
| Evaporating | both | Steam evaporating cycle (configuration). |
| Switch Off | both | Power off the machine (configuration). |
| Entity | Range | Description |
|---|---|---|
| Water Hardness | 1 -- 4 | Water hardness level for descaling schedule (configuration). |
| Auto Off After | 15 -- 240 min | Idle time before automatic power off (configuration). |
| Brew Temperature | 0 -- 2 | Brew temperature level: 0 = Cold, 1 = Normal, 2 = High (configuration). |
| Freestyle Portion 1 | 5 -- 250 ml | Component 1 portion size in milliliters. |
| Freestyle Portion 2 | 0 -- 250 ml | Component 2 portion size in milliliters (0 = disabled). |
| Entity | Model | Description |
|---|---|---|
| Energy Saving | T, TS | Enable or disable energy saving mode (configuration). |
| Auto Bean Select | TS only | Enable or disable automatic bean blend selection (configuration). |
| Rinsing Disabled | T, TS | Enable or disable the automatic rinsing cycle (configuration). |
| Entity | Model | Description |
|---|---|---|
| Profile 1-4 Name | T | User profile names (read/write, configuration). |
| Profile 1-8 Name | TS | User profile names (read/write, configuration). |
| Freestyle Name | T, TS | Custom name for the freestyle recipe. |
The integration provides five custom services.
Reset a recipe to factory defaults via the HD opcode. Recipe cache is auto-refreshed so the UI / PWA show factory values immediately.
| Parameter | Type | Required | Description |
|---|---|---|---|
entity_id |
string | Yes | Any button entity of the target machine |
recipe_id |
int (200–223) | No | Target recipe; defaults to currently selected |
Acknowledge an active machine prompt via HY (e.g. "move cup to frother", "flush required"). Fails with a ServiceValidationError if no prompt is active.
| Parameter | Type | Required | Description |
|---|---|---|---|
entity_id |
string | Yes | Any button entity of the target machine |
Brew a custom recipe with fully configurable parameters.
| Parameter | Type | Required | Description |
|---|---|---|---|
entity_id |
string | Yes | Any entity from the Melitta device |
name |
string | Yes | Display name for the recipe |
process1 |
string | Yes | Primary process: coffee, milk, water |
intensity1 |
string | No | Intensity: very_mild, mild, medium, strong, very_strong |
aroma1 |
string | No | Aroma: standard, intense |
temperature1 |
string | No | Temperature: cold, normal, high |
shots1 |
string | No | Shots: none, one, two, three |
portion1_ml |
int | No | Portion size in ml (20-300) |
process2 |
string | No | Secondary process (same options + none) |
two_cups |
bool | No | Brew two cups (default: false) |
Brew from a DirectKey profile slot (uses the active profile's personalized recipe).
| Parameter | Type | Required | Description |
|---|---|---|---|
entity_id |
string | Yes | Any entity from the Melitta device |
category |
string | Yes | espresso, cafe_creme, cappuccino, latte_macchiato, milk, milk_froth, water |
two_cups |
bool | No | Brew two cups (default: false) |
Save a recipe to a DirectKey profile slot.
| Parameter | Type | Required | Description |
|---|---|---|---|
entity_id |
string | Yes | Any entity from the Melitta device |
category |
string | Yes | Recipe category (same as brew_directkey) |
profile_id |
int | No | Profile ID (default: active profile) |
| (recipe params) | — | — | Same as brew_freestyle |
Manual one-tap recovery for a wedged BLE pairing (see BLE pairing recovery). Walks every Melitta entry, finds the ESPHome proxy that owns each scanner, and reloads it to evict HA-side BLEDevice cache. No parameters. Equivalent to Configure → Repair connection in Options Flow.
Configure the integration via Settings → Devices & Services → Melitta Barista Smart & Nivona → Configure.
| Parameter | Default | Range | Description |
|---|---|---|---|
| Poll interval | 5s | 1-60s | How often to poll machine status |
| Reconnect delay | 5s | 1-60s | Initial delay before reconnect attempt |
| Reconnect max delay | 300s | 30-3600s | Maximum backoff between reconnects |
| Poll errors before disconnect | 3 | 1-20 | Consecutive errors before forcing disconnect |
| Frame timeout | 5s | 2-30s | BLE command response timeout |
| Auto-confirm soft prompts | off | bool | When on, the integration automatically sends HY for soft prompts (move cup, flush). Hardware prompts (fill water, empty trays) stay manual. |
| Parameter | Default | Range | Description |
|---|---|---|---|
| BLE connect timeout | 15s | 5-60s | Timeout for BLE connection establishment |
| Pairing timeout | 30s | 10-120s | Timeout for BLE pairing during setup |
| Recipe retries | 3 | 1-10 | Retry attempts for recipe read/write operations |
| Initial connect delay | 3s | 0-30s | Wait before first connection after setup |
| Data | Method | Frequency |
|---|---|---|
| Machine status | BLE push notifications | Every ~5 seconds |
| Cup counters | Read after each brew completes | On brew finish |
| Profile data | Read once on connect | On connection |
| Settings | Read on entity setup | On demand |
🧪 Alpha — end-to-end works, expect rough edges.
The whole pipeline is now in place: an in-HA admin SPA panel with a Sommelier tab generates recipes via any HA conversation agent and turns them into a Freestyle brew on the machine with one tap. We're flagging it alpha because (a) the result quality depends heavily on the chosen LLM and the producer page it grounds against, (b) the favourites browser / history view aren't built yet (the backend is —
/sommelier/favorites/*,/sommelier/history/list), and (c) the WebSocket schemas may still tighten before 1.0. Please report issues with thesommelierlabel.
End-to-end flow that works today:
- Open the Melitta sidebar entry → Beans tab → add producers, add beans (use Заполнить через LLM for autofill from brand + product + producer URL).
- Additives tab → add syrups / toppings / milk you actually keep.
- Settings tab → pick your LLM model from the dropdown (OpenAI, Anthropic, Gemini, GigaChat, SmartChain, Ollama — anything registered as an HA conversation agent). Edit the prompt template if you like; the JSON Schema for the response is auto-appended.
- Sommelier tab → narrow allowed syrups / toppings / milk via chips, set mood (multi-select), cup size, occasion (suggested by local clock), temperature, caffeine, dietary — hit Generate.
- Each recipe card shows the machine portion (
Machine: coffee 30 ml strong …) plus a numbered step list with dosages (1. Brew espresso — 30 ml,2. Add Vanilla syrup — 15 ml,3. Pour foamed milk — Oat — 120 ml) — in your HA UI language. ★ to favourite, "Brew this" to send the freestyle payload to the machine.
Highlights:
- Hybrid structured output: when SmartChain (or a similar provider) is selected, the request goes through that integration's native JSON Schema mode (OpenAI Structured Outputs / Gemini responseSchema / Anthropic tool-use / Ollama 0.5+ format=schema). For everything else we append the JSON Schema to the prompt and run a Pydantic-validated text-with-retry path.
- Locale-aware: HA's UI language is forwarded so names / descriptions / step instructions come back in Russian / German / French / etc., while enum values stay English so the schema validates regardless.
- Free-form vocabularies: flavor tags, milk types, syrups, toppings — all open strings. Add «Ультрапастеризованное 3%» or «дрип-кофе» — it just works.
- Diagnostics → Recent LLM calls: the panel surfaces every LLM round-trip with the full assembled prompt, raw response, validation errors, and the path that handled it (
smartchain_structuredvstext_with_validation).
Requirements: at least one conversation integration configured in HA. We recommend SmartChain (multi-provider through LangChain) when you want native structured-output mode; any single-provider HA Conversation agent works through the text+validation fallback.
Tracking: see open issues tagged sommelier in the issue tracker.
The integration is built on a three-layer abstraction (v0.40.0+) that cleanly separates:
- BLE transport (shared) — pairing, reconnect, write/notify GATT characteristics.
- Eugster/EFLibrary core (shared) — frame format
0x53…0x45, one's-complement checksum, RC4 stream cipher,HU/HV/HR/HW/HX/HE/HZ/HY/HD/HI/HA/HBopcodes. - Brand profile (pluggable) — RC4 runtime key, HU verifier table, advertisement regex, supported opcode extensions (
HC/HJfor Melitta only), per-family machine capabilities.
Adding a third Eugster OEM brand (e.g. if public RE emerges for Koenig, KitchenAid, etc.) is a matter of dropping a new file into brands/. See docs/adr/001-brand-profile-abstraction.md.
- Smart Home Dashboard — monitor coffee machine status, cup counters, and maintenance needs on your HA dashboard
- Morning Routine — automated brewing at a scheduled time via HA automations
- Family Profiles — switch between user profiles for personalized drinks
- Maintenance Alerts — get notified when descaling, filter change, or other maintenance is needed
- Kiosk Mode (Melitta only) — use the standalone PWA on a wall-mounted tablet
automation:
- alias: "Morning Espresso at 7:00"
trigger:
- platform: time
at: "07:00"
condition:
- condition: state
entity_id: sensor.melitta_state
state: "ready"
action:
- service: button.press
target:
entity_id: button.melitta_brew_espressoautomation:
- alias: "Coffee Ready Notification"
trigger:
- platform: state
entity_id: sensor.melitta_activity
from: "extracting"
to: "idle"
action:
- service: notify.mobile_app
data:
message: "Your coffee is ready! ☕"automation:
- alias: "Coffee Machine Maintenance Reminder"
trigger:
- platform: state
entity_id: sensor.melitta_action_required
condition:
- condition: not
conditions:
- condition: state
entity_id: sensor.melitta_action_required
state: "none"
action:
- service: notify.mobile_app
data:
message: "Coffee machine needs attention: {{ states('sensor.melitta_action_required') }}"- Go to Settings → Devices & Services → Melitta Barista Smart & Nivona
- Click the three-dot menu (⋮) → Delete
- The BLE connection will be closed and all entities removed automatically
- If installed via HACS: go to HACS → Integrations → Melitta Barista Smart & Nivona → Uninstall
The integration includes translations for 29 languages:
English, Russian, Ukrainian, German, Polish, Czech, Slovak, French, Italian, Spanish, Portuguese, Dutch, Swedish, Danish, Norwegian, Finnish, Hungarian, Romanian, Greek, Turkish, Bulgarian, Croatian, Serbian, Slovenian, Bosnian, Macedonian, Estonian, Latvian, Lithuanian.
- BLE range: Bluetooth Low Energy has a limited range (typically up to 10 meters). Walls and other obstacles reduce effective range. Consider placing a Bluetooth-capable device (e.g., an ESPHome BLE proxy) near the machine if your Home Assistant host is too far away.
- Single connection: The machine supports only one active BLE connection at a time. If the official Melitta app is connected, the integration will not be able to connect, and vice versa.
- Single BLE client: The integration operates as a single BLE client. User profile names can be read and edited, but per-profile recipe customizations are not yet exposed.
- Polling interval: Machine status is polled every 5 seconds while connected. There may be a brief delay between a physical action and the state update in Home Assistant.
- Recipe parameters: Built-in recipes use the machine's stored default parameters. For full customization, use the Freestyle recipe builder with adjustable process, intensity, temperature, shots, and portion for each component.
The integration supports two BLE transports:
- Local BlueZ adapter on the Home Assistant host (works out of the box on HA OS hardware with a Bluetooth radio).
- ESPHome BLE proxy — a small ESP32 board flashed with our reference config, placed near the machine. Strongly recommended if you have any range or interference issues. Significantly more stable on long-running setups.
esphome/ contains two production-tested configs:
| File | Hardware | Notes |
|---|---|---|
ble-proxy-xiao-c6.yaml |
Seeed Studio XIAO ESP32-C6 | Single-core RISC-V, RF switch for external antenna |
ble-proxy-xiao-s3.yaml |
Seeed Studio XIAO ESP32-S3 | Dual-core LX7 with 8MB PSRAM, more connection slots |
Both ship with the following recovery-related extras on top of the upstream ESPHome reference:
- Custom action
clear_ble_bonds— wipes the ESP NVS bond table (esp_ble_remove_bond_devicefor every stored peer). Surfaces in HA asesphome.<proxy_name>_clear_ble_bonds. - Custom action
disconnect_ble_peer— surgical GAP disconnect of a stuck connection slot. Surfaces asesphome.<proxy_name>_disconnect_ble_peerwith apeer_macparameter. factory_resetbutton — nuke option for the entire NVS (last-resort recovery; WiFi creds + OTA password are baked into firmware, so they survive).safe_modebutton — boots into recovery mode (API + OTA only) for fixing bad configs.BLE bondstext sensor — live count fromesp_ble_get_bond_device_num()updated every 30 s. Lets you confirmclear_ble_bondsactually emptied NVS.
After flashing one of these to your proxy, all four buttons + the bond-count sensor appear in HA under the proxy's device card, and the two custom services become callable from Developer Tools or automations.
Important: if you used an earlier release of these YAML files, reflash via the ESPHome dashboard (OTA) to pick up
clear_ble_bonds,disconnect_ble_peer, and thefactory_resetbutton. Without these the recovery flow below falls back to a partial path.
Long quiet periods, ESP-proxy restarts, machine factory resets, and certain Home Assistant restart sequences can leave the pairing wedged on either side. The symptom is one or more of:
- The machine displays a red Bluetooth indicator (it's actively rejecting our handshake).
- Logs show
HU handshake timeoutfrom the integration. - ESPHome proxy logs show
auth fail reason=82(SMP rejection) and/orConnection request ignored, state: ESTABLISHED.
The integration ships three escalating recovery paths, all of which used to require deleting and re-adding the entry. They now work without removing the integration.
After 5 consecutive failed connects the reconnect loop automatically reloads the ESPHome proxy ConfigEntry. This evicts the cached BLEDevice from habluetooth._previous_service_info; the next advertisement rebuilds it with a fresh source and address_type. Manual trigger: Settings → Devices & Services → your Melitta entry → Configure → Repair connection.
A Repair Issue surfaces in the UI the moment auto-trigger fires, with a link to issue #10 and a 3-step recovery list.
When the soft path isn't enough, Configure → Force re-pair (hard):
- Disconnects our client.
- Calls
esphome.<proxy>_clear_ble_bonds— ESP NVS bond table wiped. - Calls
esphome.<proxy>_disconnect_ble_peer— surgical GAP disconnect, releases the stuckstate: ESTABLISHEDconnection slot. - Reloads the ESPHome ConfigEntry — evicts HA-side cached BLEDevice.
- Re-arms our reconnect loop.
Before pressing Submit, put the machine into pairing mode (Settings → Bluetooth → Pair new device / App-Verbindung — path varies by firmware). Without pairing mode the machine refuses the fresh SMP exchange with auth fail reason=82. Once the bond is created, subsequent reconnects do not need pairing mode.
If even Force re-pair doesn't work, press the Factory reset button on the proxy device card. It wipes the entire ESP NVS — bond table, every cached preference. WiFi and OTA password survive (they're baked into the firmware). After the device reboots, run Force re-pair from HA with the machine in pairing mode.
The service melitta_barista.repair_connection runs the same soft-repair routine across every Melitta entry. Useful as a one-tap button or scheduled automation. The two ESPHome services (clear_ble_bonds, disconnect_ble_peer) are also exposed for granular control.
The machine is not discovered during setup
- Verify that Bluetooth is enabled on the machine (check the machine display or manual).
- Ensure the Home Assistant host has a working Bluetooth adapter. Run
bluetoothctl scan onon the host to verify BLE scanning works. - Move the Home Assistant host closer to the machine.
- Make sure no other device (e.g., the Melitta app on your phone) is currently connected to the machine.
Connection fails with "D-Bus connection lost"
- The device is not paired with the Home Assistant host. Follow the pairing instructions in the Configuration section above.
- If already paired, try removing and re-pairing:
bluetoothctl remove <MAC> && bluetoothctl pair <MAC>.
Connection drops frequently
- BLE connections are sensitive to distance and interference. Reduce the distance between the host and the machine.
- Consider using an ESPHome Bluetooth proxy placed near the machine.
- Check Home Assistant logs for BLE-related errors: Settings > System > Logs, then filter for
melitta_barista.
Buttons show as unavailable
- Recipe and maintenance buttons are only available when the machine state is "Ready". Check the State sensor.
- If the State sensor shows "unavailable", the BLE connection may be lost. Check the Connection sensor.
Settings do not update
- Number and switch entities read values from the machine. If the machine is disconnected, the last known value is displayed. Reconnect and trigger a manual refresh if needed.
Enable debug logging
Add the following to your configuration.yaml:
logger:
default: info
logs:
melitta_barista: debugRestart Home Assistant and reproduce the issue, then check the logs.
This project is an independent, open-source, non-commercial integration created for personal and home automation purposes. It is not affiliated with, endorsed by, or connected to Melitta Group Management GmbH & Co. KG, Nivona Apparate GmbH, Eugster/Frismag AG, or any of their subsidiaries or affiliates.
"Melitta", "Barista T Smart", "Barista TS Smart", "Caffeo", and the Melitta logo are registered trademarks of Melitta Group Management GmbH & Co. KG. "Nivona", "NICR", "NIVO", "NIVO 8000", and the Nivona logo are registered trademarks of Nivona Apparate GmbH. "Eugster", "Frismag", and associated product names are trademarks of Eugster/Frismag AG. All product names, logos, brands, and graphical assets are the property of their respective owners and are used here solely for identification and interoperability purposes.
This software is not intended for commercial use or the generation of revenue. See NOTICE for full legal details.
Contributions are welcome. Please open an issue or submit a pull request on GitHub.
- Fork the repository.
- Create a feature branch.
- Make your changes and add tests where applicable.
- Submit a pull request with a clear description of the changes.
This project is licensed under the MIT License.




