Giter Club home page Giter Club logo

onvif's Introduction

ONVIF

Coverage Status NPM version

ONVIF Client protocol Profile S (Live Streaming) and Profile G (Replay) Node.js implementation.

This is a wrapper to ONVIF protocol which allows you to get information about your NVT (network video transmitter) device, its media sources, control PTZ (pan-tilt-zoom) movements and manage presets, detect devices in your network and control its events. It will also allow you to get information about your NVR (network video recorder) Profile G device and obtain a list of recordings.

The library uses NodeJS. And works on the server-side.

ONVIF

Troubleshooting

The library is tested on a test bed with 5 x Axis, 2 x Bosch, 1 x Canon, 2 x Hanwha, 4 x HikVision, 1 x Panasonic, 2 x Sony and 2 x unknown vendor cameras. There is a mix of PTZ and Fixed cameras and a mix of Pre-Profile, Profile S, Profile G and Profile T devices.

It is also tested with some Analogue Encoders from Avigilon, Axis, Bosch and HikVision including testing the RS485 output.

We welcome any donations or long term loans cameras from other vendors to test compatibility especially when testing the Media2 API, ONVIF Events and OSD.

Installation

NPM

npm install onvif - install latest stable version

npm install agsh/onvif - install latest version from GitHub

npm install agsh/onvif#v1 - install latest development version

Clone the latest version from github

git clone https://github.com/agsh/onvif.git

Tests

In the library directory run npm test

By default the tests use a mockup server to generate ONVIF replies.

To test with the real device, set appropriate environment variables HOSTNAME, USERNAME, PASSWORD, PORT and run tests.

Documentation

To build jsdoc for the library with default theme run npm run jsdoc. Otherwise use jsdoc with sources from ./lib/*.js

Quick example

Special teasing example how to create little funny video server (http://localhost:6147) with 1 ffmpeg and 3 node.js libraries:

Screencast_20240524_211440-1_EDIT.webm

sudo apt install ffmpeg
npm install onvif socket.io rtsp-ffmpeg
const server = require('http').createServer((req, res) =>
        res.end(`
<!DOCTYPE html><body>
<canvas width='640' height='480' />
<script src="/socket.io/socket.io.js"></script><script>
  const socket = io(), ctx = document.getElementsByTagName('canvas')[0].getContext('2d');
  socket.on('data', (data) => {
    const img = new Image;    
    const url = URL.createObjectURL(new Blob([new Uint8Array(data)], {type: 'application/octet-binary'}));
    img.onload = () => {
      URL.revokeObjectURL(url, {type: 'application/octet-binary'});
      ctx.drawImage(img, 100, 100);
    };
    img.src = url;
  });
</script></body></html>`));
const { Cam } = require('onvif/promises'), io = require('socket.io')(server), rtsp = require('rtsp-ffmpeg');
server.listen(6147);

const cam = new Cam({username: 'username', password: 'password', hostname: '192.168.0.116', port: 2020});
(async() => {
  await cam.connect();
  const input = (await cam.getStreamUri({protocol:'RTSP'})).uri.replace('://', `://${cam.username}:${cam.password}@`);
  const stream = new rtsp.FFMpeg({input, resolution: '320x240', quality: 3});
  io.on('connection', (socket) => {
    const pipeStream = socket.emit.bind(socket, 'data');
    stream.on('disconnect', () => stream.removeListener('data', pipeStream)).on('data', pipeStream);
  });
  setInterval(() => cam.absoluteMove({
    x: Math.random() * 2 - 1,
    y: Math.random() * 2 - 1,
    zoom: Math.random()
  }), 3000);
})().catch(console.error);

Other examples (located in the Examples Folder on the Github)

  • example.js - Move camera to a pre-defined position then server the RTSP URL up via a HTTP Server. Click on the RTSP address in a browser to open the video (if you have the VLC plugin installed)
  • example2.js - takes an IP address range, scans the range for ONVIF devices (brute force scan) and displays information about each device found including make and model and RTSP URLs For Profile S Cameras and Encoders it displays the default RTSP address For Profile G Recorders it displays the RTSP address of the first recording
  • example3.js - reads the command line cursor keys and sends PTZ commands to the Camera
  • example4.js - uses Discovery to find cameras on the local network
  • example5.js - connect to a camera via SOCKS proxy. Note SSH includes a SOCKS proxy so you can use this example to connect to remote cameras via SSH
  • example6.js - ONVIF Events. Example can be switched btween using Pull Point Subscriptions and using Base Subscribe with a built in mini HTTP Server
  • example7.js - example using a Promise API. It uses 'promisify' to convert the ONVIF Library to return promises and uses Await to wait for responses
  • example8.js - example setting OSD On Screen Display. (also uses Promises API)

API

You can find this page and full API class documentation here: http://agsh.github.io/onvif/

Short description of library possibilities is below.

Discovery

Since 0.2.7 version library supports WS-Discovery of NVT devices. Currently it uses only Probe SOAP method that just works well. You can find devices in your subnetwork using probe method of the Discovery singleton. Discovery is an EventEmitter inheritor, so you can wait until discovery timeout, or subscribe on device event. You must subscribe to the error event as a device on your network could reply with bad XML Here some examples:

var onvif = require('onvif');
onvif.Discovery.on('device', function(cam){
// function will be called as soon as NVT responds
	cam.username = <USERNAME>;
	cam.password = <PASSWORD>;
	cam.connect(console.log);
})
// Must have an error handler to catch bad replies from the network
onvif.Discovery.on('error', function (err,xml) {
  // function called as soon as NVT responds, but this library could not parse the response
  console.log('Discovery error ' + err);
});
onvif.Discovery.probe();
var onvif = require('onvif');
// Must have an error handler to catch bad replies from the network
onvif.Discovery.on('error', function (err,xml) {
  console.log('Discovery error ' + err);
});
onvif.Discovery.probe(function(err, cams) {
// function will be called only after timeout (5 sec by default)
	if (err) { 
    // There is a device on the network returning bad discovery data
    // Probe results will be incomplete
    throw err;
  }
	cams.forEach(function(cam) {
		cam.username = <USERNAME>;
		cam.password = <PASSWORD>;
		cam.connect(console.log);
	});
});

In all of that cases you've got disconnected cameras. To access each camera (and issue ONVIF commands) you normally need the tuple username:password. So, as shown in the examples, you can assign these properties and call connect method to get full functionality.

Discovery.probe(options, callback)

Options

  • timeout, number. Time the probe method will wait NVT responses in ms
  • resolve, boolean. If this argument is false, all discovered NVTs would be presented as data object instead of Cam instance

Discovery events

  • device(cam, remoteInfo, responseXML) fires on device discover. cam is a Cam instance, remoteInfo is an object with network information and responseXML is a body of SOAP response
  • error(error) fires on some UDP error or on bad SOAP response from NVT

Promises

Since version 0.7.2 this library have a onvif/promises namespace. It have promisified version of Cam constructor which returns an object with the same methods as described below or in documentation but returns promises instead of callback function. Short example of common usage is here:

const onvif = require('onvif/promises');
onvif.Discovery.on('device', async (cam) => {
  // Set credentials to connect
  cam.username = 'username';
  cam.password = 'password';
  await cam.connect();
  cam.on('event', (event)=> console.log(JSON.stringify(event.message, null, '\t')));
  cam.on('eventsError', console.error);
  console.log(cam.username, cam.password);
  console.log((await cam.getStreamUri({protocol:'RTSP'})).uri);
  const date = await cam.getSystemDateAndTime();
  console.log(date);
  await cam.absoluteMove({
    x: Math.random() * 2 - 1,
    y: Math.random() * 2 - 1,
    zoom: Math.random()
  });
});
onvif.Discovery.on('error', console.error);
onvif.Discovery.probe();

Cam class

const Cam = require('onvif').Cam;

new Cam(options, callback)

Options are:

  • hostname
  • username, password (optional, to deal with majority of functions)
  • port (optional)

The library calls connect() automatically which executes the getSystemDateAndTime, getCapabilities and other methods. Note on username and password:

  • Some cameras do not require username:password credentials.
  • If a camera does require a username:password but you do not provide them, you will be limited to executing a few ONVIF methods that can operate without credentials, for example you can execute only getSystemDateAndTime method.

Callback (optional) executes when the cam is initialised. Single argument for this function is possible error.

Technical description

When the cam object is created it automatically sends a getCapabilities command to the ONVIF device. If the device is a camera or encoder (NVT) it sends two commands to the ONVIF device: getVideoSources and getProfiles. It fills corresponding properties of an object:

  • capabilities
    • device
    • events
    • imaging
    • media
    • PTZ
    • extension
  • uri (this is a links to different NVT services)
  • videoSources
    • $.token
    • framerate
    • resolution
  • profiles, array of profile object
    • name
    • videoSourceConfiguration
    • videoEncoderConfiguration
    • PTZConfiguration

After that it runs getActiveSources method. It iterates over all video sources and tries to find out proper configuration for profile and videosource. First matching profile becomes a member of defaultProfiles array and video source configuration with ptz configuration becomes a member of activeSources array.

Configuration for the first or the only one video source becomes defaultProfile and activeSource properties. All methods without passing options object use it. You can change it manually at any time.

  • defaultProfile (link to the first profile in profiles)
  • activeSource (based on the default profile)
    • sourceToken
    • profileToken
    • encoding
    • width
    • height
    • fps
    • bitrate
    • ptz

connect(callback)

Connect to the camera and fill device information properties with getSystemDateAndTime, getCapabilities, getVideoSources, getProfiles methods

See more detailed information at http://www.onvif.org/ver10/media/wsdl/media.wsdl After cam initialisation we can run several ONVIF commands. There are several common methods that work without credentials. Here are they: getSystemDateAndTime.

getSystemDateAndTime(callback)

Returns a Date object with current camera datetime in the callback. The ONVIF Standard says this would work without credentials (passed username and password arguments) so that the timeShift difference between the local clock and the NVT's onboard clock can be calculated for SOAP Authentication. However some devices claiming ONVIF support require a password and the library will re-try the connection if a username and password are available.

getDeviceInformation(callback)

Device. Returns a device information, such as manufacturer, model and firmware version in the callback

getServices(callback)

Device. Returns in callback and assigns to #services property an array consists of objects with properties: namespace, XAddr, version

getServiceCapabilities(callback)

Device. Returns in callback and assigns to #serviceCapabilities property the capabilities of the device service (not media): network, security and system. If your device supports some auxiliary capabilities they will be there too.

getStreamUri(options, callback)

Media. Returns a URI that can be used to initiate a live media stream using RTSP as the control protocol The options are:

  • stream (optional) - defines if a multicast or unicast stream is requested. Possible values are: 'RTP-Unicast' (default), 'RTP-Multicast'
  • protocol (optional) - defines the network protocol for streaming. Possible values are: 'UDP', 'TCP', 'RTSP' (default), 'HTTP'
  • profileToken (optional) - defines media profile to use and will define the configuration of the content of the stream. Default is #activeSource.profileToken

getSnapshotUri(options, callback)

Media. Obtain a JPEG snapshot URI from the device.

getPresets(options, callback)

Returns the saved presets as an a key-value object where the key is the name of a preset and a value is a preset token. This method also stores the presets information in a #presets property of an object.

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

gotoPreset(options, callback)

PTZ. Operation to go to a saved preset position for the PTZ node in the selected profile.

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
  • preset - the name of preset. List of presets you can get by #getPresets method or in #presets property.

setPreset(options, callback)

PTZ. Operation to set the current position as a preset for the PTZ node in the selected profile. If presetToken is passed as an option, then the preset for which that token is attached will be replaced. After success, you should re-fetch the presets with #getPresets method.

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
  • presetName - the name to give to the preset. (optional) is this is a preset update.

removePreset(options, callback)

PTZ. Operation to remove a preset specified by the preset token. After success, you should re-fetch the presets with #getPresets method.

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
  • presetToken - the preset token to use for preset removal (this will be the value of a preset object found in #presets after calling the #getPresets method.

gotoHomePosition(options, callback)

PTZ. Operation to go to the saved home position for the PTZ node in the selected profile. If no home position has been saved, the ONVIF camera will do nothing.

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

  • speed An object with properties

    • x Pan speed, float within 0 to 1
    • y Tilt speed, float within 0 to 1
    • zoom Zoom speed, float within 0 to 1

    If the speed option is omitted, the default speed set by the PTZConfiguration will be used.

setHomePosition(options, callback)

PTZ. Operation to set the current position as the home position for the PTZ node in the selected profile.

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

getNodes(callback)

PTZ. Returns the properties of the current PTZ node, if it exists. Use this function to get maximum number of presets, ranges of admitted values for x, y, zoom, iris, focus. Sets all information into #nodes property.

relativeMove(options, callback)

PTZ. 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:

  • 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 0 to 1, optional

  • speed An object with properties

    • x Pan speed, float within 0 to 1
    • y Tilt speed, float within 0 to 1
    • zoom Zoom speed, float within 0 to 1

    If the speed option is omitted, the default speed set by the PTZConfiguration will be used.

Callback is optional and means essentially nothing

absoluteMove(options, callback)

PTZ. This is an absolute pan-tilt-zoom method. Options for this method is an absolute position of the camera.

The options are:

  • 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 0 to 1, optional

  • speed An object with properties

    • x Pan speed, float within 0 to 1
    • y Tilt speed, float within 0 to 1
    • zoom Zoom speed, float within 0 to 1

    If the speed option is omitted, the default speed set by the PTZConfiguration will be used.

Callback is optional and means essentially nothing

continuousMove(options, callback)

PTZ. Operation for continuous Pan/Tilt and Zoom movements

The options are:

  • x Pan velocity, number or a string within -1 to 1, optional
  • y Tilt velocity, number or a string within -1 to 1, optional
  • zoom Zoom velocity, number or a string within -1 to 1, optional
  • timeout Timeout in milliseconds, number. If timeout is omitted, movement will continue until stop command

stop(options, callback)

PTZ. Stop ongoing pan, tilt and zoom movements of absolute, relative and continuous type

Options and callback are optional. The options properties are:

  • profileToken (optional) - defines media profile to use and will define the configuration of the content of the stream. Default is #activeSource.profileToken
  • panTilt (optional) - set true when we want to stop ongoing pan and tilt movements. If panTilt arguments are not present, this command stops these movements.
  • zoom (optional) - set true when we want to stop ongoing zoom movement. If zoom arguments are not present, this command stops ongoing zoom movement.

getStatus(options, callback)

PTZ. Returns an object with the current PTZ values.

{
	position: {
		x: 'pan position', 
        y: 'tilt position',
		zoom: 'zoom'
	}
	, moveStatus: {} // camera moving
	, utcTime: 'current camera datetime'
}

getConfigurations(callback)

PTZ. Get all the existing PTZConfigurations from the device. Configurations saved into #configurations property

getConfigurationOptions(configurationToken, callback)

PTZ. Get supported coordinate systems including their range limitations for selected configuration. Extends corresponding configuration object

GetRecordings(callback)

Recordings. Get all the recordings tracks available on the device. Note: Only Onvif Profile G devices provide this features.

GetReplayUri(callback)

Recordings. Get the replay stream or streams (if using a NVR) - usually RTSP - for the provided recording token/s.

GetRecordingOptions(callback)

Recordings. Get the information of a recording token. Needed in order to match a recordingToken with a sourceToken. Used with both GetRecordings and GetReplayUri will allow to retreive recordings from an Onvif Profile G device. Note: not all devices are 100% Onvif G compliant.

Changelog

  • 0.7.1 Improved events handling
  • 0.6.5 Add MEDIA2 support, Profile T and GetServices XAddrs support for H265 cameras. Add support for HTTPS. Add Discovery.on('error') to examples. Add flag to only send Zoom, or only send Pan/Tilt for some broken cameras (Sony XP1 Xiongmai). Fix bug in GetServices. Improve setNTP command. API changed on getNetworkInterfaces and other methods that could return an Array or a Single Item. We now return an Array in all cases. Add example converting library so it uses Promises with Promisify. Enable 3702 Discovery on Windows for MockServer. Add MockServer test cases)
  • 0.6.1 Workaround for cams that don't send date-time
  • 0.6.0 Refactor modules for proper import in electron-based environment
  • 0.5.5 Added ptz.gotoHomePosition, ptz.setHomePosition. Fixed exceptions in ptz.getConfigurations and utils.parseSOAPString. Added tests for ptz.setPreset, ptz.removePreset, ptz.gotoHomePosition, and ptz.setHomePosition.
  • 0.5.4 Bumped for NPM.
  • 0.5.3 Some fixes. Tests
  • 0.5.2 preserveAddress property for NAT devices, discovery with multiple network interfaces (@Climax777)
  • 0.5.1 Critical bugfix in SOAP-auth for some cams
  • 0.5.0 Profile G support (@RogerHardiman), proper SOAP auth, nodejs support >= 0.12
  • 0.4.2 Bugfixes
  • 0.4.1 Improved discovery (@sousandrei, @RogerHardiman)
  • 0.4.0 Encoder support (@chriswiggins), Imaging service (@EastL)
  • 0.3.1 EventEmitter-based events
  • 0.3.0 Refactoring, documentation, event service basics
  • 0.2.7 WS-Discovery

Links

WSDL schemes and docs:

onvif's People

Contributors

agsh avatar bl0ggy avatar brandone avatar bryopsida avatar chriswiggins avatar climax777 avatar dependabot[bot] avatar eastl avatar francesco-ismb avatar glaadiss avatar haoguangsu avatar harryemartland avatar joastonish avatar joshperry avatar koush avatar lattice0 avatar manjunathan avatar mdalprato avatar mudrekh avatar rodrigograca31 avatar rogerhardiman avatar rommni avatar rotemdoar avatar silqa avatar sjkummer avatar sunnyworm avatar ta2k avatar thabetsabha avatar walkercode1989 avatar yuxiaolejs avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

onvif's Issues

Problems with PTZ-supported camera

I've run your sample code with a PTZ-supported camera:

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" target="' + stream.uri + '"></embed>' +
        '</body></html>');
    }).listen(3030);
  });
});

There's an exception:

..../node_modules/onvif/lib/ptz.js:333
            '<ProfileToken>' + (options.profileToken || this.activeSource.profileToken) + '</ProfileToken>' +
                                                                         ^

TypeError: Cannot read property 'profileToken' of undefined

some problems of search cam

hi agsh,

when i using function Discovery.probe of onvif,

sometime i can find all cam,but sometime i only search empte array

and if i clean my arptable , then i can find again

my OS is WINDOWS 7

Constructors should not cause side effects

Hi @agsh, first I would like to say; great package! Thank you for taking the time to put this together and for sharing it with all of us!

I've been playing around with your package lately as I learn more about the vast world of streaming IP security cameras, and for the most part, your library has worked great, and my issues have lied elsewhere.

However, in integrating with your library I have hit some integration pain points with the API that it exposes. The first being that the model objects exposed (Cam in this example) cause side effects when they are instantiated.

new Cam({
 hostname: <CAMERA_HOST>,
 username: <USERNAME>,
 password: <PASSWORD>
}, function(err) {
 // camera has connected
});

In the above example, the connect prototype method is called in the Cam constructor, which causes side effects such as firing network requests, etc.

In general, this is considered bad practice, as it prevents the consumer from separating the creation of objects, and the invocation of methods which cause side effects.

A more preferable pattern would be:

const camera = new Cam({
 hostname: <CAMERA_HOST>,
 username: <USERNAME>,
 password: <PASSWORD>
});

camera.connect((context) => {
 // camera has connected
});

Would you be open to a pull request that changes this behavior for Cam and other classes?

If so, I would recommend that once the PR was merged, a new major version of this package would be required, as changing the constructor behavior would be a breaking change to the current API contract.

Thanks for your time.

Resources for reference:
http://blog.millermedeiros.com/constructors-should-not-cause-side-effects/
https://stackoverflow.com/a/31392273

How to run the test

I download the latest ONVIF package and follow the step to install but failed to run the test. please help how to solve this.

  1. go to the unzip directory and run "npm install" to download all dependent library for this project.
    By checking folder node_modules, all modules download successfully.
  2. As the document said I run "npm test" to test it , it failed with attached snapsh
    1

Any one help how to runt the test?

profileToken problem using stock example.js

Running the example using node I get this exception right at start up. It appears to be generated as a result of the initial call to absoluteMove below. How should the profileToken have been set up?

new Cam({
    hostname: CAMERA_HOST,
    username: USERNAME,
    password: PASSWORD
}, function(err) {
    this.absoluteMove({
        x: 1
        , y: 1
        , zoom: 1
    });

though the asynchronous callback system makes this a little difficult to trace.

C:\src\onvif\lib\ptz.js:330
                        '<ProfileToken>' + (options.profileToken || this.activeS
ource.profileToken) + '</ProfileToken>' +

     ^

TypeError: Cannot read property 'profileToken' of undefined
    at Cam.absoluteMove (C:\src\onvif\lib\ptz.js:330:65)
    at null.<anonymous> (C:\src\onvif\example.js:17:7)
    at null.<anonymous> (C:\src\onvif\lib\cam.js:96:13)
    at null.<anonymous> (C:\src\onvif\lib\cam.js:415:13)
    at ClientRequest.<anonymous> (C:\src\onvif\lib\cam.js:193:4)
    at emitOne (events.js:77:13)
    at ClientRequest.emit (events.js:169:7)
    at Socket.socketErrorListener (_http_client.js:267:9)
    at emitOne (events.js:77:13)
    at Socket.emit (events.js:169:7)

Any thoughts on this?

dev branch and backward API compatibility

Due to 'API changes crash things',
I would like to suggest to have a 'dev' branch for new feature and API changes or experiments.
And before release, there might be better to have some 'backward API compatibility' for users to prepare the transation process. :-)

I was trying to clarify and debug a crash when IPcam only has H264 encoding (no MPEG4), but suddently the world changed. lol

Allow a timeout to be specified when creating a Cam instance

If the camera changes IP addresses, it can take a couple minutes to for the request to timeout when trying to connect to it. That's quite a while to wait to receive an error, so it would be nice to be able to configure a timeout for the http request.

Error on resolving response data from getPreset()

For my camera, when there's only 1 preset or even no preset, the result of linerase(data).getPresetsResponse.preset (in ptz.js, line 32) will not be an array(instead, its an empty string for 0, and an object for 1), thus no forEach method.

TypeError: undefined is not a function
    at null.<anonymous> (C:\Users\Derek\temp\camera-onvif\node_modules\onvif\lib\ptz.js:33:45)
    at C:\Users\Derek\temp\camera-onvif\node_modules\onvif\lib\utils.js:86:5
    at Parser.<anonymous> (C:\Users\Derek\temp\camera-onvif\node_modules\onvif\node_modules\xml2js\lib\xml2js.js:432:18)
    at Parser.emit (events.js:107:17)
    at Object.onclosetag (C:\Users\Derek\temp\camera-onvif\node_modules\onvif\node_modules\xml2js\lib\xml2js.js:401:26)
    at emit (C:\Users\Derek\temp\camera-onvif\node_modules\onvif\node_modules\xml2js\node_modules\sax\lib\sax.js:615:33)

    at emitNode (C:\Users\Derek\temp\camera-onvif\node_modules\onvif\node_modules\xml2js\node_modules\sax\lib\sax.js:620
:3)
    at closeTag (C:\Users\Derek\temp\camera-onvif\node_modules\onvif\node_modules\xml2js\node_modules\sax\lib\sax.js:861
:5)
    at Object.write (C:\Users\Derek\temp\camera-onvif\node_modules\onvif\node_modules\xml2js\node_modules\sax\lib\sax.js
:1294:29)
    at Parser.exports.Parser.Parser.parseString (C:\Users\Derek\temp\camera-onvif\node_modules\onvif\node_modules\xml2js
\lib\xml2js.js:451:31)

Eventing

feature request to add support to list and subscribe to ONVIF events, ie motion detection.

Something wrong with get profiletoken

Hello~I'm now using your onvif on my project, and I would like to discuss some questions with you.

I use your getStreamUri function but sometimes it got this error:

/home/Hydra/node_modules/onvif/lib/media.js:219
'' + (options.profileToken || this.activeSource.profileToken)
^
TypeError: Cannot read property 'profileToken' of undefined
at Cam.getStreamUri (/home/Hydra/node_modules/onvif/lib/media.js:219:65)
at null. (/home/Hydra/lib/wrapper/devices/onvifc.js:143:16)
at null. (/home/Hydra/node_modules/onvif/lib/cam.js:473:13)
at ClientRequest. (/home/Hydra/node_modules/onvif/lib/cam.js:172:3)
at ClientRequest.EventEmitter.emit (events.js:95:17)
at Socket.socketOnData (http.js:1588:9)
at TCP.onread (net.js:525:27)

When it runs on the same camera, sometimes success, sometimes error, And when this error occurs, camera still respone getProfiles correctly. How can I fix this problem, please give me advice, thanks.

try to use getSnapshotUri

Hi,
I'm new in nodejs.
I have no problem running the examples with my avigilon 2.0w-h3ptz-dp20. Now I'm trying to use the method getSnapshotUri, with no success.
Can you guys show some examples.

tks,

Can't play x-vlc format...

Browsers don't seem to like that format now and it seems support has been removed from Chrome/others.

I can use the API to display a single image but I want to display live video/stream. How do I encode the html with that URI?

two callbacks fired with getRecordings

Recently there was a change in lib/cam.js so that it fires a callback if there is a connection error from the camera.

When I call getRecordings on an NVT that does not support Profile G I now get two callbacks, the first being a callback with ECONNRESET and the second being a callback with 'Wrong ONVIF SOAP response'

The proper operation would be to check if getCapabilities lists a recording service.

But in this situation I was only expecting one callback to be fired.

Should we change lib/cam.js so that after the ECONNRESET callback, the value of callback is cleared so that the callback function is not executed a 2nd time.

Thanks

Improvement: Testing with non PTZ cameras

Hi there
I have been running the coffee script Test code against some IP cameras.
I have some cameras without PTZ so there is no PTZ Service XAddr in GetCapabilities.

This causes the initial camera check to fail (as there is no ptz.uri) and then the 3 'move' tests and the 1 'stop' test all fail.

I wondered if the test could change so that if there is no PTZ.URI then it skips PTZ tests.

Thanks
Roger

Improvement: RTSP address re-write for NAT devices

I am connecting to an NVT via a public IP address over the internet eg 8.8.8.8
The NVT is accessed via a NAT broadband router and has a 192.168.0.10 local address.

The NVT returns XAddrs with 192.168.0.10 but I notice this ONVIF libary ignores the IP address in the XAddrs and uses the original IP address used to connect to (eg the 8.8.8.8 address)

When asking for a RTSP stream (GetStreamUri) it returns a RTSP string with 192.168.0.10

As an Improvement it would be good to have a function to re-write the RTSP string, replacing the 192.168.0.10 with the public IP address (eg 8.8.8.8).
ONVIF Device Manager works like this

events not working

I tried with node 6.10, 8.0, 8.1.
I'm not sure if it's related to camera (some clone from china), since I can see events in its manager (some internet explorer activex plugin), but... if someone else also has this problem, then there might be something here to explore...

var CAMERA_HOST = '192.168.1.10',
    USERNAME = 'admin',
    PASSWORD = '',
    PORT = 8899;

var http = require('http'),
    Cam = require('onvif').Cam;

new Cam({
    hostname: CAMERA_HOST,
    username: USERNAME,
    password: PASSWORD,
    port: PORT
}, function(err) {
    if (err) {
        console.log('Connection Failed');
        return;
    }
    console.log('CONNECTED');   
    this.on('event', function(camMessage) { console.log(camMessage) });

});

Error: You should create pull-point subscription first!
at Cam.pullMessages (/home/mm/Downloads/tempp/node_modules/onvif/lib/events.js:137:9)
at Cam._eventPull (/home/mm/Downloads/tempp/node_modules/onvif/lib/events.js:196:8)
at Cam. (/home/mm/Downloads/tempp/node_modules/onvif/lib/events.js:100:12)
at ClientRequest. (/home/mm/Downloads/tempp/node_modules/onvif/lib/cam.js:225:4)
at emitOne (events.js:115:13)
at ClientRequest.emit (events.js:210:7)
at Socket.socketOnEnd (_http_client.js:435:9)
at emitNone (events.js:110:20)
at Socket.emit (events.js:207:7)
at endReadableNT (_stream_readable.js:1045:12)

--
and when I remove require ('http') (wich should not be a problem), then error changes to:

TypeError: Cannot read property 'events' of undefined
    at Cam._request (d:\moje\pcele\nodetesting\test_onvif3\node_modules\onvif\lib\cam.js:175:16)
    at Cam.createPullPointSubscription (d:\moje\pcele\nodetesting\test_onvif3\node_modules\onvif\lib\events.js:87:10)
    at Cam._eventRequest (d:\moje\pcele\nodetesting\test_onvif3\node_modules\onvif\lib\events.js:183:14)
    at Cam.<anonymous> (d:\moje\pcele\nodetesting\test_onvif3\node_modules\onvif\lib\events.js:170:14)
    at emitTwo (events.js:125:13)
    at Cam.emit (events.js:213:7)
    at _addListener (events.js:248:14)
    at Cam.addListener (events.js:298:10)
    at Cam.<anonymous> (d:\moje\pcele\nodetesting\test_onvif3\app.js:12:10)
    at Cam.<anonymous> (d:\moje\pcele\nodetesting\test_onvif3\node_modules\onvif\lib\cam.js:104:13)

Set camera resolution?

Hi, is it possible to set the camera resolution with this library?
I have a onvif ip camera (Sricam) that comes with a horrible android app. If I capture it's rtsp h264 stream with avconv or ffmpeg I get the resolution that I last selected in the android app. I have sniffed the packets the app sends and it does indeed send a start/setup packet with the desired resolution. Can I do the same with this library?

absoluteMove() question

Hi there, first let me say thank you for an excellent library!

I have a PTZ cam and have been playing with getting PTZ functionality working with this library. I tested the absoluteMove() method and the camera does indeed move but I am a bit confused about the maximum value of -1 to 1. I would have thought that an absolute movement would have given actual PTZ values rather than in a normalised range of -1 to 1.

When I tell the camera to move {x: 1, y: 0, zoom: 0} it will tilt down by 1 unit... this seems a bit weird to me since it will not accept any value above 1. How do you achieve setting exact values when you only have a range from -1 to 1?

Many thanks!

onvif package from npm is missing functionality (0.5.3)

npm is reporting the latest onvif package as 0.5.3, but it's missing some functionality, like setPreset and removePreset functions in ptz.js. Anyone know why this is happening? The latest version online on github shows "version": "0.5.3". Is it possible that the version wasn't bumped in the last submission to npm?
I'm going to have to download the latest and use it locally. :(

TypeError: Cannot read property '0' of undefined

When I try to run a discovery using the latest version (installed with npm install agsh/onvif#dev), I get the following:

# discover.coffee
onvif = require('onvif')
onvif.Discovery.on 'device', (cam) ->
  console.log('Camera!')

onvif.Discovery.probe()                     
# coffee discover.coffee
Camera!
Camera!
Camera!
events.js:160
      throw er; // Unhandled 'error' event
      ^

TypeError: Cannot read property '0' of undefined
  at Cam.<anonymous> (/dev/onvif/node_modules/onvif/lib/cam.js:255:103)
  at /dev/onvif/node_modules/onvif/lib/utils.js:94:5
  at Parser.<anonymous> (/dev/onvif/node_modules/xml2js/lib/xml2js.js:489:18)
  at emitOne (events.js:96:13)
  at Parser.emit (events.js:188:7)
  at Object.onclosetag (/dev/onvif/node_modules/xml2js/lib/xml2js.js:447:26)
  at emit (/dev/onvif/node_modules/sax/lib/sax.js:640:35)
  at emitNode (/dev/onvif/node_modules/sax/lib/sax.js:645:5)
  at closeTag (/dev/onvif/node_modules/sax/lib/sax.js:905:7)
  at Object.write (/dev/onvif/node_modules/sax/lib/sax.js:1449:13)
  at Parser.exports.Parser.Parser.parseString (/dev/onvif/node_modules/xml2js/lib/xml2js.js:508:31)
  at Parser.parseString (/dev/onvif/node_modules/xml2js/lib/xml2js.js:7:59)
  at Object.exports.parseString (/dev/onvif/node_modules/xml2js/lib/xml2js.js:540:19)
  at parseSOAPString (/dev/onvif/node_modules/onvif/lib/utils.js:62:9)
  at IncomingMessage.<anonymous> (/dev/onvif/node_modules/onvif/lib/cam.js:202:4)
  at emitNone (events.js:91:20)
  at IncomingMessage.emit (events.js:185:7)
  at endReadableNT (_stream_readable.js:974:12)
  at _combinedTickCallback (internal/process/next_tick.js:74:11)
  at process._tickCallback (internal/process/next_tick.js:98:9)

Any ideas?

ECONNREFUSED

For some reason the script gets stuck in this ocasion. Cam.js - line 186
It sould land in the callback on line 178 and timeout after the set time but it doesnt :/

Bug in parsing XAddrs in Discovery

I have some ONVIF devices which respond to a WS-Discovery but in the discovery XML reply there are TWO different XAddrs with a space between them.
The parsing code in discovery.js cannot handle this

Axis Encoder return this...
<d:XAddrs>http://169.254.119.177/onvif/services http://192.168.1.125/onvif/services</d:XAddrs>
Axis Q1615 returns this...
<d:XAddrs>http://192.168.1.102/onvif/device_service http://169.254.125.197/onvif/device_service</d:XAddrs>

Bosch Encoder returns this...
<d:XAddrs>http://192.168.1.124:80/onvif/device_service https://192.168.1.124:443/onvif/device_service</d:XAddrs>

One device (360 Vision Pred) only has one entry in the XAddr and so parses fine

The problem looks like this line in discovery.js

                                                var camUri = url.parse(data.probeMatches.probeMatch.XAddrs);
                                                cam = new Cam({
                                                        hostname: camUri.hostname
                                                        , port: camUri.port
                                                        , path: camUri.path
                                                });

followed by
Discovery.emit('device', cam, rinfo, xml);

It needs to detect if there are multiple XAddrs (some form of Split on Whitespace) and either loop through them, with multiple Emits() or turn the cam parameter into an array.

Logging?

Thanks for this library. I'm trying to validate a camera and it would be really useful to be able to record both outgoing and incoming packets. Where is the best place to hook in to do this? Additionally any thoughts on which logger package?

TAIA.

When trying to access events, getting Cannot read property 'address' of undefined

I have this code

var Cam = require('onvif').Cam;
var cam = new Cam({
  hostname: '192.168.1.108',
  username: 'admin',
  password: 'admin'
}, function(err) {
  console.log('CONNECTED');
  console.log(this)

  this.on('event', function(camMessage){console.log(camMessage)});
});

When I run it I get:

$ node onvif_events.js
CONNECTED
Cam {
  hostname: '192.168.1.108',
  username: 'admin',
  password: 'admin',
  port: 80,
  path: '/onvif/device_service',
  timeout: 120000,
  preserveAddress: false,
  events: {},
  timeShift: -822,
  capabilities: 
   { analytics: 
      { XAddr: 'http://192.168.1.108/onvif/analytics_service',
        ruleSupport: true,
        analyticsModuleSupport: true },
     device: 
      { XAddr: 'http://192.168.1.108/onvif/device_service',
        network: [Object],
        system: [Object],
        IO: [Object],
        security: [Object] },
     events: 
      { XAddr: 'http://192.168.1.108/onvif/event_service',
        WSSubscriptionPolicySupport: false,
        WSPullPointSupport: false,
        WSPausableSubscriptionManagerInterfaceSupport: false },
     imaging: { XAddr: 'http://192.168.1.108/onvif/imaging_service' },
     media: 
      { XAddr: 'http://192.168.1.108/onvif/media_service',
        streamingCapabilities: [Object],
        extension: [Object] },
     extension: { deviceIO: [Object], extensions: [Object] } },
  uri: 
   { media: 
      Url {
        protocol: 'http:',
        slashes: true,
        auth: null,
        host: '192.168.1.108',
        port: null,
        hostname: '192.168.1.108',
        hash: null,
        search: null,
        query: null,
        pathname: '/onvif/media_service',
        path: '/onvif/media_service',
        href: 'http://192.168.1.108/onvif/media_service' },
     imaging: 
      Url {
        protocol: 'http:',
        slashes: true,
        auth: null,
        host: '192.168.1.108',
        port: null,
        hostname: '192.168.1.108',
        hash: null,
        search: null,
        query: null,
        pathname: '/onvif/imaging_service',
        path: '/onvif/imaging_service',
        href: 'http://192.168.1.108/onvif/imaging_service' },
     events: 
      Url {
        protocol: 'http:',
        slashes: true,
        auth: null,
        host: '192.168.1.108',
        port: null,
        hostname: '192.168.1.108',
        hash: null,
        search: null,
        query: null,
        pathname: '/onvif/event_service',
        path: '/onvif/event_service',
        href: 'http://192.168.1.108/onvif/event_service' },
     device: 
      Url {
        protocol: 'http:',
        slashes: true,
        auth: null,
        host: '192.168.1.108',
        port: null,
        hostname: '192.168.1.108',
        hash: null,
        search: null,
        query: null,
        pathname: '/onvif/device_service',
        path: '/onvif/device_service',
        href: 'http://192.168.1.108/onvif/device_service' },
     deviceIO: 
      Url {
        protocol: 'http:',
        slashes: true,
        auth: null,
        host: '192.168.1.108',
        port: null,
        hostname: '192.168.1.108',
        hash: null,
        search: null,
        query: null,
        pathname: '/onvif/deviceIO_service',
        path: '/onvif/deviceIO_service',
        href: 'http://192.168.1.108/onvif/deviceIO_service' } },
  videoSources: [ { '$': [Object], framerate: 25, resolution: [Object] } ],
  profiles: 
   [ { '$': [Object],
       name: 'MediaProfile_Channel1_MainStream',
       videoSourceConfiguration: [Object],
       audioSourceConfiguration: [Object],
       videoEncoderConfiguration: [Object],
       audioEncoderConfiguration: [Object],
       videoAnalyticsConfiguration: [Object],
       metadataConfiguration: [Object] },
     { '$': [Object],
       name: 'MediaProfile_Channel1_SubStream1',
       videoSourceConfiguration: [Object],
       audioSourceConfiguration: [Object],
       videoEncoderConfiguration: [Object],
       audioEncoderConfiguration: [Object],
       videoAnalyticsConfiguration: [Object],
       metadataConfiguration: [Object] } ],
  defaultProfiles: 
   [ { '$': [Object],
       name: 'MediaProfile_Channel1_MainStream',
       videoSourceConfiguration: [Object],
       audioSourceConfiguration: [Object],
       videoEncoderConfiguration: [Object],
       audioEncoderConfiguration: [Object],
       videoAnalyticsConfiguration: [Object],
       metadataConfiguration: [Object] } ],
  activeSources: 
   [ { sourceToken: '000',
       profileToken: 'MediaProfile000',
       encoding: 'H264',
       width: 1920,
       height: 1080,
       fps: undefined,
       bitrate: 2048 } ],
  defaultProfile: 
   { '$': { token: 'MediaProfile000', fixed: true },
     name: 'MediaProfile_Channel1_MainStream',
     videoSourceConfiguration: 
      { '$': [Object],
        name: 'VideoSourceConfig_Channel1',
        useCount: 2,
        sourceToken: '000',
        bounds: [Object] },
     audioSourceConfiguration: 
      { '$': [Object],
        name: 'AudioSourceConfig_Channel1',
        useCount: 2,
        sourceToken: '000' },
     videoEncoderConfiguration: 
      { '$': [Object],
        name: 'VideoEncoderConfig_Channel1_MainStream',
        useCount: 1,
        encoding: 'H264',
        resolution: [Object],
        quality: 4,
        rateControl: [Object],
        H264: [Object],
        multicast: [Object],
        sessionTimeout: 'PT60S' },
     audioEncoderConfiguration: 
      { '$': [Object],
        name: 'AudioEncoderConfig_Channel1_MainStream',
        useCount: 1,
        encoding: 'AAC',
        bitrate: 384,
        sampleRate: 48,
        multicast: [Object],
        sessionTimeout: 'PT60S' },
     videoAnalyticsConfiguration: 
      { '$': [Object],
        name: 'VideoAnalyticsConfig_Channel1',
        useCount: 2,
        analyticsEngineConfiguration: [Object],
        ruleEngineConfiguration: [Object] },
     metadataConfiguration: 
      { '$': [Object],
        name: 'MetadataConfig_Channel1',
        useCount: 2,
        PTZStatus: [Object],
        events: [Object],
        analytics: true,
        multicast: [Object],
        sessionTimeout: 'PT60S' } },
  activeSource: 
   { sourceToken: '000',
     profileToken: 'MediaProfile000',
     encoding: 'H264',
     width: 1920,
     height: 1080,
     fps: undefined,
     bitrate: 2048 } }
rtsp://192.168.1.108:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
events.js:163
      throw er; // Unhandled 'error' event
      ^

TypeError: Cannot read property 'address' of undefined
    at Cam.<anonymous> (/Users/test/script/node_modules/onvif/lib/events.js:207:40)
    at Array.forEach (native)
    at Cam.<anonymous> (/Users/test/script/node_modules/onvif/lib/events.js:205:31)
    at Cam.<anonymous> (/Users/test/script/node_modules/onvif/lib/events.js:151:12)
    at /Users/test/script/node_modules/onvif/lib/utils.js:94:5
    at Parser.<anonymous> (/Users/test/script/node_modules/xml2js/lib/xml2js.js:489:18)
    at emitOne (events.js:96:13)
    at Parser.emit (events.js:191:7)
    at SAXParser.onclosetag (/Users/test/script/node_modules/xml2js/lib/xml2js.js:447:26)
    at emit (/Users/test/script/node_modules/sax/lib/sax.js:640:35)
    at emitNode (/Users/test/script/node_modules/sax/lib/sax.js:645:5)

Any ideas?

EDIT: This is a Dahua camera, full details:
Device TypeIPC-HDW4431EM-AS
Software Version2.460.0000.1.R, Build Date: 2016-10-25
WEB Version3.2.1.388722
ONVIF Version2.42

Onvif browser support

I want to use this module in my frontend application written in Aurelia.
I use ES6 to load the module

import {Onvif} from 'onvif';

I get this error in de console:
Error: Node dgram module not supported in browsers.

Is there a way to avoid this module?

Any recommendation for supported camera product?

Thanks for this library!

Recently I'm playing with camera. My foscam supports part of ONVIF but pretty incomplete. Do you have some recommendation for cameras that fully supports the protocol?

SpaceNotSupported on continuousMove.

Hello, I'm just trying to get continuousMove to work with my ONVIF camera. It supports Pan and Tilt, but not Zoom. When I try to use continuousMove with {x: 1}, I get this error as a result. The ONVIF specification says that means A space is referenced in an argument which is not supported by the PTZ node. Thank you for this library.

Error: ONVIF SOAP Fault: {
  "value":"SOAP-ENV:Sender",
  "subcode": {
    "value":"ter:InvalidArgVal",
    "subcode": {
      "value":"ter:SpaceNotSupported"
    }
  }
}

Discovery XML incorrect (fix included)

Hi
I tested v.0.4.0 and Discovery and found an error with the XML that you send out.
I have a working fix too.

In lib/discovery.js you are using a 2009 schema for discovery. The ONVIF spec requires devices to support the 2005 version (but could support newer vesions too). If I make the change below discovery works.

//change this
//'<a:To s:mustUnderstand="1">urn:docs-oasis-open-org:ws-dd:ns:discovery:2009:01</a:To>' +
// to this
'<a:To s:mustUnderstand="1">urn:schemas-xmlsoap-org:ws:2005:04:discovery</a:To>' +

Here is my test program

var onvif = require('onvif');
onvif.Discovery.on('device', function(cam){
    // function would be called as soon as NVT responses 
    console.log('received discovery message');
    console.log(cam.hostname);
    console.log(cam.port);
    console.log(cam.path);
})
onvif.Discovery.probe();

Also, while looking at the XML you generate I see the uuid has URN at the start
, messageID = 'urn:uuid:' + (options.messageId || guid())

Putting URN: at the start is the 2009 OASIS WS Discovery 1.1 way of doing things.
But in the 2005 WS Discovery standard you start with uuid: and there is no urn:.
I noticed my Axis IP encoder did not complain about the urn: at the start but perhaps for consistency you
(http://specs.xmlsoap.org/ws/2005/04/discovery/ws-discovery.pdf)
But perhaps the line should be
, messageID = 'uuid:' + (options.messageId || guid())

How can I save a jpg image from the camera?

Hi, Thanks for sharing your project, I have the following situation: I can see the image in the browser, but I can not save the jpg on my disk, it gives me authorization error (401).

new Cam({
hostname: getIP(),
username: getUser(),
password: getPassword(),
port: getPort()
}, function(err) {
if (err) {
console.log('Connection Failed for ' + obtenerIP() + ' Port: ' + obtenerPuerto() + ' Username: ' + obtenerUsuario() + ' Password: ' + obtenerPassword());
return;
}
console.log('CONNECTED');
this.absoluteMove({
x: 1
, y: 1
, zoom: 1
});

		this.getSnapshotUri({protocol:'RTSP'}, function(err, stream) {
				
			saveImage(stream.uri);

		});
	});

function saveImage(rutaOnvifImagen){

var file = fs.createWriteStream("miImagen.jpg");

request(rutaOnvifImagen).pipe(file);

}

This code generates a jpg file but it is not an image, When I open it with a notepad it contains the following message:

<title>401 Unauthorized</title>

Unauthorized

This server could not verify that you are authorized to access the document requested. Either you supplied the wrong credentials (e.g., bad password), or your browser doesn't understand how to supply the credentials required.

Thanks for your help

XML namespace not handled properly (plus workaround)

Hi
I am testing your ONVIF library and recently submitted Pull Request for a new example program

I hit upon the problem that xml2js output is different when there are xmlns namespace attributes in the XML and the ONVIF library does not cope with this.

For example xml2js gives me this output for one camera
{"uri":"rtsp://192.168.1.128:554/ch0.h264","invalidAfterConnect":false,"invalidAfterReboot":false,"timeout":"PT0S"}

But another camera gives this
{"uri":{"_":"rtsp://192.168.1.30:9554/h264","$":{"xmlns:tt":"http://www.onvif.org/ver10/schema"}},"invalidAfterConnect":{"_":false,"$":{"xmlns:tt":"http://www.onvif.org/ver10/schema"}},"invalidAfterReboot":{"_":false,"$":{"xmlns:tt":"http://www.onvif.org/ver10/schema"}},"timeout":{"_":"PT30S","$":{"xmlns:tt":"http://www.onvif.org/ver10/schema"}}}

*Note the '' and '$' which split the value from the namsapce.
*_

In the first camera I can use stream.uri to get the RTSP string.
But in the second camera I need to use the something like stream.uri['_']

The cause is the XML has name spaces in
<soap:Body><trt:GetStreamUriResponse xmlns:trt="http://www.onvif.org/ver10/media/wsdl" xmlns="http://www.onvif.org/ver10/media/wsdl"><trt:MediaUri><tt:Uri xmlns:tt="http://www.onvif.org/ver10/schema">rtsp://192.168.1.30:9554/h264</tt:Uri><tt:InvalidAfterConnect xmlns:tt="http://www.onvif.org/ver10/schema">false</tt:InvalidAfterConnect><tt:InvalidAfterReboot xmlns:tt="http://www.onvif.org/ver10/schema">false</tt:InvalidAfterReboot><tt:Timeout xmlns:tt="http://www.onvif.org/ver10/schema">PT30S</tt:Timeout></trt:MediaUri></trt:GetStreamUriResponse></soap:Body>

Notice the xmlns after the text 'GetStreamUriResponse'

The Fix
My quick fix is to add a RegEx to remove the XML name spaces before passing them to xml2js in the lib/utils.js file

const parseSOAPString = function(xml, callback) {

        /* Filter out xml name spaces */
        xml = xml.replace(/xmlns(.*?)=(".*?")/g,'');

        xml2js.parseString(
                xml
                , {

I looked for some options flags for xml2js.
I found one that aways put in the '_' but that needs all of the ONVIF library to change as the object that comes out of xml2js is different.

So I went for this quick one line fix.

Do you want me to do a Pull Request for it?
Or is there a way to get xml2js to handle this for us?

Roger

Authentication error in ONVIF enabled Dahua Camera

Make: Dahua
Camera Model: SD6A8240-HNI
ONVIF 2.4.1 supported camera

Running the example code changing the hostname, user, pass, with my login credentials, I hit an error in the function(err) callback.

Error: ONVIF SOAP Fault: Sender not Authorized

I checked ONVIF the camera settings and ONVIF support is enabled. Is there some settings regarding how the credentials are hashed that could be different between cameras? I'm not too familiar with IP cameras and but I would like to contribute a fix so it'd work with this camera model line.

Thank you

full stack trace below


Error: ONVIF SOAP Fault: Sender not Authorized
    at /Users/stanleyzheng/Code/Code/cam/node_modules/onvif/lib/utils.js:83:12
    at Parser.<anonymous> (/Users/stanleyzheng/Code/cam/node_modules/xml2js/lib/xml2js.js:489:18)
    at emitOne (events.js:96:13)
    at Parser.emit (events.js:188:7)
    at Object.onclosetag (/Users/stanleyzheng/Code/cam/node_modules/xml2js/lib/xml2js.js:447:26)
    at emit (/Users/stanleyzheng/Code/cam/node_modules/sax/lib/sax.js:640:35)
    at emitNode (/Users/stanleyzheng/Code/cam/node_modules/sax/lib/sax.js:645:5)
    at closeTag (/Users/stanleyzheng/Code/cam/node_modules/sax/lib/sax.js:905:7)
    at Object.write (/Users/stanleyzheng/Code/cam/node_modules/sax/lib/sax.js:1449:13)
    at Parser.exports.Parser.Parser.parseString (/Users/stanleyzheng/Code/cam/node_modules/xml2js/lib/xml2js.js:508:31)

Setting system date and time

Hello there,

Awesome work ! Very helpful :)

Could it be possible to add a method to set system's date and time ?

Docs

Rewrite README.md and generate fresh ones.

Encoder support

Hi all,

I'm keen to implement encoder support into this library (its already really powerful) - I've been playing with emitting new camera instances from inside getActiveSources if this.videoSources is an array (and consequently associating it with the right token), but its not really working and seems messy.

Can someone point to me where I/we should implement the encoder configuration? Is it best to support each encoder port as a new "camera" or should we keep it all under one camera instance?

Thanks for the help in the right direction!

TypeError in parseSOAPString on SOAP Error: "TypeError: Cannot read property '0' of undefined"

The parseSOAPString function in utils.js is crashing with this error:

TypeError: Cannot read property '0' of undefined
at utils.js:89:64

The problem is that your code is expecting a "text" object in "detail"
(result.envelope.body[0].fault[0].detail[0].text[0])
but the message from the camera has none.

To get this far I also had to work around issue #66 . Let me know if I can provide any more details

Thanks!

Here's the SOAP message:

{
  "envelope": {
    "header": [
      ""
    ],
    "body": [
      {
        "fault": [
          {
            "code": [
              {
                "value": [
                  "SOAP-ENV:Receiver"
                ],
                "subcode": [
                  {
                    "value": [
                      "Ter:PTZNotSupported"
                    ],
                    "subcode": [
                      ""
                    ]
                  }
                ]
              }
            ],
            "reason": [
              {
                "text": [
                  {
                    "_": "PTZ not supported",
                    "$": {
                      "xml:lang": "en"
                    }
                  }
                ]
              }
            ],
            "node": [
              "http://www.w3.org/2003/05/soap-envelope/node/ultimateReceiver"
            ],
            "role": [
              "http://www.w3.org/2003/05/soap-envelope/node/ultimateReceiver"
            ],
            "detail": [
              "PTZ is not supported by the device."
            ]
          }
        ]
      }
    ]
  }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.