Skip to content

Releases: AxelHamburch/zapbox_extension

v2.6.4 — GPIO pin added to the successAction message

Choose a tag to compare

@AxelHamburch AxelHamburch released this 15 Sep 12:49

GPIO pin added to the successAction message (v2.6.4)

The LUD-09 successAction message shown after a payment could be ambiguous when
two switches shared the same label, or a label was changed after the fact —
there was no way to tell which switch actually fired from the confirmation text
alone.

The message now also includes the GPIO pin number:

  • With a label: <Label> - GPIO <pin> - x sats sent
  • Without a label: GPIO <pin> - x sats sent

Compatibility

Component Required version
LNbits ≥ 1.4.0

Upgrade notes

No migration needed. Simply uninstall and reinstall the extension in LNbits so
the updated files are loaded.

v2.6.3 — Switch label in LUD-09 success message

Choose a tag to compare

@AxelHamburch AxelHamburch released this 07 Sep 12:59

What's new since v2.6.2

Switch label in the LUD-09 success message (v2.6.3)

Wallets that support LUD-09 (successAction) previously only showed a generic
"X sats sent" confirmation after paying a ZapBox invoice, with no indication
of which switch/relay was actually paid for. The success message now prepends
the switch's configured Label (set per pin in the switch editor), e.g.
"Door - 21sats sent" instead of just "21sats sent". If no label is set,
the message is unchanged. The existing "wrong password" warning still appends
as before.


Compatibility

Component Required version
LNbits ≥ 1.4.0

Upgrade notes

No migrations or breaking changes. Existing switches without a label keep
showing the plain "X sats sent" message; set a Label on a switch to see it
included in the payer's wallet confirmation.

v2.6.2 — PIN entry over the device channel

Choose a tag to compare

@AxelHamburch AxelHamburch released this 01 Sep 14:52

What's new since v2.6.1

pin_submit over the device channel (v2.6.2)

The 4-digit payment PIN was the last payment-critical step still travelling
over a fresh HTTPS connection — on routers that fail new TLS connections in
phases, the PIN submit could fail exactly while the customer waited at the
PIN pad.

  • The channel handler accepts {"event": "pin_submit", "session_id": "...", "pin": "1234"} with the same validation as the HTTPS endpoint and replies
    with pin_submit_result (status / detail) on the same socket
  • The HTTPS endpoint POST /api/v1/nfc/pin_submit remains as fallback for
    older firmware and for when the channel is down
  • With this, the complete PIN flow rides the persistent channel:
    pin_required and pin_error (via push_to_device() since v2.6.1),
    now also the PIN entry itself

Compatibility

Combination Result
PIN-over-channel firmware + extension v2.6.2 ✅ intended setup
PIN-over-channel firmware + extension v2.6.1 ⚠️ PIN payments fail (PIN sent to channel is ignored, session times out) — plain taps and QR unaffected
Older firmware + extension v2.6.2 ✅ PIN arrives via the HTTPS fallback
Component Required version
LNbits ≥ 1.4.0
ZapBox firmware PIN-over-channel build (fix/network-stability, commit ab9daca or later) for the full flow

Upgrade notes

No database migration. Uninstall the old extension in LNbits, install v2.6.2,
flash the matching firmware. Expected log line on the device when a PIN is
entered:

[INFO][PIN] PIN sent over device channel – waiting for WS response

v2.6.1 — Single-connection mode: all events over the device channel

Choose a tag to compare

@AxelHamburch AxelHamburch released this 01 Sep 14:30

What's new since v2.6.0

Single-connection mode (v2.6.1)

v2.6.0 introduced the device WebSocket channel for Bolt Card taps, but ran it
alongside the core WebSocket — two persistent connections to the same
host:443. On NAT-challenged routers those two connections clobber each other's
tracking entries and both flap in a ~60 s cycle. Observed symptoms: QR
payments rejected with "No active ZapBox connections", invoices paid but the
relay trigger lost, Bolt Card replies arriving while the settlement event
vanished into a half-open socket.

v2.6.1 routes every server→device event through the device channel when it
is connected:

  • New module device_channel.py: registry of connected device channels plus
    push_to_device() — device channel first, automatic fallback to the core
    WebSocket. Either/or per event, so no duplicate relay triggers.
  • All push sites converted (relay triggers in tasks.py, pin_required /
    pin_error, teach and auth events, manual trigger endpoint).
  • The device channel's liveness is proven to the server by the firmware's
    protocol pings every 20 s — unlike the core WebSocket, it cannot sit
    half-open unnoticed.
  • The "No active ZapBox connections" check accepts the device channel too:
    matching firmware deliberately keeps only that one connection open and
    releases the core WebSocket.

Compatibility

Combination Result
Firmware ≥ single-connection build + extension v2.6.1 ✅ intended setup — one persistent connection
Firmware < v2.6.0 (HTTPS taps) + extension v2.6.1 ✅ works via fallback
Firmware v2.6.0 build + extension v2.6.1 ⚠️ broken — triggers pushed to the channel are ignored
Single-connection firmware + extension v2.6.0 ⚠️ broken — triggers pushed to the released core WS are lost

Update firmware and extension together. The v2.6.0 firmware/extension pair
is superseded and should not remain installed.

Component Required version
LNbits ≥ 1.4.0
ZapBox firmware single-connection build (fix/network-stability, commit 5f8949d or later)

Upgrade notes

No database migration. Uninstall the old extension in LNbits, install v2.6.1,
then flash the matching firmware. Expected log lines on the device:

[NFC-WS] Device channel connected – single-connection mode
[NFC-WS] Releasing core WebSocket — device channel carries all events

v2.6.0 — Device WebSocket channel for Bolt Card taps

Choose a tag to compare

@AxelHamburch AxelHamburch released this 01 Sep 13:12

What's new since v2.5.4

Device WebSocket channel (v2.6.0)

Bolt Card taps previously reached the server via a fresh HTTPS POST per tap.
Some consumer routers fail new TLS connections in phases (any destination)
while established connections keep working in both directions — on such a
router the NFC payment failed exactly when the phase was bad, while QR
payments (which only ride the established core WebSocket) kept working.

New endpoint: /zapbox/api/v1/ws/nfc/{device_id} — a persistent WebSocket the
device sends events over. A tap now rides an established channel that was
opened once at boot and needs no fresh TLS connection.

  • {"event": "lnurlw", ...} from the device runs the same payment logic as
    the HTTP endpoint (extracted into a shared process_nfc_lnurlw())
  • The reply (lnurlw_result with status/detail/request_id) goes back on
    the same socket; handling runs in a spawned task so the channel stays
    responsive, replies are serialized per connection
  • The relay trigger on settlement still arrives via the core WebSocket
    (/api/v1/ws/{device_id}) exactly as for QR payments — server pings, the
    "No active ZapBox connections" check, and the PIN flow (pin_required via
    core WS, pin_submit via HTTPS) are all unchanged
  • The HTTP endpoint POST /zapbox/api/v1/nfc/{device_id} remains as fallback
    for older firmware and for when the channel is down — compatible in both
    directions

Compatibility

Component Required version
LNbits ≥ 1.4.0
ZapBox firmware any — older firmware keeps using the HTTP endpoint; the channel needs a firmware with serviceNfcWebSocket() (branch fix/network-stability or later)
Reverse proxy must pass WebSocket upgrades on /zapbox/... (usually already configured host-wide for /api/v1/ws/...)

Upgrade notes

No database migration. Uninstall the old extension in LNbits and install
v2.6.0 so the new module is loaded. Devices reconnect automatically; firmware
with channel support logs Device channel connected – taps use the persistent channel once the new endpoint is live.

v2.5.4 — Fixed: Settled payments

Choose a tag to compare

@AxelHamburch AxelHamburch released this 15 Jul 17:23

Bug fixes

  • Payments settled but the device was never triggered (v2.5.4): the invoice
    listener sent the relay trigger via websocket_manager.send(...), which no
    longer reaches the device's WebSocket on current LNbits versions. The call also
    raised, which killed the listener task — so after the first settled payment
    no further payment (single, multi-channel, Bolt Card or Mini-PoS) was
    reported to the device, even though the invoice was paid. Switched tasks.py
    back to the public websocket_updater(...) helper — the same call every other
    trigger in the extension already uses (Identity-Login, NFC-Tag, PIN prompt).
  • Listener hardening (v2.5.4): a failure while handling one paid invoice can
    no longer stop the listener; the error is logged and the next payment is still
    processed.

Upgrade notes

Reinstall the extension (uninstall → reinstall).

v2.5.3 — Decoupling GPIO Relays

Choose a tag to compare

@AxelHamburch AxelHamburch released this 15 Jul 14:42

Relay GPIO is now supplied by the device (v2.5.3)

The extension no longer hard-codes any hardware GPIO. Previously the Mini-PoS
relay pin — and the Identity-Login / NFC-Tag fallback pin — were fixed to a
specific GPIO number in the extension code. When the ZapBox Touch 3.5 channel
layout was re-mapped (the primary channel CH01 moved to GPIO 14), Mini-PoS
stopped switching: the server kept sending the old, now-wrong pin.

The device is the only component that knows its own GPIO layout, so it now tells
the server which relay pin to fire:

  • Mini-PoS: the device sends its primary-channel pin in the
    POST /zapbox/api/v1/pos/invoice body ("pin": <gpio>). It is stored with the
    invoice and echoed back over WebSocket on settlement.
  • Identity-Login / NFC-Tag: the pin / auth_pin query parameters are now
    required (the device already sent them) instead of falling back to a hard-coded
    default.

A future re-map of the channel layout needs no server-side change — the
extension holds no GPIO knowledge at all.

v2.5.2 — Identity🫆Login: LNURL-auth & NFC tap

Choose a tag to compare

@AxelHamburch AxelHamburch released this 28 Jun 18:11

What's new since v2.3.0

This release bundles all changes from v2.4.0 through v2.5.2.


LNURL-auth — Identity Login via Lightning Wallet (v2.4.0)

ZapBox can now recognise a known Lightning wallet and trigger a relay — without any payment. The wallet signs a one-time challenge (LNURL-auth / LUD-04); the server verifies the signature and fires the relay.

  • New teach mode: 6-tap gesture on the device opens a PIN-gated enrolment screen; the wallet scans a QR code to register its public key
  • Up to 3 failed teach-PIN attempts lock the teach access (unlockable in LNbits)
  • Teach session auto-expires after 5 minutes
  • Each k1 challenge is single-use and valid for ~120 seconds

NFC Identity Login — NTAG 424 DNA / Bolt Ring (v2.5.0)

In addition to wallet login, ZapBox now supports NFC card authentication (Bolt Card, Bolt Ring, or any NTAG 424 DNA card):

  • New /api/v1/nfc/auth/ endpoint: verifies tap via tagid_extension, triggers relay WebSocket on a known card
  • New /api/v1/nfc/teach/ endpoint: enrols a card during teach mode
  • Management API for enrolled NFC identities (GET/PUT/DELETE /api/v1/nfc/identities/…)
  • UI: TagID base URL + invoice key fields and enrolled-cards list in the instance editor

Both methods run in parallel — the LNURL-auth QR is always visible while the NFC reader listens simultaneously.


Instance editor UI redesign (v2.5.0 → v2.5.2)

The Identity Login section was fully restructured for clarity:

  • Section is collapsed by default; a single toggle expands all sub-content
  • Teach mode toggle and Teach-PIN (6 digits) shown side by side
  • LNURL-auth Identities and NFC Identities are clearly separated into named sub-sections
  • Section now appears correctly when creating a new ZapBox instance (was hidden during creation)
  • Label updated from "NTAG424" to "NFC Tag"

Bug fixes

  • bech32 LNURL-auth fix (v2.4.3): wallets received the raw URL instead of the bech32 lnurl1… string — auth flow was not recognised. Fixed: .bech32 property is now used correctly.
  • Migration fix (v2.4.1): CREATE UNIQUE INDEX zapbox.auth_key failed on SQLite (schema-qualified syntax not supported). Replaced with inline UNIQUE constraint in CREATE TABLE.

Compatibility

Component Required version
tagid_extension v2.1.0+ (for NFC Identity Login)

Upgrade notes

Migrations run automatically on install. If upgrading from a version before v2.4.1 that left a partial auth_key table, the migration drops and recreates it cleanly.

v2.3.0 - Mini-PoS Support

Choose a tag to compare

@AxelHamburch AxelHamburch released this 11 Jun 19:26

Server-side support for the new ZapBox Touch 3.5" Mini-PoS mode (firmware v953139t): the device requests a Lightning invoice for a freely entered amount, the extension pushes the settlement back over the existing WebSocket.

Tag: v2.3.0 (db1d610) · Requires: LNbits ≥ 1.4.0 · Firmware: ZapBox Touch 3.5" v953139t for Mini-PoS (older firmware keeps working — fully backwards compatible)

✨ Features

Mini-PoS invoice endpoints

  • POST /zapbox/api/v1/pos/invoice (X-Api-Key = wallet invoice key): converts amount + currency to sats (fiat via fiat_amount_as_satoshis, sat/sats passthrough), creates the BOLT11 invoice and stores it in the new zapbox.minipos_payment table
  • GET /zapbox/api/v1/pos/invoice/last?device_id=...: amount/currency of the last settled Mini-PoS payment — used by the LAST PAY button on the device

Settlement push

  • Mini-PoS-tagged settlements mark the payment as paid and push the relay trigger 5-{duration} over the WebSocket — duration taken from the pin 5 switch config (fallback 3000 ms)

Bolt Card pays the pending invoice

  • /zapbox/api/v1/nfc/{device_id} accepts an optional minipos_hash: a Bolt Card tap then pays the pending Mini-PoS invoice (stored bolt11) instead of creating a new withdraw — the PIN-limit flow is unchanged

🐛 Fixes

  • pin_error WebSocket events carry a session_id, preventing stale events from interfering with a new PIN session
  • Device is forced into blocked state when the server reports the card as blocked
  • Import of get_minipos_payment in views_api.py — Bolt Card Mini-PoS payment threw a NameError (HTTP 500)

🗄️ Database

  • New migration m005: table zapbox.minipos_payment (runs automatically on first start after the update)

📜 Commits since v2.2.0

  • db1d610 fix: import get_minipos_payment in views_api - Bolt Card minipos payment threw NameError (HTTP 500)
  • c6f17ec feat: release v2.3.0 - Mini-PoS invoice endpoints and settlement push
  • f037ee7 feat(minipos): Mini-PoS invoice endpoints and settlement push
  • 15648b9 fix: add session_id to pin_error events to prevent stale event interference
  • 2b022a6 fix: force blocked state on device when server reports card blocked
  • f6f206f fix: update extensions.json hash for v2.2.0 (timeout WS event fix)

📦 Install / Update

Archive: https://github.com/AxelHamburch/zapbox_extension/archive/refs/tags/v2.3.0.zip
SHA256: 630759eb904e9c63b71a92c01ddda579e6ab026e7ae47634f68c00013f34b830 (verified against the tag archive, matches extensions.json on main)

v2.2.0 – Bolt Card PIN Limit Support

Choose a tag to compare

@AxelHamburch AxelHamburch released this 23 May 17:33

What's new

Bolt Card PIN Limit (pinLimit)

ZapBox now supports the pinLimit field from the LUD-XX proposal.

When a Bolt Card has a PIN configured and the payment amount reaches the limit, the ZapBox device shows a PIN entry screen. The user enters 4 digits directly on the touch display — no app or phone required.

Flow:

  1. Bolt Card tapped → server detects pinLimit in the LNURLW response
  2. ZapBox shows PIN pad (amount + 4-dot indicator + numpad)
  3. User enters PIN → sent to server → forwarded to Bolt Card server
  4. Wrong PIN: error shown for 5 seconds, up to 3 attempts
  5. Card blocked after 3 failures: 10-second message, then back to normal screen

Changes

  • views_api.py: PIN session handling with asyncio.Event, new POST /nfc/pin_submit endpoint, retry loop with WS events pin_required / pin_error

Requirements

  • ZapBox firmware ≥ feature/pin-pad-screen (JC3248W535C with touch display)
  • boltcards extension on pin-limit branch