Refactor Monitor Launch Sequence
parent
4b2a82f77c
commit
638b0076ad
|
@ -60,6 +60,13 @@ module.exports = {
|
|||
},timeoutInSeconds * 1000 || 1000)
|
||||
},queueItemsRunningInParallel || 3)
|
||||
},
|
||||
createQueueAwaited: (timeoutInSeconds, queueItemsRunningInParallel) => {
|
||||
return async.queue(function(action, callback) {
|
||||
setTimeout(function(){
|
||||
action().then(callback)
|
||||
},timeoutInSeconds * 1000 || 1000)
|
||||
},queueItemsRunningInParallel || 3)
|
||||
},
|
||||
copyObject: (obj) => {
|
||||
return Object.assign({},obj)
|
||||
},
|
||||
|
|
|
@ -413,6 +413,41 @@ module.exports = function(s,config,lang){
|
|||
setHomePositionTimeout(event)
|
||||
}
|
||||
}
|
||||
function setHomePositionPreset(e){
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
setPresetForCurrentPosition({
|
||||
ke: e.ke,
|
||||
id: monitorId
|
||||
},(endData) => {
|
||||
if(endData.ok === false){
|
||||
setTimeout(() => {
|
||||
setPresetForCurrentPosition({
|
||||
ke: e.ke,
|
||||
id: monitorId
|
||||
},(endData) => {
|
||||
if(endData.ok === false){
|
||||
setTimeout(() => {
|
||||
setPresetForCurrentPosition({
|
||||
ke: e.ke,
|
||||
id: monitorId
|
||||
},(endData) => {
|
||||
console.log(endData)
|
||||
resolve()
|
||||
})
|
||||
},5000)
|
||||
}else{
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
},5000)
|
||||
}else{
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
},5000)
|
||||
})
|
||||
}
|
||||
return {
|
||||
startMove,
|
||||
stopMove,
|
||||
|
@ -421,5 +456,6 @@ module.exports = function(s,config,lang){
|
|||
setPresetForCurrentPosition,
|
||||
moveToPresetPosition,
|
||||
moveCameraPtzToMatrix,
|
||||
setHomePositionPreset,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -230,7 +230,7 @@ module.exports = function(s,config,lang,app,io){
|
|||
var firstDroppedPart = pathPieces[2]
|
||||
var monitorEventDropDir = s.dir.dropInEvents + ke + '/' + mid + '/'
|
||||
var deleteKey = monitorEventDropDir + firstDroppedPart
|
||||
onFileOrFolderFound(monitorEventDropDir + firstDroppedPart,deleteKey,Object.assign(s.group[ke].rawMonitorConfigurations[mid],{}))
|
||||
onFileOrFolderFound(monitorEventDropDir + firstDroppedPart,deleteKey,Object.assign({},s.group[ke].rawMonitorConfigurations[mid]))
|
||||
})
|
||||
resolve({root: s.dir.dropInEvents + user.ke})
|
||||
}else{
|
||||
|
|
121
libs/ffmpeg.js
121
libs/ffmpeg.js
|
@ -44,64 +44,73 @@ module.exports = async (s,config,lang,onFinish) => {
|
|||
buildTimelapseOutput(e),
|
||||
];
|
||||
if(allOutputs.filter(output => !!output).length > 0){
|
||||
([
|
||||
buildMainInput(e),
|
||||
]).concat(allOutputs).forEach(function(commandStringPart){
|
||||
ffmpegCommand.push(commandStringPart)
|
||||
})
|
||||
s.onFfmpegCameraStringCreationExtensions.forEach(function(extender){
|
||||
extender(e,ffmpegCommand)
|
||||
})
|
||||
const stdioPipes = createPipeArray(e)
|
||||
const ffmpegCommandString = ffmpegCommand.join(' ')
|
||||
//hold ffmpeg command for log stream
|
||||
activeMonitor.ffmpeg = sanitizedFfmpegCommand(e,ffmpegCommandString)
|
||||
//clean the string of spatial impurities and split for spawn()
|
||||
const ffmpegCommandParsed = splitForFFPMEG(ffmpegCommandString)
|
||||
try{
|
||||
fs.rmSync(e.sdir + 'cmd.txt')
|
||||
}catch(err){
|
||||
return new Promise((resolve) => {
|
||||
try{
|
||||
([
|
||||
buildMainInput(e),
|
||||
]).concat(allOutputs).forEach(function(commandStringPart){
|
||||
ffmpegCommand.push(commandStringPart)
|
||||
})
|
||||
s.onFfmpegCameraStringCreationExtensions.forEach(function(extender){
|
||||
extender(e,ffmpegCommand)
|
||||
})
|
||||
const stdioPipes = createPipeArray(e)
|
||||
const ffmpegCommandString = ffmpegCommand.join(' ')
|
||||
//hold ffmpeg command for log stream
|
||||
activeMonitor.ffmpeg = sanitizedFfmpegCommand(e,ffmpegCommandString)
|
||||
//clean the string of spatial impurities and split for spawn()
|
||||
const ffmpegCommandParsed = splitForFFPMEG(ffmpegCommandString)
|
||||
try{
|
||||
fs.rmSync(e.sdir + 'cmd.txt')
|
||||
}catch(err){
|
||||
|
||||
}
|
||||
fs.writeFileSync(e.sdir + 'cmd.txt',JSON.stringify({
|
||||
dataPortToken: dataPortToken,
|
||||
cmd: ffmpegCommandParsed,
|
||||
pipes: stdioPipes.length,
|
||||
rawMonitorConfig: s.group[e.ke].rawMonitorConfigurations[e.id],
|
||||
globalInfo: {
|
||||
config: config,
|
||||
isAtleatOneDetectorPluginConnected: s.isAtleatOneDetectorPluginConnected
|
||||
}
|
||||
},null,3),'utf8')
|
||||
var cameraCommandParams = [
|
||||
config.monitorDaemonPath ? config.monitorDaemonPath : __dirname + '/cameraThread/singleCamera.js',
|
||||
config.ffmpegDir,
|
||||
e.sdir + 'cmd.txt'
|
||||
]
|
||||
const cameraProcess = spawn('node',cameraCommandParams,{detached: true,stdio: stdioPipes})
|
||||
if(config.debugLog === true && config.debugLogMonitors === true){
|
||||
cameraProcess.stderr.on('data',(data) => {
|
||||
const string = data.toString()
|
||||
var checkLog = function(x){return string.indexOf(x)>-1}
|
||||
switch(true){
|
||||
case checkLog('pkt->duration = 0'):
|
||||
case checkLog('[hls @'):
|
||||
case checkLog('Past duration'):
|
||||
case checkLog('Last message repeated'):
|
||||
case checkLog('Non-monotonous DTS'):
|
||||
case checkLog('NULL @'):
|
||||
case checkLog('RTP: missed'):
|
||||
case checkLog('deprecated pixel format used'):
|
||||
if(!config.debugLogMonitorsVerbose){
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
console.log(`${e.ke} ${e.name} (${e.mid})`)
|
||||
console.log(data.toString())
|
||||
})
|
||||
}
|
||||
return cameraProcess
|
||||
fs.writeFileSync(e.sdir + 'cmd.txt',JSON.stringify({
|
||||
dataPortToken: dataPortToken,
|
||||
cmd: ffmpegCommandParsed,
|
||||
pipes: stdioPipes.length,
|
||||
rawMonitorConfig: s.group[e.ke].rawMonitorConfigurations[e.id],
|
||||
globalInfo: {
|
||||
config: config,
|
||||
isAtleatOneDetectorPluginConnected: s.isAtleatOneDetectorPluginConnected
|
||||
}
|
||||
},null,3),'utf8')
|
||||
var cameraCommandParams = [
|
||||
config.monitorDaemonPath ? config.monitorDaemonPath : __dirname + '/cameraThread/singleCamera.js',
|
||||
config.ffmpegDir,
|
||||
e.sdir + 'cmd.txt'
|
||||
]
|
||||
const cameraProcess = spawn('node',cameraCommandParams,{detached: true,stdio: stdioPipes})
|
||||
if(config.debugLog === true && config.debugLogMonitors === true){
|
||||
cameraProcess.stderr.on('data',(data) => {
|
||||
const string = data.toString()
|
||||
var checkLog = function(x){return string.indexOf(x)>-1}
|
||||
switch(true){
|
||||
case checkLog('pkt->duration = 0'):
|
||||
case checkLog('[hls @'):
|
||||
case checkLog('Past duration'):
|
||||
case checkLog('Last message repeated'):
|
||||
case checkLog('Non-monotonous DTS'):
|
||||
case checkLog('NULL @'):
|
||||
case checkLog('RTP: missed'):
|
||||
case checkLog('deprecated pixel format used'):
|
||||
if(!config.debugLogMonitorsVerbose){
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
console.log(`${e.ke} ${e.name} (${e.mid})`)
|
||||
console.log(data.toString())
|
||||
})
|
||||
}
|
||||
cameraProcess.stdio[5].once('data',(data) => {
|
||||
resolve(cameraProcess)
|
||||
})
|
||||
}catch(err){
|
||||
s.systemLog(err)
|
||||
return null
|
||||
}
|
||||
})
|
||||
}else{
|
||||
return null
|
||||
}
|
||||
|
|
1344
libs/monitor.js
1344
libs/monitor.js
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -76,7 +76,7 @@ module.exports = function(s,config,lang,io){
|
|||
}
|
||||
}
|
||||
if(checkedAdminUsers[monitor.ke]){
|
||||
setTimeout(function(){
|
||||
setTimeout(async function(){
|
||||
if(!orphanedVideosForMonitors[monitor.ke])orphanedVideosForMonitors[monitor.ke] = {}
|
||||
if(!orphanedVideosForMonitors[monitor.ke][monitor.mid])orphanedVideosForMonitors[monitor.ke][monitor.mid] = 0
|
||||
s.initiateMonitorObject(monitor)
|
||||
|
@ -88,7 +88,8 @@ module.exports = function(s,config,lang,io){
|
|||
code: 5
|
||||
});
|
||||
const monObj = Object.assign({},monitor,{id : monitor.mid})
|
||||
s.camera(monitor.mode,monObj)
|
||||
await s.camera('stop',monObj);
|
||||
await s.camera(monitor.mode,monObj);
|
||||
checkAnother()
|
||||
},1000)
|
||||
}else{
|
||||
|
|
26
libs/user.js
26
libs/user.js
|
@ -3,6 +3,7 @@ var events = require('events');
|
|||
var spawn = require('child_process').spawn;
|
||||
var exec = require('child_process').exec;
|
||||
var async = require("async");
|
||||
const { createQueueAwaited } = require('./common.js')
|
||||
module.exports = function(s,config,lang){
|
||||
const {
|
||||
deleteSetOfVideos,
|
||||
|
@ -128,22 +129,25 @@ module.exports = function(s,config,lang){
|
|||
if(!s.group[e.ke].init){
|
||||
s.group[e.ke].init={}
|
||||
}
|
||||
if(!s.group[e.ke].addStorageUse){s.group[e.ke].addStorageUse={}};
|
||||
if(!s.group[e.ke].fileBin){s.group[e.ke].fileBin={}};
|
||||
if(!s.group[e.ke].users){s.group[e.ke].users={}}
|
||||
if(!s.group[e.ke].dashcamUsers){s.group[e.ke].dashcamUsers={}}
|
||||
if(!s.group[e.ke].sizePurgeQueue){s.group[e.ke].sizePurgeQueue=[]}
|
||||
if(!s.group[e.ke].addStorageUse){s.group[e.ke].addStorageUse = {}}
|
||||
const theGroup = s.group[e.ke]
|
||||
if(!theGroup.addStorageUse){theGroup.addStorageUse={}};
|
||||
if(!theGroup.fileBin){theGroup.fileBin={}};
|
||||
if(!theGroup.users){theGroup.users={}}
|
||||
if(!theGroup.dashcamUsers){theGroup.dashcamUsers={}}
|
||||
if(!theGroup.sizePurgeQueue){theGroup.sizePurgeQueue=[]}
|
||||
if(!theGroup.addStorageUse){theGroup.addStorageUse = {}}
|
||||
if(!e.limit||e.limit===''){e.limit=10000}else{e.limit=parseFloat(e.limit)}
|
||||
//save global space limit for group key (mb)
|
||||
s.group[e.ke].sizeLimit = e.limit || s.group[e.ke].sizeLimit || 10000
|
||||
s.group[e.ke].sizeLimitVideoPercent = parseFloat(s.group[e.ke].init.size_video_percent) || 90
|
||||
s.group[e.ke].sizeLimitTimelapseFramesPercent = parseFloat(s.group[e.ke].init.size_timelapse_percent) || 5
|
||||
s.group[e.ke].sizeLimitFileBinPercent = parseFloat(s.group[e.ke].init.size_filebin_percent) || 5
|
||||
theGroup.sizeLimit = e.limit || theGroup.sizeLimit || 10000
|
||||
theGroup.sizeLimitVideoPercent = parseFloat(theGroup.init.size_video_percent) || 90
|
||||
theGroup.sizeLimitTimelapseFramesPercent = parseFloat(theGroup.init.size_timelapse_percent) || 5
|
||||
theGroup.sizeLimitFileBinPercent = parseFloat(theGroup.init.size_filebin_percent) || 5
|
||||
//save global used space as megabyte value
|
||||
s.group[e.ke].usedSpace = s.group[e.ke].usedSpace || ((e.size || 0) / 1048576)
|
||||
theGroup.usedSpace = theGroup.usedSpace || ((e.size || 0) / 1048576)
|
||||
//emit the changes to connected users
|
||||
s.sendDiskUsedAmountToClients(e.ke)
|
||||
// create monitor management queue
|
||||
theGroup.startMonitorInQueue = createQueueAwaited(0.5, 1)
|
||||
}
|
||||
s.loadGroupApps = function(e){
|
||||
// e = user
|
||||
|
|
|
@ -1231,7 +1231,7 @@ module.exports = function(s,config,lang,app,io){
|
|||
['mid','=',req.params.id],
|
||||
],
|
||||
limit: 1
|
||||
},(err,r) => {
|
||||
},async (err,r) => {
|
||||
if(r && r[0]){
|
||||
r = r[0];
|
||||
if(req.query.reset==='1'||(s.group[r.ke]&&s.group[r.ke].rawMonitorConfigurations[r.mid].mode!==req.params.f)||req.query.fps&&(!s.group[r.ke].activeMonitors[r.mid].currentState||!s.group[r.ke].activeMonitors[r.mid].currentState.trigger_on)){
|
||||
|
@ -1261,7 +1261,7 @@ module.exports = function(s,config,lang,app,io){
|
|||
s.group[r.ke].rawMonitorConfigurations[r.mid]=r;
|
||||
s.tx({f:'monitor_edit',mid:r.mid,ke:r.ke,mon:r},'GRP_'+r.ke);
|
||||
s.tx({f:'monitor_edit',mid:r.mid,ke:r.ke,mon:r},'STR_'+r.ke);
|
||||
s.camera('stop',s.cleanMonitorObject(r));
|
||||
await s.camera('stop',s.cleanMonitorObject(r));
|
||||
if(req.params.f!=='stop'){
|
||||
s.camera(req.params.f,s.cleanMonitorObject(r));
|
||||
}
|
||||
|
@ -1288,7 +1288,7 @@ module.exports = function(s,config,lang,app,io){
|
|||
req.timeout=req.params.ff*1000
|
||||
break;
|
||||
}
|
||||
s.group[r.ke].activeMonitors[r.mid].trigger_timer=setTimeout(function(){
|
||||
s.group[r.ke].activeMonitors[r.mid].trigger_timer=setTimeout(async function(){
|
||||
delete(s.group[r.ke].activeMonitors[r.mid].trigger_timer)
|
||||
s.knexQuery({
|
||||
action: "update",
|
||||
|
@ -1304,12 +1304,11 @@ module.exports = function(s,config,lang,app,io){
|
|||
r.neglectTriggerTimer=1;
|
||||
r.mode=s.group[r.ke].activeMonitors[r.mid].currentState.mode;
|
||||
r.fps=s.group[r.ke].activeMonitors[r.mid].currentState.fps;
|
||||
s.camera('stop',s.cleanMonitorObject(r),function(){
|
||||
if(s.group[r.ke].activeMonitors[r.mid].currentState.mode!=='stop'){
|
||||
s.camera(s.group[r.ke].activeMonitors[r.mid].currentState.mode,s.cleanMonitorObject(r));
|
||||
}
|
||||
s.group[r.ke].rawMonitorConfigurations[r.mid]=r;
|
||||
});
|
||||
await s.camera('stop',s.cleanMonitorObject(r));
|
||||
if(s.group[r.ke].activeMonitors[r.mid].currentState.mode!=='stop'){
|
||||
s.camera(s.group[r.ke].activeMonitors[r.mid].currentState.mode,s.cleanMonitorObject(r));
|
||||
}
|
||||
s.group[r.ke].rawMonitorConfigurations[r.mid]=r;
|
||||
s.tx({f:'monitor_edit',mid:r.mid,ke:r.ke,mon:r},'GRP_'+r.ke);
|
||||
s.tx({f:'monitor_edit',mid:r.mid,ke:r.ke,mon:r},'STR_'+r.ke);
|
||||
},req.timeout);
|
||||
|
|
|
@ -69,7 +69,7 @@ module.exports = function(s,config,lang,app){
|
|||
define: s.getDefinitonFile(user.details ? user.details.lang : config.lang),
|
||||
lang: lang,
|
||||
$user: $user,
|
||||
mon: Object.assign(s.group[req.params.ke].rawMonitorConfigurations[req.params.id],{}),
|
||||
mon: Object.assign({},s.group[req.params.ke].rawMonitorConfigurations[req.params.id]),
|
||||
originalURL: s.getOriginalUrl(req)
|
||||
});
|
||||
}else{
|
||||
|
|
|
@ -757,6 +757,10 @@ monitorEditorWindow.on('change','[detail="auto_host"]',function(e){
|
|||
}
|
||||
})
|
||||
editorForm.submit(function(e){
|
||||
function setSubmitButton(text,icon,toggle){
|
||||
var submitButtons = editorForm.find('[type="submit"]').prop('disabled',toggle)
|
||||
submitButtons.html(`<i class="fa fa-${icon}"></i> ${text}`)
|
||||
}
|
||||
e.preventDefault();
|
||||
var validation = getMonitorEditFormFields()
|
||||
if(!validation.ok){
|
||||
|
@ -765,6 +769,7 @@ editorForm.submit(function(e){
|
|||
new PNotify({title:'Configuration Invalid',text:errorsFound.join('<br>'),type:'error'});
|
||||
}
|
||||
var monitorConfig = validation.monitorConfig
|
||||
setSubmitButton(lang[`Please Wait...`], `spinner fa-pulse`, true)
|
||||
$.post(getApiPrefix()+'/configureMonitor/'+$user.ke+'/'+monitorConfig.mid,{data:JSON.stringify(monitorConfig)},function(d){
|
||||
if(d.ok === false){
|
||||
new PNotify({
|
||||
|
@ -774,6 +779,7 @@ editorForm.submit(function(e){
|
|||
})
|
||||
}
|
||||
debugLog(d)
|
||||
setSubmitButton(lang.Save, `check`, false)
|
||||
})
|
||||
//
|
||||
if(copySettingsSelector.val() === '1'){
|
||||
|
|
Loading…
Reference in New Issue