init
This commit is contained in:
180
app/_helpers/cameraHelper.js
Normal file
180
app/_helpers/cameraHelper.js
Normal file
@@ -0,0 +1,180 @@
|
||||
/*jshint esversion: 6 */
|
||||
const path = require('path');
|
||||
const http = require('http');
|
||||
const tcpPortUsed =require('tcp-port-used');
|
||||
const db = require(path.resolve(__dirname, './db.js'));
|
||||
const Camera = db.Camera;
|
||||
|
||||
module.exports = {
|
||||
getDeviceModel,
|
||||
checkPortUse,
|
||||
createNewCameraStreamPort
|
||||
};
|
||||
|
||||
async function checkPortUse(port) {
|
||||
return tcpPortUsed.check(port, '127.0.0.1')
|
||||
.then((inuse) => {
|
||||
return inuse;
|
||||
})
|
||||
.catch(err => {
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
async function getDeviceModel(ip) {
|
||||
const options = {
|
||||
hostname: ip,
|
||||
path: '/cgi-bin/param.cgi?get_serial_number',
|
||||
method: 'GET'
|
||||
};
|
||||
return sendCgiReq(options)
|
||||
.then((res) => {
|
||||
const rawData = res.toString().replace(/\n/g, '').toUpperCase();
|
||||
return calcCamModel(rawData, rawData.substring(0, 1), rawData.substring(0, 2))
|
||||
.then(res => {
|
||||
return res;
|
||||
})
|
||||
.catch(err => {
|
||||
throw err;
|
||||
});
|
||||
})
|
||||
.catch(err => {
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
async function calcCamModel(serial, first_letter, twoFirst_letter) {
|
||||
let model = '';
|
||||
// Check 12x
|
||||
if (["1", "A", "B", "C", "D", "N", "O"].includes(first_letter)) {
|
||||
model = "PT12X-";
|
||||
(first_letter === "1") ? model += serial.slice(3, 6) + "-XX-" + serial.slice(8, 10) + checkPoe(serial.slice(10)) : model += newSerialAnsBuilder(serial);
|
||||
}
|
||||
|
||||
// Check 20x
|
||||
if (["2", "E", "F", "G", "H", "P", "Q"].includes(first_letter) && twoFirst_letter !== "PT" ) {
|
||||
model = "PT20X-";
|
||||
(first_letter === "2") ? model += serial.slice(3, 6) + "-XX-" + serial.slice(8, 10) + checkPoe(serial.slice(10)) : model += newSerialAnsBuilder(serial);
|
||||
}
|
||||
|
||||
// Check 30x
|
||||
if (["W", "X", "R", "S"].includes(first_letter)) {
|
||||
model = "PT30X-" + newSerialAnsBuilder(serial);
|
||||
}
|
||||
|
||||
// Check zcams
|
||||
if (["J", "U", "I", "T"].includes(first_letter)) {
|
||||
(["J", "U"].includes(first_letter)) ? model = "PT20X-ZCAM-" : model = "PTVL-ZCAM";
|
||||
}
|
||||
|
||||
if ('PT' == twoFirst_letter) {
|
||||
(serial.slice(0, 4) === "PTVL") ? model = "PTVL-ZCAM-" : model = "PT20X-ZCAM-";
|
||||
}
|
||||
return [model, serial];
|
||||
}
|
||||
|
||||
function newSerialAnsBuilder(serial) {
|
||||
let ans = '';
|
||||
switch(serial.substring(0, 1)) {
|
||||
// 12X
|
||||
case "A":
|
||||
case "B":
|
||||
ans = "SDI-XX-G2" + checkPoe(serial.slice(1));
|
||||
break;
|
||||
|
||||
case "C":
|
||||
case "D":
|
||||
ans = "USB-XX-G2";
|
||||
break;
|
||||
|
||||
case "N":
|
||||
case "O":
|
||||
ans = "SDI-XX-G2 POE";
|
||||
break;
|
||||
|
||||
// 20X
|
||||
case "E":
|
||||
case "F":
|
||||
ans = "SDI-XX-G2" + checkPoe(serial.slice(1));
|
||||
break;
|
||||
|
||||
case "G":
|
||||
case "H":
|
||||
ans = "USB-XX-G2";
|
||||
break;
|
||||
|
||||
case "P":
|
||||
case "Q":
|
||||
ans = "SDI-XX-G2 POE";
|
||||
break;
|
||||
|
||||
// 30X
|
||||
case "W":
|
||||
case "X":
|
||||
ans = "SDI-XX-G2 POE";
|
||||
break;
|
||||
|
||||
case "R":
|
||||
case "S":
|
||||
ans = "NDI-XX-G2";
|
||||
break;
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
||||
function checkPoe (serialNum) {
|
||||
if (serialNum <= "B1025000") {
|
||||
return '';
|
||||
} else if (serialNum >= "B1025001" && serialNum <= "D0129000") {
|
||||
return "-POE";
|
||||
} else if(serialNum >= "D0129001") {
|
||||
return "-POE";
|
||||
}
|
||||
}
|
||||
|
||||
async function createNewCameraStreamPort() {
|
||||
let port = 5000;
|
||||
let cameraStreamPorts;
|
||||
try {
|
||||
// Returns all saved camera stream ports
|
||||
cameraStreamPorts = await currentCameraStreamPorts();
|
||||
} catch(err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
while (cameraStreamPorts.includes(port)) {
|
||||
++port;
|
||||
}
|
||||
return port;
|
||||
}
|
||||
|
||||
async function currentCameraStreamPorts() {
|
||||
return Camera.find().select('streamPort').lean()
|
||||
.then((cameras) => {
|
||||
return cameras.map((camera) => {
|
||||
return camera.streamPort;
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
|
||||
function sendCgiReq(options) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
const req = http.request(options, (res) => {
|
||||
let rawData = '';
|
||||
res.setEncoding('utf8');
|
||||
res.on('data', (chunk) => {
|
||||
rawData += chunk;
|
||||
});
|
||||
res.on('end', () => {
|
||||
resolve(rawData);
|
||||
});
|
||||
});
|
||||
req.on('error', function(err) {
|
||||
reject(err);
|
||||
});
|
||||
req.end();
|
||||
});
|
||||
}
|
11
app/_helpers/db.js
Normal file
11
app/_helpers/db.js
Normal file
@@ -0,0 +1,11 @@
|
||||
/*jshint esversion: 6 */
|
||||
const path = require('path');
|
||||
const config = require(path.resolve(__dirname, '../config.json'));
|
||||
const mongoose = require('mongoose');
|
||||
|
||||
mongoose.connect(config.connectionString, {useNewUrlParser: true });
|
||||
mongoose.Promise = global.Promise;
|
||||
|
||||
module.exports = {
|
||||
Camera: require('../camera/camera.model')
|
||||
};
|
9
app/_helpers/error-handler.js
Normal file
9
app/_helpers/error-handler.js
Normal file
@@ -0,0 +1,9 @@
|
||||
module.exports = errorHandler;
|
||||
|
||||
function errorHandler(err, req, res, next) {
|
||||
console.log(err);
|
||||
if (typeof err === 'string') {
|
||||
return res.status(409).json({message: err});
|
||||
}
|
||||
return res.status(500).json({message: err.message});
|
||||
}
|
85
app/_helpers/ptzHelper.js
Normal file
85
app/_helpers/ptzHelper.js
Normal file
@@ -0,0 +1,85 @@
|
||||
/*jshint esversion: 6 */
|
||||
|
||||
module.exports = {
|
||||
translateDirection,
|
||||
hexStrToNum,
|
||||
numToHexStr,
|
||||
sanitizeSpeed,
|
||||
getCurrentPos
|
||||
};
|
||||
|
||||
function translateDirection(direction) {
|
||||
let hexStr;
|
||||
switch(direction.toLowerCase()) {
|
||||
case "stop":
|
||||
hexStr = "0303FF";
|
||||
break;
|
||||
case "up":
|
||||
hexStr = "0301FF";
|
||||
break;
|
||||
case "down":
|
||||
hexStr = "0302FF";
|
||||
break;
|
||||
case "right":
|
||||
hexStr = "0203FF";
|
||||
break;
|
||||
case "left":
|
||||
hexStr = "0103FF";
|
||||
break;
|
||||
case "upleft":
|
||||
hexStr = "0101FF";
|
||||
break;
|
||||
case "upright":
|
||||
hexStr = "0201FF";
|
||||
break;
|
||||
case "downleft":
|
||||
hexStr = "0102FF";
|
||||
break;
|
||||
case "downright":
|
||||
hexStr = "0202FF";
|
||||
break;
|
||||
default:
|
||||
throw "The direction " + direction + " is not a valid movement direction";
|
||||
}
|
||||
return hexStr;
|
||||
}
|
||||
|
||||
function hexStrToNum(str) {
|
||||
return parseInt(str, 16);
|
||||
}
|
||||
|
||||
function numToHexStr(num) {
|
||||
if (num == 0) {
|
||||
return '00';
|
||||
}
|
||||
|
||||
if (typeof num === 'string') {
|
||||
num = parseInt(num);
|
||||
}
|
||||
|
||||
return num.toString(16).toUpperCase().split('').reduce(function(str, char) {
|
||||
return '0' + char;
|
||||
});
|
||||
}
|
||||
|
||||
function sanitizeSpeed(pan, tilt) {
|
||||
let sanitizedPan, sanitizedTilt;
|
||||
|
||||
if (pan >= 1 && pan <= 18) {
|
||||
sanitizedPan = ("0" + pan).slice(-2);
|
||||
} else {
|
||||
throw 'The pan speed value must be greater than or equal to 1 and less than or equal to 18';
|
||||
}
|
||||
|
||||
if (tilt >= 1 && tilt <= 14) {
|
||||
sanitizedTilt = ("0" + pan).slice(-2);
|
||||
} else {
|
||||
throw 'The tilt speed value must be greater than or equal to 1 and less than or equal to 14';
|
||||
}
|
||||
|
||||
return [sanitizedPan, sanitizedTilt];
|
||||
}
|
||||
|
||||
async function getCurrentPos(id) {
|
||||
return numToHexStr(await socket.sendCmd(id, "81090612FF"));
|
||||
}
|
81
app/_helpers/socket.js
Normal file
81
app/_helpers/socket.js
Normal file
@@ -0,0 +1,81 @@
|
||||
/*jshint esversion: 6 */
|
||||
|
||||
const path = require('path');
|
||||
const db = require(path.resolve(__dirname, '../_helpers/db.js'));
|
||||
const Camera = db.Camera;
|
||||
const net = require('net');
|
||||
|
||||
module.exports = {
|
||||
sendCmd: _sendCmd
|
||||
};
|
||||
|
||||
async function _sendCmd(id, cmd) {
|
||||
const camera = await Camera.findById(id);
|
||||
const buffer = Buffer.from(cmd, 'hex');
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const socket = new net.Socket({allowHalfOpen: true});
|
||||
const conn = net.createConnection(Number(camera.port), camera.ip);
|
||||
conn.setNoDelay();
|
||||
conn.setEncoding('hex');
|
||||
|
||||
conn.on('connect', () => {
|
||||
conn.write(buffer);
|
||||
});
|
||||
|
||||
conn.on('error', (error) => {
|
||||
reject(error);
|
||||
});
|
||||
|
||||
conn.on('data', (buf) => {
|
||||
if (conn.bytesRead >= 3) {
|
||||
conn.end();
|
||||
decode(buf.toString('hex'))
|
||||
.then((res) => {
|
||||
resolve(res);
|
||||
})
|
||||
.catch(err => {
|
||||
reject(err);
|
||||
});
|
||||
} else {
|
||||
reject("Unusual Camera Response: " + buf.toString('hex') + " connection bytes Read: " + conn.bytesRead);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function decode(hexStr) {
|
||||
let decoded = '';
|
||||
switch (hexStr) {
|
||||
case "9041ff":
|
||||
case "9042ff":
|
||||
decoded = "Command Accepted";
|
||||
break;
|
||||
case "9051ff":
|
||||
case "9041ff9051ff":
|
||||
decoded = "Socket1 Cmd Done";
|
||||
break;
|
||||
case "9052ff":
|
||||
case "9042ff9052ff":
|
||||
decoded = "Socket2 Cmd Done";
|
||||
break;
|
||||
case "906002ff":
|
||||
throw "Command Syntax Error";
|
||||
case "906003ff":
|
||||
throw "Command Buffer Full";
|
||||
case "906104ff":
|
||||
throw "Socket1 Cmd Cancelled";
|
||||
case "906204ff":
|
||||
throw "Socket2 Cmd Cancelled";
|
||||
case "906105ff":
|
||||
case "906205ff":
|
||||
throw "No Socket";
|
||||
case "906141ff":
|
||||
throw "Socket1 Cmd Not Executable";
|
||||
case "906241ff":
|
||||
throw "Socket2 Cmd Not Executable";
|
||||
default:
|
||||
throw "Unusual Camera Response: " + hexStr;
|
||||
}
|
||||
return decoded;
|
||||
}
|
Reference in New Issue
Block a user