TP-LINK HS100 Smart Plug (WiFi)?

Eventually, a full-blown binding would be neat for this. Seems like an easy enough project (maybe I’ll take a stab, just to get familiar with binding development).

In case anyone wants an auto-updating Switch in OH2 that works with this in the meantime:
https://community.openhab.org/t/oh2-switch-triggered-rule-not-working/

My primary motivation was wanting OH-backed UIs to properly show the outlet state when it gets changed from somewhere else (such as Alexa).

I have a Ruby script that polls the network for all of the tp-link bulbs and outlets I have, and sends this on an mqtt topic. The same Ruby script remembers where these devices live in IP address space, and also accepts commands to turn them on and off.

I think it’s time to open source my minor amount of work…

1 Like

The commands for the smart bulbs are like this

I figured these out myself and tested them and they work.

{“smartlife.iot.smartbulb.lightingservice”:{“transition_light_state”:{“ignore_default”:0,“mode”:“normal”,“on_off”:0,“transition_period”:0}}}
{“smartlife.iot.smartbulb.lightingservice”:{“transition_light_state”:{“ignore_default”:0,“mode”:“normal”,“on_off”:1,“transition_period”:0}}}

there are several other commands for “brightness”, etc

Yes! I am trying to use a javascript lib for the plugs to decode the bulbs and having some issues. Any hints on decoding the bulb’s messages would be greatly appreciated.

What is the algorithm you are using to decode? I am using this (in javascript, from this node lib) and getting gibberish mixed with bits of JSON:

function decrypt(input, firstKey) {
  if (typeof firstKey === 'undefined') firstKey = 0x2B;
  var buf = new Buffer(input); // node v6: Buffer.from(input)
  var key = firstKey;
  var nextKey;
  for (var i = 0; i < buf.length; i++) {
    nextKey = buf[i];
    buf[i] = buf[i] ^ key;
    key = nextKey;
  }
  return buf;
}

here is shell script that controls tplink

#!/bin/bash

Controls TP-LINK HS100,HS110, HS200 wlan smart plugs

Tested with HS100 firmware 1.0.8

Credits to Thomas Baust for the query/status/emeter commands

Author George Georgovassilis, https://github.com/ggeorgovassilis/linuxscripts

ip=$1
port=$2
cmd=$3

encoded (the reverse of decode) commands to send to the plug

encoded {“system”:{“set_relay_state”:{“state”:1}}}

payload_on=“AAAAKtDygfiL/5r31e+UtsWg1Iv5nPCR6LfEsNGlwOLYo4HyhueT9tTu36Lfog==”

encoded {“system”:{“set_relay_state”:{“state”:0}}}

payload_off=“AAAAKtDygfiL/5r31e+UtsWg1Iv5nPCR6LfEsNGlwOLYo4HyhueT9tTu3qPeow==”

encoded { “system”:{ “get_sysinfo”:null } }

payload_query=“AAAAI9Dw0qHYq9+61/XPtJS20bTAn+yV5o/hh+jK8J7rh+vLtpbr”

the encoded request { “emeter”:{ “get_realtime”:null } }

payload_emeter=“AAAAJNDw0rfav8uu3P7Ev5+92r/LlOaD4o76k/6buYPtmPSYuMXlmA==”

tools

check_dependencies() {
command -v nc >/dev/null 2>&1 || { echo >&2 “The nc programme for sending data over the network isn’t in the path, communication with the plug will fail”; exit 2; }
command -v base64 >/dev/null 2>&1 || { echo >&2 “The base64 programme for decoding base64 encoded strings isn’t in the path, decoding of payloads will fail”; exit 2; }
command -v od >/dev/null 2>&1 || { echo >&2 “The od programme for converting binary data to numbers isn’t in the path, the status and emeter commands will fail”;}
command -v read >/dev/null 2>&1 || { echo >&2 “The read programme for splitting text into tokens isn’t in the path, the status and emeter commands will fail”;}
command -v printf >/dev/null 2>&1 || { echo >&2 “The printf programme for converting numbers into binary isn’t in the path, the status and emeter commands will fail”;}
}

show_usage() {
echo Usage: $0 IP PORT COMMAND
echo where COMMAND is one of on/off/check/status/emeter/toggle
exit 1
}

check_arguments() {
check_arg() {
name="$1"
value="$2"
if [ -z “$value” ]; then
echo "missing argument $name"
show_usage
fi
}
check_arg “ip” $ip
check_arg “port” $port
check_arg “command” $cmd
}

send_to_plug() {
ip="$1"
port="$2"
payload="$3"
echo -n “$payload” | base64 --decode | nc $ip $port || echo couldn’'t connect to $ip:$port, nc failed with exit code $?
}

decode(){
code=171
offset=4
input_num=od -j $offset -An -t u1 -v | tr "\n" " "
IFS=’ ’ read -r -a array <<< “$input_num"
args_for_printf=”"
for element in "${array[@]}“
do
output=$(( $element ^ $code ))
args_for_printf=”$args_for_printf\x$(printf %x $output)"
code=$element
done
printf “$args_for_printf”
}

query_plug(){
payload=$1
send_to_plug $ip $port “$payload” | decode
}

plug commands

cmd_print_plug_relay_state(){
output=send_to_plug $ip $port "$payload_query" | decode | egrep -o 'relay_state":[0,1]' | egrep -o '[0,1]'
if [[ $output -eq 0 ]]; then
echo OFF
elif [[ $output -eq 1 ]]; then
echo ON
else
echo Couldn’'t understand plug response $output
fi
}

cmd_print_plug_status(){
query_plug “$payload_query”
}

cmd_print_plug_consumption(){
query_plug “$payload_emeter”
}

cmd_switch_on(){
send_to_plug $ip $port $payload_on > /dev/null
}

cmd_switch_off(){
send_to_plug $ip $port $payload_off > /dev/null
}

cmd_switch_toggle() {
output=cmd_print_plug_relay_state
if [[ $output == OFF ]]; then
cmd_switch_on
elif [[ $output == ON ]]; then
cmd_switch_off
else
echo $output
fi
}

Main programme

check_dependencies
check_arguments

case “$cmd” in
ON)
cmd_switch_on
;;
on)
cmd_switch_on
;;
OFF)
cmd_switch_off
;;
off)
cmd_switch_off
;;
toggle)
cmd_switch_toggle
;;
check)
cmd_print_plug_relay_state
;;
status)
cmd_print_plug_status
;;
emeter)
cmd_print_plug_consumption
;;
*)
show_usage
;;
esac

use it as:
/opt/openhab2/conf/scripts/hs100.sh 192.168.10.42 9999 OFF
/opt/openhab2/conf/scripts/hs100.sh 192.168.10.42 9999 on
/opt/openhab2/conf/scripts/hs100.sh 192.168.10.42 9999 status
i do not know how to attach to the message - it screwed script a bit replacing # characters with bigger font encodings.

Are there commands that allow you to turn it on, off, set brightness, etc?

Would you be able to give samples?

Would you be able to share the commands for brightness and such that you found?

Any idea why the “smartlife.*” as the name? Seems weird given what they did for the plugs.

Hi all… I’m completely new to OpenHab and have just started using OpenHab 2.0 in Mac. I had been trying to use the shell script as mentioned above but not able to bind it. The shell script is working for me (tested using terminal). However, Exec Binding isn’t working (using Paper UI). I am still not clear about what would be the Configuration Parameters - Command and Transform. Would really appreciate if someone could help me out.

Please note my shell script path is /Applications/openhab/conf/scripts/

Thanks

I ran into problems when I added a tp-link smart bulb to my collection of smart plugs on my OpenHab2 window 10 installation. It turns out that the information is different for these two devices. In order to solved this I created a nodejs script that I use to control my tp-link smart plugs and bulbs. More info can be found at https://github.com/veetrik/tplink-handler. I now added support for changing the hue on a color smart bulb (LB130).

First shot:
PR: https://github.com/openhab/openhab2-addons/pull/2018
Project: https://github.com/computerlyrik/openhab2-addon-hs110

I’d be happy to hear from HS100 Users - i’m owner of HS110 (with powermeter)

1 Like

Hey Christian,

thank you for the addon.

When i try to install this i get an error:

[16:47:52] pi@openHABianPi:/usr/share/openhab2$ git subtree pull --squash --prefix addons/binding/org.openhab.binding.hs110 https://github.com/computerlyrik/openhab2-addon-hs110.git master
fatal: Not a git repository (or any of the parent directories): .git

I tried the url with and without the ‘.git’. Where is my error?

Best regards,
Dirk

Perhaps the project information was somewhat misleading. The commands you issued are used to ‘copy’ the source code from a separate github project into the openhab2-addons tree.

I updated the Readme for your need: https://github.com/computerlyrik/openhab2-addon-hs110#building--testing

Ok.

Thank you for the clarification!

All just wondering if there will ever be a binding for the TPlink sockets (HS100).

They are around a while now (2-3 years) and seem one of the more popular WIFI sockets and its strange there isnt a binding for it yet…

I see lots of users using exec and scripts etc… would a binding not be more effective than tons of scripts.

Is the issue with TPLink or the complexity to do it ???

Thanks

2 Likes

Script isn’t working for me; thoughts?

nevermind i got it

@computerlyrik thanks for starting this. Would it be possible to add a .jar to github for those users who don’t have a development environment setup (for example myself :slight_smile: )? Will happily wait until the PR merges if not possible, but just wondering.

How would one do the following:

/opt/openhab2/conf/scripts/hs100.sh 192.168.10.42 9999 status

Run that, and based on if it was on or off, go and set something in openhab.

I assume it would have to be:
Rule calls another script that runs this script with the parameters.
Then the first script would have to maybe set something in rest(lets say postUpdate to a switch in openhab)?

How would one do this?