Recoil:Bluetooth Protocol Details
Overview
Using nRF Connect[1], the tagger tells us that it supports 4 services. 3 of these services can basically be ignored. The UUIDs of the 3 that can be ignored are:
- 0x1800 for Generic Access - contains device name and connection params
- 0x1801 for Generic Attribute - is empty
- 0x180A for Device Information - tells us that SkyRocketToys made it
This leaves us with a final unknown service with a UUID of e6f59d10-8230-4a5c-b22f-c062b1d329e3
This has 4 "Unknown Characteristics"
e6f59d11-8230-4a5c-b22f-c062b1d329e3, properties notify, read, handle 0d
This ID characteristic contains 20 bytes. The first 2 bytes are always 32 E0 which is the firmware version. The next 8 bytes contain the device's serial number in somewhat reversed order. The 11th byte will 01 for the SR-12 Rogue and 02 for the RK-45 Spitfire. The rest of the bytes are 00 00 00 C7 A2 31 1E 00 20.
Client Characteristic Configuration UUID 0x2902, read only, value of notifications and indications disabled, handle 0e
Characteristic User Description UUID 0x2901, read and write, value of ID, handle 0f
e6f59d12-8230-4a5c-b22f-c062b1d329e3, properties notify, handle 11
Client Characteristic Configuration UUID 0x2902, read only, value of notifications and indications disabled, handle 12
Characteristic User Description UUID 0x2901, read and write, value of Telemetry, handle 13
setting a continuous read on this one monitors the buttons on the tagger, 1 for trigger, 2 for reload, 4 for back button
e6f59d13-8230-4a5c-b22f-c062b1d329e3, properties read, write, handle 15
Characteristic User Description UUID 0x2901, read and write, value of Command, handle 16
Contains a very long string of data, handle 17
e6f59d14-8230-4a5c-b22f-c062b1d329e3, properties read, write, handle 18
Characteristic User Description UUID 0x2901, read and write, value of Config, handle 19
Contains a very long string of data, handle 1a
Telemetry
We need to enable continuous notification packets from the tagger that the phone is supposed to monitor from the Telemetry service. They are 20 bytes each
00 | the first nibble is the value of the last accepted command ID, the second nibble is a continuous counter that ranges from 0 to F |
---|---|
01 | player ID, 01, 02, 03, etc. 00 when not set |
02 | first byte is the power button 0 unpressed and 1 for pressed, second is button presses, 01 for trigger, 02 for reload, 04 for back button, add them together for pressing multiple buttons, so 07 means all three buttons are being pressed |
03 | counters for the number of times a button has been pressed, the first byte is reload presses, second byte is trigger presses |
04 | again a button counter, first byte is unused, second byte is for back button presses |
05 | first byte unused, second byte is a count of power button presses |
06 | Low order byte for battery level |
07 | High order byte for battery level - RK-45, 10 is brand new alkalines, 0E for fully charged rechargables with 0D showing up pretty quick. The SR-12 uses 6 AA instead of 4 and the battery level value will be 50% higher than the RK-45 |
08 | hit by player data set 1 field 1, the 2 most significant bits are the least 2 significant bits of the weapon profile ID (combine with bits from byte 9), the middle 3 bits indicate charge level if a charge-based weapon profile is being used for a total of 8 possible charge levels (note, if the weapon config is not set to use a charge firing mode, all 3 of these bits are set to 1 and there is no way to tell if you are being hit with charge level 8 or with a normal shot from a non-charge firing mode), the 3 least significant bits are a shot ID that can be used to eliminate duplicate hit reports |
09 | hit by player data set 1 field 2, the 6 most significant bits are the player ID, so player 1 shows up as 0x04 and player 2 as 0x08. The 2 least significant bits are the 2 most significant bits of the weapon profile ID being used (combine with bits from byte 8) |
10 | nibble 1 - bitfield for which sensors were hit, 0b1000 = clip on sensor, 0b0100 = front sensor, 0b0010 = left sensor, 0b0001 = right sensor / nibble 2 - hit counter(same counter as byte 13) |
11 | hit by player data set 2 field 1, the 2 most significant bits are the least 2 significant bits of the weapon profile ID (combine with bits from byte 12), the middle 3 bits indicate charge level if a charge-based weapon profile is being used for a total of 8 possible charge levels (note, if the weapon config is not set to use a charge firing mode, all 3 of these bits are set to 1 and there is no way to tell if you are being hit with charge level 8 or with a normal shot from a non-charge firing mode), the 3 least significant bits are a shot ID that can be used to eliminate duplicate hit reports |
12 | hit by player data set 2 field 2, the 6 most significant bits are the player ID, so player 1 shows up as 0x04 and player 2 as 0x08. The 2 least significant bits are the 2 most significant bits of the weapon profile ID being used (combine with bits from byte 11) |
13 | nibble 1 - bitfield for which sensors were hit, 0b1000 = clip on sensor, 0b0100 = front sensor, 0b0010 = left sensor, 0b0001 = right sensor / nibble 2 - hit counter(same counter as byte 10) |
14 | how many shots you have left, starts out at 0x1e which would be 30 in decimal and decreases when you pull the trigger |
15 | GunFlags - Bit map:0x01 = Reload mode (clip out, can’t fire) 0x02 = Clip-on IR sensor disconnected |
16 | starts as 02 but changes to 00 after player ID is set |
17 | current weapon profile, usually 00 unless you have changed the weapon profile |
18 | 00 |
19 | 00 |
Sending to Command a packet with 10 00 80 00 PLAYER# then 15 more 00's sets the player ID. This works for initially setting the ID, but does not work consistently afterwards. You can consistently change the player ID by doing a reload procedure.
Config PP 00 09 xx yy ff c8 ff ff 80 01 34 - PP is the weapon profile ID (we normally use 00), xx is the number of shots and if you set yy to 01 for full auto for xx shots or 00 for single shot mode, increasing yy decreases RoF. Setting 03 03 for shots and RoF gives a good 3 shot burst, 03 01 is so fast that you feel 1 recoil for 3 shots
Recoil blasters feature an IR blaster with a lens that is used for long range shots. They also feature a "cone style" IR blaster for close range to make it easier to hit players close by without precise aiming.
Config PP 00 09 FE 01 vv ww FF FF 80 01 34 - PP is the weapon profile ID (we normally use 00), vv is (I believe) the strength used for the long range IR blaster and ww is the strength used for close range.
In outdoor games, FF C8 is used for vv and ww. Indoor games use 19 00 with the 00 to disable the close range cone style blaster completely. Reducing the C8 to 08 seemed to reduce the blast radius of the indoor IR blaster in my very limited testing.
Config
Weapon Config bytes, what we know:
00 | weapon profile ID, we usually use 0x00 |
---|---|
01 | flag byte 1, always 0x00, changing this seems to leave the blaster in single shot only mode |
02 | length, always 0x09, number of bytes in the rest of the config packet |
03 | number of shots to shoot max per trigger pull -- blaster will keep shooting up to this many shots so long as the trigger is held and there are shots remaining in the clip |
04 | rate of fire -- setting 0x00 will leave you in single shot mode, 0x01 is the default in the official app for full auto, 0x03 gives you a good rate of fire for 3 shot burst on the pistol but rifle users may feel a partial 4th recoil per 3 shot burst |
05 | strength of the long distance IR blast, 0xFF for outdoor games and 0x19 is used for indoor games in the official app |
06 | strength of the wide angle IR blast, 0xC8 for outdoor games and 0x00 for indoor |
07 | brightness of the muzzle flash LED, 0x00 turns it off, default is 0xFF for max brightness |
08 | brightness of second, non-existent LED, default is 0xFF |
09 | recoil strength / power, official app uses 0x80. Setting 0x00 seems to cause the blaster to disconnect, lower numbers like 0x20 don't hit very hard, 0xFF hits a little harder and a little faster than 0x80, but not much different than 0x80 |
10 | seems to adjust both the muzzle flash LED and firing mode -- 0x00 turns off the flash, 0x01 turns it on and flashes 3 times slowly after the last shot is fired(square wave), 0x02 and 0x03 make the flash shorter and does not flash 3 times, 0x04 seems to make full auto only shoot 3 shots |
11 | seems to adjust muzzle flash LED and firing mode, official app uses 0x34 -- low numbers like 0x00 and 0x01 seem to cause single shot mode to go full auto, high numbers cause the muzzle led to flash for a longer time after last shot is fired |
Shot Config bytes
00 | flag byte 0, always 0x10 |
---|---|
01 | flag byte 1, always 0x00 |
02 | length, always 0x02, number of bytes in the rest of the config packet |
03 | feedback, controls blaster feedback, bitfield, 0b001 - auto recoil, 0b010 - flash on shoot, 0b100 - flash on hit |
04 | trigger override, 0xFF default, allows you to override current trigger mode, not sure of the use but: plasma = 0x0, single = 0x01, burst = 0x02, full auto = 0xFE, no override = 0xff |
IR Configuration bytes (needs experimentation)
00 | flag byte 0, unknown "tag" |
---|---|
01 | flag byte 1, unknown "tag" |
02 | length, always 0x03, number of bytes in the rest of the config packet |
03 | repeat transmission flag, 0x00 default |
04 | enable sensors, bitfield, first 4 bits control turning on and off sensors, 1 = on, 0 = off |
05 | clip-on interval, unknown, maybe a development flag for how often the blaster should look for clip-on sensor plug/unplug events |
Command
There are 10 commands:
0x000 | does nothing |
---|---|
0x001 | fire blaster |
0x002 | reload blaster (start) |
0x004 | reload blaster (finish) |
0x008 | recoil (makes the blaster recoil without shooting) |
0x010 | flash muzzle LED (muzzle LED blinks without shooting) |
0x020 | turn off blaster |
0x040 | output stats to UART |
0x080 | set player ID |
0x100 | reboot to bootloader |
(to be updated) Commands all follow the same basic structure, the first nibble of the first byte is a counter that needs to be different for every new command or the blaster will reject the command. The first nibble of the first byte of the telemetry data will change to the same value of the last command ID you used when the command is accepted. For example, if you wish to send multiple player ID commands, you have to use a different command ID each time, so you could toggle between 2 command IDs or increment for each command sent. The third byte and fourth bytes are a command from the table above. The third byte is the command most of the time, except for reboot to bootloader where it would be 0x00 and the fourth is 0x10 because of little endian(needs to be tested). The fifth byte is always the player ID(need to test if fire blaster command will accept different player ID) and the sixth byte is additional data, like the magazine size for finishing a reload.
If you send the following command to the command characteristic, the blaster will "reboot" into a bootloader mode that exposes a Secure DFU (Device Firmware Update) service that appears to be a way to update the firmware running on the blaster: 11 00 00 01 00 00 00 FF FF FF FF FF FF 00 00 00 00 00 00 00
While in the bootloader mode, you will lose your existing Bluetooth connection to the device. The blaster will report a Bluetooth device name of SRG1_BL. The power LED will be off and the muzzle LED will be on. Note, the nibble of the first byte of this command may need to be changed / incremented depending on what the last command ID was used. This command should work if it is the first / only command that you send to the blaster after powering it on.
Packet notes
Weapon Profiles
Weapon profiles exist that do different things so long as you don't override the config. Profile 0x00 is single shot mode, 0x01 is a 5 shot burst, 0x02 is full auto, 0x03 through 0x0f are various charge firing modes that allow you to hold the trigger to charge up a shot and only fires on release. The blaster subtracts 4 shots from your ammo per level charged up to 8 levels of charge. If you set a config after changing the profile, the blaster can be set in a different mode from the default for that profile ID (e.g. if you switch to weapon profile 3 which is a charging mode and set full auto config, the blaster will switch to full auto instead of this special charging firing mode). A developer can also use the weapon profile as a way to set more player IDs than the base 64 possible IDs using the regular player ID field.
Reloading
- at the beginning of a reload the official app sends a Command d0 00 04 00 01 and 15 sets of 00 (this does not seem to be required)
- a little later we send Command X0 00 02 00 01 and 15 sets of 00 which changes item 16 from its usual 02 to a 03! and this stops the tagger from shooting, X is the command ID, SimpleCoil uses 0 for the reload start command ID
- finally we send a Command X0 00 04 00 01 PP 1e and 13 sets of 00 and we get 30 bullets and can shoot again and resets the 03 to 02, PP is the weapon profile ID and you can use this command to switch weapon profiles, X is the command ID, SimpleCoil uses F for reload finished commands
(note this was all on player 1 -- the 01 indicates player 1 and needs to be set as appropriate for other players)
Toggling recoil
- Config 10 00 02 02 ff and 15 sets of 00 disables recoil
- Config 10 00 02 03 ff and 15 sets of 00 enables recoil
Other packets that I saw but don't seem to need
- there are various Config packets of 00 00 09 00 and then 16 00's... maybe a reset config?
- Command 50 00 04 00 02 00 1e seems to load 30 bullets and sets player 2, but won't reload 30 bullets
- Somewhere after connecting but before joining a lobby we send a Config 00 00 09 fe 01 ff c8 ff ff 80 01 34 and 8 sets of 00 which enables full auto
- also see Config 00 00 09 fe 01 19 00 ff ff 80 01 34