Rovio

From ZoneMinder Wiki
Jump to navigationJump to search

Rovio is a robot webcam from WowWee http://www.wowwee.com/ .

Here's what I've done to get my Rovio working in ZoneMinder with PTZ functionality.

Rovio setup: Create a username and password in the Rovio under Settings-> Security tab. Guest access should be fine. (As of this writing, the newer Java applet has not been tested and is assumed not to work with ZoneMinder). Configure Rovio's Resolution to 640x480 and High.

In Zoneminder “Add new Monitor” -Set “Source Type” to “Remote” on the General tab The Source tab has more settings. It is the left picture. The right is the Control Tab. Later we will explain how to setup the Control Type and named “Rovio” (If you don't have a “Control” Tab, then from the ZoneMinder console check the box in “Options” -> “System” Tab -> “OPT_CONTROL ”)

Rovio1.jpg Rovio2.jpg

To create the Rovio Control Type: Edit -> “Add New Control” (This is on the control tab of the Monitor you just created for your Rovio.) Configure the following settings, tabs not shown are left with default settings.

Rovio3.jpg Rovio4.jpg

Rovio5.jpg Rovio6.jpg

Rovio7.jpg Rovio8.jpg

Rovio9.jpg


Once all of that is set. Now you need to create/copy the Rovio.pm file to your ZoneMinder PTZ Control directory. (See Hints further down on this page to locate the PTZ control directory on your ZoneMinder server.) The Rovio.pm file has been posted at the end of this article.

The Rovio.pm PTZ script has the ability to use paths that you have previously defined in your Rovio. You must edit the Rovio.pm file to reflect your path names. Look for a line beginning with "#Define your Rovio Path names here." and edit as appropriate.

Rovio Control Tab Notes: The “Focus” arrows are used to turn the headlight on and off. The “Zoom” buttons will move the Rovio's head up and down. The numbered buttons 1-8 will point to paths you have defined in your Rovio as described above.

Hints:

1. zmcontrol.pl and Debugging. If you are having PTZ issues and are not sure what is going on, check /tmp/zmcontrol-9.log To enable debug: which zmcontrol.pl edit /usr/local/bin/zmcontrol.pl (This is where I found the file on my OpenSuSE install) and change the line “use constant DBG_LEVEL => 0” Change 0 to 1.

2. Zoneminder PTZ Control Files It was tricky to find this location for me, but on my OpenSuSE install, the control file directory is : “/usr/lib/perl5/site_perl/5.10.0/ZoneMinder/Control/” Files in this location include: AxisV2.pm and PanasonicIP.pm. (You may be able to use “locate” to find one of these if you have trouble finding the Control directory.

3. Testing PTZ from command line You can test scripts by running “zmcontrol.pl --id 9 --command=moveConDownLeft” You can get the --id number by hovering over a camera in the webconsole and looking at the end of the url listed as “mid=9” An example: http://zoneminder/zm/index.php?view=watch&mid=9

To get the --command value, use one of the “Sub moveConDownLeft” from the control .pm file

Also, note. If you do this as any other user except your web server user, you will need to change the permissions on the /tmp/zmcontrol-*.sock file. Otherwise you will get the error message “Can't bind: Address already in use” chown wwwrun:www /tmp/zmcontrol-9.sock

4. If you edit the .pm control file, you may need do the following before the changes will take place:

killall -9 zmcontrol.pl

Restart Zoneminder (either from command line or from the web console).

Restart Apache

5. Rovio API Documentation: http://www.wowwee.com/static/support/rovio/manuals/Rovio_API_Specifications_v1.2.pdf

Here is the content of the Rovio.pm control File

(Disclaimer: This was not written by a programmer, but a hack with a Rovio :-) )

# ==========================================================================
#
# ZoneMinder Wowwee Rovio Control Protocol Module, $Date: 2010-05-22 
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
# ==========================================================================
#
# This module contains the implementation of the Wowwee Rovio camera control
# protocol
#
# Rovio API settings can be found at 
#http://www.wowwee.com/static/support/rovio/manuals/Rovio_API_Specifications_v1.2.pdf OR
#http://www.wowee.com/ under Rovio support.
#
package ZoneMinder::Control::Rovio;

use 5.006;
use strict;
use warnings;

require ZoneMinder::Base;
require ZoneMinder::Control;

our @ISA = qw(ZoneMinder::Control);

our $VERSION = $ZoneMinder::Base::VERSION;

# ==========================================================================
#
# Wowwee Rovio Control Protocol
#
# ==========================================================================

use ZoneMinder::Debug qw(:all);
use ZoneMinder::Config qw(:all);

use Time::HiRes qw( usleep );

sub new
{
    my $class = shift;
    my $id = shift;
    my $self = ZoneMinder::Control->new( $id );
    bless( $self, $class );
    srand( time() );
    return $self;
}

our $AUTOLOAD;

sub AUTOLOAD
{
    my $self = shift;
    my $class = ref($self) || croak( "$self not object" );
    my $name = $AUTOLOAD;
    $name =~ s/.*://;
    if ( exists($self->{$name}) )
    {
        return( $self->{$name} );
    }
    Fatal( "Can't access $name member of object of class $class" );
}

sub open
{
    my $self = shift;

    $self->loadMonitor();

    use LWP::UserAgent;
    $self->{ua} = LWP::UserAgent->new;
    $self->{ua}->agent( "ZoneMinder Control Agent/".ZM_VERSION );

    $self->{state} = 'open';
}

sub close
{
    my $self = shift;
    $self->{state} = 'closed';
}

sub printMsg
{
    my $self = shift;
    my $msg = shift;
    my $msg_len = length($msg);

    Debug( $msg."[".$msg_len."]" );
}

sub sendCmd
{
    my $self = shift;
    my $cmd = shift;

    my $result = undef;

    printMsg( $cmd, "Tx" );

    my $req = HTTP::Request->new( GET=>"http://".$self->{Monitor}->{ControlAddress}."/$cmd" );
    my $res = $self->{ua}->request($req);

    if ( $res->is_success )
    {
        $result = !undef;
    }
    else
    {
        Error( "Error check failed: '".$res->status_line()."'" );
    }

    return( $result );
}

#Drive Forward
sub moveConUp
{
    my $self = shift;
    Debug( "Move Up" );
    my $cmd = "rev.cgi?Cmd=nav&action=18&drive=1&speed=2";
    $self->sendCmd( $cmd );
}

#Drive Backward
sub moveConDown
{
    my $self = shift;
    Debug( "Move Down" );
    my $cmd = "rev.cgi?Cmd=nav&action=18&drive=2&speed=2";
    $self->sendCmd( $cmd );
}

#Drive Left
sub moveConLeft
{
    my $self = shift;
    Debug( "Move Left" );
    my $cmd = "rev.cgi?Cmd=nav&action=18&drive=3&speed=5";
    $self->sendCmd( $cmd );
}

#Drive Right
sub moveConRight
{
    my $self = shift;
    Debug( "Move Right" );
    my $cmd = "rev.cgi?Cmd=nav&action=18&drive=4&speed=5";
    $self->sendCmd( $cmd );
}

#Rotate Right
sub moveConUpRight
{
   my $self = shift;
   Debug( "Move Up Right");
   my $cmd = "rev.cgi?Cmd=nav&action=18&drive=6&speed=7";
   $self->sendCmd( $cmd );
}

#Rotate Left
sub moveConUpLeft
{
   my $self = shift;
   Debug( "Move Up Left");
   my $cmd = "rev.cgi?Cmd=nav&action=18&drive=5&speed=7";
   $self->sendCmd( $cmd );
}

#Move Diagonally Back and Right
sub moveConDownRight
{
   my $self = shift;
   Debug( "Move Up right");
   my $cmd = "rev.cgi?Cmd=nav&action=18&drive=10&speed=2";
   $self->sendCmd( $cmd );
}

#Move Diagonally Back and Left
sub moveConDownLeft
{
   my $self = shift;
   Debug( "Move Down Left");
   my $cmd = "rev.cgi?Cmd=nav&action=18&drive=9&speed=2";
   $self->sendCmd( $cmd );
}

#action=33 is the actual stop moving action number
#action=17 is "full stop" I'm not sure what that means. :-)
sub moveStop
{
   my $self = shift;
   Debug( "Move Stop");
   my $cmd = "rev.cgi?Cmd=nav&action=17";
   $self->sendCmd( $cmd );
}

#Move Head to Middle
sub zoomConTele
{
    my $self = shift;
    Debug( "Zoom Tele" );
    my $cmd = "rev.cgi?Cmd=nav&action=18&drive=13";
    $self->sendCmd( $cmd );
}

#Move Head to Bottom
sub zoomConWide
{
    my $self = shift;
    Debug( "Zoom Wide" );
    my $cmd = "rev.cgi?Cmd=nav&action=18&drive=12";
    $self->sendCmd( $cmd );
}

#Headlight On
sub focusConNear
{
    my $self = shift;
    Debug( "Focus Near" );
    my $cmd = "rev.cgi?Cmd=nav&action=19&LIGHT=1";
    $self->sendCmd( $cmd );
}

#Headlight Off
sub focusConFar
{
    my $self = shift;
    Debug( "Focus Far" );
    my $cmd = "rev.cgi?Cmd=nav&action=19&LIGHT=0";
    $self->sendCmd( $cmd );
}

sub presetGoto
{
    my $self = shift;
    my $params = shift;
    my $roviopath = shift;
    my $preset = $self->getParam( $params, 'preset' );
    Debug( "Goto Preset $preset" );

#Define your Rovio Path names here.
# Hint: Change "Rovio Path Name 1" To a path you have defined in your Rovio."
    my $roviopath1 = "Rovio Path Name 1";
    my $roviopath2 = "Rovio Path Name 2";
    my $roviopath3 = "Rovio Path Name 3";
    my $roviopath4 = "Rovio Path Name 4";
    my $roviopath5 = "Rovio Path Name 5";
    my $roviopath6 = "Rovio Path Name 6";
    my $roviopath7 = "Rovio Path Name 7";
    my $roviopath8 = "Rovio Path Name 8";

    if ($preset == 1) {
	$roviopath = $roviopath1;
	}
     elsif ($preset == 2) {
	$roviopath = $roviopath2;
	}
     elsif ($preset == 3) {
        $roviopath = $roviopath3;
        }
     elsif ($preset == 4) {
        $roviopath = $roviopath4;
        }
     elsif ($preset == 5) {
        $roviopath = $roviopath5;
        }
     elsif ($preset == 6) {
        $roviopath = $roviopath6;
        }
     elsif ($preset == 7) {
        $roviopath = $roviopath7;
        }
     elsif ($preset == 8) {
        $roviopath = $roviopath8;
        }
     else { 
	exit;
	}
   #(below is the correct syntax for the Rovio)
    my $cmd = "rev.cgi?Cmd=nav&action=7&name=$roviopath";
    $self->sendCmd( $cmd );
}



#Go Home and Dock
sub presetHome
{
    my $self = shift;
    Debug( "Home Preset" );
    my $cmd = "rev.cgi?Cmd=nav&action=13";
    $self->sendCmd( $cmd );
}

1;
__END__