#!/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
#       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;
use Data::Dumper;
# cons -------------------------------------------------------------------------
# no code for Verint

# --------- 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 $respond=ProbeRequest("/FramesetQuickStatus.asp");
if($respond!~ /^HTTP ERROR/) {
  $result{MODELID} = $1 if $respond =~ /Device Type:<\/b><\/?td><td.*?>(.+)</i;
  $result{FIRMWARE} = $1 if $respond =~ /Firmware Version:<\/b><\/?td><td.*?>(.+)</i;
}else {
  my ($err)= $respond=~/^HTTP ERROR \[(\d+)\]/;
  ProbeErr("PCE-0500","Device does not respond",$respond) if $err=~/^5\d\d/;
  ProbeErr("PCE-0401","Authorization error",    $respond) if $err==401;
}
ProbeErr("PCE-0030","Cannot get MODELID or FIRMWARE",$respond) 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 Sample picture 
#------------------------------------------------------------------------------
if($conf->{PROBE} eq 'DEFINE') {
   $result{SNAPSHOT}=ProbeSamplePicture();
}

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

# no code for Verint

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

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

# Configuration request:
#
#MenuSection=512
#ItemName_805568513=4000 - Target Bit Rate
#&ItemName_805568514=30 - Target Frame Rate
#&ItemName_805568515=4 - Minimum quantitazer (2-31)
#&ItemName_805568516=31 - Maximum quantitazer (2-31)
#&ItemName_805568542=0 - Input filter mode
#&ItemName_805568599=1 - Noise reduction filter mode
#&ItemName_805568543=1 - Resolution (1-QCIF, 2-CIF, 4-4CIF, 7-VGA)
#&ItemName_805568553=2 - Rate control mode (2-CBR)
#&ItemName_805568551=224.16.32.2 - Web multicast IP address
#&ItemName_805568552=2543 - Web multicast IP port
#&ItemName_805568547=30 - Intra interval
#&ItemName_805568567=1 - Compression mode (1- MPEG4, 4-MJPEG)
#&ok=Apply

# Adjusting framerate
# Assuming we have NTSC mode (TODO: check it out)
my $fr = $conf->{FRAMERATE};
if ($fr - 15 >= 8) {$fr = 30;}
elsif ($fr - 15 > 0 && $fr - 15 < 8) {$fr = 15;}
elsif ($fr < 15 && $fr > 10) {$fr = 15;}
elsif ($fr < 10 && $fr > 7) {$fr=10;}
elsif ($fr < 7 && $fr > 1) {$fr = 7;}
elsif ($fr < 1) {$fr = 1;}

$respond=ProbeRequest(
		"/goform/ConfigureParams",'POST',[],
		[
                   "MenuSection"=>"512",
                   "ItemName_805568513"=>$conf->{RC_TARGETBITRATE} eq "cam-defined" || $conf->{RC_TARGETBITRATE} eq "unlimited"?6000:($conf->{RC_TARGETBITRATE}>6000?6000:$conf->{RC_TARGETBITRATE}),
                   "ItemName_805568514"=>$fr,
                   "ItemName_805568515"=>$conf->{CAMCOMPRESSION}==1?"2":$conf->{CAMCOMPRESSION}*6,
                   "ItemName_805568516"=>$conf->{CAMCOMPRESSION}==1?"2":$conf->{CAMCOMPRESSION}*6+1,
                   "ItemName_805568543"=>$conf->{IMAGESIZE} eq "hugesize"?"4":($conf->{IMAGESIZE} eq "fullsize"?"2":"1"),
                   "ItemName_805568553"=>"2",
                   "ItemName_805568567"=>$conf->{MEDIA_FORMAT} eq "mjpg"?"4":"1",
                   "ok"=>"Apply"
                ]
);
ProbeErr("PCE-0040","Cannot update video settings",$respond) if $respond=~/^HTTP ERROR/;
# Save parameters to flash
$respond=ProbeRequest("/goform/SaveSettings");
ProbeErr("PCE-0040","Cannot update video settings",$respond) if $respond=~/^HTTP ERROR/;

# Bellow it's what happening in HTTP. Basicaly it's more related with GUI, but first request can be usefull 
# because it returns "Stream GUID" and "TargetSerialPort".
#
# 1) Get config:
$respond=ProbeRequest("/FramesetLiveView.asp?Command=Config&Audio=1&Serial=1&Connection=UTCP");
ProbeErr("PCE-0042","Cannot get video settings",$respond) if $respond=~/^HTTP ERROR/;

# Checking for this lines in the response:
# SourceGuid = "00000001-0000-0000-0000-00079AB664B1
# TargetSIp   = "82.207.126.122"
# TargetSPort = 5510

my $sourceGUID;
my $entropy;

open(DEVRANDOM, "/dev/random");
read(DEVRANDOM, $entropy, 6);
close(DEVRANDOM);

#my $targetGUID="CBE80C91-2297-4E40-8579-C62E843026C1";
my $targetGUID="CBE80C91-2297-4E40-8579-".(unpack("h*", $entropy))[0];

my $targetSIP;
my $targetSPort;

if ($respond !~ m{SourceGuid\s*=\s*"([A-F\d\-]+)"?}s) 
{
	ProbeErr("PCE-0042","Cannot get video settings: Response unknown",$respond);
}
$sourceGUID = $1;

if ($respond !~ m{TargetSIp\s*=\s*"([\d\.]+)"?}s) 
{
	ProbeErr("PCE-0042","Cannot get video settings: Response unknown",$respond);
}
$targetSIP = $1;

if ($respond !~ m{TargetSPort\s*=\s*([\d]+)?}s) 
{
	ProbeErr("PCE-0042","Cannot get video settings: Response unknown",$respond);
}
$targetSPort = $1;

# Ignore this, seems it's useless.
# 2) Command "View"
#$resp = $ua->get("http://207.207.176.25/FramesetLiveView.asp?Command=View&Popup=0&Connection=UTCP&Audio=1&Serial=1");
#if ($resp->is_error())
#{
#    die "HTTP error: " . $resp->status_line ;
#}

# 3) Command StartStreaming
$respond=ProbeRequest("/FramesetRightCommand.asp?command=StartStreaming&TargetIp=$targetSIP&TargetPort=0 \
                  &TargetGuid=$targetGUID&Connection=UTCP&SourceGuid=$sourceGUID&TargetAudioIp=$targetSIP&TargetAudioPort=0 \
                  &TargetSerialIp=$targetSIP&TargetSerialPort=$targetSPort&FakeParam=1");
ProbeErr("PCE-0040","Cannot start streaming",$respond) if $respond=~/^HTTP ERROR/;

# 4) Command "KeepAlive". I not yet digged for what this, but keep it for now.
$respond=ProbeRequest("/FramesetRightCommand.asp?command=KeepAlive&TargetGuid=$targetGUID \
                  &TargetIp=$targetSIP&TargetPort=0&SourceGuid=$sourceGUID&TargetAudioIp=$targetSIP&TargetAudioPort=0&FakeParam=1");
ProbeErr("PCE-0040","Cannot set keepalive",$respond) if $respond=~/^HTTP ERROR/;

$result{VSIP_TARGET_GUID} = $targetGUID;
$result{VSIP_SOURCE_GUID} = $sourceGUID;
$result{VSIP_TARGET_SIP}  = $targetSIP;
$result{VSIP_PORT}  = $targetSPort;
$targetGUID =~ s/\-//g;
$sourceGUID =~ s/\-//g;
$result{DEFINEDUID} = "$targetGUID"."02"."$sourceGUID";

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

