Mobile App Development for Electric Scooters and E-Bikes

Electric scooters and e-bikes with a controller are not just devices with a BLE chip. A typical stack: a BLDC motor controller (Sabvoton, Kelly, Votol) communicates with a display or BMS via UART/RS485 (often proprietary), while a BLE module (Nordic nRF52840, ESP32) listens to the bus and relays dat

Development and support of all types of mobile applications:

Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1All 1734 services
Mobile App Development for Electric Scooters and E-Bikes
Complex
from 1 week to 3 months

Our competencies:

Frequently Asked Questions

Latest works

  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    897
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    784
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    1081
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    1004
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    599

Electric scooters and e-bikes with a controller are not just devices with a BLE chip. A typical stack: a BLDC motor controller (Sabvoton, Kelly, Votol) communicates with a display or BMS via UART/RS485 (often proprietary), while a BLE module (Nordic nRF52840, ESP32) listens to the bus and relays data to the mobile app. Developing an app without understanding this chain ends with an app that "connected" but doesn't know what to do with the byte stream. Our team has 5+ years of experience in this niche and over 30 successfully launched projects. We guarantee a stable BLE connection and correct data handling from any controllers.

How we solve the problem of missing controller documentation

Most controller manufacturers (especially Chinese) do not publish protocols. The process: remove the original display, connect a USB-UART analyzer (FTDI232, CP2102) in parallel to the bus, and capture traffic logs. Tools: PulseView with UART decoder, or simply log to a file via minicom/CoolTerm.

A typical Xiaomi M365 protocol frame (as an open example):

[0x55][0xAA][len][addr][cmd][data...][crc_lo][crc_hi] 

The frame starts with 0x55 0xAA, followed by payload length, recipient address (0x20 — controller, 0x21 — BMS, 0x3E — display), command, data, CRC16. For less popular brands, CRC is computed differently — XOR, Modbus CRC, sometimes just a sum of bytes with a mask.

class ScooterFrameParser { private val buffer = ByteArrayOutputStream() fun feed(byte: Byte): ScooterFrame? { buffer.write(byte.toInt()) val bytes = buffer.toByteArray() // Look for frame start val start = findStart(bytes) ?: return null if (bytes.size - start < 4) return null val len = bytes[start + 2].toInt() and 0xFF val totalLen = len + 6 // header(2) + len(1) + addr(1) + cmd(1) + crc(2) - 1 if (bytes.size - start < totalLen) return null val frame = bytes.copyOfRange(start, start + totalLen) buffer.reset() if (start + totalLen < bytes.size) { buffer.write(bytes, start + totalLen, bytes.size - start - totalLen) } return if (verifyCRC(frame)) parseFrame(frame) else null } } 

Why BLE connection stability is critical for rides

On Android, BLE works via BluetoothGatt. The main pain is onConnectionStateChange with status = 133 (GATT_ERROR) when connecting, especially on Android 12+ with Bluetooth Permission enabled. Remedy: retry with 500–1000 ms delay, maximum 3 attempts, then show the user an instruction to reconnect Bluetooth.

class ScooterBLEManager(private val context: Context) { private var gatt: BluetoothGatt? = null private var retryCount = 0 fun connect(device: BluetoothDevice) { gatt = device.connectGatt(context, false, object : BluetoothGattCallback() { override fun onConnectionStateChange(g: BluetoothGatt, status: Int, newState: Int) { when { newState == BluetoothProfile.STATE_CONNECTED -> { retryCount = 0 g.discoverServices() } status == 133 && retryCount < 3 -> { retryCount++ g.close() Handler(Looper.getMainLooper()).postDelayed({ connect(device) }, 800) } else -> notifyConnectionFailed() } } override fun onCharacteristicChanged(g: BluetoothGatt, characteristic: BluetoothGattCharacteristic, value: ByteArray) { frameParser.feed(value) } }, BluetoothDevice.TRANSPORT_LE) } } 

On iOS, CBPeripheral is more stable, but the CoreBluetooth session does not survive app restart — we save peripheral.identifier (UUID) in UserDefaults and restore via retrievePeripherals(withIdentifiers:). A platform comparison shows that Android BLE requires more retry mechanisms, increasing development time by 10–15% relative to iOS.

Characteristic Android iOS
Connection stability Lower (status 133) High
Retry logic 3 attempts Not required
BLE layer development time ~2 weeks ~1 week
Background operation Limited (Background limits) Good

Dashboard: what we display

Standard data set from a scooter/bike controller:

  • Speed (km/h) — actual from wheel sensor or calculated from RPM + tire circumference
  • Battery charge (%) — from BMS, rarely voltage-based estimation
  • Battery voltage/current — important for monitoring regeneration
  • Controller and motor temperature — critical for heavy climbs
  • Mileage — odometer, total and per trip
  • Riding mode — Eco/Normal/Sport or D1–D5
  • Brake status (if sensors are connected to the controller)

We highlight speed, battery charge, and temperature as key indicators — their updates should be as fast as possible. A speed graph during the trip is mandatory. Render via MPAndroidChart (Android) or Swift Charts (iOS 16+). Data is written to Room/Core Data every 500 ms — a 30 km trip at this interval yields ~3600 points, which is not a problem.

Details on controller protocolsBeyond Xiaomi, there are protocols with frames 10–20 bytes long, where CRC is computed as XOR of all bytes, or Modbus RTU. We have analyzed Votol controllers (EM-30, EM-100) — there the frame starts with 0xAA, command 0xB1 for data, CRC16 Modbus. The parsing algorithm is universal: find the preamble, read length, check CRC.

Controlling modes and controller settings

Some controllers allow reprogramming parameters: maximum current, speed limit, regenerative braking power. We send a write command to the Notify Characteristic. Important: changing controller parameters requires user warning and confirmation — incorrect current can damage the motor or drain the battery in one trip.

For sharing services (fleet of scooters), a server part is added: MQTT or WebSocket, trip history on the backend, geofencing, remote lock. This is a separate level of complexity.

Process

  1. Analysis of the controller protocol and BLE module specification (1–2 weeks).
  2. Connection prototype: receive and send commands, verification (1 week).
  3. UI/UX development: dashboard, trip screen, settings (2–3 weeks).
  4. BLE layer implementation, parser, data recording (2 weeks).
  5. Testing on real rides (1–2 weeks).
  6. Publishing to App Store and Google Play, passing review (1 week).

Timelines: 6–8 weeks for a single platform, 3–4 months for a cross-platform solution (Flutter) with support for multiple protocols. Cost is calculated individually after analyzing your specific device model and the availability of protocol documentation. Contact us for a project assessment.

What is included

After project completion, you receive:

  • Source code of the app (native or Flutter) with documentation.
  • Build and deployment instructions.
  • Controller protocol documentation (if reverse engineering was performed).
  • Access to the repository and CI/CD tools.
  • Support during app store publishing.
  • Fleet administrator training (if a sharing project).

We guarantee stable BLE connection and correct data parsing. We continuously update the app for new iOS and Android versions.

Save time: order turnkey app development and get a product tested on real devices. Write to us — we will help.