BLE Transport Layer¶
The Segway-Ninebot BLE protocol runs over standard BLE GATT. Three service profiles are supported, selected based on hardware generation.
Service & characteristic UUIDs¶
Ninebot Custom (primary — modern devices)¶
This is the primary service used by current Segway-Ninebot vehicles.
| Role | UUID |
|---|---|
| Service | 6e400001-0000-0000-006e-696e65626f74 |
| Write (app → device) | 6e400002-0000-0000-006e-696e65626f74 |
| RCTP Write (secondary) | 6e400003-0000-0000-006e-696e65626f74 |
| Notify (device → app) | 6e400004-0000-0000-006e-696e65626f74 |
| Test Write (factory) | 6e400005-0000-0000-006e-696e65626f74 |
| Test Notify (factory) | 6e400006-0000-0000-006e-696e65626f74 |
UUID structure
The UUID suffix 006e-696e65626f74 decodes to \x00ninebot in ASCII. The internal codename for this service is "Hospitality".
Characteristic 0004, not 0003
The notify characteristic is 0004, not 0003. Characteristic 0003 is the RCTP Write channel (a secondary write path), not the notification channel. This is a common source of confusion.
Nordic UART (compatibility)¶
Older devices and some accessories use the standard Nordic UART Service.
| Role | UUID |
|---|---|
| Service | 6e400001-b5a3-f393-e0a9-e50e24dcca9e |
| Write (TX) | 6e400002-b5a3-f393-e0a9-e50e24dcca9e |
| Notify (RX) | 6e400003-b5a3-f393-e0a9-e50e24dcca9e |
HMSoft (legacy)¶
Very old devices may use the HMSoft BLE module profile.
| Role | UUID |
|---|---|
| Service | 0000ffe0-0000-1000-8000-00805f9b34fb |
| Notify | 0000ffe1-0000-1000-8000-00805f9b34fb |
Characteristic roles¶
| Characteristic | Property | Usage |
|---|---|---|
0002 (RTP Write) |
Write | App → device commands |
0003 (RCTP Write) |
Write | App → device (secondary channel) |
0004 (RTCP Notify) |
Notify | Device → app responses |
0005 (Test Write) |
Write | Factory/diagnostic writes |
0006 (Test Notify) |
Notify | Factory/diagnostic reads |
The app writes encrypted frames to characteristic 0002 and subscribes to notifications on characteristic 0004.
MTU & fragmentation¶
BLE packets are fragmented at the GATT MTU boundary:
- Default MTU: 20 bytes (BLE 4.0)
- Negotiated MTU: Up to 512 bytes (BLE 4.2+)
- Modern devices support MTU negotiation (
mtu_negotiation: truein device config)
The protocol layer handles reassembly across multiple GATT writes/notifications using the frame sync bytes (0x5A 0xA5) and the length field. A state machine scans incoming bytes for the sync pattern, reads the length, and accumulates bytes until a complete frame is received.
Frame reassembly state machine¶
IDLE ─── see 0x5A ───► HAVE_HEAD ─── see 0xA5 ───► HAVE_BEGIN ──► accumulate
│ │
└── other ──► IDLE until LENGTH + 13 bytes
│
▼
deliver frame
Connection flow¶
sequenceDiagram
participant App
participant Device
App->>Device: BLE Scan (look for "Ninebot*" / "S1D*" names)
App->>Device: Connect
App->>Device: Discover services
App->>Device: Find write (0002) + notify (0004) characteristics
App->>Device: Subscribe to notifications (0004)
App->>Device: Negotiate MTU
Note over App,Device: Begin authentication handshake
App->>Device: PRE_COMM (encrypted, non-SN mode)
Device->>App: auth_param + serial number
App->>Device: SET_PWD (encrypted, SN mode)
Device->>App: accepted
App->>Device: AUTH (encrypted, SN mode)
Device->>App: authenticated
Note over App,Device: Normal encrypted communication
Device discovery¶
Segway-Ninebot vehicles advertise with BLE names that typically follow these patterns:
| Pattern | Example | Device type |
|---|---|---|
S1DXXXXXXXXXX |
S1DCA2045K0123 |
Mopeds (E-series) |
NBxxxxxxxxxx |
NB-MK046J2345 |
Kick scooters (Max, F-series) |
Ninebot-XXXX |
Ninebot-1234 |
Self-balancing vehicles |
The BLE device name is significant — it is used as key material during the first two phases of the authentication handshake.