Skip to content

Changelog

All notable changes to this documentation project.


2026-04-18

Clarified (provenance)

  • How the ident reaches both sides — New "Provenance" section on the Credential QR page explains: the 16-byte vehicle-action ident is a factory-programmed per-device secret burned into scooter flash at manufacturing, mirrored in Segway's cloud keyed by serial number. The app fetches it once via POST /vehicle/vehicle/vehicle-basic-info with {uid, wnumber} and caches it for offline use. There is no BLE command that sets the ident on the scooter — the scooter already has it — which is why scoot-side verification works offline and why wrong-ident frames fail silently. Documents why the value is not derivable from public inputs (serial, ECU PN, BLE device name).

Added

  • Python BLE Client chapter — Nav was promoted from "Implementation" to a top-level "Python BLE Client" section. client.md rewritten with: current CLI surface (including --ident and open-acc / close-acc / open-trunk subcommands), worked-example walkthrough, per-MAC session-file schema, Gen2/Gen3 constant tables, and "extending the client" recipe. Cross-linked to credentials-qr.md.
  • Vehicle-action builders in the reference clientnb_protocol.py now exposes build_open_acc / build_close_acc / build_open_trunk with a 16-byte ident payload; build_frame and all convenience builders take a gen="gen2"|"gen3" argument (default Gen2 for the E-series moped target). Fixed a latent bug where the old client hardcoded Gen3 sync bytes (0x5A 0xB5) despite claiming E125S (Gen2) compatibility.
  • Credential QR setup page — Documents the segway://credentials?sn=…&pwd=…&ident=… URI format used to transfer session password and vehicle-action ident between installations. Ships a tools/make_creds_qr.py CLI with --password, --ident, --sn, --ascii, and --out flags.
  • Cross-link from Authentication — Added a closing "Authorization beyond the handshake" section so readers who finished the 3-phase handshake know why writes may still silently fail without $ident.

Clarified

  • $ident is a 16-byte secret, not the ECU PN — Rewrote the Vehicle actions section of the command reference. Documented: (1) wire format is 16 raw bytes derived from a 32-char hex string, (2) mismatched payloads are silently dropped by the firmware (MAC still verifies, no error response — the worst possible failure mode for an app developer to diagnose), (3) storage location is iOS UserDefaults {serialNumber}_ident / Android SharedPreferences, (4) the value is cloud-issued at first pairing and cached locally for offline use.
  • Not related to "airlock" — Explicit disclaimer that the nb_airlock_* UserDefaults keys belong to the separate proximity-unlock feature (iBeacon). They coincidentally hold the same byte value in the reference app but are not the source of truth for cmd=0x64 payloads.

2026-04-05

Added

  • fw_data constant documentation — Documented the 16-byte fw_data constant (97 CF B8 02...) from libnbcrypto.so that is substituted for null key2 in Gen2 non-SN mode. Explains why Gen2 and Gen3 produce different ciphertext for the same plaintext.
  • iOS bonded device behaviour — New transport section covering stale CCCD state, notification draining, echo detection, and retry recovery. Practical workarounds for each issue.
  • Vehicle action commands with $ident — Rewrote security commands section. Documents Gen2 vs Gen3 target board differences (VCU 0x09 vs BLE 0x04), action registers (open ACC, close ACC, open trunk), and the $ident authorization token payload.
  • Stored password recovery — Step-by-step guide to extracting stored BLE passwords from iOS backups ({SN}_decrypt key in UserDefaults plist), including sqlite3 and plutil commands.
  • System device discovery — Documented iOS-specific systemDevices() API for finding bonded peripherals that don't appear in scans.

Fixed

  • Index page — Updated Python BLE client description from "untested with real hardware" to "verified against Segway E125S".

2026-04-04 (evening)

Verified

  • Live hardware test — BLE client tested successfully against a real Segway E125S. Handshake (PRE_COMM + stored-password AUTH), register reads, and session persistence all confirmed working.

Fixed

  • MTU fragmentation — App must split outgoing frames exceeding MTU - 3 bytes (20 bytes at default MTU 23). AUTH frames (27 bytes) were silently truncated without fragmentation, causing the device to never respond. Added explicit documentation and implementation.
  • Authentication 0x5A 0xB5 references — Fixed remaining 5A B5 references in handshake examples (should be 5A A5 for BLE).
  • Speed limit data values — Corrected speed limit write examples (values are in 0.1 km/h units: 250=25 km/h, not 0x19=25).
  • Odometer units — Documented as 0.001 km (1 metre precision), not raw km.

Added

  • Board availability by power state — Table showing which boards respond when vehicle is off (DIS, BLE, VCU: always on; MCU, BMS, ECU: asleep). Commands to sleeping boards time out silently.
  • Reconnect counter documentation — First AUTH frame in reconnect mode uses counter=2, same as normal flow.
  • --password CLI flag — Supply stored password from iOS backup to skip SET_PWD phase during reconnection.
  • Register value units — Range (0.1 km), speeds (0.1 km/h), odometer (0.001 km) now explicitly documented.

2026-04-04

Fixed

  • Critical: BLE header correction — All BLE protocols (Protocol 2, Encryption2, Encryption3) use 0x5A 0xA5. The 0x5A 0xB5 header is exclusively used by WiFi v2 transport (WifiEncryptionProtocol2). Previous documentation incorrectly stated Encryption2 uses 0x5AB5. Confirmed by decompilation of BleEncryption2Protocol.java (FRAME_BEGIN = -91, i.e. 0xA5) and WifiEncryptionProtocol2.java (FRAME_BEGIN = -75, i.e. 0xB5).

Added

  • Per-device protocol map — All 71 devices now show their BLE protocol class (Proto1, Proto2, Enc2) on the Board Addressing page, derived from backup_config.nb scan configuration.
  • Protocol column in device tables — The Device Command Reference tables now include a Protocol column, auto-generated from generate_device_pages.py.
  • Protocol class hierarchy — Full class hierarchy documented (BleProtocol1 → BleProtocol2 → BleEncryption2Protocol → BleEncryption3Protocol2), including WiFi variants.
  • Encryption3 / V3Auth — Added documentation for the newest protocol variant (BleEncryption3Protocol2), which uses a different handshake flow.
  • Protocol version selection logic — Documented DynamicDevice.createBleProtocol() selection rules and BLE advertisement manufacturer data (0x4E42/0x4E43).
  • Gear profile commands — MCU board registers for reading/writing gear profiles (top speed, acceleration, TCS, nitro, energy recovery, speed safety lock).
  • Vehicle action commandspower-on, power-off, open-seat CLI commands with --ident flag for E-series mopeds (cmd 0x64, target VCU 0x09).
  • Sound preset control — DIS register 0x75 (rWarn) bit 8 for sound effect toggling, volume control, alarm settings.
  • Gen2/Gen3 protocol support — BLE client now supports both Gen2 (E-series mopeds) and Gen3 (newer kick scooters) protocol variants via --gen flag.
  • Changelog — This page.

Changed

  • WiFi v2 documentation clarified — WiFi v2 section now explicitly states it is the only protocol using 0xB5.
  • Device count updated — 71 devices documented (was 66), including newer models from updated scan config.

2026-03-28

Added

  • Initial release — Full protocol documentation published.
  • 66 device command tables — Auto-generated from decrypted device configuration packages.
  • Python BLE client — Reference implementation of Encryption2 protocol.
  • Encryption algorithm — Complete AES-128 CTR + CBC-MAC documentation with Python reference code.
  • Authentication handshake — 3-phase PRE_COMM / SET_PWD / AUTH sequence.
  • BLE transport — Service UUIDs, characteristics, MTU handling.
  • Board addressing — Module IDs and routing for all device families.
  • Command reference — Register-based read/write commands for speed, battery, lights, security.
  • Firmware update protocol — IAP (In-Application Programming) documentation.