Wallbox Gateway — local BLE → MQTT / HA for Pulsar Chargers (no cloud, full HA control)

ESP32-S3 gateway that talks to a Wallbox Pulsar over BLE and publishes everything to MQTT / HA. No cloud, no Wallbox account — fully local on your LAN.

Home Assistant picks it up automatically via MQTT discovery OR Native HA Intergration

HA out of the box (~30 entities):

  • Start / stop charging, lock / unlock
  • Live power, current, voltage, session kWh
  • Lifetime Energy sensor wired for the HA Energy dashboard
  • Schedule editor, Eco Smart mode, Phase Switch, Halo LED, Auto Lock, OCPP

Also a self-hosted web UI on the ESP32 itself — captive-portal first-boot,
weekly heatmap with click-to-drill-down, daily charging totals (groups
solar/eco-smart pause/resume cycles into one plug-in event), CSV export of
session history, and a "Release BLE for app" button so you can pop into
the official Wallbox app without rebooting the gateway.

Hardware: ESP32-S3 with 8 MB+ flash. I'm using an N16R8 with IPEX antenna
— the Pulsar MAX BLE is weak so range matters.

Install: flash via ESP Web Tools in the browser
or OTA, connect to the WallboxGW-Setup AP for first-boot config.

Repo + pre-built binaries: GitHub - botts7/esp32-wallbox: Local BLE to MQTT gateway for Wallbox Pulsar MAX. No cloud. Home Assistant auto-discovery. · GitHub

Pairs nicely with the official HA Wallbox cloud integration if you want
session cost and billing history — this gateway handles the local/fast side,
that one handles the cloud side. Use both.

Feedback and compatibility reports from other Pulsar MAX owners (or
adjacent models — Pulsar Plus, Copper SB) much appreciated.

I just got my first EV and have been looking for chargers that integrate well with home assistant. This looks awesome!

Thank so much for the work and posting!

Thanks @Judman13 let me know how you go if you get the charger

Wow, great project! I will install it and provide you with feedback. I’ve tried multiple ways to manage this wall box, but if this works well, it’s a game changer.

May I ask if this can manage the power charging control, modifying the current in real-time?

Thank you. Please do! There is a slider for the current. Im not sure how the Wallbox handles a max current change when already charging.

You could try modifying current using a HA automation and see if it works, or change current while its charging with the slider. This has not been tested so do so at your own risk! But I believe its a standard Wallbox feature to alow for tarrif changes or solar production changes.




This is an interesting project.. I haven't tried it yet, but I definitely will. Nice work!

Have you considered skipping the whole MQTT in between layer and just making it a custom HA integration? HA supports BLE proxies as far as I know (Bluetooth - Home Assistant), so range shouldn't be a problem.

I guess the local webui would be lost by this approach, so that might be the reason why you choose not to. Just curious to hear your thoughts :slight_smile:

Great question — I did consider it, and there's a real argument for the
HA-native route. Reasons I went with the MQTT bridge:

  1. Standalone operation. The ESP32 has its own web UI and keeps charging
    working even when HA is down (restart, update, migration). Schedules live
    on the ESP32, not in HA's state machine. For something that controls a
    real-world appliance, I wanted decoupling from any single consumer.

  2. A BLE proxy isn't quite the right shape. HA proxies relay raw GATT
    traffic — they're great for stateless devices (BLE thermos, presence
    beacons). Wallbox uses a stateful custom protocol (BAPI framing with
    sequencing + checksums on writes, raw JSON on responses, PIN auth flow).
    A native integration would still need that whole protocol stack
    reimplemented in Python under HA's async loop, with its lifecycle
    quirks. The ESP32 already does this in C++; moving it to HA is a rewrite.

  3. Multi-consumer. MQTT means Node-RED, openHAB, custom scripts, or a
    future second HA instance can all consume it. Pure HA integration locks
    in to HA.

  4. Dedicated radio. Single-purpose ESP32 holds the BLE link 24/7. HA's
    Bluetooth stack shares time with whatever else you've got it doing
    (ESPresense, etc.) and reconnect behavior under load isn't always
    great.

  5. OTA. Firmware updates ship as a .bin you upload to the device. No
    redeploying integration code or bumping HACS versions.

That said — a native integration is absolutely doable. The
right path would be: extract a pybapi Python library, then build the
integration on top with an HA Bluetooth backend. The protocol's already
documented in the repo's include/bapi.h.

For now the architecture is "ESP32 = the protocol; HA = the dashboard",
which I think keeps both ends simple.

v2.2.0 just shipped — biggest release since launch:

:electric_plug: WebSocket live dashboard — no more 10-second polling lag. Web UI
tiles update the instant the gateway gets fresh data from BLE.

:money_bag: Cost tracking with time-of-use tariffs — set your $/kWh + custom
peak / off-peak / shoulder periods (any number of tiers, day-of-week + hour
ranges). See $ per session, per day, and Week/Month totals at a glance.
CSV export for spreadsheet nerds.

:sun: Solar savings tracking — if you use Eco Smart mode, the charger
already knows how much of each session came from your solar surplus vs the
grid. This release surfaces that as a real $ figure:

"15 kWh charged from solar this week — $4.50 saved vs grid rates"

Set your feed-in tariff in the cost panel and you can also see what you
chose to self-consume vs export. Pairs with HA's Energy dashboard for the
long-term picture.

:bell: Charger notifications surfaced on the dashboard tile.

:satellite_antenna: BLE health banner with 5 tiers — tells you when to move the ESP32
closer instead of just feeling slow UI.
:bell: Charger notifications surfaced on the dashboard tile.

:satellite_antenna: BLE health banner with 5 tiers — tells you when to move the ESP32
closer instead of just feeling slow UI.

:shield: Settings panels won't overwrite real config — refuse to render if
they couldn't read current state from the charger (was a real bug — fall-
back defaults could silently overwrite eco/lock/OCPP if you opened a panel
during a BLE blip).

Download / changelog → Release v2.2.0 — Cost tracking · WebSocket live dashboard · Panel guards · botts7/esp32-wallbox · GitHub

OTA upgrade from v2.x at http://wallbox-gw.local/ota.

Coming next (~2 weeks): PWA push notifications — "Charging complete"
alert on your phone without HA or cloud, with toggle for HA users who
already get notifs that way.

:folded_hands: Compatibility wanted: anyone running a Pulsar Plus, Copper
SB
, or Commander 2, please open a GitHub issue with the r_dat
output from /info — keen to broaden the supported charger list.

I've realised it is a dumb question - the firmware page gives a bit more info. I've ordered an ESP32-S3 and will try it this week with our PulsarPlus charger.


This is probably a dumb question but is control "instant" when I do things like start/stop charging? I'm using the official Wallbox integration and the 90 second polling interval is causing problems - if I try to do things too soon after the car has been plugged in it fails. And because it takes up to 90 seconds to action anything people keep hitting buttons wondering why it's broken!

[quote="peter_mcc, post:9, topic:1007464, full:true"]
I've realised it is a dumb question - the firmware page gives a bit more info. I've ordered an ESP32-S3 and will try it this week with our PulsarPlus charger.


Not a dumb question at all — that's the exact pain that motivated this
whole project. Short version:

Yes, control is essentially instant. Commands typically round-trip
in ~1–2 seconds over BLE, and live state pushes to the web UI / HA
in real time via WebSocket. The 90-second cloud polling lag you're
hitting with the official integration is gone, because there's no cloud
in the path at all. Tap "Stop" → it stops.

Now to your bigger news — Pulsar Plus is the model I've been hoping
to get a real datapoint on.
I spent some time today reading
@jagheterfredrik's
wallbox-ble (HA
component that targets Plus directly) so I could brief you honestly on
what to expect. The repo's been quiet for a while, but the
protocol details don't go stale.

Differences vs Pulsar MAX (what our current build supports):

Pulsar MAX (ours) Pulsar Plus
BLE UUIDs u-blox single bidirectional char Nordic UART — separate RX (write) and TX (notify) characteristics
Frame format EaE + len + JSON + checksum Identical :white_check_mark:
Pairing App-layer PIN auth OS-level BLE pairing required first
Status codes 0–210 sparse map (lots of values) 0–18 dense map (different meanings)
BAPI methods ~70 used Mostly overlapping — core commands match

So roughly: the commands and JSON shape are the same, but the
transport layer (UUIDs, RX/TX separation, pairing) is different.

What I'll add to the gateway to support Plus:

  1. Dual RX/TX characteristic mode (the biggest change — currently we
    write and read on one char; Plus needs two)
  2. "Charger model" dropdown in the Config page so you pick Pulsar MAX
    (default)
    or Pulsar Plus; presets fill the right UUIDs + char roles
  3. Per-model status-code translation table
  4. Auto-detect on the BLE Scan step (Plus advertising-name prefix should
    make this trivial)

Ben's recent SMP-pairing PR in v2.3.0 may already handle Plus's
OS-level pairing requirement — that's the one piece I want to confirm
with your hardware. Best case: very little new code needed.

What I need from your first run (which is also what I planned to ask
of any Plus tester):

  1. Flash v2.3.0, captive-portal setup (WiFi + MQTT). Leave BLE
    address blank.
  2. On http://wallbox-gw.local/ → Config → hit BLE Scan. Send me
    the advertised name, address, and the listed services/UUIDs.
  3. Telnet in (telnet wallbox-gw.local — new in v2.3.0, also by
    @benvanmierloo :folded_hands:) and try saving the BLE address. The scan / connect
    / service-discover log lines tell me almost everything.
  4. If you can paste an r_dat response (raw BAPI output via the Info
    page's tool), even better — confirms which fields your firmware emits.

With that data I can almost certainly ship a v2.4 with Pulsar Plus
support shortly after. Either open a GitHub issue with the logs, or
just paste them here — happy either way.

Looking forward to it!

Not a dumb question at all — that's the exact pain that motivated this
whole project. Short version:

Yes, control is essentially instant. Commands typically round-trip
in ~1–2 seconds over BLE, and live state pushes to the web UI / HA
in real time via WebSocket. The 90-second cloud polling lag you're
hitting with the official integration is gone, because there's no cloud
in the path at all. Tap "Stop" → it stops.

Now to your bigger news — Pulsar Plus is the model I've been hoping
to get a real datapoint on.
I spent some time today reading
@jagheterfredrik's
wallbox-ble (HA
component that targets Plus directly) so I could brief you honestly on
what to expect. The repo's been quiet for a while, but the
protocol details don't go stale.

Differences vs Pulsar MAX (what our current build supports):

Pulsar MAX (ours) Pulsar Plus
BLE UUIDs u-blox single bidirectional char Nordic UART — separate RX (write) and TX (notify) characteristics
Frame format EaE + len + JSON + checksum Identical :white_check_mark:
Pairing App-layer PIN auth OS-level BLE pairing required first
Status codes 0–210 sparse map (lots of values) 0–18 dense map (different meanings)
BAPI methods ~70 used Mostly overlapping — core commands match

So roughly: the commands and JSON shape are the same, but the
transport layer (UUIDs, RX/TX separation, pairing) is different.

What I'll add to the gateway to support Plus:

  1. Dual RX/TX characteristic mode (the biggest change — currently we
    write and read on one char; Plus needs two)
  2. "Charger model" dropdown in the Config page so you pick Pulsar MAX
    (default)
    or Pulsar Plus; presets fill the right UUIDs + char roles
  3. Per-model status-code translation table
  4. Auto-detect on the BLE Scan step (Plus advertising-name prefix should
    make this trivial)

Ben's recent SMP-pairing PR in v2.3.0 may already handle Plus's
OS-level pairing requirement — that's the one piece I want to confirm
with your hardware. Best case: very little new code needed.

What I need from your first run (which is also what I planned to ask
of any Plus tester):

  1. Flash v2.3.0, captive-portal setup (WiFi + MQTT). Leave BLE
    address blank.
  2. On http://wallbox-gw.local/ → Config → hit BLE Scan. Send me
    the advertised name, address, and the listed services/UUIDs.
  3. Telnet in (telnet wallbox-gw.local — new in v2.3.0, also by
    @benvanmierloo :folded_hands:) and try saving the BLE address. The scan / connect
    / service-discover log lines tell me almost everything.
  4. If you can paste an r_dat response (raw BAPI output via the Info
    page's tool), even better — confirms which fields your firmware emits.

With that data I can almost certainly ship a v2.4 with Pulsar Plus
support shortly after. Either open a GitHub issue with the logs, or
just paste them here — happy either way.

Looking forward to it!

Quick follow-up — v2.3.0 is now live on GitHub Releases →
Release v2.3.0 — Community contributions · solar savings · faster reveal · botts7/esp32-wallbox · GitHub

Two notable additions in this drop, both from @benvanmierloo (first community PR on the project, much appreciated :folded_hands:):

  • BLE SMP pairing for Wallbox firmware ≥ 6.11.26 — newer firmware
    requires an encrypted BLE link before allowing notifications. The
    gateway now handles that transparently. Backwards-compatible with
    older firmware.
  • Telnet log server on port 23 — telnet wallbox-gw.local from
    any machine on your LAN gives you live serial output without a USB
    cable. Lovely for debugging.

Plus on the local-additions side: :sun: solar savings on the Stats tiles (per-week / per-month $ saved vs grid tariff for Eco Smart users), and a DOMContentLoaded reveal fix that makes the UI feel snappierunder load.

Pulsar Plus compatibility is in active prep — the v2.4 branch already has dual-RX/TX-characteristic support and a "Charger model" dropdown ready. Looking for Pulsar Plus owners to flash and share scan/telnet logs. A new pulsar-plus-compat issue template makes that 60 seconds of work — even partial reports are useful.

I’ve got a Pulsar Plus and can confirm v2.3 doesn’t work. Charger is running 6.7.38. How can I help?

Excellent — "doesn't work" is exactly the data I needed. Thanks for
flashing v2.3 to confirm the baseline.

Quick context: v2.3 ships u-blox UUIDs by default (Pulsar MAX BLE
radio). Pulsar Plus uses a different module — Nordic UART pattern with
separate RX/TX characteristics. So the gateway connects to your Plus
but then fails on service discovery looking for the wrong UUIDs.

I have a v2.4-pulsar-plus branch staged for exactly this — adds a
"Charger model" dropdown in Config → Advanced that flips to the Nordic
UART preset. I'll cut a pre-release binary in the next hour and post the
link here.

In the meantime, two things that would massively help:

1. BLE scan + telnet log (so I can confirm the Plus UUIDs still
match what Fredrik documented):

  • Open http://wallbox-gw.local/config → tap BLE Scan, copy the
    row that looks like your charger
  • In another window: telnet wallbox-gw.local (built-in Win10+, or
    nc wallbox-gw.local 23)
  • Save the BLE address and watch the log capture the connect attempt

2. FW confirmation — 6.7.38 is pre-SMP-era, so plain CCCD writes
should work without any encryption fallback. Good news, less to fail.

You can paste the scan + log inline here, or open an issue using the
"Pulsar Plus compatibility report" template on the repo — either works.

Standby for the binary.

I did a report on the repo. Telnet isn’t installed by default with Win 11 though it can be added. A bigger issue was that you’re only sending LF with the log messages not CRLF so they were hard to read. I had to install Putty then find the special option to turn LFs into CRLFs when receiving.

I’m in Australia (not sure if that’s relevant) - my charger has the latest firmware according to the Android app.

PS Sorry I didn’t read your post above before trying things - I also had the Github page open so when my ESP32 arrived today I followed the instructions there, not realising you’d commented here as well.

No apology needed. Two things came out of your scan: fixed the LF/CRLF telnet bug you flagged, and wired up the Pulsar Plus dropdown - both in rc2.

Release v2.4.0-rc2 — Pulsar Plus pre-release · telnet CRLF fix · botts7/esp32-wallbox · GitHub

Let me know how it goes?

Hmmm, the OTA update fails at 8%. Goes very quickly from 0-8% then stops and says “upload error”. The first time I had to power cycle the board, all the other times it’s just failed. I rebooted it and tried with the 2.3.0 firmware and it did the same thing.

It’s in the garage, I’m in the house and it’s wet out (they aren’t connected) - I’ll take my laptop up there a bit later and update via USB.

Not sure if this is a “me” bug or something you want me to report. Gets to 8% with Chrome, gets to 43% with FireFox. Gets to 8% with Edge. All Win 11.

Possibly worth a try before the rain run — your v2.3.0 has a
Release BLE for App button under Settings → Charger that pauses
BLE for 5 minutes.

The hunch (not 100% sure): your gateway is in a tight reconnect loop
because v2.3 keeps trying the wrong UUIDs on your Plus, and every
scan/connect cycle hands the radio to BT for a few seconds. That
might be starving WiFi enough to drop the OTA TCP upload. If that
turns out to be what's happening, releasing BLE first should give
/ota a clean window. Could also be something else entirely — only
one way to find out.

I've added v2.4.0-rc3
on the assumption that diagnosis is right — it pauses BLE
automatically at OTA start so future flashes don't trip the same
issue regardless. Same Plus dropdown + CRLF fix as rc2 plus that.

If you want to try without going to the garage:

  1. Existing dashboard (v2.3.0)
  2. Settings → Charger → Release BLE for App → confirm
  3. /ota → upload wallbox-gateway-esp32s3-v2.4.0-rc3.bin
  4. After reboot: /config → Advanced → Charger model = Pulsar Plus → Save

USB should still works either way.

Huge thanks to @botts - it’s now working with my Wallbox Pulsar Plus!