konsumer / tplink-lightbulb

Control TP-Link smart lightbulbs from nodejs
MIT License
191 stars 32 forks source link

Adding wifi setup functionality #55

Closed sergimn closed 3 years ago

sergimn commented 3 years ago

Another good feature would be to add the capability of connecting the devices to a WiFi network, thus removing the necessity of the Kasa app for setting up the device

konsumer commented 3 years ago

Can you do some traffic analysis of the setup process?

sergimn commented 3 years ago

Unfortunately, this feature came to my mind as I have no means to do the setup without a smartphone. When I get access to one I can upload a .pcap file or even take a look at it (I guess the process won't be complicated?) but it may take some weeks :(

konsumer commented 3 years ago

I am pretty busy with other stuff right now, so I probably won't have time to get to this, anytime soon.

It's a bit tricky to record because it has it's own wifi you connect to, to set it up, so you'd need to capture the traffic on a phone (or a computer attached to the setup network, before the setup routine is run.) It may be very tied to kasa-servers (like it's totally possible the devices do not allow anything too advanced without talking to kasa servers.)

This lib doesn't use kasa once the light is setup, though, it interacts with the devices directly, over wifi. I made another lib that does use kasa, if you want that (allows remote interaction, if you are not on the local network.) So, an alternative approach might be to connect your computer to the device's setup-wifi and control it from there. it would mean using a separate setup-wifi (not authenticated!) for each light, which sounds like a terrible idea, but might be fun for experimenting.

sergimn commented 3 years ago

No problem, I'll try to look into it myself even though I've never done anything in JS. I know some networking, so that part won't be a problem.

I've seen your other library and it's quite interesting but it doesn't fit my necessities right now because I have a bulb that isn't connected anywhere

which sounds like a terrible idea

Yep, it does hahaha. I don't mind having it open while I test (at the end of the day there is no workaround) but definitely I'm not going to use this solution. I guess I'll have to look into it myself

konsumer commented 3 years ago

What is the other library? If they have this functionality, I can take a look at it.

sergimn commented 3 years ago

There is no other library, I meant your library, the one you linked in your comment :slightly_smiling_face:

sergimn commented 3 years ago

Ok so thanks to the wonderful developers of Wireshark TP-Link filters I got it. It doesn't seem too difficult to implement as long as TP-Link hasn't set up artificial barriers for making it difficult. I'll try to do it next week. The current plan is to add three functionalities:

Do you have any specific names you would like to call the functions to call this? Or any advice in general?

konsumer commented 3 years ago

That is great news!

Sounds like it may be very tricky for cross-platform wifi-control.

I found these:

I have no experience with either, so we should just pick whichever is easier to accomplish our goals.

Do you have any specific names you would like to call the functions to call this? Or any advice in general?

I am thinking this may be nice as a separate script, that we keep in same repo, to help people out, so main lib doesn't gain a wifi-lib dep, but also it would be a cool feature for the CLI, so I'm totally fine with whichever wifi-lib you get working. I bet using send() from this lib would help with the actual comm.

After that I would maybe suggest this flow, based on what wifi-libs can do:

A simple snippet to send a direct command to a all devices on a current wifi network would be similar this:

import TPLSmartDevice from 'tplink-lightbulb'

// setup every light on current wifi
TPLSmartDevice.scan()
  .on('light', light => {
    // I dunno what this is, use what you learned
    const setup_stuff = {

    }
    // this does the encryption/json for you
    light.send(setup_stuff)
  })

// OR

// if it only has one IP:
const light = new TPLSmartDevice('10.0.0.1') // or whatever the IP is

const setup_stuff = {
}

light.send(setup_stuff)

use node -r esm yourscript.js to run this without a need for babel (to handle import and stuff)

If you work it out (or share what you discovered here) I can just add it to the CLI, even though I'm busy. it's a cool feature, and it should go pretty quick if you've done all the research.

konsumer commented 3 years ago

Also, I forgot to mention, but I can do traffic analysis of setup process. I totally forgot you are without phone to do it, and it's super-useful to verify how the legit traffic looks.

konsumer commented 3 years ago

We might even be able to use androiddump to capture from a real android device.

sergimn commented 3 years ago

Hey :slightly_smiling_face:

My plan wasn't so ambitious, I was thinking on relying on the user manually connecting to the open WiFi network TP-Link devices create on setup to interact with it, keeping the library simple. The good think about this is that TP-Link devices have a DHCP server and the devices themselves always have the IP 192.168.0.1, thus making the setup process quite easy. We could also call scan under the hood to make sure we have the correct IP or allow the user to manually set a destination IP (as all other commands allow)

The problem (if you could even call that a problem) with what you proposed with mangling WiFi settings is that the user would need to give root permissions for some steps as getting the password of the saved networks is not something you can do in with normal user permissions.

The plan is to do something as you pointed out in your code snippet and put correct command for the bulb to list their accessible AP's and connect to one of those.

The JSON to send for connecting to one AP should look like something like this, but please, let me do the pull request, it will be my first code contribution to a project ^^

{
    "smartlife.iot.common.softaponboarding": {
        "set_stainfo": {
            "cipher_type": 2,
            "key_type": 3,
            "password": "12345678",
            "ssid": "MyWiFi"
        }
    },
    "context": {
        "source": "xxx-xxxx-xxxx-xxxx-xxxx-xxxx"
    }
}

I already got a smartphone to the traffic analysis (well, with the help of Wireshark and monitor mode). That's how I got the data so I will not do this blindly but when I have an implementation it would be nice to test with more devices and make sure it doesn't break anything.

use node -r esm yourscript.js to run this without a need for babel (to handle import and stuff)

I know nothing about JS development but thanks for the tip :smiley:

sergimn commented 3 years ago

I just did a test with tplight raw and the device connected to my WiFi, so it seems like it won't be a problem to implement :smiley:

konsumer commented 3 years ago

The problem (if you could even call that a problem) with what you proposed with mangling WiFi settings is that the user would need to give root permissions for some steps as getting the password of the saved networks is not something you can do in with normal user permissions.

Ah yes, this is a good consideration. Again, maybe as a separate script this would be helpful to people. They could always run sudo node SCRIPT and we could just keep it totally separate from the main CLI.

I just did a test with tplight raw and the device connected to my WiFi, so it seems like it won't be a problem to implement

That is very good news! It might be possible to just write the whole thing as a bash/batch script, if you wanted to. Like you could just tell the user to do stuff that requires extra perms like echo "ok, switch to tplight-WHATEVER wifi, now, and hit enter here to continue" that kind of thing. After that you can use tplight raw to do stuff. I dunno, go with whichever feels more comfortable (js or shell script or whatever.)

The JSON to send for connecting to one AP should look like something like this, but please, let me do the pull request, it will be my first code contribution to a project

Of course! This is all you. You got it.

konsumer commented 3 years ago

I think I'm going to close this issue for now, as we have commands & api-functions to do basic wifi setup. If you want to write a script, or add some wiki directions about it, that'd be great, but not totally required. Thanks for the great PR!