UNPKG

@arisan/data-api

Version:

The Universal Database API Gateway for CLIO's Modules

265 lines (253 loc) 9.71 kB
'use strict'; // eslint-disable-line strict /* Platform Libraries */ const ipaddr = require('ipaddr.js'); const ObjectID = require('mongodb').ObjectID; /* Project Libraries */ const BaseHandler = require('./base-handler'); const valueOf = require('../Utils').valueOf; const CLIO_HEARTBEAT_INTERVAL = process.env.CLIO_HEARTBEAT_INTERVAL; class RecorderHandler extends BaseHandler { constructor(logger, recorders, cameras) { super(logger); this.recorders = recorders; this.cameras = cameras; this.debug(`${ this.constructor.name } Constructed`); } /** * @param {Object} req * @param {string} req.body.publicIp * @param {string} req.ip * @param {Object} res */ createRecorder(req, res) { const tag = 'createRecorder> '; this.debug(`${ tag }Body ${ JSON.stringify(req.body, null, 2) }`); const now = new Date(); const recorder = { public_ip: req.body.publicIp, private_ip: ipaddr.process(req.ip).toString(), port: req.body.port, module: req.body.module, created: now, updated: now }; if (!this.checkValidPublicIp(recorder.public_ip)) { return; } if (!this.checkValidPort(recorder.port)) { return; } if (recorder.module !== 'broker' && recorder.module !== 'archive' && recorder.module !== 'live' && recorder.module !== 'event') { this.handleError(res, 400, `${ tag }Invalid Module Name ${ recorder.module }`); return; } this.recorders.insertOne(recorder, (insertOneErr, insertOneRes) => { if (insertOneErr) { 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 }`)); }); } readArchiveRecorderInfo(req, res) { const tag = 'readArchiveRecorderInfo> '; const cameraId = req.params.cameraId; const streamIndex = req.params.streamIndex; this.debug(`${ tag }Stream ${ cameraId }/${ streamIndex }`); const validDate = new Date(Date.now() - (CLIO_HEARTBEAT_INTERVAL + 3) * 1000); this.recorders.findOne({ module: 'archive', updated: { $gt: validDate } }, { sort: { cpu_load: 1 } }, (findOneErr, findOneRes) => { if (findOneErr) { this.handleError(res, 500, `${ tag }${ findOneErr.message }`); return; } if (!findOneRes) { this.handleError(res, 404, `${ tag }Archive Recorder Not Available`); return; } const reply = { host: findOneRes.private_ip, port: parseInt(findOneRes.port, 10) }; this.info(`${ tag }Stream ${ cameraId }/${ streamIndex } ` + `Reply ${ JSON.stringify(reply, null, 2) }`); res.status(200).send(reply); }); } readLiveRecorderInfo(req, res) { const tag = 'readLiveRecorderInfo> '; const cameraId = req.params.cameraId; const streamIndex = req.params.streamIndex; this.debug(`${ tag }Stream ${ cameraId }/${ streamIndex }`); const validDate = new Date(Date.now() - (CLIO_HEARTBEAT_INTERVAL + 3) * 1000); this.recorders.findOne({ module: 'live', updated: { $gt: validDate } }, { sort: { cpu_load: 1 } }, (findOneErr, findOneRes) => { if (findOneErr) { this.handleError(res, 500, `${ tag }${ findOneErr.message }`); return; } if (!findOneRes) { this.handleError(res, 404, `${ tag }Live Recorder Not Available`); return; } const reply = { host: findOneRes.private_ip, port: parseInt(findOneRes.port, 10) }; this.info(`${ tag }Stream ${ cameraId }/${ streamIndex } ` + `Reply ${ JSON.stringify(reply, null, 2) }`); res.status(200).send(reply); }); } readEventRecorderInfo(req, res) { const tag = 'readEventRecorderInfo> '; const cameraId = req.params.cameraId; const streamIndex = req.params.streamIndex; this.debug(`${ tag }Stream ${ cameraId }/${ streamIndex }`); const validDate = new Date(Date.now() - (CLIO_HEARTBEAT_INTERVAL + 3) * 1000); this.recorders.findOne({ module: 'event', updated: { $gt: validDate } }, { sort: { cpu_load: 1 } }, (findOneErr, findOneRes) => { if (findOneErr) { this.handleError(res, 500, `${ tag }${ findOneErr.message }`); return; } if (!findOneRes) { this.handleError(res, 404, `${ tag }Event Recorder Not Available`); return; } const reply = { host: findOneRes.private_ip, port: parseInt(findOneRes.port, 10) }; this.info(`${ tag }Stream ${ cameraId }/${ streamIndex } ` + `Reply ${ JSON.stringify(reply, null, 2) }`); res.status(200).send(reply); }); } readEventBrokerInfo(req, res) { const tag = 'readEventBrokerInfo> '; const cameraId = req.params.cameraId; const streamIndex = req.params.streamIndex; this.debug(`${ tag }Stream ${ cameraId }/${ streamIndex }`); let objectId; try { objectId = new ObjectID(cameraId); } catch (err) { this.handleError(res, 400, `${ tag }${ err.message }`); return; } this.cameras.findOne({ _id: objectId }, (findCameraErr, findCameraRes) => { if (findCameraErr) { this.handleError(res, 500, `${ tag }${ findCameraErr.message }`); return; } if (!findCameraRes) { this.handleError(res, 404, `${ tag }ID ${ cameraId }/${ streamIndex } Not Found`); return; } let triggeredStreams = valueOf(findCameraRes, 'streams', streamIndex, 'triggered_streams'); this.debug(JSON.stringify(triggeredStreams, null, 2)); if (!triggeredStreams) { triggeredStreams = []; } const validDate = new Date(Date.now() - (CLIO_HEARTBEAT_INTERVAL + 3) * 1000); const reply = { recorderInfo: [] }; triggeredStreams.forEach((triggeredStream, index, array) => { this.debug(JSON.stringify(triggeredStream, null, 2)); const triggeredCameraId = triggeredStream.camera_id; const triggeredStreamIndex = triggeredStream.stream_index; const triggeredStreamId = `${ triggeredCameraId }/${ triggeredStreamIndex }`; this.recorders.findOne({ module: 'broker', updated: { $gt: validDate } }, { sort: { cpu_load: 1 } }, (findBrokerErr, findBrokerRes) => { if (findBrokerErr) { this.error(`${ tag }ID ${ triggeredStreamId } ${ findBrokerErr.message }`); return; } this.debug(`${ tag } Before push ${ JSON.stringify(reply, null, 2) }`); reply.recorderInfo.push({ host: findBrokerRes.private_ip, port: findBrokerRes.port, cameraId: triggeredCameraId, streamIndex: triggeredStreamIndex }); this.debug(`${ tag } After push ${ JSON.stringify(reply, null, 2) }`); if (index === array.length - 1) { this.info(`${ tag }Stream ${ cameraId }/${ streamIndex } ` + `Reply ${ JSON.stringify(reply, null, 2) }`); res.status(200).send(reply); } }); }); }); } /** * @param {Object} req * @param {string} req.params.recorderId * @param {Object[]} req.streamInfos * @param {boolean} req.streamInfos.archiveStarted; * @param {boolean} req.streamInfos.liveStarted; * @param {boolean} req.streamInfos.eventStarted; * @param {number} req.cpuUsagePercentage * @param {number} req.memoryUsagePercentage * @param {number} req.hddUsageKB * @param {number} req.hddTotalKB * @param {number} req.netUploadBytesPerSecond * @param {number} req.netDownloadBytesPerSecond * @param {Object} res */ updateRecorder(req, res) { const tag = 'updateRecorder> '; const recorderId = req.params.recorderId; this.debug(`${ tag }ID ${ recorderId } Body ${ JSON.stringify(req.body, null, 2) }`); let objectId; try { objectId = new ObjectID(recorderId); } catch (err) { this.handleError(res, 400, `${ tag }${ err.message }`); return; } if (!this.checkRequestBodyProperties(req.body, res, tag, recorderId, 'cpuUsagePercentage', 'memoryUsagePercentage', 'hddUsageKB', 'hddTotalKB', 'netUploadBytesPerSecond', 'netDownloadBytesPerSecond')) { return; } const diff = { stream_infos: [], updated: new Date() }; if (req.body.streamInfos) { for (let i = 0; i < req.body.streamInfos.length; i++) { const streamInfo = req.body.streamInfos[i]; diff.stream_infos.push({ id: streamInfo.id, archive: streamInfo.archiveStarted, live: streamInfo.liveStarted, event: streamInfo.eventStarted }); } } diff.cpu_load = Math.ceil(req.body.cpuUsagePercentage * 100); diff.mem_load = Math.ceil(req.body.memoryUsagePercentage); diff.hdd_load = Math.ceil(req.body.hddUsageKB * 100 / req.body.hddTotalKB); diff.upload_kbps = Math.ceil(req.body.netUploadBytesPerSecond * 8 / 1024); diff.download_kbps = Math.ceil(req.body.netDownloadBytesPerSecond * 8 / 1024); this.recorders.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 ${ recorderId } Not Found`); return; } this.info(`${ tag }ID ${ objectId } Updated`); res.sendStatus(200); }); } } module.exports = RecorderHandler; //# sourceMappingURL=recorder-handler.js.map