-
-
Save eriknylund/16c1a3bceaed4c43252ab4b36332ef86 to your computer and use it in GitHub Desktop.
Chinese DVR Alarm Server
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
# Simple log/alarm server receiving and printing to console remote dvr/camera events. | |
# Output is in CSV format. | |
# | |
# Tested with: | |
# | |
# HandyKam DigiMiniCam HD camera HK101182 | |
# http://www.handykam.com/Cameras-only/DigiMinicam-HD-camera/flypage.tpl.html | |
# | |
# Usage: perl dvr-alarm-server.pl | tee -a cam.csv | |
use IO::Socket; | |
use IO::Socket::INET; | |
use Sys::Syslog; | |
use Sys::Syslog qw(:DEFAULT setlogsock); | |
use Sys::Syslog qw(:standard :macros); | |
use Time::Local; | |
use JSON; | |
use Data::Dumper; | |
setlogsock("console"); | |
openlog("dvr-alarm-server", "cons,pid", LOG_USER); | |
sub BuildPacket { | |
my ($type, $params) = ($_[0], $_[1]); | |
my @pkt_prefix_1; | |
my @pkt_prefix_2; | |
my @pkt_type; | |
my $sid = 0; | |
my $json = JSON->new; | |
@pkt_prefix_1 = (0xff, 0x00, 0x00, 0x00); | |
@pkt_prefix_2 = (0x00, 0x00, 0x00, 0x00); | |
if ($type eq 'login') { | |
@pkt_type = (0x00, 0x00, 0xe8, 0x03); | |
} elsif ($type eq 'info') { | |
@pkt_type = (0x00, 0x00, 0xfc, 0x03); | |
} | |
$sid = hex($params->{'SessionID'}); | |
my $pkt_prefix_data = pack('c*', @pkt_prefix_1) . pack('i', $sid) . pack('c*', @pkt_prefix_2). pack('c*', @pkt_type); | |
my $pkt_params_data = $json->encode($params); | |
my $pkt_data = $pkt_prefix_data . pack('i', length($pkt_params_data)) . $pkt_params_data; | |
return $pkt_data; | |
} | |
sub GetReplyHead { | |
my $sock = $_[0]; | |
my @reply_head_array; | |
for (my $i = 0; $i < 5; $i++) { | |
$sock->recv($data, 4); | |
$reply_head[$i] = unpack('i', $data); | |
print OUT $data; | |
} | |
my $reply_head = { | |
Prefix1 => $reply_head[0], | |
Prefix2 => $reply_head[1], | |
Prefix3 => $reply_head[2], | |
Prefix4 => $reply_head[3], | |
Content_Length => $reply_head[4] | |
}; | |
return $reply_head; | |
} | |
my $sock = new IO::Socket::INET( | |
LocalHost => '0.0.0.0', | |
LocalPort => '15002', | |
Proto => 'tcp', | |
Listen => 1, | |
Reuse => 1); | |
die "Could not create socket: $!\n" unless $sock; | |
while (my ($client,$clientaddr) = $sock->accept()) { | |
write_log("Connected from ".$client->peerhost()); | |
$pid = fork(); | |
die "Cannot fork: $!" unless defined($pid); | |
if ($pid == 0) { | |
# Child process | |
my $data = ''; | |
my $reply = GetReplyHead($client); | |
# Client protocol detection | |
$client->recv($data, $reply->{'Content_Length'}); | |
# Format CSV data | |
# timestamp, address, channel, serialid, event, starttime, status, type | |
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time()); | |
my $timestamp = sprintf("%4d-%02d-%02d %02d:%02d:%02d",$year+1900,$mday,$mon+1,$hour,$min,$sec); | |
my $json = decode_json($data); | |
print "$timestamp,$json->{Address},$json->{Channel},$json->{SerialID},$json->{Event},$json->{StartTime},$json->{Status},$json->{Type}\n"; | |
exit(0); # Child process exits when it is done. | |
} | |
} | |
close($sock); | |
sub write_log() { | |
#my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time()); | |
#my $timestamp = sprintf("%02d.%02d.%4d %02d:%02d:%02d",$mday,$mon+1,$year+1900,$hour,$min,$sec); | |
#print "$timestamp dvr-alarm-server[] " . $_[0] ."\n"; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment