14 KiB
14 KiB
Bluetooth Low Energy protocol documentation
For every LED Mask that gets controlled by the App called 'Shining Mask'. Google Play, App Store
Characteristics:
- Command Characteristic:
D44BC439-ABFD-45A2-B575-925416129600(Write) - Notification Characteristic:
D44BC439-ABFD-45A2-B575-925416129601(Notify) - Image Upload Characteristic:
D44BC439-ABFD-45A2-B575-92541612960A(Write) - Audio Visualization Characteristic:
D44BC439-ABFD-45A2-B575-92541612960B(Write)
Data is encrypted using AES-128 in ECB mode with a fixed key:
Note that all the data sent to the command characteristic needs to be 16 bytes long (encrypted data), same as all the to-be-encrypted data.
32672f7974ad43451d9c6c894a0e8764
Command Structure for the commands that are sent to the command handle:
- 1 byte, length of the command plus arguments
- 1-5 bytes, hex representation of the ASCII command
- x bytes, arguments of the command
- the rest is just padding up to 16 bytes
Commands:
Utility:
-
LIGHT:- Description: Sets the brightness, lower brightness means less color accuracy in color dependend modes, such as images, and higher brightness over
128means more flickering due to the LEDs not being able to get that bright at the same frequency, probably due to battery limitations. I personally keep it at a max of100 - Hex of the ASCII name:
4c49474854 - arguments:
- 1 byte for the brightness
- Description: Sets the brightness, lower brightness means less color accuracy in color dependend modes, such as images, and higher brightness over
-
IMAG:- Description: Displays the builtin image at the provided id. Everything above
0x69will display out of bounds data, mostly partial frames of the builtin animations. - Hex of the ASCII name:
494d4147 - arguments:
- 1 byte for the builtin image id to be displayed
- Description: Displays the builtin image at the provided id. Everything above
-
ANIM:- Description: Plays the builtin animation at the provided id. Everything above
0x45will display out of bounds data, mostly some random pixels. Strangely it still plays that data as an animation - Hex of the ASCII name:
414e494d - arguments:
- 1 byte for the built-in animation id to be displayed
- Description: Plays the builtin animation at the provided id. Everything above
-
DELE:- Description: Deletes the given DIY images from the mask
- Hex of the ASCII name:
44454c45 - arguments:
- 1 byte for the count of the to be deleted DIY images
- max 10 bytes for the DIY image ids of the images that should get deleted
-
PLAY:- Description: Plays the given DIY images in order
- Hex of the ASCII name:
504C4159 - arguments:
- 1 byte for the count of the to be played DIY images
- max 10 bytes for the DIY image ids of the images that should get played (in order)
-
CHEC:- Description: Command for checking how many DIY images are on the mask
- Hex of the ASCII name:
43484543 - arguments: none, triggers a response on the notify Characteristic, sending back the number of DIY images uploaded in one byte
Text:
-
MODE:- Description: Allows to change the animation used to display the current text
- Hex of the ASCII name:
4d4f4445 - arguments:
- 1 byte for setting the text display mode:
- 0: n/a (all n/a are just reverting to off)
- 1: off
- 2: blink
- 3: scroll right to left
- 4: scroll left to right
- 5 to 255: n/a
- 1 byte for setting the text display mode:
-
SPEED:- Description: Changes the speed of the text displayment modes
- Hex of the ASCII name:
5350454544 - arguments:
- 1 byte for setting the speed of the
MODEeffect
- 1 byte for setting the speed of the
-
M:- Description: Sets the special color/effect for the text
- Hex of the ASCII name:
4d - arguments:
- 1 byte for controlling wether it's enabled
- 1 byte for controlling the mode:
- 0: Random color dots on white background
- 1: Idk, seems like a bit of rainbow on the top and bottom of the text, with red on the left transitioning to purple on the right. A big white part is in the middle
- 2: Fade from Yellow (top) to Blue (bottom)
- 3: fade from Green (sides) to blue (middle) (circle shaped)
- 4: enables the first background image
- 5: enables the second background image
- 6: enables the third background image
- 7: enables the fourth background image
- 8 to 255: just doesn't change it from the previous effect (aka it just stays at the same one)
-
FC:- Description: Sets the text color
- Hex of the ASCII name:
4643 - arguments:
- 1 byte for controlling wether it's enabled
- 3 bytes for controlling the color in RGB format
-
BC:- Description: Sets the background color, can be used to 'disable' the images from the
Mcommand by setting it to black - Hex of the ASCII name:
4243 - arguments:
- 1 byte for controlling wether it's enabled
- 3 bytes for controlling the color in RGB format
- Description: Sets the background color, can be used to 'disable' the images from the
-
Text uploading procedure:
- You will need something that can create a bitmap and, although not required, something that can create a color array for this to work (the text, or part of the text, will just be white if no color data is provided for it. For example if you have a bitmap that is
31pixels wide and color data that has data for only26pixels, the last five pixels will be displayed as white).- I haven't really figured out the correct way of creating a colormap yet.
- The bitmap has to be
16pixels high and could theoretically be a few thousand pixels wide, but I wouldn't recommend doing that as it can cause the mask to become unresponsive and buggy, forcing one to cut the power by removing the battery (for some models, you will have to open the mask to do so).- I would limit the length of the bitmap to about
512to be save but of course making it1024or2048could work, it just poses a risk (I also haven't really tested this so I just assumed512would be good).
- I would limit the length of the bitmap to about
- The color array can be used to give each pixel stripe of the text (so 1 x 16, width x height) a different color.
- You might need to calculate the total bitmap pixel length and generate an array of bytes with the format RGB
0-faccordingly. - The special thing about this is that the color stays fixed to the text and not the background like it's the case with the
Mcommand.
- You might need to calculate the total bitmap pixel length and generate an array of bytes with the format RGB
- Once you have a bitmap, you can use the
DATScommand with the indicator byte set to0x00- the first two bytes after the command being the size of the combined data (so bitmap with the color array appended to the end of it, this structure is also used for the uploaded data)
- the next two bytes being the size of the bitmap alone to initialize a bitmap upload.
- For the data upload, you just have to send the data to the mask like you would do with the image data, including the
DATCPcommand at the end.
- You will need something that can create a bitmap and, although not required, something that can create a color array for this to work (the text, or part of the text, will just be white if no color data is provided for it. For example if you have a bitmap that is
Image:
-
DATS:- Description: Used to tell the mask that an image upload is about to start
- Hex of the ASCII name:
44415453 - arguments:
- 2 bytes for the image size of the following image
- 2 bytes for the image index
- 1 byte for the image toggle (wether to tell that an image is going to be uploaded or a bitmap. Has to be correctly set for the desired mode, otherwise the upload fails)
-
DATCP:- Description: seems to confirm the image upload, sending the current unix timecode with it
- Hex of the ASCII name:
4441544350 - arguments: current unix time code
-
Image uploading process:
- The program sends the
DATScommand and waits for theDATOKanswer from the mask. After that, it starts uploading the image. - The image is broken up into chunks of
98bytes per packet (the image size is just the amount of bytes of the image), each byte being either thered,greenorbluechannel of a pixel.- So for one pixel, three bytes are used.
- The first byte (not counting towards those
98image data bytes) indicates the length of the image bytes in the package, so for the full98bytes of image data it would be0x63, as there are98bytes of image data plus one package counter byte, which starts at0x00and goes up by one each package. - After every successfull packet transfer, the mask respons with REOKOK for that image/packet.
- The last packet can have less than
98bytes, so the data length byte is calculated for the less than98bytes. - After that, the packet gets padded up to the full
100bytes. - Note that the packet does not need encrypting.
- After all packets have been uploaded, the program sends the
DATCPcommand, to wich the mask respons withDATCPOK.
- The program sends the
Audio:
All audio data is sent to the audio visualizer handle, encrypted of course
-
Audio data:
- 1 byte for the counter (it's always
0x0f, as all 15 following bytes are utilized) - 1 byte for the mode (modes are listed below)
- 14 bytes for the visualization. Each nibble (one of the two characters of a byte) of these 14 bytes corresponds to one row of pixels, changing the value of a nibble also changes the size of the pixel row.
0x0means that that row is off and0xfmeans that that row is 100% full or on.
- 1 byte for the counter (it's always
-
Modes:
- 0: vertical bars, color fade from red (middle) over green and blue to purple (left and right sides). The following nibbles are off all the time (starting from nibble 0): 2, 5, 8, 11, 14, 17, 20 (problably also 23 and 26, but those are outside of the screen so they are cut off and never visible in this mode)
- 1: vertical bars, color fade from red (middle) over green and blue to purple (top and bottom sides). All nibbles are used to control a bars
- 2: vertical bars, color fade from turquoise (middle) over blue, purple/magenta and red to yellow (left and right sides). The following nibbles are off all the time (starting from nibble 0): 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22 (probably also the rest in the pattern, but those are outside of the screen so they are cut off and never visible in this mode)
- 3: same as 2, but the color fade is reversed and it's not centered in the middle but on the top and bottom sides of the mask.
- 4: horizontal bars, color fade from light purple (middle) over dark blue, light blue and turquoise to green (top and bottom sides). The following nibbles are off all the time (starting from nibble 0): 2, 5, 8, 11, 14, 17, 20, 23, 26. There are two dots on each side of the screen, on the top and bottom of it. In this mode, if the value of a nibble goes over
0xc, it just behaves like its value is0x0.
Responses:
All responses are sent on the notification handle and their last byte is always plus 0x01 regardless of any previous calculation
-
REOKOK:- Description: Confirms that the mask has recieved and processed the image packet
- Hex of the ASCII name:
52454F4B4F4B - arguments:
- 2 bytes for the ID of the currently uploading image
- 1 byte for telling if it's a bitmap or an image (
0x00if bitmap and 0x01 if image) - padding up to 15 bytes
- 1 byte for the current packet index with an offset of 1 (it starts to count at
0x01instead of0x00) plus the above mentioned0x01(so for packet index0x50it would return0x52)
-
DATCPOK- Description: Confirms the recieving of the unix timecode
- Hex of the ASCII name:
44415443504F4B - arguments:
- 2 bytes for the two most significant bytes of the unix timecode sent by the
DATCPcommand
- 2 bytes for the two most significant bytes of the unix timecode sent by the
-
DATOK- Description: Confirms the start of the image upload for the specific image id
- Hex of the ASCII name:
444154534f4b - arguments:
- 2 bytes for the image id
- 1 byte to tell wether it's an image or a bitmap
-
PLAYOK- Description: Confirms that the
PLAYcommand was executed on the mask - Hex of the ASCII name:
504c41594f4b - arguments: none
- Description: Confirms that the
-
DELEOK -
CHEC- Description: Returns the number of DIY images
- Hex of the ASCII name:
43484543 - arguments:
- 1 byte for the number of DIY images
NOT YET DONE:
-
DELEOK: -
LOOA:-
Data that I know of:
04 4c 4f 4f 41 b1 91 f8 ec 4b 69 8c 90 1b 2c 37 04 4c 4f 4f 41 5a 7c b8 3d c5 4e bd dc 97 a0 b7 04 4c 4f 4f 41 c5 aa 6d 20 43 1c b5 0d b7 bd 92 04 4c 4f 4f 41 d3 36 d2 49 e5 90 8f 26 8b 94 28 04 4c 4f 4f 41 65 cd d5 51 db 6b 2f 71 ed 7e bd
-
-
TIME:-
Data that I know of:
09 54 49 4d 45 00 67 1a 3a fd 00 00 00 00 00 00 07 54 49 4d 45 45 52 52 3a fd 00 00 00 00 00 01 (this is the answer to the previous command coming from the mask, I'm not entirely sure which byte is still part of the command name and which is data. It could be that the command/response name is TIMEERR)
-