179 lines
7.2 KiB
JavaScript
179 lines
7.2 KiB
JavaScript
var os = require('os');
|
|
var exec = require('child_process').exec;
|
|
const onvif = require("shinobi-onvif");
|
|
const {
|
|
addCredentialsToUrl,
|
|
} = require('../common.js')
|
|
module.exports = function(s,config,lang,app,io){
|
|
const {
|
|
createSnapshot,
|
|
addCredentialsToStreamLink,
|
|
} = require('../monitor/utils.js')(s,config,lang)
|
|
const createOnvifDevice = async (onvifAuth) => {
|
|
var response = {ok: false}
|
|
const monitorConfig = s.group[onvifAuth.ke].rawMonitorConfigurations[onvifAuth.id]
|
|
const controlBaseUrl = monitorConfig.details.control_base_url || s.buildMonitorUrl(monitorConfig, true)
|
|
const controlURLOptions = s.cameraControlOptionsFromUrl(controlBaseUrl,monitorConfig)
|
|
//create onvif connection
|
|
const device = new onvif.OnvifDevice({
|
|
address : controlURLOptions.host + ':' + controlURLOptions.port,
|
|
user : controlURLOptions.username,
|
|
pass : controlURLOptions.password
|
|
})
|
|
s.group[onvifAuth.ke].activeMonitors[onvifAuth.id].onvifConnection = device
|
|
try{
|
|
const info = await device.init()
|
|
response.ok = true
|
|
response.device = device
|
|
}catch(err){
|
|
response.msg = 'Device responded with an error'
|
|
response.error = err
|
|
}
|
|
return response
|
|
}
|
|
const replaceDynamicInOptions = (Camera,options) => {
|
|
const newOptions = {}
|
|
Object.keys(options).forEach((key) => {
|
|
const value = options[key]
|
|
if(typeof value === 'string'){
|
|
newOptions[key] = value.replace(/__CURRENT_TOKEN/g,Camera.current_profile ? Camera.current_profile.token : 'NOTOKEN')
|
|
}else if(value !== undefined && value !== null){
|
|
newOptions[key] = value
|
|
}
|
|
})
|
|
return newOptions
|
|
}
|
|
const runOnvifMethod = async (onvifOptions,callback) => {
|
|
var onvifAuth = onvifOptions.auth
|
|
var response = {ok: false}
|
|
var errorMessage = function(msg,error){
|
|
response.ok = false
|
|
response.msg = msg
|
|
response.error = error
|
|
callback(response)
|
|
}
|
|
var actionCallback = function(onvifActionResponse){
|
|
response.ok = true
|
|
if(onvifActionResponse.data){
|
|
response.responseFromDevice = onvifActionResponse.data
|
|
}else{
|
|
response.responseFromDevice = onvifActionResponse
|
|
}
|
|
if(onvifActionResponse.soap)response.soap = onvifActionResponse.soap
|
|
callback(response)
|
|
}
|
|
var isEmpty = function(obj) {
|
|
for(var key in obj) {
|
|
if(obj.hasOwnProperty(key))
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
var doAction = function(Camera){
|
|
var completeAction = function(command){
|
|
if(command && command.then){
|
|
command.then(actionCallback).catch(function(error){
|
|
errorMessage('Device Action responded with an error',error)
|
|
})
|
|
}else if(command){
|
|
response.ok = true
|
|
response.repsonseFromDevice = command
|
|
callback(response)
|
|
}else{
|
|
response.error = 'Big Errors, Please report it to Shinobi Development'
|
|
callback(response)
|
|
}
|
|
}
|
|
var action
|
|
if(onvifAuth.service){
|
|
if(Camera.services[onvifAuth.service] === undefined){
|
|
return errorMessage('This is not an available service. Please use one of the following : '+Object.keys(Camera.services).join(', '))
|
|
}
|
|
if(Camera.services[onvifAuth.service] === null){
|
|
return errorMessage('This service is not activated. Maybe you are not connected through ONVIF. You can test by attempting to use the "Control" feature with ONVIF in Shinobi.')
|
|
}
|
|
action = Camera.services[onvifAuth.service][onvifAuth.action]
|
|
}else{
|
|
action = Camera[onvifAuth.action]
|
|
}
|
|
if(!action || typeof action !== 'function'){
|
|
errorMessage(onvifAuth.action+' is not an available ONVIF function. See https://github.com/futomi/node-onvif for functions.')
|
|
}else{
|
|
var argNames = s.getFunctionParamNames(action)
|
|
var options
|
|
var command
|
|
if(argNames[0] === 'options' || argNames[0] === 'params'){
|
|
options = replaceDynamicInOptions(Camera,onvifOptions.options || {})
|
|
response.options = options
|
|
}
|
|
if(onvifAuth.service){
|
|
command = Camera.services[onvifAuth.service][onvifAuth.action](options)
|
|
}else{
|
|
command = Camera[onvifAuth.action](options)
|
|
}
|
|
completeAction(command)
|
|
}
|
|
}
|
|
if(!s.group[onvifAuth.ke].activeMonitors[onvifAuth.id].onvifConnection){
|
|
const response = await createOnvifDevice(onvifAuth)
|
|
if(response.ok){
|
|
doAction(response.device)
|
|
}else{
|
|
errorMessage(response.msg,response.error)
|
|
}
|
|
}else{
|
|
doAction(s.group[onvifAuth.ke].activeMonitors[onvifAuth.id].onvifConnection)
|
|
}
|
|
}
|
|
async function getSnapshotFromOnvif(onvifOptions){
|
|
let theUrl;
|
|
if(onvifOptions.mid && onvifOptions.ke){
|
|
const groupKey = onvifOptions.ke
|
|
const monitorId = onvifOptions.mid
|
|
const theDevice = s.group[groupKey].activeMonitors[monitorId].onvifConnection
|
|
theUrl = addCredentialsToUrl({
|
|
username: onvifOptions.username,
|
|
password: onvifOptions.password,
|
|
url: (await theDevice.services.media.getSnapshotUri({
|
|
ProfileToken : theDevice.current_profile.token,
|
|
})).GetSnapshotUriResponse.MediaUri.Uri
|
|
});
|
|
}else{
|
|
theUrl = addCredentialsToStreamLink({
|
|
username: onvifOptions.username,
|
|
password: onvifOptions.password,
|
|
url: onvifOptions.uri
|
|
})
|
|
}
|
|
return await createSnapshot({
|
|
output: ['-s 400x400'],
|
|
url: theUrl,
|
|
})
|
|
}
|
|
/**
|
|
* API : ONVIF Method Controller
|
|
*/
|
|
app.all([
|
|
config.webPaths.apiPrefix+':auth/onvif/:ke/:id/:action',
|
|
config.webPaths.apiPrefix+':auth/onvif/:ke/:id/:service/:action'
|
|
],function (req,res){
|
|
s.auth(req.params,function(user){
|
|
const options = s.getPostData(req,'options',true) || s.getPostData(req,'params',true)
|
|
runOnvifMethod({
|
|
auth: {
|
|
ke: req.params.ke,
|
|
id: req.params.id,
|
|
action: req.params.action,
|
|
service: req.params.service,
|
|
},
|
|
options: options,
|
|
},(endData) => {
|
|
s.closeJsonResponse(res,endData)
|
|
})
|
|
},res,req);
|
|
})
|
|
s.getSnapshotFromOnvif = getSnapshotFromOnvif
|
|
s.createOnvifDevice = createOnvifDevice
|
|
s.runOnvifMethod = runOnvifMethod
|
|
}
|