Repository navigation
Conversation
The Anker manufacturer record (company id 0xffff) carries the device MAC, model, and a capability byte declaring which negotiation path the device accepts -- readable at scan time, before any frame is sent. Add a parser for it as the basis for choosing the cleartext vs encrypted handshake per device rather than by product class. Capability is length-relative (last byte when present, absent on the F3800), so it is derived from the sku length rather than read at a fixed offset. Decoded against the app's own field values for five bench records. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Move the AES-GCM negotiation out of PrimeDevice into SolixBLEDevice so any device can take it. The path is selected from the capability byte in the device's advertisement when the caller passes one, otherwise from the class default (encrypted for Prime devices, plain text for the Solix power stations). The device's declared MTU and auth mode from 4803 are echoed in 4005, and the timezone confer carries the local UTC offset. A fresh P-256 key pair is generated for every negotiation instead of the hard-coded key pairs; the keys the recorded test vectors were captured with move to the test constants and are pinned by the fake_time fixture. The cipher and ECDH primitives live in utilities as plain functions. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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>
_post_connect on the C1000 G2 and the MagGo 3-in-1 still called _send_command with the pre-parameters signature, so the subscribe that starts their telemetry was never sent. The raw payload a10121 is parameter a1 with value 21, so the bytes on the wire are unchanged. Adds a command test for the C1000 G2 subscribe. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Some devices post a second live frame beside their telemetry stream: a protobuf message built against a schema the device names in the frame. The walker flattens it to a .path map, with packed integer arrays declared per schema so they are not mistaken for sub-messages, and a per-schema field map names and scales the values. A frame naming an unknown schema is kept by path and logged once. The summary, its schema name and the time of the last post are exposed on the device, and state-change callbacks run when one arrives. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Adds the C2000(X) Gen 2 power station on top of the C1000 G2, which shares its telemetry framing and AC/DC control. It negotiates on the encrypted path, which its current firmware requires, subscribes and arms the realtime latch on connect, and decodes the 4103 system group (display, timeouts, SoC limits), the status and time-remaining fields, the version block, and the BP2000 expansion block. Status is polled with get_status_update() like the other power stations. The c490 device summary the unit posts about every nine minutes is decoded through field maps for its two current schema revisions, and the energy ledgers and DC input voltage it carries are exposed as properties that read None until a post arrives; the summary is gated by a schema map the device only holds after reaching the vendor cloud, so a unit kept off the network may never post one. The command test harness now checks every packet a command sends, so a setup routine that sends two can be asserted. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The accepted set was the three values that happened to appear in the captures. The app's picker offers 10 s, 20 s, 30 s, 1 min, 5 min and 30 min, so the device now accepts all six and DisplayTimeout gains S10 for the shortest one. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Each group-command setting gets a PARAMETERS_* constant with a lambda for its value, like the other devices, instead of a helper that built the dictionary at call time. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This was referenced Sep 20, 2026
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Replaces #50 and the C2000 G2 part of #51, rebuilt on Harvey's review with the existing names.
Five commits (the fourth widens the display timeout set to the six values the app offers and adds
DisplayTimeout.S10; the fifth turns the command payloads intoPARAMETERS_*constants):_post_connecton the C1000 G2 and the MagGo 3-in-1 still called_send_commandwith the pre-parameters signature, so their subscribe was never sent. The C1000 G2 hunk is byte-for-byte the one in Fix C1000 Gen 2 subscribe using the new send_command interface #67; this PR adds the same fix for the MagGo and a command test. If Fix C1000 Gen 2 subscribe using the new send_command interface #67 merges first this commit rebases away.SolixBLE/parsing.pywalks a protobuf blob to a.pathmap (packed integer arrays declared per schema), a per-schema field map names and scales the values, and the base class exposessummary,summary_schema,last_summary_updatefor commands listed in_PROTOBUF_TELEMETRY_COMMANDS. Unknown schemas are kept by path and logged once._post_connectsubscribes (4100) and arms the realtime latch (4057) once per connection; decodes the4103system group, status and time-remaining fields, the version block and the BP2000 expansion block; status is polled withget_status_update()like the other power stations (no keep-alive polling).Names and interfaces follow the existing devices per the review:
ac_timer/ac_timer_remaining/set_ac_timer(seconds)and the DC equivalents (the raw fields are live countdowns, confirmed against the app log),ac_charging_power/set_ac_charging_power(watts),power_saving_mode_enabled,device_timeout,is_display_on,display_mode(LightStatus) /set_display_mode(LightStatus),set_display_timeout(DisplayTimeout),software_version_controller,num_expansion.disable_realtime_telemetry,expansion_present,battery_percentage_a6_9andusb_total_power_out-style aggregates are gone; the charge-cap setters carry a.. warning::; parameters are module constants; commands come after properties.The
c490device summary the unit posts about every nine minutes is decoded through field maps for its two current schema revisions (charging_pps_series_c_0005/_0009); the energy ledgers and DC input voltage it carries are properties that readNoneuntil a post arrives, since the post is gated by a schema map the device only holds after reaching the vendor cloud.Docs:
c2000g2.rstcarries the device note; the index table has a C2000 G2 column with ticks and crosses only; the command test harness now checks every packet a command sends, in order.Validated on hardware: C2000 G2 (A1783) with and without a BP2000. The C1000 G2 and MagGo subscribe fix is by inspection of the wire bytes (identical to before the regression).
Suite: 407 passed.
🤖 Generated with Claude Code