aronsky / esphome-components

Custom components for ESPHome
MIT License
45 stars 40 forks source link

Fan support #16

Open timmcfly85 opened 4 months ago

timmcfly85 commented 4 months ago

I installed your code in my ESPHome configuration. It paired perfectly the first time with my ceiling light and Home Assistant. I am now able to turn the light on using a better switch and button configuration.

My light has a ceiling fan on it and I would love to be able to control the fan going off and on and changing speeds depending on the temp of the room.

I have zero idea how to add that functionality to your repository. Is this something that you think you could add and/or get me started on adding in a branch. I'm using the lampsmart_pro_light component.

I think your code works for my fan even though it was not designed for that model. Just looking to add more functionality. If you are interested, the fan I have is https://a.co/d/0bQsB0o1

Thanks and keep up the great work.

aronsky commented 4 months ago

Hi Tim,

Unfortunately, adding the fan controlling functionality requires quite a bit of time that I don't have. If you feel comfortable with disassembly and reverse engineering, I can point you to the parts of the application that needs analysis - and afterwards, a fan component emulating that functionality needs to be added to the repo.

yacko1975 commented 4 months ago

I have a fan that uses a similar app by the same author (FanLamp Pro) I have downloaded and decompiled the APK and have some experience reverse engineering. If you want to point me in the direction of what parts of the app need analyzed to get the codes, I will see if I can pull the pieces that are needed and see if I can add them to a Pull. Thanks for all your work on this project.

aronsky commented 4 months ago

Hi @yacko1975 - so, I took a look at FanLamp Pro APK, version 1.3.6 (downloaded from APK Pure).

After opening it in JADX, the relevant code is in package j0, class a, method f(i, j$d) (it's Flutter, and everything is obfuscated badly). In that method, you can see 2 switch cases. The first simply sets the value that chooses the branch in the second switch - you should focus on the 2nd switch. In it, most branches call various methods of ToolV3 with various arguments. The method names are self-evidend: blevbBinding is for binding to the fan/light, blevbLampOnOff toggles the lamp, blevbDimming dims the lamp, and so on. The issue is that the arguments to that method are generated dynamically, so you need a way to figure them out. Assuming you have a rooted phone, Frida would be the best way to get that information. Notice that while the first argument - type - should be the same, the values for the other arguments might be different from call to call, they can represent the dimming level, for instance - and so on.

Once you have that information (i.e., for each ToolV3.blevb... method that you want to implement, the actual argument values that are passed), it's time to jump into the native code. From the resources of the APK, get the native library called libencodeV3.so (there are arm64, armeabi, and x86-64 varieties - choose whichever arch you feel most comfortable with). Open it in your favorite disassembler (I recommend Ghidra), and find the methods that match the Java native method names (they are all exported so that Java can find them, and start with Java_.... Follow the code in those methods - they should all be pretty similar, and take the values passed and run it through an encoding procedure that returns a byte array (in fact, 2 byte arrays - V2 and V3). Then jump back to the Java code, and see what's done after the native method call. I haven't verified it, but I think that at this point the V2 and V3 byte arrays are simply advertised multiple times.

Once you know how to build the BLE advertising data for each method you want to implement, it's time to jump back to the ESPHome component code and develop. Create the fan component in Python and add the corresponding C++ implementation. You can use the code for lamps for reference. The trickiest part is the encoding procedure in libencodeV3, that generates the byte array - decompilers usually fail to create proper code for it, so you'll have to play around to get a working implementation - that's where the multiple architectures come in handy (some may end up with better decompilation results than others). Note that if the current code in the repository works with the lamp part of the fan, I believe it means that the encoding that's already implemented here is the same, and you should be able to use it in your code.

Good luck!

sssushi commented 4 months ago

Hello, I tried your code to control my ceiling fan…. Light works like a charm…. However the Fan controlling would be really great. It would be worth a good donation from my side…. Anyone had luck to implement the commands ? The Fan would be even more important than the light because there is no other solution like bluetooth and remote.