Skip to content

Navigation Menu

Sign in
Sign up

Feature Discussion: (smart) grinder integration and assisted dial-in #707

MaxRink started this conversation in Ideas
Discussion options

I have a Mahlkonig E64WS hat home, whoms APIs i've reverse engineered and seeing the new decent app brought up some ideas i would like to float with you before i start implementing them (either upstream or in a fork of mine).

Smart grinders and a decent with a scale unlock a lot of possibilities, that to a certain extend can also be applied to manual grinders.
The new app already records grind size and some data about shots, but i would like to enhance that.

I would like to introduce a better grinder abstraction that can map capabilities of each grinder (to keep it open for more grinders than just the E64 WS) and we could move basically all relevant interactions into the app, e.g. automatically set grind size and weight depending on the selected profile, bean and grinder combination.

Having that control also opens up a basic assisted dial-in setup for less experienced users where the machine can give recommendations based upon the just pulled shot and maybe some customer feedback (e.g. how does the puck look like, too sour, too bitter, was it way to fast for the selected profile and so forth). This in theory could even work for manual grind adjustment but is a lot more precise to implement with grinders like the e64 ws (which already has some form of this built-in, that just doesnt sync with the decent)
This would obviously not be targeted at advanced users.

Is there a general Interest in having such functionality in the decaid app?

You must be logged in to vote

Replies: 3 comments 3 replies

Comment options

hey @MaxRink , we're definitely interested. I have been thinking about how to integrate that for some time now, especially since there are reverse-engineered implementations popping up.

I am not familiar with E64WS control method, can you explain a bit more? At the moment I know about a BLE controlled grinder and a Websocket controlled grinder.

My initial idea was to use plugins to control grinders - and your idea about extending the Grinder data model could fit into that too perhaps. In the sense, that Grinder object gains the interface for controlling parameters as well as an optional transport object that would relay that info.

Please check if #146 would help with this idea. There are other interesting things hanging on it too, so it would be nice to confirm we can solve a lot with one task.

I'll also move this to discussions, where we'll be more free to discuss before formalizing a plan.

You must be logged in to vote
2 replies
Comment options

I had AI summarize the current state of my reverse engineering in my Repo

The E64 WS is a recipe-driven grinder with three dosing modes:
 Manual: start/stop grinding manually.
 Grind-by-Time: grind until the recipe's time target is reached.
 Grind-by-Weight: grind until the internal load cell reaches the target dose. The same load cell can identify a previously registered portafilter and select its associated recipe.
Recipes also store a reference disc distance (DD, in microns), dose settings, and an optional Grind-by-Sync (GbS) flag. The HMI can select/edit recipes with its buttons and rotary encoder. It also provides quick manual DD/dose editing and purge; these are controls rather than additional dosing modes. The local web UI is available in either the grinder's access-point mode or station mode.
GbS is the closed-loop mode: a compatible espresso machine or Sync Scale provides a brew event, principally the observed brew time. The grinder compares that with the recipe target and its AGSA motor adjusts the electronic burr distance finer when the shot is too fast, or coarser when it is too slow. It is intended as small ongoing corrections after an initial dial-in, not as a single-shot guarantee. The built-in Assisted Dial-In wizard is a separate workflow that asks for coffee/shot parameters and brew time, suggests a DD, and can refine/assign the resulting recipe.
For the E64 WS image I inspected, the local control surface is:
HTTPS REST: POST /rest_api/<route>
TLS WebSocket: wss://<grinder-ip>:9997/?token=<short-lived-local-token>
Messages: JSON request/response envelopes
The recovered WebSocket registry includes state/config/log reads and named actions such as StartGrindManual, StartGrindGbw, StartGrindGbt, Stop, SetAgsaTargetDdValue, AddBrewEvent, and GbsCreateReport. The normal action envelope is {"type":"GrinderAction","data":{"actionType":"..."}}. This is separate from the vendor cloud API; the local WSS client does not need to call the cloud, although the officially documented Sync Scale → grinder GbS path is cloud/Machine-to-Machine based.
The E64 firmware contains a brew-event parser and an AddBrewEvent action, but we have not yet proven that a locally injected event is accepted by every firmware revision or causes a physical GbS adjustment. That makes two useful Decaid paths possible: a safe host-side recommendation mode, and an explicit, owner-enabled E64 event/actuation adapter after live validation. A Decent- attached scale or OpenScale can be normalized as an independent mass source; flow-only data must not be treated as weight.
API map
The API split is roughly:
local device Mahlkönig Sync cloud / mobile app
------------ -----------------------------
HTTPS REST /rest_api/* HTTPS https://sync.mahlkoenig.com/api/*
JSON WSS :9997 scale WSS scale.sync.mahlkoenig.com/socket/device
HMI/driver state + actuation accounts, pairing, recipes, events, analytics
local onboarding/Wi-Fi cloud device binding and firmware presentation
The local REST surface is PHP behind lighttpd. The recovered routes include session/login (ping, check_session, login, logout, update_session), device information (get_machine_info), Wi-Fi/onboarding (scan_wifi, get_wifi_info, request_onboarding), and operational or maintenance functions (reboot, get_fw_update_state, download_database, and download_machine_logs). Firmware and ESP/splash uploads are separate local PHP pages rather than normal REST routes. They should be treated as maintenance surfaces, not as part of a generic grinder driver.
The local WSS registry has 52 records: six state/config reads, provisioning and Wi-Fi messages, and 39 GrinderAction variants. The read families cover driver state/config, logs, ADC/config-manager settings, and machine info. The important control variants cover manual/time/weight grinding, stop, tare and calibration, AGSA/DD adjustment, brew-event insertion, and GBS report creation. The remaining variants expose fans, lights, language, setup state, simulated buttons/rotary input, endurance tests, ESP maintenance, and configuration updates. Exact names, payload keys, development flags, callbacks.
Local WSS requests use msgId; ordinary replies use the corresponding refId, while action replies normally contain data.success. The local web login creates a short-lived bearer token used in the WSS query string. The examined binary contains no per-message HMAC/signature scheme. These are static findings for one firmware image, not a promise that every command is enabled or safe on a production unit.
The cloud/mobile side is a different API. The Android APK contains the cloud root https://sync.mahlkoenig.com/api/, auth/token-provider code, and these route families:
 authentication and account lifecycle: security-service/auth/token, security-service/auth/refresh, password/reset and registration routes;
 device/pairing: mobile-service/device/query, device-union queries, offboarding, profile/store/region and invitation routes;
 grinder and brew history: mobile-service/grind-event/find and count, device-event/brew-event/find and count, error events, and grind totals;
 recipes: recipe presets, cloud-recipe query/slot/create/status/merge, and recipe-threshold services;
 scale/live data: ScaleApiClient plus wss://scale.sync.mahlkoenig.com/socket/device;
 dashboards, chat/help, Firebase messaging/analytics/crash/performance, remote configuration, and firmware/app-version status models.
The APK also contains local provisioning candidates such as /api/v2/network/list, /api/v2/network/connect, and /api/v2/network/forcescan, alongside /rest_api/* onboarding routes. A route literal proves only that the string is present: the exact HTTP method, headers, body, response schema, retry policy, and authorization are not all recoverable from the stripped Flutter AOT snapshot. In particular, the APK does not contain a literal E64 RequestDriverState or GrinderAction string, so stock-app-to-local-WSS compatibility remains unproven.

Looking at #146: its useful for the asynchronous transport and workflow-event plumbing, but its generic outbound transport should cover TLS text frames and request/response streams, not only binary frames.

Comment options

It also looks to me like someone mostly just copied over the software feom their commercial grinders, as i also found references for the E80 in the GBS code

Comment options

Another potential pathway to the grinder control might be through the generic sensor device. Maybe worth investigating

You must be logged in to vote
1 reply
Comment options

Yes, but id say grinders are important enough in the workflow to warrant their own modeling.

Comment options

Following up with a more concrete assisted-dial-in shape, including how it overlaps the existing bean, grinder, workflow, and tasting discussions. This remains exploratory.

Build on the existing models

Decaid's grinder model already distinguishes numeric settings from named values and supports small/big setting and RPM increments (current model). WorkflowContext already links the selected grinder, grinder setting, bean batch, target dose, and target yield (current workflow context). Shot annotations already carry actual dose/yield, enjoyment, and espresso notes (current annotations).

The existing discussions remain the right homes for their underlying schemas:

Grinder comparison model

For recommendations, the model additionally needs:

  • setting direction: whether a larger numeric value means finer or coarser;
  • the existing increments/presets expressed consistently;
  • calibration/maintenance epochs, so burr replacement, zero-point changes, or recalibration starts a new comparison period;
  • capabilities separated from transport, so manual and connected grinders use the same evidence model.

A raw setting must never be compared across different grinders or calibration epochs. Smart-grinder communication is a separate capability; issue #146 is already discussing permission-gated plugin transports and workflow-change events that could support it.

Taste and outcome input

Keep the existing enjoyment score and free-form notes, while optionally adding a small structured vocabulary useful for suggestions. A first iteration could capture balance/direction and defects such as sour, bitter, astringent, weak, or harsh, plus optional flavor observations.

The vocabulary should be tested with real users before promoting a large tasting schema into typed core fields. #66 already contains a much broader tasting-field proposal and should remain the schema discussion.

Recommendation behavior

Assisted dial-in should be suggestion-only:

  • never change a grinder, workflow, or machine profile automatically;
  • show the prior shots used as evidence and the reason for the suggestion;
  • state confidence and abstain when there is not enough comparable history;
  • let the user explicitly accept, edit, or ignore a suggestion.

Comparable history should require, at minimum:

  • the same bean or batch relationship;
  • the same grinder and calibration epoch;
  • the same machine-profile identity/version or a deliberately compatible group;
  • compatible dose and target-yield context.

The first useful implementation can be deterministic rather than AI-based: find the last-known-good comparable shot, compare extraction outcome and taste feedback, then suggest one bounded change. Advice should avoid changing grind and machine recipe simultaneously unless the evidence can explain why.

Roaster-provided settings or profiles can be a starting prior, but must be visibly attributed and treated as recommendations for the named hardware rather than universal truth. The separate interoperability discussion covers that source data: #721 Beanconqueror and roaster interoperability

Questions

  1. What is the smallest useful structured taste vocabulary?
  2. How many comparable observations are required before suggesting a change?
  3. Should the first iteration only recommend grind changes, or may it also recommend an explicit profile/recipe adjustment?
  4. How should users mark a shot as a trusted "good" reference?
  5. Which grinder maintenance events should start a new calibration epoch?
You must be logged in to vote
0 replies
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Ideas
Labels
None yet
2 participants
Converted from issue

This discussion was converted from issue #701 on August 27, 2026 05:32.

AltStyle によって変換されたページ (->オリジナル) /