#!/usr/bin/perl -w
#  $Id: probe 29776 2013-11-06 14:41:04Z vakchurin $
# -----------------------------------------------------------------------------
#  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
#	CAMERA_LIST=1,2,3,4
#   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: teetov, 03/22/10
#  Edited by:
#  QA by:
#  Copyright: videoNEXT Network Solutions, Inc, 2010
# -----------------------------------------------------------------------------
#
use strict;
use Device::Conf ":all";
use JSON;
#use Data::Dumper;
# cons -------------------------------------------------------------------------
my @VERSION_URL = (
       #{'URL' => '/cgi-x/get-general', 'PROD' => '"partNumber"\s*:\s*"(.+)"', 'FW' => '"firmwareVersion": "(.+)"' }
       {'URL' => '/cgi-x/get-general', 'PROD' => 'partNumber', 'FW' => 'firmwareVersion' }
);

# --------- 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};
ProbeWarn("PCW-0009","PROBE=RESET is not supported") if $conf->{PROBE} eq 'RESET';
#------------------------------------------------------------------------------
# Probe camera MODELID & FIRMWARE
#------------------------------------------------------------------------------
my %result=(MODELID=>'0',FIRMWARE=>'0.0',STATUS=>'OK',RC_SET=>'NONE',AUDIO_SET=>'NONE');
my $postmortem;

my $myua = LWP::UserAgent->new(keep_alive => 1);
my $hostport = "$conf->{DEVIP}:$conf->{HTTP_PORT}";
my $response = $myua->get("http://$hostport/cgi-x/get-general");
$response->header('www-authenticate') =~ /realm=\"([^"]+)\"/;
my $realm = $1; 
UA($myua);
UA()->timeout(5);
UA()->credentials($hostport, $realm, $conf->{USRNAME}, $conf->{PASSWD});
foreach my $def (@VERSION_URL) {             # check different models
    my $respond = ProbeRequest($def->{URL});
    #print Dumper($respond);
    if($respond!~ /^HTTP ERROR/) {
       $respond = decode_json($respond);
       $result{MODELID}      = $respond->{$def->{PROD}};
       $result{FIRMWARE}     = $respond->{$def->{FW}};
       last;
    }
    my ($err)= $respond=~/^HTTP ERROR \[(\d+)\]/;
    $postmortem .= "$respond\n";
    ProbeErr("PCE-0500","Device does not respond",$respond) if $err=~/^5\d\d/;
    ProbeErr("PCE-0401","Authorization error",    $respond) if $err==401;
} # foreach

ProbeErr("PCE-0030","Cannot get MODELID or FIRMWARE",$postmortem) if ! $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";
}

#------------------------------------------------------------------------------
# get video and audio properties ( only firmware 4.x 5.x)
#------------------------------------------------------------------------------
my %fmt2enc = ('mjpg' => 0, 'h264' => 2);
if($conf->{PROBE} eq 'DEFINE') {
	%result=(%result);
	my $req = "/cgi-x/get-compression";
	my $res = ProbeRequest($req);
	if ($res =~ /^HTTP ERROR/) {
		# one more try
		sleep 1;
		$res = ProbeRequest($req);
	}
	if($res !~ /^HTTP ERROR/) {
		my %properties = %{decode_json($res)};
        my @r_list = ();
        foreach my $resol (@{$properties{'optionsResolution'}}) {
            push @r_list, "$resol->[1]:$resol->[0]";
        }
        my @f_list = ();
        foreach my $fmt (@{$properties{'optionsEncoding'}}) {
            push @f_list, "$fmt->[1]:$fmt->[0]";
        }
		$result{IMAGESIZE_LIST}    = join(',', @r_list);
		#$result{MEDIA_FORMAT_LIST} = join(',', @f_list);
	}
}

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

#------------------------------------------------------------------------------
# set RC (rate control) parameters
#------------------------------------------------------------------------------
my $postParam = "encoding=$fmt2enc{$conf->{MEDIA_FORMAT}}&frameRateLimit=$conf->{FRAMERATE}&quality=$conf->{CAMCOMPRESSION}&resolution=$conf->{IMAGESIZE}";
#encoding=2&frameRateLimit=13&quality=15&resolution=2&bitrateLimit=12000&gopLength=30
if ($conf->{MEDIA_FORMAT} eq 'h264') { # only if media format is h264
    $postParam .= "&bitrateLimit=$conf->{RC_MAXBITRATE}&gopLength=$conf->{GOP}";
}
my $setResult = ProbeRequest('/cgi-x/set-compression', 'POST', [], $postParam);
if ($setResult !~ /^HTTP ERROR/) {
    $result{RC_SET}="OK";
} else {
#    print Dumper($setResult);
    $result{RC_SET} = "ERROR";
}
#------------------------------------------------------------------------------
# set AudioParams
#------------------------------------------------------------------------------
# final report-----------------------------------------------------------------------
ProbeResult(\%result);
