UNPKG

node-gotapi-plugin-onvif

Version:

This module is an ONVIF Plug-In for the node-gotapi.

239 lines (222 loc) 7.46 kB
/* ------------------------------------------------------------------ * node-gotapi - node-gotapi-plugin-onvif/index.js * * Copyright (c) 2017, Futomi Hatano, All rights reserved. * Released under the MIT license * Date: 2017-01-12 * ---------------------------------------------------------------- */ 'use strict'; /* ------------------------------------------------------------------ * Constructor * The name of the constructor must be add the prefix `GotapiPlugin`. * ---------------------------------------------------------------- */ let GotapiPlugin = function(util) { this.util = util; this.info = { name: 'ONVIF Network Camera', services: [] }; this.onvif = require('node-onvif'); this.devices = {}; this.last_request_time = 0; this.service_tmpl = { serviceId : 'com.github.futomi.onvif', name : 'ONVIF Network Camera', online : true, scopes : ['onvif'], manufacturer: '', version : '0.0.5', type : '' }; }; /* ------------------------------------------------------------------ * Method: init(callback) * This method initializes this module, called when the GotAPI * Server loads this module. * ---------------------------------------------------------------- */ GotapiPlugin.prototype.init = function(callback) { this.util.init(this.info); this.util.onservicediscoverry = this._serviceDiscovery.bind(this); this.util.onmessage = this._receiveMessage.bind(this); this._startDiscoveryBackground(); callback(this.info); }; GotapiPlugin.prototype._startDiscoveryBackground = function() { let now = Date.now(); let t = 60000 - (now - this.last_request_time); if(t > 0) { setTimeout(this._startDiscoveryBackground.bind(this), t); return; } let devices = {}; this.onvif.startDiscovery((info) => { let service = JSON.parse(JSON.stringify(this.service_tmpl)); service.serviceId = service.serviceId + '.' + info.urn; service.name = info.name; devices[service.serviceId] = { discovery : info, // The information from the service discovery information: null, // The information from the getInformation command onvifDevice: null, // The OnvifDevice object of the node-onvif service : service }; }); setTimeout(() => { this.devices = devices; this.onvif.stopDiscovery(() => { let service_list = []; for(let id in this.devices) { service_list.push(this.devices[id]['service']); } this.info.services = service_list; }); setTimeout(this._startDiscoveryBackground.bind(this), 60000); }, 5000); }; GotapiPlugin.prototype._serviceDiscovery = function(message) { message['services'] = JSON.parse(JSON.stringify(this.info.services)); this.util.returnServiceDiscovery(message); }; GotapiPlugin.prototype._receiveMessage = function(message) { if(message.profile === 'onvif') { if(message.attribute === 'userAuth') { this.userAuth(message); } else if(message.attribute === 'fetchSnapshot') { this.fetchSnapshot(message); } else if(message.attribute === 'ptzMove') { this.ptzMove(message); } else if(message.attribute === 'ptzStop') { this.ptzStop(message); } else if(message.attribute === 'ptzGotoHome') { this.ptzGotoHome(message); } else { this.returnError(message['requestCode'], 501, 'The specified attribute `' + message.attribute + '` is unknown.'); } this.last_request_time = Date.now(); } else { this.returnError(message['requestCode'], 501, 'The specified profile `' + message.profile + '` is unknown.'); } }; GotapiPlugin.prototype.userAuth = function(message) { let sid = message['params']['serviceId']; let dev = this.devices[sid]; if(!dev) { this.returnError(message['requestCode'], 404, 'The specified serviceId is not found.'); return; } let user = message['params']['user']; let pass = message['params']['pass']; dev['onvifDevice'] = new this.onvif.OnvifDevice({ xaddr: dev['discovery']['xaddrs'][0], user : user, pass : pass }); dev['onvifDevice'].init((e) => { if(e) { this.returnError(message['requestCode'], 401, 'The specified NVT denied the user.'); } else { dev['information'] = dev['onvifDevice'].getInformation(); this.returnSuccess(message['requestCode'], JSON.parse(JSON.stringify(dev['information']))); } }); }; GotapiPlugin.prototype.fetchSnapshot = function(message) { let sid = message['params']['serviceId']; let dev = this.devices[sid]; if(!dev) { this.returnError(message['requestCode'], 404, 'The specified serviceId is not found.'); return; } dev['onvifDevice'].fetchSnapshot((e, res) => { if(e) { this.returnError(message['requestCode'], 401, 'The specified NVT denied the user.'); } else { let ct = res['headers']['content-type']; let buffer = res['body']; let b64 = buffer.toString('base64'); let uri = 'data:' + ct + ';base64,' + b64; this.returnSuccess(message['requestCode'], uri); } }); }; GotapiPlugin.prototype.ptzMove = function(message) { let sid = message['params']['serviceId']; let dev = this.devices[sid]; if(!dev) { this.returnError(message['requestCode'], 404, 'The specified serviceId is not found.'); return; } let speed = {x: 0, y: 0, z: 0}; ['x', 'y', 'z'].forEach((k) => { let v = message['params'][k]; if(typeof(v) === 'string' && v.match(/^[\d\.\-]+$/)) { speed[k] = parseFloat(v); } }); let p = { speed: speed, timeout: 30 }; dev['onvifDevice'].ptzMove(p, (e) => { if(e) { this.returnError(message['requestCode'], 401, 'The specified NVT denied the user.'); } else { this.returnSuccess(message['requestCode'], null); } }); }; GotapiPlugin.prototype.ptzStop = function(message) { let sid = message['params']['serviceId']; let dev = this.devices[sid]; if(!dev) { this.returnError(message['requestCode'], 404, 'The specified serviceId is not found.'); return; } dev['onvifDevice'].ptzStop((e) => { if(e) { this.returnError(message['requestCode'], 401, 'The specified NVT denied the user.'); } else { this.returnSuccess(message['requestCode'], null); } }); }; GotapiPlugin.prototype.ptzGotoHome = function(message) { let sid = message['params']['serviceId']; let dev = this.devices[sid]; if(!dev) { this.returnError(message['requestCode'], 404, 'The specified serviceId is not found.'); return; } let ptz = dev['onvifDevice'].services.ptz; if(!ptz) { this.returnError(message['requestCode'], 501, 'The specified NVT does not support PTZ.'); return; } let profile = dev['onvifDevice'].getCurrentProfile(); let params = { 'ProfileToken': profile['token'], 'Speed' : 1 }; ptz.gotoHomePosition(params, (e, res) => { if(e) { this.returnError(message['requestCode'], 401, 'The specified NVT denied the user.'); } else if(res) { this.returnSuccess(message['requestCode'], null); } }); }; GotapiPlugin.prototype.returnSuccess = function(request_code, data) { this.util.returnMessage({ requestCode : request_code, result : 0, data : data }); }; GotapiPlugin.prototype.returnError = function(request_code, result, error_message) { this.util.returnMessage({ requestCode : request_code, result : result, data : null, errorMessage : error_message }); }; module.exports = GotapiPlugin;