BLE Protocol Analysis#
This page documents the BLE (Bluetooth Low Energy) protocol used by SkyRC MC3000 battery chargers.
It is based on analyzing sniffed Bluetooth traffic and decompilation of the official SkyRC MC3000 Android app.
Device Identification#
Local Name#
According to the Android app, the device announces itself using one of the following names:
SimpleBLEPeripheralChargerHitecCharger
My device with hardware version 2.2 and firmware version 1.15 uses the name Charger.
MAC Address#
My device uses a MAC address starting with a Texas Instruments OUI (d8:a9:8b:xx:xx:xx).
Other hardware revisions might use different chipset manufacturers.
Service Description#
The device offers a BLE service with the 16-bit UUID 0xffe0 (corresponding 128-bit UUID: 0000ffe0-0000-1000-8000-00805f9b34fb). The 16-bit UUID is in the reserved range, but has not been officially registered with the Bluetooth SIG.
The service contains a single characteristic with 16-bit UUID 0xffe1 (128-bit UUID: 0000ffe1-0000-1000-8000-00805f9b34fb).
This characteristic is used to communicate with the device by writing correctly formatted commands to it. The device will respond by sending a value change notification from the characteristic with the results of the command. It is therefore important to enable notifications for this characteristic after connecting to the device.
The device will never send notifications on its own - all data must be polled from the device!
Protocol#
General Packet Layout#
All packets follow the same layout:
Byte Index |
Description |
|---|---|
0 |
Packet start byte, always 0x0F |
1 |
Command |
2-19 |
Payload |
20
|
Checksum
Sum of previous bytes (modulo 256)
|
Get Version Info#
Example packets#
> 0F-57-00-BE-56-7B-8B-A9-D8-00-00-00-00-00-00-00-00-00-00-01 getVerInfo()
< 0F-57-00-31-30-30-30-38-33-01-00-00-00-00-01-0F-16-00-AD-E7
> 0F-57-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-66 getVerInfo()
< 0F-57-00-31-30-30-30-38-33-01-00-00-00-00-01-0F-16-00-AD-B2
Request#
Byte Index |
Example packet (hex) |
Description |
|---|---|---|
0 |
|
Packet start byte, always 0x0F |
1 |
|
Command (0x57 = 87) |
2 |
|
Empty |
3-8 |
|
MAC address of device. Can be left empty. |
9-19 |
|
Empty |
20 |
|
Checksum (sum of previous bytes) |
Response#
Note
Version response packets seem to have no valid checksum. This might be due to a firmware bug.
Byte Index |
Example packet (hex) |
Description |
|---|---|---|
0 |
|
Packet start byte, always 0x0F |
1 |
|
Command (0x57 = 87) |
2-13 |
|
Unknown |
14-15
|
01-0F |
Firmware version
0x01 = 1, 0x0F = 15 –> “1.15”
|
16
|
16 |
Hardware version
0x16 = 22 –> “2.2”
|
17-18 |
|
Unknown |
20 |
|
Invalid Checksum? |
Get Basic Data#
Example packets#
> 0F-61-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-70 getBasicData()
< 0F-61-00-00-01-01-00-2A-F8-00-00-00-00-00-00-00-00-00-00-94
Request#
Byte Index |
Example packet (hex) |
Description |
|---|---|---|
0 |
|
Packet start byte, always 0x0F |
1 |
|
Command (0x61 = 97) |
2-19 |
|
Empty |
20 |
|
Checksum (sum of previous bytes) |
Response#
Byte Index |
Example packet (hex) |
Description |
|---|---|---|
0 |
|
Packet start byte, always 0x0F |
1 |
|
Command (0x61 = 97) |
2
|
00 |
Temperature unit
0 = Celsius
1 = Fahrenheit
|
3
|
00 |
System beep
0 = Off
1 = On
|
4
|
01 |
Display
0 = Off
1 = Auto
2 = 1 minute
3 = 3 minutes
4 = 5 minutes
5 = Always on
|
5
|
01 |
Screensaver
0 = Off
1 = On
|
6
|
00 |
Cooling fan
0 = Auto
1 = Off
2 = On
3 = 20 °C / 68 °F
4 = 25 °C / 77 °F
5 = 30 °C / 86 °F
6 = 35 °C / 95 °F
7 = 40 °C / 104 °F
8 = 45 °C / 113 °F
9 = 50 °C / 122 °F
|
7-8
|
2A-F8 |
Input voltage (mV)
0x2AF8 = 11000 mV = 11.000 V
|
9-19 |
|
Empty |
20 |
|
Checksum (sum of previous bytes) |
Get Channel Data#
Example packets#
> 0F-55-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-64 getChannel(0)
< 0F-55-00-00-00-00-04-14-56-10-51-00-00-04-F9-1B-00-1D-70-D8
> 0F-55-01-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-65 getChannel(1)
< 0F-55-01-00-00-00-04-09-86-10-4D-00-00-02-95-1B-00-21-00-28
> 0F-55-02-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-66 getChannel(2)
< 0F-55-02-00-00-00-04-0B-5A-10-47-00-00-02-8D-1B-00-7D-00-4D
> 0F-55-03-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-67 getChannel(3)
< 0F-55-03-00-00-00-00-00-00-00-00-00-00-00-00-1B-00-00-00-82
Request#
Byte Index |
Example packet (hex) |
Description |
|---|---|---|
0 |
|
Packet start byte, always 0x0F |
1 |
|
Command (0x55 = 85) |
2 |
|
Channel (between 0 and 3) |
3-19 |
|
Empty |
20 |
|
Checksum (sum of previous bytes) |
Response#
Byte Index |
Example packet (hex) |
Description |
|---|---|---|
0 |
|
Packet start byte, always 0x0F |
1 |
|
Command (0x55 = 85) |
2 |
|
Channel (between 0 and 3) |
3
|
00 |
Battery type
0 = LiIon
1 = LiFe
2 = LiIon 4.35V
3 = NiMH
4 = NiCd
5 = NiZn
6 = Eneloop
7 = RAM
8 = LTO
|
4
|
00 |
Mode
0 = Charge
1 = Refresh
2 = Storage (for LiIon/LiFe/LiIo4_35) or Break-in
3 = Discharge
4 = Cycle
|
5 |
|
Cycle count |
6
|
04 |
Status
0 = Stand-by
1 = Charge
2 = Discharge
3 = Pause
4 = Done (completed)
128 = Input voltage too low
129 = Input voltage too high
130 = MCP3424-1 Err
131 = MCP3424-2 Err
132 = Connection break
133 = Check Voltage
134 = Capacity protection
135 = Time protection
136 = Temp. is too high!
137 = Battery’s temp is too high!
138 = Battery short circuit
139 = Reverse polarity
|
7-8
|
14-56 |
Time (s)
0x1456 = 5206 s = 01:26:46
|
9-10
|
10-51 |
Voltage (mV)
0x1051 = 4177 mV = 4.177 V
|
11-12
|
00-00 |
Current (mA)
0x0000 = 0 mA = 0.000 A
|
13-14
|
04-F9 |
Capacity (mAh)
0x04F9 = 1273 mAh
|
15
|
1B |
Temperature (°C)
0x1B = 27 °C
|
16-17
|
00-1D |
Internal resistance (mΩ)
0x001D = 29 mΩ
|
18
|
70 |
LEDs (Bitmask of all channels)
0x70 = Green, Green, Green, Off
Bitmask:
0x01 = Channel 1 Red
0x02 = Channel 2 Red
0x04 = Channel 3 Red
0x08 = Channel 4 Red
0x10 = Channel 1 Green
0x20 = Channel 2 Green
0x40 = Channel 3 Green
0x80 = Channel 4 Green
|
20 |
|
Checksum (sum of previous bytes) |
Get Voltage Curve#
Example packets#
> 0F-56-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-65 getVoltageCurve(0)
< 0F-56-00-00-20-0F-4E-0F-81-0F-8A-0F-90-0F-95-0F-9B-0F-A0-0F
< A6-0F-AB-0F-AF-0F-B4-0F-B9-0F-BF-0F-C4-0F-C9-0F-CE-0F-D2-0F
< D8-0F-DD-0F-E2-0F-E8-0F-ED-0F-F2-0F-F7-0F-FD-10-02-10-07-10
< 0B-10-10-10-15-10-18-10-1D-10-20-10-25-10-28-10-2D-10-30-10
< 35-10-39-10-3D-10-41-10-46-10-4B-10-50-10-56-10-5C-10-62-10
< 68-10-68-10-68-10-68-10-68-10-68-10-68-10-68-10-68-10-68-10
< 68-10-68-10-68-10-68-10-68-10-68-10-68-10-68-10-68-10-68-10
< 68-10-68-10-68-10-68-10-68-10-68-10-68-10-68-10-68-00-00-00
< 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
< 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
< 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
< 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
< 00-00-00-00-00-71
Request#
Byte Index |
Example packet (hex) |
Description |
|---|---|---|
0 |
|
Packet start byte, always 0x0F |
1 |
|
Command (0x56 = 86) |
2 |
|
Channel (between 0 and 3) |
3-19 |
|
Empty |
20 |
|
Checksum (sum of previous bytes) |
Response#
Note
This is the only known command with a multi-packet response messages. The response will always be 246 bytes long.
Byte Index |
Example packet (hex) |
Description |
|---|---|---|
0 |
|
Packet start byte, always 0x0F |
1 |
|
Command (0x56 = 86) |
2 |
|
Channel (between 0 and 3) |
3-4 |
|
Time? |
5-244
|
10-5C-10-62-10-68… |
120 measurements (mV)
0x105C = 4188 mV = 4.188 V
0x1062 = 4194 mV = 4.194 V
0x1068 = 4200 mV = 4.200 V
|
245 |
|
Checksum (sum of previous bytes) |
Start Charging#
Example packets#
> 0F-05-01-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-15 startCharge(0)
< 0F-05-01-F0-FF-FF-00-00-00-00-00-00-00-00-00-00-00-00-00-03
> 0F-05-02-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-16 startCharge(1)
< 0F-05-02-F0-FF-FF-00-00-00-00-00-00-00-00-00-00-00-00-00-04
> 0F-05-04-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-18 startCharge(2)
< 0F-05-04-F0-FF-FF-00-00-00-00-00-00-00-00-00-00-00-00-00-06
> 0F-05-08-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-1C startCharge(3)
< 0F-05-08-F0-FF-FF-00-00-00-00-00-00-00-00-00-00-00-00-00-0A
Request#
Byte Index |
Example packet (hex) |
Description |
|---|---|---|
0 |
|
Packet start byte, always 0x0F |
1 |
|
Command (0x05 = 5) |
2 |
|
Channels (4 bits, one per channel) |
3-19 |
|
Empty |
20 |
|
Checksum (sum of previous bytes) |
Response#
Byte Index |
Example packet (hex) |
Description |
|---|---|---|
0 |
|
Packet start byte, always 0x0F |
1 |
|
Command (0x05 = 5) |
2 |
|
Channels (4 bits, one per channel) |
3-5 |
|
Unknown |
6-19 |
|
Empty |
20 |
|
Checksum (sum of previous bytes) |
Stop Charging#
Example packets#
> 0F-FE-01-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-0E stopCharge(0)
< 0F-FE-01-F0-FF-FF-00-00-00-00-00-00-00-00-00-00-00-00-00-FC
> 0F-FE-02-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-0F stopCharge(1)
< 0F-FE-02-F0-FF-FF-00-00-00-00-00-00-00-00-00-00-00-00-00-FD
> 0F-FE-04-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-11 stopCharge(2)
< 0F-FE-04-F0-FF-FF-00-00-00-00-00-00-00-00-00-00-00-00-00-FF
> 0F-FE-08-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-15 stopCharge(3)
< 0F-FE-08-F0-FF-FF-00-00-00-00-00-00-00-00-00-00-00-00-00-03
Request#
Byte Index |
Example packet (hex) |
Description |
|---|---|---|
0 |
|
Packet start byte, always 0x0F |
1 |
|
Command (0xFE = 254) |
2 |
|
Channels (4 bits, one per channel) |
3-19 |
|
Empty |
20 |
|
Checksum (sum of previous bytes) |
Response#
Byte Index |
Example packet (hex) |
Description |
|---|---|---|
0 |
|
Packet start byte, always 0x0F |
1 |
|
Command (0x05 = 5) |
2 |
|
Channels (4 bits, one per channel) |
3-5 |
|
Unknown |
6-19 |
|
Empty |
20 |
|
Checksum (sum of previous bytes) |