stpihkal icon indicating copy to clipboard operation
stpihkal copied to clipboard

Document Pavlok-S Protocol

Open TapGhoul opened this issue 3 years ago • 1 comments

This is for the S series of pavloks (2 and 3). Note: firmware versions 5.4.73 and later (inc. 6.x.x) use the time calculation listed below. Prior versions just use a fixed value of 0xfa/250.

Protocol negotiation

To ensure the correct protocol is used (that is, it's the S series of devices), the app checks the following characteristic contains the phrase "Pavlok-S":

Service UUID: 0000180a-0000-1000-8000-00805f9b34fb (Device Information) Characteristic UUID: 00002a24-0000-1000-8000-00805f9b34fb (Model Number String)

Applicable characteristics

Service UUID: 156e1000-a300-4fea-897b-86f698d74461 Characteristic UUIDs:

  • Vibrate: 00001001-0000-1000-8000-00805f9b34fb
  • Beep: 00001002-0000-1000-8000-00805f9b34fb
  • Zap: 00001003-0000-1000-8000-00805f9b34fb
  • LED: 00001004-0000-1000-8000-00805f9b34fb

This list is non-exhaustive as for what the pavlok 3 exposes, however it is all that is possible to be utilized by the stimuli operations. Other operations relate to the RTC for the alarm, battery level, and other features.

Stimuli packet format

To send a vibration or a beep: RR 0c II TA TO

  • RR: Repeats - calculated as 0x80 + repeats (0x81 for example is 1 repeat, 0x82 is 2, etc)
  • 0c: Constant - unknown purpose, does not seem to make a difference. In app it's hard-coded.
  • II: Intensity - specified as 0-100
  • TA: Time Active/Duration of stimuli - defaults to 0x18 for firmware versions 5.4.73 and later, and 0xfa for prior versions
  • TO: Time Off/Duration between repeats - defaults to 0x18 for firmware versions 5.4.73 and later, and 0xfa for prior versions

To send a zap: RR II

  • RR: Repeats - calculated as 0x80 + repeats (0x81 for example is 1 repeat, 0x82 is 2, etc)
  • II: Intensity - specified as 0-100 Timing is not configurable for zaps.

LED protocol unknown, however it takes 4 bytes and seems to run a pattern - none of which are used or detailed in-app. Incorrect/invalid patterns seem to just no-op.

Time calculation

Calculation for time, for firmware versions 5.4.73 and later:

public static int timeCodeForPavlok2(long timeCode) {
  if (timeCode > 10000L) {
    return 62;
  } else if (timeCode >= 3000L) {
    return (int)((timeCode - 3000L) / 500L) | 48;
  } else if (timeCode >= 1000L) {
    return (int)((timeCode - 1000L) / 100L) | 32;
  } else {
    return timeCode >= 200L ? (int)((timeCode - 200L) / 50L) | 16 : (int)(timeCode / 10L) | 0;
  }
}

Default value fed in is 0x280L/640L, which results in 0x18/24 The app hard-codes this value, however, it can be freely varied and will work accordingly.

Sample messages

  • Vibrate at 30% intensity 1 time for default duration: write 0x810c1e1818 to 00001001-0000-1000-8000-00805f9b34fb
  • Zap at 50% intensity twice: write 0x8232 to 00001003-0000-1000-8000-00805f9b34fb

TapGhoul avatar Aug 17 '21 17:08 TapGhoul

So my own reverse engineering attempt isn't lost to the void. Maybe it'll help someone. Did this months ago, but never ended up writing anything fit for public consumption, these are some resulting notes.

If someone knows how to enable streaming of the motion sensor, I would be very interested to know how.


BLE scan with commentary:

attr handle: 0x0001, end grp handle: 0x0009 uuid: 00001800-0000-1000-8000-00805f9b34fb (Unknown)
    handle: 0x0002, char properties: 0x02 (0b000010), char value handle: 0x0003, uuid: 00002a00-0000-1000-8000-00805f9b34fb (Device name, i.e. "Pavlok-3-F282")
        handle: 0x0003, uuid: 00002a00-0000-1000-8000-00805f9b34fb
    handle: 0x0004, char properties: 0x02 (0b000010), char value handle: 0x0005, uuid: 00002a01-0000-1000-8000-00805f9b34fb
        handle: 0x0005, uuid: 00002a01-0000-1000-8000-00805f9b34fb
    handle: 0x0006, char properties: 0x02 (0b000010), char value handle: 0x0007, uuid: 00002a04-0000-1000-8000-00805f9b34fb
        handle: 0x0007, uuid: 00002a04-0000-1000-8000-00805f9b34fb
    handle: 0x0008, char properties: 0x02 (0b000010), char value handle: 0x0009, uuid: 00002aa6-0000-1000-8000-00805f9b34fb
        handle: 0x0009, uuid: 00002aa6-0000-1000-8000-00805f9b34fb

attr handle: 0x000a, end grp handle: 0x000d uuid: 00001801-0000-1000-8000-00805f9b34fb (Unknown)
    handle: 0x000b, char properties: 0x20 (0b100000), char value handle: 0x000c, uuid: 00002a05-0000-1000-8000-00805f9b34fb
        handle: 0x000c, uuid: 00002a05-0000-1000-8000-00805f9b34fb
        handle: 0x000d, uuid: 00002902-0000-1000-8000-00805f9b34fb (Notify)

attr handle: 0x000e, end grp handle: 0x0027 uuid: 156e1000-a300-4fea-897b-86f698d74461 (Unknown)
    handle: 0x000f, char properties: 0x0a (0b001010), char value handle: 0x0010, uuid: 00001001-0000-1000-8000-00805f9b34fb (Vibrate)
        handle: 0x0010, uuid: 00001001-0000-1000-8000-00805f9b34fb
        handle: 0x0011, uuid: 00002901-0000-1000-8000-00805f9b34fb ("Vibe")
    handle: 0x0012, char properties: 0x0a (0b001010), char value handle: 0x0013, uuid: 00001002-0000-1000-8000-00805f9b34fb (Beep)
        handle: 0x0013, uuid: 00001002-0000-1000-8000-00805f9b34fb
        handle: 0x0014, uuid: 00002901-0000-1000-8000-00805f9b34fb ("Beep")
    handle: 0x0015, char properties: 0x1a (0b011010), char value handle: 0x0016, uuid: 00001003-0000-1000-8000-00805f9b34fb (Zap)
        handle: 0x0016, uuid: 00001003-0000-1000-8000-00805f9b34fb
        handle: 0x0017, uuid: 00002902-0000-1000-8000-00805f9b34fb (Notify)
        handle: 0x0018, uuid: 00002901-0000-1000-8000-00805f9b34fb ("Zap")
    handle: 0x0019, char properties: 0x0a (0b001010), char value handle: 0x001a, uuid: 00001004-0000-1000-8000-00805f9b34fb (LED)
        handle: 0x001a, uuid: 00001004-0000-1000-8000-00805f9b34fb
        handle: 0x001b, uuid: 00002901-0000-1000-8000-00805f9b34fb ("LED")
    handle: 0x001c, char properties: 0x0a (0b001010), char value handle: 0x001d, uuid: 00001005-0000-1000-8000-00805f9b34fb (Set RTC, really complex looking)
        handle: 0x001d, uuid: 00001005-0000-1000-8000-00805f9b34fb
        handle: 0x001e, uuid: 00002901-0000-1000-8000-00805f9b34fb ("Time")
    handle: 0x001f, char properties: 0x0a (0b001010), char value handle: 0x0020, uuid: 00001006-0000-1000-8000-00805f9b34fb (Hand detection, also double tap?)
        handle: 0x0020, uuid: 00001006-0000-1000-8000-00805f9b34fb
        handle: 0x0021, uuid: 00002901-0000-1000-8000-00805f9b34fb ("HD")
    handle: 0x0022, char properties: 0x0a (0b001010), char value handle: 0x0023, uuid: 00001007-0000-1000-8000-00805f9b34fb (Buttons, pavlok 2?)
        handle: 0x0023, uuid: 00001007-0000-1000-8000-00805f9b34fb
        handle: 0x0024, uuid: 00002901-0000-1000-8000-00805f9b34fb ("Button")
    handle: 0x0025, char properties: 0x0a (0b001010), char value handle: 0x0026, uuid: 00001008-0000-1000-8000-00805f9b34fb (Enable Sleep tracking?)
        handle: 0x0026, uuid: 00001008-0000-1000-8000-00805f9b34fb
        handle: 0x0027, uuid: 00002901-0000-1000-8000-00805f9b34fb ("DAQ")

attr handle: 0x0028, end grp handle: 0x0050 uuid: 156e2000-a300-4fea-897b-86f698d74461 (Unknown)
    handle: 0x0029, char properties: 0x12 (0b010010), char value handle: 0x002a, uuid: 00002001-0000-1000-8000-00805f9b34fb
        handle: 0x002a, uuid: 00002001-0000-1000-8000-00805f9b34fb
        handle: 0x002b, uuid: 00002902-0000-1000-8000-00805f9b34fb (Notify)
        handle: 0x002c, uuid: 00002901-0000-1000-8000-00805f9b34fb ("Get Time")
    handle: 0x002d, char properties: 0x18 (0b011000), char value handle: 0x002e, uuid: 00002002-0000-1000-8000-00805f9b34fb (Used for stopwatch?)
        handle: 0x002e, uuid: 00002002-0000-1000-8000-00805f9b34fb
        handle: 0x002f, uuid: 00002902-0000-1000-8000-00805f9b34fb (Notify)
        handle: 0x0030, uuid: 00002901-0000-1000-8000-00805f9b34fb ("Events")
    handle: 0x0031, char properties: 0x1a (0b011010), char value handle: 0x0032, uuid: 00002003-0000-1000-8000-00805f9b34fb (Timer?)
        handle: 0x0032, uuid: 00002003-0000-1000-8000-00805f9b34fb
        handle: 0x0033, uuid: 00002902-0000-1000-8000-00805f9b34fb (Notify)
        handle: 0x0034, uuid: 00002901-0000-1000-8000-00805f9b34fb ("Events")
    handle: 0x0035, char properties: 0x12 (0b010010), char value handle: 0x0036, uuid: 00002004-0000-1000-8000-00805f9b34fb (Any button press, no idea how to reset the count)
        handle: 0x0036, uuid: 00002004-0000-1000-8000-00805f9b34fb (int)
        handle: 0x0037, uuid: 00002902-0000-1000-8000-00805f9b34fb (Notify)
        handle: 0x0038, uuid: 00002901-0000-1000-8000-00805f9b34fb ("Button Count")
    handle: 0x0039, char properties: 0x12 (0b010010), char value handle: 0x003a, uuid: 00002005-0000-1000-8000-00805f9b34fb
        handle: 0x003a, uuid: 00002005-0000-1000-8000-00805f9b34fb
        handle: 0x003b, uuid: 00002902-0000-1000-8000-00805f9b34fb (Notify)
        handle: 0x003c, uuid: 00002901-0000-1000-8000-00805f9b34fb ("Zap Count")
    handle: 0x003d, char properties: 0x12 (0b010010), char value handle: 0x003e, uuid: 00002006-0000-1000-8000-00805f9b34fb
        handle: 0x003e, uuid: 00002006-0000-1000-8000-00805f9b34fb
        handle: 0x003f, uuid: 00002902-0000-1000-8000-00805f9b34fb (Notify)
        handle: 0x0040, uuid: 00002901-0000-1000-8000-00805f9b34fb ("Beep Count")
    handle: 0x0041, char properties: 0x12 (0b010010), char value handle: 0x0042, uuid: 00002007-0000-1000-8000-00805f9b34fb
        handle: 0x0042, uuid: 00002007-0000-1000-8000-00805f9b34fb
        handle: 0x0043, uuid: 00002902-0000-1000-8000-00805f9b34fb (Notify)
        handle: 0x0044, uuid: 00002901-0000-1000-8000-00805f9b34fb ("Vibe Count")
    handle: 0x0045, char properties: 0x12 (0b010010), char value handle: 0x0046, uuid: 00002008-0000-1000-8000-00805f9b34fb
        handle: 0x0046, uuid: 00002008-0000-1000-8000-00805f9b34fb
        handle: 0x0047, uuid: 00002902-0000-1000-8000-00805f9b34fb (Notify)
        handle: 0x0048, uuid: 00002901-0000-1000-8000-00805f9b34fb ("LED Count")
    handle: 0x0049, char properties: 0x18 (0b011000), char value handle: 0x004a, uuid: 00002009-0000-1000-8000-00805f9b34fb (Sleep tracking data? Also steps?)
        handle: 0x004a, uuid: 00002009-0000-1000-8000-00805f9b34fb
        handle: 0x004b, uuid: 00002902-0000-1000-8000-00805f9b34fb (Notify)
        handle: 0x004c, uuid: 00002901-0000-1000-8000-00805f9b34fb ("Files")
    handle: 0x004d, char properties: 0x12 (0b010010), char value handle: 0x004e, uuid: 0000200a-0000-1000-8000-00805f9b34fb
        handle: 0x004e, uuid: 0000200a-0000-1000-8000-00805f9b34fb
        handle: 0x004f, uuid: 00002902-0000-1000-8000-00805f9b34fb (Notify)
        handle: 0x0050, uuid: 00002901-0000-1000-8000-00805f9b34fb ("Alarm Time")

attr handle: 0x0051, end grp handle: 0x0057 uuid: 156e4000-a300-4fea-897b-86f698d74461 (Unknown)
    handle: 0x0052, char properties: 0x12 (0b010010), char value handle: 0x0053, uuid: 00004001-0000-1000-8000-00805f9b34fb (Training data, maybe used for internal testing?)
        handle: 0x0053, uuid: 00004001-0000-1000-8000-00805f9b34fb
        handle: 0x0054, uuid: 00002902-0000-1000-8000-00805f9b34fb (Notify)
    handle: 0x0055, char properties: 0x1a (0b011010), char value handle: 0x0056, uuid: 00004002-0000-1000-8000-00805f9b34fb (Training data control byte)
        handle: 0x0056, uuid: 00004002-0000-1000-8000-00805f9b34fb
        handle: 0x0057, uuid: 00002902-0000-1000-8000-00805f9b34fb (Notify)

attr handle: 0x0058, end grp handle: 0x0064 uuid: 156e5000-a300-4fea-897b-86f698d74461 (Unknown)
    handle: 0x0059, char properties: 0x1a (0b011010), char value handle: 0x005a, uuid: 00005001-0000-1000-8000-00805f9b34fb (Application control?)
        handle: 0x005a, uuid: 00005001-0000-1000-8000-00805f9b34fb
        handle: 0x005b, uuid: 00002902-0000-1000-8000-00805f9b34fb (Notify)
        handle: 0x005c, uuid: 00002901-0000-1000-8000-00805f9b34fb ("App Control")
    handle: 0x005d, char properties: 0x1e (0b011110), char value handle: 0x005e, uuid: 00005002-0000-1000-8000-00805f9b34fb (Application download?)
        handle: 0x005e, uuid: 00005002-0000-1000-8000-00805f9b34fb
        handle: 0x005f, uuid: 00002902-0000-1000-8000-00805f9b34fb (Notify)
        handle: 0x0060, uuid: 00002901-0000-1000-8000-00805f9b34fb ("App Write")
    handle: 0x0061, char properties: 0x12 (0b010010), char value handle: 0x0062, uuid: 00005003-0000-1000-8000-00805f9b34fb (Alarm info?)
        handle: 0x0062, uuid: 00005003-0000-1000-8000-00805f9b34fb
        handle: 0x0063, uuid: 00002902-0000-1000-8000-00805f9b34fb (Notify)
        handle: 0x0064, uuid: 00002901-0000-1000-8000-00805f9b34fb ("Alarm Ntfy")

attr handle: 0x0065, end grp handle: 0x0068 uuid: 156e6000-a300-4fea-897b-86f698d74461 (OTA for PAVLOK2?)
    handle: 0x0066, char properties: 0x1a (0b011010), char value handle: 0x0067, uuid: 00006002-0000-1000-8000-00805f9b34fb
        handle: 0x0067, uuid: 00006002-0000-1000-8000-00805f9b34fb
        handle: 0x0068, uuid: 00002902-0000-1000-8000-00805f9b34fb (Notify)

attr handle: 0x0069, end grp handle: 0x006c uuid: 0000180f-0000-1000-8000-00805f9b34fb (Battery Service)
    handle: 0x006a, char properties: 0x12 (0b010010), char value handle: 0x006b, uuid: 00002a19-0000-1000-8000-00805f9b34fb (Battery Level, int)
        handle: 0x006b, uuid: 00002a19-0000-1000-8000-00805f9b34fb (int)
        handle: 0x006c, uuid: 00002902-0000-1000-8000-00805f9b34fb (Notify)

attr handle: 0x006d, end grp handle: 0x0079 uuid: 0000180a-0000-1000-8000-00805f9b34fb (Device Information Service)
    handle: 0x006e, char properties: 0x02 (0b000010), char value handle: 0x006f, uuid: 00002a29-0000-1000-8000-00805f9b34fb (Manufacturer Name, string, i.e. "Behavioral Technolo")
        handle: 0x006f, uuid: 00002a29-0000-1000-8000-00805f9b34fb
    handle: 0x0070, char properties: 0x02 (0b000010), char value handle: 0x0071, uuid: 00002a24-0000-1000-8000-00805f9b34fb (Model Number, string, i.e "Pavlok-S")
        handle: 0x0071, uuid: 00002a24-0000-1000-8000-00805f9b34fb
    handle: 0x0072, char properties: 0x02 (0b000010), char value handle: 0x0073, uuid: 00002a25-0000-1000-8000-00805f9b34fb (Serial Number, string, i.e. "FD0000AEF000")
        handle: 0x0073, uuid: 00002a25-0000-1000-8000-00805f9b34fb
    handle: 0x0074, char properties: 0x02 (0b000010), char value handle: 0x0075, uuid: 00002a27-0000-1000-8000-00805f9b34fb (Hardware version, string, i.e. "6.0.0")
        handle: 0x0075, uuid: 00002a27-0000-1000-8000-00805f9b34fb
    handle: 0x0076, char properties: 0x02 (0b000010), char value handle: 0x0077, uuid: 00002a26-0000-1000-8000-00805f9b34fb (Firmware version, string i.e. "6.4.0")
        handle: 0x0077, uuid: 00002a26-0000-1000-8000-00805f9b34fb
    handle: 0x0078, char properties: 0x02 (0b000010), char value handle: 0x0079, uuid: 00002a28-0000-1000-8000-00805f9b34fb (Unknown, maybe string?, i.e. "+0")
        handle: 0x0079, uuid: 00002a28-0000-1000-8000-00805f9b34fb

attr handle: 0x007a, end grp handle: 0x008d uuid: 156e0000-a300-4fea-897b-86f698d74461 (Placeholder for device type?)
    handle: 0x007b, char properties: 0x12 (0b010010), char value handle: 0x007c, uuid: 00000001-0000-1000-8000-00805f9b34fb
        handle: 0x007c, uuid: 00000001-0000-1000-8000-00805f9b34fb
        handle: 0x007d, uuid: 00002902-0000-1000-8000-00805f9b34fb (Notify)
    handle: 0x007e, char properties: 0x02 (0b000010), char value handle: 0x007f, uuid: 00000002-0000-1000-8000-00805f9b34fb
        handle: 0x007f, uuid: 00000002-0000-1000-8000-00805f9b34fb
    handle: 0x0080, char properties: 0x02 (0b000010), char value handle: 0x0081, uuid: 00000003-0000-1000-8000-00805f9b34fb
        handle: 0x0081, uuid: 00000003-0000-1000-8000-00805f9b34fb
    handle: 0x0082, char properties: 0x02 (0b000010), char value handle: 0x0083, uuid: 00000004-0000-1000-8000-00805f9b34fb
        handle: 0x0083, uuid: 00000004-0000-1000-8000-00805f9b34fb
    handle: 0x0084, char properties: 0x02 (0b000010), char value handle: 0x0085, uuid: 00000005-0000-1000-8000-00805f9b34fb
        handle: 0x0085, uuid: 00000005-0000-1000-8000-00805f9b34fb
    handle: 0x0086, char properties: 0x02 (0b000010), char value handle: 0x0087, uuid: 00000006-0000-1000-8000-00805f9b34fb
        handle: 0x0087, uuid: 00000006-0000-1000-8000-00805f9b34fb
    handle: 0x0088, char properties: 0x18 (0b011000), char value handle: 0x0089, uuid: 00000007-0000-1000-8000-00805f9b34fb
        handle: 0x0089, uuid: 00000007-0000-1000-8000-00805f9b34fb
        handle: 0x008a, uuid: 00002902-0000-1000-8000-00805f9b34fb (Notify)
    handle: 0x008b, char properties: 0x18 (0b011000), char value handle: 0x008c, uuid: 00000008-0000-1000-8000-00805f9b34fb (Diagnostic command)
        handle: 0x008c, uuid: 00000008-0000-1000-8000-00805f9b34fb (Hard reset [1, 90, -16], enable sleep [2,1], disable sleep [2,0])
        handle: 0x008d, uuid: 00002902-0000-1000-8000-00805f9b34fb (Notify)

attr handle: 0x008e, end grp handle: 0xffff uuid: 156e7000-a300-4fea-897b-86f698d74461 (Unknown)
    handle: 0x008f, char properties: 0x1e (0b011110), char value handle: 0x0090, uuid: 00007001-0000-1000-8000-00805f9b34fb (Update buttons, pavlok 3?)
        handle: 0x0090, uuid: 00007001-0000-1000-8000-00805f9b34fb
        handle: 0x0091, uuid: 00002902-0000-1000-8000-00805f9b34fb (Notify)
    handle: 0x0092, char properties: 0x0e (0b001110), char value handle: 0x0093, uuid: 00007999-0000-1000-8000-00805f9b34fb
        handle: 0x0093, uuid: 00007999-0000-1000-8000-00805f9b34fb

Training data, appears to work as a motion/position sensor, but I can't find a way to enable the notification. Guessing this is for dev work? Characteristic: 00004001-0000-1000-8000-00805f9b34fb

int x = ((data[0] & 255) << 8) | (data[1] & 255);
int y = (data[3] & 255) | ((data[2] & 255) << 8);
int z = (data[5] & 255) | ((data[4] & 255) << 8);

How to enable?


Update buttons (only for pavlok 3?) 00007001-0000-1000-8000-00805f9b34fb

0 2 (hard coded)
1 1/2/3 (top/middle/bottom)
2 2/1/3 (beep/vibrate/zap)

if(zap) {
    3 (number + 64) stimulusCountRemote?
    4 (percent 1-100)
} else {
    3 (number + 64) stimulusCountRemote?
    4 12 (hard coded)
    5 (percent 1-100)
    6 time code (time active)
    7 time code (time sleeping)
}

Almost appears to match (first byte is double for button presses) the data packet for sending stimuli https://github.com/buttplugio/stpihkal/issues/137

Silvenga avatar Aug 13 '22 20:08 Silvenga