Update your Decent Espresso DE1 firmware from macOS over Bluetooth. No Android tablet needed.
The DE1 requires the stock Android tablet app (de1app) to update firmware. If your tablet breaks, or you just don't have an Android device, you're stuck on whatever firmware the machine last received. Community apps like Despresso and Streamline handle shot control but don't do firmware updates.
This tool lets you update firmware directly from a Mac (or any machine running Python with BLE) using a single command.
git clone https://github.com/kalfreese/de1-firmware-updater.git
cd de1-firmware-updater
pip install -r requirements.txtFind your DE1:
python ble_find_de1.pyFlash the latest firmware:
python de1_fw_update.py --address <YOUR_DE1_ADDRESS>The tool connects to your DE1 over Bluetooth Low Energy, downloads the latest firmware from Decent's GitHub repo, and updates it in three steps:
$ python de1_fw_update.py --address A9EA0EC9-E8B4-5751-3929-8A5176ED4448
DE1 Firmware Updater
========================================
Connecting...
Connected.
Downloading latest firmware from GitHub...
Saved to /tmp/bootfwupdate.dat (456,704 bytes)
Reading machine info...
Current FW build: 449
BLE version: 4
HW version: 0x0EB8C631
Firmware to flash:
File: bootfwupdate.dat
Size: 456,704 bytes
Board marker: 0xDE100001
FW version: v1333 (0.0.5.53)
Proceed with firmware update? This will erase and reflash. [y/N] y
[1/3] Erasing firmware slot...
Erase complete.
[2/3] Uploading firmware (456,704 bytes in 28,544 chunks)...
[████████████████████████████████████████] 100.0% (456,704/456,704 bytes)
Upload complete in 1760.8s (0.3 KB/s)
[3/3] Verifying firmware...
Verification PASSED - no errors detected.
The DE1 should reboot with the new firmware.
Done.
The DE1 normally advertises over BLE as "DE1". However, machines with very old firmware advertise as "nRF5x" (the raw Nordic Semiconductor chip name). This is undocumented and will cause standard BLE scans to miss the machine entirely.
The included ble_find_de1.py script handles this by probing every nearby BLE device's service UUID:
$ python ble_find_de1.py
Step 1: Scanning for all BLE devices (15s)...
Found 39 devices.
Step 2: Probing 25 unnamed devices for DE1 service...
Probing 25/25: 74BCA60F-4A5C-708D-06B2-39041E6F7332...
Step 3: Probing 14 named devices for DE1 service...
Probing 2/14: nRF5x [A9EA0EC9-E8B4-5751-3929-8A5176ED4448]...
*** FOUND DE1! ***
Name: nRF5x
Address: A9EA0EC9-E8B4-5751-3929-8A5176ED4448
Service: 0000a000-0000-1000-8000-00805f9b34fb
Save this address for the firmware updater:
python de1_fw_update.py --address A9EA0EC9-E8B4-5751-3929-8A5176ED4448
Once you have the address, use it with --address for all subsequent commands.
If you're not comfortable with the terminal, you can use Claude Code to do this for you. It's the AI coding tool that was used to build this project in the first place.
- Install Claude Code (see docs)
- Open your terminal and type
claude - Tell it: "I need to update my Decent DE1 firmware. The repo is at github.com/kalfreese/de1-firmware-updater. Clone it, set it up, find my DE1, and flash the latest firmware."
- Claude Code will clone the repo, install dependencies, run the discovery script, and walk you through the flash. It handles the technical details so you don't have to.
This is actually how the tool was built: the entire thing, from researching the BLE protocol to writing the code to flashing the machine, was done in a single Claude Code session.
Read machine info without flashing:
python de1_fw_update.py --address <ADDRESS> --scan-onlyFlash a specific firmware file:
python de1_fw_update.py --address <ADDRESS> --file /path/to/bootfwupdate.dat- Quit other BLE apps (Streamline Bridge, Despresso, etc). The DE1 only allows one BLE connection at a time.
- Power cycle the DE1 by flipping the rear switch off, waiting 10 seconds, then flipping it back on.
- Keep the machine powered on during the upload (~30 minutes at 0.3 KB/s over BLE).
- Grant Bluetooth permission to your terminal app (System Settings > Privacy & Security > Bluetooth).
- The tool validates the firmware file header before erasing anything.
- The DE1 has dual-slot firmware. If a flash fails, the machine falls back to the previous working firmware on the next boot.
- After uploading, the tool verifies every byte and reports any errors.
- You'll be asked to confirm before the erase step begins.
- DE1 with firmware build 449 (upgraded to v1333)
- macOS 16 (Darwin 25.2.0)
- Python 3.9.6
- bleak 1.1.1
Should also work on Linux and Windows (anywhere bleak supports BLE), though only tested on macOS.
The DE1 communicates over BLE using a single GATT service (0xA000) with 18 characteristics. Firmware updates use two:
- WriteToMMR (
0xA006) writes 16-byte chunks of firmware data - FWMapRequest (
0xA009) controls erase, verify, and error reporting
The upload protocol: erase the firmware slot, write the entire firmware image in 16-byte chunks starting at address 0x000000, then verify by checking for errors. The firmware file (bootfwupdate.dat) is a binary with a 64-byte header containing a board marker (0xDE100001), version, checksums, and an encryption IV.
- pyDE1 by Jeff Kletsky for the protocol implementation that made this possible. pyDE1 is a full DE1 controller for Raspberry Pi that includes firmware upload. This tool extracts and simplifies that capability into a standalone script.
- Decent Espresso for open-sourcing the de1app and firmware, making community tools like this possible.
- bleak for the cross-platform BLE library.
MIT