I have a network-attached SNC-RZ30n that I've been dying to get a control script for, but sadly, only a serial-attached script was provided by ZM. So, using it as a bit of a reference, and also the PDF manual provided by goreo95033, I whipped up a functioning control script.
Code: Select all
#!/usr/bin/php
<?php
/*
* Contributed by: Ammaross Danan
* If this breaks your camera, it is not my fault.
* Use at your own risk.
* Some functions (such as sleep and wake) were ommitted.
* The queryParameter function is supplied if you would like to fetch
* current settings from the camera. (not tested)
* Manual: http://www.cs.unc.edu/Research/stc/FAQs/Cameras_Lenses/Sony/New%20SNC-RZ30N_CGI%20Manual%202.00EN.pdf
*/
$_ARG; // holds our command line arguments
// Decodes our command line arguments
function arguments($argv) {
$_ARG = array();
foreach ($argv as $arg) {
if (ereg('--([^=]+)=(.*)',$arg,$reg)) {
$_ARG[$reg[1]] = $reg[2];
} elseif(ereg('-([a-zA-Z0-9])',$arg,$reg)) {
$_ARG[$reg[1]] = 'true';
}
}
return $_ARG;
}
function def(&$arg,$default) {
if ( !isset($arg) )
return $default;
else
return $arg;
}
// queries the camera for current stat of param
function queryParameter($param) {
global $_ARG;
$fp = @get_file_contents("http://$_ARG[address]/command/visca-inquiry.cgi?visca=$visca", "r");
if ( $fp == FALSE )
; // error occured
else
{
// Data is stored in post area at end of results. Problem is, it
// doesn't follow standard \r\n\r\n to seperate it, but only a single
// \r\n, so can't strstr for it... It does provide a content-length
// parameter, so we use that value and step back from the end of
// a stringified version of the file...
$pos = strpos( $fp, "Content-Length: " );
$pos2 = strpos( $fp, "\r\n", $pos );
$content_length = intval(substr( $fp, $pos + strlen("Content-Length: "), $pos2-$pos ));
$status = substr( $fp, $content_length*-1 );
return $status;
}
return "";
}
// Issues the command to the camera
function doCmd($visca) {
global $_ARG;
$fp = @fopen("http://$_ARG[address]/command/visca-gen.cgi?visca=$visca", "r");
if ( $fp == 0 )
; // error occured
else
fclose($fp); // we're fine
}
$_ARG = arguments($_SERVER['argv']); // $_SERVER for backwards compatibility
/* // Uncomment for DEBUG if you wish
$logfile = fopen( "/var/log/zmcontrol.log", "a" );
fprintf($logfile, "ARGV: %s\n", serialize($_SERVER['argv']) );
fclose($logfile);
*/
$visca = "";
switch( def($_ARG['command'],"") )
{
case "move_stop":
$visca = sprintf( "81010601%02X%02X0303FF", 0, 0 ); break;
case "move_con_up":
$visca = sprintf( "81010601%02X%02X0302FF", 0, def($_ARG['tiltspeed'],3) ); break;
case "move_con_down":
$visca = sprintf( "81010601%02X%02X0301FF", 0, def($_ARG['tiltspeed'],3) ); break;
case "move_con_left":
$visca = sprintf( "81010601%02X%02X0203FF", def($_ARG['panspeed'],3), 0 ); break;
case "move_con_right":
$visca = sprintf( "81010601%02X%02X0103FF", def($_ARG['panspeed'],3), 0 ); break;
case "move_con_upleft":
$visca = sprintf( "81010601%02X%02X0202FF", def($_ARG['panspeed'],3), def($_ARG['tiltspeed'],3) ); break;
case "move_con_upright":
$visca = sprintf( "81010601%02X%02X0102FF", def($_ARG['panspeed'],3), def($_ARG['tiltspeed'],3) ); break;
case "move_con_downleft":
$visca = sprintf( "81010601%02X%02X0201FF", def($_ARG['panspeed'],3), def($_ARG['tiltspeed'],3) ); break;
case "move_con_downright":
$visca = sprintf( "81010601%02X%02X0101FF", def($_ARG['panspeed'],3), def($_ARG['tiltspeed'],3) ); break;
case "move_rel_up":
$visca = sprintf( "81010603%02X%02X%08X%08XFF", 0, def($_ARG['tiltspeed'],3), 0, def($_ARG['tiltstep'],0x03CC) ); break;
case "move_rel_down":
$visca = sprintf( "81010603%02X%02X%08X%08XFF", 0, def($_ARG['tiltspeed'],3), 0, def($_ARG['tiltstep'],0xFCC4) ); break;
case "move_rel_left":
$visca = sprintf( "81010603%02X%02X%08X%08XFF", def($_ARG['panspeed'],3), 0, def($_ARG['panstep'],0xF670), 0 ); break;
case "move_rel_right":
$visca = sprintf( "81010603%02X%02X%08X%08XFF", def($_ARG['panspeed'],3), 0, def($_ARG['panstep'],0x0990), 0 ); break;
case "move_rel_upleft":
$visca = sprintf( "81010603%02X%02X%08X%08XFF", def($_ARG['panspeed'],3), def($_ARG['tiltspeed'],3), def($_ARG['panstep'],0xF670), def($_ARG['tiltstep'],0x03CC) ); break;
case "move_rel_upright":
$visca = sprintf( "81010603%02X%02X%08X%08XFF", def($_ARG['panspeed'],3), def($_ARG['tiltspeed'],3), def($_ARG['panstep'],0x0990), def($_ARG['tiltstep'],0x03CC) ); break;
case "move_rel_downleft":
$visca = sprintf( "81010603%02X%02X%08X%08XFF", def($_ARG['panspeed'],3), def($_ARG['tiltspeed'],3), def($_ARG['panstep'],0xF670), def($_ARG['tiltstep'],0xFCC4) ); break;
case "move_rel_downright":
$visca = sprintf( "81010603%02X%02X%08X%08XFF", def($_ARG['panspeed'],3), def($_ARG['tiltspeed'],3), def($_ARG['panstep'],0x0990), def($_ARG['tiltstep'],0xFCC4) ); break;
case "zoom_rel_tele":
case "zoom_con_tele":
$visca = sprintf( "810104072%1XFF", def($_ARG['speed'],4) ); break;
case "zoom_rel_wide":
case "zoom_con_wide":
$visca = sprintf( "810104073%1XFF", def($_ARG['speed'],4) ); break;
case "zoom_stop":
$visca = "8101040700FF"; break;
case "focus_con_near":
$visca = "8101040803FF"; break;
case "focus_con_far":
$visca = "8101040802FF"; break;
case "focus_stop":
$visca = "8101040800FF"; break;
case "focus_auto":
$visca = "8101043802FF"; break;
case "focus_man":
$visca = "8101043803FF"; break;
case "preset_goto":
$visca = sprintf( "8101043F02%02XFF", def($_ARG['preset'],0) ); break;
case "preset_clear":
$visca = sprintf( "8101043F00%02XFF", def($_ARG['preset'],0) ); break;
case "preset_set":
$visca = sprintf( "8101043F01%02XFF", def($_ARG['preset'],0) ); break;
case "preset_home":
$visca = "81010604FF"; break;
default:
echo "Command not supported: " . def($_ARG['command'],"") . "\n";
return;
}
doCmd( $visca );
// Any commands that require a timeout...
switch( def($_ARG['command'],"") )
{
case "zoom_con_tele":
case "zoom_con_wide":
usleep(1000000*$_ARG['autostop']);
doCmd( "8101040700FF" );
break; // zoom stop
case "move_con_up":
case "move_con_down":
case "move_con_left":
case "move_con_right":
case "move_con_upleft":
case "move_con_upright":
case "move_con_downleft":
case "move_con_downright":
usleep(1000000*$_ARG['autostop']);
doCmd( sprintf("81010601%02X%02X0303FF",0,0) );
break;
case "focus_con_near":
case "focus_con_far":
usleep(1000000*$_ARG['autostop']);
doCmd( "8101040800FF" );
break;
}
?>
As it states, it is a use-at-own-risk script, but it works for my camera. As a suggestion, it would be nice to add a [near] and [far] button on the zooming feature that will zoom all the way in/out (con-zooming) and then just use the current arrows for step(rel)-zooming. This script uses the timeout to do step pan/tilt/zoom to overcome the continuous mode default.
Adding the script:
Copy the script to /usr/local/bin/zmcontrol-visca.php
Be sure to: chmod a+x /usr/local/bin/zmcontrol-visca.php
Make sure controllable cameras is enabled in the config.
Open your camera monitor page, then click on the control tab.
Enable 'Controllable' on the camera.
Click "Edit" next to Control Type.
Add New Control
Main Tab:
- Name: Sony VISCA
Type: Remote
Command: zmcontrol-visca.php
Move Tab:
- Can Move: checked
Can Move Diagonally: checked
Can Move Relative: checked
Can Move Continuous: checked
Pan Tab:
- Can Pan: checked
Min Pan Range: 2448
Max Pan Range: 63088
Min Pan Step: 100
Max Pan Step: 10000
Has Pan Speed: checked
Min Pan Speed: 0
Max Pan Speed: 24
Tilt Tab:
- Can Tilt: checked
Min Tilt Range: 972
Max Tilt Range: 64708
Min Tilt Step: 100
Max Tilt Step: 5000
Has Tilt Speed: checked
Min Tilt Speed: 0
Max Tilt Speed: 20
Zoom Tab:
- Can Zoom: checked
Can Zoom Continuous: checked
Min Zoom Range: 0
Max Zoom Range: 30464
Min Zoom Step: 10
Max Zoom Step: 4000
Has Zoom Speed: checked
Min Zoom Speed: 0
Max Zoom Speed: 7
Focus Tab:
- Can Focus: checked
Can Auto Focus: checked
Can Focus Continuous: checked
Min Focus Range: 0
Max Focus Range: 15
Presets Tab:
- Has Presets: checked
Num Presets: 16
Has Home Preset: checked
Can Set Presets: checked
Save the control settings.
Back on the control tab of your camera monitor page:
- Controllable: checked
Control Type: Sony VISCA
Control Address: <user>:<passwd>@<ipaddress>
Auto Stop Timeout: 0.25
The <user>:<passwd>@ only needs to be used if you have set up security users and an admin user/password, since normal users don't have CGI access to move the camera around...
Once you save your camera, you can now use the ZM controls to spy on those people in the parking lot...
PS. ZM, this might be something to review and include in next version. I know you're rewriting the control code a bit, but this works in the meantime.
Let me know if I missed anything.