How-to – IT Nerd Space http://itnerd.space Blog about Cloud, Automation, Android, Smart things... Thu, 27 Jul 2017 22:59:31 +0000 en-US hourly 1 https://wordpress.org/?v=4.7.5 https://i2.wp.com/itnerd.space/wp-content/uploads/2016/10/cropped-99789e30b0a6eac11f33246750ca29f9.jpg?fit=32%2C32 How-to – IT Nerd Space http://itnerd.space 32 32 133306427 Looking back and Forward: Coming soon to this blog http://itnerd.space/2017/07/27/looking-back-and-forward-coming-soon-to-this-blog/ http://itnerd.space/2017/07/27/looking-back-and-forward-coming-soon-to-this-blog/#respond Thu, 27 Jul 2017 21:19:35 +0000 https://itnerd.space/?p=361 I started this blog writing a series of articles about Azure App Service Architecture, mainly trying to explain and illustrate how I understand it works, beyond what one can find publicly in Microsoft (extensive) documentation. Then I got an HS100 TP-Link smartplug: a “connected thing”, a plug that is connected to Internet (don’t say that to any person, most will look at you like o.0?!), a plug that you can control from an App on your phone, from wherever you are: at home, or from outside: from anywhere in the world. And  I guess Oops I did it again!

Interface the HS100 with everything

I couldn’t resist to imagine many potential applications and possible integrations with online (cloud) services that are publicly and freely available, like IFTTT; I’m also a big fan of Android Tasker, Node-Red, the MQTT pub/sub protocol, and Raspberry Pi / NodeMCU hooked with sensors and hardware pieces attached on the GPIO pins) that make more connected things, so literally ideas are all over the places in my heads, on papers, in Keep notes…

Like this one that just popped in my mind:

Switch off the main lights in the salon, dim the lights around the sofa and TV, power on the media server box (smartplug) and TV when I sit on the sofa, with a NodeMCU controller and a pressure sensor (FSR)! Or maybe I’d prefer to have all that triggered when I power on the TV, but only in a certain time slot?…

Told you I have crasy ideas ;). Totally got to try to do that BTW!

Error: Time not found

What I only lack really is time. First, time to try and make some of those idea work (they do eventually with perseverence and I always learn a lot in the process), then time to write about them (here).

I didn’t realize the time it take to write articles people need to write good articles. I usually take notes of what I do, notes that I understand, but publishing those is no value to anyone. You need to structure the ideas, give them some form so the result make sense for the reader, enough at least so they can be inspired in trying also themselves to do, learn and make something that work for them out of what I wrote. Unfortunately due to the lack of time, I don’t enter into too much details, and I assume the reader is tech-savvy enough to read, understand and try by himself. That means some reader gets frustrated because I missed some parts they didn’t know… Sorry about that.

Wins so far

Back to the HS100: there were some (very good) resources publicly available already out there that showed how to interact with an HS100 plug, from shell scripts based on cURL, php and python libraries or Node.js modules, even a Node-Red. But they all had the same problem: they only worked withing the same local network (WiFi/LAN) the plug was connected to. Ugh bummer.

The Kasa App and the Alexa integration were proof that TP-Link was hosting a cloud service, but no API was publicly available yet.

So I started to work on figuring out how the App talked to the TP-Link Cloud endpoint, and started to publish it here. The series got (modestly) popular among the maker and tinkerers ;), and people used the comments to exchange ideas, issues, and come with solutions. So far, I’ve published (not in chronological order)

So far the whole process was rather hacky and manual I reckon, but still one could achieve the goal of switching a smartplug from a remote place (outside of the smartplug local network), like from one’s smartphone (Tasker), or an IFTTT recipe. It already enabled some cool logics.

Pitfalls: what about scenes?

Soon after having found out how to trigger one TP-Link HS100 smartplug, the most frequently asked question in the comments has been ¿how can I power On/Off multiple devices from ITFFF?

After all it’s a feature that people know from the Kasa App: you define buttons in the app that will put several of you smartplugs in a state you define.

Related to my idea above, a scene would be:

“Time to watch some TV” scene: Switch off the main lights in the salon, dim the lights around the sofa and TV, power on the media server box (smartplug) and TV.

You can define that in Kasa, but what about calling it from IFTTT? You can’t. You can only call one POST call (via Maker), in an IFTTT recipe.

The second to most request in the mind of all is probably related to the TOKEN that will eventually expire sooner of later, making it a hassle to edit all your IFTTT Recipes/Tasker tasks/whatever scripts… manually!

Well, I’m happy to say this was until now!

More Wins coming soon…

This week I’ve been working hard on this (it’s the second time I try it, and this time I made it!).

This is what I have done:

  • I’ve created a node.js module to easily interact (power On/Off, get state) with any number of HS100/HS110 smartplugs and LB100/LB110/LB120 and LB130 smartbulbs (set on/off, set brightness, set color). The module handles the login, token retrieval, and device triggering, in almost no call.
  • I’ve created a Glitch example app in which one can define scenes. As Glitch publishes a URL, you can then trigger one “scene” with only one call (http://url.glich.me/scene1/) and with only one POST call it will do whatever you want to! Not only that but you can even define as many scenes as you want in a single Glitch app ( each with a different end-point: http://url.glich.me/scene2/, http://url.glich.me/scene3/…).
  • Next I will create a library of new TP-Link Node-Red nodes to control the smartthings from Node-Red!

All that is already working fine for me, so this is what I’ll talk about in next posts (and I’ll publish the code for everything 😉 ) when I get some more time to talk about it. (Believe it or not, it took me more than two hours to write this post)!

So, stay tuned if you are interested. I suggest you follow me on Twitter, and follow this blog, recommend on Disqus (the heart icon).

Ah and well… all this is free, but you might see some interesting (or not) Ads around my content. I won’t mind if you all start clicking everywhere. I’m not suggesting anything… :p

]]>
http://itnerd.space/2017/07/27/looking-back-and-forward-coming-soon-to-this-blog/feed/ 0 361
How to authenticate to TP Link cloud API with Tasker http://itnerd.space/2017/06/19/how-to-authenticate-to-tp-link-cloud-api-with-tasker/ http://itnerd.space/2017/06/19/how-to-authenticate-to-tp-link-cloud-api-with-tasker/#respond Mon, 19 Jun 2017 23:03:06 +0000 http://itnerd.space/?p=356 We’ve seen in a previous post what is the protocol to authenticate to TP Link cloud API. Now, what about doing that from Tasker you can ask me? Well, that’s very simple actually!

To implement that in Tasker I have used RESTask for Tasker (because I had troubles having the native HTTP Post action work for me):

RESTask for Tasker (Free, Google Play) →

Next create 3 global variables in Tasker (self-explanatory I guess):

  • TPLUSER
  • TPLPASS
  • TPLTERM (use the UUIDv4 you got above)

Then create a new Task with the following 4 actions:

The first action will be a Variable Set %payload:

Name:%payload
To: { "method" :"login",
"params" : {
  "appType" :"Kasa_Android",
  "cloudPassword" :"%TPLPASS",
  "cloudUserName" :"%TPLUSER",
  "terminalUUID" :"%TPLTERM" } }

The second action will be the RESTask call:

Further down we need to set the custom body to %payload:

Then we set the Headers:

The third action will be a Javascriptlet with the following code, to extract the token (from the rtres, passed from  RESTask) to the %mtoken variable:

var mtoken = JSON.parse(rtres).result.token;

Finally, here the fourth action will just be a Flash action, that will show the token:

Flash [ Text:%mtoken Long:On ]

The whole task should end up looking like this:

You can run the Task and it should flash the token on the screen!! Yay

]]>
http://itnerd.space/2017/06/19/how-to-authenticate-to-tp-link-cloud-api-with-tasker/feed/ 0 356
How to authenticate to TP-Link cloud API http://itnerd.space/2017/06/19/how-to-authenticate-to-tp-link-cloud-api/ http://itnerd.space/2017/06/19/how-to-authenticate-to-tp-link-cloud-api/#comments Mon, 19 Jun 2017 23:01:45 +0000 http://itnerd.space/?p=345 This is breaking news! No need to hack into your phone’s backups any more to obtain the TP-Link token!

First you need to generate an UUID v4. You can open https://www.uuidgenerator.net/version4 and pick the one they give you there (no need to create one every time, one is fine, just keep it). This will represent your Client Term ID (like the one of your Kasa App).

Now this is how you can authenticate to the TP Link cloud backend and obtain a token:

We have to do a POST request to https://wap.tplinkcloud.com, with the following payload:

{
 "method": "login",
 "params": {
 "appType": "Kasa_Android",
 "cloudUserName": "XXXXX",
 "cloudPassword": "XXXXX",
 "terminalUUID": "MY_UUID_v4"
 }
}

In the payload, replace cloudUserName and cloudPassword with your TP-Link (or Kasa) credentials, and the terminalUUID with the one you got above.

Remember to pass the Header Content-Type: application/json as well.

No need to have any extra tool, you can simply try it with Hurl.it from your browser:

What you’ll get should look like this:

{
 "error_code": 0,
 "result": {
 "regTime": "2017-01-06 08:42:35",
 "email": "XXXXX",
 "token": "YOUR_TOKEN_HERE"
 }
}

Isn’t that cool? Of course you can implement that in any language, Shell script with cURL, Python, Node.js,… Your token is response.result.token.

In a next post I’ll show how to do the same with Tasker! 😀

From here you can also have a look at this post: Get the end point URL and HS100 Device ID.

]]>
http://itnerd.space/2017/06/19/how-to-authenticate-to-tp-link-cloud-api/feed/ 19 345
Remotely control your HS100 timer (API) http://itnerd.space/2017/06/05/remotely-control-your-hs100-timer-api/ http://itnerd.space/2017/06/05/remotely-control-your-hs100-timer-api/#comments Mon, 05 Jun 2017 18:43:38 +0000 http://itnerd.space/?p=334 Thanks to a comment by Jacob K. on a previous post, I looked into how to set/unset the HS100 plug timer via the TP-Link API call.

To replay the steps below, be sure to already have:

In the next step, I recommend you use Hurl.it service to test the API calls, it’s the easiest way.

First let’s retrieve the timer Rule ID

Destination:

Body:
{“method”:”passthrough”, “params”: {“deviceId”: “YOUR_DEVICE_ID_HERE”, “requestData”: “{\”count_down\”:{\”get_rules\“:null}}” }}
 Then hit the Launch Request button. The result body should look like this:
{“error_code”:0,”result”:{“responseData”:”{\”count_down\”:{\”get_rules\”:{\”rule_list\”:[{\”enable\”:0,\”id\”:\”YOUR_RULE_ID_HERE\”,\”name\”:\”\”,\“delay\”:1800,\”act\”:0}],\”err_code\”:0}}}”}}
Have a look at the id field! I call it the Rule Id (YOUR_RULE_ID_HERE). we’ll need it in the next step. I would say it never changes but I am not sure.

Now you can enable/disable the timer like this:

Destination:
Body:
{“method”:”passthrough”, “params”: {“deviceId”: “YOUR_DEVICE_ID_HERE”, “requestData”: “{\”count_down\”:{\”edit_rule\“:{\”name\”:\”\”,\”act\”:0,\”enable\”:1,\”id\”:\”YOUR_RULE_ID_HERE\”,\”delay\”:1800}}}” }}
Use the following values in your body:
  • act: (action)
    • Use 0 to power off the plug after the timer
    • Use 1 to power on the plug after the timer
  • enable:
    • Use 0 to disable the timer
    • Use 1 to enable the timer
  • delay:
    • timer delay in seconds

Have fun!!

]]>
http://itnerd.space/2017/06/05/remotely-control-your-hs100-timer-api/feed/ 1 334
Control your TP-Link HS100 smart plug from your Android Watch! http://itnerd.space/2017/04/03/control-your-tp-link-hs100-smart-plug-from-your-android-watch/ http://itnerd.space/2017/04/03/control-your-tp-link-hs100-smart-plug-from-your-android-watch/#respond Mon, 03 Apr 2017 22:11:01 +0000 http://itnerd.space/?p=254 In this post I’ll show how I control my TP-Link HS100 smart plug right from my LG G Watch R Android smart watch, from anywhere, which is very handy.

The first thing we need is the ability to control the HS100 smart plug from Tasker on our Android phone. If you haven’t already, be sure to check my preview post where I explain how to create two Tasker Tasks, that will turn our plug On and Off.

For the next step I’ll use the WearTasker: with this app you can choose some of your Tasker tasks and publish them on your watch. They will show as buttons when you open WearTasker on your wrist, and the corresponding task will run when pressed. Quite simple. TBH WearTasker  feels like a natural extension of Tasker to Android Wear.

WearTasker - Tasker for Wear (Free+, Google Play) →

You can buy a Pro in-app purchase if you’d like, which unlocks some cool features, but what I use here works with the free version.

So let’s publish both our smart plug tasks. Open Wear Tasker on your phone, and create a new shortcut. Choose your “Power On Plug” task, and name it however you like. You can also select an icon and a color. Then repeat the same operations with the other task:

 

Back to the app, it should now look like this:

And that’s how it will look on your watch:

Now try to press one of the Task and see how your HS100 smart plug responds!

I love WearTasker. I find it extremely usefull to be able to call Tasker tasks from my watch. Some other tasks I have there are one to power off my home server, one to refresh my Plex library, and one to send a Whatsapp to my wife with my current location and current route ETA.

]]>
http://itnerd.space/2017/04/03/control-your-tp-link-hs100-smart-plug-from-your-android-watch/feed/ 0 254
Control your TP-Link HS100 smartplug with Tasker http://itnerd.space/2017/02/26/control-your-tp-link-hs100-smartplug-with-tasker/ http://itnerd.space/2017/02/26/control-your-tp-link-hs100-smartplug-with-tasker/#comments Sun, 26 Feb 2017 13:56:25 +0000 http://itnerd.space/?p=252 We’ve seen in a previous post how to switch our TP-Link HS100 smartplug from command line, from anywhere (not only the local network). In this post we’ll see how to create some Tasker tasks to control our smartplug. From that, we can imagine any useful/crazy profiles triggered from any events, time, location and switch the plug On/Off, for example “when I arrive home, switch on the Christmas Tree…” 🙂

To quickly recap, this is the command that can change the plug state (depending on the %state variable, 0: switch off, 1: switch on):

curl --request POST "https://eu-wap.tplinkcloud.com/?token=%token HTTP/1.1" \
  --data '{"method":"passthrough", "params": {"deviceId": "%deviceId", "requestData": "{\"system\":{\"set_relay_state\":{\"state\":%state}}}" }}' \
  --header "Content-Type: application/json"

Task 1: Switch Plug On 💡

Using an HTTP Post action

In Tasker let’s create a new Task called “Switch Plug On 💡”, then add  3 “Variable Set” actions, to set the value of %deviceId, %token and %state to the right values for you.

Then we’ll use an HTTP Post action, that we’ll configure like this:

  • Server:Port: https://eu-wap.tplinkcloud.com
  • Path: ?token=%token
  • Data / File: {“method”:”passthrough”, “params”: {“deviceId”: “%deviceId”, “requestData”: “{\”system\”:{\”set_relay_state\”:{\”state\”:%state}}}” }}
  • Timeout: 30
  • Content Type: application/json

Note: Remember to change the URL above to the one that works for you (check the Common Issues section at the end of first post and its comments).

The resulting Tasker Task will look like this:

In text form, it looks like this:

Switch Plug On 💡 (143)
 A1: Variable Set [ Name:%deviceId To:YOUR_DEVICE_ID_HERE Recurse Variables:Off Do Maths:Off Append:Off ] 
 A2: Variable Set [ Name:%token To:YOUR_TOKEN_ID_HERE Recurse Variables:Off Do Maths:Off Append:Off ] 
 A3: Variable Set [ Name:%state To:1 Recurse Variables:Off Do Maths:Off Append:Off ] 
 A4: HTTP Post [ Server:Port:https://eu-wap.tplinkcloud.com Path:?token=%token Data / File:{"method":"passthrough", "params": {"deviceId": "%deviceId", "requestData": "{\"system\":{\"set_relay_state\":{\"state\":%state}}}" }} Cookies: User Agent: Timeout:30 Content Type:application/json Output File: Trust Any Certificate:Off ]

Using a Run Shell action (2nd way)

If you have curl available from the command line on your Android phone, you can alternatively use a Run Shell action, instead of the HTTP Post action.

In this case, the Tasker Task would look like this:

And in text form it would read like this:

Switch Plug On 💡 (143)
 A1: Variable Set [ Name:%deviceId To:YOUR_DEVICE_ID_HERE Recurse Variables:Off Do Maths:Off Append:Off ] 
 A2: Variable Set [ Name:%token To:YOUR_TOKEN_ID_HERE Recurse Variables:Off Do Maths:Off Append:Off ] 
 A3: Variable Set [ Name:%state To:1 Recurse Variables:Off Do Maths:Off Append:Off ] 
 A4: Run Shell [ Command:curl --request POST "https://eu-wap.tplinkcloud.com/?token=%token HTTP/1.1" --data '{"method":"passthrough", "params": {"deviceId": "%deviceId", "requestData": "{\"system\":{\"set_relay_state\":{\"state\":%state}}}" }}' --header "Content-Type: application/json" Timeout (Seconds):0 Use Root:Off Store Output In: Store Errors In: Store Result In: ]

Task 2: Switch Off Plug

Once you have the Switch On task working, you can simply clone it in Tasker and change the %state variable to 0, and that will give you the “Switch Off Plug” task!

Profiles ideas

Do not hesitate to contribute in the comments with any Profile idea you have to play with your TP-Link HS100 smartplug.


You can acquire Tasker from the Play Store, personally I believe it’s really worth the money. You can also download a 7 days free trial from Tasker official website.

Tasker (€2.99, Google Play) →

In a next post I’ll show how you can control your smart plug from your Android smartwatch, which is super cool!

]]>
http://itnerd.space/2017/02/26/control-your-tp-link-hs100-smartplug-with-tasker/feed/ 2 252
How to remotely get the state of your HS100 smart plug http://itnerd.space/2017/01/29/get-the-state-of-your-hs100-smart-plug/ http://itnerd.space/2017/01/29/get-the-state-of-your-hs100-smart-plug/#comments Sun, 29 Jan 2017 18:29:49 +0000 http://itnerd.space/?p=223 In previous posts we’ve seen how to remotely switch On/Off our TP-Link HS100 smart plug, and how to control it with IFTTT. In this post we’ll see how we can remotely obtain the state of the HS100 relay: On or Off, from command line. I even do it with Tasker for Android!

Please be sure to refer to this post if you are unsure how to obtain the Token and DeviceID that are necessary to control the plug via TP-Link cloud service.

TL;DR: The one-liner below, run in a Linux/Android/Mac shell, will return ON or OFF, indicating what is the state of an HS100 relay:

curl -s --request POST "https://wap.tplinkcloud.com/?token=TOKEN_HERE HTTP/1.1"\
 --data '{"method":"passthrough", "params": {"deviceId": "DEVICEID_HERE", "requestData": "{\"system\":{\"get_sysinfo\":null},\"emeter\":{\"get_realtime\":null}}" }}'\
 --header "Content-Type: application/json" | grep -q '..relay_state..:1' && echo "ON" || echo "OFF"

I’ve put this line above in a Tasker shell action, and I can perfectly obtain my HS100 state from Tasker now! So cool.

For the one wondering what we can obtain with the get_sysinfo command: run the following line. Here I extract from the Json output the responseData field, which contains the interesting payload, I unescape it with sed, and pretty-format it using json_pp:

curl -s --request POST "https://wap.tplinkcloud.com/?token=TOKEN_HERE HTTP/1.1"\
  --data '{"method":"passthrough", "params": {"deviceId": "DEVICEID_HERE", "requestData": "{\"system\":{\"get_sysinfo\":null},\"emeter\":{\"get_realtime\":null}}" }}'\
  --header "Content-Type: application/json" | jq ".result.responseData" | sed -e 's#\\\"#"#g; s#^\"##; s#\"$##' | json_pp

The output would be something like this. I’ve masked most of the data for obvious privacy reasons, but you can still get the idea. We see the position, time the device was On, MAC Address, Model, Alias (custom name)…

{
 "system" : {
 "get_sysinfo" : {
 "fwId" : "FWID_HERE",
 "relay_state" : 1,
 "dev_name" : "Wi-Fi Smart Plug",
 "oemId" : "OEMID_HERE",
 "on_time" : 451,
 "model" : "HS100(EU)",
 "icon_hash" : "",
 "updating" : 0,
 "led_off" : 0,
 "err_code" : 0,
 "longitude" : LONGITUDE_HERE,
 "mac" : "MAC_ADD_HERE",
 "hwId" : "HWID_HERE",
 "rssi" : -53,
 "deviceId" : "DEVICEID_HERE",
 "latitude" : LATITUDE_HERE,
 "sw_ver" : "1.0.8 Build 151101 Rel.24452",
 "alias" : "My Smart Plug",
 "type" : "smartplug",
 "hw_ver" : "1.0",
 "feature" : "TIM",
 "active_mode" : "schedule"
 }
 },
 "emeter" : {
 "err_msg" : "module not support",
 "err_code" : -1
 }
}

I guess an HS110 which has some energy consumption colection capability would give more data in the emeter section. Mine is an HS100, and I get “module not support(ed)”. Don’t hesitate to send me some example of an HS110 output energy data, I’ll put them here as well.

We can also extract one particular field’s value using a one-liner like the one below. Here I would extract the value of the relay_state field:

curl -s --request POST "https://wap.tplinkcloud.com/?token=TOKEN_HERE HTTP/1.1"\
 --data '{"method":"passthrough", "params": {"deviceId": "DEVICEID_HERE", "requestData": "{\"system\":{\"get_sysinfo\":null},\"emeter\":{\"get_realtime\":null}}" }}'\
 --header "Content-Type: application/json" | jq ".result.responseData" | sed -e 's#\\\"#"#g; s#^\"##; s#\"$##' | jq ".system.get_sysinfo.relay_state"
]]>
http://itnerd.space/2017/01/29/get-the-state-of-your-hs100-smart-plug/feed/ 7 223
Control your TP-Link HS100 smart plug with IFTTT http://itnerd.space/2017/01/22/control-your-tp-link-hs100-smart-plug-with-ifttt/ http://itnerd.space/2017/01/22/control-your-tp-link-hs100-smart-plug-with-ifttt/#comments Sun, 22 Jan 2017 16:32:43 +0000 http://itnerd.space/?p=208 In my previous post we saw how we can control a TP-Link HS100 smart plug from command line from anywhere on Internet, without the Kasa app. In this post we’ll see how to switch the plug On/Off directly from IFTTT, without any third-party component, nor without any other device at home other than the smart plug itself.

In IFTTT we’ll use the Maker service, which let’s us call a custom HTTP GET/POST request with some Json payload, so that’s exactly what we need here.

Note: If you haven’t already, follow the steps in my previous post, to figure out what your Token and Device ID are.

Then create a new Recipe Applet like you normally would in IFTTT, and choose the “Maker Webhook / Make a Web Request” action service to define a new action.

For the URL, I’ve used:

https://eu-wap.tplinkcloud.com/?token=YOUR_TOKEN_HERE

and the method type is POST.

Note: For the URL: please read this other post, as you might need to use a different URL depending the region where you are from.


The Content Type is application/json, and the payload to switch the plug On should be:

{"method":"passthrough",
"params": {"deviceId": "YOUR_DEVICEID_HERE",
"requestData": "{\"system\":{\"set_relay_state\":{\"state\":1}
}
}" }
}

If you want to switch the plug Off, just replace the state 1 with state 0.

Notice how I have added extra carriage returns to separate the “}” at the end, otherwise IFTTT was giving me some error.

That’s it! Easy, right?

]]>
http://itnerd.space/2017/01/22/control-your-tp-link-hs100-smart-plug-with-ifttt/feed/ 38 208
How to control your TP-Link HS100 smartplug from Internet http://itnerd.space/2017/01/22/how-to-control-your-tp-link-hs100-smartplug-from-internet/ http://itnerd.space/2017/01/22/how-to-control-your-tp-link-hs100-smartplug-from-internet/#comments Sun, 22 Jan 2017 14:04:59 +0000 http://itnerd.space/?p=190 I recently acquired a TP-Link HS100 smart plug. Once you install and register the plug and the companion app (Kasa), you’ll be able to do some cool things like turn on/off the plug from your smartphone, schedule on/off at some time. You can also put the plug in Away Mode, so that the plug will randomly turn on/off in the specified time/date interval.

Kasa for Mobile (Free, Google Play) →

These are already really cool features, but I wanted to be able to do more with it: for example, turn on the plug when I arrive home, and turn it off 5min after I leave home. This is of course out of the scope of the Kasa app features, but I was more thinking about being able to control the plug from a smartphone automation App like Tasker, or a cloud service like IFTTT.

While there are some resources available explaining how to control the TP-Link HS100 plug from another device connected to the same Wifi network, I haven’t been able to find any that would explain how to do it via the TP-Link web service, so this is what I’ll show here.

In this post I’ll show how to change the relay state of the plug via command line from any device connected to Internet, not only from the local Wifi, which can then be called from a script, or from Tasker on Android.

Arquitecture

There are basically 3 components involved here:

  • A web service from TP-Link
  • The Kasa app that runs on your Smartphone, connected to Internet (via your Wifi network, or any network for that matter). It does (at least) two things:
    • Periodically get the status of the plug (is it turned on/off), and show the status in teh app (green icon if the plug is switched on). This happens every two seconds, when the app is in foreground and visible.
    • When the user toggles the switch from the app, it will send the new relay state change request to the TP-Link web service.
  • The plug, connected to Internet via your wifi network: It will periodically contact the TP-Link web service for any status change, like a request to turn on/off.

Communication overview

This is how the Kasa app communicates itself with the TP-Link web service. In this case when the user switches the plug On, the app will send an HTTP POST request (over SSL) like this one:

POST https://eu-wap.tplinkcloud.com/?token=74adcc7e-64f7-47c1-a751-dece6d2f4704&appName=Kasa_Android&termID=c69d10e5-5307-4602-b2c8-eee8f3761238&appVer=1.4.4.607&ospf=Android+6.0.1&netType=wifi&locale=en_US HTTP/1.1
Content-Type: application/json
User-Agent: Dalvik/2.1.0 (Linux; U; Android 6.0.1; XXPhoneModelXX)
Connection: Keep-Alive
Content-Length: 160
Host: eu-wap.tplinkcloud.com

{
 "method":"passthrough",
 "params":{
 "deviceId":"80067AC4FDBD41C54C55896BFA28EAD38A87A5A4",
 "requestData":"{\"system\":{\"set_relay_state\":{\"state\":1}}}"
 }
}

To which the TP-Link server will respond (when successful):

{
 "error_code":0,
 "result":{
 "responseData":"{\"system\":{\"set_relay_state\":{\"err_code\":0}}}"
 }
}

As expected, almost instantly, the plug will switch On.

I have highlighted 4 fields/values in the request above. This values are specific to you and your plug. This is how the TP-Link web service identifies you and which of your plugs you want to switch.

  • Token (token=74adcc7e-64f7-47c1-a751-dece6d2f4704): passed in the URL, this is acting as a authentication. The Kasa app obtains it from the TP-Link server when you log in to the service via the App. The user and passwords are not used anymore after that. All communications use the token.
  • DeviceID (“deviceId”:”80067AC4FDBD41C54C55896BFA28EAD38A87A5A4″): passed in the Json payload, it references the device we wan’t to control.
  • TermID (termID=c69d10e5-5307-4602-b2c8-eee8f3761238): ID of the Client (the Kasa app installed in that particular phone). This doesn’t seem to be a compulsory field.
  • state: this is the desired state we want to put the relay into. 1 for On, 0 for Off.

Note: I have changed all the values shown above, to avoid having anyone control my plug by error. I have also formated the Json payloads.

Knowing that, we can now reproduce the same requests, for example using curl, from the command line (even in a Tasker task!). The TP-Link server will have aboslutely no way of telling of the request was originating from the Kasa app or a script.

Now, let see how we can call again the same request from a linux command line using curl. I have removed some parameters, like the User-Agent, and some others in the URL query string, and it still works, so I assume they eventually use them for statistical reasons only:

curl --request POST "https://eu-wap.tplinkcloud.com/?token=74adcc7e-64f7-47c1-a751-dece6d2f4704 HTTP/1.1" \
 --data '{"method":"passthrough", "params": {"deviceId": "80067AC4FDBD41C54C55896BFA28EAD38A87A5A4", "requestData": "{\"system\":{\"set_relay_state\":{\"state\":1}}}" }}' \
--header "Content-Type: application/json"

Of course, we need a way to identify the value of this fields. That’s what I’ll cover below.

Data extraction

UPDATE (06/20/2017): this “Data extraction” part is now obsolete. I leave it here for historical purpose. Instead you can now follow the following steps:

  1. Authenticate to TP-Link cloud API and get a token
  2. Get the end point URL and Device ID

OBSOLETE CONTENT STARTS HERE

This is what we’ll need:

  1. Android phone with Kasa app installed and already registred, with the plug added to the app
  2. Computer with some tools to unpack the Android Backup file (adb, python, sqlite3,…)
  3. Phone with adb enabled

First let’s take an Android Backup of the Kasa app:

adb backup -f backup.ab com.tplink.kasa_android

Now let’s unpack the backup with this one-liner:

dd if=backup.ab bs=1 skip=24 | python -c "import zlib,sys;sys.stdout.write(zlib.decompress(sys.stdin.read()))" | tar -xvf -

Now we just need to find the relevant information. I show you how to retrieve the values for each field:

  • Token
$ sqlite3 db/iot.1.db "select token from accounts;"
74adcc7e-64f7-47c1-a751-dece6d2f4704
  • deviceID
$ sqlite3 db/iot.1.db "select deviceAlias,deviceID from devices;"My Smart Plug|80067AC4FDBD41C54C55896BFA28EAD38A87A5A4
  • termId
$ cat f/INSTALLATION
c69d10e5-5307-4602-b2c8-eee8f3761238

For people on Windows, some users reported in the comments below that you can use Android Backup Extractor (ABE) to extract the backup, instead of dd. See these links:

OBSOLETE CONTENT ENDS HERE

Now, control the plug without the Kasa App

If you follow these steps above you can extract the token and device ID corresponding to your Kasa app and smartplug. You can now control the smart plug from anywhere, without the need to use the Kasa app. For example, you can use the curl expression below, after you replace the values with yours:

  • Turn On the plug:
curl --request POST "https://eu-wap.tplinkcloud.com/?token=YOUR_TOKEN_HERE HTTP/1.1" \
  --data '{"method":"passthrough", "params": {"deviceId": "YOUR_DEVICEID_HERE", "requestData": "{\"system\":{\"set_relay_state\":{\"state\":1}}}" }}' \
  --header "Content-Type: application/json"
  • Turn Off the plug:
curl --request POST "https://eu-wap.tplinkcloud.com/?token=YOUR_TOKEN_HERE HTTP/1.1" \
 --data '{"method":"passthrough", "params": {"deviceId": "YOUR_DEVICEID_HERE", "requestData": "{\"system\":{\"set_relay_state\":{\"state\":0}}}" }}' \
 --header "Content-Type: application/json"

Common issues

  • AppServerURL: You’ll need to change the URL used to control the plug with the correct one specific for your plug: See how to find it here.
  • [obsolete]{“error_code”:-20580,”msg”:”Account is not binded to the device“}: Some have reported issues with the URL eu-wap.tplinkcloud.com used in this tutorial. Here are all the known (to me) URLs of different TP-Link backend instances. If you have some problem like the previous error, try a different URL:
    • use1-wap.tplinkcloud.com if you are near the US region
    • aps1-wap.tplinkcloud.com if you are near the Asia Pacific region
    • eu-wap.tplinkcloud.com if you are near the Europe region
    • wap.tplinkcloud.com, without any region prefix[/obsolete]
  • If you get an expired or invalid token error, logout from Kasa app, then login again with your account and extract again the token from the app. Some have needed to uninstall the app completely, reinstall it and start over.
  • Be sure to enable Remote Control of the plug. You will find the option in the Kasa App, enter the Plug, then there’s a Plug settings button. There enable Remote control.

If you have any questions or comment, please, do not hesitate to let me know, using the comments below :).

In future posts I’ll show how to integrate your HS100 smart plug with the cloud Automation service IFTTT (see here), and how to control it from the Android Automation app Tasker or your Smartwatch, as well as how to get the state (On/Off) of the plug.

]]>
http://itnerd.space/2017/01/22/how-to-control-your-tp-link-hs100-smartplug-from-internet/feed/ 129 190
Script to open URLs and take screenshots http://itnerd.space/2017/01/03/batch-to-open-urls-and-take-screenshots/ http://itnerd.space/2017/01/03/batch-to-open-urls-and-take-screenshots/#comments Tue, 03 Jan 2017 17:46:05 +0000 http://itnerd.space/?p=167 Today I wanted to visually check a lot of URLs, to see if the page was loading fine, or if it was giving any kind of error. So I had an Excel file with the name of some applications (Azure WebApps), and for each the list URLs of that site, and I needed to load each URL and see, in a browser, what the pages look like.

The good thing is that depending the result, I could easily identify it if I had a high level view of all the pages. That’s were the thumbnail view comes in!

To do that I needed to automate several individual steps that I would later combine.

So I created a Frankenstein Powershell script combining all the pieces together, which you can see here.

The input I’m using is an Excel file, of which I’ll use two columns: Name and Hostnames, which contains a list of comma-separated URLs, of which I’ll only take the first one. I’ll use the Name column to name the output screenshot file.

This is how the Excel file would look like:

We load it using Import-Excel CmdLet. In the example case above, we would get:

PS C:\> Import-Excel D:\temp\file.xlsx

Name HostNames
---- ---------
google google.com, www.google.com
microsoft www.microsoft.com
yahoo yahoo.com

I didn’t find a way to take a screenshot of a non visible window, so I am showing the browser, and taking the screenshot of the region. For my purpose it works and it’s quite simple, but that presents some disadvantages (you cannot use the region of the screen while running the script, or you risk altering the result in the screenshot).

Another disadvantage is that it involves some precaution and some manual preparation, to position the windows, and modify the script accordingly, the first time at least.

  • Open a Powershell command line window
  • Run the following command. This will open an Internet Explorer window. Place it on your desktop, so that it will not overlap with the Powershell window. They can be side by side. It will be easier if you have two monitors, as you can place the browser window alone on a monitor.
 $IE=new-object -com internetexplorer.application
 $IE.visible=$true
  • Run the following commands and take note of the results:
 $IE.Top
 $IE.Left
 $IE.Width
 $IE.Height
  • Replace the results in the script. That way, each time we open a new browser the script will reposition it in the same location on your screen!

That’s it. Now you just have to run the script and it will do the job.

In the case of our example input file above, the output we’d get would look like in the output folder places in Thumbnail View:

In my particular use case, this below is what I was looking for:

As you can see, by placing the images in Thumbnail View, we can rapidly identify and classify the corresponding Web sites into 4 groups:

  1. Page seems to load fine
  2. Default initial Azure page (possibly no content deployed)
  3. Page doesn’t load, or takes too long
  4. Some HTTP error

Furthermore, within the first category, a quick inspection of the image will show if the page loads apparently fine, or if it shows some content problem.

If you have hundreds of sites, it can save you some precious time!

Some considerations:

  • I’m not sure what happens if the screen switch to screensaver mode. It may not work as expected. So, either deactivate the screensaver, or keep moving the mouse (out of the browser’s way) while the script runs.
  • I use a new IE instance for each new URL, that is, I don’t recycle the IE instance for several URLs, for a simple reason: if the URL doesn’t load, I would possibly take a screenshot of the previously loaded URL, which is not what I want.
]]>
http://itnerd.space/2017/01/03/batch-to-open-urls-and-take-screenshots/feed/ 2 167