@arisan/data-api
Version:
The Universal Database API Gateway for CLIO's Modules
392 lines (379 loc) • 14.4 kB
JavaScript
; // eslint-disable-line strict
/* Platform Libraries */
const ObjectID = require('mongodb').ObjectID;
/* Project Libraries */
const BaseHandler = require('./base-handler');
const stripUndefined = require('../Utils').stripUndefined;
const valueOf = require('../Utils').valueOf;
class CameraHandler extends BaseHandler {
constructor(logger, cameras) {
super(logger);
this.cameras = cameras;
this.debug(`${ this.constructor.name } Constructed`);
}
/**
* @param {Object} req
* @param {string} req.body.projectId
* @param {string} req.body.usePublicRtspPort
* @param {Object} res
*/
createCamera(req, res) {
const tag = 'createCamera> ';
this.debug(`${ tag }Body ${ JSON.stringify(req.body, null, 2) }`);
const now = new Date();
const camera = {
project_id: req.body.projectId,
public_address: req.body.publicAddress,
web_port: req.body.webPort,
title: req.body.title,
username: req.body.username,
password: req.body.password,
public_rtsp_port: req.body.publicRtspPort,
use_public_rtsp_port: req.body.usePublicRtspPort,
private_address: req.body.privateAddress,
privateMjpegPort: req.body.privateMjpegPort,
created: now,
updated: now
};
if (!this.checkValidProjectId(camera.project_id)) {
return;
}
if (!this.checkValidPublicAddress(camera.public_address)) {
return;
}
if (!this.checkValidWebPort(camera.web_port)) {
return;
}
this.cameras.insertOne(camera, (insertOneErr, insertOneRes) => {
if (insertOneErr) {
if (insertOneErr.code === 11000) {
this.handleError(res, 409, `${ tag }${ insertOneErr.message }`);
} else {
this.handleError(res, 500, `${ tag }${ insertOneErr.message }`);
}
return;
}
this.info(`${ tag }ID ${ insertOneRes.insertedId } Created`);
res.type('text/plain');
res.status(201).send(new Buffer(`${ insertOneRes.insertedId }`));
});
}
createEvent(req, res) {
const tag = 'createEvent> ';
const cameraId = req.params.cameraId;
const streamIndex = req.params.streamIndex;
this.debug(`${ tag }ID ${ cameraId }/${ streamIndex } Body ${ JSON.stringify(req.body, null, 2) }`);
let objectId;
try {
objectId = new ObjectID(cameraId);
} catch (err) {
this.handleError(res, 400, `${ tag }${ err.message }`);
}
if (!this.checkRequestBodyProperties(req.body, res, tag, `${ cameraId }/${ streamIndex }`, 'type', 'time')) {
return;
}
const diff = {};
diff[`streams.${ streamIndex }.events`] = {
type: req.body.type,
time: parseInt(req.body.time, 10),
status: 'Pending',
videos: []
};
this.cameras.updateOne({ _id: objectId }, { $push: diff }, (updateOneErr, updateOneRes) => {
if (updateOneErr) {
this.handleError(res, 500, `${ tag }${ updateOneErr.message }`);
return;
}
if (!updateOneRes.matchedCount) {
this.handleError(res, 404, `${ tag }ID ${ objectId } Not Found`);
return;
}
this.info(`${ tag }Stream ID ${ cameraId }/${ streamIndex } Updated`);
res.sendStatus(200);
});
}
readCamera(req, res) {
const tag = 'readCamera> ';
const cameraId = req.params.cameraId;
this.debug(`${ tag }ID ${ cameraId }`);
let objectId;
try {
objectId = new ObjectID(cameraId);
} catch (err) {
this.handleError(res, 400, `${ tag }${ err.message }`);
return;
}
this.cameras.findOne({ _id: objectId }, (findOneErr, findOneRes) => {
if (findOneErr) {
this.handleError(res, 500, `${ tag }${ findOneErr.message }`);
return;
}
if (!findOneRes) {
this.handleError(res, 404, `${ tag }ID ${ cameraId } Not Found`);
return;
}
const reply = {
_id: findOneRes._id,
projectId: findOneRes.project_id,
publicAddress: findOneRes.public_address,
webPort: findOneRes.web_port,
title: findOneRes.title,
username: findOneRes.username,
password: findOneRes.password,
publicRtspPort: findOneRes.public_rtsp_port,
usePublicRtspPort: findOneRes.use_public_rtsp_port,
privateAddress: findOneRes.private_address,
privateMjpegPort: findOneRes.private_mjpeg_port,
publicIp: req.body.public_ip,
analysisStatus: req.body.analysis_status,
checkStatus: req.body.check_status,
created: findOneRes.created,
updated: findOneRes.updated
};
if (findOneRes.streams) {
reply.streams = {};
for (let i = 0; i < Object.keys(findOneRes.streams).length; i++) {
const streamIndex = Object.keys(findOneRes.streams)[i];
reply.streams[streamIndex] = {
rtspUrl: findOneRes.streams[streamIndex].rtsp_url,
availablePlans: findOneRes.streams[streamIndex].available_plans,
intendedPlan: findOneRes.streams[streamIndex].intended_plan,
currentPlan: findOneRes.streams[streamIndex].current_plan,
archiveStatus: findOneRes.streams[streamIndex].archive_status,
setStatus: findOneRes.streams[streamIndex].set_status
};
}
}
if (findOneRes.audio) {
reply.audio = {
encoding: findOneRes.audio.encoding,
bitRate: findOneRes.audio.bit_rate,
sampleRate: findOneRes.audio.sample_rate
};
}
this.info(`${ tag }ID ${ findOneRes._id } reply ${ JSON.stringify(reply, null, 2) }`);
res.status(200).send(reply);
});
}
readEventInfo(req, res) {
const tag = 'readEventInfo> ';
const cameraId = req.params.cameraId;
const streamIndex = req.params.streamIndex;
this.debug(`${ tag }ID ${ cameraId }/${ streamIndex }`);
let objectId;
try {
objectId = new ObjectID(cameraId);
} catch (err) {
this.handleError(res, 400, `${ tag }${ err.message }`);
return;
}
this.cameras.findOne({ _id: objectId }, (findOneErr, findOneRes) => {
if (findOneErr) {
this.handleError(res, 500, `${ tag }${ findOneErr.message }`);
return;
}
const rtspUrl = valueOf(findOneRes, 'streams', streamIndex, 'rtsp_url');
if (!rtspUrl) {
this.handleError(res, 404, `${ tag }ID ${ cameraId }/${ streamIndex } RTSP URL Not Found`);
return;
}
this.debug(`${ tag } rtspUrl ${ rtspUrl }`);
// const plan = valueOf(findOneRes, 'streams', streamIndex, 'selected_plan');
// if (!plan) {
// this.handleError(res, 404, `${tag}ID ${cameraId}/${streamIndex} Plan Not Found`);
// return;
// }
// this.debug(`${tag} plan ${plan}`);
// const frameRateRef = parseInt(plan.substring(plan.indexOf('f') + 1, plan.indexOf('b')), 10);
// const frameRateRef = valueOf(findOneRes, 'streams', streamIndex, 'rate_control', 'frame_rate_limit');
// const gopSizeRef = parseInt(plan.substring(plan.indexOf('g') + 1), 10);
// const gopSizeRef = valueOf(findOneRes, 'streams', streamIndex, 'h264', 'gov_length');
// if (!frameRateRef) {
// this.handleError(res, 404, `${tag}ID ${cameraId}/${streamIndex} Frame Rate Not Found`);
// return;
// }
// if (!gopSizeRef) {
// this.handleError(res, 404, `${tag}ID ${cameraId}/${streamIndex} GOV Length Not Found`);
// return;
// }
const reply = {
rtspUrl,
httpUrl: `http://${ findOneRes.username }:${ findOneRes.password }@` + `${ findOneRes.public_address }:${ findOneRes.web_port }`,
idleTime: 120000
};
this.info(`${ tag }ID ${ cameraId }/${ streamIndex } reply ${ JSON.stringify(reply, null, 2) }`);
res.status(200).send(reply);
});
}
updateCamera(req, res) {
const tag = 'updateCamera> ';
const cameraId = req.params.cameraId;
this.debug(`${ tag }ID ${ cameraId } Body ${ JSON.stringify(req.body, null, 2) }`);
let objectId;
try {
objectId = new ObjectID(cameraId);
} catch (err) {
this.handleError(res, 400, `${ tag }${ err.message }`);
return;
}
if (Object.keys(req.body).length === 0) {
this.handleError(res, 400, `${ tag }ID ${ cameraId } No Body`);
return;
}
let diff = {
project_id: req.body.projectId,
public_address: req.body.publicAddress,
web_port: req.body.webPort,
title: req.body.title,
username: req.body.username,
password: req.body.password,
public_rtsp_port: req.body.publicRtspPort,
use_public_rtsp_port: req.body.usePublicRtspPort,
private_address: req.body.privateAddress,
private_mjpeg_port: req.body.privateMjpegPort,
public_ip: req.body.publicIp,
analysis_status: req.body.analysisStatus,
check_status: req.body.checkStatus,
updated: new Date()
};
if (req.body.streams) {
Object.keys(req.body.streams).forEach(streamIndex => {
const stream = req.body.streams[streamIndex];
diff[`streams.${ streamIndex }.rtsp_url`] = stream.rtspUrl;
diff[`streams.${ streamIndex }.available_plans`] = stream.availablePlans;
diff[`streams.${ streamIndex }.intended_plan`] = stream.intendedPlan;
diff[`streams.${ streamIndex }.current_plan`] = stream.currentPlan;
diff[`streams.${ streamIndex }.archive_status`] = stream.archiveStatus;
diff[`streams.${ streamIndex }.set_status`] = stream.setStatus;
});
}
if (req.body.audio) {
diff['audio.encoding'] = req.body.audio.encoding;
diff['audio.bit_rate'] = req.body.audio.bitRate;
diff['audio.sample_rate'] = req.body.audio.sampleRate;
}
diff = stripUndefined(diff);
this.cameras.updateOne({ _id: objectId }, { $set: diff }, (updateOneErr, updateOneRes) => {
if (updateOneErr) {
this.handleError(res, 500, `${ tag }${ updateOneErr.message }`);
return;
}
if (!updateOneRes.matchedCount) {
this.handleError(res, 404, `${ tag }ID ${ cameraId } Not Found`);
return;
}
this.info(`${ tag }ID ${ cameraId } Updated`);
res.sendStatus(200);
});
}
updateStreamStatus(req, res) {
const tag = 'updateStreamStatus> ';
const cameraId = req.params.cameraId;
const streamIndex = req.params.streamIndex;
this.debug(`${ tag }ID ${ cameraId }/${ streamIndex } Body ${ JSON.stringify(req.body, null, 2) }`);
let objectId;
try {
objectId = new ObjectID(cameraId);
} catch (err) {
this.handleError(res, 400, `${ tag }${ err.message }`);
return;
}
if (!this.checkRequestBodyProperties(req.body, res, tag, cameraId, 'recorderId', 'status', 'module')) {
return;
}
const now = new Date();
const diff = {};
diff[`streams.${ streamIndex }.status.${ req.body.module }`] = {
$each: [{
message: req.body.status,
recorderId: req.body.recorderId,
updated: now
}],
$slice: 1000
};
this.cameras.updateOne({ _id: objectId }, { $push: diff }, (updateOneErr, updateOneRes) => {
if (updateOneErr) {
this.handleError(res, 500, `${ tag }${ updateOneErr.message }`);
return;
}
if (!updateOneRes.matchedCount) {
this.handleError(res, 404, `${ tag }ID ${ cameraId } Not Found`);
return;
}
this.info(`${ tag }ID ${ cameraId }/${ streamIndex } Status ${ req.body.status } Updated`);
res.sendStatus(200);
});
}
updateEventStatus(req, res) {
const tag = 'updateEventStatus> ';
const cameraId = req.params.cameraId;
const streamIndex = req.params.streamIndex;
this.debug(`${ tag }ID ${ cameraId }/${ streamIndex } Body ${ JSON.stringify(req.body, null, 2) }`);
let objectId;
try {
objectId = new ObjectID(cameraId);
} catch (err) {
this.handleError(res, 400, `${ tag }${ err.message }`);
return;
}
if (!this.checkRequestBodyProperties(req.body, res, tag, `${ cameraId }/${ streamIndex }`, 'status')) {
return;
}
const now = new Date();
const diff = {};
diff[`streams.${ streamIndex }.status.event`] = {
message: req.body.status,
updated: now
};
this.cameras.updateOne({ _id: objectId }, { $push: diff }, (updateOneErr, updateOneRes) => {
if (updateOneErr) {
this.handleError(res, 500, `${ tag }${ updateOneErr.message }`);
return;
}
if (!updateOneRes.matchedCount) {
this.handleError(res, 404, `${ tag }ID ${ cameraId } Not Found`);
return;
}
this.info(`${ tag }ID ${ cameraId }/${ streamIndex } Status ${ req.body.status } Updated`);
res.sendStatus(200);
});
}
updateEventVideoInfo(req, res) {
const tag = 'updateEventVideoInfo> ';
const cameraId = req.params.cameraId;
const streamIndex = req.params.streamIndex;
const time = req.query.time;
this.debug(`${ tag }ID ${ cameraId }${ streamIndex } time ${ time } ` + `Body ${ JSON.stringify(req.body, null, 2) }`);
let objectId;
try {
objectId = new ObjectID(cameraId);
} catch (err) {
this.handleError(res, 400, `${ tag }${ err.message }`);
return;
}
if (!this.checkRequestBodyProperties(req.body, res, tag, `${ cameraId }/${ streamIndex }`, 'videoInfo')) {
return;
}
const query = { _id: objectId };
query[`streams.${ streamIndex }.events.time`] = parseInt(time, 10);
this.debug(`${ tag }query ${ JSON.stringify(query, null, 2) }`);
const diff = {};
diff[`streams.${ streamIndex }.events.\$.videos`] = [req.body.videoInfo];
this.debug(`${ tag }diff ${ JSON.stringify(diff, null, 2) }`);
this.cameras.updateOne(query, { $set: diff }, (updateOneErr, updateOneRes) => {
if (updateOneErr) {
this.handleError(res, 500, `${ tag }${ updateOneErr.message }`);
return;
}
this.debug(`${ tag }updateOneRes ${ JSON.stringify(updateOneRes, null, 2) }`);
if (!updateOneRes.matchedCount) {
this.handleError(res, 404, `${ tag }ID ${ cameraId } Not Found`);
return;
}
this.info(`${ tag }ID ${ cameraId }/${ streamIndex } Video Info ${ time } Updated`);
res.sendStatus(200);
});
}
}
module.exports = CameraHandler;
//# sourceMappingURL=camera-handler.js.map