---
# System prepended metadata

title: Keepsmile KS03~ Protocol

---

# 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;
};
```