Control your Jura coffee machine

Maybe someday. I know how to do it, but don’t have time.

4 Likes

In spring I had the time to spend a lot of time with my Jura S8 because I really want to control the coffee machine in Home Assistant. The first tests were done with an ESP8266 and after I read here that the Wifi dongle is actually an ESP32 I bought one and “slightly” modified it. :smile:

You can see the result here, the reason is that I can flash the dongle via USB in case of problems.




This worked perfectly until the ESPHome 2023.6.5 release. Since release 2023.7 the dongle and also other ESP32 (NodeMCU e.g.) crashes at startup. The details of the problem can be found here on Github. If anyone finds the error in the code, I would be grateful for any tips, my knowledge of C++ is not deep enough.

Well, since the dongle couldn’t be convinced to work, I “built” an ESP8266 dongle which will take over the work of the Wifi dongle for the time being.


However, I have not yet updated the ESP8266 to 2023.11 as a test ESP for 2023.11 also produces errors.

1 Like

Hi Martijn,
How exactly did you split the two voltages?
I can see that indeed, there is some low voltage and some high voltage connected to the so called “topswitch”.

But when looking at the fibaro double relay switch, it seems as if both switched have a common:
image

Could you elaborate some more on your howto, I would hate to blow up my beloved F9 :slight_smile:

I used a Shelly 1 Plus and just hooked up the 120V (US) side to the dry contacts. Toggling the contact simulates a button push to turn the coffee maker on.

I have a Z10 and assume the pin out is the same. When you crack it open, you’ll find the top switch is actually pressing two microswitches. One running at 5V DC and one running at mains voltage.

I’ve got an e8 EC. Is adding a switch bot to the power button considered a no go for WAF?

If I understood correctly the wifi nor the Bluetooth dongle will let you turn on the machine whilst in power save mode? At least not the newer models?

(I’ve yet to order one of these dongle things)

Can you provide some more details on the esp 8266 board you made? Why did it have a level shifter? I think I I’ve read in this thread the wemos didn’t need one?

I doubt the switchbot has enough torque to push the button.

It has enough force (not torque, linear movement), that is my current setup but not WAF-proof

1 Like

I was hoping to find something from the Jura that would show to HA it’s time to run a cleaning cycle or change a filter, or maybe close to it.

Would make it easy to add an automation to add either task to HA’s to-do list.

Hi did you manage to get the Jurassic S8 into the Home Assistant?

just a quick question about turning the machine on with an automation…
my E8 does a cleaning cycle when powered up. Because of this I cannot automatically turn it on in the morning and make a coffee (the cup will be filled with the water from the cleaning cycle)

is there a workaround for this?

Not really. One guy got super creative and setup a servo with a 3D printed tray that would move into place when the machine was powered up, wait for the rinse to complete, and then move out the way. The tray would just redirect the water to dump beside the cup into the drip tray. But all that was done on a Philips machine where they were able to see every stage of the process.

here you have a logic level shifter example diagram

@armanivers, it might be helpful for your C5 project to check out my project for the Ena 90. You may be able to find commands that work (or at least more information about Jura design concepts in general). Good luck!

Project Github here. HA forum thread here.

Hey @koen01, I’ve done a fair bit of research into understanding Jura’s designs, schematics, design choices and compromises.

The auto-rinsing serves three important purposes, and trust me when I say you want it to complete.

  • First, and most importantly, it allows the thermoblock to get to brew temperature more accurately, more precisely, and more safely. This is because the thermoblock (at least on the ENA 90) does not have fine temperature control - it’s either heating or not heating, either active or not active. The thermoblock does have a temperature sensor, but there will be a lag, especially from a cold start, just based on the location of the temperature sensor. Brass tacks, without anything sinking or distributing heat within the thermoblock, parts of it may get very hot before the temperature sensor reads 100°C. If an extraction started in this condition, you’d scald your dose and/or produce steam through a circulation system designed for sub-steam water temperature, which will wear seals or pipes much faster than designed. It’s a much better technique to pass water through the thermoblock as it warms up to help distribute that heat and smooth out temperature spikes resulting from a cold start. Thus, water rinse on boot.

    Also, for what it’s worth, this is why your system won’t require a rinse on boot if the thremoblock is still hot (i.e., you turned the machine off recently) .

  • Second, sanitation. It is always possible that power can be cut to the machine for an unknown period of time, possibly with wet coffee grounds and/or other organic matter within the silicone pipes of your machine. The rinse on boot makes sure that any foreign matter is flushed – or at least partially flushed – prior to a first brew of a new session.

  • Third, flavor. This is the preference corollary to the second point. Apart from safety and sanitation, pulling a shot through a line with dried coffee or yesterday’s un-flushed pipes is … not ideal.

TL;DR the rinse on boot is a good idea, and not one that you can or should try to disable. The only way to disable it would be to override the thermocouple of the thermoblock (or to have a complex diverter tray like described above). Both cases are overengineering, in my opinion. Disabling the thermocouple would present a safety and quality issue as well. It is possible to manually trigger the thermoblock, but doing so without water is not a good idea as noted above. On the ENA90, you can control the output valve to dump rinsed water directly into the drainage tray, but this does not clean or sanitize the endline of the brew group.

1 Like

I’m using your integration and it’s working, to a degree. I’m not sure if it’s an issue with my machine though. What I’ve noticed is, though the integration works to control the machine, the action of picking a product results in an error of “Error: unsupported operand type(s) for -: ‘NoneType’ and ‘NoneType’”. If I just ignore the error and continue on by pressing the “make” button via your integration, the process continues without issue.
Now, the next step, I wanted to make a routine to trigger the same steps. It seems the errors however make the routine stop each time. I’ve tried using the “continue_on_error” flag, but it isn’t working. Below is my automation script:

alias: Jura Make Americano
description: ""
trigger:
  - platform: state
    entity_id:
      - input_boolean.americano
    from: "off"
    to: "on"
condition: []
action:
  - device_id: 8cfc57a66deadb352e654264e35b68f2
    domain: select
    entity_id: 0896d85673f8f25e67f191d150506b1f
    type: select_option
    option: Hotwater Portion(Green tea)
    continue_on_error: true
  - service: button.press
    metadata: {}
    data: {}
    target:
      entity_id: button.efa3ed2ee90a_make
  - delay:
      hours: 0
      minutes: 0
      seconds: 5
      milliseconds: 0
  - service: input_boolean.turn_off
    target:
      device_id: []
      area_id: []
      entity_id: input_boolean.americano
    data: {}
mode: single

In my script, only intended as an example, a helper switch turns on, serving as the automation trigger. The product for hot water for green tea is selected, as I’m troubleshooting for now and not wanting to waste precious beans. The “make” button is pressed, then a delay of 5 seconds occurs before the triggering helper is set back to off. As it stands, the automation fails each time after the errors generated from the product selection. I’m completely new to scripts here, so it’s possible my continue on error is misplaced. Any advice on how to make it work?

In the long run, my ideal setup is as follows:

  1. I manually turn the machine on and let it run the mandatory cleaning rinse (I see the conversation about that from earlier, but I just accept I’ll have to do some manual work here).
  2. I place my cup, containing my manually prepared sweetener under the dispenser.
  3. I give a voice assistant command to turn on the helper, triggering the automation.
  4. The automation runs, setting the product to an Espresso Doppio (two shots), and pressing “Make” for me.
  5. The Jura does it’s thing and makes me a two shot espresso as requested. This of course takes a bit. My plan is to time it so that…
  6. The automation pauses for that set time, then initiates another espresso doppio.
    I know such automation sounds silly to some since it doesn’t automate everything, but my own Americano workflow is such that I often need to place my cup, then do other things while the Jura is working.

Thanks guys. I have had some success with the Jura X9 Impressa.
There is a connector on the steam generator relay board beside the DB9 connector.
For the life of me, I could not make heads or tails of the read eeprom responses - they do not seem to reflect the brew counter counts shown on the display. Also the tray water/status is inconsistent and not representative of the machine.

The important part is that I can brew products and turn the machine on and off.
I used a NodeMCU clone without level shifters, getting the power from the same header (5v) to vin pin, and knock on wood - it’s chooching away with the 5v Rx and 3v Tx.

I created alexa voice routines to properly stack the multi-brews required and used the scheduler component to turn the machine on and off on work-mornings automatically.

# disable serial logging when using GPIO01/03
logger:
  baud_rate: 0
uart:
  tx_pin: GPIO1
  rx_pin:
    number: GPIO3
    inverted: no
  baud_rate: 9600
  #debug:
    #direction: BOTH
    #dummy_receiver: false
    #after:
    #  delimiter: "\n"
    #sequence:
    #  - lambda: UARTDebug::log_string(direction, bytes);
  id: uart_bus
  #rx_buffer_size: 512

#stream_server:
#   uart_id: uart_bus
#   port: 1234

switch:
  - platform: template
    name: 'Coffee Maker'
    icon: "mdi:coffee-maker"
    id: jura_on_off_switch
    turn_on_action:
      - uart.write: [0xDF, 0xDB, 0xDB, 0xDF]  ## 'A'
      - delay: 8ms
      - uart.write: [0xFB, 0xFF, 0xDB, 0xDF]  ## 'N'
      - delay: 8ms
      - uart.write: [0xFB, 0xFB, 0xFF, 0xDB]  ## ':'
      - delay: 8ms
      - uart.write: [0xDB, 0xDB, 0xFF, 0xDB]  ## '0'
      - delay: 8ms
      - uart.write: [0xDF, 0xDB, 0xFF, 0xDB]  ## '1'
      - delay: 8ms
      - uart.write: [0xDF, 0xFF, 0xDB, 0xDB]  ## '\r'
      - delay: 8ms
      - uart.write: [0xFB, 0xFB, 0xDB, 0xDB]  ## '\n'
    turn_off_action:
      - uart.write: [0xDF, 0xDB, 0xDB, 0xDF]  ## 'A'
      - delay: 8ms
      - uart.write: [0xFB, 0xFF, 0xDB, 0xDF]  ## 'N'
      - delay: 8ms
      - uart.write: [0xFB, 0xFB, 0xFF, 0xDB]  ## ':'
      - delay: 8ms
      - uart.write: [0xDB, 0xDB, 0xFF, 0xDB]  ## '0'
      - delay: 8ms
      - uart.write: [0xFB, 0xDB, 0xFF, 0xDB]  ## '2'
      - delay: 8ms
      - uart.write: [0xDF, 0xFF, 0xDB, 0xDB]  ## '\r'
      - delay: 8ms
      - uart.write: [0xFB, 0xFB, 0xDB, 0xDB]  ## '\n'
    optimistic: true
    assumed_state: true
button:
  - platform: template
    name: 'Select Decaffe'
    icon: "mdi:cup-water"
    id: jura_select_decaffe
    on_press:
      - uart.write: [0xFB, 0xDF, 0xDB, 0xDF]  ## 'F'
      - delay: 8ms
      - uart.write: [0xDF, 0xDB, 0xDB, 0xDF]  ## 'A'
      - delay: 8ms
      - uart.write: [0xFB, 0xFB, 0xFF, 0xDB]  ## ':'
      - delay: 8ms
      - uart.write: [0xDB, 0xDB, 0xFF, 0xDB]  ## '0'
      - delay: 8ms
      - uart.write: [0xFF, 0xDB, 0xFF, 0xDB]  ## '3'
      - delay: 8ms
      - uart.write: [0xDF, 0xFF, 0xDB, 0xDB]  ## '\r'
      - delay: 8ms
      - uart.write: [0xFB, 0xFB, 0xDB, 0xDB]  ## '\n'
      - delay: 1000ms
      - uart.write: [0xFB, 0xDF, 0xDB, 0xDF]  ## 'F'
      - delay: 8ms
      - uart.write: [0xDF, 0xDB, 0xDB, 0xDF]  ## 'A'
      - delay: 8ms
      - uart.write: [0xFB, 0xFB, 0xFF, 0xDB]  ## ':'
      - delay: 8ms
      - uart.write: [0xDB, 0xDB, 0xFF, 0xDB]  ## '0'
      - delay: 8ms
      - uart.write: [0xFF, 0xDB, 0xFF, 0xDB]  ## '3'
      - delay: 8ms
      - uart.write: [0xDF, 0xFF, 0xDB, 0xDB]  ## '\r'
      - delay: 8ms
      - uart.write: [0xFB, 0xFB, 0xDB, 0xDB]  ## '\n'
  - platform: template
    name: 'Brew Coffee'
    icon: "mdi:cup-water"
    id: jura_make_coffee
    on_press:
      - uart.write: [0xFB, 0xDF, 0xDB, 0xDF]  ## 'F'
      - delay: 8ms
      - uart.write: [0xDF, 0xDB, 0xDB, 0xDF]  ## 'A'
      - delay: 8ms
      - uart.write: [0xFB, 0xFB, 0xFF, 0xDB]  ## ':'
      - delay: 8ms
      - uart.write: [0xDB, 0xDB, 0xFF, 0xDB]  ## '0'
      - delay: 8ms
      - uart.write: [0xDF, 0xDB, 0xFF, 0xDB]  ## '1'
      - delay: 8ms
      - uart.write: [0xDF, 0xFF, 0xDB, 0xDB]  ## '\r'
      - delay: 8ms
      - uart.write: [0xFB, 0xFB, 0xDB, 0xDB]  ## '\n'
  - platform: template
    name: 'Brew Espresso'
    icon: "mdi:cup-water"
    id: jura_make_espresso
    on_press:
      - uart.write: [0xFB, 0xDF, 0xDB, 0xDF]  ## 'F'
      - delay: 8ms
      - uart.write: [0xDF, 0xDB, 0xDB, 0xDF]  ## 'A'
      - delay: 8ms
      - uart.write: [0xFB, 0xFB, 0xFF, 0xDB]  ## ':'
      - delay: 8ms
      - uart.write: [0xDB, 0xDB, 0xFF, 0xDB]  ## '0'
      - delay: 8ms
      - uart.write: [0xFB, 0xDB, 0xFF, 0xDB]  ## '2'
      - delay: 8ms
      - uart.write: [0xDF, 0xFF, 0xDB, 0xDB]  ## '\r'
      - delay: 8ms
      - uart.write: [0xFB, 0xFB, 0xDB, 0xDB]  ## '\n'
  - platform: template
    name: 'Brew Double'
    icon: "mdi:cup-water"
    id: jura_make_double
    on_press:
      - uart.write: [0xFB, 0xDF, 0xDB, 0xDF]  ## 'F'
      - delay: 8ms
      - uart.write: [0xDF, 0xDB, 0xDB, 0xDF]  ## 'A'
      - delay: 8ms
      - uart.write: [0xFB, 0xFB, 0xFF, 0xDB]  ## ':'
      - delay: 8ms
      - uart.write: [0xDB, 0xDB, 0xFF, 0xDB]  ## '0'
      - delay: 8ms
      - uart.write: [0xDB, 0xDF, 0xFF, 0xDB]  ## '4'
      - delay: 8ms
      - uart.write: [0xDF, 0xFF, 0xDB, 0xDB]  ## '\r'
      - delay: 8ms
      - uart.write: [0xFB, 0xFB, 0xDB, 0xDB]  ## '\n'

sensor:
  - platform: uptime
    name: "Uptime"

  - platform: wifi_signal
    name: "WiFi Signal"
    update_interval: 60s

Thanks guys. I have had some success with the Jura X9 Impressa.
There is a connector on the steam generator relay board beside the DB9 connector.
For the life of me, I could not make heads or tails of the read eeprom responses - they do not seem to reflect the brew counter counts shown on the display. Also the tray water/status is inconsistent and not representative of the machine. The commands do come back starting with a lower-case of what I sent… so it’s not a serial line readback issue as far as I can tell.

The important part is that I can brew products and turn the machine on and off.
I used a NodeMCU clone without level shifters, getting the power from the same header (5v) to vin pin, and knock on wood - it’s chooching away with the 5v Rx and 3v Tx.

I created alexa voice routines to properly stack the multi-brews required and used the scheduler component to turn the machine on and off on work-mornings automatically.

# disable serial logging when using GPIO01/03
logger:
  baud_rate: 0
uart:
  tx_pin: GPIO1
  rx_pin:
    number: GPIO3
    inverted: no
  baud_rate: 9600
  #debug:
    #direction: BOTH
    #dummy_receiver: false
    #after:
    #  delimiter: "\n"
    #sequence:
    #  - lambda: UARTDebug::log_string(direction, bytes);
  id: uart_bus
  #rx_buffer_size: 512

#stream_server:
#   uart_id: uart_bus
#   port: 1234

switch:
  - platform: template
    name: 'Coffee Maker'
    icon: "mdi:coffee-maker"
    id: jura_on_off_switch
    turn_on_action:
      - uart.write: [0xDF, 0xDB, 0xDB, 0xDF]  ## 'A'
      - delay: 8ms
      - uart.write: [0xFB, 0xFF, 0xDB, 0xDF]  ## 'N'
      - delay: 8ms
      - uart.write: [0xFB, 0xFB, 0xFF, 0xDB]  ## ':'
      - delay: 8ms
      - uart.write: [0xDB, 0xDB, 0xFF, 0xDB]  ## '0'
      - delay: 8ms
      - uart.write: [0xDF, 0xDB, 0xFF, 0xDB]  ## '1'
      - delay: 8ms
      - uart.write: [0xDF, 0xFF, 0xDB, 0xDB]  ## '\r'
      - delay: 8ms
      - uart.write: [0xFB, 0xFB, 0xDB, 0xDB]  ## '\n'
    turn_off_action:
      - uart.write: [0xDF, 0xDB, 0xDB, 0xDF]  ## 'A'
      - delay: 8ms
      - uart.write: [0xFB, 0xFF, 0xDB, 0xDF]  ## 'N'
      - delay: 8ms
      - uart.write: [0xFB, 0xFB, 0xFF, 0xDB]  ## ':'
      - delay: 8ms
      - uart.write: [0xDB, 0xDB, 0xFF, 0xDB]  ## '0'
      - delay: 8ms
      - uart.write: [0xFB, 0xDB, 0xFF, 0xDB]  ## '2'
      - delay: 8ms
      - uart.write: [0xDF, 0xFF, 0xDB, 0xDB]  ## '\r'
      - delay: 8ms
      - uart.write: [0xFB, 0xFB, 0xDB, 0xDB]  ## '\n'
    optimistic: true
    assumed_state: true
button:
  - platform: template
    name: 'Select Decaffe'
    icon: "mdi:cup-water"
    id: jura_select_decaffe
    on_press:
      - uart.write: [0xFB, 0xDF, 0xDB, 0xDF]  ## 'F'
      - delay: 8ms
      - uart.write: [0xDF, 0xDB, 0xDB, 0xDF]  ## 'A'
      - delay: 8ms
      - uart.write: [0xFB, 0xFB, 0xFF, 0xDB]  ## ':'
      - delay: 8ms
      - uart.write: [0xDB, 0xDB, 0xFF, 0xDB]  ## '0'
      - delay: 8ms
      - uart.write: [0xFF, 0xDB, 0xFF, 0xDB]  ## '3'
      - delay: 8ms
      - uart.write: [0xDF, 0xFF, 0xDB, 0xDB]  ## '\r'
      - delay: 8ms
      - uart.write: [0xFB, 0xFB, 0xDB, 0xDB]  ## '\n'
      - delay: 1000ms
      - uart.write: [0xFB, 0xDF, 0xDB, 0xDF]  ## 'F'
      - delay: 8ms
      - uart.write: [0xDF, 0xDB, 0xDB, 0xDF]  ## 'A'
      - delay: 8ms
      - uart.write: [0xFB, 0xFB, 0xFF, 0xDB]  ## ':'
      - delay: 8ms
      - uart.write: [0xDB, 0xDB, 0xFF, 0xDB]  ## '0'
      - delay: 8ms
      - uart.write: [0xFF, 0xDB, 0xFF, 0xDB]  ## '3'
      - delay: 8ms
      - uart.write: [0xDF, 0xFF, 0xDB, 0xDB]  ## '\r'
      - delay: 8ms
      - uart.write: [0xFB, 0xFB, 0xDB, 0xDB]  ## '\n'
  - platform: template
    name: 'Brew Coffee'
    icon: "mdi:cup-water"
    id: jura_make_coffee
    on_press:
      - uart.write: [0xFB, 0xDF, 0xDB, 0xDF]  ## 'F'
      - delay: 8ms
      - uart.write: [0xDF, 0xDB, 0xDB, 0xDF]  ## 'A'
      - delay: 8ms
      - uart.write: [0xFB, 0xFB, 0xFF, 0xDB]  ## ':'
      - delay: 8ms
      - uart.write: [0xDB, 0xDB, 0xFF, 0xDB]  ## '0'
      - delay: 8ms
      - uart.write: [0xDF, 0xDB, 0xFF, 0xDB]  ## '1'
      - delay: 8ms
      - uart.write: [0xDF, 0xFF, 0xDB, 0xDB]  ## '\r'
      - delay: 8ms
      - uart.write: [0xFB, 0xFB, 0xDB, 0xDB]  ## '\n'
  - platform: template
    name: 'Brew Espresso'
    icon: "mdi:cup-water"
    id: jura_make_espresso
    on_press:
      - uart.write: [0xFB, 0xDF, 0xDB, 0xDF]  ## 'F'
      - delay: 8ms
      - uart.write: [0xDF, 0xDB, 0xDB, 0xDF]  ## 'A'
      - delay: 8ms
      - uart.write: [0xFB, 0xFB, 0xFF, 0xDB]  ## ':'
      - delay: 8ms
      - uart.write: [0xDB, 0xDB, 0xFF, 0xDB]  ## '0'
      - delay: 8ms
      - uart.write: [0xFB, 0xDB, 0xFF, 0xDB]  ## '2'
      - delay: 8ms
      - uart.write: [0xDF, 0xFF, 0xDB, 0xDB]  ## '\r'
      - delay: 8ms
      - uart.write: [0xFB, 0xFB, 0xDB, 0xDB]  ## '\n'
  - platform: template
    name: 'Brew Double'
    icon: "mdi:cup-water"
    id: jura_make_double
    on_press:
      - uart.write: [0xFB, 0xDF, 0xDB, 0xDF]  ## 'F'
      - delay: 8ms
      - uart.write: [0xDF, 0xDB, 0xDB, 0xDF]  ## 'A'
      - delay: 8ms
      - uart.write: [0xFB, 0xFB, 0xFF, 0xDB]  ## ':'
      - delay: 8ms
      - uart.write: [0xDB, 0xDB, 0xFF, 0xDB]  ## '0'
      - delay: 8ms
      - uart.write: [0xDB, 0xDF, 0xFF, 0xDB]  ## '4'
      - delay: 8ms
      - uart.write: [0xDF, 0xFF, 0xDB, 0xDB]  ## '\r'
      - delay: 8ms
      - uart.write: [0xFB, 0xFB, 0xDB, 0xDB]  ## '\n'

sensor:
  - platform: uptime
    name: "Uptime"

  - platform: wifi_signal
    name: "WiFi Signal"
    update_interval: 60s

Hiya. I have managed to flash ESPHome on the official wifi dongle, but im not sure whats next. I looked at the github repo which you posted and it seems its for custom made ESP32 connected to the service port, not the official module? Im not sure what config i should put in ESPHome to flash it onto the original wifi dongle, besides that status_led and uart you have posted above.
Particularly, what should i do with .py and .h files?

Hey, I’ve had a Jura impressa F7 (F-series) for years and have been running a variant of the RyanAlden github code on it for years. I run it on a Wemos D1 as the post starts.

But in the past few weeks I’ve made a lot of improvements to it. I can now read a lot more sensors (almost all counter positions!) namely:

  • Single espresso
  • Double espresso
  • Single coffee
  • Double coffee
  • Single cappuccino (*)
  • Single ristretto (*)
  • Double ristretto (*)
  • Movements of the brewing unit (*)
  • Cleanings performed
  • Descaling performed (*)
  • Number of coffee grounds in the drawer (*)

(*) all these sensors are new compared to the original esphome interaction from Ryan Alden

I also optimized it more for the small SRAM memory that a Wemos D1 (8266 chip) has. I’m going to continue with it myself. i still miss the counters for:

  • hot water
  • steam usage

i also want to port it to an ESP32 chip so you can use more SRAM and have a separate dedicated UART port.

It’s still a work in progress, so if you have any improvements, feel free to post a pull request or “issue” on github!

P.S. the release is a stable version but does not contain all the latest found sensors and SRAM optimizations. and for the ESP32 variant a new branch has been created.

link to my repository: GitHub - alco28/Jura-F7-ESPHOME: Automate your Jura Impressa F* coffee machine. gives full control of all options and counts your consumption.

1 Like