Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for updating firmware for smart plugs? #577

Open
mxr opened this issue Dec 8, 2023 · 13 comments
Open

Support for updating firmware for smart plugs? #577

mxr opened this issue Dec 8, 2023 · 13 comments
Labels
enhancement New feature or request

Comments

@mxr
Copy link

mxr commented Dec 8, 2023

Hello. I use python-kasa through Home Assistant. Would you consider having methods to query, download, & install the latest firmware for smart plugs? Then (hypothetically) the HA integration could use them to check for newer firmware updates periodically. I did find get_available_firmwares but wasn't sure it is related. Thanks

@rytilahti
Copy link
Member

rytilahti commented Dec 8, 2023

From the looks of it, that's indeed possible but hasn't been implemented :-) I just did some googling and stumbled upon this: https://community.home-assistant.io/t/how-to-use-homeassistant-to-update-tp-link-kasa-devices/474097 and the necessary commands have also been documented in the softScheck's reverse engineering notes linked in the README of this repository.

IIRC I tested the get_available_firmwares at some point and it listed the download URLs, so adding update platform for homeassistant would require (at minimum) 1) adding the necessary methods into python-kasa (download_firmware, update_progress and flash_firmware (maybe? the softscheck says it's needed, the guide on the homeassistant community forums says the device flashes the downloaded firmware automatically)) and 2) implementing update entity in homeassistant.

PRs to do that are welcome! :-)

edit: just tested on one hs110 and here's the response for the fw list command (kasa --host 192.168.xx.xx raw-command cnCloud get_intl_fw_list):

{"fw_list": [{"fwType": 3, "fwVer": "1.2.6 Build 200727 Rel.120821", "fwReleaseDate": "2020-09-25", "fwUrl": 
"http://download.tplinkcloud.com/firmware/hs110v1_eu_1.2.6_Build_200727_Rel.120821_2020_1600998849781.bin", "fwReleaseLog": "Modifications and Bug Fixes:\n1. Optimized total performance.", 
"fwReleaseLogUrl": "undefined yet", "fwLocation": 0}]}

I'm not going to test updating for now, but I might do it at some later point just for the sake of having tried it out at least once..

@rytilahti rytilahti added the enhancement New feature or request label Dec 8, 2023
@rytilahti
Copy link
Member

rytilahti commented Dec 8, 2023

Okay, I didn't manage to refrain myself to giving it a quick try to see the outputs, so I set up a dummy server and run those commands.

Running kasa --host 192.168.x.x raw-command system download_firmware '{"url": "http://192.168.x.x:8000/foobar.html"}' makes that plug to send out an HTTP GET:

GET /foobar.html HTTP/1.1
Host: 192.168.x.x:8000
Accept: */*

Executing get_download_state returns the current download state like this:

{"ratio": 0, "flash_time": 66, "reboot_time": 20}

If the file transfer completes (at least for a dummy html file), the ratio will be 100 while those two other properties remained the original values. Maybe those are just hints for clients to wait X until trying to execute new commands.

Calling flash_firmware returns {'err_code': -19, 'err_msg': 'Firmware validate fail'} for my dummy file, so no plugs were harmed so far! :-)

While I think this should be enough information to implement the basic update functionality, it's worth testing what those commands return on a valid firmware image but I'm not going to try that out yet.

@mxr
Copy link
Author

mxr commented Dec 8, 2023

Thanks Teemu. Will try to find some time to dive into the code and implementation before year-end.

@rytilahti
Copy link
Member

Sure thing! Something to consider on the implementation, this wouldn't be something we want to check in the regular 5s update cycles we have, especially as the fw query will simply timeout after some time when the device cannot access the server. On homeassistant side, this could be something that uses its own update coordinator that checks it once a day or so.

@mxr
Copy link
Author

mxr commented Dec 9, 2023

Makes sense

@mxr
Copy link
Author

mxr commented Jan 6, 2024

Apologies, I was unable to review this before the New Year and I'm not sure I have the availability to work on it soon.

@MaxRower
Copy link

MaxRower commented Feb 7, 2024

Okay, I didn't manage to refrain myself to giving it a quick try to see the outputs, so I set up a dummy server and run those commands.

Running kasa --host 192.168.x.x raw-command system download_firmware '{"url": "http://192.168.x.x:8000/foobar.html"}' makes that plug to send out an HTTP GET:

GET /foobar.html HTTP/1.1
Host: 192.168.x.x:8000
Accept: */*

Executing get_download_state returns the current download state like this:

{"ratio": 0, "flash_time": 66, "reboot_time": 20}

If the file transfer completes (at least for a dummy html file), the ratio will be 100 while those two other properties remained the original values. Maybe those are just hints for clients to wait X until trying to execute new commands.

Calling flash_firmware returns {'err_code': -19, 'err_msg': 'Firmware validate fail'} for my dummy file, so no plugs were harmed so far! :-)

While I think this should be enough information to implement the basic update functionality, it's worth testing what those commands return on a valid firmware image but I'm not going to try that out yet.

Thanks for your info, since two of my KP115 would not successfully update from the official servers with many many retries, I downloaded the firmware from the link reported by the "cnCloud get_intl_fw_list" command, saved it to a local webserver in my lan and successfully updated the firmware from there from 1.0.16 to 1.0.20. So it actually does work!
The download_firmware command produced the following output:
WARNING:root:Deprecated, use 'kasa command --module system download_firmware'
{}

@rytilahti
Copy link
Member

Glad you got it working, and thanks a lot for reporting back!

@rct
Copy link

rct commented Feb 8, 2024

I'm very glad I stumbled on this because I was looking for a workaround to update a single device at a time.

The Kasa iOS app AFAICT only lets you upgrade all devices you own by model. Given that there is a power loss during reboot, I wanted to be able to take steps to protect (safefy shut down) the connected device) before upgrading.

I had 6 EP25's that need upgrading because the 1.0.10 firmware can cause spurious reboots when it loses connection to the TPlink cloud.

So what I would up doing in case it helps anyone who finds this follow along

# Get list of available firmware updates
$ ~/.local/bin/kasa --host $myhost raw-command cnCloud get_intl_fw_list  > /tmp/fw
WARNING:root:Deprecated, use 'kasa command --module cnCloud get_intl_fw_list'

# view available firmware Note, need to ignore 1st line "No --type or --device-family and --encrypt-type defined, discovering.."
# There should generally only be one firmware update available
$ tail -n +2 /tmp/fw | jq .
{
  "fw_list": [
    {
      "fwReleaseLog": "Modifications and Bug Fixes:\n1. Enhanced device security.\n2. Improved stability and performance.",
      "fwVer": "1.0.13 Build 231108 Rel.162846",
      "fwReleaseDate": "2023-12-05",
      "fwType": 2,
      "fwUrl": "http://download.tplinkcloud.com/firmware/KP125_FCC_1.0.13_Build_231108_Rel.162846_2023-11-08_16.33.15_1701761975388.bin",
      "fwTitle": "Hi, a new firmware with performance improvement is available for your EP25.",
      "fwLocation": 0,
      "fwReleaseLogUrl": "undefined yet"
    }
  ]
}


# tell device to download firmware
$ ~/.local/bin/kasa --host $myhost raw-command system download_firmware '{"url": '$( tail -1 /tmp/fw | jq .fw_list[0].fwUrl)'}'
No --type or --device-family and --encrypt-type defined, discovering..
WARNING:root:Deprecated, use 'kasa command --module system download_firmware'
{}


# check status
$ ~/.local/bin/kasa --host $myhost raw-command system get_download_state
No --type or --device-family and --encrypt-type defined, discovering..
WARNING:root:Deprecated, use 'kasa command --module system get_download_state'
{"status": 0, "ratio": 0, "reboot_time": 5, "flash_time": 5}

@mxr
Copy link
Author

mxr commented Feb 12, 2024

Glad you got it working, and thanks a lot for reporting back!

I think you're confusing @MaxRower and me 😅

@brandongalbraith
Copy link

As someone who has been wrestling with trying to get HS200 switches to upgrade (V5, FW 1.0.2) after they've been sitting in a box for several years, this thread has been hugely helpful after trying for hours with the Kasa iOS app. I wanted to add a suggestion based on my experience: for an upgrade process, consider an option to attempt a preflight/test retrieval of the firmware binary from the command line before instructing the device to attempt to retrieve it.

Thank you for all of the work that has gone into this project, it is amazing to have stumbled upon it in troubleshooting rage 🤣

@cjbaar
Copy link

cjbaar commented Apr 1, 2024

Thanks for the updates on this. I am also trying to download new firmware, but getting an error message I cannot find any info on. Is anyone familiar with this issue or what it means?

kasa command --module system download_firmware '{"url":"http://download.tplinkcloud.com/firmware/assigned/HS220_FCC_1.0.10_Build_230919_Rel.025055_2023-09-19_17.54.05_1695175239050.bin"}'
Got error: SmartDeviceException("Error on system download_firmware: {'err_code': -44, 'err_msg': 'In use by other client'}")

@cjbaar
Copy link

cjbaar commented Apr 1, 2024

OK; after playing with this more, I discovered that the get_download_state command was returning status: 1, so it seems like some previous download attempt was just stuck. I rebooted the switches, and was able to successfully run the download_firmware command.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

6 participants