Setup.
Blog
  • Home Assistant
  • ESPHome
  • ESP32
  • Busch-Jaeger

Build guide · 12 min read

How to make your Busch-Jaeger / ABB-Welcome intercom smart

The full build, step by step: an ESP32 on Mat931's open-source board, ESPHome and Home Assistant.

Flashing the ESP32 doorbell board over a USB-to-serial adapter on the desk.
Flashing the board over USB. Coffee crossed out on the mug, tea it was.

I live in an apartment with a wired Busch-Jaeger door intercom (an ABB-Welcome bus system). Like a lot of people, I wanted the obvious modern conveniences: a push notification on my phone when someone rings, and a way to buzz the door open without walking to the handset. So I went looking for a Ring, a Nest doorbell, an Aqara, basically anything off-the-shelf.

None of it works. Those products assume you're replacing a simple wired button or a standalone doorbell. A building intercom on a proprietary 2-wire bus is a completely different animal: there's no line you can just tap, and there's nothing you can screw a Ring onto. If you have a Busch-Jaeger / ABB-Welcome system and you've hit the same wall, this post is for you.

Before this I'd tried the lazy route: a little sound-activated box (an m-e "Sound-Active") clipped to the handset that's meant to forward the chime. It was miserable. It missed rings behind a closed door, false-triggered on any loud bang, and sometimes stayed silent while the intercom happily rang. So, the proper way it is.

A Busch-Jaeger intercom handset on the wall with a white m-e Sound-Active box mounted above it.
The old hack: an m-e "Sound-Active" box that listened for the chime. Unreliable in every direction.

What my setup does now

A push notification the instant someone rings, even when I'm not home.

My lights blink when the doorbell rings, so I never miss it with headphones on.

A button on my desk opens the building door with one press. The same little box also blinks and plays a chime when someone rings.

All of it runs through Home Assistant, self-hosted, no cloud subscription, no monthly fee.

The key partThe open-source board that makes it possible

The key is an open-source project by Mat931: the ESP32 Doorbell Bus Interface.

It's a small board with an ESP32 that talks the ABB-Welcome / Busch-Jaeger bus protocol directly. Once it's on the bus, it can see bus events (like "someone pressed the doorbell") and send commands (like "open the door"). From Home Assistant's point of view it just shows up as a device with a doorbell sensor and a door-opener switch. Huge thanks to Mat931 for reverse-engineering this and sharing it for free. None of the rest is possible without that work.

Back of the board with pin labels, GPIO25 Bus RX, GPIO26 Bus TX, the open-source hardware logo and Mat931's CERN-OHL licence.
The back says it all: open-source hardware, Mat931's design, and the BUS+ (A) / BUS- (B) pads.

The buildHow the pieces fit together

  • The interface board sits on the intercom bus. When the doorbell is pressed, the board detects the bus event and reports it to Home Assistant.
  • A Home Assistant automation reacts to that event. In my case it does three things at once: sends a push notification via the Home Assistant companion app, flashes my lights a few times, and (optionally) shows an "Open door" action button right in the notification.
  • Opening the door is just Home Assistant telling the board to put the unlock frame back on the bus. I trigger it from a small M5 Atom Echo on my desk: one press on its button and the building door opens. That same Atom Echo also flashes red and plays a chime the moment someone rings, so it doubles as my desk-side doorbell.
The interface board wired up with jumper cables during testing, status LEDs lit.
Wiring it up on the bench, status LEDs on, talking to the bus.

A word on the install, because it's almost anticlimactic: the board is tiny, so it just tucks into the cable box behind the indoor station (a Busch-Jaeger 83205). Its two bus wires go into the same a/b screw terminal the intercom already uses. That's the whole physical hookup.

The ESP32 board wired into the a/b screw terminal inside the cable box behind the indoor station.
Two wires into the same a/b terminal, board tucked into the box behind the intercom.
The ESP32 board sitting inside the cable box behind the Busch-Jaeger 83205 wall casing.
And it just disappears: the whole board fits into the cable box behind the wall casing, nothing on show.

The DIY routeIf you want to build this yourself

Mat931 has already done the hard part: schematics, board files and clear instructions are all in the repo. His how to order guide walks you through getting the PCB made at a fab like JLCPCB. That's the fully DIY route, and it's genuinely well documented.

One heads-up from experience: the fabs typically make you order 5 boards minimum, and at the time I ordered the ESP32 modules were partly out of stock, so plan around that.

Heads-upThe one honest catch: flashing

I won't sugarcoat it. Getting the firmware onto the board the first time was the part that took me longest. If you're comfortable with ESPHome or ESP-IDF it's routine. If you've never flashed an ESP32 before, set aside an evening and follow Mat931's docs carefully. Once it's flashed and set up though, it just works, and you forget it's even there.

In my case "an evening" turned into several. The board's auto-reset circuit just would not drop it into download mode, so esptool printed "Connecting…" forever. Three things finally cracked it: a jumper wire on the RTS pad so I could hit the boot/reset timing by hand, powering the board externally over the bus instead of from the USB adapter (which couldn't push enough current), and swapping in a proper data-grade USB cable, since a charge-only cable powers the adapter just fine while carrying no data at all. Writing the factory image to offset 0x0 was the final piece.

A red FT232RL USB-to-serial adapter with an orange jumper wire soldered to the RTS pad.
The adapter that finally worked. The orange wire on the RTS pad was what saved the day.

WiringWhat I connected to what

Flashing runs over a plain 3.3 V USB-to-serial adapter (I used a red FT232RL). The board has an onboard auto-reset circuit, so there's no holding GPIO0 or pressing buttons. I wired four signal lines to the board's programming header, crossing TX and RX as usual:

FT232RL ↔ board programming header
FT232RLBoard
RTSRTS
DTRDTR
TXRX
RXTX
GNDGND

For power I skipped the adapter's 3V3 line and fed the board from a 15 V bench supply on BUS+ / BUS- (the board takes 12-30 V DC there, and a bare FT232RL often can't supply enough current to flash reliably). Keep a common ground between the adapter and the board.

The ABB-Welcome side needs no wiring from you: on Mat931's PCB the ESP32 uses GPIO26 to transmit on the bus, GPIO25 to receive and GPIO2 for the status LED. In the flat the board simply sits on the two bus wires, BUS+ and BUS- (bus voltage should be around 20-30 V; there's reverse-polarity protection and a resettable fuse).

WorkflowFlashing, connecting and reading logs

The very first flash has to go over USB, following Mat931's how_to_flash guide. After that, everything runs over Wi-Fi. The commands I actually used:

# 1) First flash over USB (the demo / factory firmware)
esphome compile abb-welcome-factory.yaml
esphome run abb-welcome-factory.yaml --device /dev/cu.usbserial-A5069RR4

# if auto-reset fails and esptool just prints "Connecting........":
python3 -m esptool --chip esp32 --port /dev/cu.usbserial-A5069RR4 --baud 115200 erase_flash
python3 -m esptool --chip esp32 --port /dev/cu.usbserial-A5069RR4 --baud 115200 \
  write_flash -z 0x0 .esphome/build/abb-welcome-demo/.pioenvs/abb-welcome-demo/firmware.factory.bin
# then tap RESET on the board while it prints "Connecting........"

# 2) Wi-Fi, no app needed: join the board's own access point
#    SSID: abb-welcome-demo-XXXXXX   password: 12345678   ->  http://192.168.4.1
#    enter your home Wi-Fi, the board reboots and joins your network

# 3) Once it's on Wi-Fi, it's all over the network, no USB:
esphome logs Klingel-esp32.yaml --device 192.168.178.11   # watch live bus frames
esphome run  Klingel-esp32.yaml --device 192.168.178.11   # OTA: flash new firmware

In Home Assistant the board shows up on its own under Settings → Devices & services → ESPHome; adding it there exposes the debug text sensor (I named mine Doorbell Intercom), so you can watch frames live in the dashboard without touching the CLI. That sensor is what I used to read the addresses below.

CustomisingFinding my addresses, and two gotchas

Every ABB-Welcome install is different, so the board doesn't magically know which beep is your doorbell. You read it off the bus. With the debug sensor open, every frame shows up like this:

[1017 > 3001]  Type: 11   ring at the indoor station
[2001 > 1017]  Type: 01   ring at the outdoor station
[1017 > 4001]  Type: 0D   Data: XX XX XX   open door (code redacted)
[4001 > 1017]  Type: 8D   Data: XX XX XX   door-opener confirmation

You press one button, watch the line that repeats, and note the source, destination, type and data. That gave me my four addresses: indoor station 0x1017, outdoor station 0x2001, the gateway 0x3001 and the door controller 0x4001. Nice detail: the last two digits of the indoor address are the apartment number set by the little dials on the back of the unit, in hex.

The opened Busch-Jaeger indoor station board with its a1/b1 terminals and three rotary address dials at the bottom left.
Inside the indoor station itself: the three rotary dials at the top left set the address, and a1/b1 are the screw terminals the board taps into.

Two things cost me an evening. First, there's a second indoor station on the bus (a neighbour), so a naive "outdoor ring" rule fired for their door too. The fix is to pin every condition to my own address. Second, and this one an AI caught for me: I'd joined the checks with and:, but a single frame can't be type 0x11 and 0x91 at once, so the sensor never fired. It has to be or:. Obvious in hindsight, invisible at midnight.

I leaned on ChatGPT for the tedious parts: decoding the raw hex, deciding which frames were reliable, and turning the generic example config into my own. Mat931's how to customize guide is the reference for all of this. After the very first flash over USB, everything since has been over Wi-Fi.

ESPHomeThe config that ties it together

The whole "brain" is a single ESPHome YAML. Two things are worth knowing before you copy it: the ABB-Welcome component needs the ESP-IDF framework (not Arduino), and the ring conditions have to be joined with or:. Here's the heart of it, trimmed, with my door code blanked out:

esphome:
  name: klingel-esp32

esp32:
  board: esp32dev
  framework:
    type: esp-idf          # the ABB-Welcome component needs ESP-IDF

# read the 2-wire bus on GPIO25, transmit on GPIO26
remote_receiver:
  pin: { number: GPIO25, mode: { input: true } }
  dump: [abbwelcome]
  on_abbwelcome:
    then:
      # indoor ring: two message types, joined with OR (not AND!)
      - if:
          condition:
            or:
              - lambda: 'return x.get_message_type()==0x11 && x.get_source_address()==0x1017;'
              - lambda: 'return x.get_message_type()==0x91 && x.get_destination_address()==0x1017;'
          then:
            - binary_sensor.template.publish: { id: doorbell_indoor, state: ON }
            - binary_sensor.template.publish: { id: doorbell_indoor, state: OFF }

lock:
  - platform: template
    name: "Front Door"
    id: front_door
    unlock_action:
      - remote_transmitter.transmit_abbwelcome:
          source_address: 0x1017       # my indoor station
          destination_address: 0x4001  # door controller
          message_type: 0x0d           # unlock
          data: [0x??, 0x??, 0x??]     # your door code, read it from the log

The board then shows up in Home Assistant as a binary_sensor for the ring and a lock entity for the door. After the first USB flash, updates go over Wi-Fi with esphome run … --device <board-ip>.

Home AssistantThe automation behind the alert

On the Home Assistant side, one automation ties the board's doorbell_indoor sensor to everything that should happen: the desk Atom Echo blinks and chimes, a push goes out, and the hallway lights blink and then snap back to whatever they were. The snapshot-and-restore trick is the neat part.

alias: DOORBELL Indoor
triggers:
  - trigger: state
    entity_id: binary_sensor.klingel_doorbell_indoor   # comes from the ESP32
    to: "on"
actions:
  # desk Atom Echo: red blink + chime
  - action: light.turn_on
    target: { entity_id: light.klingel_repeater_atom_echo_led }
    data: { effect: Blink Red, brightness: 255 }
  - action: media_player.play_media
    target: { entity_id: media_player.klingel_repeater_atom_echo_speaker }
    data:
      media_content_id: http://homeassistant.local:8123/local/doorbell-indoor.mp3
      media_content_type: music
  # phone push (Pushbullet)
  - action: notify.pushbullet
    data: { title: Klingel, message: "Jemand ist an der Tür (oben)!" }
  # blink the hallway lights, then restore the previous state
  - action: scene.create
    data:
      scene_id: doorbell_pre_blink_snapshot
      snapshot_entities: "{{ doorbell_blink_lights }}"
  - repeat:
      count: 3
      sequence:
        - action: light.turn_off
          target: { entity_id: "{{ doorbell_blink_lights }}" }
        - delay: "00:00:01"
        - action: light.turn_on
          target: { entity_id: "{{ doorbell_blink_lights }}" }
        - delay: "00:00:01"
  - action: scene.turn_on
    target: { entity_id: scene.doorbell_pre_blink_snapshot }

NotificationsThe honest trade-off with phone alerts

Here's something the tutorials skip. Home Assistant's companion app can give you genuinely instant push notifications, but on Android that means a permanent background connection, and it ate through my battery. So on my phone I switched to Pushbullet, which is light and reliable. The downside: Pushbullet can't carry action buttons, so I can't open the door straight from a phone notification.

That turned out fine, because the thing I actually reach for sits right next to my PC: the M5 Atom Echo. It blinks, plays a chime and opens the door with its button, so at home I never pull out my phone for it. The phone alert is just there to tell me someone rang when I'm in another room.

Android notification: Klingel, Jemand ist an der Tür (unten)!, with an Open door button.
The companion app can even add a "Tür öffnen" (Open door) button. Handy, but it's the battery-hungry path.
Notification titled BzZzzz with the text Tür geöffnet vom Repeater.
And the confirmation when the desk button has opened the door.

CompatibilityDoes this work with your intercom?

If your ABB-Welcome / Busch-Welcome station connects with two wires (usually labelled a and b), it's very likely compatible. Models people have confirmed so far include the Busch-Jaeger 83205 AP-6 (mine), 83220 AP-624 and 83222 U-611, plus the ABB M22002-W-02, M2231, M2234, M22403-W and WLI501B / M22401-W. Some ABB stations use 3-byte addresses, where you set three_byte_address: true. The up-to-date list lives in the wiki, and the board is also on the ESPHome Devices registry.

A large pile of green PCB break-off rails left over after separating 30 boards.
Pre-flashing 30 of them leaves a pile of break-off rails like this.
30 € + shipping

…or skip the ordering and flashing

Here's the honest backstory. I built one for myself and ordered a batch of five (the fab's minimum), then sold four of them to people who found the GitHub thread. That went well enough that I ordered 30, hoping for real interest from the neighbours in my building. Out of 900-plus flats, exactly two said yes. :( I've sold a good few more through the thread since, so there's still a healthy stack on my shelf.

22 of 30 boards left 8 already gone

They're pre-flashed and ready to set up, each with the ESP32 module already fitted, so you skip the 5-board minimum order and the whole flashing learning curve. If that saves you a headache, grab one:

Ask for a board

30 € per board plus tracked, insured DHL shipping. Sent from Germany, anywhere in the EU.

No shop, no business. I'm just passing the extras on to people who'll actually use them. First come first served, and once they're gone they're gone (I'm not ordering more).