PD100 family cameras

Post here to indicate any hardware you have used and which is known to work with ZoneMinder. Not for questions.
Post Reply
tipok
Posts: 6
Joined: Mon Apr 23, 2007 2:40 pm

PD100 family cameras

Post by tipok »

I found this cameras (PD100) in ebay, they are good for outdoor, but there is some unknown binary protocol used.

I cant get jpeg images from this camera, so i wrote this perl script to get jpeg images into file and update them every 0.5 sec.

pd100_get.pl

Code: Select all

#! /usr/bin/perl -w
# client1.pl - a simple client
#----------------
use strict;
use Socket;
use IO::Handle;

our ($typacket, $dopacket);

my ($pipe, $host, $port, $proto, $iaddr, $paddr, $pid, $buf, $client_hash, $dsize, $file_to_save);

# ip and port of pd100 camera.
# login to camera is not fully implemented yet (just "admin", no password) - use factory default!!
$host = "10.16.0.149";
$port = 80;
$file_to_save="image.jpg";


#############################################################
# IF $typacket == 0x4f
# dopacket:
# -> - to camera
# <- - from camera
#############################################################
#t/f hex explanation
# -> 00 - reset camera's config for logged user
# <- 01 - show camera's mac address
# -> 02 - login info sending to camera
# <- 03 - login answer from camera (access/deny)
# -> 10 - clearing something ????
# <- 16 - answer to "10", maybe cleared ????
# -> 04 - something setup asking ????
# <- 11 - some code sended (answer)
# <- 05 - again something sended
##############################################################
#$typacket == 0x56
##############################################################
# -> 00 - send code gotted from 05 in 0x04f setup (see upper)
##############################################################
#$typacket == 0x4f
##############################################################
# -> 07 - clearing something (or say "start")
##############################################################
#$typacket == 0x56
##############################################################
# <- 01 - sending data
##############################################################

sub makepacket {
    my $data = $_[0];
    my $strsize=length($data);
    my $dsize=$strsize/2;
    $strsize = $strsize+46;
    return pack("H".$strsize,"4d4f5f".$typacket.unpack("H2",pack("i",$dopacket))."00000000000000000000".unpack("H8",pack("i",$dsize)).unpack("H8",pack("i",$dsize)).$data);
}

sub countpacketdata {
    my $buf = $_[0];
    # debug
    #my $data="4d4f5f4f01000000000000000000001b0000001b00000000003130333637353432333243410000000001000000000600000e";
    #$buf=pack("H100",$data);
    #print $buf;
    
    if ($buf =~ m/^\x4d\x4f\x5f(.)(.)\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00(.{4})(.{4}).*/){

	#print $buf."\n";
	$typacket = unpack("H2",$1);
	$dopacket = unpack("c",$2);
	my $psize=  unpack("v",$3);
	my $psizecheck=  unpack("v",$4);
	if ($psize == $psizecheck){
	    return $psize;
	} else {
	    return 0;
	}
    
    } else {
        return 0;
    }
}

# initialize host and port
$proto = getprotobyname('tcp');
# get the port address
$iaddr = inet_aton($host);
$paddr = sockaddr_in($port, $iaddr);


socketpair(CHILD, PARENT, AF_UNIX, SOCK_STREAM, PF_UNSPEC) or  die "socketpair: $!";
CHILD->autoflush(1);
PARENT->autoflush(1);

if($pid = fork()) { # Parent
    print "parent\n";
    close PARENT;

    # create the socket, connect to the port
    socket(SOCK_CTRL, PF_INET, SOCK_STREAM, $proto) or die "socket: $!";
    binmode(SOCK_CTRL);
    connect(SOCK_CTRL, $paddr) or die "connect: $!";
    
    $typacket="4f";
    $dopacket=0;
    
    $buf=makepacket("");
    send(SOCK_CTRL, $buf, 0);
    read(SOCK_CTRL,$buf,23);
    $dsize=countpacketdata($buf); # $dopacket & $typacket - changed too!!
    #debug
    #print $dsize."\n-\n";
    #print $typacket."\n-\n";
    #print $dopacket."\n-\n";
    
    read(SOCK_CTRL,$buf,$dsize);
    if ($dopacket==1){
        print "Connected to MAC:".substr($buf,2,12)."\n";
    } else {
        print "Connected, but don't know MAC!\n";
    }
    $dopacket=2;
    
    # login to camera (just "admin", no password)
    $buf=makepacket("61646d696e00000000000000000000000000000000bb76cbb7dd");
    send(SOCK_CTRL, $buf, 0);
    read(SOCK_CTRL,$buf,23);
    $dsize=countpacketdata($buf); # $dopacket & $typacket - changed too!!
    read(SOCK_CTRL,$buf,$dsize);
    if ((unpack("H6",$buf) eq "000002") && ($dopacket==3)){
        print "login OK!\n";
    } else {
        print "ERROR: wrong login or packet cmd\n";
    }
    
    $dopacket=16;
    
    $buf=makepacket("");
    send(SOCK_CTRL, $buf, 0);
    read(SOCK_CTRL,$buf,23);
    $dsize=countpacketdata($buf); # $dopacket & $typacket - changed too!!
    read(SOCK_CTRL,$buf,$dsize);
    
    if (($dopacket==22) && (unpack("H2",$buf) eq "00")){
        print "Answer to \"0x10\" OK!\n";
    } else {
        if ($dopacket==22) {
    	    print "Answer to \"0x10\" NOT OK!\n";
	} else {
	    print "No answer to \"0x10\"!\n";
	}
    }
    
    $dopacket=4;
    
    $buf=makepacket("02");
    send(SOCK_CTRL, $buf, 0);
    # 1-st packer recv
    read(SOCK_CTRL,$buf,23);
    $dsize=countpacketdata($buf); # $dopacket & $typacket - changed too!!
    read(SOCK_CTRL,$buf,$dsize);
    if ($dopacket==17){
	print "Answer to \"0x04\" give: 0x".unpack("H".length($buf)*2,$buf)."\n";
    }
    
    # 2-nd packer recv
    read(SOCK_CTRL,$buf,23);
    $dsize=countpacketdata($buf); # $dopacket & $typacket - changed too!!
    read(SOCK_CTRL,$buf,$dsize);
    
    
    if ($dopacket==05){
	#print "And: 0x".unpack("H".length($buf)*2,$buf)." - too (hash to 2-nd socket)!\n";
	#################################################################################
	# picture socket code
	#################################################################################
        $client_hash=substr(unpack("H".length($buf)*2,$buf),4);
	print CHILD $client_hash."\n";
	print "Sended client hash to file:".$client_hash."\n";
	####################################
        # say to control socket "start"!
	$typacket="4f";
        $dopacket=7;
	$buf=makepacket("00000000");
        send(SOCK_CTRL, $buf, 0);
        ####################################

	#################################################################################
    }
    
    for (;;){
	
	# 2-nd packer recv
	read(SOCK_CTRL,$buf,23);
	$dsize=countpacketdata($buf); # $dopacket & $typacket - changed too!!
	#read(SOCK_CTRL,$buf,$dsize);
	if ($dopacket=="-1"){
	    print time()." Send keep-alive: ".$dopacket."\n";
	    $buf=makepacket("");
	    send(SOCK_CTRL, $buf, 0);
	    # 1-st packer recv
	
	} else {
	    print "Control received: 0x".unpack("H".length($buf)*2,$buf)." - unknown data!\n";
	}
    }
    
    waitpid($pid,0);	
    
    ####################################
    # say to control socket "stop"!
    $typacket="4f";
    $dopacket=6;
    $buf=makepacket("");
    send(SOCK_CTRL, $buf, 0);
    ####################################
    
    close(SOCK_CTRL) or die "close: $!"; 
    close CHILD;

} elsif(defined $pid) { # Child
    print "children\n";
    close CHILD;
    chomp($buf = <PARENT>);
	print "getting hash\n";
	print $buf."<- got user hash\n";

	$typacket="56";
        $dopacket=0;
	$buf=makepacket($buf);
	
        socket(SOCK_GET, PF_INET, SOCK_STREAM, $proto) or die "socket: $!";
	binmode(SOCK_GET);
        connect(SOCK_GET, $paddr) or die "connect: $!";
	send(SOCK_GET, $buf, 0);
        
	####################################
        # loop for image gets
	do {
        
	    read(SOCK_GET,$buf,23);
	    $dsize=countpacketdata($buf); # $dopacket & $typacket - changed too!!
        
    	    if ($dsize > 0){
		print time()." got image \n";
		read(SOCK_GET,$buf,$dsize);
		# save to file
		open(FH, ">$file_to_save.tmp") or die "Can't open $file_to_save.tmp: $!";
		$jpgcode= substr($buf,13);
		print FH $jpgcode;
		close(FH) or die "close: $!"; 
		
		rename("$file_to_save.tmp", "$file_to_save");
		#sleep 1;
		select(undef,undef,undef,.5);
	    }
	} while (($typacket eq "56") && ($dsize > 0));
	####################################
	close(SOCK_GET) or die "close: $!"; 
    close PARENT;
}
Post Reply