#!/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;

# -- 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 %result=(MODELID=>'0',FIRMWARE=>'0.0',STATUS=>'OK',RC_SET=>'NONE',AUDIO_SET=>'NONE');

my @DEFINE_PATH = (
  "/cgi-bin/getinfo?FILE=caminfo.html&PAGE=1111",
  "/cgi-bin/getinfo?FILE=1&page=1111",
  "/Get?Func=Model&Kind=1"
);

my $rsp;
my %params;

foreach my $path (@DEFINE_PATH) {
  $rsp = ProbeRequest($path);
  if ($rsp !~ /^HTTP ERROR/) {
    $result{MODELID}   = $1 if $rsp =~ /NAME=(.+)\b/i;
    $result{MODELID} ||= $1 if $rsp =~ /ModelName:(.+)/;
    $result{FIRMWARE}  = $1 if $rsp =~ /VERSION=(.+)\b/i;
    $result{FIRMWARE}||= $1 if $rsp =~ /BootFirm:(.+)/;
    last if $result{MODELID};
  } 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;
  }
}

ProbeErr("PCE-0030","Cannot get MODELID or FIRMWARE",$rsp) 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 --
if ($result{FIRMWARE} =~ m/V4\.[1-3]\dR\d\d/) {
    $rsp = ProbeRequest('/Get?Func=ValidResolution&Kind=1');
    if ($rsp !~ /^HTTP ERROR/) {
	my ($image_size_list, $media_format_list);

	%params = map { if (/^(.+)\s*:\s*(.+)$/) {(NormMediaFormat($1),$2)}}  split /\r?\n/, $rsp;
	foreach(keys %params) {
	    $params{$_} =~ s/\s*,\s*/\\,/g;
	    $image_size_list .= "$_:$params{$_},";
	    $media_format_list .= "$_,";
	}
	chop($media_format_list);
	chop($image_size_list);
	$result{CURRENT_FORMAT} = $media_format_list =~ m/.*h264.*/ ? 'h264' : 'mpeg4';
	$result{MEDIA_FORMAT} = $conf->{MEDIA_FORMAT};
    } 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;
    }
}


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

# -------------------------------------------------------------------------------
# -- set RC (rate control) parameters -------------------------------------------
# -------------------------------------------------------------------------------

my ($url,$url2)=("","");
my $param={};


if ($result{MODELID} eq 'NP472') {
    # Model not supported
} elsif ($result{MODELID} eq 'WV-NS202') {
    if ($conf->{MEDIA_FORMAT} eq 'mpeg4') {
	$url = "/cgi-bin/set_mpeg";
        $param = {
    	    'mpeg_transmit' => '1',
    	    'mpeg_resolution' => '320',
    	    'mpeg_bandwidth' => '64',
	    'mpeg_quality' => 'normal',
	    'mpeg_unimulti' => 'uni'
	};
        $param->{mpeg_resolution}=$conf->{IMAGESIZE} if defined $conf->{IMAGESIZE};
        $param->{mpeg_bandwidth} =$conf->{RC_MAXBITRATE} 
    	    if defined $conf->{RC_MAXBITRATE} and $conf->{RC_MAXBITRATE} ne 'cam-defined';
        $param->{mpeg_quality}=$conf->{CAMCOMPRESSION_MPEG4} if defined $conf->{CAMCOMPRESSION_MPEG4};
    } else {
        ### Disable mpeg4 stream ###
        $url="/cgi-bin/set_mpeg";
        $param = {
    	    'mpeg_transmit' => '0'
        };
	
	$rsp = ProbeRequest($url,'POST',[],$param);
        if ($rsp =~ /^HTTP ERROR/) {
	    ProbeErr("PCE-0040","can't disable mpeg4 stream at $result{MODELID}", $rsp);
	}
        ###
        $url="/cgi-bin/set_jpeg";
        $param = {
    	    'jpeg_interval' => '5',
	    'jpeg_quality' => '5',
	    'jpeg_resolution' => '320'
	};
	$param->{jpeg_resolution}=$conf->{IMAGESIZE} if defined $conf->{IMAGESIZE};
        $param->{jpeg_interval}  =$conf->{FRAMERATE} if defined $conf->{FRAMERATE};
        $param->{jpeg_quality}   =$conf->{CAMCOMPRESSION_MJPG} if defined $conf->{CAMCOMPRESSION_MJPG};
    }
    $rsp = ProbeRequest($url,'POST',[],$param);
    if ($rsp =~ /^HTTP ERROR/) {
	ProbeErr("PCE-0040","can't configure stream",$rsp);
    }
} elsif ($result{MODELID} eq 'WV-NW502S') {
    my $smode;

    ##### GET UID ########################################
    $url="/cgi-bin/getuid?FILE=2&vcodec=jpeg&page=1112";
    $rsp = ProbeRequest($url);
    if ($rsp !~ /^HTTP ERROR/) {
	$result{UID} = $1 if $rsp =~ /UID=(.+)\b/i;
    } else {
	ProbeErr("PCE-0040","Can't get image mode and UID",$rsp);
    }
    ProbeErr("PCE-0040","UID not defined") unless defined $result{UID};

    ######## CONFIGURE STREAM NOW #########################
    if ($conf->{MEDIA_FORMAT} eq 'mjpg') {
	$url="/cgi-bin/set_jpeg";
	$param = {
	    'jpeg_interval' => '5',
	    'jpeg_quality' => '5',
	    'jpeg_resolution' => '320'
	};
	$param->{jpeg_interval}   = $conf->{FRAMERATE} if defined $conf->{FRAMERATE};
	$param->{jpeg_resolution} = '640'  if $conf->{IMAGESIZE} eq 'VGA';
	$param->{jpeg_resolution} = '1280' if $conf->{IMAGESIZE} eq '1280x960';
	$param->{jpeg_resolution} = '2048' if $conf->{IMAGESIZE} eq '2048x1536';
	$param->{jpeg_quality}    = $conf->{CAMCOMPRESSION} if defined $conf->{CAMCOMPRESSION};

    } elsif ($conf->{MEDIA_FORMAT} eq 'mpeg4') {
	$url ="/cgi-bin/set_mpeg";
	$url2="/cgi-bin/set_stream";
	$smode = 'stream_mode=0';
	$param = {
		'rtsp_mode' => '1',
		'f_priority' => '1',
		'mpeg_transmit' => '1',
		'mpeg_resolution' => '320',
		'mpeg_bandwidth' => '64',
		'nr_framerate' => '5'
	};
	$param->{'nr_framerate'} = $conf->{FRAMERATE} if defined $conf->{FRAMERATE};
	$param->{'mpeg_bandwidth'} = $conf->{RC_MAXBITRATE} if defined $conf->{RC_MAXBITRATE};
	delete $param->{'mpeg_bandwidth'} if $param->{'mpeg_bandwidth'} eq 'cam-defined';
	$param->{'mpeg_resolution'} = '640' if $conf->{IMAGESIZE} eq 'VGA';
    } else { ### assume media format h.264
	$url = "/cgi-bin/set_h264";
	$url2= "/cgi-bin/set_stream";
	$smode = 'stream_mode=1';
	$param = {
		'h264_rtsp_mode' => '1',
		'f_priority' => '1',
		'h264_transmit' => '1',
		'h264_resolution' => '320',
		'h264_bandwidth' => '64',
		'nr_framerate' => '5'
	};
	$param->{nr_framerate} = $conf->{FRAMERATE} if defined $conf->{FRAMERATE};
	$param->{h264_bandwidth} = $conf->{RC_MAXBITRATE} if defined $conf->{RC_MAXBITRATE};
	delete $param->{h264_bandwidth} if $param->{h264_bandwidth} eq 'cam-defined';
	$param->{h264_resolution} = '640' if $conf->{IMAGESIZE} eq 'VGA';
	$param->{h264_resolution} = '1280' if $conf->{IMAGESIZE} eq '1280x960';
    }
		
    if(defined($smode)) {
	$rsp = ProbeRequest($url2,'POST',[],$smode);
	if ($rsp =~ /^HTTP ERROR/) {
		ProbeErr("PCE-0040","can't set stream mode",$rsp);
	}
    }
    $rsp = ProbeRequest($url,'POST',[],$param);
    if ($rsp =~ /^HTTP ERROR/) {
	ProbeErr("PCE-0040","can't configure",$rsp);
    }
} elsif (($result{MODELID} eq 'BB-HCM701A') || ($result{MODELID} eq 'BL-C210A')) {
    my $req = '/Set?Func=VDelivery&Kind=1';

    # -- if stream format changed --
    if ($conf->{MEDIA_FORMAT} ne $result{CURRENT_FORMAT}) {

	#print "media format mode changed restart needed...\n";
	if ($conf->{MEDIA_FORMAT} eq 'h264') {
	    $req .= '&Format=H.264';
	} else {
	    $req .= '&Format=MPEG-4';
	}
    }

    # -- set video stream parameters --
    unless ($conf->{MEDIA_FORMAT} =~ /mjpg|audio/) {
	my ($isize) = $conf->{IMAGESIZE} =~ m/(\d+)x\d+/;
	if ($conf->{MEDIA_FORMAT} eq 'mpeg4') {
	    my %framerate = ('640' => '640framerate','320' => '320framerate','192' => '192framerate');
	    my %minbr = ('640' => '640bitrateL','320' => '320bitrateL','192' => '192bitrateL');
	    my %maxbr = ('640' => '640bitrateH','320' => '320bitrateH','192' => '192bitrateH');
	    if (defined $conf->{FRAMERATE}) {
		$req .= "&$framerate{$isize}=$conf->{FRAMERATE}";
	    }
	    if (defined $conf->{RC_TARGETBITRATE}) {
		$req .= "&$minbr{$isize}=$conf->{RC_TARGETBITRATE}";
	    }
	    if (defined $conf->{RC_MAXBITRATE}) {
		$req .= "&$maxbr{$isize}=$conf->{RC_MAXBITRATE}";
	    }
	} elsif ($conf->{MEDIA_FORMAT} eq 'h264') {
	    my %framerate = ('640' => '640H264framerate','320' => '320H264framerate');
	    my %minbr = ('640' => '640H264bitrateL','320' => '320H264bitrateL');
	    my %maxbr = ('640' => '640H264bitrateH','320' => '320H264bitrateH');
	    if (defined $conf->{FRAMERATE}) {
		$req .= "&$framerate{$isize}=$conf->{FRAMERATE}";
	    }
	    if (defined $conf->{RC_TARGETBITRATE}) {
		$req .= "&$minbr{$isize}=$conf->{RC_TARGETBITRATE}";
	    }
	    if (defined $conf->{RC_MAXBITRATE}) {
		$req .= "&$maxbr{$isize}=$conf->{RC_MAXBITRATE}";
	    }

	}
	$rsp = ProbeRequest($req);
	if ($rsp =~ /^HTTP ERROR/) {
	    ProbeErr("PCE-0040","can't set stream mode",$rsp);
	}
    }
    
    # -- set audio --

    if ($conf->{AUDIO} eq 'on') {
	$req = "/Set?Func=AudioSetup&Kind=1&OutputEnable=1&TimeOut=3600&InputEnable=1";
    } else {
	$req = "/Set?Func=AudioSetup&Kind=1&OutputEnable=0&InputEnable=0";
    }
    $rsp = ProbeRequest($req);
    if ($rsp =~ /^HTTP ERROR/) {
	ProbeErr("PCE-0040","can't set audio stream", $rsp);
    }
}

# -- set AudioParams --
if ($result{MODELID} eq 'WV-NS202') {
    if ($conf->{AUDIO} eq 'on') {
	$param = {
	    'audio' => 'inout',
	    'audio_bitrate' => '16',
	    'audio_sens' => 'middle',
	    'audio_interval' => '40',
	    'out_sens' => 'middle',
	    'out_interval' => '320',
	    'audio_level' => 'all'
	};
    } else {
	$param = {
	    'audio' => 'off'
	};
    }
    
    $url="/cgi-bin/set_audio";
    $rsp = ProbeRequest($url,'POST',[],$param);
    if ($rsp =~ /^HTTP ERROR/) {
	ProbeErr("PCE-0050","can't configure audio",$rsp);
    }
} elsif ($result{MODELID} eq 'WV-NW502S') {
    if ($conf->{AUDIO} eq 'on') {
	$param = {
		'audio' => 'inout_full',
		'audio_bitrate' => '16',
		'audio_sens' => 'middle',
		'audio_interval' => '40',
		'out_sens' => 'middle',
		'out_interval' => '320',
		'audio_level' => 'all'
	};
    } else {
	$param = {
	    'audio' => 'off'
	};
    }
    $url = "/cgi-bin/set_audio";
    $rsp = ProbeRequest($url,'POST',[],$param);
    if ($rsp =~ /^HTTP ERROR/) {
	ProbeErr("PCE-0050","can't configure audio",$rsp);
    }
}

$result{RC_SET} = 'OK';
$result{AUDIO_SET} = 'OK';
# -- final report --
ProbeResult(\%result);
