Skip to content

Instantly share code, notes, and snippets.

@adampetrovic
Last active May 13, 2025 18:10
Show Gist options
  • Save adampetrovic/448b276d591ee1c1a2ebd9e52119c9f8 to your computer and use it in GitHub Desktop.
Save adampetrovic/448b276d591ee1c1a2ebd9e52119c9f8 to your computer and use it in GitHub Desktop.
Homebrew by Weight - La Marzocco Linea Micra

This is my 'homebrew' version of the brew-by-weight functionality that comes with a Linea Mini plus the LaMarzocco + Acaia proprietary scales. Given I have a Micra, this functionality isn't supported out of the box.

It uses:

How it works:

  • input_number.coffee_target_weight: used to set the desired weight
  • input_number.coffee_drip_duration: used to estimate how long (in secs) the coffee continues to drip after the pump is stopped.
  1. Turn on the scales and wait for the connected symbol to show on the scales (next to the timer).
  2. Start the shot. Homeassistant will tare the scales automatically and start the timer on the scales.
  3. Once the shot timer reaches 10 seconds, the brew-by-weight automation should trigger
  4. The automation continues to monitor the current weight and flow rate from the scales, continually updating the coffee_estimated_drip_weight template sensor.
  5. Once the current weight reaches the threshold of (current_weight + coffee_estimated_drip_weight >= target_weight) it turns off the machine (only way to stop the pump) and turns it back on.

Adjust the input_number.coffee_drip_duration over time to get more accurate.

external_components:
- source:
type: git
url: https://github.com/adampetrovic/esphome-acaia-component
ref: log_flow
refresh: 0s
esphome:
name: coffee-controller
friendly_name: coffee-controller
esp32:
board: esp32-s3-devkitc-1
framework:
type: arduino
logger:
level: DEBUG
api:
ota:
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
ap:
ssid: "Coffee-Controller"
password: "password"
bluetooth_proxy:
active: True
esp32_ble_tracker:
ble_client:
- mac_address: <mac address of your scales>
id: acaia_client
acaia:
ble_client_id: acaia_client
id: acaia_1
binary_sensor:
- platform: acaia
connected:
name: Acaia Connected
id: acaia_connected
sensor:
- platform: acaia
weight:
id: scale_sens
name: Scale weight
accuracy_decimals: 1
unit_of_measurement: g
filters:
- lambda: return x * 1000;
flow:
name: Scale flow
id: flow_sens
button:
- platform: template
name: Tare Scales
id: scale_tare
icon: "mdi:scale"
on_press:
- acaia.tare: acaia_1
- platform: template
name: Start Timer
id: start_timer
icon: "mdi:timer-outline"
on_press:
- acaia.start_timer: acaia_1
- platform: template
name: Stop Timer
id: stop_timer
icon: "mdi:timer-outline"
on_press:
- acaia.stop_timer: acaia_1
- platform: template
name: Reset Timer
id: reset_timer
icon: "mdi:timer-outline"
on_press:
- acaia.reset_timer: acaia_1
input_number:
coffee_target_weight:
name: Coffee Target Weight
unit_of_measurement: g
initial: 42
min: 10
max: 60
step: 1
coffee_drip_duration:
name: Coffee Drip Duration
unit_of_measurement: s
initial: 2.5
min: 0
max: 10
step: 0.1
sensor:
- platform: template
sensors:
coffee_estimated_drip_weight:
unique_id: coffee_estimated_drip_weight
friendly_name: Coffee Post-Shot Drip Weight
unit_of_measurement: "g"
availability_template: "{{ states('sensor.coffee_controller_scale_flow') | float > 0 }}"
value_template: >
{{ (states('input_number.coffee_drip_duration') | float * states('sensor.coffee_controller_scale_flow') | float) | round(2) }}
automation:
- id: start_shot_setup_scales
alias: "[Coffee] Setup scales on shot start"
mode: single
trigger:
- platform: state
entity_id: binary_sensor.micra_brewing_active
to: "on"
condition:
- "{{ is_state('binary_sensor.coffee_controller_acaia_connected', 'on') }}"
action:
- service: button.press
target:
entity_id: button.coffee_controller_reset_timer
- service: button.press
target:
entity_id: button.coffee_controller_start_timer
- service: button.press
target:
entity_id: button.coffee_controller_tare_scales
- id: stop_shot_setup_scales
alias: "[Coffee] Stop scales on target weight"
mode: single
trigger:
- platform: template
value_template: "{{ states('sensor.coffee_controller_scale_weight') | float >= states('input_number.coffee_target_weight') | float }}"
condition:
- "{{ states('sensor.micra_shot_timer') | float >= 10 }}"
action:
- service: button.press
target:
entity_id: button.coffee_controller_stop_timer
- id: brew_by_weight
alias: "[Coffee] Brew by Weight"
mode: single
trigger:
# make sure we're actually brewing a valid shot
- platform: template
value_template: "{{ states('sensor.micra_shot_timer') | float >= 10 }}"
condition:
- "{{ is_state('binary_sensor.coffee_controller_acaia_connected', 'on') }}"
action:
- wait_template: "{{ states('sensor.coffee_controller_scale_flow') | float > 0 }}"
timeout:
seconds: 5
continue_on_timeout: false
- repeat:
# stop when actual_weight >= target_weight - estimated_drip_weight
# estimated_drip_weight is calculated above
until: "{{ (states('sensor.coffee_controller_scale_weight') | float >= (states('input_number.coffee_target_weight') | float - states('sensor.coffee_estimated_drip_weight') | float))}}"
sequence:
- delay:
milliseconds: 100
- service: switch.turn_off
target:
entity_id: switch.coffee_machine
- delay:
seconds: 2
- service: switch.turn_on
target:
entity_id: switch.coffee_machine
@joeshmoe9898
Copy link

Can you provide instructions for ESPHome? I'm familiar with Home Assistant and getting the LaMarzocco HA integration working shouldn't be a problem. But How does ESPHome connect in? The readme on ESPHome doesn't have instructions.

@adampetrovic
Copy link
Author

@joeshmoe9898 i'll update the readme in the coming days with a proper set of instructions for the ESPHome :) Hang in there.

@taupeshuitun
Copy link

taupeshuitun commented Aug 19, 2024

Having trouble finding my MAC address for my Acaia. Can it be derived from UUID?

Update: Within Home Assistant if you do a debug on the bluetooth module it dumps all of the BT devices it sees and their MAC addresses. Just search for Acaia in the output file.

@carlton81
Copy link

Hey,
Can you please confirm that this works with La Marzocco Home x Acaia scales?

@adampetrovic
Copy link
Author

Hey, Can you please confirm that this works with La Marzocco Home x Acaia scales?

@carlton81 I’ve only tested it on vanilla Acaia Lunar scales, but I don’t see why it wouldn’t.

@taupeshuitun
Copy link

@joeshmoe9898 i'll update the readme in the coming days with a proper set of instructions for the ESPHome :) Hang in there.

@adampetrovic any chance you could provide a rough outline of the instructions? I've got an esp32 (a CYD) up and running and have connected it, the scale, and the machine together in HA. However, I'm having trouble with loading the automation to do the actual work though... When I try to paste in the automation.yaml as an automation on the esp32, HA gives the following error:

"Message malformed: extra keys not allowed @ data['input_number']"

Thanks in advance!

@adampetrovic
Copy link
Author

adampetrovic commented Nov 15, 2024

@taupeshuitun the automations.yaml is meant for homeassistant, not ESPHome.

@TiStef
Copy link

TiStef commented Jan 13, 2025

@adampetrovic thank you so much for putting this together.
Have you experienced very unstable Bluetooth connection? IN the ESP32 logs it seems to connect, but immediately after it disconnects and none of the HA buttons result in any action on the scale.
I have removed the ACAIA integration from HA and remove the scale from the ACAIA app in order not to have duplicate connection requests to the scale.

[10:08:23][I][esp32_ble_client:227]: [0] [60:8A:10:4D:C1:6E] Connected
[10:08:23][D][ACAIA:062]: Registering for notifications
[10:08:23][W][ACAIA:069]: No control service found at device, not an Anova..?
[10:08:23][D][esp32_ble_client:188]: [0] [60:8A:10:4D:C1:6E] cfg_mtu status 0, mtu 247
[10:08:23][D][ACAIA:232]: GATTC Event incoming, type 18
[10:08:23][W][component:237]: Component esp32_ble took a long time for an operation (53 ms).
[10:08:23][W][component:238]: Components should block for at most 30 ms.
[10:08:25][D][button:010]: 'Start Timer' Pressed.
[10:08:25][D][ACAIA:273]: Starting timer

@Subtletree
Copy link

Hey @adampetrovic, cheers for this!

With the new cloud only communication with the machine are your timings still working? I guess I'll just adjust the drip duration to include the latency with shutting off the machine.

@adampetrovic
Copy link
Author

@Subtletree The only thing impacted by the new firmware and its delay is the trigger to the brew_by_weight automation. That being delayed by 4 seconds won't really have a measurable impact on the result. Really we only care about brewing being active at some point, so we can start calculating the coffee_estimated_drip_weight.

The logic of brew by weight in this case is only dependent on sensor.coffee_controller_scale_flow being accurate. This is a value that is calculated internally in the esp32 component (esphome-acaia-component).

@adampetrovic
Copy link
Author

adampetrovic commented May 6, 2025

It's also worth noting that the reliance on the ESP32 controller firmware is optional now. If instead, you use ESP32 bluetooth proxies in your HomeAssistant installation, you can use the Acaia component bundled in the HomeAssistant core now. Which supports everything we're doing here: https://www.home-assistant.io/integrations/acaia/

Volume flow rate: Calculates the current flow rate (in mL/s) while brewing.
Weight: The weight currently shown on the scale.

I will look to provide a blueprint to perform brew-by-weight when I get a chance, which should significantly lower the barrier to entry for people to get started.

@StefanoGaliani
Copy link

It's also worth noting that the reliance on the ESP32 controller firmware is optional now. If instead, you use ESP32 bluetooth proxies in your HomeAssistant installation, you can use the Acaia component bundled in the HomeAssistant core now. Which supports everything we're doing here: https://www.home-assistant.io/integrations/acaia/

Volume flow rate: Calculates the current flow rate (in mL/s) while brewing.
Weight: The weight currently shown on the scale.

I will look to provide a blueprint to perform brew-by-weight when I get a chance, which should significantly lower the barrier to entry for people to get started.

This would be great. Thank you very much Adam

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment