# Keepsmile KS03~ Protocol This document details the reverse-engineered protocol Keepsmile uses to communicate with LED strip lights. These structures were found by creating a BLE server on an ESP32 using the same "KS03~XXXXXXX" identifier and the same service and write characteristic UUIDs. This setup spoofs the ESP32 into looking like a legitimate device, and thus most packets were logged and documented here. The spoofer source code can be found in this [repository.](https://example.com) **Changelog:** ``` 2024-09-12: Initial release. ``` ## UUIDs Here are the following uuid's related to the device's services and characteristics: **Service 1** - `00001800-0000-1000-8000-00805f9b34fb` - Characteristic 1 - `00002a00-0000-1000-8000-00805f9b34fb` (Read) **Service 2** - `0000afd0-0000-1000-8000-00805f9b34fb` - Characteristic 1 - `0000afd1-0000-1000-8000-00805f9b34fb` (Write) - Characteristic 2 - `0000afd2-0000-1000-8000-00805f9b34fb` (Notify) - Characteristic 3 - `0000afd3-0000-1000-8000-00805f9b34fb` (Read) **Service 2** and **Characteristic 2** is what Keepsmile uses to communicate and send commands to the device. The following packets and their structure can be found below: ## Bluetooth Packets Each packet sent to the device starts with an **identifier** byte, and the identifier byte flipped. For example, if the a packet is sent with an id of 0x5F, the structure would look like the following: `5F [...argument bytes] F5`. Additionally, most packets end with a null byte before the final byte. ### Initial Connection When the app connects to the device, it sends 2 packets: `5F 01 00 F5` The next packet is sent immediately after, and changes slightly each time. Strangely, it does not adhere to the usual structure sent above. `7E 07 83 15 11 15 05 FF EF` (received at _21:17:21.663_) `7E 07 83 15 12 05 05 FF EF` (received at _21:18:05.523_) `7E 07 83 15 12 34 05 FF EF` (received at _21:18:52.425_) `7E 07 83 16 01 06 05 FF EF` (received at _22:01:06.533_) `7E 07 83 17 05 27 05 FF EF` (received at _23:05:39.540_) The structure of these packets are currently unknown, and it is worth noting that sending them is not required. ### On / Off The following packet is used to turn the device on or off: ```c++ struct Operation_t { uint8_t id = 0x5B; uint8_t operation; // On - 0xF0, Off - 0x0F uint8_t unk1 = 0x00; uint8_t id_end = 0xB5; }; ``` ### Custom Color This packet is sent whenever the lights need to change to a custom color. This same structure is also used when the **rythm** feature is used, sent many times. ```c++ struct ColorCustom_t { uint8_t id = 0x5A; uint8_t unk1 = 0x00; uint8_t unk2 = 0x01; uint8_t r; // 0 - 255 uint8_t g; // 0 - 255 uint8_t b; // 0 - 255 uint8_t unk3 = 0; uint8_t brightness; // 0 - 100 uint8_t unk4 = 0x00; uint8_t id_end = 0xA5; }; ``` ### Color Profile This packet is sent when a color profile is set. ```c++ struct ColorProfile_t { uint8_t id = 0x5C; uint8_t unk1 = 0x00; uint8_t profile; // 0x80 - 0x96 uint8_t speed; // 0 - 100 uint8_t brightness; // 0 - 100 uint8_t unk2 = 0x00; uint8_t id_end = 0xC5; }; ``` Here are the **23** available color profiles that range from **0x80 to 0x96**: - Seven color jumping change - RGB jumping change - Pulsating Seven colors - Pulsating RGB - Pulsating red - Pulsating green - Pulsating blue - Pulsating yellow - Pulsating cyan - Pulsating purple - Pulsating white - Pulsating red,green - Pulsating red,blue - Pulsating green,blue - Seven color strobe flash - RGB strobe - Red strobe flash - Green strobe flash - Blue strobe flash - Yellow strobe flash - Cyan strobe flash - Purple strobe flash - White strobe flash ### Rythm Selection ```c++ struct RythmSelection_t { uint8_t id = 0x5A; uint8_t unk1 = 0x0A; uint8_t mic_type; // Phone mic - 0x0F, device mic - 0xF0 uint8_t type; // 1 - 4 uint8_t speed; // 8 - 1 (8 being the slowest) uint8_t unk3 = 0x01; uint8_t id_end = 0xA5; }; ```