Difference between revisions of "Apexis"

From ZoneMinder Wiki
Jump to navigationJump to search
 
(17 intermediate revisions by 4 users not shown)
Line 1: Line 1:
== Apexis APM J0233 WS IR (IR, outdoor, IP66) ==
[[File:APMJ0233WSIR_02.png|200px|thumb|right|Apexis APM J0233 WS IR]]
[[File:Snapshot 20140915180703.jpg|200px|thumb|right|Snapshot from Apexis APM J0233 WS IR]]
<strike>Sometimes there are distortions when switching from Nightvision to Dayvision and back.</strike> (I have sent the camera for repair and since then it has not occurred again.)
Overall moderate image quality (see example picture on the right).
I had to create a new user to access the image (needs only limited permissions).
Remote Protocol: HTTP<br/>
Remote Method: Simple<br/>
Remote Host Name: <ip of camera><br/>
Remote Host Port: 80<br/>
Remote Host Path: videostream.cgi?user='''<USERNAME>'''&pwd='''<PASSWORD>'''&resolution='''32'''&rate='''11'''<br/>
Remote Image colors: 24 bit<br/>
Capture Width: 640<br/>
Capture Height: 480<br/>
'''Available resolutions:'''<br/>
'''2''' = 160x120 (QQVGA); '''8''' = 320x240 (QVGA); '''32''' = 640x480 (VGA)
'''Possible image transmission rates:'''<br/>
'''1''' = 20fps; '''3''' = 15fps; '''6''' = 10fps; '''11''' = 5fps; '''13''' = 3fps; '''15''' = 1fps; '''17''' = 0.5fps;
== Apexis J12 IP Camera ==
== Apexis J12 IP Camera ==


Line 11: Line 34:
<br/>
<br/>
It is recommended to set Max FPS to 20.<br/>
It is recommended to set Max FPS to 20.<br/>
== [http://www.apexis.com.cn/productsdetails_211.html Apexis APM-HP602-MPC-WS IP Wireless/Wired Camera] ==
=== Features ===
:Wired and Wireless Ethernet. 802.11b/g with WEP & WPA WPA2 encryption
:1280*720 Pixels(1.0 megapixel)
:Night Vision. 30 IR LEDs,40meters
:UPnP
:DDNS
:Supports Firefox/Chrome (Push-mode, VLC and Quicktime)
:Audio capable
:FTP uploads
:Email alerts
The ActiveX control, Quicktime and VLC plugins all use an rtsp stream.
There is an ActiveX control file for Internet Explorer found in: http://<CAMERA_IP>/codebase/DvmHIPCam.zip or http://<CAMERA_IP>/codebase/DvmHIPCam.exe if the firmware is outdated.
=== RTSP Settings ===
{| border="0" cellpadding="5" cellspacing="0"
|-
! style="background:#efefef;" width="100px" | Source
| width="90%" |
{| border="1" cellpadding="5" cellspacing="0" width="95%"
|width="25%" | Source Type
|width="75%" | ffmpeg or libvlc
|-
| Source Path
| rtsp://<CAMERA_IP>/live/av0?user=<USER>&passwd=<PASSWORD>
|-
| Remote Method
| RTSP
|-
| Remote Image colors
| 24 bit
|-
| Capture Width
| 640
|-
| Capture Height
| 480
|-
|}
|-
|}
Notes: libvlc ends up with a segmentation fault in some installations.
Source type: Remote and RTSP settings may work. I couldn't make it work, but I suspect that it was a problem with the capture size.
=== Simple snapshot settings ===
{| border="0" cellpadding="5" cellspacing="0"
|-
! style="background:#efefef;" width="100px" | Source
| width="90%" |
{| border="1" cellpadding="5" cellspacing="0" width="95%"
|width="25%" | Remote Protocol
|width="75%" | HTTP
|-
| Remote Method
| Simple
|-
| Remote Host Name
| <IP_ADDRESS_OF_CAMERA>
|-
| Remote Host Port
| 80
|-
| Remote Host Path
| /cgi-bin/videostream.cgi?user=<USERNAME>&pwd=<PASSWORD><br/>
'''or'''<br/>
/cgi-bin/video_snapshot.cgi?user=<USERNAME>&pwd=<PASSWORD><br/>
'''or'''<br/>
/cgi-bin/mobile_snapshot.cgi?user=<USERNAME>&pwd=<PASSWORD><br/>
''eg: /cgi-bin/videostream.cgi?user=zoneminder&pwd=zonepass
|-
| Remote Image colors
| 24 bit
|-
| Capture Width
| 640
|-
| Capture Height
| 480
|-
|}
|-
|}


== Apexis APM-J011-WS IP Camera ==
== Apexis APM-J011-WS IP Camera ==
Line 24: Line 134:
<br/>
<br/>
Maximum frame rate this IP web camera can handle is 15 fps at 640x480. The <USERNAME> and <PASSWORD> are found in the "Users Settings" section of the IP Camera's web setup page.  
Maximum frame rate this IP web camera can handle is 15 fps at 640x480. The <USERNAME> and <PASSWORD> are found in the "Users Settings" section of the IP Camera's web setup page.  
Pan Tilt Control is not available in Zoneminder at this time. (version 1.25.0, Feb 2012)<br/>
Pan Tilt Control is not available in Zoneminder 1.25.0 at this time (Feb 2012.)  This IP camera does not have a zoom function, only pan and tilt.<br/>
 
== [http://apexis.cc/Products/63.aspx Apexis APM-J901-Z-WS PTZ IP Wireless/Wired Camera] ==
[[file:APM-J901-Z-WS-3.jpg|200px|thumb|right|Apexis APM-J901-Z-WS]]
 
=== Features ===
:Wired and Wireless Ethernet. 802.11b/g with WEP & WPA WPA2 encryption
:3x optical zoom
:355° pan, 90° tilt
:POE
:DDNS
:Supports VLC ''(apparently!)''
:Supports MSN
:Supports Firefox/Chrome (ie: Push-mode)
:Two-way audio capable (microphone and speaker not included)
:FTP uploads
:Email alerts
 
 
=== Settings ===
{| border="0" cellpadding="5" cellspacing="0"
|-
! style="background:#efefef;" width="100px" | Source
| width="90%" |
{| border="1" cellpadding="5" cellspacing="0" width="95%"
|width="25%" | Remote Protocol
|width="75%" | HTTP
|-
| Remote Method
| Simple
|-
| Remote Host Name
| <IP_ADDRESS_OF_CAMERA>
|-
| Remote Host Port
| 80
|-
| Remote Host Path
| videostream.cgi?user=<USERNAME>&pwd=<PASSWORD><br/>
'''or'''<br/>
snapshot.cgi?user=<USERNAME>&pwd=<PASSWORD>&resolution=32&rate=0<br/>
''eg: snapshot.cgi?user=zoneminder&pwd=zonepass&resolution=32&rate=0
|-
| Remote Image colors
| 24 bit
|-
| Capture Width
| 640
|-
| Capture Height
| 480
|-
|}
|-
|}
 
{| border="0" cellpadding="5" cellspacing="0"
|-
! style="background:#efefef;" width="100px" | Control
| width="90%" |
{| border="1" cellpadding="5" cellspacing="0" width="95%"
|width="25%" | Controllable
|width="75%" | [[Image:Tick.png|frameless|selected]]
|-
| Control Type
| Apexis Mjpeg IP ''<br/>(Select '''Edit''' to access '''Control Capabilities''')''
|-
| Control Address
| <USERNAME>:<PASSWORD>@<IP_ADDRESS_OF_CAMERA>:<PORT><br/>
eg: admin:@<IP_ADDRESS_OF_CAMERA>:80<br/>
eg: zoneminder:zonepass@192.168.1.111
|-
| Auto Stop Timeout
| 0.10
|-
|}
|-
|}
 
<br/>
;Control Capability - Apexis Mjpeg IP
{| border="0" cellpadding="5" cellspacing="0"
|-
! style="background:#efefef;" width="100px" | Main
| width="90%" |
{| border="1" cellpadding="5" cellspacing="0" width="95%"
|width="25%" | Name
|width="75%" | Apexis Mjpeg IP
|-
| Type
| Remote
|-
| Protocol
| ApexisMjpegIP<br/>''(Refer to control protocol below)''
|-
| Can Reset
| [[Image:Tick.png|frameless|selected]]
|-
|}
|-
 
{| border="0" cellpadding="5" cellspacing="0"
|-
! style="background:#efefef;" width="100px" | Move
| width="90%" |
{| border="1" cellpadding="5" cellspacing="0" width="95%"
| width="25%" | Can Move
| width="75%" | [[Image:Tick.png|frameless|selected]]
|-
| Can Move Continuous
| [[Image:Tick.png|frameless|selected]]
|-
|}
|-
 
{| border="0" cellpadding="5" cellspacing="0"
|-
! style="background:#efefef;" width="100px" | Pan
| width="90%" |
{| border="1" cellpadding="5" cellspacing="0" width="95%"
| width="25%" | Can Pan
| width="75%" | [[Image:Tick.png|frameless|selected]]
|-
|}
|-
 
{| border="0" cellpadding="5" cellspacing="0"
|-
! style="background:#efefef;" width="100px" | Tilt
| width="90%" |
{| border="1" cellpadding="5" cellspacing="0" width="95%"
| width="25%" | Can Tilt
| width="75%" | [[Image:Tick.png|frameless|selected]]
|-
|}
|-
 
{| border="0" cellpadding="5" cellspacing="0"
|-
! style="background:#efefef;" width="100px" | Zoom
| width="90%" |
{| border="1" cellpadding="5" cellspacing="0" width="95%"
| width="25%" | Can Zoom
| width="75%" | [[Image:Tick.png|frameless|selected]]
|-
| width="25%" | Can Zoom Continuous
| width="75%" | [[Image:Tick.png|frameless|selected]]
|-
|}
|-
 
{| border="0" cellpadding="5" cellspacing="0"
|-
! style="background:#efefef;" width="100px" | Presets
| width="90%" |
{| border="1" cellpadding="5" cellspacing="0" width="95%"
| width="25%" | Has Presets
| width="75%" | [[Image:Tick.png|frameless|selected]]
|-
| width="25%" | Num Presets
| width="75%" | 8 ''(to be confirmed)''
|-
| width="25%" | Can Set Presets
| width="75%" | [[Image:Tick.png|frameless|selected]]
|-
|}
|-
|}
<br/>
 
== Control protocol for Apexis MJPEG Cameras ==
 
Save the following code as ''/usr/share/perl5/ZoneMinder/Control/ApexisMjpegIP.pm''<br/>
Don't forget to set the user and password as I haven't figured that bit out yet ;).
 
# ==========================================================================
#
# ZoneMinder Apexis MJPEG IP Camera Control Protocol Module
# Copyright (C) 2012 Marcus Brown
# Shamefully copied from the Loftek module by Philip Coombes
#
# 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 Apexis MJPEG IP camera control
# protocol
#
package ZoneMinder::Control::ApexisMjpegIP;
use 5.006;
use strict;
use warnings;
require ZoneMinder::Base;
require ZoneMinder::Control;
our @ISA = qw(ZoneMinder::Control);
our $VERSION = $ZoneMinder::Base::VERSION;
our %CamParams = ();
# ==========================================================================
#
# Apexis MJPEG IP Control Protocol
#
# On ControlAddress use the format :
#  USERNAME:PASSWORD@ADDRESS:PORT
#  eg : admin:@10.1.2.1:80
#        zoneminder:zonepass@10.0.100.1:40000
#
# ==========================================================================
# Change "ZoneMinder::Logger" to "ZoneMinder::Debug" for zoneminder < 1.25.0
use ZoneMinder::Logger 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 );
    my $logindetails = "";
    bless( $self, $class );
    srand( time() );
    return $self;
}
our $AUTOLOAD;
sub AUTOLOAD
{
    my $self = shift;
    my $class = ref( ) || 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" );
    # ############################################################################################
    #
    #  CHANGE THE FOLLOWING LINE IF NECESSARY
    #  IT SHOULD WORK WITH A DEFAULT CAMERA, BUT SURELY YOU WILL BE SETTING AN ADMIN PASSWORD? :)
    # 
    # ############################################################################################
    my $req = HTTP::Request->new( GET=>"http://".$self->{Monitor}->{ControlAddress}."/$cmd\&user=admin\&pwd="  );
    my $res = $self->{ua}->request($req);
    if ( $res->is_success )
    {
        $result = !undef;
    }
    else
    {
        Error( "Error check failed:'".$res->status_line()."'" );
    }
    return( $result );
}
sub getCamParams
{
    my $self = shift;
    my $req = HTTP::Request->new( GET=>"http://".$self->{Monitor}->{ControlAddress}."/get_params.cgi" );
    my $res = $self->{ua}->request($req);
    if ( $res->is_success )
    {
        # Parse results setting values in %FCParams
        my $content = $res->decoded_content;
        while ($content =~ s/var\s+([^=]+)=([^;]+);//ms) {
            $CamParams{$1} = $2;
        }
    }
    else
    {
        Error( "Error check failed:'".$res->status_line()."'" );
    }
}
#autoStop
#This makes use of the ZoneMinder Auto Stop Timeout on the Control Tab
sub autoStop
{
    my $self = shift;
    my $stop_command = shift;
    my $autostop = shift;
    if( $stop_command && $autostop)
    {
        Debug( "Auto Stop" );
        usleep( $autostop );
        my $cmd = "decoder_control.cgi?command=".$stop_command;
        $self->sendCmd( $cmd );
    }
}
# Reset the Camera
sub reset
{
    my $self = shift;
    Debug( "Camera Reset" );
    my $cmd = "reboot.cgi?";
    $self->sendCmd( $cmd );
}
#Up Arrow
sub moveConUp
{
    my $self = shift;
    my $stop_command = "1";
    Debug( "Move Up" );
    my $cmd = "decoder_control.cgi?command=0";
    $self->sendCmd( $cmd );
    $self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} );
}
#Down Arrow
sub moveConDown
{
    my $self = shift;
    my $stop_command = "3";
    Debug( "Move Down" );
    my $cmd = "decoder_control.cgi?command=2";
    $self->sendCmd( $cmd );
    $self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} );
}
#Left Arrow
sub moveConLeft
{
    my $self = shift;
    my $stop_command = "5";
    Debug( "Move Left" );
    my $cmd = "decoder_control.cgi?command=4";
    $self->sendCmd( $cmd );
    $self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} );
}
#Right Arrow
sub moveConRight
{
    my $self = shift;
    my $stop_command = "7";
    Debug( "Move Right" );
    my $cmd = "decoder_control.cgi?command=6";
    $self->sendCmd( $cmd );
    $self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} );
}
#####################################################################################
# Single-step movements
#
# 'onestep' and 'degree' don't appear to work for the J901
sub moveRelUp
{
    my $self = shift;
    Debug( "Move Up" );
    my $cmd = "decoder_control.cgi?command=0&onestep=1";
    $self->sendCmd( $cmd );
}
#~ #~
sub moveRelDown
{
    my $self = shift;
    Debug( "Move Down" );
    my $cmd = "decoder_control.cgi?command=2&onestep=1";
    $self->sendCmd( $cmd );
}
#~ #~
sub moveRelLeft
{
    my $self = shift;
    Debug( "Move Left" );
    my $cmd = "decoder_control.cgi?command=4&onestep=1";
    $self->sendCmd( $cmd );
}
#~ #~
sub moveRelRight
{
    my $self = shift;
    Debug( "Move Right" );
    my $cmd = "decoder_control.cgi?command=6&onestep=1";
    $self->sendCmd( $cmd );
}
#This camera does not have builtin diagonal commands so we emulate them
sub moveRelUpRight
{
    my $self = shift;
    Debug( "Step Diagonally Up Right" );
    $self->stepConUp( );
    $self->stepConRight( );
}
#~ #~
sub moveRelDownRight
{
    my $self = shift;
    Debug( "Step Diagonally Down Right" );
    $self->stepConDown( );
    $self->stepConRight( );
}
#~ #~
sub moveRelUpLeft
{
    my $self = shift;
    Debug( "Step Diagonally Up Left" );
    $self->stepConUp( );
    $self->stepConLeft( );
}
#~ #~
sub moveRelDownLeft
{
    my $self = shift;
    Debug( "Step Diagonally Down Left" );
    $self->stepConDown( );
    $self->stepConLeft( );
}
#
#####################################################################################
# Iris/Aperture control ... this is *NOT* 'iris' as 'brightness' ?
#
# Doubt this works on J901
sub irisConClose
{
    my $self = shift;
    my $stop_command = "8";
    Debug( "Focus Near" );
    my $cmd = "decoder_control.cgi?command=9";
    $self->sendCmd( $cmd );
    $self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} );
}
#~ #~
sub irisConOpen
{
    my $self = shift;
    my $stop_command = "10";
    Debug( "Focus Near" );
    my $cmd = "decoder_control.cgi?command=11";
    $self->sendCmd( $cmd );
    $self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} );
}
#
#####################################################################################
# Focus control
#
# J901 is manual focus
sub focusConNear
{
    my $self = shift;
    my $stop_command = "13";
    Debug( "Focus Near" );
    my $cmd = "decoder_control.cgi?command=12";
    $self->sendCmd( $cmd );
    $self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} );
}
#~ #~
sub focusConFar
{
    my $self = shift;
    my $stop_command = "15";
    Debug( "Focus Near" );
    my $cmd = "decoder_control.cgi?command=14";
    $self->sendCmd( $cmd );
    $self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} );
}
#
#####################################################################################
#Zoom In
sub zoomConTele
{
    my $self = shift;
    my $stop_command = "19";
    Debug( "Zoom Tele" );
    my $cmd = "decoder_control.cgi?command=18";
    $self->sendCmd( $cmd );
    $self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} );
}
#~ #Zoom Out
sub zoomConWide
{
    my $self = shift;
    my $stop_command = "17";
    Debug( "Zoom Wide" );
    my $cmd = "decoder_control.cgi?command=16";
    $self->sendCmd( $cmd );
    $self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} );
}
#~ #Diagonally Up Right Arrow
#This camera does not have builtin diagonal commands so we emulate them
sub moveConUpRight
{
    my $self = shift;
    Debug( "Move Diagonally Up Right" );
    $self->moveConUp( );
    $self->moveConRight( );
}
#Diagonally Down Right Arrow
#This camera does not have builtin diagonal commands so we emulate them
sub moveConDownRight
{
    my $self = shift;
    Debug( "Move Diagonally Down Right" );
    $self->moveConDown( );
    $self->moveConRight( );
}
#~
#Diagonally Up Left Arrow
#This camera does not have builtin diagonal commands so we emulate them
sub moveConUpLeft
{
    my $self = shift;
    Debug( "Move Diagonally Up Left" );
    $self->moveConUp( );
    $self->moveConLeft( );
}
#~
#Diagonally Down Left Arrow
#This camera does not have builtin diagonal commands so we emulate them
sub moveConDownLeft
{
    my $self = shift;
    Debug( "Move Diagonally Down Left" );
    $self->moveConDown( );
    $self->moveConLeft( );
}
#Stop
#~ sub moveStop
#~ {
    #~ my $self = shift;
    #~ Debug( "Move Stop" );
    #~ my $cmd = "decoder_control.cgi?command=1";
    #~ $self->sendCmd( $cmd );
#~ }
#Set Camera Preset
#Presets must be translated into values internal to the camera
#Those values are: 30,32,34 ... 88,90,92 for presets 1-32 respectively
sub presetSet
{
    my $self = shift;
    my $params = shift;
    my $preset = $self->getParam( $params, 'preset' );
    Debug( "Set Preset $preset" );
#~
    if (( $preset >= 1 ) && ( $preset <= 32 )) {
        my $cmd = "decoder_control.cgi?command=".(($preset*2) + 28);
        $self->sendCmd( $cmd );
    }
}
#Recall Camera Preset
#Presets must be translated into values internal to the camera
#Those values are: 31,33,35 ... 89,91,93 for presets 1-32 respectively
sub presetGoto
{
    my $self = shift;
    my $params = shift;
    my $preset = $self->getParam( $params, 'preset' );
    Debug( "Goto Preset $preset" );
#~
    if (( $preset >= 1 ) && ( $preset <= 32 )) {
        my $cmd = "decoder_control.cgi?command=".(($preset*2) + 29);
        $self->sendCmd( $cmd );
    }
    #~ if ( $preset == 9 ) {
        #~ $self->horizontalPatrol();
    #~ }
    #~ if ( $preset == 10 ) {
        #~ $self->horizontalPatrolStop();
    #~ }
}
#~ sub presetHome
#~ {
    #~ my $self = shift;
    #~ Debug( "Home Preset" );
    #~ my $cmd = "decoder_control.cgi?command=25";
    #~ $self->sendCmd( $cmd );
#~ }
#Horizontal Patrol - Vertical Patrols are not supported
sub horizontalPatrol
{
    my $self = shift;
    Debug( "Horizontal Patrol" );
    my $cmd = "decoder_control.cgi?command=20";
    $self->sendCmd( $cmd );
}
#Horizontal Patrol Stop
sub horizontalPatrolStop
{
    my $self = shift;
    Debug( "Horizontal Patrol Stop" );
    my $cmd = "decoder_control.cgi?command=21";
    $self->sendCmd( $cmd );
}
# Set Absolute Brightness
#~ sub setAbsBrightness
#~ {
    #~ my $self = shift;
    #~ my $brightness = shift;
    #~ $brightness = 255 if $brightness > 255;
    #~ $brightness = 0  if $brightness < 0;
    #~ Debug( "Setting brightness to $brightness" };
    #~ $CamParams{'brightness'} = $brightness;
    #~ my $cmd = "camera_control.cgi?param=1&value=".$brightness;
    #~ $self->sendCmd( $cmd );
#~ }
# Increase Brightness
#~ sub irisAbsOpen
#~ {
    #~ my $self = shift;
    #~ my $params = shift;
    #~ $self->getCamParams() unless($CamParams{'brightness'});
    #~ my $step = $self->getParam( $params, 'step' );
#~
    #~ $CamParams{'brightness'} += $step;
    #~ $CamParams{'brightness'} = 255 if ($CamParams{'brightness'} > 255);
    #~ Debug( "Iris $CamParams{'brightness'}" );
    #~ my $cmd = "camera_control.cgi?param=1&value=".$CamParams{'brightness'};
    #~ $self->sendCmd( $cmd );
#~ }
# Decrease Brightness
#~ sub irisAbsClose
#~ {
    #~ my $self = shift;
    #~ my $params = shift;
    #~ $self->getCamParams() unless($CamParams{'brightness'});
    #~ my $step = $self->getParam( $params, 'step' );
#~
    #~ $CamParams{'brightness'} -= $step;
    #~ $CamParams{'brightness'} = 0 if ($CamParams{'brightness'} < 0);
    #~ Debug( "Iris $CamParams{'brightness'}" );
    #~ my $cmd = "camera_control.cgi?param=1&value=".$CamParams{'brightness'};
    #~ $self->sendCmd( $cmd );
#~ }
# Set Absolute Contrast
#~ sub setAbsContrast
#~ {
    #~ my $self = shift;
    #~ my $contrast = shift;
    #~ $contrast = 255 if $contrast > 255;
    #~ $contrast = 0   if $contrast < 0;
    #~ Debug( "Setting contrast to $contrast" };
    #~ $CamParams{'contrast'} = $contrast;
    #~ my $cmd = "camera_control.cgi?param=2&value=".$contrast;
    #~ $self->sendCmd( $cmd );
#~ }
# Increase Contrast
#~ sub whiteAbsIn
#~ {
    #~ my $self = shift;
    #~ my $params = shift;
    #~ $self->getCamParams() unless($CamParams{'contrast'});
    #~ my $step = $self->getParam( $params, 'step' );
#~
    #~ $CamParams{'contrast'} += $step;
    #~ $CamParams{'contrast'} = 6 if ($CamParams{'contrast'} > 6);
    #~ Debug( "Contrast $CamParams{'contrast'}" );
    #~ my $cmd = "camera_control.cgi?param=2&value=".$CamParams{'contrast'};
    #~ $self->sendCmd( $cmd );
#~ }
# Decrease Contrast
#~ sub whiteAbsOut
#~ {
    #~ my $self = shift;
    #~ my $params = shift;
    #~ $self->getCamParams() unless($CamParams{'contrast'});
    #~ my $step = $self->getParam( $params, 'step' );
#~
    #~ $CamParams{'contrast'} -= $step;
    #~ $CamParams{'contrast'} = 0 if ($CamParams{'contrast'} < 0);
    #~ Debug( "Iris $CamParams{'contrast'}" );
    #~ my $cmd = "camera_control.cgi?param=2&value=".$CamParams{'contrast'};
    #~ $self->sendCmd( $cmd );
#~ }
1;

Latest revision as of 14:27, 24 March 2016

Apexis APM J0233 WS IR (IR, outdoor, IP66)

Apexis APM J0233 WS IR
Snapshot from Apexis APM J0233 WS IR

Sometimes there are distortions when switching from Nightvision to Dayvision and back. (I have sent the camera for repair and since then it has not occurred again.)

Overall moderate image quality (see example picture on the right). I had to create a new user to access the image (needs only limited permissions).

Remote Protocol: HTTP
Remote Method: Simple
Remote Host Name: <ip of camera>
Remote Host Port: 80
Remote Host Path: videostream.cgi?user=<USERNAME>&pwd=<PASSWORD>&resolution=32&rate=11
Remote Image colors: 24 bit
Capture Width: 640
Capture Height: 480

Available resolutions:
2 = 160x120 (QQVGA); 8 = 320x240 (QVGA); 32 = 640x480 (VGA)

Possible image transmission rates:
1 = 20fps; 3 = 15fps; 6 = 10fps; 11 = 5fps; 13 = 3fps; 15 = 1fps; 17 = 0.5fps;

Apexis J12 IP Camera

Remote Protocol: HTTP
Remote Method: Simple
Remote Host Name: <ip of camera>
Remote Host Port: 80
Remote Host Path: videostream.cgi?user=<USERNAME>&pwd=<PASSWORD>
Remote Image colors: 24 bit
Capture Width: 640
Capture Height: 480

It is recommended to set Max FPS to 20.

Apexis APM-HP602-MPC-WS IP Wireless/Wired Camera

Features

Wired and Wireless Ethernet. 802.11b/g with WEP & WPA WPA2 encryption
1280*720 Pixels(1.0 megapixel)
Night Vision. 30 IR LEDs,40meters
UPnP
DDNS
Supports Firefox/Chrome (Push-mode, VLC and Quicktime)
Audio capable
FTP uploads
Email alerts


The ActiveX control, Quicktime and VLC plugins all use an rtsp stream. There is an ActiveX control file for Internet Explorer found in: http://<CAMERA_IP>/codebase/DvmHIPCam.zip or http://<CAMERA_IP>/codebase/DvmHIPCam.exe if the firmware is outdated.

RTSP Settings

Source
Source Type ffmpeg or libvlc
Source Path rtsp://<CAMERA_IP>/live/av0?user=<USER>&passwd=<PASSWORD>
Remote Method RTSP
Remote Image colors 24 bit
Capture Width 640
Capture Height 480

Notes: libvlc ends up with a segmentation fault in some installations. Source type: Remote and RTSP settings may work. I couldn't make it work, but I suspect that it was a problem with the capture size.

Simple snapshot settings

Source
Remote Protocol HTTP
Remote Method Simple
Remote Host Name <IP_ADDRESS_OF_CAMERA>
Remote Host Port 80
Remote Host Path /cgi-bin/videostream.cgi?user=<USERNAME>&pwd=<PASSWORD>

or
/cgi-bin/video_snapshot.cgi?user=<USERNAME>&pwd=<PASSWORD>
or
/cgi-bin/mobile_snapshot.cgi?user=<USERNAME>&pwd=<PASSWORD>
eg: /cgi-bin/videostream.cgi?user=zoneminder&pwd=zonepass

Remote Image colors 24 bit
Capture Width 640
Capture Height 480

Apexis APM-J011-WS IP Camera

Remote Protocol: HTTP
Remote Method: Simple
Remote Host Name: <IP_ADDRESS_OF_CAMERA>
Remote Host Port: 80
Remote Host Path: videostream.cgi?user=<USERNAME>&pwd=<PASSWORD>
Remote Image colors: 24 bit
Capture Width: 640
Capture Height: 480

Maximum frame rate this IP web camera can handle is 15 fps at 640x480. The <USERNAME> and <PASSWORD> are found in the "Users Settings" section of the IP Camera's web setup page. Pan Tilt Control is not available in Zoneminder 1.25.0 at this time (Feb 2012.) This IP camera does not have a zoom function, only pan and tilt.

Apexis APM-J901-Z-WS PTZ IP Wireless/Wired Camera

Apexis APM-J901-Z-WS

Features

Wired and Wireless Ethernet. 802.11b/g with WEP & WPA WPA2 encryption
3x optical zoom
355° pan, 90° tilt
POE
DDNS
Supports VLC (apparently!)
Supports MSN
Supports Firefox/Chrome (ie: Push-mode)
Two-way audio capable (microphone and speaker not included)
FTP uploads
Email alerts


Settings

Source
Remote Protocol HTTP
Remote Method Simple
Remote Host Name <IP_ADDRESS_OF_CAMERA>
Remote Host Port 80
Remote Host Path videostream.cgi?user=<USERNAME>&pwd=<PASSWORD>

or
snapshot.cgi?user=<USERNAME>&pwd=<PASSWORD>&resolution=32&rate=0
eg: snapshot.cgi?user=zoneminder&pwd=zonepass&resolution=32&rate=0

Remote Image colors 24 bit
Capture Width 640
Capture Height 480
Control
Controllable selected
Control Type Apexis Mjpeg IP
(Select Edit to access Control Capabilities)
Control Address <USERNAME>:<PASSWORD>@<IP_ADDRESS_OF_CAMERA>:<PORT>

eg: admin:@<IP_ADDRESS_OF_CAMERA>:80
eg: zoneminder:zonepass@192.168.1.111

Auto Stop Timeout 0.10


Control Capability - Apexis Mjpeg IP
Main
Name Apexis Mjpeg IP
Type Remote
Protocol ApexisMjpegIP
(Refer to control protocol below)
Can Reset selected
Move
Can Move selected
Can Move Continuous selected
Pan
Can Pan selected
Tilt
Can Tilt selected
Zoom
Can Zoom selected
Can Zoom Continuous selected
Presets
Has Presets selected
Num Presets 8 (to be confirmed)
Can Set Presets selected


Control protocol for Apexis MJPEG Cameras

Save the following code as /usr/share/perl5/ZoneMinder/Control/ApexisMjpegIP.pm
Don't forget to set the user and password as I haven't figured that bit out yet ;).

# ==========================================================================
#
# ZoneMinder Apexis MJPEG IP Camera Control Protocol Module
# Copyright (C) 2012 Marcus Brown
# Shamefully copied from the Loftek module by Philip Coombes
#
# 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 Apexis MJPEG IP camera control
# protocol
#
package ZoneMinder::Control::ApexisMjpegIP;

use 5.006;
use strict;
use warnings;

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

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

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

our %CamParams = ();

# ==========================================================================
#
# Apexis MJPEG IP Control Protocol
#
# On ControlAddress use the format :
#   USERNAME:PASSWORD@ADDRESS:PORT
#   eg : admin:@10.1.2.1:80
#        zoneminder:zonepass@10.0.100.1:40000
#
# ==========================================================================

# Change "ZoneMinder::Logger" to "ZoneMinder::Debug" for zoneminder < 1.25.0
use ZoneMinder::Logger 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 );
    my $logindetails = "";
    bless( $self, $class );
    srand( time() );
    return $self;
}

our $AUTOLOAD;

sub AUTOLOAD
{
    my $self = shift;
    my $class = ref( ) || 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" );

    # ############################################################################################
    #
    #  CHANGE THE FOLLOWING LINE IF NECESSARY
    #  IT SHOULD WORK WITH A DEFAULT CAMERA, BUT SURELY YOU WILL BE SETTING AN ADMIN PASSWORD? :)
    #  
    # ############################################################################################
    my $req = HTTP::Request->new( GET=>"http://".$self->{Monitor}->{ControlAddress}."/$cmd\&user=admin\&pwd="  );
    my $res = $self->{ua}->request($req);

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

    return( $result );
}

sub getCamParams
{
    my $self = shift;

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

    if ( $res->is_success )
    {
        # Parse results setting values in %FCParams
        my $content = $res->decoded_content;

        while ($content =~ s/var\s+([^=]+)=([^;]+);//ms) {
            $CamParams{$1} = $2;
        }
    }
    else
    {
        Error( "Error check failed:'".$res->status_line()."'" );
    }
}

#autoStop
#This makes use of the ZoneMinder Auto Stop Timeout on the Control Tab
sub autoStop
{
    my $self = shift;
    my $stop_command = shift;
    my $autostop = shift;
    if( $stop_command && $autostop)
    {
        Debug( "Auto Stop" );
        usleep( $autostop );
        my $cmd = "decoder_control.cgi?command=".$stop_command;
        $self->sendCmd( $cmd );
    }

}

# Reset the Camera
sub reset
{
    my $self = shift;
    Debug( "Camera Reset" );
    my $cmd = "reboot.cgi?";
    $self->sendCmd( $cmd );
}

#Up Arrow
sub moveConUp
{
    my $self = shift;
    my $stop_command = "1";
    Debug( "Move Up" );
    my $cmd = "decoder_control.cgi?command=0";
    $self->sendCmd( $cmd );
    $self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} );
}

#Down Arrow
sub moveConDown
{
    my $self = shift;
    my $stop_command = "3";
    Debug( "Move Down" );
    my $cmd = "decoder_control.cgi?command=2";
    $self->sendCmd( $cmd );
    $self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} );
}

#Left Arrow
sub moveConLeft
{
    my $self = shift;
    my $stop_command = "5";
    Debug( "Move Left" );
    my $cmd = "decoder_control.cgi?command=4";
    $self->sendCmd( $cmd );
    $self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} );
}

#Right Arrow
sub moveConRight
{
    my $self = shift;
    my $stop_command = "7";
    Debug( "Move Right" );
    my $cmd = "decoder_control.cgi?command=6";
    $self->sendCmd( $cmd );
    $self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} );
}

#####################################################################################
# Single-step movements
#

# 'onestep' and 'degree' don't appear to work for the J901

sub moveRelUp
{
    my $self = shift;
    Debug( "Move Up" );
    my $cmd = "decoder_control.cgi?command=0&onestep=1";
    $self->sendCmd( $cmd );
}
#~ #~
sub moveRelDown
{
    my $self = shift;
    Debug( "Move Down" );
    my $cmd = "decoder_control.cgi?command=2&onestep=1";
    $self->sendCmd( $cmd );
}
#~ #~
sub moveRelLeft
{
    my $self = shift;
    Debug( "Move Left" );
    my $cmd = "decoder_control.cgi?command=4&onestep=1";
    $self->sendCmd( $cmd );
}
#~ #~
sub moveRelRight
{
    my $self = shift;
    Debug( "Move Right" );
    my $cmd = "decoder_control.cgi?command=6&onestep=1";
    $self->sendCmd( $cmd );
}

#This camera does not have builtin diagonal commands so we emulate them
sub moveRelUpRight
{
    my $self = shift;
    Debug( "Step Diagonally Up Right" );
    $self->stepConUp( );
    $self->stepConRight( );
}
#~ #~
sub moveRelDownRight
{
    my $self = shift;
    Debug( "Step Diagonally Down Right" );
    $self->stepConDown( );
    $self->stepConRight( );
}
#~ #~
sub moveRelUpLeft
{
    my $self = shift;
    Debug( "Step Diagonally Up Left" );
    $self->stepConUp( );
    $self->stepConLeft( );
}
#~ #~
sub moveRelDownLeft
{
    my $self = shift;
    Debug( "Step Diagonally Down Left" );
    $self->stepConDown( );
    $self->stepConLeft( );
}

#
#####################################################################################
# Iris/Aperture control ... this is *NOT* 'iris' as 'brightness' ?
#
# Doubt this works on J901

sub irisConClose
{
    my $self = shift;
    my $stop_command = "8";
    Debug( "Focus Near" );
    my $cmd = "decoder_control.cgi?command=9";
    $self->sendCmd( $cmd );
    $self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} );
}
#~ #~
sub irisConOpen
{
    my $self = shift;
    my $stop_command = "10";
    Debug( "Focus Near" );
    my $cmd = "decoder_control.cgi?command=11";
    $self->sendCmd( $cmd );
    $self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} );
}

#
#####################################################################################
# Focus control
#
# J901 is manual focus

sub focusConNear
{
    my $self = shift;
    my $stop_command = "13";
    Debug( "Focus Near" );
    my $cmd = "decoder_control.cgi?command=12";
    $self->sendCmd( $cmd );
    $self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} );
}
#~ #~
sub focusConFar
{
    my $self = shift;
    my $stop_command = "15";
    Debug( "Focus Near" );
    my $cmd = "decoder_control.cgi?command=14";
    $self->sendCmd( $cmd );
    $self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} );
}


#
#####################################################################################

#Zoom In
sub zoomConTele
{
    my $self = shift;
    my $stop_command = "19";
    Debug( "Zoom Tele" );
    my $cmd = "decoder_control.cgi?command=18";
    $self->sendCmd( $cmd );
    $self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} );
}

#~ #Zoom Out
sub zoomConWide
{
    my $self = shift;
    my $stop_command = "17";
    Debug( "Zoom Wide" );
    my $cmd = "decoder_control.cgi?command=16";
    $self->sendCmd( $cmd );
    $self->autoStop( $stop_command, $self->{Monitor}->{AutoStopTimeout} );
}

#~ #Diagonally Up Right Arrow
#This camera does not have builtin diagonal commands so we emulate them
sub moveConUpRight
{
    my $self = shift;
    Debug( "Move Diagonally Up Right" );
    $self->moveConUp( );
    $self->moveConRight( );
}

#Diagonally Down Right Arrow
#This camera does not have builtin diagonal commands so we emulate them
sub moveConDownRight
{
    my $self = shift;
    Debug( "Move Diagonally Down Right" );
    $self->moveConDown( );
    $self->moveConRight( );
}
#~
#Diagonally Up Left Arrow
#This camera does not have builtin diagonal commands so we emulate them
sub moveConUpLeft
{
    my $self = shift;
    Debug( "Move Diagonally Up Left" );
    $self->moveConUp( );
    $self->moveConLeft( );
}
#~
#Diagonally Down Left Arrow
#This camera does not have builtin diagonal commands so we emulate them
sub moveConDownLeft
{
    my $self = shift;
    Debug( "Move Diagonally Down Left" );
    $self->moveConDown( );
    $self->moveConLeft( );
}

#Stop
#~ sub moveStop
#~ {
    #~ my $self = shift;
    #~ Debug( "Move Stop" );
    #~ my $cmd = "decoder_control.cgi?command=1";
    #~ $self->sendCmd( $cmd );
#~ }

#Set Camera Preset
#Presets must be translated into values internal to the camera
#Those values are: 30,32,34 ... 88,90,92 for presets 1-32 respectively
sub presetSet
{
    my $self = shift;
    my $params = shift;
    my $preset = $self->getParam( $params, 'preset' );
    Debug( "Set Preset $preset" );
#~
    if (( $preset >= 1 ) && ( $preset <= 32 )) {
        my $cmd = "decoder_control.cgi?command=".(($preset*2) + 28);
        $self->sendCmd( $cmd );
    }
}

#Recall Camera Preset
#Presets must be translated into values internal to the camera
#Those values are: 31,33,35 ... 89,91,93 for presets 1-32 respectively
sub presetGoto
{
    my $self = shift;
    my $params = shift;
    my $preset = $self->getParam( $params, 'preset' );
    Debug( "Goto Preset $preset" );
#~
    if (( $preset >= 1 ) && ( $preset <= 32 )) {
        my $cmd = "decoder_control.cgi?command=".(($preset*2) + 29);
        $self->sendCmd( $cmd );
    }

    #~ if ( $preset == 9 ) {
        #~ $self->horizontalPatrol();
    #~ }
    #~ if ( $preset == 10 ) {
        #~ $self->horizontalPatrolStop();
    #~ }
}

#~ sub presetHome
#~ {
    #~ my $self = shift;
    #~ Debug( "Home Preset" );
    #~ my $cmd = "decoder_control.cgi?command=25";
    #~ $self->sendCmd( $cmd );
#~ }

#Horizontal Patrol - Vertical Patrols are not supported
sub horizontalPatrol
{
    my $self = shift;
    Debug( "Horizontal Patrol" );
    my $cmd = "decoder_control.cgi?command=20";
    $self->sendCmd( $cmd );
}

#Horizontal Patrol Stop
sub horizontalPatrolStop
{
    my $self = shift;
    Debug( "Horizontal Patrol Stop" );
    my $cmd = "decoder_control.cgi?command=21";
    $self->sendCmd( $cmd );
}

# Set Absolute Brightness
#~ sub setAbsBrightness
#~ {
    #~ my $self = shift;
    #~ my $brightness = shift;
    #~ $brightness = 255 if $brightness > 255;
    #~ $brightness = 0   if $brightness < 0;
    #~ Debug( "Setting brightness to $brightness" };
    #~ $CamParams{'brightness'} = $brightness;
    #~ my $cmd = "camera_control.cgi?param=1&value=".$brightness;
    #~ $self->sendCmd( $cmd );
#~ }

# Increase Brightness
#~ sub irisAbsOpen
#~ {
    #~ my $self = shift;
    #~ my $params = shift;
    #~ $self->getCamParams() unless($CamParams{'brightness'});
    #~ my $step = $self->getParam( $params, 'step' );
#~
    #~ $CamParams{'brightness'} += $step;
    #~ $CamParams{'brightness'} = 255 if ($CamParams{'brightness'} > 255);
    #~ Debug( "Iris $CamParams{'brightness'}" );
    #~ my $cmd = "camera_control.cgi?param=1&value=".$CamParams{'brightness'};
    #~ $self->sendCmd( $cmd );
#~ }

# Decrease Brightness
#~ sub irisAbsClose
#~ {
    #~ my $self = shift;
    #~ my $params = shift;
    #~ $self->getCamParams() unless($CamParams{'brightness'});
    #~ my $step = $self->getParam( $params, 'step' );
#~
    #~ $CamParams{'brightness'} -= $step;
    #~ $CamParams{'brightness'} = 0 if ($CamParams{'brightness'} < 0);
    #~ Debug( "Iris $CamParams{'brightness'}" );
    #~ my $cmd = "camera_control.cgi?param=1&value=".$CamParams{'brightness'};
    #~ $self->sendCmd( $cmd );
#~ }

# Set Absolute Contrast
#~ sub setAbsContrast
#~ {
    #~ my $self = shift;
    #~ my $contrast = shift;
    #~ $contrast = 255 if $contrast > 255;
    #~ $contrast = 0   if $contrast < 0;
    #~ Debug( "Setting contrast to $contrast" };
    #~ $CamParams{'contrast'} = $contrast;
    #~ my $cmd = "camera_control.cgi?param=2&value=".$contrast;
    #~ $self->sendCmd( $cmd );
#~ }

# Increase Contrast
#~ sub whiteAbsIn
#~ {
    #~ my $self = shift;
    #~ my $params = shift;
    #~ $self->getCamParams() unless($CamParams{'contrast'});
    #~ my $step = $self->getParam( $params, 'step' );
#~
    #~ $CamParams{'contrast'} += $step;
    #~ $CamParams{'contrast'} = 6 if ($CamParams{'contrast'} > 6);
    #~ Debug( "Contrast $CamParams{'contrast'}" );
    #~ my $cmd = "camera_control.cgi?param=2&value=".$CamParams{'contrast'};
    #~ $self->sendCmd( $cmd );
#~ }

# Decrease Contrast
#~ sub whiteAbsOut
#~ {
    #~ my $self = shift;
    #~ my $params = shift;
    #~ $self->getCamParams() unless($CamParams{'contrast'});
    #~ my $step = $self->getParam( $params, 'step' );
#~
    #~ $CamParams{'contrast'} -= $step;
    #~ $CamParams{'contrast'} = 0 if ($CamParams{'contrast'} < 0);
    #~ Debug( "Iris $CamParams{'contrast'}" );
    #~ my $cmd = "camera_control.cgi?param=2&value=".$CamParams{'contrast'};
    #~ $self->sendCmd( $cmd );
#~ }

1;