Skip to content

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: true in 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.