#!/usr/bin/perl -w
#  $Id$
# -----------------------------------------------------------------------------
#  Purpose:
#    - probe the camera
#    - pre-tune camera befor for retriever (RC and Audio)
# -----------------------------------------------------------------------------
#  Call:
#    probe DEVID=123   
#    probe DEVID=123 PROBE=FAST  
#    probe DEVID=123 DEVIP=192.168.17.177 [ ... ]
#    probe DEVIP=192.168.17.177 USRNAME=admin PASSWD=pass PROBE=DEFINE
# -----------------------------------------------------------------------------
#  Does:
#   0. can be called without DEVID argument. 
#      In this case DEVIP,USRNAME,PASSWD should be provided in command line
#   1. load $APL_CONF/<DEVID>/conf if DEVID is provided
#   2. combine conf and args into one hash
#   3. connect to camera over http and read MODELID and FIRMWARE
#   4. report MODELID|FIRMWARE|STATUS to $APL_CONF/<DEVID>/conf.probe and stdout
#   5. if PROBE=DEFINE then get
#         IMAGESIZE_LIST,MEDIA_FORMAT_LIST
#         AUDIO_LIST,AUDIO_FORMAT_LIST
#         SNAPSHOT (picture)
#   6. set RC camera attributes    if mpeg4 | h264
#   7. set AUDIO camera attributes if AUDIO is on 
#   8. example output:
#       AUDIO_SET=OK
#       FIRMWARE=5.02
#       MODELID=Q1755
#       RC_SET=OK
#       STATUS=OK
#       -------------
#       AUDIO_SET=NONE
#       FIRMWARE=5.02
#       MODELID=Q1755
#       RC_SET=NONE
#       STATUS=OK
#       SNAPSHOT=/tmp/probe/192.168.17.177-12367576123.jpg
#       IMAGESIZE_LIST=640x480,480x360,320x240,240x180,176x144,160x120
#       MEDIA_FORMAT_LIST=mjpeg,h264
#       AUDIO_LIST=off,on
#       AUDIO_FORMAT_LIST=g711,g726,aac
#   9. sample errors: 
#       STATUS=ERROR: PCE-0001 [101] configuration is not found
#       STATUS=ERROR: PCE-0002 [101] USRNAME and PASSWD should provided
#       STATUS=ERROR: PCE-0003 [101] DEVIP is not defined
#       STATUS=ERROR: PCE-0500 [101] Device does not respond (http://207.107.163.123:80)
#       STATUS=ERROR: PCE-0401 [101] Authorization error 
#       STATUS=ERROR: PCE-0403 [101] Forbidden 
#       STATUS=ERROR: PCE-0030 [101] Cannot get MODELID
#       note: [101] is DEVID
#  10. warnings:
#       STATUS=WARNING: PCW-0001 [101] MODELID does not match configuration
#       STATUS=WARNING: PCW-0002 [101] FIRMWARE does not match configuration
#       
# -----------------------------------------------------------------------------
#  Note:
#   1. CAMERAMODEL file is obsolite. ptz_axisv2.pl & ptz_udp.pl has to be modified
#   2. Script mast be in the directory .../camera/<BRAND>/bin/
# -----------------------------------------------------------------------------
#  Author: teetov, 03/22/10
#  Edited by:
#  QA by:
#  Copyright: videoNEXT Network Solutions, Inc, 2010
# -----------------------------------------------------------------------------
#
use strict;
use Socket qw(:DEFAULT);
use Fcntl;
use Errno qw(EAGAIN);
use MIME::Base64 "encode_base64";
use Device::Conf;
use Data::Dumper;
# cons -------------------------------------------------------------------------
# no code for Radiant-RTSP

# --------- check required parameters: DEVID,USRNAME,PASSWD,
my $conf=ProbeInit();  # uses <BRAND> from path and ARGV
ProbeErr("PCE-0001","configuration is not found") if not defined $conf->{DEVID}; 
ProbeErr("PCE-0003","DEVIP is not defined")       if not defined $conf->{DEVIP};
ProbeErr("PCE-0002","USRNAME and PASSWD should be provided") 
                 if not defined $conf->{USRNAME} or not defined $conf->{PASSWD};
#------------------------------------------------------------------------------
# Probe camera MODELID & FIRMWARE 
#------------------------------------------------------------------------------
my %result=(MODELID=>'0',FIRMWARE=>'0.0',STATUS=>'OK',RC_SET=>'NONE',AUDIO_SET=>'NONE');

my $rtsp_port = $conf->{RTSP_PORT} || 554;
my $timeout = 10;
my $url = "rtsp://$conf->{DEVIP}:$rtsp_port/stream";
my $buffer = '';
my $auth = encode_base64("$conf->{USRNAME}:$conf->{PASSWD}", '');
my ($status,$message);

# Send RTSP OPTIONS
my $req = <<END;
OPTIONS $url RTSP/1.0\r
CSEQ: 1\r
User-Agent: probe\r
Authorization: Basic $auth\r
\r
END

eval {
    socket(FH, PF_INET, SOCK_STREAM, getprotobyname('tcp'));
    my $addr = inet_aton($conf->{DEVIP});
    if (!$addr) {
        close FH;
        die "$!\n";
    }
    my $sin = sockaddr_in($rtsp_port,$addr);
    connect(FH, $sin) or die "$!\n";
    fcntl(FH, F_SETFL, O_NONBLOCK);

    # Write data to socket
    my $size = length($req);
    my $bytes = syswrite(FH, $req, $size, 0);
    while ( ($size - $bytes) > 0) {
        $bytes += syswrite(FH, $req, 4096, $bytes );
    }
    
    # Read response
    while ($buffer !~ /\n/) {
        # nope -- wait for incoming data
        my ($inbuf,$bits,$chars) = ("","",0);
        vec($bits,fileno(FH),1)=1;
        my $nfound = select($bits, undef, $bits, $timeout);
        if ($nfound == 0) {
            # Timed out
            die "TIMEOUT\n";
        } else {
            # Get the data
            $chars = sysread(FH, $inbuf, 1024);
        }
        # End of stream?
        if ($chars <= 0 && !$!{EAGAIN}) {
            last;
        }
        # tag data onto end of buffer  
        $buffer.=$inbuf;
    }
    # Get first line of server answer
    my $line = (split(/\n/, $buffer))[0];
    if ($line and $line =~ /^.+\s+(\d+)\s+(.+)$/) {
        $status = $1;
        $message = $2;
    }
};
if ($@) {
    chomp $@;
    #ProbeErr("PCE-0500","Device does not respond","$@");
}
close FH;

if ($status) {
    if ($status == 200) {
        $result{MODELID} = "V4430";
        $result{FIRMWARE} = "0.0";
    }
    elsif ($status == 401) {
        ProbeErr("PCE-0401","Authorization error") if $status == 401;
    }
}

ProbeErr("PCE-0030","Cannot get MODELID or FIRMWARE",$message) if ! $result{MODELID};

#------------------------------------------------------------------------------
# get Sample picture 
#------------------------------------------------------------------------------
if($conf->{PROBE} eq 'DEFINE') {
   $result{SNAPSHOT}=ProbeSamplePicture();
}

#------------------------------------------------------------------------------
# get video and audio properties
#------------------------------------------------------------------------------

# no code for Radiant-RTSP

#------------------------------------------------------------------------------
# interim report & exit 
#------------------------------------------------------------------------------
ProbeResult(\%result)  if $conf->{PROBE} =~ /^(DEFINE|FAST)$/;
ProbeResult(\%result)  if $conf->{DEVID}==0;

#------------------------------------------------------------------------------
# set RC (rate control) parameters + qality + imagesize
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
# set AudioParams
#------------------------------------------------------------------------------
if ( $conf->{AUDIO} eq 'on' ) { 
# no code for Radiant-RTSP
}
# final report-----------------------------------------------------------------------
ProbeResult(\%result);
