Skip to content

Commit

Permalink
Redesigned move methods
Browse files Browse the repository at this point in the history
  • Loading branch information
agsh committed Jan 21, 2015
1 parent d2524b2 commit 8d698b9
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 87 deletions.
76 changes: 56 additions & 20 deletions README.md
Expand Up @@ -31,23 +31,21 @@ In the library directory run
This example asks your camera to look up and starts a web server at port 3030 that distributes a web page with vlc-plugin
container which translates video from the camera.
```javascript
var http = require('http')
, Cam = require('./lib/onvif').Cam
;

new Cam({hostname: CAMERA_HOSTNAME, username: USERNAME, password: PASSWORD}, function(err) {
this.ptzAbsoluteMove({
positionPanTiltX: 1
, positionPanTiltY: 1
, zoom: 1
});
var http = require('http'),
Cam = require('onvif').Cam;

new Cam({
hostname: CAMERA_HOST,
username: USERNAME,
password: PASSWORD
}, function(err) {
this.absoluteMove({x: 1, y: 1, zoom: 1});
this.getStreamUri({protocol:'RTSP'}, function(err, stream) {
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(
'<html><body>' +
'<embed type="application/x-vlc-plugin" name="video" id="video" autoplay="yes"' +
'loop="yes" height="240" width="320" target="' + stream.uri + '"></embed>' +
'<embed type="application/x-vlc-plugin" target="' + stream.uri + '"></embed>' +
'</boby></html>');
}).listen(3030);
});
Expand Down Expand Up @@ -136,15 +134,53 @@ The options are:

* `profileToken` (optional) - defines media profile to use and will define the configuration of the content of the stream. Default is `#activeSource.profileToken`

### ptzRelativeMove(options, callback)
This is a relative pan-tilt method. Options for this method is a delta between desired and current position of the camera.
### relativeMove(options, callback)
This is a relative pan-tilt-zoom method. Options for this method is a delta between desired and current position of the camera.
The options are:
```javascript
{
x: 'Pan, number or a string within -1 to 1, optional',
y: 'Tilt, number or a string within -1 to 1, optional',
zoom: 'Zoom, number or a string within -1 to 1, optional',
speed: { // If the speed argument is omitted, the default speed set by the PTZConfiguration will be used.
x: 'Pan speed',
y: 'Tilt speed',
zoom: 'Zoom speed'
}
}
```

* `translationPanTiltX` (optional)
* `translationPanTiltY` (optional)
* `speedPanTiltX` (optional)
* `speedPanTiltY` (optional)
* `zoom` (optional)
### absoluteMove(options, callback)
This is an absolute pan-tilt-zoom method. Options for this method is an absolute position of the camera.
The options are:
```javascript
{
x: 'Pan, number or a string within -1 to 1, optional',
y: 'Tilt, number or a string within -1 to 1, optional',
zoom: 'Zoom, number or a string within -1 to 1, optional',
speed: { // If the speed argument is omitted, the default speed set by the PTZConfiguration will be used.
x: 'Pan speed',
y: 'Tilt speed',
zoom: 'Zoom speed'
}
}
```

### getStatus(options, callback)
Returns an object with the current PTZ values.
Returns an object with the current PTZ values.
```javascript
{
position: {
x: 'pan position'
, y: 'tilt position'
, zoom: 'zoom'
}
, moveStatus: {} // camera moving
, utcTime: 'current camera datetime'
}
```

##Links
WSDL schemes:
- http://www.onvif.org/ver10/media/wsdl/media.wsdl```
- http://www.onvif.org/ver20/ptz/wsdl/ptz.wsdl
23 changes: 15 additions & 8 deletions example.js
Expand Up @@ -2,22 +2,29 @@
* Created by Andrew D.Laptev<a.d.laptev@gmail.com> on 1/21/15.
*/

var http = require('http')
, Cam = require('./lib/onvif').Cam
;
var CAMERA_HOST = '192.168.68.111',
USERNAME = 'admin',
PASSWORD = '9999';

new Cam({hostname: '192.168.68.111', username: 'admin', password: '9999'}, function(err) {
this.ptzAbsoluteMove({
positionPanTiltX: 1
, positionPanTiltY: 1
var http = require('http'),
Cam = require('./lib/onvif').Cam;

new Cam({
hostname: CAMERA_HOST,
username: USERNAME,
password: PASSWORD
}, function(err) {
this.absoluteMove({
x: 1
, y: 1
, zoom: 1
});
this.getStreamUri({protocol:'RTSP'}, function(err, stream) {
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(
'<html><body>' +
'<embed type="application/x-vlc-plugin" name="video1" id="video1" controls="false" autoplay="yes" loop="yes" height="264" width="352" target="' + stream.uri + '"></embed>' +
'<embed type="application/x-vlc-plugin" target="' + stream.uri + '"></embed>' +
'</boby></html>');
}).listen(3030);
});
Expand Down
76 changes: 37 additions & 39 deletions lib/onvif.js
Expand Up @@ -383,29 +383,34 @@ Cam.prototype.getNode = function() {
};

/**
* TODO add zoom option, rename arguments, make options optional
* PTZ relative move
* @param {object} options
* @param {string} [options.profileToken]
* @param {string} [options.translationPanTiltX]
* @param {string} [options.translationPanTiltY]
* @param {string} [options.speedPanTiltX]
* @param {string} [options.speedPanTiltY]
* @param [callback]
* @constructor
* @param {string|number} [options.x] Pan, float
* @param {string|number} [options.y] Tilt, float
* @param {string|number} [options.zoom] Zoom, float
* @param {object} [options.speed] If the speed argument is omitted, the default speed set by the PTZConfiguration will be used.
* @param {string|number} [options.speed.x] Pan speed, float
* @param {string|number} [options.speed.y] Tilt speed, float
* @param {string|number} [options.speed.zoom] Zoom speed, float
* @param {Function} [callback]
*/
Cam.prototype.ptzRelativeMove = function(options, callback) {
Cam.prototype.relativeMove = function(options, callback) {
callback = callback ? callback.bind(this) : function() {};
this._request({
body: this._envelopeHeader() +
'<RelativeMove xmlns="http://www.onvif.org/ver20/ptz/wsdl">' +
'<ProfileToken>' + (options.profileToken || this.activeSource.profileToken) + '</ProfileToken>' +
'<Translation>' +
'<PanTilt x="' + options.translationPanTiltX + '" y="' + options.translationPanTiltY + '" space="http://www.onvif.org/ver10/tptz/PanTiltSpaces/TranslationGenericSpace" xmlns="http://www.onvif.org/ver10/schema"/>' +
'</Translation>' +
'<ProfileToken>' + (options.profileToken || this.activeSource.profileToken) + '</ProfileToken>' +
'<Translation>' +
(options.x && options.y ? '<PanTilt x="' + options.x + '" y="' + options.y + '" space="http://www.onvif.org/ver10/tptz/PanTiltSpaces/PositionGenericSpace" xmlns="http://www.onvif.org/ver10/schema"/>' : '') +
(options.zoom ? '<Zoom x="' + options.zoom + '" space="http://www.onvif.org/ver10/tptz/ZoomSpaces/PositionGenericSpace" xmlns="http://www.onvif.org/ver10/schema"/>' : '') +
'</Translation>' +
(options.speed ?
'<Speed>' +
'<PanTilt x="' + options.speedPanTiltX + '" y="' + options.speedPanTiltY + '" space="http://www.onvif.org/ver10/tptz/PanTiltSpaces/GenericSpeedSpace" xmlns="http://www.onvif.org/ver10/schema"/>' +
'</Speed>' +
(options.speed.x && options.speed.y ? '<PanTilt x="' + options.speed.x + '" y="' + options.speed.y + '" space="http://www.onvif.org/ver10/tptz/PanTiltSpaces/PositionGenericSpace" xmlns="http://www.onvif.org/ver10/schema"/>' : '') +
(options.zoom ? '<Zoom x="' + options.zoom + '" space="http://www.onvif.org/ver10/tptz/ZoomSpaces/PositionGenericSpace" xmlns="http://www.onvif.org/ver10/schema"/>' : '') +
'</Speed>'
: '') +
'</RelativeMove>' +
this._envelopeFooter()
}, callback);
Expand All @@ -415,22 +420,31 @@ Cam.prototype.ptzRelativeMove = function(options, callback) {
* PTZ absolute move
* @param {object} options
* @param {string} [options.profileToken]
* @param {string} options.positionPanTiltX
* @param {string} options.positionPanTiltY
* @param {string} options.zoom
* @param callback
* @constructor
* @param {string|number} [options.x] Pan, float
* @param {string|number} [options.y] Tilt, float
* @param {string|number} [options.zoom] Zoom, float
* @param {object} [options.speed] If the speed argument is omitted, the default speed set by the PTZConfiguration will be used.
* @param {string|number} [options.speed.x] Pan speed, float
* @param {string|number} [options.speed.y] Tilt speed, float
* @param {string|number} [options.speed.zoom] Zoom speed, float
* @param {Function} [callback]
*/
Cam.prototype.ptzAbsoluteMove = function(options, callback) {
Cam.prototype.absoluteMove = function(options, callback) {
callback = callback ? callback.bind(this) : function() {};
this._request({
body: this._envelopeHeader() +
'<AbsoluteMove xmlns="http://www.onvif.org/ver20/ptz/wsdl">' +
'<ProfileToken>' + (options.profileToken || this.activeSource.profileToken) + '</ProfileToken>' +
'<Position>' +
'<PanTilt x="' + options.positionPanTiltX + '" y="' + options.positionPanTiltY + '" space="http://www.onvif.org/ver10/tptz/PanTiltSpaces/PositionGenericSpace" xmlns="http://www.onvif.org/ver10/schema"/>' +
'<Zoom x="' + options.zoom + '" space="http://www.onvif.org/ver10/tptz/ZoomSpaces/PositionGenericSpace" xmlns="http://www.onvif.org/ver10/schema"/>' +
(options.x && options.y ? '<PanTilt x="' + options.x + '" y="' + options.y + '" space="http://www.onvif.org/ver10/tptz/PanTiltSpaces/PositionGenericSpace" xmlns="http://www.onvif.org/ver10/schema"/>' : '') +
(options.zoom ? '<Zoom x="' + options.zoom + '" space="http://www.onvif.org/ver10/tptz/ZoomSpaces/PositionGenericSpace" xmlns="http://www.onvif.org/ver10/schema"/>' : '') +
'</Position>' +
(options.speed ?
'<Speed>' +
(options.speed.x && options.speed.y ? '<PanTilt x="' + options.speed.x + '" y="' + options.speed.y + '" space="http://www.onvif.org/ver10/tptz/PanTiltSpaces/PositionGenericSpace" xmlns="http://www.onvif.org/ver10/schema"/>' : '') +
(options.zoom ? '<Zoom x="' + options.zoom + '" space="http://www.onvif.org/ver10/tptz/ZoomSpaces/PositionGenericSpace" xmlns="http://www.onvif.org/ver10/schema"/>' : '') +
'</Speed>'
: '') +
'</AbsoluteMove>' +
this._envelopeFooter()
}, callback);
Expand Down Expand Up @@ -479,20 +493,4 @@ Cam.prototype._envelopeFooter = function() {
'</s:Envelope>';
};

module.exports.Cam = Cam;

/*//var cam = new Cam({hostname: 'localhost', port: 10101, username: 'admin', password: '9999'}, function(err) {
var cam = new Cam({hostname: '192.168.68.111', username: 'admin', password: '9999'}, function(err) {
if (err) {
return console.log(err);
}
console.log(JSON.stringify(this));
//console.log(this.ptzUri);
//this.getPresets({}, console.log);
this.getStatus({}, function(err,d){console.log(JSON.stringify(d));});
//this.getStreamUri({protocol:'HTTP'}, console.log)
});
cam.on('rawResponse', function(data) {
console.log(data);
});*/
module.exports.Cam = Cam;
7 changes: 4 additions & 3 deletions package.json
@@ -1,8 +1,8 @@
{
"name": "onvif",
"version": "0.1.0",
"version": "0.1.1",
"author": "Andrew D.Laptev <a.d.laptev@gmail.com>",
"description": "ONVIF client",
"description": "Client to ONVIF NVT devices, especially cameras",
"main": "lib/onvif.js",
"scripts": {
"test": "./node_modules/.bin/istanbul cover ./node_modules/.bin/_mocha",
Expand All @@ -22,7 +22,8 @@
"onvif",
"video",
"PTZ",
"camera"
"camera",
"RTSP"
],
"license": "MIT",
"engines": {
Expand Down
18 changes: 10 additions & 8 deletions test/common.coffee
Expand Up @@ -138,33 +138,35 @@ describe 'Simple and common get functions', () ->

describe 'absolute move', () ->
it 'should returns empty RelativeResponseObject', (done) ->
cam.ptzAbsoluteMove {
cam.absoluteMove {
positionPanTiltX: 1
positionPanTiltY: 1
zoom: 1
}, done
it 'should works without callback', () ->
cam.ptzAbsoluteMove {
cam.absoluteMove {
positionPanTiltX: 1
positionPanTiltY: 1
zoom: 1
}

describe 'relative move', () ->
it 'should returns empty RelativeResponseObject', (done) ->
cam.ptzAbsoluteMove {
cam.relativeMove {
speedPanTiltX: 1
speedPanTiltY: 1
translationPanTiltX: 1
translationPanTiltY: 1
zoom: 1
}, done
it 'should works without callback', () ->
cam.ptzAbsoluteMove {
speedPanTiltX: 1
speedPanTiltY: 1
translationPanTiltX: 1
translationPanTiltY: 1
cam.relativeMove {
speed: {
x: 1
y: 1
}
x: 1
y: 1
zoom: 1
}

Expand Down
18 changes: 10 additions & 8 deletions test/common.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 8d698b9

Please sign in to comment.