Freitag, 19. Dezember 2014

Xiaomi releases MiBand iOS App

While I am working on the open source Android app Xiaomi has released their long awaited iOS app just a few days ago.
Their Android UI has been ported 1:1 to iOS which seems confusing, but works somehow. However the app is Chinese only so you have to guess what button does what - which is why the app has an astonishing rating of 1 out of 5 stars in the app store. UPATE: new version is in English.
And again I am confused why Xiaomi doesn't want to expand to Europe - so many people here want that thing and it is much better than competitive products.
Download: https://itunes.apple.com/de/app/xiao-mi-shou-huan/id938688461?l=en&mt=8






Donnerstag, 4. Dezember 2014

Xiaomi Mi Band BLE Protocol reverse-engineering and API

My Mi-Band is finally here and I totally love it.
Only compatible with Xiaomi Mi3 and Mi4? Lies! Except for unlocking and notifications, every other BLE phone will work with it. Just grab the (translated) app from xda-developers and enjoy. Official App now available for Android and iOS.
To allow third-party developers access to this device I will post details here.


Libraries & Apps

Made by me:
Android: https://github.com/paulgavrikov/xiaomi-miband-android

Cocoa / Swift: https://github.com/paulgavrikov/xiaomi-miband-cocoa

Based on me:

Android by lwis: https://github.com/lwis/miband-notifier
Python by OscarAcena: https://bitbucket.org/OscarAcena/mibanda



Used BLE chip: Dialog DA14580
Default name      MI
Connectable        yes (approx. 30sec timeout)
Does advertise    yes


What features does it have (accessible by BLE):
3 LED (color adjustable), capacitive touch sensor, Vibrator (can be stopped actively), Timer (starts to Vibrate), Battery stats, stores full user profile (gender, age, weight, ...), live step notifications, save step notifications, sleep detection


The device has 3 BLE Services:

After a firmware update Mi Band no longer has user-descriptions for their Chars & Services. Either they don't want us to reverse engineer or they simply forgot it ...
  • Service 1 (0xFEE0) "Mili-Service"
    • 0xFF01 read
      • DEVICE_INFO
    • 0xFF02 read write
      • DEVICE_NAME
    • 0xFF03 read notify
      • NOTIFICATION
    • 0xFF04 read write
      • USER_INFO
    • 0xFF05 write
      • CONTROL_POINT
    • 0xFF06 read notify
      • REALTIME_STEPS
    • 0xFF07 read indicate
      • ACTIVITY_DATA
    • 0xFF08 write without response
      • FIRMWARE_DATA
    • 0xFF09 read write
      • LE_PARAMS
    • 0xFF0A read write
      • DATE_TIME
    • 0xFF0B read write
      • STATISTICS
    • 0xFF0C read notify
      • BATTERY
    • 0xFF0D read write
      • TEST
    • 0xFF0E read notify
      • SENSOR_DATA
    • 0xFF0F read write
      • PAIR
    • Service 2 (0xFEE1)
      • 0xFEDD write
      • 0xFEDE write
      • 0xFEDF read
    • Service 3 (0xFEE7)
      • 0xFEC7 write
      • 0xFEC8 read indicate
      • 0xFEC9 read

    BLE Actions


    The protocol is not up to date, I am no longer updating it.


    Extracted from com.xiaomi.hm.bleservice.profile.MiLiProfile.java


    Pair
    Note: Once the Miband is actively paired with a device, other devices won't discover it

    Write 2 to Characteristic 0xFF0F (PAIR). Maybe you have to confirm by putting your finger on the aluminium part of the Mi Band. 
    Mi Band will respond with 2 on the same characteristic if the pairing was successful.
    Mi Band will respond with 0xfff on the same characteristic if the device is not paired.

    Self Test
    Note: This will remove bonding information on the Mi Band, which might confused iOS (and probably Android, too). So before you connect next time remove your Mi Band via Settings > Bluetooth.

    Write 2 to Characteristic 0xFF0D (TEST). Your Mi Band will do crazy things (LED flashing, vibrate)

    Realtime Step Notification

    Enable Notifications:  Write 3, 1 to Characteristic 0xFF05 (CONTROL_POINT). 
    Disable Notifications: Write 3, 0 to Characteristic 0xFF05 (CONTROL_POINT). 

    I assume that you will be notified from 0xFF03 but I haven't verified yet.

    Sensor Data Notification

    Enable Notifications:  Write 18, 1 to Characteristic 0xFF05 (CONTROL_POINT). 
    Disable Notifications: Write 18, 0 to Characteristic 0xFF05 (CONTROL_POINT). 

    I assume that you will be notified from 0xFF03 but I haven't verified yet.

    Get Battery Info

    Read or let notify from Characteristic 0xFF0C (BATTERY). 
    Interpret the received byte array, skip if received not exactly 10 bytes:

    Battery Info:
    Level in%: byte[0]
    Charges:   0xffff & (0xff & byte[7] | (0xff & byte[8]) << 8)
    Status:    byte[9]
    where 1 = Battery low
          2 = Battery charging
          3 = Battery full (charging)
          4 = Not charging

    Last charged Date Information (Gregorian Calendar):
    Year:        byte[1] + 2000
    Month:       byte[2]
    Day / date:  byte[3]

    Hour (0-24): byte[4]
    Minute:      byte[5]
    Second:      byte[6]

    Example response: 33 0E 09 1B 08 03 2E 06 00 04
    => 51 % charged
    => Not charging
    => Last charged 2014\09\27 08:03:46
    => 6 Cycles (seems like someone charged it before me 5 times ...)



    Get Date Time

    Get Device / Bluetooth Name

    Read from Characteristic 0xFF02 (DEVICE_NAME). The received bytes are to be interpreted as UTF8 String. 

    Get Device Info

    Read from Characteristic 0xFF01 (DEVICE_INFO). Interpret the received byte array.

    UUID: formate byte[0-7] as "%02X%02X%02X%02X%02X%02X%02X%02X"

    You can extract features, appearance (probably the color) and hardwareRevision form UUID.
    There other bytes inside the array are profileVersion and firmwareVersion. Calculation will be posted later.

    Get LE Params

    Read from Characteristic 0xFF09 (LE_PARAMS). Interpret the received byte array, skip if received not exactly 12 bytes:

    connIntMin: 0xffff & (0xff & byte[0] | (0xff & byte[1]) << 8)
    connIntMax: 0xffff & (0xff & byte[2] | (0xff & byte[3]) << 8)
    latency:    0xffff & (0xff & byte[4] | (0xff & byte[5]) << 8)
    timeout:    0xffff & (0xff & byte[6] | (0xff & byte[7]) << 8)
    connInt:    0xffff & (0xff & byte[8] | (0xff & byte[9]) << 8)
    advInt:     0xffff & (0xff & byte[10] | (0xff & byte[11]) << 8)

    How to interpret this raw timing data:

    connIntMin * 1.25  milliseconds
    connIntMax * 1.25  milliseconds
    latency            milliseconds
    timeout    * 10    milliseconds
    connInt    * 1.25  milliseconds
    advInt     * 0.625 milliseconds


    Get Usage

    Get User Info

    Get Realtime Steps

    Read from Characteristic 0xFF06 (REALTIME_STEPS). The 2 received bytes are the steps. Interpret them as integer.

    Example response: 12 16
    => 4630 steps

    Factory Reset
    Note: This will remove bonding information on the Mi Band, which might confused iOS (and probably Android, too). So before you connect next time remove your Mi Band via Settings > Bluetooth.

    Write 9 to Characteristic 0xFF05 (CONTROL_POINT). 

    Reboot

    Write 12 to Characteristic 0xFF05 (CONTROL_POINT). 

    Remind (seems to be Beta testing)

    Remote Disconnect
    Note: This will remove bonding information on the Mi Band, which might confused iOS (and probably Android, too). So before you connect next time remove your Mi Band via Settings > Bluetooth.

    Write 1 to Characteristic 0xFF0D (TEST). 

    Start Vibration

    Write 8, 2 to Characteristic 0xFF05 (CONTROL_POINT). 

    Stop Motor Vibration

    Write 19 to Characteristic 0xFF05 (CONTROL_POINT). 

    Sync

    Write 11 to Characteristic 0xFF05 (CONTROL_POINT). 

    Write MD5 (???)

    Send Firmware

    Send Firmware Info

    Set Color Theme

    Write 14, R, G, B, D to Characteristic 0xFF05 (CONTROL_POINT). Where R, G, B, is a byte representing red, green blue value and D is 0 (don't flash) or 1 (quickly flash Color).

    Default colors from the app:

    blue:     1542 (Note: yes, this is a int)
    green:   0x40500
    red:       0x60102
    orange: 0x60200


    Set Goal (in steps)

    Set Device / Bluetooth Name

    Write an UTF8 String (as byte array) to Characteristic 0xFF02 (DEVICE_NAME).

    Set Realtime Steps

    Set Timer

    Set User Info

    Set Wear Location (Left Hand, Right Hand, Neck)

    Authenticate





    I will update more details and post the protocol soon (step by step).