$deviceMatches[1], 'standards' => $standard, 'preferredStandard' => $preferredStandard, 'formats' => $formats, 'preferredFormat' => $preferredFormat, ); $inputs = array(); for ( $i = 0; $i < $deviceMatches[4]; $i++ ) { if ( !preg_match('/i'.$i.':([^|]+)\|i'.$i.'T:([^|]+)\|/', $deviceMatches[5], $inputMatches) ) { ZM\Error("Can't parse input '".$deviceMatches[5]."'"); continue; } if ( $inputMatches[2] == 'Camera' ) { $input = array( 'index' => $i, 'id' => $deviceMatches[1].':'.$i, 'name' => $inputMatches[1], 'free' => empty($monitors[$deviceMatches[1].':'.$i]), ); $inputMonitor = array( 'Type' => 'Local', 'Device' => $deviceMatches[1], 'Channel' => $i, 'Colours' => 3, 'Format' => $preferredStandard, 'Palette' => $preferredFormat, ); if ( $preferredStandard == 'NTSC' ) { $inputMonitor['Width'] = 320; $inputMonitor['Height'] = 240; } else { $inputMonitor['Width'] = 384; $inputMonitor['Height'] = 288; } if ( $preferredFormat == 'GREY' ) { $inputMonitor['Colours'] = 1; $inputMonitor['SignalCheckColour'] = '#000023'; } $inputDesc = base64_encode(json_encode($inputMonitor)); $inputString = $deviceMatches[1].', chan '.$i.($input['free']?(' - '.translate('Available')):(' ('.$monitors[$input['id']]['Name'].')')); $inputs[] = $input; $cameras[$inputDesc] = $inputString; } } $device['inputs'] = $inputs; $devices[] = $device; } # end foreach output line return $cameras; } # end function probeV4L // Probe Network Cameras // function probeAxis($ip) { $url = 'http://'.$ip.'/axis-cgi/admin/param.cgi?action=list&group=Brand'; $camera = array( 'model' => 'Unknown Axis Camera', 'monitor' => array( 'Type' => 'Remote', 'Protocol' => 'http', 'Host' => $ip, 'Port' => 80, 'Path' => '/axis-cgi/mjpg/video.cgi?resolution=320x240', 'Colours' => 3, 'Width' => 320, 'Height' => 240, ), ); if ( $lines = @file($url) ) { foreach ( $lines as $line ) { $line = rtrim( $line ); if ( preg_match('/^(.+)=(.+)$/', $line, $matches) ) { if ( $matches[1] == 'root.Brand.ProdShortName' ) { $camera['model'] = $matches[2]; break; } } } } return $camera; } function probePana($ip) { $url = 'http://'.$ip.'/Get?Func=Model&Kind=1'; $camera = array( 'model' => 'Unknown Panasonic Camera', 'monitor' => array( 'Type' => 'Remote', 'Protocol' => 'http', 'Host' => $ip, 'Port' => 80, 'Path' => '/nphMotionJpeg?Resolution=320x240&Quality=Standard', 'Colours' => 3, 'Width' => 320, 'Height' => 240, ), ); return $camera; } function probeActi($ip) { $url = 'http://'.$ip.'/cgi-bin/system?USER=Admin&PWD=123456&SYSTEM_INFO'; $camera = array( 'model' => 'Unknown Panasonic Camera', 'monitor' => array( 'Type' => 'Remote', 'Protocol' => 'rtsp', 'Method' => 'rtpUni', 'Host' => 'Admin:123456@'.$ip, 'Port' => 7070, 'Path' => '', 'Colours' => 3, 'Width' => 320, 'Height' => 240, ), ); if ( $lines = @file($url) ) { foreach ( $lines as $line ) { $line = rtrim( $line ); if ( preg_match('/^(.+?)\s*=\s*(.+)$/', $line, $matches) ) { if ( $matches[1] == 'Production ID' ) { $camera['model'] = 'ACTi '.substr($matches[2], 0, strpos($matches[2], '-')); break; } } } } return $camera; } function probeHikvision($ip) { $url = 'rtsp://admin:password@'.$ip.':554/Streaming/Channels/101?transportmode=unicast'; $camera = array( 'model' => 'Unknown Hikvision Camera', 'monitor' => array( 'Type' => 'FFmpeg', 'Path' => $url, 'Colours' => 4, 'Width' => 1920, 'Height' => 1080, ), ); return $camera; } function probeVivotek($ip) { $url = 'http://'.$ip.'/cgi-bin/viewer/getparam.cgi'; $camera = array( 'model' => 'Unknown Vivotek Camera', 'monitor' => array( 'Type' => 'Remote', 'Protocol' => 'rtsp', 'Method' => 'rtpUni', 'Host' => $ip, 'Port' => 554, 'Path' => '', 'Colours' => 3, 'Width' => 352, 'Height' => 240, ), ); if ( $lines = @file($url) ) { foreach ( $lines as $line ) { $line = rtrim($line); if ( preg_match('/^(.+?)\s*=\'(.+)\'$/', $line, $matches) ) { if ( $matches[1] == 'system_info_modelname' ) { $camera['model'] = 'Vivotek '.$matches[2]; } elseif ( $matches[1] == 'network_rtsp_port' ) { $camera['monitor']['Port'] = $matches[2]; } elseif ( $matches[1] == 'network_rtsp_s0_accessname' ) { $camera['monitor']['Path'] = $matches[2]; } } } } return $camera; } function probeWansview($ip) { $camera = array( 'model' => 'Wansview Camera', 'monitor' => array( 'Type' => 'Remote', 'Protocol' => 'http', 'Host' => 'admin:123456@'.$ip, 'Port' => 80, 'Path' => 'videostream.cgi', 'Width' => 640, 'Height' => 480, 'Palette' => 3 ), ); return $camera; } function get_arp_results() { $results = array(); $arp_command = ZM_PATH_ARP; $result = explode(' ', $arp_command); if ( !is_executable($result[0]) ) { ZM\Error('ARP compatible binary not found or not executable by the web user account. Verify ZM_PATH_ARP points to a valid arp tool.'); return $results; } if (count($result)==1) { $arp_command .= ' -n'; } $result = exec(escapeshellcmd($arp_command), $output, $status); if ($status) { ZM\Error("Unable to probe network cameras, status is '$status'"); return $results; } foreach ($output as $line) { if ( !preg_match('/(\d+\.\d+\.\d+\.\d+).*(([0-9a-f]{2}:){5})/', $line, $matches) ) { ZM\Debug("Didn't match preg $line"); continue; } $results[$matches[2]] = $matches[1]; // results[mac] = ip } return $results; } function get_arp_scan_results($network) { ZM\Debug("arp-scanning $network"); $results = array(); $arp_scan_command = ZM_PATH_ARP_SCAN; $result = explode(' ', $arp_scan_command); if (!is_executable($result[0])) { ZM\Error('arp-scan compatible binary not found or not executable by the web user account. Verify ZM_PATH_ARP_SCAN points to a valid arp-scan tool.'); return $results; } $arp_scan_command = '/usr/bin/pkexec '.ZM_PATH_ARP_SCAN.' '.$network.' 2>&1'; $result = exec(escapeshellcmd($arp_scan_command), $output, $status); if ($status) { ZM\Error("Unable to probe network cameras, command was $arp_scan_command, status is '$status' output: ".implode(PHP_EOL, $output)); return $results; } foreach ($output as $line) { if (preg_match('/(\d+\.\d+\.\d+\.\d+)\s+(([0-9a-f]{2}:){5})/', $line, $matches)) { $results[$matches[2]] = $matches[1]; } else { ZM\Debug("Didn't match preg $line"); } } return $results; } function probeNetwork() { $cameras = array(); $monitors = array(); foreach ( dbFetchAll("SELECT `Id`, `Name`, `Host` FROM `Monitors` WHERE `Type` = 'Remote' ORDER BY `Host`") as $monitor ) { if ( preg_match('/^(.+)@(.+)$/', $monitor['Host'], $matches) ) { //echo "1: ".$matches[2]." = ".gethostbyname($matches[2])."
"; $monitors[gethostbyname($matches[2])] = $monitor; } else { //echo "2: ".$monitor['Host']." = ".gethostbyname($monitor['Host'])."
"; $monitors[gethostbyname($monitor['Host'])] = $monitor; } } foreach ( dbFetchAll("SELECT `Id`, `Name`, `Path` FROM `Monitors` WHERE `Type` = 'Ffmpeg' ORDER BY `Path`") as $monitor ) { $url_parts = parse_url($monitor['Path']); ZM\Debug("Ffmpeg monitor ${url_parts['host']} = ${monitor['Id']} ${monitor['Name']}"); $monitors[gethostbyname($url_parts['host'])] = $monitor; } $macBases = array( '00:0f:7c' => array('type'=>'ACTi','probeFunc'=>'probeACTi'), '00:40:8c' => array('type'=>'Axis', 'probeFunc'=>'probeAxis'), '2c:a5:9c' => array('type'=>'Hikvision', 'probeFunc'=>'probeHikvision'), '00:80:f0' => array('type'=>'Panasonic','probeFunc'=>'probePana'), '00:02:d1' => array('type'=>'Vivotek','probeFunc'=>'probeVivotek'), '7c:dd:90' => array('type'=>'Wansview','probeFunc'=>'probeWansview'), '78:a5:dd' => array('type'=>'Wansview','probeFunc'=>'probeWansview') ); foreach ( get_arp_results() as $mac=>$ip ) { $macRoot = substr($mac,0,8); if ( isset($macBases[$macRoot]) ) { ZM\Debug("Have match for $macRoot ".$macBases[$macRoot]['type']); $macBase = $macBases[$macRoot]; $camera = call_user_func($macBase['probeFunc'], $ip); $sourceDesc = base64_encode(json_encode($camera['monitor'])); $sourceString = $camera['model'].' @ '.$host; if ( isset($monitors[$ip]) ) { $monitor = $monitors[$ip]; $sourceString .= ' ('.$monitor['Name'].')'; } else { $sourceString .= ' - '.translate('Available'); } $cameras[$sourceDesc] = $sourceString; } else { ZM\Debug("No match for $macRoot"); } } # end foreach output line if (isset($_REQUEST['interface']) and $_REQUEST['interface']) { foreach (get_subnets($_REQUEST['interface']) as $network) { foreach ( get_arp_scan_results($network) as $mac=>$ip ) { $macRoot = substr($mac,0,8); ZM\Debug("Got $macRoot from $mac"); if (isset($macBases[$macRoot])) { ZM\Debug("Have match for $macRoot $ip ".$macBases[$macRoot]['type']); $macBase = $macBases[$macRoot]; $camera = call_user_func($macBase['probeFunc'], $ip); $sourceDesc = base64_encode(json_encode($camera['monitor'])); $sourceString = $camera['model'].' @ '.$host; if (isset($monitors[$ip])) { $monitor = $monitors[$ip]; $sourceString .= ' ('.$monitor['Name'].')'; } else { $sourceString .= ' - '.translate('Available'); } $cameras[$sourceDesc] = $sourceString; } else { ZM\Debug("No match for $macRoot"); } } # end foreach output line } # end foreach network } # end if we have a network specified return $cameras; } # end function probeNetwork() $cameras = array(); $cameras[0] = translate('ChooseDetectedCamera'); if ( ZM_HAS_V4L2 ) $cameras += probeV4L(); $cameras += probeNetwork(); if ( count($cameras) <= 1 ) $cameras[0] = translate('NoDetectedCameras'); $focusWindow = true; xhtmlHeaders(__FILE__, translate('MonitorProbe') ); ?>

'changeInterface') ); ?>

'configureButtons')); ?>