Merge branch 'fix_onvif' into storageareas

This commit is contained in:
Isaac Connor 2016-10-04 15:00:28 -04:00
commit 96b5af9021
6 changed files with 152 additions and 121 deletions

View File

@ -77,6 +77,8 @@ my %soap_version_of :ATTR(:default<('1.1')>);
sub service sub service
{ {
my ($self, $serviceName, $attr) = @_; my ($self, $serviceName, $attr) = @_;
#print "service: " . $services_of{${$self}}{$serviceName}{$attr} . "\n";
# Please note that the Std::Class::Fast docs say not to use ident.
$services_of{ident $self}{$serviceName}{$attr}; $services_of{ident $self}{$serviceName}{$attr};
} }
@ -113,27 +115,59 @@ sub set_soap_version
delete $serializer_of{ ident $self }; delete $serializer_of{ ident $self };
} }
sub get_service_urls sub get_service_urls {
{
my ($self) = @_; my ($self) = @_;
my $result = $self->service('device', 'ep')->GetServices( { my $result = $self->service('device', 'ep')->GetServices( {
IncludeCapability => 'true', # boolean IncludeCapability => 'true', # boolean
},, },,
); );
if ( $result ) {
die $result if not $result; foreach my $svc ( @{ $result->get_Service() } ) {
# print $result . "\n"; my $short_name = $namespace_map{$svc->get_Namespace()};
my $url_svc = $svc->get_XAddr()->get_value();
foreach my $svc ( @{ $result->get_Service() } ) { if(defined $short_name && defined $url_svc) {
my $short_name = $namespace_map{$svc->get_Namespace()};
my $url_svc = $svc->get_XAddr()->get_value();
if(defined $short_name && defined $url_svc) {
# print "Got $short_name service\n"; # print "Got $short_name service\n";
$self->set_service($short_name, 'url', $url_svc); $self->set_service($short_name, 'url', $url_svc);
}
} }
# } else {
#print "No results from GetServices: $result\n";
} }
}
# Some devices do not support getServices, so we have to try getCapabilities
$result = $self->service('device', 'ep')->GetCapabilities( {}, , );
if ( ! $result ) {
print "No results from GetCapabilities: $result\n";
return;
}
# Result is a GetCapabilitiesResponse
foreach my $capabilities ( @{ $result->get_Capabilities() } ) {
foreach my $capability ( 'PTZ', 'Media', 'Imaging', 'Events', 'Device' ) {
if ( my $function = $capabilities->can( "get_$capability" ) ) {
my $Services = $function->( $capabilities );
if ( ! $Services ) {
print "Nothing returned ffrom get_$capability\n";
} else {
foreach my $svc ( @{ $Services } ) {
# The capability versions don't have a namespace, so just lowercase them.
my $short_name = lc $capability;
my $url_svc = $svc->get_XAddr()->get_value();
if( defined $url_svc) {
# print "Got $short_name service\n";
$self->set_service($short_name, 'url', $url_svc);
}
} # end foreach svr
}
} else {
print "No $capability function\n";
} # end if has a get_ function
} # end foreach capability
} # end foreach capabilities
} # end sub get_service_urls
sub http_digest { sub http_digest {
my ($service, $username, $password) = @_; my ($service, $username, $password) = @_;

View File

@ -272,7 +272,11 @@ sub _initialize {
# #
$_method =~s{\.}{__}xg; $_method =~s{\.}{__}xg;
$_method =~s{\-}{_}xg; $_method =~s{\-}{_}xg;
$list->[-1]->$_method( $current ); if ( $list->[-1]->can( $_method ) ) {
$list->[-1]->$_method( $current );
} else {
print ( "ERror " . $list->[-1] . " cannot $_method\n" );
}
$current = pop @$list; # step up in object hierarchy $current = pop @$list; # step up in object hierarchy

View File

@ -15,6 +15,7 @@ __PACKAGE__->__set_ref();
use base qw( use base qw(
SOAP::WSDL::XSD::Typelib::Element SOAP::WSDL::XSD::Typelib::Element
WSDiscovery10::Types::ProbeType WSDiscovery10::Types::ProbeType
WSDiscovery10::Types::ProbeMatchesType
); );
} }

View File

@ -1,4 +1,5 @@
#!/usr/bin/perl -w #!/usr/bin/perl -w
use strict;
# #
# ========================================================================== # ==========================================================================
# #
@ -41,6 +42,7 @@ require WSDiscovery::TransportUDP;
# Globals # Globals
my $verbose = 0; my $verbose = 0;
my $soap_version = undef;
my $client; my $client;
# ========================================================================= # =========================================================================
@ -172,60 +174,65 @@ sub discover
my $uuid_gen = Data::UUID->new(); my $uuid_gen = Data::UUID->new();
if($verbose) { if ( ( ! $soap_version ) or ( $soap_version eq '1.1' ) ) {
print "Probing for SOAP 1.1\n"
} if($verbose) {
my $svc_discover = WSDiscovery10::Interfaces::WSDiscovery::WSDiscoveryPort->new({ print "Probing for SOAP 1.1\n"
}
my $svc_discover = WSDiscovery10::Interfaces::WSDiscovery::WSDiscoveryPort->new({
# no_dispatch => '1', # no_dispatch => '1',
}); });
$svc_discover->set_soap_version('1.1'); $svc_discover->set_soap_version('1.1');
my $uuid = $uuid_gen->create_str(); my $uuid = $uuid_gen->create_str();
my $result = $svc_discover->ProbeOp( my $result = $svc_discover->ProbeOp(
{ # WSDiscovery::Types::ProbeType { # WSDiscovery::Types::ProbeType
Types => 'http://www.onvif.org/ver10/network/wsdl:NetworkVideoTransmitter http://www.onvif.org/ver10/device/wsdl:Device', # QNameListType Types => 'http://www.onvif.org/ver10/network/wsdl:NetworkVideoTransmitter http://www.onvif.org/ver10/device/wsdl:Device', # QNameListType
Scopes => { value => '' }, Scopes => { value => '' },
}, },
WSDiscovery10::Elements::Header->new({ WSDiscovery10::Elements::Header->new({
Action => { value => 'http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe' }, Action => { value => 'http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe' },
MessageID => { value => "urn:uuid:$uuid" }, MessageID => { value => "urn:uuid:$uuid" },
To => { value => 'urn:schemas-xmlsoap-org:ws:2005:04:discovery' }, To => { value => 'urn:schemas-xmlsoap-org:ws:2005:04:discovery' },
}) })
); );
# print $result . "\n"; print $result . "\n" if $verbose;
interpret_messages($svc_discover, \%services, @responses); interpret_messages($svc_discover, \%services, @responses);
@responses = (); @responses = ();
} # end if doing soap 1.1
if($verbose) { if ( ( ! $soap_version ) or ( $soap_version eq '1.2' ) ) {
print "Probing for SOAP 1.2\n" if($verbose) {
} print "Probing for SOAP 1.2\n"
$svc_discover = WSDiscovery10::Interfaces::WSDiscovery::WSDiscoveryPort->new({ }
my $svc_discover = WSDiscovery10::Interfaces::WSDiscovery::WSDiscoveryPort->new({
# no_dispatch => '1', # no_dispatch => '1',
}); });
$svc_discover->set_soap_version('1.2'); $svc_discover->set_soap_version('1.2');
# copies of the same Probe message must have the same MessageID. # copies of the same Probe message must have the same MessageID.
# This is not a copy. So we generate a new uuid. # This is not a copy. So we generate a new uuid.
$uuid = $uuid_gen->create_str(); my $uuid = $uuid_gen->create_str();
$result = $svc_discover->ProbeOp( # Everyone else, like the nodejs onvif code and odm only ask for NetworkVideoTransmitter
{ # WSDiscovery::Types::ProbeType my $result = $svc_discover->ProbeOp(
xmlattr => { 'xmlns:dn' => 'http://www.onvif.org/ver10/network/wsdl', { # WSDiscovery::Types::ProbeType
'xmlns:tds' => 'http://www.onvif.org/ver10/device/wsdl', }, xmlattr => { 'xmlns:dn' => 'http://www.onvif.org/ver10/network/wsdl', },
Types => 'dn:NetworkVideoTransmitter tds:Device', # QNameListType Types => 'dn:NetworkVideoTransmitter', # QNameListType
Scopes => { value => '' }, Scopes => { value => '' },
}, },
WSDiscovery10::Elements::Header->new({ WSDiscovery10::Elements::Header->new({
Action => { value => 'http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe' }, Action => { value => 'http://schemas.xmlsoap.org/ws/2005/04/discovery/Probe' },
MessageID => { value => "urn:uuid:$uuid" }, MessageID => { value => "urn:uuid:$uuid" },
To => { value => 'urn:schemas-xmlsoap-org:ws:2005:04:discovery' }, To => { value => 'urn:schemas-xmlsoap-org:ws:2005:04:discovery' },
}) })
); );
# print $result . "\n"; print $result . "\n" if $verbose;
interpret_messages($svc_discover, \%services, @responses);
} # end if doing soap 1.2
interpret_messages($svc_discover, \%services, @responses);
} }
@ -321,7 +328,7 @@ my $OPTIONS = "v";
sub HELP_MESSAGE sub HELP_MESSAGE
{ {
my ($fh, $pkg, $ver, $opts) = @_; my ($fh, $pkg, $ver, $opts) = @_;
print $fh "Usage: " . __FILE__ . " [-v] probe \n"; print $fh "Usage: " . __FILE__ . " [-v] probe <soap version>\n";
print $fh " " . __FILE__ . " [-v] <command> <device URI> <soap version> <user> <password>\n"; print $fh " " . __FILE__ . " [-v] <command> <device URI> <soap version> <user> <password>\n";
print $fh <<EOF print $fh <<EOF
Commands are: Commands are:
@ -359,14 +366,15 @@ if(!defined $action) {
} }
if($action eq "probe") { if($action eq "probe") {
$soap_version = shift;
discover(); discover();
} }
else { else {
# all other actions need URI and credentials # all other actions need URI and credentials
my $url_svc_device = shift; my $url_svc_device = shift @ARGV;
my $soap_version = shift; $soap_version = shift @ARGV;
my $username = shift; my $username = @ARGV ? shift @ARGV : '';
my $password = shift; my $password = @ARGV ? shift @ARGV: '';
$client = ONVIF::Client->new( { $client = ONVIF::Client->new( {
'url_svc_device' => $url_svc_device, 'url_svc_device' => $url_svc_device,

View File

@ -520,6 +520,7 @@ $SLANG = array(
'NewUser' => 'New User', 'NewUser' => 'New User',
'Next' => 'Next', 'Next' => 'Next',
'NoDetectedCameras' => 'No Detected Cameras', 'NoDetectedCameras' => 'No Detected Cameras',
'NoDetectedProfiles' => 'No Detected Profiles',
'NoFramesRecorded' => 'There are no frames recorded for this event', 'NoFramesRecorded' => 'There are no frames recorded for this event',
'NoGroup' => 'No Group', 'NoGroup' => 'No Group',
'NoneAvailable' => 'None available', 'NoneAvailable' => 'None available',

View File

@ -18,41 +18,40 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
// //
if ( !canEdit( 'Monitors' ) ) if ( !canEdit( 'Monitors' ) ) {
{ $view = 'error';
$view = "error";
return; return;
} }
$cameras = array(); $cameras = array();
$cameras[0] = translate('ChooseDetectedCamera'); $cameras[0] = translate('ChooseDetectedCamera');
$profiles = array();
$profiles[0] = translate('ChooseDetectedProfile');
function execONVIF( $cmd ) function execONVIF( $cmd ) {
{ $shell_command = escapeshellcmd(ZM_PATH_BIN . "/zmonvif-probe.pl $cmd");
exec( escapeshellcmd(ZM_PATH_BIN . "/zmonvif-probe.pl $cmd"), $output, $status );
if ( $status ) exec( $shell_command, $output, $status );
if ( $status ) {
$html_output = implode( '<br/>', $output ); $html_output = implode( '<br/>', $output );
Fatal( "Unable to probe network cameras, status is '$status'. Output was:<br/><br/> Fatal( "Unable to probe network cameras, status is '$status'. Output was:<br/><br/>
$html_output<br/><br/> $html_output<br/><br/>
Please the following command from a command line for more information:<br/><br/>". Please the following command from a command line for more information:<br/><br/>$shell_command"
ZM_PATH_BIN . "/zmonvif-probe.pl $cmd" ); );
}
return $output; return $output;
} }
function probeCameras( $localIp ) function probeCameras( $localIp ) {
{
$cameras = array(); $cameras = array();
$count = 0; $count = 0;
if ( $lines = @execONVIF( "probe" ) ) if ( $lines = @execONVIF( 'probe' ) ) {
{ foreach ( $lines as $line ) {
foreach ( $lines as $line )
{
$line = rtrim( $line ); $line = rtrim( $line );
if ( preg_match( '|^(.+),(.+),\s\((.*)\)$|', $line, $matches ) ) if ( preg_match( '|^(.+),(.+),\s\((.*)\)$|', $line, $matches ) ) {
{
$device_ep = $matches[1]; $device_ep = $matches[1];
$soapversion = $matches[2]; $soapversion = $matches[2];
$camera = array( $camera = array(
@ -65,15 +64,12 @@ function probeCameras( $localIp )
), ),
); );
foreach ( preg_split('|,\s*|', $matches[3]) as $attr_val ) { foreach ( preg_split('|,\s*|', $matches[3]) as $attr_val ) {
if( preg_match( '|(.+)=\'(.*)\'|', $attr_val, $tokens ) ) if( preg_match( '|(.+)=\'(.*)\'|', $attr_val, $tokens ) ) {
{
if($tokens[1] == "hardware") { if($tokens[1] == "hardware") {
$camera['model'] = $tokens[2]; $camera['model'] = $tokens[2];
} } elseif($tokens[1] == "name") {
elseif($tokens[1] == "name") {
$camera['monitor']['Name'] = $tokens[2]; $camera['monitor']['Name'] = $tokens[2];
} } elseif($tokens[1] == "location") {
elseif($tokens[1] == "location") {
// $camera['location'] = $tokens[2]; // $camera['location'] = $tokens[2];
} }
@ -86,21 +82,16 @@ function probeCameras( $localIp )
return( $cameras ); return( $cameras );
} }
function probeProfiles( $device_ep, $soapversion, $username, $password ) function probeProfiles( $device_ep, $soapversion, $username, $password ) {
{
$profiles = array(); $profiles = array();
$count = 0; $count = 0;
if ( $lines = @execONVIF( "profiles $device_ep $soapversion $username $password" ) ) if ( $lines = @execONVIF( "profiles $device_ep $soapversion $username $password" ) ) {
{ foreach ( $lines as $line ) {
foreach ( $lines as $line )
{
$line = rtrim( $line ); $line = rtrim( $line );
if ( preg_match( '|^(.+),\s*(.+),\s*(.+),\s*(.+),\s*(.+),\s*(.+),\s*(.+)\s*$|', $line, $matches ) ) if ( preg_match( '|^(.+),\s*(.+),\s*(.+),\s*(.+),\s*(.+),\s*(.+),\s*(.+)\s*$|', $line, $matches ) ) {
{
$stream_uri = $matches[7]; $stream_uri = $matches[7];
// add user@pass to URI // add user@pass to URI
if( preg_match( '|^(\S+://)(.+)$|', $stream_uri, $tokens ) ) if( preg_match( '|^(\S+://)(.+)$|', $stream_uri, $tokens ) ) {
{
$stream_uri = $tokens[1].$username.':'.$password.'@'.$tokens[2]; $stream_uri = $tokens[1].$username.':'.$password.'@'.$tokens[2];
} }
@ -133,25 +124,19 @@ xhtmlHeaders(__FILE__, translate('MonitorProbe') );
if( !isset($_REQUEST['step']) || ($_REQUEST['step'] == "1")) { if( !isset($_REQUEST['step']) || ($_REQUEST['step'] == "1")) {
$monitors = array(); $monitors = array();
foreach ( dbFetchAll( "select Id, Name, Host from Monitors where Type = 'Remote' order by Host" ) as $monitor ) foreach ( dbFetchAll( "select Id, Name, Host from Monitors where Type = 'Remote' order by Host" ) as $monitor ) {
{ if ( preg_match( '/^(.+)@(.+)$/', $monitor['Host'], $matches ) ) {
if ( preg_match( '/^(.+)@(.+)$/', $monitor['Host'], $matches ) )
{
//echo "1: ".$matches[2]." = ".gethostbyname($matches[2])."<br/>"; //echo "1: ".$matches[2]." = ".gethostbyname($matches[2])."<br/>";
$monitors[gethostbyname($matches[2])] = $monitor; $monitors[gethostbyname($matches[2])] = $monitor;
} } else {
else
{
//echo "2: ".$monitor['Host']." = ".gethostbyname($monitor['Host'])."<br/>"; //echo "2: ".$monitor['Host']." = ".gethostbyname($monitor['Host'])."<br/>";
$monitors[gethostbyname($monitor['Host'])] = $monitor; $monitors[gethostbyname($monitor['Host'])] = $monitor;
} }
} }
$detcameras = probeCameras( '' ); $detcameras = probeCameras( '' );
foreach ( $detcameras as $camera ) foreach ( $detcameras as $camera ) {
{ if ( preg_match( '|([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)|', $camera['monitor']['Host'], $matches ) ) {
if ( preg_match( '|([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)|', $camera['monitor']['Host'], $matches ) )
{
$ip = $matches[1]; $ip = $matches[1];
} }
$host = $ip; $host = $ip;
@ -220,15 +205,14 @@ if( !isset($_REQUEST['step']) || ($_REQUEST['step'] == "1")) {
} }
else if($_REQUEST['step'] == "2") else if($_REQUEST['step'] == "2")
{ {
if ( empty($_REQUEST['probe']) || empty($_REQUEST['username']) || if ( empty($_REQUEST['probe']) )
empty($_REQUEST['password']) ) Fatal("No probe passed in request. Please go back and try again.");
Fatal("Internal error. Please re-open this page."); #|| empty($_REQUEST['username']) ||
#empty($_REQUEST['password']) )
$probe = unserialize(base64_decode($_REQUEST['probe'])); $probe = unserialize(base64_decode($_REQUEST['probe']));
foreach ( $probe as $name=>$value ) foreach ( $probe as $name=>$value ) {
{ if ( isset($value) ) {
if ( isset($value) )
{
$monitor[$name] = $value; $monitor[$name] = $value;
} }
} }
@ -237,8 +221,7 @@ else if($_REQUEST['step'] == "2")
//print $monitor['Host'].", ".$_REQUEST['username'].", ".$_REQUEST['password']."<br/>"; //print $monitor['Host'].", ".$_REQUEST['username'].", ".$_REQUEST['password']."<br/>";
$detprofiles = probeProfiles( $monitor['Host'], $monitor['SOAP'], $_REQUEST['username'], $_REQUEST['password']); $detprofiles = probeProfiles( $monitor['Host'], $monitor['SOAP'], $_REQUEST['username'], $_REQUEST['password']);
foreach ( $detprofiles as $profile ) foreach ( $detprofiles as $profile ) {
{
$monitor = $camera['monitor']; $monitor = $camera['monitor'];
$sourceString = "${profile['Name']} : ${profile['Encoding']}" . $sourceString = "${profile['Name']} : ${profile['Encoding']}" .
@ -252,11 +235,11 @@ else if($_REQUEST['step'] == "2")
$monitor['Path'] = $profile['Path']; $monitor['Path'] = $profile['Path'];
// $sourceDesc = htmlspecialchars(serialize($monitor)); // $sourceDesc = htmlspecialchars(serialize($monitor));
$sourceDesc = base64_encode(serialize($monitor)); $sourceDesc = base64_encode(serialize($monitor));
$cameras[$sourceDesc] = $sourceString; $profiles[$sourceDesc] = $sourceString;
} }
if ( count($cameras) <= 0 ) if ( count($profiles) <= 0 )
$cameras[0] = translate('NoDetectedCameras'); $profiles[0] = translate('NoDetectedProfiles');
?> ?>
<body> <body>
@ -273,7 +256,7 @@ else if($_REQUEST['step'] == "2")
<?php echo translate('ProfileProbeIntro') ?> <?php echo translate('ProfileProbeIntro') ?>
</p> </p>
<p> <p>
<label for="probe"><?php echo translate('DetectedProfiles') ?></label><?php echo buildSelect( "probe", $cameras, 'configureButtons( this )' ); ?> <label for="probe"><?php echo translate('DetectedProfiles') ?></label><?php echo buildSelect( 'probe', $profiles, 'configureButtons( this )' ); ?>
</p> </p>
<div id="contentButtons"> <div id="contentButtons">
<input type="button" name="prevBtn" value="<?php echo translate('Prev') ?>" onclick="gotoStep1( this )"/> <input type="button" name="prevBtn" value="<?php echo translate('Prev') ?>" onclick="gotoStep1( this )"/>