#!/usr/bin/perl -w
#  $Id: probe 18145 2010-04-01 01:13:50Z jscott $
# -----------------------------------------------------------------------------
#  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
#       STATUS=WARNING: PCW-0009 [101] PROBE=RESET is not supported
#       
# -----------------------------------------------------------------------------
#  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: jscott, 09/28/11
#  Edited by:
#  QA by:
#  Copyright: videoNEXT Network Solutions, Inc, 2011

use strict;
use Device::Conf;

use HTTP::Request::Common;
use LWP::UserAgent;

sub send_get {
	my ($url, $username, $password) =@_;
	my $ua = LWP::UserAgent->new;
	$url =~ tr/ //d;
	my $req = GET $url;
	$req->authorization_basic($username, $password);
	my $rsp = $ua->request($req);
	return ($rsp->is_success) ? $rsp->content."\n" : "HTTP ERROR [".$rsp->code."]";
}

sub send_post {
	my ($devip, $port, $url, $username, $password, %params) = @_;
	my $ua = LWP::UserAgent->new();
	$url =~ tr/ //d;
	$ua->credentials(
		$devip.":80",
		'Siqura',
		$username=>$password);
	my ($req, $key);
	foreach $key (keys %params){
		$req .= $key."=".$params{$key}."\r\n";
	}
	my $rsp = $ua->request(POST $url, Content_Type=>'text/plain', Content=>$req);
	return ($rsp->is_success) ? $rsp->content."\n" : "HTTP ERROR [".$rsp->code."]";
}

# --------- check required parameters: DEVID,USRNAME,PASSWD,
my $conf=ProbeInit(7);  # 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};
ProbeWarn("PCW-0009","PROBE=RESET is not supported") if $conf->{PROBE} eq 'RESET';
# -- Probe camera MODELID & FIRMWARE --
my %params;
my %norm_mfl;
my $codec;
my %result = (MODELID=>'0',FIRMWARE=>'0.0',STATUS=>'OK',RC_SET=>'NONE',AUDIO_SET=>'NONE');
my $camera = defined($conf->{CAMERA}) ? $conf->{CAMERA} : '1';

my $rsp = send_get("http://$conf->{DEVIP}/api/param.cgi?req=General.FirmwareVersion&req=General.Brand.ModelName&req=VideoInput.$camera.Capabilities.CodecList",$conf->{USRNAME}, $conf->{PASSWD});

if ($rsp !~ /^HTTP ERROR/) {
	%params = map { $_ =~ /^(.+)=(.*)$/ }  split /\r?\n/, $rsp;
	$result{MODELID} = $params{'General.Brand.ModelName'};
	$result{FIRMWARE} = $params{'General.FirmwareVersion'};
} else {
    my ($err)= $rsp =~ /^HTTP ERROR \[(\d+)\]/;
    ProbeErr("PCE-0500","Device does not respond",$rsp) if $err=~/^5\d\d/;
    ProbeErr("PCE-0401","Authorization error",    $rsp) if $err==401;
}

%norm_mfl = map {$_,$_} split /,/ , $params{"VideoInput.$camera.Capabilities.CodecList"};

for my $key (keys %norm_mfl) {
    $codec = $norm_mfl{$key};
}; # get the codec for later

ProbeErr("PCE-0030","Cannot get MODELID or FIRMWARE",$rsp) unless $result{MODELID};

# -- Check MODELID & FIRMWARE --
if(defined $conf->{MODELID} and $result{MODELID} ne $conf->{MODELID}) {
	$result{STATUS}="WARNING: PCW-0001 [$conf->{DEVID}] MODELID does not match configuration";
}elsif(defined $conf->{CAMERAFIRMWARE} and $result{FIRMWARE} ne $conf->{CAMERAFIRMWARE}) {
	$result{STATUS}="WARNING: PCW-0001 [$conf->{DEVID}] FIRMWARE does not match configuration";
}


if ($conf->{PROBE} eq 'DEFINE') {
    $rsp = ProbeRequest("/api/param.cgi?req=VideoInput.Capabilities.EntityCount&req=VideoInput.$camera.$codec.1.Capabilities.ResolutionList&req=VideoInput.$camera.$codec.1.Capabilities.FrameRateList");
	$result{SNAPSHOT_PORT} = 10015 - $camera;

    if ($rsp !~ /^HTTP ERROR/) {
		%params = map { $_ =~ /^(.+)=(.*)$/ }  split /\r?\n/, $rsp;
    } else {
		my ($err)= $rsp =~ /^HTTP ERROR \[(\d+)\]/;
		ProbeErr("PCE-0500","Device does not respond",$rsp) if $err=~/^5\d\d/;
		ProbeErr("PCE-0401","Authorization error",    $rsp) if $err==401;
    }
    
	my $cams = $params{"VideoInput.Capabilities.EntityCount"};
    my @isl;
    	
	my %resl = map {$_,$_} split /,/ , $params{"VideoInput.1.$codec.$camera.Capabilities.ResolutionList"};
	my %frl = map {$_,$_} split /,/ , $params{"VideoInput.1.$codec.$camera.Capabilities.FrameRateList"};
	
    for (my $i = 1; $i <= $cams; ++$i) {
        $result{CAMERA_LIST} .= "$i,";
		$result{SNAPSHOT_LIST} .= "$i:".ProbeSamplePicture({CAMERA=>$i}).",";
	}
	chop($result{CAMERA_LIST});
	
	$result{FR_LIST} .= "$_," foreach(keys %frl);
	chop($result{FR_LIST});
	
	$result{IMAGESIZE_LIST} .= "$_," foreach(keys %resl);
	chop($result{IMAGESIZE_LIST});
    
	$result{MEDIA_FORMAT_LIST} .= "$_," foreach(keys %norm_mfl);
    chop($result{MEDIA_FORMAT_LIST});
	
}

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


# -- set RC (rate control) parameters + qality + imagesize --
my $mf = defined($conf->{MEDIA_FORMAT}) ? $conf->{MEDIA_FORMAT} : 'h264';
my %req;
$req{"VideoInput.$camera.$mf.1.Resolution"} = $conf->{IMAGESIZE} if defined($conf->{IMAGESIZE});
$req{"VideoInput.$camera.$mf.1.FrameRate"} = $conf->{FRAMERATE} if defined($conf->{FRAMERATE});
$req{"VideoInput.$camera.$mf.1.GopSize"} = $conf->{GOP} if defined($conf->{GOP}); 
$req{"VideoInput.$camera.$mf.1.Bitrate"} = $conf->{RC_TARGETBITRATE} if defined($conf->{RC_TARGETBITRATE});

# -- set AudioParams --
if ($conf->{AUDIO} eq 'on') {
	;
} else {
	;
}

$rsp = send_post($conf->{DEVIP}, "80", "http://$conf->{DEVIP}/api/param.cgi",$conf->{USRNAME},$conf->{PASSWD},%req);


if ($rsp !~ /^HTTP ERROR/) {
    $result{RC_SET} = 'OK';
    $result{AUDIO_SET} = 'OK';
} else {
    my ($err)= $rsp =~ /^HTTP ERROR \[(\d+)\]/;
    ProbeErr("PCE-0500","Device does not respond",$rsp) if $err=~/^5\d\d/;
    ProbeErr("PCE-0401","Authorization error",    $rsp) if $err==401;
}

ProbeResult(\%result);
