konsumer / tplink-lightbulb

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

Beginning of WiFi management #56

Closed sergimn closed 3 years ago

sergimn commented 3 years ago

Solves #55

By adding the ability to control the WiFi features of the devices, the need for the Kasa App is completely removed for the setup process. I will try to add 3 features, both in the library and the cli:

konsumer commented 3 years ago

Looking good so far!

Should we name it something more different than scan() like maybe listwifi() or even just wifi()?

sergimn commented 3 years ago

Sure, I'll change it on the next iteration. This way there will be less confusion :slightly_smiling_face:

sergimn commented 3 years ago

I'm not confident that 7ecbd0a works and I'm unable to test it properly at the moment, could you give it a try? The current behavior is to not give any errors but it doesn't connect to the AP I tell it to soo :shrug: . I think that this command may only work if the device is in setup mode, when it creates the AP for the user to configure.

konsumer commented 3 years ago

I wrote this as an initial test:

const TPLSmartDevice = require('./build/lib')

TPLSmartDevice.scan()
  .on('light', async light => {
    try {
      const wifi = await light.listwifi()
      console.log(`${light.name} (${light._sysinfo.model}): found ${wifi.length} wifi`)
    } catch (e) {
      console.error(`${light.name} (${light._sysinfo.model}): ERROR: ${e.message}`)
    }
  })

and I get TypeError: Cannot read property 'ap_list' of undefined on many of them. A couple on my network are working, though!

Entryway (HS200(US)): ERROR: Cannot read property 'ap_list' of undefined
Porch (HS200(US)): ERROR: Cannot read property 'ap_list' of undefined
livingroom (LB130(US)): found 7 wifi
Tin Lamp (LB120(US)): found 5 wifi

livingroom and Tin Lamp are actual lightbulbs, and Porch and Entryway are lightswitches (I included model-number in output). They are in different parts of the house, which accounts for the difference in wifi-counts, I think.

For livingroom I tested setting wifi with this code:

const TPLSmartDevice = require('./build/lib')

async function main () {
  const light = new TPLSmartDevice('192.168.86.235')
  console.log(await light.connectwifi('SECRET', 'SECRET', 3, 2))
}
main()

It doesn't error, but subsequent scans on the same network continue to show it (so it doesn't seem to be updating settings.) I think this verifies your assumption about "setup mode". I can try a half-manual process like this, in a bit:

konsumer commented 3 years ago

Noticing also the ones that don't support it, return this:

{
  'smartlife.iot.common.softaponboarding': { err_code: -1, err_msg: 'module not support' }
}

I did set these up with kasa app, so there must be some way to do that. Once we get wifi setup working for the bulbs, I can switch to trying to reverse-engineer that.

I'm actually having trouble getting a bulb to revert to factory mode (been switching it off/on like mad) but I will keep trying.

konsumer commented 3 years ago

Ok, did manual test. reset Tin Lamp and switched computer to that wifi network. now, when I log the light, I get is_factory: true, as I should.

I ran similar connectwifi code to above (after also testing listwifi) and both worked well. After I did setup it connected to correct wifi with a new name TP-LINK_Smart Bulb_XXXX.

So I'm going to say it works.

sergimn commented 3 years ago

and I get TypeError: Cannot read property 'ap_list' of undefined on many of them. A couple on my network are working, though! Noticing also the ones that don't support it, return this:

This repo suggests using netif instead of smartlife.iot.common.softaponboarding. Try to change the library manually to see if it works and we'll find a way to make it compatible with the two kinds of endpoints.

I'm actually having trouble getting a bulb to revert to factory mode (been switching it off/on like mad) but I will keep trying.

If you have the app available, press on the gear button inside one of the devices and at the bottom there should be a red button to reset the device to factory settings. I had the .pcap that had the command to actually reset the devices but I lost the file. I'll try to do it from memory.

konsumer commented 3 years ago

If you have the app available, press on the gear button inside

I ended up getting it, just had to leave it off/on for like 3secs each time. It's a little finicky.

konsumer commented 3 years ago

This repo suggests using netif instead of smartlife.iot.common.softaponboarding

Yep, that worked for Porch on my network. We can put a similar fail-through on it, maybe after we get this merged.

konsumer commented 3 years ago

I'm ready to merge, and then I (or you, if you want) can add a fail-through on netif. I will note that the returned data from netif doesn't seem to include cypher_type, but maybe that is ok.

konsumer commented 3 years ago

Another sidenote: netif worked on all my devices, so maybe that is a better default.

sergimn commented 3 years ago

Another sidenote: netif worked on all my devices, so maybe that is a better default.

If that's the case, I agree that it seems better. However, the cypher_type is needed for connectwifi so I'm not sure what to do

I'm ready to merge

There is still some work left to do. I would like to add an unpairing feature and put the features to the cli, but I'm not sure how to generate a binary

sergimn commented 3 years ago

Regardless, before merging, let me clean the commits

konsumer commented 3 years ago

However, the cypher_type is needed for connectwifi so I'm not sure what to do

We might be able to leave it out. I have noticed this with other endpoints: they don't always need all the params. There might also be a default value that works (like they are all 2 in my neighborhood.)

Regardless, before merging, let me clean the commits

Yep, no prob. Let me know when you feel good about it, and I'll merge. I will probly add a few little things (run it through standard format, make netif default, etc.) We don't have to do it all in this PR, either way.

sergimn commented 3 years ago

I'm comfortable with the current code and commit messages but I would still like to add the cli implementation and the unpairing. We can do it in another PR or in this one. Either way I won't have good access to a TPLink device until next week

konsumer commented 3 years ago

Ok, I will merge, run some formatting and get this published. If you want to focus on the API-side to get the reset-signal, I think we should do the CLI stuff separate, still. It would make it really fancy to use something like inquirer, which isn't otherwise used, but I think with a little user-input ("please switch to the setup wifi, which looks like TPKLINK-DEVICE-XXX, and press enter") we can probly do it all without a wifi lib (since the device itself can list available wifi.)

konsumer commented 3 years ago

that other repo leaves off cypherType, so it might be fine.

konsumer commented 3 years ago

I've added a few things: 2 CLI commands for wifi, API docs, code cleanup, etc.

konsumer commented 3 years ago

I also added more to the docs. It should be ready for more additions, if you want to. I also added new binary CLI releases with the new commands.

sergimn commented 3 years ago

Perfect, I'll look into it next week :smile: