Hi all,
I got this device too. Using the protocol description I successfully wrote a small perl script that can turn on and off the plugs using the protocol on port 5000 (not the webserver itself). If your’e interested, it looks like this (should not be difficult to implement it in any other language), $pass and $ip must be filled in of course:
use strict;
use IO::Socket::INET;
my $pass = "...";
my $ip = "...";
sub response($$)
{
my @d = map (ord, split //,shift);
my @k = map (ord, split //,shift);
my $v1 = (($d[0]^$k[2]) * $k[0]) ^ ($k[6] | ($k[4]<<8)) ^ $d[2];
my $v2 = (($d[1]^$k[3]) * $k[1]) ^ ($k[7] | ($k[5]<<8)) ^ $d[3];
return join "",map(chr, ($v1%256,$v1>>8,$v2%256,$v2>>8));
}
sub encrypt($$$)
{
my @d = map (ord, split //,shift);
my @k = map (ord, split //,shift);
my @t = map (ord, split //,shift);
my @r = (0,0,0,0);
my $x;
for (my $i=0; $i<4; $i++)
{
$x = $d[3-$i];
$x ^= $t[2];
$x += $t[3];
$x ^= $k[0];
$x += $k[1];
$r[$i] = 0xff & $x;
}
return join "",map(chr, @r);
}
sub decrypt($$$)
{
my @d = map (ord, split //,shift);
my @k = map (ord, split //,shift);
my @t = map (ord, split //,shift);
my @r = (0,0,0,0);
my $x;
for (my $i=0; $i<4; $i++)
{
$x = $d[$i];
$x -= $k[1];
$x ^= $k[0];
$x -= $t[3];
$x ^= $t[2];
$r[3-$i] = 0xff & $x;
}
return join "",map(chr, @r);
}
sub setPlug($$$)
{
my $ip = shift;
my $idx = shift;
return 0 if $idx<0 or $idx>3; # plugs 0-3
my $flg = shift;
return 0 if $flg<0 or $flg>2; # 0: turn off, 1: turn on, 2: toggle
my $done = 0;
while (!$done)
{
my $s;
eval
{
local $SIG{ALRM} = sub { die 'Timed Out'; };
alarm 10;
my ($t,$d);
$s = new IO::Socket::INET (
PeerHost => $ip,
PeerPort => '5000',
Proto => 'tcp',
) or return 0;
$s->send("\x11");
$s->recv($t,4);
$s->send(response($t,$pass));
$s->recv($d,4);
$d = decrypt($d,$pass,$t);
my $ctrl = "\x04\x04\x04\x04"; # default is: no action on any plug
if ($flg==0) # turn off, unless it already is off
{
substr($ctrl,$idx,1) = "\x02" unless substr($d,$idx,1) eq "\x82";
}
if ($flg==1) # turn on, unless it alredy is on
{
substr($ctrl,$idx,1) = "\x01" unless substr($d,$idx,1) eq "\x41";
}
if ($flg==2) # toggle
{
substr($ctrl,$idx,1) = chr((ord(substr($d,$idx,1))&1) + 1);
}
$s->send(encrypt($ctrl,$pass,$t));
$s->recv($d,4);
$d = decrypt($d,$pass,$t);
$done=1;
$s->send("\x01\x02\x03\x04");
alarm 0;
};
alarm 0;
$s->close() if defined $s;
}
return 1;
}
setPlug($ip,0,0); # turn off plug 1
setPlug($ip,0,1); # turn on plug 1
setPlug($ip,0,2); # toggle plug 1
The while/eval construct is just there to repeat the TCP connection in case of a problem. You might want to increase/decrase the “alarm 10” value - in this setup, the connection is re-tries after 10 seconds if it does not succeeds (timeout).
Hope it helps,
Andy