Reverse Engineering Blisslights 2.0 Bluetooth Star Projector?

Hi all. Sorry in advance for the huge post.

I recently got one of those Blisslights Star Projectors (the 2.0 version with Bluetooth) and I’m trying to reverse engineer the commands that their official app sends to the device so I can hopefully integrate it into Home Assistant somehow… As of right now the device does not remember its last state while on, so my only current way to integrate it into HA (a smart plug) allows essentially only one light mode, the default when it turns on.

I followed this wonderful guide to get myself started trying to figure out what the commands being sent from the Blisslights app to the projector are, but I think I may have exhausted my abilities at this point.

Following the guide, I found the device on the nRF app, found 4 characteristics used to communicate with the device:

  1. 1911 Notifications
  2. 1912 Commands
  3. 1913 OTA (Assuming over the air update stuff)
  4. 1914 Pair

I sniffed some bluetooth packets using my Android phone while sending some commands through the app, and the order of notable events essentially was:

  1. Phone sends write request 0cc4c38bb5649aae797759a5daece26f02 (this changes every time, and there’s zero pattern for each command) through 1914, to pair the device I’m assuming.
  2. Projector sends reply (WireShark doesn’t say what it is)
  3. Phone sends a read request through 1914
  4. Projector sends back 0da3fe0961edf42718cc2967034afe3748 (again, no pattern I can see between different times)
  5. Phone sends 01 request to projector through 1911
  6. Projector sends back c8400d0000863cc4199b7cbc12bf635628b96926
  7. Phone sends command c7c5207b64ca9fe414e210c249a8da606a863ef5 to change lights to stars only through 1912

Looking through more logs, it’s clear that the app sometimes sends the 01 write request through 1911 prior to sending a command through 1912, but also seems to have the capability to send multiple commands through 1912 after one another.

Here is a list of commands that I sent (alternating between Nebula only and Stars only):

Value: c7c5207b64ca9fe414e210c249a8da606a863ef5
Value: c8c5204961239e7c67c70045b40acc799edb6625
Value: c9c52013faf771b29ef4a9353f950820b32acd07
Value: cac52026b5d07933491a23bd6b701de747c84f48
Value: cbc5208c56ab84173ac338d4a85e7be6b1f5a46a
Value: ccc520ed45b4a35ed54a7b37586d83805009f975
Value: cdc520f6ea193cb83cd19e5674cd2e0dc4a726e4
Value: cec52068def24e42073b55cbda8670d0fc600eae
Value: cfc5209d4305920e223c6b706816d2791a7d5270
Value: d0c5203ec99c4ef2f921413774bff5bccc905c45
Value: d1c5203d12cc74466fcc5de3ae23b66f3622b390
Value: d2c520dd124ab3885620bfe4d5e4b341eaf8f249
Value: d3c52094d43160b6c61f57f10ec5920f471edba0
Value: d4c52011765f7a7b727c068046d7a2dbc27e2947
Value: d5c520ff5aeb8fa08f78cf22cc4e77729e9dbe77
Value: d6c5205edc055bbb3fbad78c3b12e9a26767c6e1

Value: 87159869260c326c66a8073abb8e75a1d403a21f
Value: 881598b6a79412cc660045fa9f676921e99a5572
Value: 891598419aacaba126ccc59c3f943afb7f6a17e9
Value: 8a1598b9b62f598d0e6869a740c2b74494aa9e37
Value: 8b1598e15e347c2d1ad77cca5609eddaf394cdcb
Value: 8c15981f22dde086ea2bd4c666b6f9d860531c96
Value: 8d1598c1460c1ae3423d84c135df7962c7765965

Unfortunately, these commands seem to have no pattern whatsoever, which makes it rather difficult to reverse engineer them. I can tell the first two digits are incrementing each command, and the next 4 digits after that always stay the same (unless I log out and in, then they change). Other than that, zero patterns I can see.

A couple of other notes:

  • I’ve tried simply writing all those commands into 1912 to no avail
  • I’ve tried recreating every step I laid out above to no avail
  • When I send 01 to 1911 through the nRF app, I get a response only if I’ve already “paired” the device by sending that same long string of digits to 1914 in step 1. Although the actual letters/numbers always change, I can still use that one from above to get a response every time. If I don’t do that step, I get no response back when sending 01 to 1911.
  • If I open the Blisslights app and connect, then switch to the nRF app, the app will already be connected to the projector and I won’t need to do step 1, I will get a response by sending 01 to 1911 every time.

The only way I ever managed to change the lights successfully using the nRF app was by doing step 5 and step 7 only. I am thinking this worked because I switched from the Blisslights app right into the nRF app, and thus didn’t need to do step 1 as my last note bullet says. The nRF log said I received a response back when sending 01 to 1911. Unfortunately, I can no longer repeat it - it only worked once for a couple of commands and never again.

I am thinking maybe the 1912 commands are encrypted or contain some code that expires, and maybe that’s why I’m not able to send them anymore? My knowledge of this stuff is very slim, so please excuse my ignorance here, and please excuse me if this isn’t the right forum for this, I’m not really sure where else to ask. Thanks in advance!

8 Likes

I’m about to poke around in my Sky Lite 2.0 too.
I just need to get the dang bits for those security screws…

Sadly I can’t find any internal pictures, would be good to know what controller this thing uses.

2 Likes

I used a Torx T15 screwdriver to open. chip is TLSR8250





2 Likes

It occurred to me to try looking at the binary representation of the commands. My thought is if they’re using bit masks for commands, it might make things clearer? There’s a bit of a pattern, certain quartets are incrementing by one bit and other quartets are identical across commands. I don’t have anything definitive yet, but I thought I’d share my line of reasoning! Here’s the first four commands converted to binary from the list above (view them so each is on a single line, if you can):

1100 0111 1100 0101 0010 0000 0111 1011 0110 0100 1100 1010 1001 1111 1110 0100 0001 0100 1110 0010 0001 0000 1100 0010 0100 1001 1010 1000 1101 1010 0110 0000 0110 1010 1000 0110 0011 1110 1111 0101
1100 1000 1100 0101 0010 0000 0100 1001 0110 0001 0010 0011 1001 1110 0111 1100 0110 0111 1100 0111 0000 0000 0100 0101 1011 0100 0000 1010 1100 1100 0111 1001 1001 1110 1101 1011 0110 0110 0010 0101
1100 1001 1100 0101 0010 0000 0001 0011 1111 1010 1111 0111 0111 0001 1011 0010 1001 1110 1111 0100 1010 1001 0011 0101 0011 1111 1001 0101 0000 1000 0010 0000 1011 0011 0010 1010 1100 1101 0000 0111
1100 1010 1100 0101 0010 0000 0010 0110 1011 0101 1101 0000 0111 1001 0011 0011 0100 1001 0001 1010 0010 0011 1011 1101 0110 1011 0111 0000 0001 1101 1110 0111 0100 0111 1100 1000 0100 1111 0100 1000
1 Like

Thanks for the pictures. I noticed there was what looked like UART pins so my curiosity took over, but had to wait a day to get some longer torx bits! For mine, it was a T10 security screw, so there might be some variation in different models? 3" long bits off amazon.

I was able to get connected to the UART pins no problem using some jumpers I had. 115000 baud, but not 100% sure if that’s from my FTDI adapter or the light. Here’s the output of powering up and then pressing a few of the physical buttons.

..3»               
....  

void app_gpio_normal_init(void) in sig mesh USEWORKMODE:0

 init IO to IIC with pull 

-----------------------mac:a4c1XXXXXXXX-----------------------
v001.13
ff030006000a00001001000000000001ffffffffff01ffffffffff01000000ffff01ffffff00ff0100ffffffff01ff00ffffff00ff00060dff01ffff00ffff01ff000000ff01ff0dff68ff00a0b0c0d0ff00a0b0c0d0ff00a0b0c0d0ff00a0b0c0d0ff00a0b0c0d0ff00a0b0c0d0ff00a0b0c0d0ff00a0b0c0d0ff00a0b0c0d0ff0000010000000000000000000000000000000000000102030405060708090a0b0c0d0e0f101112131668

 read flash allSceneData len:171 
nowMotor:ff 
nowBright:03 
lightOnTimer:00 
lightOffTimer:06 
defaultScene:00 
lastScene:0a 
loopTimer:00 
isLoop:00 
isConfig:10 

 should turn on light --------------- 

  scene 01 r:255 g:255 b:255 l:255 m:255 
  
 start 
 clock :32M 
MY_RF_POWER_INDEX:169
timer 10ms
rgblm stop

 s1 keyDown 

  scene 02 r:255 g:255 b:255 l:255 m:255 
rgblm stop

 s1 keyDown 

  scene 03 r:0 g:0 b:0 l:255 m:255 
rgblm stop

 s2 keyDown 
rgblm stop

 s3 keyDown 
rgblm stop
APPVERSION v001.13
APPVERSION v001.13

I tried entering commands, but it doesn’t seem to take what it outputs as commands. Or maybe it has to be booted into another mode to allow control over serial? But no idea how to go about that.

It looks like the first 9 bytes of the long string is the current state. I only saw it output that long string when first plugged in. So might not be very useful.

ff 03 00 06 00 0a 00 00 10

nowMotor:ff 
nowBright:03 
lightOnTimer:00 
lightOffTimer:06 
defaultScene:00 
lastScene:0a 
loopTimer:00 
isLoop:00 
isConfig:10 

Unfortunately sending commands over bluetooth doesn’t show much. It just outputs like this…

rgblm stop
rgblm stop

I’m assuming RGBLM stands for red, green, blue, laser, motion based on the scene output.

 s1 keyDown 

  scene 00 r:0 g:0 b:0 l:0 m:0 
rgblm stop

 turn off light --------------- 

 s1 keyDown 

 should turn on light --------------- 

  scene 01 r:255 g:255 b:255 l:255 m:255 
rgblm stop

 s1 keyDown 

  scene 02 r:255 g:255 b:255 l:255 m:255 
rgblm stop

 s1 keyDown 

  scene 03 r:0 g:0 b:0 l:255 m:255 

 s1 keyDown 

  scene 04 r:255 g:255 b:255 l:0 m:255 

 s1 keyDown 

  scene 05 r:0 g:255 b:255 l:255 m:255 

 s1 keyDown 

  scene 06 r:255 g:0 b:255 l:255 m:255 

 s1 keyDown 

  scene 08 r:255 g:255 b:0 l:255 m:255 

 s1 keyDown 

  scene 09 r:255 g:0 b:0 l:0 m:255 

 s1 keyDown 

  scene 0a r:255 g:13 b:255 l:104 m:255 
rgblm stop

 s1 keyDown 

  scene 00 r:0 g:0 b:0 l:0 m:0 
rgblm stop

 turn off light --------------- 

I’m familiar with serial ports from the enterprise IT realm, and I’m an engineer / developer by trade, but this is as deep as my knowledge goes in the circuit realm. There is some documentation from the bluetooth chip manufacturer on the chip. There’s mention of a single wire debug interface, and the pins on my unit are labeled TX, RST, RX, SWS, GND, so SWS might be part of that. But I’ve gone as far as I’m going to go with this one today.

Hopefully this will help someone else take this further. Would be great if we could add an ESP in to control it via HA.

3 Likes

Hi all, I had a quick go with my SkyLite 2.0 mostly to try bluetooth sniffing. I took the Mac OS PacketLogger approach and could see traffic, but all a bit to obfuscated for a quick job.

What does seem a lot more promising is pulling apart the android APK. jadx comes out with something pretty sane and this will do the job nicely - Apktool - decode apk ONLINE with open-source APKTOOL. App supports many different devices. Looks like it’s using telink mesh, which appears to involve AES. Have a sniff of com.quhwa.blisslights/mesh & com.telink

I think there’s enough to go on if someone’s sufficiently motivated/bored but it’s not a simple protocol.

1 Like

Small bump to this topic, but found it fascinating.
Although Bluetooth control was not something I’ve experienced with.

So I hardwired the thing!
Five wires from the different FX6402 and FX6404 (could not find any datasheets…) to an ESP32 (5x PWM outputs) running with ESPHome.
Cutting the 3.3v trace to the existing TLSR8250F512ET32 so it will not be powered up.

1 Like