stpihkal
stpihkal copied to clipboard
Document Pavlok-S Protocol
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 as0x80
+ 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 to0x18
for firmware versions 5.4.73 and later, and0xfa
for prior versions -
TO
: Time Off/Duration between repeats - defaults to0x18
for firmware versions 5.4.73 and later, and0xfa
for prior versions
To send a zap:
RR II
-
RR
: Repeats - calculated as0x80
+ 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
to00001001-0000-1000-8000-00805f9b34fb
- Zap at 50% intensity twice: write
0x8232
to00001003-0000-1000-8000-00805f9b34fb
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