A Home Assistant custom integration for brewing custom multi-step coffee recipes on Beko/Miele/Jura/similar smart coffee machines.
- 🧾 Define recipes with multiple steps (e.g. Macchiato → Americano)
- 🔀 Flexible steps — each step can brew a Drink, run one or more auxiliary switches (milk frothing, hot water, espresso shot) a configurable number of times, or both at once
- 🗂️ Manage recipes directly from the HA UI — no YAML editing required
- 🛡️ Fault monitoring — pauses recipe and auto-resumes after fault is cleared
- 📱 Notifications — persistent HA notification + optional mobile push
- 🖥️ Config Flow — full UI setup, no YAML editing required for setup
- 📝 Recipes also editable via
coffee_recipes.yamlin your HA config directory - 🎛️ Device page controls — Select Recipe dropdown + Brew/Abort/View buttons
- 📊 Brew statistics — persistent count per recipe + last completed timestamp
- 🔧 HACS compatible with integration icon
- Open HACS in Home Assistant
- Go to Integrations → click the three-dot menu → Custom repositories
- Add this repository URL and select category Integration
- Click Download
- Restart Home Assistant
- Go to Settings → Devices & Services → Add Integration
- Search for Coffee Recipe Manager
The config flow will guide you through 3 steps:
- Machine entities — select your drink selector, start switch (used to detect when brewing starts and finishes), and auxiliary switches (the switches you want available as per-step actions, e.g. milk frothing, hot water dispensing, espresso shot). The work state sensor field is still present for backward compatibility but is no longer used for completion tracking.
- Fault sensors — select all binary sensors that indicate machine errors
- Notifications — optional mobile push service + recipes file name
Go to Settings → Devices & Services → Coffee Recipe Manager → Configure.
The options menu has two sections:
Update machine entities (including the auxiliary switches list), fault sensors, and notification service.
Three actions are available:
- Click Configure on the integration card
- Choose Manage recipes → Add new recipe
- Fill in Recipe name and optional Description, then click Submit
- For each step, fill in:
- Drink — select from the dropdown (choose — None — to skip the drink action)
- Double portion — toggle for a double dose
- Switch 0 / Switch 1 / … — one number field per configured auxiliary switch; set how many times each should run (0 = skip, 1–10 = repeat that many times). Switches run sequentially before the drink.
- Timeout — max seconds to wait per action
- Add another step — enable to continue adding more steps
- On the last step disable Add another step and click Submit — the recipe is saved immediately
The auxiliary switch fields are labelled
Switch 0,Switch 1, etc. The step description shows which entity each index maps to. Configure the switch list once in Machine Settings → Auxiliary switches.
The recipe key (used in automations) is auto-generated from the name, e.g. Morning Boost → morning_boost.
- Choose Manage recipes → Edit recipe
- Select the recipe from the dropdown
- Modify name and description, then step through all steps one by one (the form pre-fills existing values, including previous switch counts and drink selection)
- Click Submit on the last step
- Choose Manage recipes → Delete recipe
- Select the recipe to remove
- Click Submit — permanently deleted from the YAML file
Recipes are also editable directly in <ha_config>/coffee_recipes.yaml. An example file is created automatically on first run:
recipes:
macchiato_americano:
name: "Macchiato + Americano"
description: "Double macchiato followed by americano"
steps:
- drink: LatteMacchiato
double: false
timeout: 300
- drink: Americano
double: false
timeout: 300| Field | Required | Default | Description |
|---|---|---|---|
drink |
✅ | — | Drink name from the machine's select entity |
double |
❌ | false |
Activate the double-portion switch |
timeout |
❌ | 300 |
Max seconds to wait for the machine to finish |
Activates auxiliary machine switches — milk frothing, hot water dispensing, raw espresso shot, etc. Each switch can be run a configurable number of times. Switches execute sequentially, each with full fault monitoring. A step can include both a drink and switches.
Preferred format (v0.3.3+, generated by the UI):
| Field | Required | Default | Description |
|---|---|---|---|
switch_counts |
✅ | — | Map of {entity_id: count} — count 0 = skip, 1+ = repeat N times |
timeout |
❌ | 300 |
Max seconds to wait per run for the switch to turn OFF |
steps:
- switch_counts:
switch.coffee_machine_milkfrothing: 2
switch.coffee_machine_espressoshot: 1
timeout: 120Combined drink + switch step:
steps:
- drink: LatteMacchiato
switch_counts:
switch.coffee_machine_milkfrothing: 1
timeout: 300Legacy formats (still supported for backward compatibility):
| Field | Description |
|---|---|
switch: entity_id |
Single switch, run once |
switches: [e1, e2] |
List of switches, each run once |
Commonly used auxiliary switches:
switch.coffee_machine_milkfrothingswitch.coffee_machine_hotwaterdispensingswitch.coffee_machine_espressoshot
Espresso, Americano, CafeLatte, LatteMacchiato, Ristretto, Doppio, EspressoMacchiato, RistrettoBianco, FlatWhite, Cortado, IcedAmericano, IcedLatte, Hotwater, HotMilk, TravelMug, Cappuccino
| Service | Description |
|---|---|
coffee_recipe_manager.brew_recipe |
Start a recipe by key name |
coffee_recipe_manager.abort_recipe |
Abort current recipe |
coffee_recipe_manager.reload_recipes |
Reload YAML after manual edits |
coffee_recipe_manager.add_recipe |
Add/update recipe via service call |
coffee_recipe_manager.delete_recipe |
Delete a recipe by key |
coffee_recipe_manager.list_recipes |
Show all recipes with keys in a notification |
coffee_recipe_manager.get_recipe |
Show full details of one recipe in a notification |
Useful from Developer Tools → Actions or in automations/scripts:
# 1. See all available recipe keys
service: coffee_recipe_manager.list_recipes
# 2. See full steps of a specific recipe
service: coffee_recipe_manager.get_recipe
data:
recipe_name: morning_boost
# 3. Add or update a recipe
service: coffee_recipe_manager.add_recipe
data:
name: "Morning Boost"
description: "Quick start"
steps:
- drink: Espresso
double: false
timeout: 120
- drink: Americano
double: false
timeout: 300
# 4. Delete a recipe
service: coffee_recipe_manager.delete_recipe
data:
recipe_name: morning_boostautomation:
- alias: "Morning coffee"
trigger:
- platform: time
at: "07:30:00"
action:
- service: coffee_recipe_manager.brew_recipe
data:
recipe_name: macchiato_americano| Entity | Description |
|---|---|
sensor.coffee_recipe_status |
Current status: idle, running, completed, error |
select.coffee_recipe_select_recipe |
Dropdown to pick which recipe to brew |
button.coffee_recipe_brew_selected_recipe |
Brew the currently selected recipe |
button.coffee_recipe_view_selected_recipe |
Show selected recipe details in a notification |
button.coffee_recipe_edit_recipes |
Send a notification with a link to the recipe editor |
button.coffee_recipe_abort_recipe |
Abort the current recipe |
recipe_name— currently running recipecurrent_step/total_steps— step progresscurrent_step_drink— drink being prepared right now (e.g.LatteMacchiato)last_recipe— name of last completed recipelast_completed_at— ISO timestamp of last completion (persisted across restarts)brew_count— dict of how many times each recipe was brewed (persisted)error— error message if status iserror
Option 1 — Developer Tools:
Go to Developer Tools → States, search for coffee_recipe_status — all attributes are listed there.
Option 2 — Dashboard card: Add a Markdown card to any dashboard:
type: markdown
content: |
## ☕ Coffee Recipe Manager
**Status:** {{ states('sensor.coffee_recipe_manager_recipe_status') }}
**Recipe:** {{ state_attr('sensor.coffee_recipe_manager_recipe_status', 'recipe_name') }}
**Step:** {{ state_attr('sensor.coffee_recipe_manager_recipe_status', 'current_step') }} / {{ state_attr('sensor.coffee_recipe_manager_recipe_status', 'total_steps') }}
**Now brewing:** {{ state_attr('sensor.coffee_recipe_manager_recipe_status', 'current_step_drink') }}
**Last brew:** {{ state_attr('sensor.coffee_recipe_manager_recipe_status', 'last_recipe') }} at {{ state_attr('sensor.coffee_recipe_manager_recipe_status', 'last_completed_at') | as_datetime | as_local }}
**Brew counts:** {{ state_attr('sensor.coffee_recipe_manager_recipe_status', 'brew_count') }}Option 3 — Automation condition (example):
condition:
- condition: template
value_template: >
{{ (now() - state_attr('sensor.coffee_recipe_manager_recipe_status', 'last_completed_at') | as_datetime)
.total_seconds() > 1800 }}Want to open the recipe editor without leaving your dashboard?
Press the Edit Recipes button (button.coffee_recipe_edit_recipes) from the device Controls card. It sends a persistent notification in HA with a clickable link that takes you directly to the integration's configuration page where you can add, edit or delete recipes.
Add a button card to any dashboard that navigates directly to the recipe editor with a single tap:
type: button
name: Edit Recipes
icon: mdi:pencil-box
tap_action:
action: navigate
navigation_path: /config/integrations/integration/coffee_recipe_managerThis card requires no integration changes — paste it anywhere in your Lovelace YAML.
If any fault sensor turns on during brewing (e.g. water empty, tray full):
- Recipe pauses immediately
sensor.coffee_recipe_status→waiting_fault_clear- Persistent notification appears in HA:
⚠️ Recipe paused — fix the issue and brewing will resume automatically - Mobile push sent (if configured)
Once the fault is resolved (sensor turns off):
- Integration detects the change automatically
- Waits 2 seconds for the machine to stabilise
- Restarts the current step from the beginning (re-selects drink, re-starts machine)
- Sends a ✅ Fault resolved. Resuming recipe... notification
sensor.coffee_recipe_status→running
You can call
coffee_recipe_manager.abort_recipeat any time to cancel instead of waiting.
- Only one recipe can run at a time. Starting a new one aborts the current.
- The integration checks for faults before each step and during brewing.
timeoutper step defaults to 300s (5 min). Adjust for slow machines.- Brew completion is tracked by monitoring the start switch entity (ON → OFF cycle), not the work state sensor. This is polling-independent and works uniformly for both drink and switch steps.
- Switch steps (direct switch activation) use the same completion logic as drink steps: the executor turns the switch ON and waits for it to turn OFF, with full fault monitoring and retry-on-fault-clear.