agsh / onvif Goto Github PK
View Code? Open in Web Editor NEWONVIF node.js implementation
Home Page: http://agsh.github.io/onvif/
License: MIT License
ONVIF node.js implementation
Home Page: http://agsh.github.io/onvif/
License: MIT License
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
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?
Rewrite README.md and generate fresh ones.
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
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?
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
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."
]
}
]
}
]
}
}
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?
Make correct passwordDigest headers (timestamp and nonce).
I download the latest ONVIF package and follow the step to install but failed to run the test. please help how to solve this.
Any one help how to runt the test?
Is there a note on how to run this?
TAIA.
Please implement the OSD operations
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.
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)
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.
Make sure that event mechanism is working.
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())
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?
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)
A common setup is to attach cameras to a second network interface which is not the interface for the default gateway of the host.
This line will only broadcast to the interface which is the default gateway: , socket = require('dgram').createSocket('udp4');
https://github.com/agsh/onvif/blob/master/lib/discovery.js#L89
Hi,
I noticed that if some device, in my case a LAN printer, respond to a discovery request, the library doesn't check if that response message is onvif compliant. Then the library raise an exception when it try to create the cam object. I think it's enough adding a check here :
Line 101 in 5cfed69
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.
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!
If $.token
was used to set the config, the resulting query for the getVideoEncoderConfiguration
tries to query with token
, which isn't set. This causes the wrong config to be returned.
Fixed it here: #59
I follow the probe example and using Wireshark to watching package, but no "239.2255.255250" package. it seems windows system block "239.255.255.250" package.
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,
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?
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
http://www.onvif.org/ver10/media/wsdl/GetVideoEncoderConfigurationOptions returns all the options for a given configuration token or profile token (or default one I guess). This is something I dearly need.
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
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
I'm working on testing node-onvif with rpos https://github.com/BreeeZe/rpos
I found that GetScopes failed. BreeeZe/rpos#16
@RogerHardiman opened a PR fixing the problem #38
feature request to add support to list and subscribe to ONVIF events, ie motion detection.
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.
I think this method is not supported by the libray and has usefull features.
Maybe, Could we implement this method?
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)
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>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
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!
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
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. :(
Write all methods and build docs for http://www.onvif.org/ver20/imaging/wsdl/imaging.wsdl specs
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
Hello there,
Awesome work ! Very helpful :)
Could it be possible to add a method to set system's date and time ?
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"
}
}
}
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?
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
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 :/
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.