aronsky / esphome-components

Custom components for ESPHome
MIT License
38 stars 33 forks source link

Unable to connect to alternative brand of lights - incorrect base code? #5

Open jymbob opened 1 year ago

jymbob commented 1 year ago

I'm not having any success pairing any of the three lights I've got here. I've set up a second ESP32 as a sniffer to help me debug what's going on.

ESP32 controller sends:

Adv data: 02.01.02.1B.16.F0.08.10.80.0A.EE.31.BE.0A.F3.67.CB.A9.E3.C2.0E.9B.5C.9E.D4.BA.0F.29.31.31.93 (31)

Whereas hitting “pair” in the Android app sends (example):

Adv data: 02.01.01.1B.03.77.F8.B6.5F.2B.5E.00.FC.31.51.CC.E4.92.56.2E.4A.1B.FC.AC.ED.F4.1B.7C.B6.89.00 (31)

The first 5 digits always appear to be 02.01.01.1B.03, but just swapping those in the prefix doesn't work either.

I'm working on the assumption that the command needed is very slightly different for my brand of light, but altering these bits manually is then throwing off some sort of checksum value?

I'm not familiar enough with C to fully understand what manipulation takes place for the rest of the values. I expect if I replayed a working command it'd work as expected, but can't see how to build the right packet

aronsky commented 1 year ago

Hi,

Two things:

  1. The packets you captured are "whitened". You have to "unwhiten" them in order to really see what's going on inside. Use the ble_whiten function for a reference, it should receive a buffer of 18 bytes taken from the 10th byte onwards of each packet (0A in packet one, 2B in packet two). The seed is a short 2 bytes before the end of each packet, that is 0x3129 for the first packet, and 0xb67c for the second one (or 0x3129/0x7cb6, not sure about endianness). Once you "unwhiten" the packet, it should be more readable, and you can check the values of the different fields properly.
  2. For the life of me, I can't see how the prefix (the bytes before the 10th byte of the packets) would be different. I'm looking at the code of the app (both the Java decompiled code in JADX, and the native functions called from Java code to actually generated the BLE packet's buffer) - and the first 9 bytes are hard-coded. There's nothing dynamic about them - they should be the same. I'm at a loss about how your app generates those bytes differently from what I'm seeing in the disassembly. Which version of the app are you using - can you send me the APK?
jymbob commented 1 year ago

The app I'm using is from https://play.google.com/store/apps/details?id=com.jingyuan.lamp - v1.2.3

I'll see if I can get "unwhitened" packets into the console so I have a better idea of what's going on. I'm not particularly at home with C but will give it a try.

NB: Which app have you been basing your work off? Doing a quick search I can also see https://play.google.com/store/apps/details?id=com.alllink.smart_lighting which appears to be functionally equivalent. I wouldn't be surprised if there are others.

aronsky commented 1 year ago

Yep - it's the same app and version that I disassembled (LampSmart Pro 1.2.3). Very strange.

aronsky commented 1 year ago

I've unwhitened the packets for you. Here's a Python code to do that:

XBOXES = [
  0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,
  0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
  0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A,
  0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
  0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85,
  0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
  0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
  0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
  0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
  0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
  0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9,
  0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
  0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94,
  0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
  0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,
  0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
]

def unwhiten(buf, size, seed):
  res = []
  for i in range(size):
    res.append(buf[i] ^ XBOXES[(seed + i + 9) & 0x1f])
    res[i] ^= seed
    res[i] &= 0xff
  return res

As expected, the output of the packet from the app is absolutely garbled (i.e., it probably wasn't "whitened" with that function to begin with). Are you sure you're capturing the correct packet from the app? Maybe there are additional packets going out that you're missing?

jymbob commented 1 year ago

Thanks, getting more info.

I may have had the wrong packet earlier.

Latest transmit from here: [10:27:02][VV][esp32_ble_tracker:419]: Adv data: 02.01.01.1B.03.F0.08.10.80.D1.A2.BA.77.9E.70.9E.AE.C2.5F.67.6E.A6.9D.65.F4.B4.A0.51.A8.9A.C8 (31)

So, I can extract that into a packet and seed:

buf = [0xD1,0xA2,0xBA,0x77,0x9E,0x70,0x9E,0xAE,0xC2,0x5F,0x67,0x6E,0xA6,0x9D,0x65,0xF4,0xB4,0xA0]
seed= 0xa851

and plugging it into your unwhiten function:

00 11 00 01 7d 54 78 02 00 28 00 00 00 00 00 00 00 00
aronsky commented 1 year ago

That looks much better - but then, it also looks exactly like the packet sent by the ESP32, so I'm not sure why it's not working...

This is the packet sent by the ESP32 (from your first message):

00 04 00 01 26 40 49 f0 00 28 00 00 00 00 00 00 00 00

The 2nd byte seems to be just a counter, so it makes sense it differs. And the 4 bytes starting at index 4 (26 40 49 f0) are simply a random 32-bit identifier for the lamp...

You can make a few changes to the code and force it to send the same packet as the app, see if that works.

  1. Keep the counter (the 2nd byte) constant at 0x11. Though my testing shows that it does need to change, doubt if that will work.
  2. Use a hard-coded identifier of 0xf0494026 (or reverse the bytes, again - not sure about the endianness). Theoretically, if that pairing above succeeded, and the lamp is controllable by the phone - if you hardcode the identifier into the code, it should control the lamp without pairing. If that does work, the issue is only with the pairing mechanism.
jymbob commented 1 year ago

Yeah, the app definitely appears to be sending two distinct codes (although not every time, or maybe I'm just missing some of them), one which I can "unlighten" and one which I can't.

Locking down the identifier to my light (yes, it's little-endian) I can send packets that look almost exactly like some of the ones coming from the phone, but still no response from the light itself.

Here's a sample

esp
[14:52:19][VV][esp32_ble_tracker:419]: Adv data: 02.01.01.1B.03.F0.08.10.80.CB.51.1A.0F.F4.73.B6.E8.FB.28.DC.3C.E7.69.FA.65.F8.ED.FF.B7.5F.1A (31)
00 0b 00 01 7a 54 78 02 00 10 00 00 00 00 00 00 00 00

esp
[14:52:20][VV][esp32_ble_tracker:419]: Adv data: 02.01.01.1B.03.F0.08.10.80.0B.96.DA.CF.34.B3.76.28.3B.D9.1C.FC.27.56.C5.A5.38.2D.3F.D4.04.48 (31)
00 0c 00 01 7a 54 78 02 00 21 00 00 00 ff ff 00 00 00

esp
[14:54:14][VV][esp32_ble_tracker:419]: Adv data: 02.01.01.1B.03.F0.08.10.80.4A.EF.EF.E7.54.41.95.7E.3C.39.A8.01.E8.CC.DD.1E.FA.1A.D9.6F.67.44 (31)
00 10 00 01 7a 54 78 02 00 11 00 00 00 00 00 00 00 00

app
[14:55:23][VV][esp32_ble_tracker:419]: Adv data: 02.01.01.1B.03.F0.08.10.80.28.87.2A.3E.D7.9B.BE.08.9E.49.9A.D0.BE.0B.1B.12.DA.E1.2D.5A.63.40 (31)
00 30 00 01 7a 54 78 02 01 11 00 00 00 00 00 00 00 00

app
[14:55:23][VV][esp32_ble_tracker:419]: Adv data: 02.01.01.1B.03.F9.08.49.13.F0.69.25.4E.31.51.BA.32.C6.82.24.CB.3B.78.71.9E.5A.55.C6.49.4C.4C (31)
23 ab 24 ab 34 8f ea f1 9a 43 f0 8d 1f 55 90 ea e9 24

app
[14:55:23][VV][esp32_ble_tracker:419]: Adv data: 02.01.01.1B.03.F0.08.10.80.28.87.2A.3E.D7.9B.BE.08.9E.49.9A.D0.BE.0B.1B.12.DA.E1.2D.5A.63.40 (31)
00 30 00 01 7a 54 78 02 01 11 00 00 00 00 00 00 00 00

app
[14:55:24][VV][esp32_ble_tracker:419]: Adv data: 02.01.01.1B.03.77.F8.B6.5F.2B.5E.00.FC.31.51.50.E4.12.08.24.CB.BF.FC.AD.EC.F4.1A.20.CF.24.05 (31)
ae 9b d1 ad c9 40 65 c0 f5 0b c7 f3 09 d9 17 cb c6 ba

app
[15:16:08][VV][esp32_ble_tracker:419]: Adv data: 02.01.01.1B.03.F0.08.10.80.52.BA.12.37.5D.B0.78.E2.3A.94.26.B9.24.D9.DB.C1.C8.04.23.4D.C8.2F (31)
00 41 00 01 7a 54 78 02 01 21 00 00 00 e8 78 00 00 00

app
[15:16:07][VV][esp32_ble_tracker:419]: Adv data: 02.01.01.1B.03.F0.08.10.80.D4.B0.E1.23.BC.72.85.71.E1.5E.E2.F7.65.EF.76.C2.57.90.E5.C1.29.9B (31)
00 40 00 01 7a 54 78 02 01 21 00 00 00 e8 78 00 00 00

Not sure where to go from here. I might just set up something to send the exact codes I'm receiving back and see if I can get a response.

aronsky commented 1 year ago

OK. So it looks like the main difference between the app and the ESP32 (assuming the garbage packets are irrelevant) is the byte right after the identifier and before the command, which is set to 0 on the ESP32 (hard-coded), and seems to be 1 in the app.

Try setting it to 1 (on this line: https://github.com/aronsky/esphome-components/blob/main/components/lampsmart_pro_light/lampsmart_pro_light.cpp#L163), and see if that helps?

I don't remember whether I set it to 0 because it's what the app does, or because I had no other values to go off, and assumed it to be 0 - but it looks like 1 is the correct value, at least for you.

Let me know if that works.

cekosss commented 1 year ago

Hello guys, I also have issues with pairing my Lampsmart Pro compatible Lamp with the esp32. What do you mean with setting to 1? I am not good at programming, but I can manage to change the code. Can you please write what I have to write instead of 0x0?

Try setting it to 1 (on this line: https://github.com/aronsky/esphome-components/blob/main/components/lampsmart_pro_light/lampsmart_pro_light.cpp#L163), and see if that helps?

I don't remember whether I set it to 0 because it's what the app does, or because I had no other values to go off, and assumed it to be 0 - but it looks like 1 is the correct value, at least for you.

aronsky commented 1 year ago

Change the 0x0 on the line I linked to 1, that's it.

However, I'm not sure it will work - I was hoping it would, but @jymbob hasn't come back with positive results, which, I suspect, means that it didn't help...

cekosss commented 1 year ago

I've just tested it - unfortunately it didn't work either. Below my message, I have attached the log from my esp32 tracker when I controlled the Lamp from my iPhone with the beloved Lampsmart Pro iOS App. Maybe it can be useful for you. It looks similar to the adv in the first posting.

[22:27:10][VV][esp32_ble_tracker:396]: Ad Flag: 26 [22:27:10][VV][esp32_ble_tracker:399]: Service UUID: 0xF877 [22:27:10][VV][esp32_ble_tracker:399]: Service UUID: 0x5FB6 [22:27:10][VV][esp32_ble_tracker:399]: Service UUID: 0x5E2B [22:27:10][VV][esp32_ble_tracker:399]: Service UUID: 0xFC00 [22:27:10][VV][esp32_ble_tracker:399]: Service UUID: 0x5131 [22:27:10][VV][esp32_ble_tracker:399]: Service UUID: 0x935C [22:27:10][VV][esp32_ble_tracker:399]: Service UUID: 0x0892 [22:27:10][VV][esp32_ble_tracker:399]: Service UUID: 0xCBBC [22:27:10][VV][esp32_ble_tracker:399]: Service UUID: 0xFC7E [22:27:10][VV][esp32_ble_tracker:399]: Service UUID: 0xC030 [22:27:10][VV][esp32_ble_tracker:399]: Service UUID: 0x36F4 [22:27:10][VV][esp32_ble_tracker:399]: Service UUID: 0x0ADD [22:27:10][VV][esp32_ble_tracker:399]: Service UUID: 0x8B58 [22:27:10][VV][esp32_ble_tracker:418]: Adv data: >02.01.1A.1B.03.77.F8.B6.5F.2B.5E.00.FC.31.51.5C.93.92.08.BC.CB.7E.FC.30.C0.F4.36.DD.0A.58.8B (31)

jymbob commented 1 year ago

Sorry, yeah, no joy yet. Will try some more things this week and report back.

On Sat, 1 Jul 2023, 22:11 cekosss, @.***> wrote:

I've just tested it - unfortunately it didn't work either. Below my message, I have attached the log from my esp32 tracker when I controlled the Lamp from my iPhone with the beloved Lampsmart Pro iOS App. Maybe it can be useful for you.

[22:27:10][VV][esp32_ble_tracker:396]: Ad Flag: 26 [22:27:10][VV][esp32_ble_tracker:399]: Service UUID: 0xF877 [22:27:10][VV][esp32_ble_tracker:399]: Service UUID: 0x5FB6 [22:27:10][VV][esp32_ble_tracker:399]: Service UUID: 0x5E2B [22:27:10][VV][esp32_ble_tracker:399]: Service UUID: 0xFC00 [22:27:10][VV][esp32_ble_tracker:399]: Service UUID: 0x5131 [22:27:10][VV][esp32_ble_tracker:399]: Service UUID: 0x935C [22:27:10][VV][esp32_ble_tracker:399]: Service UUID: 0x0892 [22:27:10][VV][esp32_ble_tracker:399]: Service UUID: 0xCBBC [22:27:10][VV][esp32_ble_tracker:399]: Service UUID: 0xFC7E [22:27:10][VV][esp32_ble_tracker:399]: Service UUID: 0xC030 [22:27:10][VV][esp32_ble_tracker:399]: Service UUID: 0x36F4 [22:27:10][VV][esp32_ble_tracker:399]: Service UUID: 0x0ADD [22:27:10][VV][esp32_ble_tracker:399]: Service UUID: 0x8B58 [22:27:10][VV][esp32_ble_tracker:418]: Adv data:

02.01.1A.1B.03.77.F8.B6.5F.2B.5E.00.FC.31.51.5C.93.92.08.BC.CB.7E.FC.30.C0.F4.36.DD.0A.58.8B (31)

— Reply to this email directly, view it on GitHub https://github.com/aronsky/esphome-components/issues/5#issuecomment-1616116303, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA7U2FKGQ4Y3LKWQQTXOAMDXOCG7TANCNFSM6AAAAAAZJVUBEI . You are receiving this because you were mentioned.Message ID: @.***>

cekosss commented 1 year ago

Hello again,

I just have logged the signal of the remote control, which was delivered with the lamp. The button I pressed was the SETUP button for pairing with the lamp. I hope, that this could be useful for you, since the adv data of the pairing command looks a little bit different.

[20:52:27][VV][esp32_ble_tracker:368]: Parse Result: [20:52:27][VV][esp32_ble_tracker:385]: Address: 10:9E:3A:10:25:5D (RANDOM) [20:52:27][VV][esp32_ble_tracker:387]: RSSI: -28 [20:52:27][VV][esp32_ble_tracker:388]: Name: '' [20:52:27][VV][esp32_ble_tracker:396]: Ad Flag: 2 [20:52:27][VV][esp32_ble_tracker:413]: Service data: [20:52:27][VV][esp32_ble_tracker:414]: UUID: 0x08F0 [20:52:27][VV][esp32_ble_tracker:415]: Data: 10.00.27.30.1A.D7.E2.C8.46.0C.62.FF.C7.CE.06.3D.C5.54.14.00.F1.15.F8.36 (24) [20:52:28][VV][esp32_ble_tracker:418]: Adv data: 02.01.02.1B.16.F0.08.10.00.27.30.1A.D7.E2.C8.46.0C.62.FF.C7.CE.06.3D.C5.54.14.00.F1.15.F8.36 (31)

aronsky commented 1 year ago

I'll need to unwhiten that message to check its contents. But at least as far as the beginning goes, it looks similar to what the compnent transmits.

@jymbob @cekosss has any of you used lampify successfully? If so, a fallback to lampify's algorithm (which seems quite different from what I disassembled from the app), could work.

aronsky commented 1 year ago

[20:52:28][VV][esp32_ble_tracker:418]: Adv data: 02.01.02.1B.16.F0.08.10.00.27.30.1A.D7.E2.C8.46.0C.62.FF.C7.CE.06.3D.C5.54.14.00.F1.15.F8.36 (31)

@cekosss so the unwhitened data in this packet looks like this:

56 23 00 01 a1 4c 00 00 00 28 00 00 00 00 00 00 00 00

Broken down, that is (note, it's little-endian, so the bytes for each field are reversed):

So, that matches what this component sends out pretty well, except:

  1. The first byte is always 00, and here it is 56. Since the following byte is an 8-bit packet number, there's a chance that I misunderstood, and both bytes are a 16-bit packet number (so in the above packet, the packet number is 0x2356). That's the most likely explanation to the discrepancy, and makes it irrelevant (as the packet number seems irrelevant mostly, other than having to change).
  2. The identifier seems to be only 16 bits (and not 32 bits) wide. That should hardly matter - i.e., if the lamp expects a 16-bit identifier, it will simply look at the 1st 2 bytes out of the 4. So, again, unlikely that this is the culprit.

So, if that button press worked, and the lamp was paired - I'm quite at a loss as to what may cause this. The current code is really spot-on, other than the above 2 points. I made a branch with those changes for you to test out: https://github.com/aronsky/esphome-components/tree/support-additional-lamps The first commit fixes the 1st point, whereas the 2nd commit fixes the 2nd point (in case you want to revert each separately and test if it helps).

If that doesn't help, you can take the main branch and hardcode 0x56 to be the last byte on line https://github.com/aronsky/esphome-components/blob/7cdddcef91d3238f9093ffaec36c6516b04c2b2e/components/lampsmart_pro_light/lampsmart_pro_light.cpp#L159 (instead of 0x00). I really doubt that it will help, but worth trying if all the other options fail.

Finally, if none of the above works - I'm not sure what else can be done. Clearly the code works the same as the remote control, so if the remote control works - so should the code... Any chance the lights are simply too far away from the ESP32?

jymbob commented 1 year ago

The lights are part of an ongoing extension so I'm only able to test this out when the builders aren't around. I'll try to do some more testing shortly. My understanding is that the BLE remote is doing a far simpler interaction with the light compared to the app, although the end result appears to be the same. I'm also not sure it can support a rolling code, but haven't yet fully tested that with my sniffer.

On Mon, Jul 3, 2023 at 10:09 AM Lev Aronsky @.***> wrote:

I'll need to unwhiten that message to check its contents. But at least as far as the beginning goes, it looks similar to what the compnent transmits.

@jymbob https://github.com/jymbob @cekosss https://github.com/cekosss has any of you used lampify successfully? If so, a fallback to lampify's algorithm (which seems quite different from what I disassembled from the app), could work.

— Reply to this email directly, view it on GitHub https://github.com/aronsky/esphome-components/issues/5#issuecomment-1617684400, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA7U2FPEPT2UBNY3O6BAL43XOKD4DANCNFSM6AAAAAAZJVUBEI . You are receiving this because you were mentioned.Message ID: @.***>

-- GMail. Marvellous

cekosss commented 1 year ago

Unfortunately lampify doesn't work on my Raspberry Pi Zero 2W, which is supposed to support BLE... Getting a "failed to send notification" message.

@jymbob @cekosss has any of you used lampify successfully? If so, a fallback to lampify's algorithm (which seems quite different from what I disassembled from the app), could work.

andyxpert commented 1 year ago

Hi Aronsky,

Great work !! Used this for a month and then because of a crack in the housing I had to replace the entire fixture. This new one (although 95% identical with the previous one) works with a different app - http://mihuan.iotworkshop.com/zhiguang/ Not working with any of the ones mentioned above (Previous one worked with LampSmart Pro, this one doesn't).

Anyway, same issue as OP, your code or the fork can't pair, lampify similarly doesn't connect - no light flicker to confirm.

Is there a guide or a script I can use to sniff what the remote or the app send (BT codes I mean, ideally unwhitened) ??

Also, couldn't you code be simplified ? I.e. separating the static part of the bytes sent for setup from the dynamic part to make it easier to try some combinations for other devices as such ?

Have a linux with a BT dongle and a few ESPs, HA, a RPi, etc

aronsky commented 1 year ago

Sorry, if that fixture doesn't work with LampSmart Pro, it's out of scope for this repo. A different app means that the protocol is probably completely different (otherwise it would support the other apps).

andyxpert commented 1 year ago

Thank for the reply. Not sure it's that different, it's the same fixture as the previous one, only difference is the app, which is pretty much identical to the old one, and I can bet it's the same protocol (as the HW is the same), maybe only a few bytes are different. How could I go about debugging it ?? With btmon I sniffed this command that is sent in the pairing/setup phase:

From the Remote: 18f90849b2ce2c109a9efd050320c9412c10111213141516171819 The App is sending many UUIDs:

HCI Event: LE Meta Event (0x3e) plen 43 #170 [hci0] 7.056681 LE Advertising Report (0x02) Num reports: 1 Event type: Connectable undirected - ADV_IND (0x00) Address type: Random (0x01) Address: 69:E5:B6:0E:2B:60 (Resolvable) Data length: 31 Flags: 0x01 LE Limited Discoverable Mode 16-bit Service UUIDs (complete): 13 entries Unknown (0x08f9) Unknown (0xb249) Unknown (0x2cce) Unknown (0x3b8f) Unknown (0x906b) Unknown (0x3e0e) Unknown (0x3de1) Unknown (0xa5dc) Intercom (0x1110) Unknown (0x1312) Unknown (0x1514) Unknown (0x1716) Unknown (0x1918) RSSI: -86 dBm (0xaa)

Don't know yet how to alter your code for ESP locally (without publishing my own GitHub repo) but I can use the base Lampify code locally where I can easily change the base bytes that are sent. Tried with a few combinations without any luck. Any pointers would be great.

Alternatively I can unpack the apk and decompile it but I'm not sure what to look for there also.

andyxpert commented 1 year ago

I think I'm close... Used nRF Connect on Android to sniff the BT communication, here's what I got:

Remote Control: 18f90849b2ce2c51dbdfbc444220886b5910111213141516171819 1848464b4a69e8b0d5fb6a94c8cacfc218e90b9a39101112131415 UUID: 0x5558 Data: 0x1eff5855 then the strings above 18...

Aronsky ESP: 1080534181640a4b4106dc6954c6a4ad61f433f146f6a982 1080c8df4f2cabfdecff781a5ce9f9f03803fb6acf8c7ec7 UUID: 0x08f0 Data: 0x1080... - the string from above

Now, I tried altering the lampify script to send these hex values, but I may be doing something wrong, as not all the array elements need to be updated, only some of them... will try some more later this evening. It would be great though to be able to play with your code without the need to publish it on GitHUB so that ESP can grab the custom_component. How can I play with it locally and use your altered code in ESP more easily ? I'll also try to alter the generated image from ESPHome server, but I think they're already built...

aronsky commented 1 year ago

Hi, You can fork this repo and point your ESPHome config to your fork (replace my username with yours). You can also download the code and put it in a custom_components subfolder in your ESPHome directory - I don't recall the exact details, but look it up, it's possible (I started with that before uploading my code to GitHub).

However, be advised, that this may be more difficult than you expect. There are multiple apps that work with the lamps supported by this repo, so clearly there is some protocol that remains shared between all those apps. Since you say that you had to switch to a different app, and other apps don't work - it's quite possible that underneath a similar appearance, the protocol is completely different.

In any case, guessing what bytes need to be changed based on BLE monitoring alone is moot. The data you see is encoded, and without decoding it properly, there's no chance you will see a single byte or two of difference - the whole packet will look different. You'll have to disassemble the app and see what it's doing.

cekosss commented 1 year ago

Since I am not a programmer, I may not be very useful in developing the code, but I can offer you me testing your work with my ESP32 and my lamp.

If you like to get more information about the specific remote control of my lamp, just let me know and I will do my best to provide the information you need.

Never give up :-)

andyxpert commented 1 year ago

:) never give up, indeed, until I decompiled that chinese apk (about 35MB) and got a bit scared... it tries to constantly send data to some chinese servers... So I did the normal rational thing - bought 3 other fairly similar fixtures, this one I'll return for a refund... and out of the new ones I hope to find one that works way easier without the need to hack the bytes sent to it...

With ESP what I managed to do is grab Aronsky's code and put it locally so I can play with it, tried a few byte changes but it's pretty much pointless, as after decompiling the APK I saw that every packet sent to the light is followed by another packet... so somehow they always send a pair of packets. Couldn't understand much of the payload as the apk is done on some existing frameworks and there are waaaaaaaaaaay too many interfaces and abstractizations and a few decorators... so unless I convert the decompiled apk into a working Android project I can't do much on it :(

Zulex commented 1 year ago

I was running at the same issue as @jymbob .

Tried the

Logs are always saying the device is trying to pair: [11:27:42][D][lampsmartpro:146]: LampSmartProLight::on_pair called! [11:27:43][W][component:204]: Component api took a long time for an operation (1.00 s). [11:27:43][W][component:205]: Components should block for at most 20-30ms.

I have managed to sniff out the 'setup' button on the BLE controller that was provided with the light:

0201021B16F0081000759804E5F373A4BD201DA7C5CC00955290DA270338FC If correct that should give:

buf = [0x75,0x98,0x04,0xE5,0xF3,0x73,0xA4,0xBD,0x20,0x1D,0xA7,0xC5,0xCC,0x00,0x95,0x52,0x90,0xDA]
seed= 0x0327
result: [86, 120, 0, 1, 204, 194, 134, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0]

I also tried to see what the code would be after a few clicks and also after reconnecting (2 times).

After a few clicks: [86, 133, 0, 1, 204, 194, 134, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0]
After reconnecting 2 times: [86, 135, 0, 1, 204, 194, 134, 0, 0, 40, 0, 0, 0, 0, 0, 0, 0, 0]

It seems like the only thing that is changing is the counter, as you already figured. I am not sure how to go on from here, it does not seem to match with the signal we are sending out if I read correctly above. I also noticed that you mention 0x28 is the command for pairing, however, it looks like 0x40 is used here. (@aronsky , any clue what the 40 does? It might also just be a verification which is send later).

So here I also tried too just change the 0x28 definition by 0x40, however that also did not do the trick unfortunately.

I am really not sure where to go from here actually.

Justin8428 commented 1 year ago

I also had the same issues as described above -- the commands would send to the esp32 (light flashes) but lamp does not respond, even after trying the various branches If it helps @aronsky @cekosss I actually managed to get lampify to work on a laptop running Debian 12 with an Intel AC-8265 wireless card (was a bit of an adventure to get it working actually -- it wouldn't work on Ubuntu, nor on a newer laptop with an AX210 -- not really sure why it would matter, but anyway...). I don't have a Raspberry Pi to test but I think with lampify the "failed to send notification" message doesn't necessarily mean its not working, that particular error likely refers to some gnome notification dependencies.

aronsky commented 1 year ago

I also had the same issues as described above -- the commands would send to the esp32 (light flashes) but lamp does not respond

What do you mean the light flashes? The light on the ESP32, or the lamp you're trying to control flashes after using the ESP32 to pair?

Justin8428 commented 1 year ago

Sorry should have been clearer -- I meant the led on the esp32, not the lamp itself :-)

aronsky commented 1 year ago

In that case (especially since lampify works for you), it seems like the protocol emulated in this repo is not supported by your lamp. Does LampSmart Pro work for you?

Justin8428 commented 1 year ago

Yes my lamp uses LampSmartPro (for reference, this is the lamp I have https://www.amazon.com.au/Jaycomey-Modern-Ceiling-Chandelier-Bedroom/dp/B098PX1NTC/ref=asc_df_B098PX1NTC/?tag=googleshopmob-22&linkCode=df0&hvadid=463557230554&hvpos=&hvnetw=g&hvrand=9187376774626490782&hvpone=&hvptwo=&hvqmt=&hvdev=m&hvdvcmdl=&hvlocint=&hvlocphy=9071869&hvtargid=pla-1644068114591&psc=1)

aronsky commented 1 year ago

I see. In that case, I don't have any advice on offer - as I mentioned before, the only comms protocol I found in the app is the one implemented here, and if it doesn't work - I have no idea where to look for something different. You're welcome to change the implementation to use the logic from lampify, and make a PR.

jymbob commented 1 year ago

@Justin8428 Well done for managing to get lampify working - I gave up!

Are you able to sniff some packets? I installed the ESPHome BLE tracker on my ESP32 so I could grab packets and try to figure out what was or wasn't working. I'd be very interested to see what lampify is sending and how it differs from the code generated above. As @aronsky says it should be possible to replicate what lampify is doing if that's working.

Justin8428 commented 1 year ago

@jymbob it might be a while before I'll be able to sniff some packets :-( -- the laptop with the working wireless card in it broke, and my main machine has the problematic AX210. In the meantime I have forked the lampify repo and provided some updated instructions on how to run it + made some minor changes to the code (mostly removing the GNOME dependencies and adding a feature to control multiple lamps). Not exactly that great at C so porting that code to the ESP32 might be out of my depth but hopefully you or someone else could try getting lampify working again and looking at what exactly its doing? From what I can see in the lampify code it seems to be relying on a whole heap of low level hci commands to send custom packets which I'm not even sure ESPhome would be able to support (but then again I haven't looked too hard into the ESPhome documentation so maybe its been done already haha)

dmiyyy commented 1 year ago

So here I also tried too just change the 0x28 definition by 0x40, however that also did not do the trick unfortunately.

Dec 40 is 0x28 in hex. It looks like this is correct. Has anybody progress on resolve connection problems with another lamps?

Di1Ly commented 1 year ago

Has anybody progress on resolve connection problems with another lamps? I have compile lampify project at x86 platform. Now I can pair and control LED successfully. Unable to use this ESP32 project for the control. Does it metter which board I have use? I have ESP32-CAM board (ESP32s the name on the controller).

dimerr commented 1 year ago

None of the code from this repo works, so i took lamp smart pro app, also disassembled libs, to check what app does and i see exactly what @aronsky said and implemented in this repo.

Then i've sniffed packets from app - they are the same, like: 0x0201011b03f0081080a5de7e6feef569bcfd95a92980694d5c9f7b5886d531 unwhitened to: ['0x0', '0x15', '0x0', '0x1', '0x89', '0x5a', '0xfd', '0xd0', '0x0', '0x28', '0x0', '0x0', '0x0', '0x0', '0x0', '0x0', '0x0', '0x0']

and app works just fine.

Then i've sniffed remote control that comes with lamp: 0x0201021B16F0081000F17D55C1A45EF8E1556C4D85BE46D7CB6C03726D5BDE -> ['0x61', '0xe4', '0x0', '0x1', '0xa3', '0x9b', '0x77', '0x0', '0x1', '0x28', '0x0', '0x0', '0x0', '0x0', '0x0', '0x5c', '0xef', '0x0']

Even if i fake exactly the same payload, it wont pair. But lampify works. What is that magic, when android app works for everyone and self-crafted code wont?!

Zulex commented 1 year ago

So I thought that maybe the ESP is not compatible with all light (different bluetooth versions?), and want to try sending these commands via my phone, from which the application is working as a double check. I would like to use 'EFR Connect BLE Mobile app' for advertising the same data as the ESP. However I am a bit puzzled by the entry fields; anyone got the pairing commands from app/in ESP code to work via an android app like this? Or anyone that could give me a hint on what to fill in exactly?

A screenshot elsewhere with the entryfields in the app: Link

aronsky commented 1 year ago

Hi,

While there are different BLE versions, the changes in newer versions (5+) that are unsupported by older ESP32 boards are irrelevant to this code (it's mainly support for bigger messages and higher bitrate).

Georgerdx commented 10 months ago

Hello All,

Interesting reading here. i would be interested to know how are you guys able to sniff the remote and the pairing command from the phone. I’ve got wireshark & nrf52840 setup, but i can’t recognoze the phone or the lamp remote in the traffic. I know the bluetooth mac address of my phone but there are no packets visible unfortunately. I am using iphone xr with the lampsmart pro app on it.

Thank you

aronsky commented 10 months ago

The phone will use a random MAC address for privacy. Use the nRF Connect app (it is for Android, not sure if there’s an iOS version) to find the MAC of the lights, then look for packets directed to it.

However, that probably won’t work, either. Most of Bluetooth traffic (except the broadcasts, I think) uses channel hopping, so sniffing it without specialized hardware is hard. You’ll be better off impersonating the lights, and seeing the traffic reaching you from the app/remote that way.

On Tue, 21 Nov 2023 at 18:23 Georgerdx @.***> wrote:

Hello All,

Interesting reading here. i would be interested to know how are you guys able to sniff the remote and the pairing command from the phone. I’ve got wireshark & nrf52840 setup, but i can’t recognoze the phone or the lamp remote in the traffic. I know the bluetooth mac address of my phone but there are no packets visible unfortunately. I am using iphone xr with the lampsmart pro app on it.

Thank you

— Reply to this email directly, view it on GitHub https://github.com/aronsky/esphome-components/issues/5#issuecomment-1821246810, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABD52DBFUGSTZOI5W3WJAFLYFTIPTAVCNFSM6AAAAAAZJVUBEKVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQMRRGI2DMOBRGA . You are receiving this because you were mentioned.Message ID: @.***>

jymbob commented 10 months ago

@Georgerdx the easiest way I've found of reliably sniffing packets is to get a second ESP32 and install https://esphome.io/components/esp32_ble_tracker.html to scan for packets, although how useful that will be depends on the number of other chatty BLE devices in your vicinity.

igui commented 10 months ago

Hello All, Interesting reading here. i would be interested to know how are you guys able to sniff the remote and the pairing command from the phone. I’ve got wireshark & nrf52840 setup, but i can’t recognoze the phone or the lamp remote in the traffic. I know the bluetooth mac address of my phone but there are no packets visible unfortunately. I am using iphone xr with the lampsmart pro app on it.

It is possible to capture packets using a Rasperry Pi.

The command I use is sudo tcpdump -i bluetooth0 --packet-buffered -w - > bluetooth-capture.dmp without any setup. I can read packets from other devices like packages from neighbours, so it can be noisy as @jymbob pointed out.

StevenReitsma commented 7 months ago

The code in this repository didn't work for my lights either, but Lampify worked perfectly. I wanted to use an ESP however, so I ported the Lampify code over to ESPHome.

https://github.com/StevenReitsma/esphome-lampsmart-pro

It's basically a merge of the ESPHome component in this repository and the Lampify protocol. Hopefully it's of some use to others as well!

oxcid3 commented 7 months ago

Hey aronsky, thanks for all your work getting this far.

I have a lamp that works wtih LampSmartPro, but sadly doesn't pair using this repo.

I'm technical, and reasonably familiar with Wireshark, but not a dev by any stretch. I've managed to log the Bluetooth HCI output from the app, and after a fight with my phone, managed to get it out Looking at some of the info above, I think I've identified the string that was the initial pairing request: (because it starts with "02.01.01.1b.03.77")

02.01.01.1b.03.77.f8.b6.5f.2b.5e.00.fc.31.51.cc.46.92.f4.2e.4a.eb.fc.00.59.f4.af.7c.75.ef.3f

I wondered if anyone could help 'unwhiten' this so help me see if perhaps my light uses a different number for the pairing command.

Here's the packet info:

Frame 1057: 39 bytes on wire (312 bits), 39 bytes captured (312 bits) Bluetooth Bluetooth HCI H4 [Direction: Sent (0x00)] HCI Packet Type: HCI Command (0x01) Bluetooth HCI Command - LE Set Extended Advertising Data Command Opcode: LE Set Extended Advertising Data (0x2037) 0010 00.. .... .... = Opcode Group Field: LE Controller Commands (0x08) .... ..00 0011 0111 = Opcode Command Field: LE Set Extended Advertising Data (0x037) Parameter Total Length: 35 Advertising Handle: 0x02 Data Operation: Complete scan response data (0x03) Fragment Preference: Controller should not fragment or should minimize fragmentation of Host data (0x01) Data Length: 31 Advertising Data Flags Length: 2 Type: Flags (0x01)

  1. .... = Reserved: 0x0 ...0 .... = Simultaneous LE and BR/EDR to Same Device Capable (Host): false (0x0) .... 0... = Simultaneous LE and BR/EDR to Same Device Capable (Controller): false (0x0) .... .0.. = BR/EDR Not Supported: false (0x0) .... ..0. = LE General Discoverable Mode: false (0x0) .... ...1 = LE Limited Discoverable Mode: true (0x1) 16-bit Service Class UUIDs Length: 27 Type: 16-bit Service Class UUIDs (0x03) UUID 16: Unknown (0xf877) UUID 16: Unknown (0x5fb6) UUID 16: Unknown (0x5e2b) UUID 16: Unknown (0xfc00) UUID 16: Unknown (0x5131) UUID 16: Unknown (0x46cc) UUID 16: Unknown (0xf492) UUID 16: Unknown (0x4a2e) UUID 16: Avi-On (0xfceb) UUID 16: Unknown (0x5900) UUID 16: Unknown (0xaff4) UUID 16: Unknown (0x757c) UUID 16: Unknown (0x3fef) [Response in frame: 1058] [Command-Response Delta: 0.738ms]

Really appreciate any support.

jymbob commented 7 months ago

The code in this repository didn't work for my lights either, but Lampify worked perfectly. I wanted to use an ESP however, so I ported the Lampify code over to ESPHome.

https://github.com/StevenReitsma/esphome-lampsmart-pro

It's basically a merge of the ESPHome component in this repository and the Lampify protocol. Hopefully it's of some use to others as well!

This is also working for at least one of my lights!

Zulex commented 7 months ago

The code in this repository didn't work for my lights either, but Lampify worked perfectly. I wanted to use an ESP however, so I ported the Lampify code over to ESPHome.

https://github.com/StevenReitsma/esphome-lampsmart-pro

It's basically a merge of the ESPHome component in this repository and the Lampify protocol. Hopefully it's of some use to others as well!

Also worked for my light without any hassle, thanks/bedankt Steven!

aronsky commented 7 months ago

The code in this repository didn't work for my lights either, but Lampify worked perfectly. I wanted to use an ESP however, so I ported the Lampify code over to ESPHome.

https://github.com/StevenReitsma/esphome-lampsmart-pro

It's basically a merge of the ESPHome component in this repository and the Lampify protocol. Hopefully it's of some use to others as well!

Glad that it worked for you, and it looks like it's working for additional people. If you feel like it, you're welcome to merge the code so that the two repos can be combined, and the end-user can choose the subtype of the lights (i.e., the protocol to use) in the configuration.

flicker581 commented 7 months ago

I'm also trying to reverse-engineer RC protocol for these lamps. Unfortunately, now I have two different remotes at hands and zero lights (they are installed at friend's home, we will try to control them someday). What I've managed to know so far:

Both remotes send TWO different advertisements each time. One adv comes with MAC 10:9E:3A:10:25:5D and second with MAC 59:BA:2B:D2:57:8D. Advertisements come really fast, interval is about 1-2ms. nRF Connect catches ~200 copies of each message, except for Setup, which does ~800 copies. This violates BLE specs, AFAIK, because proper advertisement interval cannot be less than ~20ms.

Those two advertisements are very different. Type1 (10:9E:3A:10:25:5D) is almost the same as used in this repo (with several slight differences), and Type2 (59:BA:2B:D2:57:8D) is similar to lampify protocol, but with important differences in layout and CRC calculation. I'm not sure which of advs (or both) is needed for our lights. They carry almost the same information.

Also, I'm unsure if emulator should fake those MACs to gain control. 10:9E: looks like regular random address and can be sent from ESP32, but 59:BA: is RPA address and ESP32 is, AFAIK, unable to fake it. Sadly, I've not managed yet to re-calculate CRC for Type2 protocol. Honestly, I cannot be sure that it is CRC at all.

0x56 from the discussion above is somewhat like variant number. One remote with white lights has 0x56, and second one for RGB light has 0x57. This number appear in different places: at the beginning of Type1 packet, in header of Type2 packet (you may see it as manufacturer data with id 0x5556 or 0x5557), and in Setup request of Type2.

Also, ble_whiten from this repo is not proper BLE whitening, it is some kind of encryption for Type1. Whereas the lampify tool use proper BLE whitening for channel 37. In fact, it looks that this part of message is transmitted over the air unwhitened, which is somewhat strange and may be legacy of some non-bluetooth radio receivers.

flicker581 commented 7 months ago

@oxcid3,

02.01.01.1b.03.77.f8.b6.5f.2b.5e.00.fc.31.51.cc.46.92.f4.2e.4a.eb.fc.00.59.f4.af.7c.75.ef.3f

Unfortunately, this packet is using some different format. The app is sending three (as far as I can see from BT logs) different setup commands. Only one of them follow known protocol.

0201021b03f0083080b864e1279cfb26d76544a49f67f6b67f0e8b532ba064 - this one can be deciphered. 0201021b03f9084913f069254e3151baae86023ac1ba7c7186c6555a29c94c 0201021b0377f8b65f2b5e00fc3151cca492162e4abbfc9356f4a0a208c40a - these are different.

oxcid3 commented 7 months ago

@flicker581

Thanks for taking a look - Just to be clear the one I posted starts 020101, not 020102 But I've found a packet that very closely matches that top one, again the only difference is the 3rd pair is "01" not "02" which appears to be something to do with 'Limited Discovery Mode' being True Here's a bunch of values that all start with the same 0201011b03 prefix if that helps:

0201011b03f0083080b86ee127dbfc4be76544a49f67f6b65db88b532bddbe 0201011b0377f8b65f2b5e00fc3151cc4692f42e4aebfc0059f4af7c75ef3f 0201011b03f9084913f069254e3151baae6402d8c1ba2c71ea3655aa33684c

0201011b03f9084913f069254e3151baae6402d8c1bacc71528e551259a64c 0201011b0377f8b65f2b5e00fc3151cc4692f42e4a0bfc1049f4bf9fd03f65

0201011b03f0083080b86fe127dbfc4be76544a49f67f6b6d6a88b532b4ab5 0201011b03f0083080b868e127dbfc4be76544a49f67f6b694f18b532bf25c 0201011b03f9084913f069254e3151baae6402d8c1ba4c71ed3155adffe04c