Skip to content

feat(ble): client-token pairing with physical button confirmation - #1

Closed
kb1ibt wants to merge 2 commits into
pr/negotiation-pathfrom
pr/pairing
Closed

kb1ibt wants to merge 2 commits into
pr/negotiation-pathfrom
pr/pairing

Conversation

@kb1ibt

@kb1ibt kb1ibt commented Sep 20, 2026

Copy link
Copy Markdown
Owner

Replaces the pairing half of flip-dots#49.

Firmware that pairs clients (C2000 G2 v0.3.3.0) answers the client registration with status 09 the first time it sees a token and waits for the button on the device; once pressed it pushes a grant on packet pattern 030101 and remembers the token, so later connections are accepted silently.

  • SolixBLEDevice(ble_device, capability=None, client_token=None): the token registered in 4027, defaulting to the class UUID string so the Prime bytes on the wire are unchanged.
  • 4827 status 00 authorizes the link; 09 sets pairing_required and runs the registered add_pairing_callback / remove_pairing_callback callbacks so the user can be told to press the button (the callback option from the feat(prime): A91B2 (240W) + A2345 (250W) live BLE telemetry + control flip-dots/SolixBLE#51 review). connect() keeps waiting for the grant instead of restarting the handshake; the grant on 030101 authorizes.
  • On the encrypted path negotiated now requires the authorization; the plain-text path is unchanged.
  • Docs: "Pairing with a button press" section in protocols.rst, including a note that an account's owner_user_id passed as the token registers the same bytes the app sends and pairs without a press.

Validated on hardware: C2000 G2 with a fresh token (button press) and with a remembered one.

Suite: 369 passed.

🤖 Generated with Claude Code

kb1ibt and others added 2 commits September 13, 2026 15:12
The client registration on the encrypted path now carries a client token
(the class identifier unless the caller passes one) and the link only counts
as negotiated once the device accepts it. Firmware that pairs clients
answers a new token with status 9 and waits for its button: the device
reports pairing_required, runs the registered pairing callbacks so a user
can be prompted, and connect() keeps waiting instead of restarting the
handshake. The grant the device then pushes on pattern 030101 authorizes
the link. The device remembers the token, so later connections with the
same token are accepted without a press.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@kb1ibt kb1ibt closed this Sep 20, 2026
kb1ibt added a commit that referenced this pull request Oct 6, 2026
From the advertisements in SolixBLE and HaSolixBLE issues: product types b112 (F3800 Plus, the A1790's command and telemetry map), b006 (Solarbank 2 E1600 Pro), b103 (C800; A1753/4/5 share one map) and b119 (C1000 Plus / X Gen 2, the A1763's display-board build), and the advertised model names. The A1763 part-number entry goes: that model advertises "SOLIX C1000 Gen 2".

The A1340 Prime power bank advertises service 2215 and uses 22150002/22150003 characteristics with the ff09 framing and negotiation; it gets Transport2215, and the factory returns None for it as for the legacy transport until a class exists. discover_devices also matches the 0xffff record, which a passive scan carries without the services, and uses the scanner it is given.

Telemetry is matched on the 12-bit message type, so a clear fragmented 8405 (SolixBLE #1) is read as the c405 a model lists; the always-telemetry type stays 0x300.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant