Skip to content

Repository files navigation

De'Longhi Coffee Link for Home Assistant

GitHub release (latest by date) hacs_badge License Validate

Open in HACS Add Integration

Home Assistant custom integration for DeLonghi PrimaDonna Soul and other Ayla-based DeLonghi coffee machines, controlled through the Coffee Link cloud.

Supported machines

Any DeLonghi coffee machine exposed by the Coffee Link mobile app through Ayla Networks IoT. Confirmed working:

  • PrimaDonna Soul ECAM610.xx, ECAM612.xx, ECAM613.xx (oem_model = DL-millcore) - works out of the box.
  • Eletta Explore ECAM45x.xx (oem_model = DL-striker-cb) - beverages and power-on confirmed working; needs a one-time "teach from the app" step per drink (see Eletta Explore below).
  • Other Coffee Link Wi-Fi machines may work; the same teach-from-app mechanism applies.

Features

  • 21 beverage buttons (Espresso, Cappuccino, Latte Macchiato, Hot Water, Tea, etc.)
  • Wake and Standby buttons (power the machine on / off remotely)
  • Counters sensors (total beverages, per-drink counters, descale status)
  • Machine Status (standby, ready, rinsing, dispensing...) and Connection Status sensors, plus Last Connected - when the machine established its current cloud connection
  • Generic Stop button
  • Services for raw binary command injection (advanced use)

When the machine is unreachable

The cloud accepts a command for a machine that is offline and answers 200 OK; the machine simply never receives it. So when the cloud reports your machine as offline, commands are refused with a clear error instead of being written into the void - check that the machine is powered at the mains and joined to Wi-Fi. Connection Status tells you how the cloud sees it right now, and Last Connected when it last established that connection. A machine merely in standby stays online and can still be woken, and send_raw_command is never blocked so you can always poke a machine by hand.

Eletta Explore (and other non-Soul models)

The PrimaDonna Soul this integration was built on uses a fixed beverage command. The Eletta Explore (oem_model = DL-striker-cb) - and likely other non-Soul models - uses a different, variable-length command (the recipe, quantity, intensity and milk are all encoded in the bytes, and the frame carries a per-device signature). Rather than guess those bytes, the integration learns the exact command your machine's official app sends and replays it - which is reliable by construction.

So on an Eletta Explore there is a one-time teach step, after which everything works from Home Assistant (and is remembered across restarts):

Beverages

  1. Make sure Home Assistant is running and the machine is online.
  2. Start each drink once from the official Coffee Link app. Home Assistant captures the exact bytes (you can confirm on the Last Captured Command diagnostic sensor: style: eletta, crc_valid: true).
  3. From then on, the matching Home Assistant button (or start_beverage service) brews that drink.

Power-on (Wake)

  1. With Home Assistant running, power the machine on once from the official app.
  2. From then on the Wake button powers it from standby.

Power-off (Standby) The official app has no power-off control, so this frame is always synthesized (84 0f, params 01 01 - validated live on the reference Soul). On Eletta-style models it needs the per-device signature, which is taken from any frame already learned (e.g. the wake frame) - so once the Wake teach step above is done, the Standby button works too.

If you change a drink's settings in the app (e.g. quantity), start it once more from the app so Home Assistant re-learns the new bytes.

Why the teach step also unlocks the cloud session. ECAM machines only obey commands sent inside a cloud session registered with their own 4-byte device signature - the one they append to every frame. That signature is read from the first frame you teach, so before any teach step the machine may accept a command (HTTP 200, valid CRC, machine_status: ready) and simply do nothing. The Cloud Session app_id diagnostic sensor shows which id is in use through its session_id_source attribute (device_signature once taught, default_constant before). See issue #15.

A read-only Dump Recipe Datapoints diagnostic button is also provided; it logs the recipe definitions the machine stores (it sends nothing to the machine). See issue #1 for the reverse-engineering details.

IMPORTANT - Coffee Link mobile app must be closed

The machine prioritizes LAN connections over cloud. As long as the Coffee Link mobile app is running on a phone on the same Wi-Fi network, it holds a LAN session (30s keep-alive) and the machine ignores cloud commands.

Close the Coffee Link app completely (swipe from recents) before using Home Assistant. If you want to regain control from the app, just reopen it.

A future version of this integration will include a local LAN server to bypass this limitation.

Installation

Via HACS (recommended)

One-click install - click the badge below (requires HACS already installed in your HA) :

Open in HACS

Or manually :

  1. In HACS, click the 3-dots menu > Custom repositories
  2. Add https://github.com/actabi/delonghi_coffeelink as category Integration
  3. Install "De'Longhi Coffee Link"
  4. Restart Home Assistant
  5. Click this badge to add the integration :

Add Integration

  1. Enter your Coffee Link email and password (same as the mobile app)

Manual

  1. Copy custom_components/delonghi_coffeelink/ to your HA config/custom_components/
  2. Restart Home Assistant
  3. Add integration via Settings > Devices & Services

Services

# Start a beverage
service: delonghi_coffeelink.start_beverage
data:
  beverage: hot_water  # espresso, cappuccino, latte_macchiato, etc.

# Stop a beverage
service: delonghi_coffeelink.stop_beverage
data:
  beverage: hot_water

# Send a raw binary command (advanced)
service: delonghi_coffeelink.send_raw_command
data:
  value_base64: DQ2D8BABDwD6GwEGgSRp6Myg

Technical details

This integration implements the Coffee Link authentication and command protocol:

  1. Authenticate to Gigya (SAP Customer Data Cloud) identity service
  2. Request a signed JWT (HMAC-SHA1 over the Gigya session)
  3. Exchange the JWT for an Ayla Networks SSO token
  4. Poll Ayla Networks IoT cloud for 312 device properties
  5. Send binary commands via the data_request property (base64-encoded)

Beverage command format - PrimaDonna Soul (fixed 18 bytes):

byte  0-1  : 0x0d 0x0d       prefix + length
byte  2-3  : 0x83 0xf0       command family: beverage
byte  4    : beverage_id     0x01 = espresso, 0x10 = hot water, etc.
byte  5    : action          0x01 = start, 0x02 = stop
byte  6-11 : recipe params   temperature, quantity, aroma
byte 12-13 : CRC16 AUG-CCITT over bytes 0..11
byte 14-17 : Unix timestamp (big-endian)

Eletta Explore (DL-striker-cb) uses a variable-length frame: the same 0x83 0xf0 <bev> <action> header, then a variable recipe block (quantity in ml, intensity and milk encoded inline), the same CRC16 AUG-CCITT (over the whole frame before the CRC), the timestamp, and a 4-byte per-device signature. Because the recipe layout varies, the integration does not synthesize this frame; it replays the exact frame captured from the official app (see Eletta Explore). The power-on frame uses family 0x84 0x0f and is handled the same way.

Diagnostics - capturing what the official app sends

If commands are accepted by the cloud (no error) but your machine does nothing

  • common on models other than the PrimaDonna Soul this was built on - the integration can capture the exact bytes the official Coffee Link app sends, so they can be compared to what it generates.

Each device has a diagnostic sensor Last Captured Command (sensor.<machine>_last_captured_command). To use it:

  1. Make sure the integration is running and the device is online.
  2. Open the official Coffee Link app and start a beverage (e.g. an espresso).
  3. Within one polling cycle (~30 s), open Developer Tools -> States and look at sensor.<machine>_last_captured_command.
    • State = the app's raw base64 command.
    • Attributes decode it: origin (app vs integration), beverage_name, params, crc_valid, and matches_integration.
  4. matches_integration: true means the integration generates the same bytes as the app (so any "machine ignores it" issue is environmental - e.g. the app holding the local session, see the note above). matches_integration: false means the app uses different bytes - paste this sensor's attributes into a GitHub issue and the command builder can be corrected for your model.

App-originated captures are also logged (enable debug logging for custom_components.delonghi_coffeelink) as CAPTURED app->machine command ....

Adding a new machine model

Your machine isn't a PrimaDonna Soul or an Eletta Explore? It very likely already works. Unknown models default to the learn-and-replay path: trigger each drink (and power-on) once from the official Coffee Link app, Home Assistant captures the exact bytes and replays them (see Eletta Explore for the procedure). That works on any Coffee Link machine without any code change.

If you'd like first-class support for your model (so it's recognised by name, and so we can document/optimise it), open an issue with the data below. Everything needed is already exposed by the integration's diagnostics - no network sniffing, no rooting, just copy/paste.

1. Identify the machine

  • Commercial name + full reference under the machine (e.g. Maestosa ECAM650.85.MS).
  • Coffee Link account region (EU / US).
  • The oem_model and sw_version: enable debug logging for custom_components.delonghi_coffeelink, restart, and copy the Discovered DeLonghi device: log line.

2. What the official app sends (the ground truth we replay) For each drink you care about, start it from the official app with Home Assistant running, then copy the Attributes of the ...Last Captured Command sensor (Developer Tools → States). Do the same for power-on. Each block shows style, beverage_id, the full recipe/hex, crc_valid, and the device signature - exactly what's needed.

3. The recipes the machine stores (for the optional "zero-touch" path) Press the Dump Recipe Datapoints diagnostic button and paste the logged block (it's read-only - it sends nothing to the machine).

4. Does it work after teaching? Tell us whether the Home Assistant buttons brew/power the machine after you've triggered them once from the app (yes/no per drink, and whether the machine was already on or in standby).

With that, adding first-class support is usually just a new ModelProfile subclass in model_profiles.py (detection rule + whether it learns from the app) - nothing else in the integration needs to change. The Eletta Explore reverse-engineering, captured frame-by-frame this way, is tracked in issue #1 as a worked example.

Credits

Disclaimer

This is an unofficial integration. De'Longhi and Ayla Networks may change the protocol at any time. Use at your own risk.

License

MIT

About

Home Assistant integration for De'Longhi PrimaDonna Soul and other Coffee Link machines (Ayla cloud protocol)

Topics

Resources

Stars

11 stars

Watchers

3 watching

Forks

Releases

Packages

Contributors

Languages