THE PROBLEM
Some time ago, I was asked to help install a series of mods on a Gaggia Classic espresso machine. The owner of the machine wanted to add a pressure gauge and a PID temperature controller – both in a top-box that was to be installed as well – and replace the over-pressure spring to decrease the maximum pressure in the machine. While installing these mods, we happened to discuss adding Wi-Fi to the machine. This is something I had already done in the past on a regular filter coffee machine, but the button-emulation technique I used there would not work on the Gaggia Classic due to the design of the machine. We did, however, have the opportunity to get familiar with the layout of the machine while installing the mods.
Looking further into the topic of adding Wi-Fi to the espresso maker, we stumbled upon some earlier efforts by MrShades on the British coffee forums. The idea of that mod is to add a smart switch inside the machine which would allow you to turn the machine on. Unfortunately, it does not allow you to turn the machine off afterwards and it is not able to detect the current on/off state of the machine. It does provide a possible external solution to one of these problems in the form of an external smart plug, but that just won’t cut it in terms of how “clean” the end result is.
CHOOSING A DEVICE
To overcome the problems mentioned before, we would need to find or create a device with Wi-Fi, two relays and a way to measure whether or not the machine is switched on. Ideally, such a device would be controlled by an ESP8266 or ESP32 micro-controller as I was already familiar with that platform. Additionally, it would make for a great opportunity to experiment with ESPHome to integrate the whole project in Home Assistant.
Soon enough, I realized that any dual smart switch would meet most requirements. I even had a few already installed in my home! More specifically, I started looking at the Shelly 2.5. This little device is powered by an ESP8266 so it has Wi-Fi built in, it has 2 relays and the switch detection circuits should be able to detect the power state of the machine. One small thing: the Shelly 2.5 is end-of-life and has been superseded by the Shelly Plus 2PM. The 2PM has the same external connections, but is powered by an ESP32 and has power monitoring capabilities (this will be useful later).
FIRST ATTEMPT
The idea was to use one of the relays in the Shelly Plus 2PM to switch the machine on, just like in MrShades’ mod, and the other to switch the machine off by briefly interrupting the mains supply. To detect the power state of the machine, one of the switch inputs would be leveraged to sense the presence of mains voltage on the switched circuit inside the machine. A very crude schematic of the planned mod (still pictured with a Shelly 2.5 here) looked like this:
Output 1 (black) would be always on to allow the machine to work normally. Interrupting this connection for a short period would switch the machine off. Output 2 (green) would normally be off and would only be switched on briefly to switch the machine on. Input 1 (magenta) would be used to sense the current power state of the machine.
Unfortunately, there were some problems with this first attempt. It turns out that in this configuration, the switch input always detected the machine’s state as “on”, while also causing the main power light on the front of the machine to blink continuously. Power monitoring and switching, however, was working as expected while still allowing manual control of the machine via the power switch. We were only a few minor changes away from a working solution!
FINAL SOLUTION
To fix the problems with the first attempt, we decided to remove the sensing wire connected to input 1 (magenta) and use the power monitoring feature to determine the machine state instead. With the machine switched off, the power monitor reported a usage of around 0.1 W. When switched on the machine with PID controller was using around 3 W idle, i.e. with the heater and pump off. We settled on a power usage of 1.5 W to distinguish between “on” and “off” states. The schematic was updated to the following:
Since we were working on a machine with a top box already installed for the PID controller and a pressure gauge, we figured that that would be a great place to install the Shelly as well. There was enough space left over and the top box had some foam at the bottom to help with temperature insulation. The idea was to use the neutral and the switched mains from the PID controller since they were already present inside the top box, but the wire used to get the switched mains to the PID controller had a fuse in it which prevented us from using it. All in all we would need to get 3 additional wires from the top box down into the main housing.
CONFIGURING THE FIRMWARE
As mentioned earlier, we wanted to use ESPHome to control the machine and integrate it into Home Assistant. The benefits of this approach are that it is relatively easy to configure and that the internal switching and sensing logic can be represented as a single power toggle. We ended up with the following configuration which has all inputs and outputs configured, but only exposes the essentials to Home Assistant. It should be usable as-is after inserting your own Wi-Fi credentials.
substitutions:
devicename: "gaggia-classic"
device_friendly_name: "Gaggia Classic"
output_name_1: "Main Power"
output_name_2: "Switched Power"
input_name_1: "Input 1"
input_name_2: "Input 2"
# For PCB v0.1.9 with dual core ESP32
esphome:
name: ${devicename}
esp32:
board: esp32doit-devkit-v1
framework:
type: arduino
logger:
api:
ota:
wifi:
ssid: "<Wi-Fi SSID>"
password: "<Wi-Fi password>"
i2c:
sda: GPIO26
scl: GPIO25
output:
- platform: gpio
id: "relay_output_1"
pin: GPIO13
- platform: gpio
id: "relay_output_2"
pin: GPIO12
switch:
- platform: output
id: "relay_1"
name: "${output_name_1}"
output: "relay_output_1"
restore_mode: ALWAYS_ON
internal: true
- platform: output
id: "relay_2"
name: "${output_name_2}"
output: "relay_output_2"
restore_mode: ALWAYS_OFF
internal: true
- platform: template
name: "${device_friendly_name} Power"
lambda: |-
if (id(active_power).state > 1.5) {
return true;
} else {
return false;
}
turn_on_action:
- output.turn_on: relay_output_1
- output.turn_on: relay_output_2
- delay: 250ms
- output.turn_off: relay_output_2
turn_off_action:
- output.turn_off: relay_output_1
- output.turn_off: relay_output_2
- delay: 500ms
- output.turn_on: relay_output_1
binary_sensor:
# Button on device
- platform: gpio
name: "${device_friendly_name} Button"
pin:
number: GPIO4
inverted: yes
mode:
input: true
pullup: true
internal: true
# Input 1
- platform: gpio
name: "${input_name_1}"
pin: GPIO5
filters:
- delayed_on_off: 50ms
internal: true
# Input 2
- platform: gpio
name: "${input_name_2}"
pin: GPIO18
filters:
- delayed_on_off: 50ms
internal: true
sensor:
# Power Sensor
- platform: ade7953
irq_pin: GPIO27
voltage:
name: "${device_friendly_name} Voltage"
entity_category: 'diagnostic'
current_a:
name: "${device_friendly_name} Current"
entity_category: 'diagnostic'
active_power_a:
name: "${device_friendly_name} Power"
entity_category: 'diagnostic'
id: active_power
filters:
- multiply: -1
update_interval: 2s
# Internal NTC Temperature sensor
- platform: ntc
sensor: temp_resistance_reading
name: "${device_friendly_name} Temperature"
unit_of_measurement: "°C"
accuracy_decimals: 1
icon: "mdi:thermometer"
entity_category: 'diagnostic'
calibration:
b_constant: 3350
reference_resistance: 4.7kOhm
reference_temperature: 298.15K
# Required for NTC sensor
- platform: resistance
id: temp_resistance_reading
sensor: temp_analog_reading
configuration: DOWNSTREAM
resistor: 5.6kOhm
# Required for NTC sensor
- platform: adc
id: temp_analog_reading
pin: GPIO35
attenuation: 11db
update_interval: 10s
After flashing the Shelly with ESPHome and linking it to Home Assistant we could start to get our hands dirty with the wiring.
WIRING IT UP
Next was the actual wiring. Apart from the fused wire that we couldn’t use, all went according to plan. We used heat resistant silicone wires for all connections. 14AWG for the high-power connections and 22AWG for the low-power neutral wire. Additionally, we used a wire connector inside the top box to connect all neutral wires together. We had to improvise a bit on the connection from output 2 to the switched mains inside the machine as the PID controller was already connected to the same spot we wanted to use with a piggyback spade. Adding another piggyback on top of that seemed a bit dodgy, so we decided to make a splitter wire instead.

At the rear of the machine where the power cord is connected, we removed the connector with the brown wire from the mains connector and replaced it with the black/red wire going to the live power (L) input on the Shelly. The brown wire was then connected with the red wire to output 1 (O1) on the Shelly.

We then removed the orange wire from the piggyback connector on the back of the power switch and replaced it with the yellow spade connector of our homemade splitter. We connected the splitter’s black lead to the orange wire and the red lead to output 2 (O2) on the Shelly.

Inside the top box, the only additional connections we had to make were those of the neutral wires. We removed the red lead from pin 1 of the PID controller and placed it in the wire connector. We used two black AWG22 wires to connect the wire connector to the neutral on the PID controller (pin 1) and on the Shelly (N).
That was it! After tidying up the wiring a bit and reassembling the machine we were now able to control the machine as before with the physical switches on the front, but we were also able to switch the machine on and off and see its current power state and usage in Home Assistant.
