diff --git a/.gitignore b/.gitignore index 579043d..8659eab 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,4 @@ Temporary Items test node_modules +package-lock.json diff --git a/README.md b/README.md index 3a7c328..09201d1 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,8 @@ This package includes a sample application "[ONVIF Network Camera Manager](https * [`getCurrentProfile()` method](#OnvifDevice-getCurrentProfile-method) * [`getProfileList()` method](#OnvifDevice-getProfileList-method) * [`changeProfile(index|token)` method](#OnvifDevice-changeProfile-method) + * [`addVideoSourceConfiguration(index|token)` method](#OnvifDevice-addVideoSource-method) + * [`addVideoEncoderConfiguration(index|token)` method](#OnvifDevice-addVideoEncoder-method) * [`getUdpStreamUrl()` method](#OnvifDevice-getUdpStreamUrl-method) * [`fetchSnapshot(callback)` method](#OnvifDevice-fetchSnapshot-method) * [`ptzMove(params[, callback])` method](#OnvifDevice-ptzMove-method) @@ -63,6 +65,7 @@ This package includes a sample application "[ONVIF Network Camera Manager](https * [`getCapabilities([callback])` method](#OnvifServiceDevice-getCapabilities-method) * [`getWsdlUrl([callback])` method](#OnvifServiceDevice-getWsdlUrl-method) * [`getDiscoveryMode([callback])` method](#OnvifServiceDevice-getDiscoveryMode-method) + * [`setDiscoveryMode(mode,[callback])` method](#OnvifServiceDevice-setDiscoveryMode-method) * [`getScopes([callback])` method](#OnvifServiceDevice-getScopes-method) * [`setScopes(params[, callback])` method](#OnvifServiceDevice-setScopes-method) * [`addScopes(params[, callback])` method](#OnvifServiceDevice-addScopes-method) @@ -137,6 +140,7 @@ This package includes a sample application "[ONVIF Network Camera Manager](https * [`getPresets(params[, callback])` method](#OnvifServicePtz-getPresets-method) * [`gotoPreset(params[, callback])` method](#OnvifServicePtz-gotoPreset-method) * [`removePreset(params[, callback])` method](#OnvifServicePtz-removePreset-method) +* [`OnvifServiceImaging` object](#OnvifServiceImaging-object) * [References](#References) * [Release Note](#Release-Note) * [License](#License) @@ -600,6 +604,7 @@ Property | | Type | Description `services` | | Object | +- | `device` | Object | [`OnvifServiceDevice`](#OnvifServiceDevice-object) object +- | `media` | Object | [`OnvifServiceMedia`](#OnvifServiceMedia-object) object ++- | `imaging`| Object | [`OnvifServiceImaging`](#OnvifServiceImaging-object) object +- | `ptz` | Object | [`OnvifServicePtz`](#OnvifServicePtz-object) object These objects will be set when the initialization process is completed calling the [`init()`](#OnvifDevice-init-method) method. See the section "[ONVIF commands](#ONVIF-commands)" for details. @@ -812,7 +817,13 @@ This sample code will output the result like this: - Before: 1280 x 720 - After: 320 x 180 ``` +#### addVideoSourceConfiguration(*index|token*) +TBD + +#### addVideoEncoderConfiguration(*index|token*) + +TBD #### getUdpStreamUrl() This method returns the UDP Stream URL. Though the URL can be obtained from the result of the [`getCurrentProfile()`](#OnvifDevice-getCurrentProfile-method) method as well, this method makes that easy. @@ -1052,6 +1063,10 @@ This method sends a `GetWsdlUrl` command. This method sends a `GetDiscoveryMode` command. +### setDiscoveryMode(*[callback]*) method + +This method sends a `setDiscoveryMode` command. The 1st argument `mode` MUST be either 'Discoverable' or 'NonDiscoverable' + ### getScopes(*[callback]*) method This method sends a `GetScopes` command. @@ -1201,6 +1216,10 @@ return device.services.device.setDNS(params).then((result) => { This method sends a `GetNetworkProtocols` command. +### setNetworkInterfaces(*params[,callback]*) method + +This method sends a `GetNetworkProtocols` command. + ### getNetworkProtocols(*[callback]*) method This method sends a `GetNetworkProtocols` command. diff --git a/lib/modules/device.js b/lib/modules/device.js index 29c0522..1e2028f 100644 --- a/lib/modules/device.js +++ b/lib/modules/device.js @@ -14,6 +14,7 @@ const mEventEmitter = require('events').EventEmitter; const mOnvifServiceDevice = require('./service-device.js'); const mOnvifServiceMedia = require('./service-media.js'); const mOnvifServicePtz = require('./service-ptz.js'); +const mOnvifServiceImaging = require('./service-imaging.js'); const mOnvifServiceEvents = require('./service-events.js'); const mOnvifHttpAuth = require('./http-auth.js'); @@ -38,7 +39,10 @@ function OnvifDevice(params) { this.user = ''; this.pass = ''; this.keepAddr = false; + this.onvifCompliant = 'no'; + this.isAddressable = true; this.lastResponse = null; // for debug + this.lastError = null; if (('xaddr' in params) && typeof (params['xaddr']) === 'string') { this.xaddr = params['xaddr']; @@ -348,7 +352,16 @@ OnvifDevice.prototype.init = function (callback) { }).then(() => { return this._getDeviceInformation(); }).then(() => { - return this._mediaGetProfiles(); + return this._getVideoSources(); + }).then(() => { + if (!Array.isArray(this.video_sources)) + return this.getProfiles(); + else { + this.isMultiCameraDevice = true + return(new Promise((res,rej) => { + res(null) + })) + } }).then(() => { return this._mediaGetStreamURI(); }).then(() => { @@ -357,6 +370,38 @@ OnvifDevice.prototype.init = function (callback) { let info = this.getInformation(); resolve(info); }).catch((error) => { + + // If we can't even talk to this guy, then abort - but mark the guy as unaddressable + if (this.lastError.toString().search(/Network Error/i) >= 0){ + this.isAddressable = false; + } + reject(error); + }); + }); + if (this._isValidCallback(callback)) { + promise.then((info) => { + callback(null, info); + }).catch((error) => { + callback(error); + }); + } else { + return promise; + } +}; + +/* ------------------------------------------------------------------ +* Method: isONVIF([callback]) +* ---------------------------------------------------------------- */ +OnvifDevice.prototype.isONVIF = function (callback) { + let promise = new Promise((resolve, reject) => { + this._getSystemDateAndTime().then(() => { + resolve(null) + }).catch((error) => { + + // If we can't even talk to this guy, then abort - but mark the guy as unaddressable + if (this.lastError.toString().search(/Network Error/i) >= 0){ + this.isAddressable = false; + } reject(error); }); }); @@ -375,13 +420,19 @@ OnvifDevice.prototype.init = function (callback) { OnvifDevice.prototype._getSystemDateAndTime = function () { let promise = new Promise((resolve, reject) => { this.services.device.getSystemDateAndTime((error, result) => { - // Ignore the error becase some devices do not support - // the GetSystemDateAndTime command and the error does - // not cause any trouble. - if (!error) { + this.lastError = error; + this.lastResponse = result; + + // If no error, then use result to calculate the time difference between us + // That delta will be used in NONCE creation for subsequent authorized calls + if (!error){ this.time_diff = this.services.device.getTimeDiff(); - } - resolve(); + this.date_time = this.services.device.getDateTime() + this.date_time_unparsed = result.converted.Body.GetSystemDateAndTimeResponse.SystemDateAndTime + this.onvifCompliant = 'yes' + resolve() + } else + reject(error) }); }); return promise; @@ -391,11 +442,13 @@ OnvifDevice.prototype._getSystemDateAndTime = function () { OnvifDevice.prototype._getCapabilities = function () { let promise = new Promise((resolve, reject) => { this.services.device.getCapabilities((error, result) => { + this.lastError = error; this.lastResponse = result; if (error) { reject(new Error('Failed to initialize the device: ' + error.toString())); return; } + this.onvifCompliant = 'yes' let c = result['data']['GetCapabilitiesResponse']['Capabilities']; if (!c) { reject(new Error('Failed to initialize the device: No capabilities were found.')); @@ -412,14 +465,12 @@ OnvifDevice.prototype._getCapabilities = function () { } let imaging = c['Imaging']; if (imaging && imaging['XAddr']) { - /* this.services.imaging = new mOnvifServiceImaging({ 'xaddr' : imaging['XAddr'], 'time_diff': this.time_diff, 'user' : this.user, 'pass' : this.pass }); - */ } let media = c['Media']; if (media && media['XAddr']) { @@ -445,10 +496,28 @@ OnvifDevice.prototype._getCapabilities = function () { return promise; }; +// GetVideoSources (Access Class: READ_SYSTEM) +OnvifDevice.prototype._getVideoSources = function () { + let promise = new Promise((resolve, reject) => { + this.services.media.getVideoSources((error, result) => { + this.lastError = error; + this.lastResponse = result; + if (error) { + reject(new Error('Failed to initialize the device: ' + error.toString())); + } else { + this.video_sources = result['data']['GetVideoSourcesResponse']['VideoSources']; + resolve(); + } + }); + }); + return promise; +}; // GetDeviceInformation (Access Class: READ_SYSTEM) OnvifDevice.prototype._getDeviceInformation = function () { let promise = new Promise((resolve, reject) => { this.services.device.getDeviceInformation((error, result) => { + this.lastError = error; + this.lastResponse = result; if (error) { reject(new Error('Failed to initialize the device: ' + error.toString())); } else { @@ -461,9 +530,10 @@ OnvifDevice.prototype._getDeviceInformation = function () { }; // Media::GetProfiles (Access Class: READ_MEDIA) -OnvifDevice.prototype._mediaGetProfiles = function () { +OnvifDevice.prototype.getProfiles = function () { let promise = new Promise((resolve, reject) => { this.services.media.getProfiles((error, result) => { + this.lastError = error; this.lastResponse = result; if (error) { reject(new Error('Failed to initialize the device: ' + error.toString())); @@ -478,6 +548,7 @@ OnvifDevice.prototype._mediaGetProfiles = function () { profiles.forEach((p) => { let profile = { 'token': p['$']['token'], + 'fixed': p['$']['fixed'].toLowerCase() == 'true', 'name': p['Name'], 'snapshot': '', 'stream': { @@ -525,6 +596,7 @@ OnvifDevice.prototype._mediaGetProfiles = function () { } if (p['VideoEncoderConfiguration']) { profile['video']['encoder'] = { + 'encoding': p['VideoEncoderConfiguration']['Encoding'], 'token': p['VideoEncoderConfiguration']['$']['token'], 'name': p['VideoEncoderConfiguration']['Name'], 'resolution': { @@ -534,7 +606,9 @@ OnvifDevice.prototype._mediaGetProfiles = function () { 'quality': parseInt(p['VideoEncoderConfiguration']['Quality'], 10), 'framerate': parseInt(p['VideoEncoderConfiguration']['RateControl']['FrameRateLimit'], 10), 'bitrate': parseInt(p['VideoEncoderConfiguration']['RateControl']['BitrateLimit'], 10), - 'encoding': p['VideoEncoderConfiguration']['Encoding'] + 'encodinginterval': parseInt(p['VideoEncoderConfiguration']['RateControl']['EncodingInterval'], 10), + 'encoding': p['VideoEncoderConfiguration']['Encoding'], + 'govlength': p['VideoEncoderConfiguration']['H264'] ? parseInt(p['VideoEncoderConfiguration']['H264']['GovLength'],10) : null }; } if (p['AudioSourceConfiguration']) { @@ -604,6 +678,7 @@ OnvifDevice.prototype._mediaGetStreamURI = function () { 'Protocol': protocol }; this.services.media.getStreamUri(params, (error, result) => { + this.lastError = error; this.lastResponse = result; if (!error) { let uri = result['data']['GetStreamUriResponse']['MediaUri']['Uri']; @@ -637,6 +712,7 @@ OnvifDevice.prototype._mediaGetSnapshotUri = function () { if (profile) { let params = { 'ProfileToken': profile['token'] }; this.services.media.getSnapshotUri(params, (error, result) => { + this.lastError = error; this.lastResponse = result; if (!error) { try { diff --git a/lib/modules/http-auth.js b/lib/modules/http-auth.js index 779551a..6525e4e 100644 --- a/lib/modules/http-auth.js +++ b/lib/modules/http-auth.js @@ -90,7 +90,7 @@ OnvifHttpAuth.prototype._createAuthReqHeaderValue = function(o) { }; OnvifHttpAuth.prototype._createCnonce = function(digit) { - let nonce = new Buffer(digit); + let nonce = Buffer.alloc(digit); for(let i=0; i { resolve(result); }).catch((error) => { @@ -172,6 +186,41 @@ OnvifServiceDevice.prototype.getDiscoveryMode = function(callback) { } }; +/* ------------------------------------------------------------------ +* Method: setDiscoveryMode(mode, callback) +* - mode | String | required | 'Discoverable' or 'NonDiscoverable' +* +* }* ---------------------------------------------------------------- */ +OnvifServiceDevice.prototype.setDiscoveryMode = function(mode, callback) { + let promise = new Promise((resolve, reject) => { + let err_msg = ''; + if(err_msg = mOnvifSoap.isInvalidValue(mode, 'string') + || (mode != 'Discoverable' && mode != 'NonDiscoverable')) { + reject(new Error('The value of "mode" was invalid: ' + err_msg)); + return; + } + + let soap_body = ''; + soap_body += '' + mode + ''; + soap_body += ''; + let soap = this._createRequestSoap(soap_body); + mOnvifSoap.requestCommand(this.oxaddr, 'SetDiscoveryMode', soap).then((result) => { + resolve(result); + }).catch((error) => { + reject(error); + }); + }); + if(callback) { + promise.then((result) => { + callback(null, result); + }).catch((error) => { + callback(error); + }); + } else { + return promise; + } +}; + /* ------------------------------------------------------------------ * Method: getScopes([callback]) * ---------------------------------------------------------------- */ @@ -612,6 +661,56 @@ OnvifServiceDevice.prototype.getNetworkInterfaces = function(callback) { } }; + +/* ------------------------------------------------------------------ +* Method: setNetworkInterfaces([callback]) +* ---------------------------------------------------------------- */ +OnvifServiceDevice.prototype.setNetworkInterfaces = function(info,callback) { + //info.data.GetNetworkInterfacesResponse.NetworkInterfaces.$.token + //info.data.GetNetworkInterfacesResponse.NetworkInterfaces.IPv4.enabled = true + //info.data.GetNetworkInterfacesResponse.NetworkInterfaces.IPv4.Config.DHCP = false + //info.data.GetNetworkInterfacesResponse.NetworkInterfaces.IPv4.Config.Manual.Address = req.body.newip + //info.data.GetNetworkInterfacesResponse.NetworkInterfaces.IPv4.Config.Manual.PrefixLength = "24" + let promise = new Promise((resolve, reject) => { + let soap_body = ''; + soap_body += ''; + soap_body += '' + info.interface.data.GetNetworkInterfacesResponse.NetworkInterfaces.$.token + '' + soap_body += '' + soap_body += 'true' + //soap_body += '1500' + soap_body += '' + soap_body += 'true' + if (info.dhcp){ + soap_body += 'true' + } else { + soap_body += '' + soap_body += '
' + info.ip + '
' + soap_body += '24' + soap_body += '
' + soap_body += 'false' + } + soap_body += '
' + soap_body += '
' + soap_body += '
'; + let soap = this._createRequestSoap(soap_body); + mOnvifSoap.requestCommand(this.oxaddr, 'SetNetworkInterfaces', soap).then((result) => { + resolve(result); + }).catch((error) => { + reject(error); + }); + }); + if(callback) { + promise.then((result) => { + callback(null, result); + }).catch((error) => { + callback(error); + }); + } else { + return promise; + } +}; + + /* ------------------------------------------------------------------ * Method: getNetworkProtocols([callback]) * ---------------------------------------------------------------- */ @@ -863,13 +962,15 @@ OnvifServiceDevice.prototype.getDeviceInformation = function(callback) { OnvifServiceDevice.prototype.getSystemDateAndTime = function(callback) { let promise = new Promise((resolve, reject) => { let soap_body = ''; - let soap = this._createRequestSoap(soap_body); + let soap = this._createRequestSoap(soap_body,true); mOnvifSoap.requestCommand(this.oxaddr, 'GetSystemDateAndTime', soap).then((result) => { let parsed = this._parseGetSystemDateAndTime(result['converted']); if(parsed && parsed['date']) { let device_time = parsed['date'].getTime(); let my_time = (new Date()).getTime(); this.time_diff = device_time - my_time; + this.date_time = parsed.date + this.date_time_unparsed = result.converted.Body.GetSystemDateAndTimeResponse.SystemDateAndTime } resolve(result); }).catch((error) => { @@ -960,9 +1061,9 @@ OnvifServiceDevice.prototype.setSystemDateAndTime = function(params, callback) { if(err_msg = mOnvifSoap.isInvalidValue(params['TimeZone'], 'string')) { reject(new Error('The "TimeZone" property was invalid: ' + err_msg)); return; - } else if(!params['TimeZone'].match(/^[A-Z]{3}\-?\d{1,2}([A-Z]{3,4})?$/)) { - reject(new Error('The "TimeZone" property must be a string representing a time zone which is defined in POSIX 1003.1.')); - return; + //} else if(!params['TimeZone'].match(/^[A-Z]{3}\-?\d{1,2}([A-Z]{3,4})?$/)) { + //reject(new Error('The "TimeZone" property must be a string representing a time zone which is defined in POSIX 1003.1.')); + //return; } } @@ -1684,4 +1785,4 @@ OnvifServiceDevice.prototype.getServiceCapabilities = function(callback) { } }; -module.exports = OnvifServiceDevice; \ No newline at end of file +module.exports = OnvifServiceDevice; diff --git a/lib/modules/service-imaging.js b/lib/modules/service-imaging.js new file mode 100644 index 0000000..6e3a494 --- /dev/null +++ b/lib/modules/service-imaging.js @@ -0,0 +1,203 @@ +/* ------------------------------------------------------------------ +* node-onvif - service-imaging.js +* +* Copyright (c) 2016 - 2017, Futomi Hatano, All rights reserved. +* Released under the MIT license +* Date: 2017-08-30 +* ---------------------------------------------------------------- */ +'use strict'; +const mUrl = require('url'); +const mOnvifSoap = require('./soap.js'); + +/* ------------------------------------------------------------------ +* Constructor: OnvifServiceImaging(params) +* - params: +* - xaddr : URL of the entry point for the imaging service +* (Required) +* - user : User name (Optional) +* - pass : Password (Optional) +* - time_diff: ms +* ---------------------------------------------------------------- */ +function OnvifServiceImaging(params) { + this.xaddr = ''; + this.user = ''; + this.pass = ''; + + let err_msg = ''; + + if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { + throw new Error('The value of "params" was invalid: ' + err_msg); + } + + if('xaddr' in params) { + if(err_msg = mOnvifSoap.isInvalidValue(params['xaddr'], 'string')) { + throw new Error('The "xaddr" property was invalid: ' + err_msg); + } else { + this.xaddr = params['xaddr']; + } + } else { + throw new Error('The "xaddr" property is required.'); + } + + if('user' in params) { + if(err_msg = mOnvifSoap.isInvalidValue(params['user'], 'string', true)) { + throw new Error('The "user" property was invalid: ' + err_msg); + } else { + this.user = params['user'] || ''; + } + } + + if('pass' in params) { + if(err_msg = mOnvifSoap.isInvalidValue(params['pass'], 'string', true)) { + throw new Error('The "pass" property was invalid: ' + err_msg); + } else { + this.pass = params['pass'] || ''; + } + } + + this.oxaddr = mUrl.parse(this.xaddr); + if(this.user) { + this.oxaddr.auth = this.user + ':' + this.pass; + } + + this.time_diff = params['time_diff']; + this.name_space_attr_list = [ + 'xmlns:ter="http://www.onvif.org/ver10/error"', + 'xmlns:xs="http://www.w3.org/2001/XMLSchema"', + 'xmlns:tt="http://www.onvif.org/ver10/schema"', + 'xmlns:tptz="http://www.onvif.org/ver20/ptz/wsdl"' + ]; +} + +OnvifServiceImaging.prototype._createRequestSoap = function(body) { + let soap = mOnvifSoap.createRequestSoap({ + 'body': body, + 'xmlns': this.name_space_attr_list, + 'diff': this.time_diff, + 'user': this.user, + 'pass': this.pass + }); + return soap; +}; + +/* ------------------------------------------------------------------ +* Method: getImagingSettings(params[, callback]) +* - params: +* - ConfigurationToken | String | required | a video token of the configuration +* +* { +* 'ConfigurationToken': 'Configuration1' +* } +* ---------------------------------------------------------------- */ +OnvifServiceImaging.prototype.getImagingSettings = function(params, callback) { + let promise = new Promise((resolve, reject) => { + let err_msg = ''; + if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { + reject(new Error('The value of "params" was invalid: ' + err_msg)); + return; + } + + if(err_msg = mOnvifSoap.isInvalidValue(params['ConfigurationToken'], 'string')) { + reject(new Error('The "ConfigurationToken" property was invalid: ' + err_msg)); + return; + } + + let soap_body = ''; + soap_body += ''; + soap_body += '' + params['ConfigurationToken'] + ''; + soap_body += ''; + let soap = this._createRequestSoap(soap_body); + + mOnvifSoap.requestCommand(this.oxaddr, 'GetImagingSettings', soap).then((result) => { + resolve(result); + }).catch((error) => { + reject(error); + }); + }); + if(callback) { + promise.then((result) => { + callback(null, result); + }).catch((error) => { + callback(error); + }); + } else { + return promise; + } +}; + +/* ------------------------------------------------------------------ +* Method: getImagingSettings(params[, callback]) +* - params: +* - ConfigurationToken | String | required | a video token of the configuration +* - ImagingSettings | object | required | an ImagingSettings object +* { +* 'ConfigurationToken': 'Configuration1' +* 'ImagingSettings': '{object}' +* } +* ---------------------------------------------------------------- */ +OnvifServiceImaging.prototype.setImagingSettings = function(params, callback) { + let promise = new Promise((resolve, reject) => { + let err_msg = ''; + if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { + reject(new Error('The value of "params" was invalid: ' + err_msg)); + return; + } + + if(err_msg = mOnvifSoap.isInvalidValue(params['ConfigurationToken'], 'string')) { + reject(new Error('The "ConfigurationToken" property was invalid: ' + err_msg)); + return; + } + if(err_msg = mOnvifSoap.isInvalidValue(params['ImagingSettings'], 'object')) { + reject(new Error('The "ImagingSettings" property was invalid: ' + err_msg)); + return; + } + + let soap_body = ''; + soap_body += ''; + soap_body += '' + params['ConfigurationToken'] + ''; + soap_body += '' + soap_body += '' + soap_body += '' + params.ImagingSettings.BacklightCompensation.Mode + '' + soap_body += '' + soap_body += '' + params.ImagingSettings.Brightness + '' + soap_body += '' + params.ImagingSettings.ColorSaturation + '' + soap_body += '' + params.ImagingSettings.Contrast + '' + soap_body += '' + soap_body += '' + params.ImagingSettings.Exposure.Mode + '' + soap_body += '' + params.ImagingSettings.Exposure.MinExposureTime + '' + soap_body += '' + params.ImagingSettings.Exposure.MaxExposureTime + '' + soap_body += '' + params.ImagingSettings.Exposure.MinGain + '' + soap_body += '' + params.ImagingSettings.Exposure.MaxGain + '' + soap_body += '' + soap_body += '' + params.ImagingSettings.IrCutFilter + '' + soap_body += '' + params.ImagingSettings.Sharpness + '' + soap_body += '' + soap_body += '' + params.ImagingSettings.WideDynamicRange.Mode + '' + soap_body += ''; + soap_body += '' + soap_body += '' + params.ImagingSettings.WhiteBalance.Mode + '' + soap_body += ''; + soap_body += 'true'; + soap_body += ''; + soap_body += ''; + let soap = this._createRequestSoap(soap_body); + + mOnvifSoap.requestCommand(this.oxaddr, 'SetImagingSettings', soap).then((result) => { + resolve(result); + }).catch((error) => { + reject(error); + }); + }); + if(callback) { + promise.then((result) => { + callback(null, result); + }).catch((error) => { + callback(error); + }); + } else { + return promise; + } +}; + + +module.exports = OnvifServiceImaging; \ No newline at end of file diff --git a/lib/modules/service-media.js b/lib/modules/service-media.js index de1a316..932c91a 100644 --- a/lib/modules/service-media.js +++ b/lib/modules/service-media.js @@ -222,16 +222,836 @@ OnvifServiceMedia.prototype.getVideoEncoderConfiguration = function(params, call } }; +/* ------------------------------------------------------------------ +* Method: getVideoEncoder2Configuration(params[, callback]) +* - params: +* - ConfigurationToken | String | required | a token of the configuration +* +* { +* 'ConfigurationToken': 'Configuration1' +* } +* ---------------------------------------------------------------- */ +OnvifServiceMedia.prototype.getVideoEncoder2Configuration = function(params, callback) { + let promise = new Promise((resolve, reject) => { + let err_msg = ''; + if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { + reject(new Error('The value of "params" was invalid: ' + err_msg)); + return; + } + + if(err_msg = mOnvifSoap.isInvalidValue(params['ConfigurationToken'], 'string')) { + reject(new Error('The "ConfigurationToken" property was invalid: ' + err_msg)); + return; + } + + let soap_body = ''; + soap_body += ''; + soap_body += '' + params['ConfigurationToken'] + ''; + soap_body += ''; + let soap = this._createRequestSoap(soap_body); + + mOnvifSoap.requestCommand(this.oxaddr, 'GetVideoEncoder2Configuration', soap).then((result) => { + resolve(result); + }).catch((error) => { + reject(error); + }); + }); + if(callback) { + promise.then((result) => { + callback(null, result); + }).catch((error) => { + callback(error); + }); + } else { + return promise; + } +}; +/* ------------------------------------------------------------------ +* Method: setVideoEncoderConfiguration(params[, callback]) +* - params: +* - ConfigurationToken | String | required | a token of the configuration +* - Configuration | Object | required | The new configuration object +* +* { +* 'ConfigurationToken': 'Configuration1' +* 'Configuration' : '{}' +* } +* ---------------------------------------------------------------- */ +OnvifServiceMedia.prototype.setVideoEncoderConfiguration = function(params, callback) { + let promise = new Promise((resolve, reject) => { + let err_msg = ''; + if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { + reject(new Error('The value of "params" was invalid: ' + err_msg)); + return; + } + + if(err_msg = mOnvifSoap.isInvalidValue(params['ConfigurationToken'], 'string')) { + reject(new Error('The "ConfigurationToken" property was invalid: ' + err_msg)); + return; + } + if(err_msg = mOnvifSoap.isInvalidValue(params['Configuration'], 'object')) { + reject(new Error('The "Configuration" property was invalid: ' + err_msg)); + return; + } + + let soap_body = ''; + try { + soap_body += ''; + soap_body += ''; + soap_body += '' + params.Configuration.Name + ''; + soap_body += '' + params.Configuration.UseCount + ''; // deprecated in Media 2 as read-only + soap_body += '' + params.Configuration.Encoding + ''; + soap_body += ''; + soap_body += '' + params.Configuration.Resolution.Width + ''; + soap_body += '' + params.Configuration.Resolution.Height + ''; + soap_body += ''; + soap_body += '' + params.Configuration.Quality + ''; + soap_body += ''; + soap_body += '' + params.Configuration.RateControl.FrameRateLimit + ''; + soap_body += '' + params.Configuration.RateControl.EncodingInterval + ''; + soap_body += '' + params.Configuration.RateControl.BitrateLimit + ''; + soap_body += ''; + soap_body += ''; + soap_body += '' + params.Configuration.H264.GovLength + ''; + soap_body += '' + params.Configuration.H264.H264Profile + ''; + soap_body += ''; + soap_body += ''; + soap_body += ''; + soap_body += ''+ params.Configuration.Multicast.Address.Type + ''; + soap_body += '' + params.Configuration.Multicast.Address.IPv4Address + ''; + soap_body += ''; + soap_body += '' + params.Configuration.Multicast.Port + ''; + soap_body += '' + params.Configuration.Multicast.TTL + ''; + soap_body += '' + params.Configuration.Multicast.AutoStart + ''; + soap_body += ''; + soap_body += '' + params.Configuration.SessionTimeout + ''; + soap_body += ''; + soap_body += 'true'; + soap_body += ''; + } catch (err){ + reject(new Error(`Missing required configuration parameters ${JSON.stringify(err,null,4)}`)); + return; + } + let soap = this._createRequestSoap(soap_body); + + mOnvifSoap.requestCommand(this.oxaddr, 'SetVideoEncoderConfiguration', soap).then((result) => { + resolve(result); + }).catch((error) => { + reject(error); + }); + }); + if(callback) { + promise.then((result) => { + callback(null, result); + }).catch((error) => { + callback(error); + }); + } else { + return promise; + } +}; + + +/* ------------------------------------------------------------------ +* Method: removeVideoEncoderConfiguration(params[, callback]) +* - params: +* - ProfileToken | Object | required | a token of the profile +* +* { +* 'ProfileToken' : 'Profile_1' +* } +* ---------------------------------------------------------------- */ +OnvifServiceMedia.prototype.removeVideoEncoderConfiguration = function(params, callback) { + let promise = new Promise((resolve, reject) => { + let err_msg = ''; + + if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { + reject(new Error('The value of "params" was invalid: ' + err_msg)); + return; + } + if(err_msg = mOnvifSoap.isInvalidValue(params['ProfileToken'], 'string')) { + reject(new Error('The "ProfileToken" property was invalid: ' + err_msg)); + return; + } + + let soap_body = ''; + try { + soap_body += ''; + soap_body += '' + params.ProfileToken + ''; + soap_body += ''; + } catch (err){ + reject(new Error('Missing required configuration parammeters')); + return; + } + let soap = this._createRequestSoap(soap_body); + + mOnvifSoap.requestCommand(this.oxaddr, 'RemoveVideoEncoderConfiguration', soap).then((result) => { + resolve(result); + }).catch((error) => { + reject(error); + }); + }); + if(callback) { + promise.then((result) => { + callback(null, result); + }).catch((error) => { + callback(error); + }); + } else { + return promise; + } +}; + +/* ------------------------------------------------------------------ +* Method: addVideoEncoderConfiguration(params[, callback]) +* - params: +* - ConfigurationToken | String | required | a token of the configuration +* - ProfileToken | String | required | a token of the video encoder configuration +* +* { +* 'ConfigurationToken': 'Configuration1' +* 'ProfileToken' : 'Encoder1' +* } +* ---------------------------------------------------------------- */ +OnvifServiceMedia.prototype.addVideoEncoderConfiguration = function(params, callback) { + let promise = new Promise((resolve, reject) => { + let err_msg = ''; + if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { + reject(new Error('The value of "params" was invalid: ' + err_msg)); + return; + } + + if(err_msg = mOnvifSoap.isInvalidValue(params['ConfigurationToken'], 'string')) { + reject(new Error('The "ConfigurationToken" property was invalid: ' + err_msg)); + return; + } + if(err_msg = mOnvifSoap.isInvalidValue(params['ProfileToken'], 'string')) { + reject(new Error('The "ProfileToken" property was invalid: ' + err_msg)); + return; + } + + let soap_body = ''; + try { + soap_body += ''; + soap_body += '' + params['ConfigurationToken'] + ''; + soap_body += '' + params['ProfileToken'] + ''; + soap_body += ''; + } catch (err){ + reject(new Error('Missing required configuration parammeters')); + return; + } + let soap = this._createRequestSoap(soap_body); + + mOnvifSoap.requestCommand(this.oxaddr, 'AddVideoEncoderConfiguration', soap).then((result) => { + resolve(result); + }).catch((error) => { + reject(error); + }); + }); + if(callback) { + promise.then((result) => { + callback(null, result); + }).catch((error) => { + callback(error); + }); + } else { + return promise; + } +}; +/* ------------------------------------------------------------------ +* Method: addVideoSourceConfiguration(params[, callback]) +* - params: +* - ConfigurationToken | String | required | a token of the configuration +* - ProfileToken | String | required | The associate profile token +* +* { +* 'ConfigurationToken': 'Configuration1' +* 'ProfileToken' : 'Profile_1' +* } +* ---------------------------------------------------------------- */ +OnvifServiceMedia.prototype.addVideoSourceConfiguration = function(params, callback) { + let promise = new Promise((resolve, reject) => { + let err_msg = ''; + if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { + reject(new Error('The value of "params" was invalid: ' + err_msg)); + return; + } + + if(err_msg = mOnvifSoap.isInvalidValue(params['ConfigurationToken'], 'string')) { + reject(new Error('The "ConfigurationToken" property was invalid: ' + err_msg)); + return; + } + if(err_msg = mOnvifSoap.isInvalidValue(params['ProfileToken'], 'string')) { + reject(new Error('The "ProfileToken" property was invalid: ' + err_msg)); + return; + } + + let soap_body = ''; + try { + soap_body += ''; + soap_body += '' + params.ProfileToken + ''; + soap_body += '' + params.ConfigurationToken + ''; + soap_body += ''; + } catch (err){ + reject(new Error('Missing required configuration parammeters')); + return; + } + let soap = this._createRequestSoap(soap_body); + + mOnvifSoap.requestCommand(this.oxaddr, 'AddVideoSourceConfiguration', soap).then((result) => { + resolve(result); + }).catch((error) => { + reject(error); + }); + }); + if(callback) { + promise.then((result) => { + callback(null, result); + }).catch((error) => { + callback(error); + }); + } else { + return promise; + } +}; + +/* ------------------------------------------------------------------ +* Method: removeVideoSourceConfiguration(params[, callback]) +* - params: +* - ProfileToken | String | required | The associate profile token +* +* { +* 'ProfileToken' : 'Profile_1' +* } +* ---------------------------------------------------------------- */ +OnvifServiceMedia.prototype.removeVideoSourceConfiguration = function(params, callback) { + let promise = new Promise((resolve, reject) => { + let err_msg = ''; + if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { + reject(new Error('The value of "params" was invalid: ' + err_msg)); + return; + } + + if(err_msg = mOnvifSoap.isInvalidValue(params['ProfileToken'], 'string')) { + reject(new Error('The "ProfileToken" property was invalid: ' + err_msg)); + return; + } + + let soap_body = ''; + try { + soap_body += ''; + soap_body += '' + params.ProfileToken + ''; + soap_body += ''; + } catch (err){ + reject(new Error('Missing required configuration parammeters')); + return; + } + let soap = this._createRequestSoap(soap_body); + + mOnvifSoap.requestCommand(this.oxaddr, 'RemoveVideoSourceConfiguration', soap).then((result) => { + resolve(result); + }).catch((error) => { + reject(error); + }); + }); + if(callback) { + promise.then((result) => { + callback(null, result); + }).catch((error) => { + callback(error); + }); + } else { + return promise; + } +}; + /* ------------------------------------------------------------------ * Method: getCompatibleVideoEncoderConfigurations(params[, callback]) * - params: -* - ProfileToken | String | required | a token of the profile +* - ProfileToken | String | required | a token of the profile +* +* { +* 'ProfileToken': 'Profile1' +* } +* ---------------------------------------------------------------- */ +OnvifServiceMedia.prototype.getCompatibleVideoEncoderConfigurations = function(params, callback) { + let promise = new Promise((resolve, reject) => { + let err_msg = ''; + if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { + reject(new Error('The value of "params" was invalid: ' + err_msg)); + return; + } + + if(err_msg = mOnvifSoap.isInvalidValue(params['ProfileToken'], 'string')) { + reject(new Error('The "ProfileToken" property was invalid: ' + err_msg)); + return; + } + + let soap_body = ''; + soap_body += ''; + soap_body += '' + params['ProfileToken'] + ''; + soap_body += ''; + let soap = this._createRequestSoap(soap_body); + + mOnvifSoap.requestCommand(this.oxaddr, 'GetCompatibleVideoEncoderConfigurations', soap).then((result) => { + resolve(result); + }).catch((error) => { + reject(error); + }); + }); + if(callback) { + promise.then((result) => { + callback(null, result); + }).catch((error) => { + callback(error); + }); + } else { + return promise; + } +}; + +/* ------------------------------------------------------------------ +* Method: getVideoEncoderConfigurationOptions(params[, callback]) +* - params: +* - ProfileToken | String | optional | a token of the profile +* - ConfigurationToken | String | optional | a token of the configuration +* +* { +* 'ProfileToken': 'Profile1' +* } +* ---------------------------------------------------------------- */ +OnvifServiceMedia.prototype.getVideoEncoderConfigurationOptions = function(params, callback) { + let promise = new Promise((resolve, reject) => { + let err_msg = ''; + if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { + reject(new Error('The value of "params" was invalid: ' + err_msg)); + return; + } + + if('ProfileToken' in params) { + if(err_msg = mOnvifSoap.isInvalidValue(params['ProfileToken'], 'string')) { + reject(new Error('The "ProfileToken" property was invalid: ' + err_msg)); + return; + } + } + + if('ConfigurationToken' in params) { + if(err_msg = mOnvifSoap.isInvalidValue(params['ConfigurationToken'], 'string')) { + reject(new Error('The "ConfigurationToken" property was invalid: ' + err_msg)); + return; + } + } + + let soap_body = ''; + soap_body += ''; + if(params['ProfileToken']) { + soap_body += '' + params['ProfileToken'] + ''; + } + if(params['ConfigurationToken']) { + soap_body += '' + params['ConfigurationToken'] + ''; + } + soap_body += ''; + let soap = this._createRequestSoap(soap_body); + + mOnvifSoap.requestCommand(this.oxaddr, 'GetVideoEncoderConfigurationOptions', soap).then((result) => { + resolve(result); + }).catch((error) => { + reject(error); + }); + }); + if(callback) { + promise.then((result) => { + callback(null, result); + }).catch((error) => { + callback(error); + }); + } else { + return promise; + } +}; + +/* ------------------------------------------------------------------ +* Method: getVideoEncoder2ConfigurationOptions(params[, callback]) +* - params: +* - ProfileToken | String | optional | a token of the profile +* - ConfigurationToken | String | optional | a token of the configuration +* +* { +* 'ProfileToken': 'Profile1' +* } +* ---------------------------------------------------------------- */ +OnvifServiceMedia.prototype.getVideoEncoder2ConfigurationOptions = function(params, callback) { + let promise = new Promise((resolve, reject) => { + let err_msg = ''; + if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { + reject(new Error('The value of "params" was invalid: ' + err_msg)); + return; + } + + if('ProfileToken' in params) { + if(err_msg = mOnvifSoap.isInvalidValue(params['ProfileToken'], 'string')) { + reject(new Error('The "ProfileToken" property was invalid: ' + err_msg)); + return; + } + } + + if('ConfigurationToken' in params) { + if(err_msg = mOnvifSoap.isInvalidValue(params['ConfigurationToken'], 'string')) { + reject(new Error('The "ConfigurationToken" property was invalid: ' + err_msg)); + return; + } + } + + let soap_body = ''; + soap_body += ''; + if(params['ProfileToken']) { + soap_body += '' + params['ProfileToken'] + ''; + } + if(params['ConfigurationToken']) { + soap_body += '' + params['ConfigurationToken'] + ''; + } + soap_body += ''; + let soap = this._createRequestSoap(soap_body); + + mOnvifSoap.requestCommand(this.oxaddr, 'GetVideoEncoder2ConfigurationOptions', soap).then((result) => { + resolve(result); + }).catch((error) => { + reject(error); + }); + }); + if(callback) { + promise.then((result) => { + callback(null, result); + }).catch((error) => { + callback(error); + }); + } else { + return promise; + } +}; + +/* ------------------------------------------------------------------ +* Method: getGuaranteedNumberOfVideoEncoderInstances(params[, callback]) +* - params: +* - ConfigurationToken | String | required | a token of the configuration +* +* { +* 'ConfigurationToken': 'Configuration1' +* } +* ---------------------------------------------------------------- */ +OnvifServiceMedia.prototype.getGuaranteedNumberOfVideoEncoderInstances = function(params, callback) { + let promise = new Promise((resolve, reject) => { + let err_msg = ''; + if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { + reject(new Error('The value of "params" was invalid: ' + err_msg)); + return; + } + + if(err_msg = mOnvifSoap.isInvalidValue(params['ConfigurationToken'], 'string')) { + reject(new Error('The "ConfigurationToken" property was invalid: ' + err_msg)); + return; + } + + let soap_body = ''; + soap_body += ''; + soap_body += '' + params['ConfigurationToken'] + ''; + soap_body += ''; + let soap = this._createRequestSoap(soap_body); + + mOnvifSoap.requestCommand(this.oxaddr, 'GetGuaranteedNumberOfVideoEncoderInstances', soap).then((result) => { + resolve(result); + }).catch((error) => { + reject(error); + }); + }); + if(callback) { + promise.then((result) => { + callback(null, result); + }).catch((error) => { + callback(error); + }); + } else { + return promise; + } +}; + +/* ------------------------------------------------------------------ +* Method: getProfiles([callback]) +* ---------------------------------------------------------------- */ +OnvifServiceMedia.prototype.getProfiles = function(callback) { + let promise = new Promise((resolve, reject) => { + let soap_body = ''; + let soap = this._createRequestSoap(soap_body); + mOnvifSoap.requestCommand(this.oxaddr, 'GetProfiles', soap).then((result) => { + resolve(result); + }).catch((error) => { + reject(error); + }); + }); + if(callback) { + promise.then((result) => { + callback(null, result); + }).catch((error) => { + callback(error); + }); + } else { + return promise; + } +}; + +/* ------------------------------------------------------------------ +* Method: getProfile(params[, callback]) +* - params: +* - ProfileToken | required | a token of the profile +* +* { +* 'ProfileToken': 'Profile1' +* } +* ---------------------------------------------------------------- */ +OnvifServiceMedia.prototype.getProfile = function(params, callback) { + let promise = new Promise((resolve, reject) => { + let err_msg = ''; + if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { + reject(new Error('The value of "params" was invalid: ' + err_msg)); + return; + } + + if(err_msg = mOnvifSoap.isInvalidValue(params['ProfileToken'], 'string')) { + reject(new Error('The "ProfileToken" property was invalid: ' + err_msg)); + return; + } + + let soap_body = ''; + soap_body += ''; + soap_body += '' + params['ProfileToken'] + ''; + soap_body += ''; + let soap = this._createRequestSoap(soap_body); + + mOnvifSoap.requestCommand(this.oxaddr, 'GetProfile', soap).then((result) => { + resolve(result); + }).catch((error) => { + reject(error); + }); + }); + if(callback) { + promise.then((result) => { + callback(null, result); + }).catch((error) => { + callback(error); + }); + } else { + return promise; + } +}; + +/* ------------------------------------------------------------------ +* Method: createProfile(params[, callback]) +* - params: +* - Name | String | required | a name of the profile +* - Token | String | optional | a token of the profile +* +* { +* 'Name: 'TestProfile1' +* } +* ---------------------------------------------------------------- */ +OnvifServiceMedia.prototype.createProfile = function(params, callback) { + let promise = new Promise((resolve, reject) => { + let err_msg = ''; + if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { + reject(new Error('The value of "params" was invalid: ' + err_msg)); + return; + } + + if(err_msg = mOnvifSoap.isInvalidValue(params['Name'], 'string')) { + reject(new Error('The "Name" property was invalid: ' + err_msg)); + return; + } + + if('Token' in params) { + if(err_msg = mOnvifSoap.isInvalidValue(params['Token'], 'string')) { + reject(new Error('The "Token" property was invalid: ' + err_msg)); + return; + } + } + + let soap_body = ''; + soap_body += ''; + soap_body += '' + params['Name'] + ''; + if('Token' in params) { + soap_body += '' + params['Token'] + ''; + } + soap_body += ''; + let soap = this._createRequestSoap(soap_body); + + mOnvifSoap.requestCommand(this.oxaddr, 'CreateProfile', soap).then((result) => { + resolve(result); + }).catch((error) => { + reject(error); + }); + }); + if(callback) { + promise.then((result) => { + callback(null, result); + }).catch((error) => { + callback(error); + }); + } else { + return promise; + } +}; + +/* ------------------------------------------------------------------ +* Method: deleteProfile(params[, callback]) +* - params: +* - ProfileToken | String | required | +* +* { +* 'ProfileToken: 'TestProfile1' +* } +* ---------------------------------------------------------------- */ +OnvifServiceMedia.prototype.deleteProfile = function(params, callback) { + let promise = new Promise((resolve, reject) => { + let err_msg = ''; + if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { + reject(new Error('The value of "params" was invalid: ' + err_msg)); + return; + } + + if(err_msg = mOnvifSoap.isInvalidValue(params['ProfileToken'], 'string')) { + reject(new Error('The "ProfileToken" property was invalid: ' + err_msg)); + return; + } + + let soap_body = ''; + soap_body += ''; + soap_body += '' + params['ProfileToken'] + ''; + soap_body += ''; + let soap = this._createRequestSoap(soap_body); + + mOnvifSoap.requestCommand(this.oxaddr, 'DeleteProfile', soap).then((result) => { + resolve(result); + }).catch((error) => { + reject(error); + }); + }); + if(callback) { + promise.then((result) => { + callback(null, result); + }).catch((error) => { + callback(error); + }); + } else { + return promise; + } +}; + +/* ------------------------------------------------------------------ +* Method: getVideoSources([callback]) +* ---------------------------------------------------------------- */ +OnvifServiceMedia.prototype.getVideoSources = function(callback) { + let promise = new Promise((resolve, reject) => { + let soap_body = ''; + let soap = this._createRequestSoap(soap_body); + mOnvifSoap.requestCommand(this.oxaddr, 'GetVideoSources', soap).then((result) => { + resolve(result); + }).catch((error) => { + reject(error); + }); + }); + if(callback) { + promise.then((result) => { + callback(null, result); + }).catch((error) => { + callback(error); + }); + } else { + return promise; + } +}; + +/* ------------------------------------------------------------------ +* Method: getVideoSourceConfiguration(params[, callback]) +* - params: +* - ConfigurationToken | String | required | +* +* { +* 'ConfigurationToken': 'Profile1' +* } +* ---------------------------------------------------------------- */ +OnvifServiceMedia.prototype.getVideoSourceConfiguration = function(params, callback) { + let promise = new Promise((resolve, reject) => { + let err_msg = ''; + if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { + reject(new Error('The value of "params" was invalid: ' + err_msg)); + return; + } + + if(err_msg = mOnvifSoap.isInvalidValue(params['ConfigurationToken'], 'string')) { + reject(new Error('The "ConfigurationToken" property was invalid: ' + err_msg)); + return; + } + + let soap_body = ''; + soap_body += ''; + soap_body += '' + params['ConfigurationToken'] + ''; + soap_body += ''; + let soap = this._createRequestSoap(soap_body); + + mOnvifSoap.requestCommand(this.oxaddr, 'GetVideoSourceConfiguration', soap).then((result) => { + resolve(result); + }).catch((error) => { + reject(error); + }); + }); + if(callback) { + promise.then((result) => { + callback(null, result); + }).catch((error) => { + callback(error); + }); + } else { + return promise; + } +}; + +/* ------------------------------------------------------------------ +* Method: getVideoSourceConfigurations([callback]) +* ---------------------------------------------------------------- */ +OnvifServiceMedia.prototype.getVideoSourceConfigurations = function(callback) { + let promise = new Promise((resolve, reject) => { + let soap_body = ''; + let soap = this._createRequestSoap(soap_body); + mOnvifSoap.requestCommand(this.oxaddr, 'GetVideoSourceConfigurations', soap).then((result) => { + resolve(result); + }).catch((error) => { + reject(error); + }); + }); + if(callback) { + promise.then((result) => { + callback(null, result); + }).catch((error) => { + callback(error); + }); + } else { + return promise; + } +}; + +/* ------------------------------------------------------------------ +* Method: addVideoSourceConfiguration(params[, callback]) +* - params: +* - ProfileToken | String | required | a token of the Profile +* - ConfigurationToken | String | required | * * { * 'ProfileToken': 'Profile1' +* 'ConfigurationToken': 'Profile1' * } +* +* No device I own does not support this command * ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.getCompatibleVideoEncoderConfigurations = function(params, callback) { +OnvifServiceMedia.prototype.addVideoSourceConfiguration = function(params, callback) { let promise = new Promise((resolve, reject) => { let err_msg = ''; if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { @@ -244,13 +1064,19 @@ OnvifServiceMedia.prototype.getCompatibleVideoEncoderConfigurations = function(p return; } + if(err_msg = mOnvifSoap.isInvalidValue(params['ConfigurationToken'], 'string')) { + reject(new Error('The "ConfigurationToken" property was invalid: ' + err_msg)); + return; + } + let soap_body = ''; - soap_body += ''; + soap_body += ''; soap_body += '' + params['ProfileToken'] + ''; - soap_body += ''; + soap_body += '' + params['ConfigurationToken'] + ''; + soap_body += ''; let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'GetCompatibleVideoEncoderConfigurations', soap).then((result) => { + mOnvifSoap.requestCommand(this.oxaddr, 'AddVideoSourceConfiguration', soap).then((result) => { resolve(result); }).catch((error) => { reject(error); @@ -268,16 +1094,62 @@ OnvifServiceMedia.prototype.getCompatibleVideoEncoderConfigurations = function(p }; /* ------------------------------------------------------------------ -* Method: getVideoEncoderConfigurationOptions(params[, callback]) +* Method: getCompatibleVideoSourceConfigurations(params[, callback]) * - params: -* - ProfileToken | String | optional | a token of the profile -* - ConfigurationToken | String | optional | a token of the configuration +* - ProfileToken | String | required | a token of the targeted PTZ node * * { * 'ProfileToken': 'Profile1' * } * ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.getVideoEncoderConfigurationOptions = function(params, callback) { +OnvifServiceMedia.prototype.getCompatibleVideoSourceConfigurations = function(params, callback) { + let promise = new Promise((resolve, reject) => { + let err_msg = ''; + if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { + reject(new Error('The value of "params" was invalid: ' + err_msg)); + return; + } + + if(err_msg = mOnvifSoap.isInvalidValue(params['ProfileToken'], 'string')) { + reject(new Error('The "ProfileToken" property was invalid: ' + err_msg)); + return; + } + + let soap_body = ''; + soap_body += ''; + soap_body += '' + params['ProfileToken'] + ''; + soap_body += ''; + let soap = this._createRequestSoap(soap_body); + + mOnvifSoap.requestCommand(this.oxaddr, 'GetCompatibleVideoSourceConfigurations', soap).then((result) => { + resolve(result); + }).catch((error) => { + reject(error); + }); + }); + if(callback) { + promise.then((result) => { + callback(null, result); + }).catch((error) => { + callback(error); + }); + } else { + return promise; + } +}; + +/* ------------------------------------------------------------------ +* Method: getVideoSourceConfigurationOptions(params[, callback]) +* - params: +* - ProfileToken | optional | a token of the Profile +* - ConfigurationToken | optional | a token of the configuration +* +* { +* 'ProfileToken': 'Profile1' +* 'ConfigurationToken': 'Conf1' +* } +* ---------------------------------------------------------------- */ +OnvifServiceMedia.prototype.getVideoSourceConfigurationOptions = function(params, callback) { let promise = new Promise((resolve, reject) => { let err_msg = ''; if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { @@ -300,17 +1172,17 @@ OnvifServiceMedia.prototype.getVideoEncoderConfigurationOptions = function(param } let soap_body = ''; - soap_body += ''; - if(params['ProfileToken']) { - soap_body += '' + params['ProfileToken'] + ''; + soap_body += ''; + if('ProfileToken' in params) { + soap_body += '' + params['ProfileToken'] + ''; } - if(params['ConfigurationToken']) { - soap_body += '' + params['ConfigurationToken'] + ''; + if('ConfigurationToken' in params) { + soap_body += '' + params['ConfigurationToken'] + ''; } - soap_body += ''; + soap_body += ''; let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'GetVideoEncoderConfigurationOptions', soap).then((result) => { + mOnvifSoap.requestCommand(this.oxaddr, 'GetVideoSourceConfigurationOptions', soap).then((result) => { resolve(result); }).catch((error) => { reject(error); @@ -328,15 +1200,15 @@ OnvifServiceMedia.prototype.getVideoEncoderConfigurationOptions = function(param }; /* ------------------------------------------------------------------ -* Method: getGuaranteedNumberOfVideoEncoderInstances(params[, callback]) +* Method: getMetadataConfiguration(params[, callback]) * - params: -* - ConfigurationToken | String | required | a token of the configuration +* - ConfigurationToken | required | * * { -* 'ConfigurationToken': 'Configuration1' +* 'ConfigurationToken': 'Conf1' * } * ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.getGuaranteedNumberOfVideoEncoderInstances = function(params, callback) { +OnvifServiceMedia.prototype.getMetadataConfiguration = function(params, callback) { let promise = new Promise((resolve, reject) => { let err_msg = ''; if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { @@ -350,12 +1222,12 @@ OnvifServiceMedia.prototype.getGuaranteedNumberOfVideoEncoderInstances = functio } let soap_body = ''; - soap_body += ''; + soap_body += ''; soap_body += '' + params['ConfigurationToken'] + ''; - soap_body += ''; + soap_body += ''; let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'GetGuaranteedNumberOfVideoEncoderInstances', soap).then((result) => { + mOnvifSoap.requestCommand(this.oxaddr, 'GetMetadataConfiguration', soap).then((result) => { resolve(result); }).catch((error) => { reject(error); @@ -373,13 +1245,13 @@ OnvifServiceMedia.prototype.getGuaranteedNumberOfVideoEncoderInstances = functio }; /* ------------------------------------------------------------------ -* Method: getProfiles([callback]) +* Method: getMetadataConfigurations([callback]) * ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.getProfiles = function(callback) { +OnvifServiceMedia.prototype.getMetadataConfigurations = function(callback) { let promise = new Promise((resolve, reject) => { - let soap_body = ''; + let soap_body = ''; let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'GetProfiles', soap).then((result) => { + mOnvifSoap.requestCommand(this.oxaddr, 'GetMetadataConfigurations', soap).then((result) => { resolve(result); }).catch((error) => { reject(error); @@ -397,15 +1269,19 @@ OnvifServiceMedia.prototype.getProfiles = function(callback) { }; /* ------------------------------------------------------------------ -* Method: getProfile(params[, callback]) +* Method: addMetadataConfiguration(params[, callback]) * - params: -* - ProfileToken | required | a token of the profile +* - ProfileToken | String | required | a token of the Profile +* - ConfigurationToken | String | required | * * { * 'ProfileToken': 'Profile1' +* 'ConfigurationToken': 'Conf1' * } +* +* No device I own does not support this command * ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.getProfile = function(params, callback) { +OnvifServiceMedia.prototype.addMetadataConfiguration = function(params, callback) { let promise = new Promise((resolve, reject) => { let err_msg = ''; if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { @@ -418,13 +1294,19 @@ OnvifServiceMedia.prototype.getProfile = function(params, callback) { return; } + if(err_msg = mOnvifSoap.isInvalidValue(params['ConfigurationToken'], 'string')) { + reject(new Error('The "ConfigurationToken" property was invalid: ' + err_msg)); + return; + } + let soap_body = ''; - soap_body += ''; + soap_body += ''; soap_body += '' + params['ProfileToken'] + ''; - soap_body += ''; + soap_body += '' + params['ConfigurationToken'] + ''; + soap_body += ''; let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'GetProfile', soap).then((result) => { + mOnvifSoap.requestCommand(this.oxaddr, 'AddMetadataConfiguration', soap).then((result) => { resolve(result); }).catch((error) => { reject(error); @@ -442,16 +1324,15 @@ OnvifServiceMedia.prototype.getProfile = function(params, callback) { }; /* ------------------------------------------------------------------ -* Method: createProfile(params[, callback]) +* Method: getCompatibleMetadataConfigurations(params[, callback]) * - params: -* - Name | String | required | a name of the profile -* - Token | String | optional | a token of the profile +* - ProfileToken | String | required | a token of the Profile * * { -* 'Name: 'TestProfile1' +* 'ProfileToken': 'Profile1' * } * ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.createProfile = function(params, callback) { +OnvifServiceMedia.prototype.getCompatibleMetadataConfigurations = function(params, callback) { let promise = new Promise((resolve, reject) => { let err_msg = ''; if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { @@ -459,28 +1340,18 @@ OnvifServiceMedia.prototype.createProfile = function(params, callback) { return; } - if(err_msg = mOnvifSoap.isInvalidValue(params['Name'], 'string')) { - reject(new Error('The "Name" property was invalid: ' + err_msg)); + if(err_msg = mOnvifSoap.isInvalidValue(params['ProfileToken'], 'string')) { + reject(new Error('The "ProfileToken" property was invalid: ' + err_msg)); return; } - if('Token' in params) { - if(err_msg = mOnvifSoap.isInvalidValue(params['Token'], 'string')) { - reject(new Error('The "Token" property was invalid: ' + err_msg)); - return; - } - } - let soap_body = ''; - soap_body += ''; - soap_body += '' + params['Name'] + ''; - if('Token' in params) { - soap_body += '' + params['Token'] + ''; - } - soap_body += ''; + soap_body += ''; + soap_body += '' + params['ProfileToken'] + ''; + soap_body += ''; let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'CreateProfile', soap).then((result) => { + mOnvifSoap.requestCommand(this.oxaddr, 'GetCompatibleMetadataConfigurations', soap).then((result) => { resolve(result); }).catch((error) => { reject(error); @@ -498,15 +1369,17 @@ OnvifServiceMedia.prototype.createProfile = function(params, callback) { }; /* ------------------------------------------------------------------ -* Method: deleteProfile(params[, callback]) +* Method: getMetadataConfigurationOptions(params[, callback]) * - params: -* - ProfileToken | String | required | +* - ProfileToken | String | optional | a token of the Profile +* - ConfigurationToken | String | optional | * * { -* 'ProfileToken: 'TestProfile1' +* 'ProfileToken': 'Profile1' +* 'ConfigurationToken': 'Conf1' * } * ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.deleteProfile = function(params, callback) { +OnvifServiceMedia.prototype.getMetadataConfigurationOptions = function(params, callback) { let promise = new Promise((resolve, reject) => { let err_msg = ''; if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { @@ -514,18 +1387,32 @@ OnvifServiceMedia.prototype.deleteProfile = function(params, callback) { return; } - if(err_msg = mOnvifSoap.isInvalidValue(params['ProfileToken'], 'string')) { - reject(new Error('The "ProfileToken" property was invalid: ' + err_msg)); - return; + if('ProfileToken' in params) { + if(err_msg = mOnvifSoap.isInvalidValue(params['ProfileToken'], 'string')) { + reject(new Error('The "ProfileToken" property was invalid: ' + err_msg)); + return; + } + } + + if('ConfigurationToken' in params) { + if(err_msg = mOnvifSoap.isInvalidValue(params['ConfigurationToken'], 'string')) { + reject(new Error('The "ConfigurationToken" property was invalid: ' + err_msg)); + return; + } } let soap_body = ''; - soap_body += ''; - soap_body += '' + params['ProfileToken'] + ''; - soap_body += ''; + soap_body += ''; + if('ProfileToken' in params) { + soap_body += '' + params['ProfileToken'] + ''; + } + if('ConfigurationToken' in params) { + soap_body += '' + params['ConfigurationToken'] + ''; + } + soap_body += ''; let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'DeleteProfile', soap).then((result) => { + mOnvifSoap.requestCommand(this.oxaddr, 'GetMetadataConfigurationOptions', soap).then((result) => { resolve(result); }).catch((error) => { reject(error); @@ -543,13 +1430,13 @@ OnvifServiceMedia.prototype.deleteProfile = function(params, callback) { }; /* ------------------------------------------------------------------ -* Method: getVideoSources([callback]) +* Method: getAudioSources([callback]) * ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.getVideoSources = function(callback) { +OnvifServiceMedia.prototype.getAudioSources = function(callback) { let promise = new Promise((resolve, reject) => { - let soap_body = ''; + let soap_body = ''; let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'GetVideoSources', soap).then((result) => { + mOnvifSoap.requestCommand(this.oxaddr, 'GetAudioSources', soap).then((result) => { resolve(result); }).catch((error) => { reject(error); @@ -567,15 +1454,15 @@ OnvifServiceMedia.prototype.getVideoSources = function(callback) { }; /* ------------------------------------------------------------------ -* Method: getVideoSourceConfiguration(params[, callback]) +* Method: getAudioSourceConfiguration(params[, callback]) * - params: * - ConfigurationToken | String | required | * * { -* 'ConfigurationToken': 'Profile1' +* 'ConfigurationToken': 'Conf1' * } * ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.getVideoSourceConfiguration = function(params, callback) { +OnvifServiceMedia.prototype.getAudioSourceConfiguration = function(params, callback) { let promise = new Promise((resolve, reject) => { let err_msg = ''; if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { @@ -589,12 +1476,12 @@ OnvifServiceMedia.prototype.getVideoSourceConfiguration = function(params, callb } let soap_body = ''; - soap_body += ''; - soap_body += '' + params['ConfigurationToken'] + ''; - soap_body += ''; + soap_body += ''; + soap_body += '' + params['ConfigurationToken'] + ''; + soap_body += ''; let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'GetVideoSourceConfiguration', soap).then((result) => { + mOnvifSoap.requestCommand(this.oxaddr, 'GetAudioSourceConfiguration', soap).then((result) => { resolve(result); }).catch((error) => { reject(error); @@ -612,13 +1499,13 @@ OnvifServiceMedia.prototype.getVideoSourceConfiguration = function(params, callb }; /* ------------------------------------------------------------------ -* Method: getVideoSourceConfigurations([callback]) +* Method: getAudioSourceConfigurations([callback]) * ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.getVideoSourceConfigurations = function(callback) { +OnvifServiceMedia.prototype.getAudioSourceConfigurations = function(callback) { let promise = new Promise((resolve, reject) => { - let soap_body = ''; + let soap_body = ''; let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'GetVideoSourceConfigurations', soap).then((result) => { + mOnvifSoap.requestCommand(this.oxaddr, 'GetAudioSourceConfigurations', soap).then((result) => { resolve(result); }).catch((error) => { reject(error); @@ -636,19 +1523,19 @@ OnvifServiceMedia.prototype.getVideoSourceConfigurations = function(callback) { }; /* ------------------------------------------------------------------ -* Method: addVideoSourceConfiguration(params[, callback]) +* Method: addAudioSourceConfiguration(params[, callback]) * - params: * - ProfileToken | String | required | a token of the Profile -* - ConfigurationToken | String | required | +* - ConfigurationToken | String | required | * * { -* 'ProfileToken': 'Profile1' -* 'ConfigurationToken': 'Profile1' +* 'ProfileToken': 'Profile1', +* 'ConfigurationToken': 'Conf1' * } * * No device I own does not support this command * ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.addVideoSourceConfiguration = function(params, callback) { +OnvifServiceMedia.prototype.addAudioSourceConfiguration = function(params, callback) { let promise = new Promise((resolve, reject) => { let err_msg = ''; if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { @@ -667,13 +1554,13 @@ OnvifServiceMedia.prototype.addVideoSourceConfiguration = function(params, callb } let soap_body = ''; - soap_body += ''; - soap_body += '' + params['ProfileToken'] + ''; - soap_body += '' + params['ConfigurationToken'] + ''; - soap_body += ''; + soap_body += ''; + soap_body += '' + params['ProfileToken'] + ''; + soap_body += '' + params['ConfigurationToken'] + ''; + soap_body += ''; let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'AddVideoSourceConfiguration', soap).then((result) => { + mOnvifSoap.requestCommand(this.oxaddr, 'AddAudioSourceConfiguration', soap).then((result) => { resolve(result); }).catch((error) => { reject(error); @@ -691,15 +1578,65 @@ OnvifServiceMedia.prototype.addVideoSourceConfiguration = function(params, callb }; /* ------------------------------------------------------------------ -* Method: getCompatibleVideoSourceConfigurations(params[, callback]) +* Method: removeAudioEncoderConfiguration(params[, callback]) * - params: -* - ProfileToken | String | required | a token of the targeted PTZ node +* - ProfileToken | Object | required | a token of the profile +* +* { +* 'ProfileToken' : 'Profile_1' +* } +* ---------------------------------------------------------------- */ +OnvifServiceMedia.prototype.removeAudioEncoderConfiguration = function(params, callback) { + let promise = new Promise((resolve, reject) => { + let err_msg = ''; + + if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { + reject(new Error('The value of "params" was invalid: ' + err_msg)); + return; + } + if(err_msg = mOnvifSoap.isInvalidValue(params['ProfileToken'], 'string')) { + reject(new Error('The "ProfileToken" property was invalid: ' + err_msg)); + return; + } + + let soap_body = ''; + try { + soap_body += ''; + soap_body += '' + params.ProfileToken + ''; + soap_body += ''; + } catch (err){ + reject(new Error('Missing required configuration parammeters')); + return; + } + let soap = this._createRequestSoap(soap_body); + + mOnvifSoap.requestCommand(this.oxaddr, 'RemoveAudioEncoderConfiguration', soap).then((result) => { + resolve(result); + }).catch((error) => { + reject(error); + }); + }); + if(callback) { + promise.then((result) => { + callback(null, result); + }).catch((error) => { + callback(error); + }); + } else { + return promise; + } +}; + +/* ------------------------------------------------------------------ +* Method: getCompatibleAudioSourceConfigurations(params[, callback]) +* - params: +* - ProfileToken | String | required | a token of the profile * * { * 'ProfileToken': 'Profile1' * } * ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.getCompatibleVideoSourceConfigurations = function(params, callback) { +OnvifServiceMedia.prototype.getCompatibleAudioSourceConfigurations = function(params, callback) { let promise = new Promise((resolve, reject) => { let err_msg = ''; if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { @@ -713,12 +1650,12 @@ OnvifServiceMedia.prototype.getCompatibleVideoSourceConfigurations = function(pa } let soap_body = ''; - soap_body += ''; - soap_body += '' + params['ProfileToken'] + ''; - soap_body += ''; + soap_body += ''; + soap_body += '' + params['ProfileToken'] + ''; + soap_body += ''; let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'GetCompatibleVideoSourceConfigurations', soap).then((result) => { + mOnvifSoap.requestCommand(this.oxaddr, 'GetCompatibleAudioSourceConfigurations', soap).then((result) => { resolve(result); }).catch((error) => { reject(error); @@ -736,17 +1673,17 @@ OnvifServiceMedia.prototype.getCompatibleVideoSourceConfigurations = function(pa }; /* ------------------------------------------------------------------ -* Method: getVideoSourceConfigurationOptions(params[, callback]) +* Method: getAudioSourceConfigurationOptions(params[, callback]) * - params: -* - ProfileToken | optional | a token of the Profile -* - ConfigurationToken | optional | a token of the configuration +* - ProfileToken | String | optional | a token of the Profile +* - ConfigurationToken | String | optional | * * { * 'ProfileToken': 'Profile1' * 'ConfigurationToken': 'Conf1' * } * ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.getVideoSourceConfigurationOptions = function(params, callback) { +OnvifServiceMedia.prototype.getAudioSourceConfigurationOptions = function(params, callback) { let promise = new Promise((resolve, reject) => { let err_msg = ''; if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { @@ -769,17 +1706,17 @@ OnvifServiceMedia.prototype.getVideoSourceConfigurationOptions = function(params } let soap_body = ''; - soap_body += ''; + soap_body += ''; if('ProfileToken' in params) { - soap_body += '' + params['ProfileToken'] + ''; + soap_body += '' + params['ProfileToken'] + ''; } if('ConfigurationToken' in params) { - soap_body += '' + params['ConfigurationToken'] + ''; + soap_body += '' + params['ConfigurationToken'] + ''; } - soap_body += ''; + soap_body += ''; let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'GetVideoSourceConfigurationOptions', soap).then((result) => { + mOnvifSoap.requestCommand(this.oxaddr, 'GetAudioSourceConfigurationOptions', soap).then((result) => { resolve(result); }).catch((error) => { reject(error); @@ -797,15 +1734,64 @@ OnvifServiceMedia.prototype.getVideoSourceConfigurationOptions = function(params }; /* ------------------------------------------------------------------ -* Method: getMetadataConfiguration(params[, callback]) +* Method: removeAudioSourceConfiguration(params[, callback]) * - params: -* - ConfigurationToken | required | +* - ProfileToken | Object | required | a token of the profile * * { -* 'ConfigurationToken': 'Conf1' +* 'ProfileToken' : 'Profile_1' * } * ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.getMetadataConfiguration = function(params, callback) { +OnvifServiceMedia.prototype.removeAudioSourceConfiguration = function(params, callback) { + let promise = new Promise((resolve, reject) => { + let err_msg = ''; + + if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { + reject(new Error('The value of "params" was invalid: ' + err_msg)); + return; + } + if(err_msg = mOnvifSoap.isInvalidValue(params['ProfileToken'], 'string')) { + reject(new Error('The "ProfileToken" property was invalid: ' + err_msg)); + return; + } + + let soap_body = ''; + try { + soap_body += ''; + soap_body += '' + params.ProfileToken + ''; + soap_body += ''; + } catch (err){ + reject(new Error('Missing required configuration parammeters')); + return; + } + let soap = this._createRequestSoap(soap_body); + + mOnvifSoap.requestCommand(this.oxaddr, 'RemoveAudioSourceConfiguration', soap).then((result) => { + resolve(result); + }).catch((error) => { + reject(error); + }); + }); + if(callback) { + promise.then((result) => { + callback(null, result); + }).catch((error) => { + callback(error); + }); + } else { + return promise; + } +}; +/* ------------------------------------------------------------------ +* Method: getAudioEncoderConfiguration(params[, callback]) +* - params: +* - ConfigurationToken | String | required | +* +* { +* 'ConfigurationToken': 'Profile1' +* } +* ---------------------------------------------------------------- */ +OnvifServiceMedia.prototype.getAudioEncoderConfiguration = function(params, callback) { let promise = new Promise((resolve, reject) => { let err_msg = ''; if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { @@ -819,12 +1805,12 @@ OnvifServiceMedia.prototype.getMetadataConfiguration = function(params, callback } let soap_body = ''; - soap_body += ''; - soap_body += '' + params['ConfigurationToken'] + ''; - soap_body += ''; + soap_body += ''; + soap_body += '' + params['ConfigurationToken'] + ''; + soap_body += ''; let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'GetMetadataConfiguration', soap).then((result) => { + mOnvifSoap.requestCommand(this.oxaddr, 'GetAudioEncoderConfiguration', soap).then((result) => { resolve(result); }).catch((error) => { reject(error); @@ -842,13 +1828,13 @@ OnvifServiceMedia.prototype.getMetadataConfiguration = function(params, callback }; /* ------------------------------------------------------------------ -* Method: getMetadataConfigurations([callback]) +* Method: getAudioEncoderConfigurations([callback]) * ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.getMetadataConfigurations = function(callback) { +OnvifServiceMedia.prototype.getAudioEncoderConfigurations = function(callback) { let promise = new Promise((resolve, reject) => { - let soap_body = ''; + let soap_body = ''; let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'GetMetadataConfigurations', soap).then((result) => { + mOnvifSoap.requestCommand(this.oxaddr, 'GetAudioEncoderConfigurations', soap).then((result) => { resolve(result); }).catch((error) => { reject(error); @@ -866,19 +1852,19 @@ OnvifServiceMedia.prototype.getMetadataConfigurations = function(callback) { }; /* ------------------------------------------------------------------ -* Method: addMetadataConfiguration(params[, callback]) +* Method: addAudioEncoderConfiguration(params[, callback]) * - params: * - ProfileToken | String | required | a token of the Profile -* - ConfigurationToken | String | required | +* - ConfigurationToken | String | required | * * { -* 'ProfileToken': 'Profile1' +* 'ProfileToken': 'Profile1', * 'ConfigurationToken': 'Conf1' * } * -* No device I own does not support this command +* Not device I own does not support this command * ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.addMetadataConfiguration = function(params, callback) { +OnvifServiceMedia.prototype.addAudioEncoderConfiguration = function(params, callback) { let promise = new Promise((resolve, reject) => { let err_msg = ''; if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { @@ -897,13 +1883,13 @@ OnvifServiceMedia.prototype.addMetadataConfiguration = function(params, callback } let soap_body = ''; - soap_body += ''; - soap_body += '' + params['ProfileToken'] + ''; - soap_body += '' + params['ConfigurationToken'] + ''; - soap_body += ''; + soap_body += ''; + soap_body += '' + params['ProfileToken'] + ''; + soap_body += '' + params['ConfigurationToken'] + ''; + soap_body += ''; let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'AddMetadataConfiguration', soap).then((result) => { + mOnvifSoap.requestCommand(this.oxaddr, 'AddAudioEncoderConfiguration', soap).then((result) => { resolve(result); }).catch((error) => { reject(error); @@ -921,15 +1907,15 @@ OnvifServiceMedia.prototype.addMetadataConfiguration = function(params, callback }; /* ------------------------------------------------------------------ -* Method: getCompatibleMetadataConfigurations(params[, callback]) +* Method: getCompatibleAudioEncoderConfigurations(params[, callback]) * - params: -* - ProfileToken | String | required | a token of the Profile +* - ProfileToken | String | required | a token of the profile * * { * 'ProfileToken': 'Profile1' * } * ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.getCompatibleMetadataConfigurations = function(params, callback) { +OnvifServiceMedia.prototype.getCompatibleAudioEncoderConfigurations = function(params, callback) { let promise = new Promise((resolve, reject) => { let err_msg = ''; if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { @@ -943,12 +1929,12 @@ OnvifServiceMedia.prototype.getCompatibleMetadataConfigurations = function(param } let soap_body = ''; - soap_body += ''; - soap_body += '' + params['ProfileToken'] + ''; - soap_body += ''; + soap_body += ''; + soap_body += '' + params['ProfileToken'] + ''; + soap_body += ''; let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'GetCompatibleMetadataConfigurations', soap).then((result) => { + mOnvifSoap.requestCommand(this.oxaddr, 'GetCompatibleAudioEncoderConfigurations', soap).then((result) => { resolve(result); }).catch((error) => { reject(error); @@ -966,7 +1952,7 @@ OnvifServiceMedia.prototype.getCompatibleMetadataConfigurations = function(param }; /* ------------------------------------------------------------------ -* Method: getMetadataConfigurationOptions(params[, callback]) +* Method: getAudioEncoderConfigurationOptions(params[, callback]) * - params: * - ProfileToken | String | optional | a token of the Profile * - ConfigurationToken | String | optional | @@ -976,7 +1962,7 @@ OnvifServiceMedia.prototype.getCompatibleMetadataConfigurations = function(param * 'ConfigurationToken': 'Conf1' * } * ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.getMetadataConfigurationOptions = function(params, callback) { +OnvifServiceMedia.prototype.getAudioEncoderConfigurationOptions = function(params, callback) { let promise = new Promise((resolve, reject) => { let err_msg = ''; if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { @@ -997,43 +1983,19 @@ OnvifServiceMedia.prototype.getMetadataConfigurationOptions = function(params, c return; } } - + let soap_body = ''; - soap_body += ''; + soap_body += ''; if('ProfileToken' in params) { soap_body += '' + params['ProfileToken'] + ''; } if('ConfigurationToken' in params) { soap_body += '' + params['ConfigurationToken'] + ''; } - soap_body += ''; + soap_body += ''; let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'GetMetadataConfigurationOptions', soap).then((result) => { - resolve(result); - }).catch((error) => { - reject(error); - }); - }); - if(callback) { - promise.then((result) => { - callback(null, result); - }).catch((error) => { - callback(error); - }); - } else { - return promise; - } -}; - -/* ------------------------------------------------------------------ -* Method: getAudioSources([callback]) -* ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.getAudioSources = function(callback) { - let promise = new Promise((resolve, reject) => { - let soap_body = ''; - let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'GetAudioSources', soap).then((result) => { + mOnvifSoap.requestCommand(this.oxaddr, 'GetAudioEncoderConfigurationOptions', soap).then((result) => { resolve(result); }).catch((error) => { reject(error); @@ -1051,15 +2013,19 @@ OnvifServiceMedia.prototype.getAudioSources = function(callback) { }; /* ------------------------------------------------------------------ -* Method: getAudioSourceConfiguration(params[, callback]) +* Method: setAudioEncoderConfiguration(params[, callback]) * - params: -* - ConfigurationToken | String | required | +* - ConfigurationToken | String | required | +* - Name | String | required +* - Encoding | String | required +* - Bitrate | number | optional +* - SampleRate | number | optional * * { -* 'ConfigurationToken': 'Conf1' +* 'ConfigurationToken': 'audio_encoder_token' * } * ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.getAudioSourceConfiguration = function(params, callback) { +OnvifServiceMedia.prototype.setAudioEncoderConfiguration = function(params, callback) { let promise = new Promise((resolve, reject) => { let err_msg = ''; if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { @@ -1071,14 +2037,42 @@ OnvifServiceMedia.prototype.getAudioSourceConfiguration = function(params, callb reject(new Error('The "ConfigurationToken" property was invalid: ' + err_msg)); return; } + if(err_msg = mOnvifSoap.isInvalidValue(params['Encoding'], 'string')) { + reject(new Error('The "Encoding" property was invalid: ' + err_msg)); + return; + } + if(err_msg = mOnvifSoap.isInvalidValue(params['Name'], 'string')) { + reject(new Error('The "Name" property was invalid: ' + err_msg)); + return; + } let soap_body = ''; - soap_body += ''; - soap_body += '' + params['ConfigurationToken'] + ''; - soap_body += ''; + soap_body += ''; + soap_body += ``; + soap_body += `${params['Name']}` + soap_body += `0` // Required, but ignored by device + soap_body += ` + + IPv4 + 0.0.0.0 + + 0 + 1 + false + ` // Required, but I don't do anything with it + soap_body += `PT0H0M30S`// Required, but I don't do anything with it + if (params['Encoding']) + soap_body += '' + params['Encoding'] + '' + if (params['Bitrate']) + soap_body += '' + params['Bitrate'] + '' + if (params['SampleRate']) + soap_body += '' + params['SampleRate'] + '' + soap_body += ''; + soap_body += 'true'; + soap_body += ''; + let soap = this._createRequestSoap(soap_body); - - mOnvifSoap.requestCommand(this.oxaddr, 'GetAudioSourceConfiguration', soap).then((result) => { + mOnvifSoap.requestCommand(this.oxaddr, 'SetAudioEncoderConfiguration', soap).then((result) => { resolve(result); }).catch((error) => { reject(error); @@ -1096,13 +2090,18 @@ OnvifServiceMedia.prototype.getAudioSourceConfiguration = function(params, callb }; /* ------------------------------------------------------------------ -* Method: getAudioSourceConfigurations([callback]) +* Method: getAudioOutputs([, callback]) * ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.getAudioSourceConfigurations = function(callback) { +OnvifServiceMedia.prototype.getAudioOutputs = function(callback) { let promise = new Promise((resolve, reject) => { - let soap_body = ''; + + let soap_body = ''; + soap_body += ''; + soap_body += ''; + let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'GetAudioSourceConfigurations', soap).then((result) => { + + mOnvifSoap.requestCommand(this.oxaddr, 'GetAudioOutputs', soap).then((result) => { resolve(result); }).catch((error) => { reject(error); @@ -1120,44 +2119,18 @@ OnvifServiceMedia.prototype.getAudioSourceConfigurations = function(callback) { }; /* ------------------------------------------------------------------ -* Method: addAudioSourceConfiguration(params[, callback]) -* - params: -* - ProfileToken | String | required | a token of the Profile -* - ConfigurationToken | String | required | -* -* { -* 'ProfileToken': 'Profile1', -* 'ConfigurationToken': 'Conf1' -* } -* -* No device I own does not support this command +* Method: getAudioOutputConfigurations([, callback]) * ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.addAudioSourceConfiguration = function(params, callback) { +OnvifServiceMedia.prototype.getAudioOutputConfigurations = function(callback) { let promise = new Promise((resolve, reject) => { - let err_msg = ''; - if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { - reject(new Error('The value of "params" was invalid: ' + err_msg)); - return; - } - - if(err_msg = mOnvifSoap.isInvalidValue(params['ProfileToken'], 'string')) { - reject(new Error('The "ProfileToken" property was invalid: ' + err_msg)); - return; - } - - if(err_msg = mOnvifSoap.isInvalidValue(params['ConfigurationToken'], 'string')) { - reject(new Error('The "ConfigurationToken" property was invalid: ' + err_msg)); - return; - } let soap_body = ''; - soap_body += ''; - soap_body += '' + params['ProfileToken'] + ''; - soap_body += '' + params['ConfigurationToken'] + ''; - soap_body += ''; + soap_body += ''; + soap_body += ''; + let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'AddAudioSourceConfiguration', soap).then((result) => { + mOnvifSoap.requestCommand(this.oxaddr, 'GetAudioOutputConfigurations', soap).then((result) => { resolve(result); }).catch((error) => { reject(error); @@ -1175,15 +2148,18 @@ OnvifServiceMedia.prototype.addAudioSourceConfiguration = function(params, callb }; /* ------------------------------------------------------------------ -* Method: getCompatibleAudioSourceConfigurations(params[, callback]) +* Method: setAudioOutputConfiguration(params[, callback]) * - params: -* - ProfileToken | String | required | a token of the profile +* - ConfigurationToken | String | required | +* - OutputToken | String | required | +* - OutputLevel | integer | required + * * { -* 'ProfileToken': 'Profile1' +* 'ConfigurationToken': 'audio_encoder_token' * } * ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.getCompatibleAudioSourceConfigurations = function(params, callback) { +OnvifServiceMedia.prototype.setAudioOutputConfiguration = function(params, callback) { let promise = new Promise((resolve, reject) => { let err_msg = ''; if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { @@ -1191,18 +2167,29 @@ OnvifServiceMedia.prototype.getCompatibleAudioSourceConfigurations = function(pa return; } - if(err_msg = mOnvifSoap.isInvalidValue(params['ProfileToken'], 'string')) { - reject(new Error('The "ProfileToken" property was invalid: ' + err_msg)); + if(err_msg = mOnvifSoap.isInvalidValue(params['ConfigurationToken'], 'string')) { + reject(new Error('The "ConfigurationToken" property was invalid: ' + err_msg)); + return; + } + if(err_msg = mOnvifSoap.isInvalidValue(params['OutputToken'], 'string')) { + reject(new Error('The "OutputToken" property was invalid: ' + err_msg)); + return; + } + if(err_msg = mOnvifSoap.isInvalidValue(params['OutputLevel'], 'integer')) { + reject(new Error('The "OutputLevel" property was invalid: ' + err_msg)); return; } let soap_body = ''; - soap_body += ''; - soap_body += '' + params['ProfileToken'] + ''; - soap_body += ''; + soap_body += ''; + soap_body += '' + params['ConfigurationToken'] + ''; + soap_body += '' + params['OutputToken'] + ''; + soap_body += '' + params['OutputLevel'] + '' + soap_body += ''; + let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'GetCompatibleAudioSourceConfigurations', soap).then((result) => { + mOnvifSoap.requestCommand(this.oxaddr, 'SetAudioOutputConfiguration', soap).then((result) => { resolve(result); }).catch((error) => { reject(error); @@ -1218,19 +2205,18 @@ OnvifServiceMedia.prototype.getCompatibleAudioSourceConfigurations = function(pa return promise; } }; - /* ------------------------------------------------------------------ -* Method: getAudioSourceConfigurationOptions(params[, callback]) +* Method: startMulticastStreaming(params[, callback]) * - params: -* - ProfileToken | String | optional | a token of the Profile -* - ConfigurationToken | String | optional | +* - ProfileToken | String | required | a token of the Profile * * { * 'ProfileToken': 'Profile1' -* 'ConfigurationToken': 'Conf1' * } +* +* No device I own does not support this command * ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.getAudioSourceConfigurationOptions = function(params, callback) { +OnvifServiceMedia.prototype.startMulticastStreaming = function(params, callback) { let promise = new Promise((resolve, reject) => { let err_msg = ''; if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { @@ -1238,32 +2224,18 @@ OnvifServiceMedia.prototype.getAudioSourceConfigurationOptions = function(params return; } - if('ProfileToken' in params) { - if(err_msg = mOnvifSoap.isInvalidValue(params['ProfileToken'], 'string')) { - reject(new Error('The "ProfileToken" property was invalid: ' + err_msg)); - return; - } - } - - if('ConfigurationToken' in params) { - if(err_msg = mOnvifSoap.isInvalidValue(params['ConfigurationToken'], 'string')) { - reject(new Error('The "ConfigurationToken" property was invalid: ' + err_msg)); - return; - } + if(err_msg = mOnvifSoap.isInvalidValue(params['ProfileToken'], 'string')) { + reject(new Error('The "ProfileToken" property was invalid: ' + err_msg)); + return; } let soap_body = ''; - soap_body += ''; - if('ProfileToken' in params) { - soap_body += '' + params['ProfileToken'] + ''; - } - if('ConfigurationToken' in params) { - soap_body += '' + params['ConfigurationToken'] + ''; - } - soap_body += ''; + soap_body += ''; + soap_body += '' + params['ProfileToken'] + ''; + soap_body += ''; let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'GetAudioSourceConfigurationOptions', soap).then((result) => { + mOnvifSoap.requestCommand(this.oxaddr, 'StartMulticastStreaming', soap).then((result) => { resolve(result); }).catch((error) => { reject(error); @@ -1281,15 +2253,17 @@ OnvifServiceMedia.prototype.getAudioSourceConfigurationOptions = function(params }; /* ------------------------------------------------------------------ -* Method: getAudioEncoderConfiguration(params[, callback]) +* Method: stopMulticastStreaming(params[, callback]) * - params: -* - ConfigurationToken | String | required | +* - ProfileToken | String | required | a token of the Profile * * { -* 'ConfigurationToken': 'Profile1' +* 'ProfileToken': 'Profile1' * } +* +* No device I own does not support this command * ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.getAudioEncoderConfiguration = function(params, callback) { +OnvifServiceMedia.prototype.stopMulticastStreaming = function(params, callback) { let promise = new Promise((resolve, reject) => { let err_msg = ''; if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { @@ -1297,42 +2271,18 @@ OnvifServiceMedia.prototype.getAudioEncoderConfiguration = function(params, call return; } - if(err_msg = mOnvifSoap.isInvalidValue(params['ConfigurationToken'], 'string')) { - reject(new Error('The "ConfigurationToken" property was invalid: ' + err_msg)); + if(err_msg = mOnvifSoap.isInvalidValue(params['ProfileToken'], 'string')) { + reject(new Error('The "ProfileToken" property was invalid: ' + err_msg)); return; } let soap_body = ''; - soap_body += ''; - soap_body += '' + params['ConfigurationToken'] + ''; - soap_body += ''; + soap_body += ''; + soap_body += '' + params['ProfileToken'] + ''; + soap_body += ''; let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'GetAudioEncoderConfiguration', soap).then((result) => { - resolve(result); - }).catch((error) => { - reject(error); - }); - }); - if(callback) { - promise.then((result) => { - callback(null, result); - }).catch((error) => { - callback(error); - }); - } else { - return promise; - } -}; - -/* ------------------------------------------------------------------ -* Method: getAudioEncoderConfigurations([callback]) -* ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.getAudioEncoderConfigurations = function(callback) { - let promise = new Promise((resolve, reject) => { - let soap_body = ''; - let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'GetAudioEncoderConfigurations', soap).then((result) => { + mOnvifSoap.requestCommand(this.oxaddr, 'StopMulticastStreaming', soap).then((result) => { resolve(result); }).catch((error) => { reject(error); @@ -1350,19 +2300,15 @@ OnvifServiceMedia.prototype.getAudioEncoderConfigurations = function(callback) { }; /* ------------------------------------------------------------------ -* Method: addAudioEncoderConfiguration(params[, callback]) +* Method: getSnapshotUri(params[, callback]) * - params: -* - ProfileToken | String | required | a token of the Profile -* - ConfigurationToken | String | required | +* - ProfileToken | String | required | a token of the Profile * * { -* 'ProfileToken': 'Profile1', -* 'ConfigurationToken': 'Conf1' +* 'ProfileToken': 'Profile1' * } -* -* Not device I own does not support this command * ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.addAudioEncoderConfiguration = function(params, callback) { +OnvifServiceMedia.prototype.getSnapshotUri = function(params, callback) { let promise = new Promise((resolve, reject) => { let err_msg = ''; if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { @@ -1375,19 +2321,13 @@ OnvifServiceMedia.prototype.addAudioEncoderConfiguration = function(params, call return; } - if(err_msg = mOnvifSoap.isInvalidValue(params['ConfigurationToken'], 'string')) { - reject(new Error('The "ConfigurationToken" property was invalid: ' + err_msg)); - return; - } - let soap_body = ''; - soap_body += ''; + soap_body += ''; soap_body += '' + params['ProfileToken'] + ''; - soap_body += '' + params['ConfigurationToken'] + ''; - soap_body += ''; + soap_body += ''; let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'AddAudioEncoderConfiguration', soap).then((result) => { + mOnvifSoap.requestCommand(this.oxaddr, 'GetSnapshotUri', soap).then((result) => { resolve(result); }).catch((error) => { reject(error); @@ -1405,15 +2345,15 @@ OnvifServiceMedia.prototype.addAudioEncoderConfiguration = function(params, call }; /* ------------------------------------------------------------------ -* Method: getCompatibleAudioEncoderConfigurations(params[, callback]) +* Method: getOSDs(params[, callback]) * - params: -* - ProfileToken | String | required | a token of the profile +* - VideoSourceToken | String | optional | a token of the video source * * { -* 'ProfileToken': 'Profile1' +* 'VideoSourceToken': 'VS1' * } * ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.getCompatibleAudioEncoderConfigurations = function(params, callback) { +OnvifServiceMedia.prototype.getOSDs = function(params, callback) { let promise = new Promise((resolve, reject) => { let err_msg = ''; if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { @@ -1421,18 +2361,14 @@ OnvifServiceMedia.prototype.getCompatibleAudioEncoderConfigurations = function(p return; } - if(err_msg = mOnvifSoap.isInvalidValue(params['ProfileToken'], 'string')) { - reject(new Error('The "ProfileToken" property was invalid: ' + err_msg)); - return; - } - let soap_body = ''; - soap_body += ''; - soap_body += '' + params['ProfileToken'] + ''; - soap_body += ''; + soap_body += ''; + if (params['VideoSourceToken']) + soap_body += '' + params['VideoSourceToken'] + '' + soap_body += ''; let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'GetCompatibleAudioEncoderConfigurations', soap).then((result) => { + mOnvifSoap.requestCommand(this.oxaddr, 'GetOSDs', soap).then((result) => { resolve(result); }).catch((error) => { reject(error); @@ -1450,17 +2386,15 @@ OnvifServiceMedia.prototype.getCompatibleAudioEncoderConfigurations = function(p }; /* ------------------------------------------------------------------ -* Method: getAudioEncoderConfigurationOptions(params[, callback]) +* Method: getOSDOptions(params[, callback]) * - params: -* - ProfileToken | String | optional | a token of the Profile -* - ConfigurationToken | String | optional | +* - VideoSourceToken | String | required | a token of the video source * * { -* 'ProfileToken': 'Profile1' -* 'ConfigurationToken': 'Conf1' +* 'VideoSourceToken': 'VS1' * } * ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.getAudioEncoderConfigurationOptions = function(params, callback) { +OnvifServiceMedia.prototype.getOSDOptions = function(params, callback) { let promise = new Promise((resolve, reject) => { let err_msg = ''; if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { @@ -1468,32 +2402,19 @@ OnvifServiceMedia.prototype.getAudioEncoderConfigurationOptions = function(param return; } - if('ProfileToken' in params) { - if(err_msg = mOnvifSoap.isInvalidValue(params['ProfileToken'], 'string')) { - reject(new Error('The "ProfileToken" property was invalid: ' + err_msg)); - return; - } + if(err_msg = mOnvifSoap.isInvalidValue(params['VideoSourceToken'], 'string')) { + reject(new Error('The "VideoSourceToken" property was invalid: ' + err_msg)); + return; } - if('ConfigurationToken' in params) { - if(err_msg = mOnvifSoap.isInvalidValue(params['ConfigurationToken'], 'string')) { - reject(new Error('The "ConfigurationToken" property was invalid: ' + err_msg)); - return; - } - } - let soap_body = ''; - soap_body += ''; - if('ProfileToken' in params) { - soap_body += '' + params['ProfileToken'] + ''; - } - if('ConfigurationToken' in params) { - soap_body += '' + params['ConfigurationToken'] + ''; - } - soap_body += ''; + soap_body += ''; + soap_body += '' + params['VideoSourceToken'] + ''; + soap_body += '' + params['VideoSourceToken'] + ''; + soap_body += ''; let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'GetAudioEncoderConfigurationOptions', soap).then((result) => { + mOnvifSoap.requestCommand(this.oxaddr, 'GetOSDOptions', soap).then((result) => { resolve(result); }).catch((error) => { reject(error); @@ -1511,17 +2432,19 @@ OnvifServiceMedia.prototype.getAudioEncoderConfigurationOptions = function(param }; /* ------------------------------------------------------------------ -* Method: startMulticastStreaming(params[, callback]) +* Method: createOSD(params[, callback]) * - params: -* - ProfileToken | String | required | a token of the Profile * * { -* 'ProfileToken': 'Profile1' +* 'Token': OSD token +* 'VideoSourceConfigurationToken': 'OSD1' +* 'Position': ': UpperLeft | UpperRight | LowerLeft | LowerRight +* 'Text': [optional] 'this is text' +* 'DateFormat': [optional] YYY-MM-DD +* 'TimeFormat': [optional] hh:mm:ss * } -* -* No device I own does not support this command * ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.startMulticastStreaming = function(params, callback) { +OnvifServiceMedia.prototype.createOSD = function(params, callback) { let promise = new Promise((resolve, reject) => { let err_msg = ''; if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { @@ -1529,18 +2452,41 @@ OnvifServiceMedia.prototype.startMulticastStreaming = function(params, callback) return; } - if(err_msg = mOnvifSoap.isInvalidValue(params['ProfileToken'], 'string')) { - reject(new Error('The "ProfileToken" property was invalid: ' + err_msg)); - return; - } - let soap_body = ''; - soap_body += ''; - soap_body += '' + params['ProfileToken'] + ''; - soap_body += ''; + soap_body += ''; + soap_body += '' + soap_body += '' + params['VideoSourceConfigurationToken'] + ''; + soap_body += 'Text' + soap_body += '' + soap_body += '' + params['Position'] + '' + soap_body += ''; + soap_body += ''; + if (params['DateFormat']){ + if (params['TimeFormat']){ + soap_body += 'DateAndTime' + soap_body += '' + params['DateFormat'] + '' + soap_body += '' + params['TimeFormat'] + '' + } else { + soap_body += 'Date' + soap_body += '' + params['DateFormat'] + '' + } + } else if (params['TimeFormat']){ + soap_body += 'Time' + soap_body += '' + params['TimeFormat'] + '' + } else if (params['Text']){ + soap_body += 'Plain' + soap_body += '' + params['Text'] + ''; + } else { + soap_body += 'Plain' + soap_body += '' + } + soap_body += '' + soap_body += '' + + soap_body += ''; let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'StartMulticastStreaming', soap).then((result) => { + mOnvifSoap.requestCommand(this.oxaddr, 'CreateOSD', soap).then((result) => { resolve(result); }).catch((error) => { reject(error); @@ -1558,17 +2504,20 @@ OnvifServiceMedia.prototype.startMulticastStreaming = function(params, callback) }; /* ------------------------------------------------------------------ -* Method: stopMulticastStreaming(params[, callback]) +* Method: setOSD(params[, callback]) * - params: -* - ProfileToken | String | required | a token of the Profile +* - VideoSourceConfigurationToken | String | required | a token of the OSD * * { -* 'ProfileToken': 'Profile1' +* 'Token': OSD token +* 'VideoSourceConfigurationToken': 'OSD1' +* 'Position': ': UpperLeft | UpperRight | LowerLeft | LowerRight +* 'Text': [optional] 'this is text' +* 'DateFormat': [optional] YYY-MM-DD +* 'TimeFormat': [optional] hh:mm:ss * } -* -* No device I own does not support this command * ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.stopMulticastStreaming = function(params, callback) { +OnvifServiceMedia.prototype.setOSD = function(params, callback) { let promise = new Promise((resolve, reject) => { let err_msg = ''; if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { @@ -1576,18 +2525,40 @@ OnvifServiceMedia.prototype.stopMulticastStreaming = function(params, callback) return; } - if(err_msg = mOnvifSoap.isInvalidValue(params['ProfileToken'], 'string')) { - reject(new Error('The "ProfileToken" property was invalid: ' + err_msg)); - return; - } - let soap_body = ''; - soap_body += ''; - soap_body += '' + params['ProfileToken'] + ''; - soap_body += ''; + soap_body += '' + soap_body += '' + soap_body += '' + params['VideoSourceConfigurationToken'] + ''; + soap_body += 'Text' + soap_body += '' + soap_body += '' + params['Position'] + '' + soap_body += ''; + soap_body += ''; + if (params['DateFormat']){ + if (params['TimeFormat']){ + soap_body += 'DateAndTime' + soap_body += '' + params['DateFormat'] + '' + soap_body += '' + params['TimeFormat'] + '' + } else { + soap_body += 'Date' + soap_body += '' + params['DateFormat'] + '' + } + } else if (params['TimeFormat']){ + soap_body += 'Time' + soap_body += '' + params['TimeFormat'] + '' + } else if (params['Text']){ + soap_body += 'Plain' + soap_body += '' + params['Text'] + ''; + } else { + soap_body += 'Plain' + soap_body += '' + } + soap_body += '' + soap_body += '' + soap_body += ''; let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'StopMulticastStreaming', soap).then((result) => { + mOnvifSoap.requestCommand(this.oxaddr, 'SetOSD', soap).then((result) => { resolve(result); }).catch((error) => { reject(error); @@ -1605,15 +2576,15 @@ OnvifServiceMedia.prototype.stopMulticastStreaming = function(params, callback) }; /* ------------------------------------------------------------------ -* Method: getSnapshotUri(params[, callback]) +* Method: deleteOSD(params[, callback]) * - params: -* - ProfileToken | String | required | a token of the Profile +* - Token | String | required | a token of the Profile * * { -* 'ProfileToken': 'Profile1' +* 'Token': 'OSD1' * } * ---------------------------------------------------------------- */ -OnvifServiceMedia.prototype.getSnapshotUri = function(params, callback) { +OnvifServiceMedia.prototype.deleteOSD = function(params, callback) { let promise = new Promise((resolve, reject) => { let err_msg = ''; if(err_msg = mOnvifSoap.isInvalidValue(params, 'object')) { @@ -1621,18 +2592,19 @@ OnvifServiceMedia.prototype.getSnapshotUri = function(params, callback) { return; } - if(err_msg = mOnvifSoap.isInvalidValue(params['ProfileToken'], 'string')) { - reject(new Error('The "ProfileToken" property was invalid: ' + err_msg)); + if(err_msg = mOnvifSoap.isInvalidValue(params['Token'], 'string')) { + reject(new Error('The "Token" property was invalid: ' + err_msg)); return; } let soap_body = ''; - soap_body += ''; - soap_body += '' + params['ProfileToken'] + ''; - soap_body += ''; + soap_body += ''; + soap_body += '' + params['Token'] + ''; + soap_body += '' + params['Token'] + ''; + soap_body += ''; let soap = this._createRequestSoap(soap_body); - mOnvifSoap.requestCommand(this.oxaddr, 'GetSnapshotUri', soap).then((result) => { + mOnvifSoap.requestCommand(this.oxaddr, 'DeleteOSD', soap).then((result) => { resolve(result); }).catch((error) => { reject(error); diff --git a/lib/modules/soap.js b/lib/modules/soap.js index 2622d87..0c64ac4 100644 --- a/lib/modules/soap.js +++ b/lib/modules/soap.js @@ -10,6 +10,7 @@ const mXml2Js = require('xml2js'); const mHttp = require('http'); const mCrypto = require('crypto'); let mHtml = null; +let mLogger = null; try { mHtml = require('html'); } catch(e) {} @@ -21,6 +22,16 @@ function OnvifSoap() { this.HTTP_TIMEOUT = 3000; // ms } +/* ------------------------------------------------------------------ +* Method: enableLogging(method) +* +* J. Udall +* - method - a logger function that will be invoked for every SOAP message +* ---------------------------------------------------------------- */ +OnvifSoap.prototype.enableLogging = function(method) { + mLogger = method +} + /* ------------------------------------------------------------------ * Method: parse(soap) * ---------------------------------------------------------------- */ @@ -58,7 +69,9 @@ OnvifSoap.prototype.requestCommand = function(oxaddr, method_name, soap) { }).then((result) => { let fault = this._getFaultReason(result); if(fault) { - let err = new Error(fault); + let err = new Error(fault) + if (typeof fault == 'object' && fault._) + err = new Error(fault._) reject(err); } else { let parsed = this._parseResponseResult(method_name, result); @@ -71,8 +84,28 @@ OnvifSoap.prototype.requestCommand = function(oxaddr, method_name, soap) { }; resolve(res); } else { - let err = new Error('The device seems to not support the ' + method_name + '() method.'); - reject(err); + + // JU: This sucks! The Arecont Vision camera provides a RemoveVideoEncoderConfigurationResponse + // rather than a RemoveVideoSourceConfigurationResponse + // So look for this abberation + if (method_name == 'RemoveVideoSourceConfiguration'){ + parsed = this._parseResponseResult('RemoveVideoEncoderConfiguration', result) + if (parsed){ + let res = { + 'soap' : xml, + 'formatted': mHtml ? mHtml.prettyPrint(xml, {indent_size: 2}) : '', + 'converted': result, + 'data': parsed + }; + resolve(res); + } else { + let err = new Error('The device seems to not support the ' + method_name + '() method.'); + reject(err); + } + } else { + let err = new Error('The device seems to not support the ' + method_name + '() method.'); + reject(err); + } } } }).catch((error) => { @@ -101,6 +134,7 @@ OnvifSoap.prototype._request = function(oxaddr, soap) { port : oxaddr.port || 80, path : oxaddr.pathname, method : 'POST', + timeout : 3000, headers: { //'Content-Type': 'application/soap+xml; charset=utf-8; action="http://www.onvif.org/ver10/device/wsdl/GetScopes"', 'Content-Type': 'application/soap+xml; charset=utf-8;', @@ -108,6 +142,10 @@ OnvifSoap.prototype._request = function(oxaddr, soap) { } }; + // J. UDALL - log SOAP request + if (mLogger){ + mLogger(soap) + } let req = mHttp.request(post_opts, (res) => { res.setEncoding('utf8'); let xml = ''; @@ -125,6 +163,12 @@ OnvifSoap.prototype._request = function(oxaddr, soap) { res.removeAllListeners('end'); } if(res.statusCode === 200) { + + // J. UDALL - log SOAP response + if (mLogger){ + mLogger(xml) + } + resolve(xml); } else { let err = new Error(res.statusCode + ' ' + res.statusMessage); @@ -138,6 +182,9 @@ OnvifSoap.prototype._request = function(oxaddr, soap) { if(typeof(msg) === 'object') { msg = msg['_']; } + if (parsed['Body']['Fault']['Detail']){ + msg += ` (${parsed['Body']['Fault']['Detail']['Text']})` + } } catch(e) {} if(msg) { reject(new Error(code + ' ' + text + ' - ' + msg)); @@ -234,7 +281,7 @@ OnvifSoap.prototype._createSoapUserToken = function(diff, user, pass) { let nonce_buffer = this._createNonce(16); let nonce_base64 = nonce_buffer.toString('base64'); let shasum = mCrypto.createHash('sha1'); - shasum.update(Buffer.concat([nonce_buffer, new Buffer(date), new Buffer(pass)])); + shasum.update(Buffer.concat([nonce_buffer, Buffer.from(date), Buffer.from(pass)])); let digest = shasum.digest('base64'); let soap = ''; soap += ''; @@ -249,7 +296,7 @@ OnvifSoap.prototype._createSoapUserToken = function(diff, user, pass) { }; OnvifSoap.prototype._createNonce = function(digit) { - let nonce = new Buffer(digit); + let nonce = Buffer.alloc(digit); for(let i=0; i { this._devices = {}; this._udp = mDgram.createSocket('udp4'); @@ -125,7 +134,26 @@ Onvif.prototype.startProbe = function(callback) { }); }); - this._udp.bind(() => { + // J. UDALL. CHANGE FROM ORIGINAL CODE TO SPECIFY NIC + let bindAddress = '0.0.0.0' + if (options == null || options.device == null){ + throw("Mandatory options.device is missing") + } else { + const os = require('os') + const interfaces = os.networkInterfaces() + // Try to find the interface based on the device name + if (options.device in interfaces) { + interfaces[options.device].some(function(address) { + // Only use IPv4 addresses + if (address.family === 'IPv4') { + bindAddress = address.address + return true + } + }) + } else + throw("NIC '" + options.device + "' not found or unplugged") + } + this._udp.bind(null,bindAddress,() => { this._udp.removeAllListeners('error'); this._sendProbe().then(() => { // Do nothing. @@ -209,7 +237,7 @@ Onvif.prototype._sendProbe = function(callback) { } let send = () => { let soap = soap_list.shift(); - if(soap) { + if(soap && this._udp) { let buf = Buffer.from(soap, 'utf8'); this._udp.send(buf, 0, buf.length, this._PORT, this._MULTICAST_ADDRESS, (error, bytes) => { this._discovery_interval_timer = setTimeout(() => { @@ -252,6 +280,7 @@ Onvif.prototype.stopDiscovery = function(callback) { /* ------------------------------------------------------------------ * Method: stopProbe([callback]) * ---------------------------------------------------------------- */ + Onvif.prototype.stopProbe = function(callback) { if(this._discovery_interval_timer !== null) { clearTimeout(this._discovery_interval_timer); diff --git a/package.json b/package.json index c0eaa73..21e1d18 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.1.7", "description": "The node-onvif is a Node.js module which allows you to communicate with the network camera which supports the ONVIF specifications.", "engines": { - "node" : ">=4.4" + "node": ">=4.4" }, "main": "./lib/node-onvif.js", "files": [ @@ -33,7 +33,7 @@ }, "readmeFilename": "README.md", "dependencies": { - "xml2js": ">=0.4.17", - "html": ">=1.0.0" + "html": ">=1.0.0", + "xml2js": "^0.6.0" } }