Difference between revisions of "Apexis"
Marcusbrutus (talk | contribs) m (easier to read) |
|||
(7 intermediate revisions by 3 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 92: | Line 202: | ||
|- | |- | ||
| Control Address | | Control Address | ||
| admin | | <USERNAME>:<PASSWORD>@<IP_ADDRESS_OF_CAMERA>:<PORT><br/> | ||
eg: admin:@<IP_ADDRESS_OF_CAMERA>:80<br/> | |||
eg: zoneminder:zonepass@192.168.1.111 | eg: zoneminder:zonepass@192.168.1.111 | ||
|- | |- |
Latest revision as of 14:27, 24 March 2016
Apexis APM J0233 WS IR (IR, outdoor, IP66)
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 |
|
---|
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 |
|
---|
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
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 |
|
---|
Control |
|
---|
- Control Capability - Apexis Mjpeg IP
Main |
|
---|
Move |
|
---|
Pan |
|
---|
Tilt |
|
---|
Zoom |
|
---|
Presets |
|
---|
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;