/**
* @namespace cam
* @description Media section for Cam class
* @author Andrew D.Laptev <a.d.laptev@gmail.com>
* @licence MIT
*/
module.exports = function(Cam) {
const linerase = require('./utils').linerase;
/**
* @typedef {object} Cam~ImagingSettings
* @property {number} brightness
* @property {number} colorSaturation
* @property {object} focus
* @property {string} focus.autoFocusMode
* @property {number} sharpness
*/
/**
* @callback Cam~GetImagingSettingsCallback
* @property {?Error} error
* @property {Cam~ImagingSettings} status
*/
/**
* Get the ImagingConfiguration for the requested VideoSource (default - the activeSource)
* @param {object} [options]
* @param {string} [options.token] {@link Cam#activeSource.profileToken}
* @param {Cam~GetImagingSettingsCallback} callback
*/
Cam.prototype.getImagingSettings = function(options, callback) {
if (typeof callback === 'undefined') {
callback = options;
options = {};
}
this._request({
service: 'imaging'
, body: this._envelopeHeader() +
'<GetImagingSettings xmlns="http://www.onvif.org/ver20/imaging/wsdl" >' +
'<VideoSourceToken xmlns="http://www.onvif.org/ver20/imaging/wsdl" >' + ( options.token || this.activeSource.sourceToken ) + '</VideoSourceToken>' +
'</GetImagingSettings>' +
this._envelopeFooter()
}, function(err, data, xml) {
if (callback) {
callback.call(this, err, err ? null : linerase(data).getImagingSettingsResponse.imagingSettings, xml);
}
}.bind(this));
};
/**
* @typedef {object} Cam~ImagingSetting
* @property {string} token Video source token
* @property {number} brightness
* @property {number} colorSaturation
* @property {number} contrast
* @property {object} exposure
* @property {string} exposure.mode Exposure mode -enum { 'AUTO', 'MANUAL' }
* @property {string} exposure.priority The exposure priority mode (low noise/framerate) -enum { 'LowNoise', 'FrameRate' }
* @property {number} exposure.minExposureTime
* @property {number} exposure.maxExposureTime
* @property {number} exposure.minGain
* @property {number} exposure.maxGain
* @property {number} exposure.minIris
* @property {number} exposure.maxIris
* @property {number} exposure.exposureTime
* @property {number} exposure.gain
* @property {number} exposure.iris
* @property {object} focus
* @property {string} focus.autoFocusMode Mode of auto focus -enum { 'AUTO', 'MANUAL' }
* @property {number} focus.defaultSpeed
* @property {number} focus.nearLimit
* @property {number} focus.farLimit
* @property {number} sharpness
* @property {string} irCutFilter Mode of ir cut filter -enum { 'AUTO', 'ON', 'OFF' }
*/
/**
* Set the ImagingConfiguration for the requested VideoSource (default - the activeSource)
* @param {Cam~ImagingSetting} options
* @param callback
*/
Cam.prototype.setImagingSettings = function(options, callback) {
this._request({
service: 'imaging'
, body: this._envelopeHeader() +
'<SetImagingSettings xmlns="http://www.onvif.org/ver20/imaging/wsdl" >' +
'<VideoSourceToken xmlns="http://www.onvif.org/ver20/imaging/wsdl" >' +
(options.token || this.activeSource.sourceToken) +
'</VideoSourceToken>' +
'<ImagingSettings xmlns="http://www.onvif.org/ver20/imaging/wsdl" >' +
(
options.brightness ?
(
'<Brightness xmlns="http://www.onvif.org/ver10/schema">' +
options.brightness +
'</Brightness>'
) : ''
)
+
(
options.colorSaturation ?
(
'<ColorSaturation xmlns="http://www.onvif.org/ver10/schema">' +
options.colorSaturation +
'</ColorSaturation>'
) : ''
)
+
(
options.contrast ?
(
'<Contrast xmlns="http://www.onvif.org/ver10/schema">' +
options.contrast +
'</Contrast>'
) : ''
)
+
(
options.exposure ?
(
'<Exposure xmlns="http://www.onvif.org/ver10/schema">' +
(
options.exposure.mode ?
(
'<Mode xmlns="http://www.onvif.org/ver10/schema">' + options.exposure.mode + '</Mode>'
) : ''
)
+
(
options.exposure.priority ?
(
'<Priority xmlns="http://www.onvif.org/ver10/schema">' + options.exposure.priority + '</Priority>'
) : ''
)
+
(
options.exposure.minExposureTime ?
(
'<MinExposureTime xmlns="http://www.onvif.org/ver10/schema">' + options.exposure.minExposureTime + '</MinExposureTime>'
) : ''
)
+
(
options.exposure.maxExposureTime ?
(
'<MaxExposureTime xmlns="http://www.onvif.org/ver10/schema">' + options.exposure.maxExposureTime + '</MaxExposureTime>'
) : ''
)
+
(
options.exposure.minGain ?
(
'<MinGain xmlns="http://www.onvif.org/ver10/schema">' + options.exposure.minGain + '</MinGain>'
) : ''
)
+
(
options.exposure.maxGain ?
(
'<MaxGain xmlns="http://www.onvif.org/ver10/schema">' + options.exposure.maxGain + '</MaxGain>'
) : ''
)
+
(
options.exposure.minIris ?
(
'<MinIris xmlns="http://www.onvif.org/ver10/schema">' + options.exposure.minIris + '</MinIris>'
) : ''
)
+
(
options.exposure.maxIris ?
(
'<MaxIris xmlns="http://www.onvif.org/ver10/schema">' + options.exposure.maxIris + '</MaxIris>'
) : ''
)
+
(
options.exposure.exposureTime ?
(
'<ExposureTime xmlns="http://www.onvif.org/ver10/schema">' + options.exposure.exposureTime + '</ExposureTime>'
) : ''
)
+
(
options.exposure.gain ?
(
'<Gain xmlns="http://www.onvif.org/ver10/schema">' + options.exposure.gain + '</Gain>'
) : ''
)
+
(
options.exposure.iris ?
(
'<Iris xmlns="http://www.onvif.org/ver10/schema">' + options.exposure.iris + '</Iris>'
) : ''
) +
'</Exposure>'
) : ''
)
+
(
options.focus ?
(
'<Focus xmlns="http://www.onvif.org/ver10/schema">' +
(
options.focus.autoFocusMode ?
(
'<AutoFocusMode xmlns="http://www.onvif.org/ver10/schema">' + options.focus.autoFocusMode + '</AutoFocusMode>'
) : ''
)
+
(
options.focus.defaultSpeed ?
(
'<DefaultSpeed xmlns="http://www.onvif.org/ver10/schema">' + options.focus.defaultSpeed + '</DefaultSpeed>'
) : ''
)
+
(
options.focus.nearLimit ?
(
'<NearLimit xmlns="http://www.onvif.org/ver10/schema">' + options.focus.nearLimit + '</NearLimit>'
) : ''
)
+
(
options.focus.farLimit ?
(
'<FarLimit xmlns="http://www.onvif.org/ver10/schema">' + options.focus.farLimit + '</FarLimit>'
) : ''
) +
'</Focus>'
) : ''
)
+
(
options.sharpness ?
(
'<Sharpness xmlns="http://www.onvif.org/ver10/schema">' +
options.sharpness +
'</Sharpness>'
) : ''
)
+
(
options.irCutFilter ?
(
'<IrCutFilter xmlns="http://www.onvif.org/ver10/schema">' +
options.irCutFilter +
'</IrCutFilter>'
) : ''
)
+
'</ImagingSettings>' +
'</SetImagingSettings>' +
this._envelopeFooter()
}, function(err, data, xml) {
if (callback) {
callback.call(this, err, err ? null : linerase(data).setImagingSettingsResponse, xml);
}
}.bind(this));
};
/**
* @typedef {object} Cam~ImagingServiceCapabilities
* @property {boolean} ImageStabilization Indicates whether or not Image Stabilization feature is supported
* @property {boolean} [Presets] Indicates whether or not Imaging Presets feature is supported
*/
/**
* @callback Cam~GetImagingServiceCapabilitiesCallback
* @property {?Error} error
* @property {Cam~ImagingServiceCapabilities} capabilities
*/
/**
* Returns the capabilities of the imaging service
* @property {Cam~GetImagingServiceCapabilitiesCallback}
*/
Cam.prototype.getImagingServiceCapabilities = function(callback) {
this._request({
service: 'imaging'
, body: this._envelopeHeader() +
'<GetServiceCapabilities xmlns="http://www.onvif.org/ver20/imaging/wsdl" >' +
'</GetServiceCapabilities>' +
this._envelopeFooter()
}, function(err, data, xml) {
if (callback) {
callback.call(this, err, err ? null : linerase(data[0].getServiceCapabilitiesResponse[0].capabilities[0].$), xml);
}
}.bind(this));
};
/**
* @typedef {object} Cam~ImagingPreset
* @property {string} token
* @property {string} type Indicates Imaging Preset Type
* @property {string} Name Human readable name of the Imaging Preset
*/
/**
* @callback Cam~GetCurrentImagingPresetCallback
* @property {?Error} error
* @property {Cam~ImagingPreset} preset
*/
/**
* Get the last Imaging Preset applied
* @param {object} [options]
* @param {string} [options.token] Reference token to the VideoSource where the current Imaging Preset should be requested
* @param {Cam~GetCurrentImagingPresetCallback} callback
*/
Cam.prototype.getCurrentImagingPreset = function(options, callback) {
if (typeof callback === 'undefined') {
callback = options;
options = {};
}
this._request({
service: 'imaging'
, body: this._envelopeHeader() +
'<GetCurrentPreset xmlns="http://www.onvif.org/ver20/imaging/wsdl" >' +
'<VideoSourceToken>' + (options.token || this.activeSource.sourceToken) + '</VideoSourceToken>' +
'</GetCurrentPreset>' +
this._envelopeFooter()
}, function(err, data, xml) {
if (callback) {
callback.call(this, err, err ? null : linerase(data).getCurrentPresetResponse.preset, xml);
}
}.bind(this));
};
/**
* Set the ImagingConfiguration for the requested or current VideoSource
* @param options
* @param {string} [options.token] Reference token to the VideoSource to which the specified Imaging Preset should be applied.
* @param {string} options.presetToken Reference token to the Imaging Preset to be applied to the specified Video Source
* @param {Cam~RequestCallback} callback
*/
Cam.prototype.setCurrentImagingPreset = function(options, callback) {
this._request({
service: 'imaging'
, body: this._envelopeHeader() +
'<SetCurrentPreset xmlns="http://www.onvif.org/ver20/imaging/wsdl" >' +
'<VideoSourceToken>' + (options.token || this.activeSource.sourceToken) + '</VideoSourceToken>' +
'<PresetToken>' + options.presetToken + '</PresetToken>' +
'</SetCurrentPreset>' +
this._envelopeFooter()
}, function(err, data, xml) {
if (callback) {
callback.call(this, err, err ? null : linerase(data).setCurrentPresetResponse, xml);
}
}.bind(this));
};
/**
* Get the video source options for a given video source
* @param {Object} options.token videoSourceToken
* @param {function} [callback]
*/
Cam.prototype.getVideoSourceOptions = function(options, callback) {
if (typeof callback === 'undefined') {
callback = options;
options = {};
}
this._request({
service: 'imaging'
, body: this._envelopeHeader() +
'<GetOptions xmlns="http://www.onvif.org/ver20/imaging/wsdl">' +
'<VideoSourceToken>' + (options.token || this.activeSource.sourceToken) + '</VideoSourceToken>' +
'</GetOptions>' +
this._envelopeFooter()
}, function(err, data, xml) {
if (callback) {
let jsonData = linerase(data),
respData = {};
if (jsonData && jsonData.getOptionsResponse && jsonData.getOptionsResponse.imagingOptions) {
respData = jsonData.getOptionsResponse.imagingOptions;
}
// Empty response on success
callback.call(this, err, respData, xml);
}
}.bind(this));
};
/**
* Get the move options to be used in the focus move command for a given video source
* @param {Object} options
* @param {string} [options.token=Cam#activeSource.sourceToken] videoSourceToken
* @param {function} [callback]
*/
Cam.prototype.imagingGetMoveOptions = function(options, callback) {
if (typeof callback === 'undefined') {
callback = options;
options = {};
}
this._request({
service: 'imaging'
, body: this._envelopeHeader() +
'<GetMoveOptions xmlns="http://www.onvif.org/ver20/imaging/wsdl">' +
'<VideoSourceToken>' + (options.token || this.activeSource.sourceToken) + '</VideoSourceToken>' +
'</GetMoveOptions>' +
this._envelopeFooter()
}, function(err, data, xml) {
if (callback) {
let jsonData = linerase(data),
respData = {};
if (jsonData && jsonData.getMoveOptionsResponse && jsonData.getMoveOptionsResponse.moveOptions) {
respData = jsonData.getMoveOptionsResponse.moveOptions;
}
// Empty response on success
callback.call(this, err, respData, xml);
}
}.bind(this));
};
/**
* Get the current status of the move operation
* @param {Object} options
* @param {string} [options.token=Cam#activeSource.sourceToken] videoSourceToken
* @param {function} [callback]
*/
Cam.prototype.imagingGetStatus = function(options, callback) {
if (typeof callback === 'undefined') {
callback = options;
options = {};
}
this._request({
service: 'imaging'
, body: this._envelopeHeader() +
'<GetStatus xmlns="http://www.onvif.org/ver20/imaging/wsdl">' +
'<VideoSourceToken>' + (options.token || this.activeSource.sourceToken) + '</VideoSourceToken>' +
'</GetStatus>' +
this._envelopeFooter()
}, function(err, data, xml) {
if (callback) {
let jsonData = linerase(data),
respData = {};
if (jsonData && jsonData.getStatusResponse && jsonData.getStatusResponse.status) {
respData = jsonData.getStatusResponse.status;
}
// Empty response on success
callback.call(this, err, respData, xml);
}
}.bind(this));
};
/**
* The command moves the focus lens in an absolute, a relative, or in a continuous manner from its current position.
* @param {object} options The supported move options are signaled via the GetMoveOptions command
* @param {string} [options.token=Cam#activeSource.sourceToken] videoSourceToken
* @param {object} [options.absolute] Absolute movement
* @param {number} [options.absolute.position] Min and Max values defined by the GetMoveOptions if support the absolute movement
* @param {number} [options.absolute.speed] If the speed argument is omitted, the default speed set by the ImagingSetting will be used.
* @param {object} [options.relative] Relative movement
* @param {number} [options.relative.distance] Min and Max values defined by the GetMoveOptions if support the relative movement
* @param {number} [options.relative.speed] If the speed argument is omitted, the default speed set by the ImagingSetting will be used.
* @param {object} [options.continuous] Continuous move until the focus lens reaches its limits or gets a stop command
* @param {number} [options.continuous.speed] Min and Max values defined by the GetMoveOptions if support the continuous movement
* @param callback
*/
Cam.prototype.imagingMove = function(options, callback) {
this._request({
service: 'imaging'
, body: this._envelopeHeader() +
'<Move xmlns="http://www.onvif.org/ver20/imaging/wsdl" >' +
'<VideoSourceToken xmlns="http://www.onvif.org/ver20/imaging/wsdl" >' +
(options.token || this.activeSource.sourceToken) +
'</VideoSourceToken>' +
'<Focus xmlns="http://www.onvif.org/ver20/imaging/wsdl">' +
(
options.absolute ?
(
'<Absolute xmlns="http://www.onvif.org/ver10/schema">' +
(
options.absolute.position ?
(
'<Position xmlns="http://www.onvif.org/ver10/schema">' + options.absolute.position + '</Position>'
) : ''
)
+
(
options.absolute.speed ?
(
'<Speed xmlns="http://www.onvif.org/ver10/schema">' + options.absolute.speed + '</Speed>'
) : ''
)
+ '</Absolute>'
) : ''
)
+
(
options.relative ?
(
'<Relative xmlns="http://www.onvif.org/ver10/schema">' +
(
options.relative.distance ?
(
'<Distance xmlns="http://www.onvif.org/ver10/schema">' + options.relative.distance + '</Distance>'
) : ''
)
+
(
options.relative.speed ?
(
'<Speed xmlns="http://www.onvif.org/ver10/schema">' + options.relative.speed + '</Speed>'
) : ''
)
+ '</Relative>'
) : ''
)
+
(
options.continuous ?
(
'<Continuous xmlns="http://www.onvif.org/ver10/schema">' +
(
options.continuous.speed ?
(
'<Speed xmlns="http://www.onvif.org/ver10/schema">' + options.continuous.speed + '</Speed>'
) : ''
)
+ '</Continuous>'
) : ''
)
+
'</Focus>' +
'</Move>' +
this._envelopeFooter()
}, function(err, data, xml) {
if (callback) {
callback.call(this, err, err ? null : linerase(data).MoveResponse, xml);
}
}.bind(this));
};
/**
* Stop the ongoing focus movements for a given video source
* @param {Object} options
* @param {string} [options.token=Cam#activeSource.sourceToken] videoSourceToken
* @param callback
*/
Cam.prototype.imagingStop = function(options, callback) {
this._request({
service: 'imaging'
, body: this._envelopeHeader() +
'<Stop xmlns="http://www.onvif.org/ver20/imaging/wsdl" >' +
'<VideoSourceToken xmlns="http://www.onvif.org/ver20/imaging/wsdl" >' +
(options.token || this.activeSource.sourceToken) +
'</VideoSourceToken>' +
'</Stop>' +
this._envelopeFooter()
}, function(err, data, xml) {
if (callback) {
callback.call(this, err, err ? null : linerase(data).StopResponse, xml);
}
}.bind(this));
};
};