Merge branch 'dev' into 'master'
Swirl of Shamshir : Critical Fixes See merge request Shinobi-Systems/Shinobi!437fix-multi-trigger
commit
f2c6578b82
|
@ -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)
|
||||
},
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
module.exports = function(s){
|
||||
const configLocation = process.argv[2]
|
||||
const superLocation = process.argv[3]
|
||||
s.location = {
|
||||
super : s.mainDirectory+'/super.json',
|
||||
super : superLocation && superLocation.endsWith('.json') ? superLocation : s.mainDirectory+'/super.json',
|
||||
config : configLocation && configLocation.endsWith('.json') ? configLocation : s.mainDirectory+'/conf.json',
|
||||
languages : s.mainDirectory+'/languages'
|
||||
}
|
||||
|
|
|
@ -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{
|
||||
|
|
136
libs/ffmpeg.js
136
libs/ffmpeg.js
|
@ -44,64 +44,86 @@ 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){
|
||||
|
||||
}
|
||||
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;
|
||||
return new Promise((resolve) => {
|
||||
var hasResolved = false
|
||||
var completionTimer = null;
|
||||
function completeResolve(data){
|
||||
clearTimeout(completionTimer)
|
||||
if(!hasResolved){
|
||||
hasResolved = true
|
||||
resolve(data)
|
||||
}
|
||||
console.log(`${e.ke} ${e.name} (${e.mid})`)
|
||||
console.log(data.toString())
|
||||
})
|
||||
}
|
||||
return cameraProcess
|
||||
}
|
||||
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())
|
||||
})
|
||||
}
|
||||
cameraProcess.stdio[5].once('data',(data) => {
|
||||
completeResolve(cameraProcess)
|
||||
})
|
||||
completionTimer = setTimeout(() => {
|
||||
completeResolve(cameraProcess)
|
||||
},20000)
|
||||
}catch(err){
|
||||
completeResolve(null)
|
||||
s.systemLog(err)
|
||||
return null
|
||||
}
|
||||
})
|
||||
}else{
|
||||
return null
|
||||
}
|
||||
|
|
|
@ -760,9 +760,10 @@ module.exports = (s,config,lang) => {
|
|||
const videoFlags = []
|
||||
const inputMap = buildInputMap(e,e.details.input_map_choices.record_timelapse)
|
||||
const { videoWidth, videoHeight } = validateDimensions(e.details.record_timelapse_scale_x,e.details.record_timelapse_scale_y)
|
||||
const creationFps = (1 / (!isNaN(parseFloat(e.details.record_timelapse_fps)) ? parseFloat(e.details.record_timelapse_fps) : 900)).toFixed(3);
|
||||
if(videoWidth && videoHeight)videoFlags.push(`-s ${videoWidth}x${videoHeight}`)
|
||||
if(inputMap)videoFlags.push(inputMap)
|
||||
videoFilters.push(`fps=${(1 / (!isNaN(parseFloat(e.details.record_timelapse_fps)) ? parseFloat(e.details.record_timelapse_fps) : 900)).toFixed(3)}`)
|
||||
videoFilters.push(`fps=${creationFps}`)
|
||||
if(e.details.record_timelapse_vf)videoFilters.push(e.details.record_timelapse_vf)
|
||||
if(e.details.record_timelapse_watermark === "1" && e.details.record_timelapse_watermark_location){
|
||||
videoFilters.push(buildWatermarkFiltersFromConfiguration('record_timelapse_',e))
|
||||
|
|
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
|
@ -80,10 +80,12 @@ module.exports = function(s,config,lang,getSnapshot){
|
|||
} : undefined)
|
||||
.then(res => res.text())
|
||||
.then((text) => {
|
||||
console.error(`Webhook Response`,text)
|
||||
response.response = text;
|
||||
resolve(response)
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(`Webhook Fail`)
|
||||
response.ok = false;
|
||||
response.error = err;
|
||||
s.userLog({
|
||||
|
@ -104,23 +106,15 @@ module.exports = function(s,config,lang,getSnapshot){
|
|||
const onEventTriggerForGlobalWebhook = async (d,filter) => {
|
||||
let filesSent = 0;
|
||||
const monitorConfig = s.group[d.ke].rawMonitorConfigurations[d.id]
|
||||
// d = event object
|
||||
if((filter.global_webhook || monitorConfig.details.notify_global_webhook === '1') && !s.group[d.ke].activeMonitors[d.id].detector_global_webhook){
|
||||
var detector_global_webhook_timeout
|
||||
if(!monitorConfig.details.detector_global_webhook_timeout||monitorConfig.details.detector_global_webhook_timeout===''){
|
||||
detector_global_webhook_timeout = 1000 * 60 * 10;
|
||||
}else{
|
||||
detector_global_webhook_timeout = parseFloat(monitorConfig.details.detector_global_webhook_timeout) * 1000 * 60;
|
||||
}
|
||||
s.group[d.ke].activeMonitors[d.id].detector_global_webhook = setTimeout(function(){
|
||||
clearTimeout(s.group[d.ke].activeMonitors[d.id].detector_global_webhook);
|
||||
s.group[d.ke].activeMonitors[d.id].detector_global_webhook = null
|
||||
},detector_global_webhook_timeout)
|
||||
if((filter.global_webhook || monitorConfig.details.notify_global_webhook === '1')){
|
||||
await getSnapshot(d,monitorConfig)
|
||||
if(d.screenshotBuffer){
|
||||
sendMessage({
|
||||
title: lang.Event+' - '+d.screenshotName,
|
||||
description: lang.EventText1+' '+d.currentTimestamp,
|
||||
ke: d.ke,
|
||||
mid: d.id,
|
||||
eventDetails: d.details
|
||||
},[
|
||||
{
|
||||
type: 'photo',
|
||||
|
@ -134,6 +128,8 @@ module.exports = function(s,config,lang,getSnapshot){
|
|||
sendMessage({
|
||||
title: lang.Event,
|
||||
description: lang.EventText1+' '+d.currentTimestamp,
|
||||
ke: d.ke,
|
||||
mid: d.id,
|
||||
eventDetails: d.details
|
||||
},[],d.ke)
|
||||
}
|
||||
|
@ -197,13 +193,12 @@ module.exports = function(s,config,lang,getSnapshot){
|
|||
"value": "1"
|
||||
}
|
||||
]
|
||||
},
|
||||
)
|
||||
}
|
||||
);
|
||||
s.definitions["Account Settings"].blocks["2-Factor Authentication"].info.push({
|
||||
"name": "detail=factor_global_webhook",
|
||||
"field": lang.Webhook,
|
||||
"default": "1",
|
||||
"example": "",
|
||||
"fieldType": "select",
|
||||
"possible": [
|
||||
{
|
||||
|
@ -215,7 +210,7 @@ module.exports = function(s,config,lang,getSnapshot){
|
|||
"value": "1"
|
||||
}
|
||||
]
|
||||
})
|
||||
});
|
||||
s.definitions["Account Settings"].blocks["Webhook"] = {
|
||||
"evaluation": "$user.details.use_global_webhook !== '0'",
|
||||
"name": lang.Webhook,
|
||||
|
@ -245,45 +240,27 @@ module.exports = function(s,config,lang,getSnapshot){
|
|||
"placeholder": "http://your-webhook-point/onEvent/{{INNER_EVENT_TITLE}}?info={{INNER_EVENT_INFO}}",
|
||||
"field": lang["Webhook URL"],
|
||||
"form-group-class":"u_global_webhook_input u_global_webhook_1",
|
||||
},
|
||||
{
|
||||
hidden: true,
|
||||
"name": "detail=factor_global_webhook",
|
||||
"field": lang["2-Factor Authentication"],
|
||||
"form-group-class":"u_global_webhook_input u_global_webhook_1",
|
||||
"default": "1",
|
||||
"example": "",
|
||||
"fieldType": "select",
|
||||
"possible": [
|
||||
{
|
||||
"name": lang.No,
|
||||
"value": "0"
|
||||
},
|
||||
{
|
||||
"name": lang.Yes,
|
||||
"value": "1"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
s.definitions["Event Filters"].blocks["Action for Selected"].info.push({
|
||||
"name": "actions=global_webhook",
|
||||
"field": lang['Webhook'],
|
||||
"fieldType": "select",
|
||||
"form-group-class": "actions-row",
|
||||
"default": "",
|
||||
"example": "1",
|
||||
"possible": [
|
||||
{
|
||||
"name": lang['Original Choice'],
|
||||
"value": "",
|
||||
"selected": true
|
||||
},
|
||||
{
|
||||
"name": lang.Yes,
|
||||
"value": "1",
|
||||
}
|
||||
]
|
||||
})
|
||||
"name": "actions=global_webhook",
|
||||
"field": lang['Webhook'],
|
||||
"fieldType": "select",
|
||||
"form-group-class": "actions-row",
|
||||
"default": "",
|
||||
"example": "1",
|
||||
"possible": [
|
||||
{
|
||||
"name": lang['Original Choice'],
|
||||
"value": "",
|
||||
"selected": true
|
||||
},
|
||||
{
|
||||
"name": lang.Yes,
|
||||
"value": "1",
|
||||
}
|
||||
]
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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{
|
||||
|
@ -171,7 +172,7 @@ module.exports = function(s,config,lang,io){
|
|||
var addStorageData = {
|
||||
files: [],
|
||||
videos: [],
|
||||
timelapeFrames: [],
|
||||
timelapseFrames: [],
|
||||
}
|
||||
if(videos && videos[0]){
|
||||
videos.forEach(function(video){
|
||||
|
@ -189,7 +190,7 @@ module.exports = function(s,config,lang,io){
|
|||
if(!frame.details.dir){
|
||||
usedSpaceTimelapseFrames += frame.size
|
||||
}else{
|
||||
addStorageData.timelapeFrames.push(frame)
|
||||
addStorageData.timelapseFrames.push(frame)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -314,6 +315,8 @@ module.exports = function(s,config,lang,io){
|
|||
storageIndex.path = path
|
||||
storageIndex.usedSpace = 0
|
||||
storageIndex.sizeLimit = parseFloat(storageData.limit) || parseFloat(userDetails.size) || 10000
|
||||
storageIndex.videoPercent = parseFloat(storageData.videoPercent) || parseFloat(userDetails.size_video_percent) || 95
|
||||
storageIndex.timelapsePercent = parseFloat(storageData.timelapsePercent) || parseFloat(userDetails.size_timelapse_percent) || 5
|
||||
var usedSpaceVideos = 0
|
||||
var usedSpaceTimelapseFrames = 0
|
||||
var usedSpaceFilebin = 0
|
||||
|
@ -326,7 +329,7 @@ module.exports = function(s,config,lang,io){
|
|||
}
|
||||
if(timelapseFrames && timelapseFrames[0]){
|
||||
timelapseFrames.forEach(function(frame){
|
||||
if(video.details.dir === storage.value){
|
||||
if(frame.details.dir === storage.value){
|
||||
usedSpaceTimelapseFrames += frame.size
|
||||
}
|
||||
})
|
||||
|
|
|
@ -65,12 +65,25 @@ module.exports = function(s,config,lang,app,io){
|
|||
}
|
||||
}
|
||||
s.insertTimelapseFrameDatabaseRow = function(e,queryInfo,filePath){
|
||||
const groupKey = e.ke
|
||||
const theGroup = s.group[groupKey]
|
||||
const frameDetails = Object.assign({},s.parseJSON(queryInfo.details) || {})
|
||||
const storageId = e.details.dir
|
||||
const storageIndex = theGroup.addStorageUse[storageId]
|
||||
const fileSize = queryInfo.size / 1048576
|
||||
s.knexQuery({
|
||||
action: "insert",
|
||||
table: "Timelapse Frames",
|
||||
insert: queryInfo
|
||||
})
|
||||
s.setDiskUsedForGroup(e.ke,queryInfo.size / 1048576,'timelapeFrames')
|
||||
if(storageIndex){
|
||||
s.setDiskUsedForGroupAddStorage(groupKey,{
|
||||
size: fileSize,
|
||||
storageIndex: storageIndex
|
||||
},'timelapseFrames')
|
||||
}else{
|
||||
s.setDiskUsedForGroup(groupKey, fileSize, 'timelapseFrames')
|
||||
}
|
||||
s.purgeDiskForGroup(e.ke)
|
||||
s.onInsertTimelapseFrameExtensions.forEach(function(extender){
|
||||
extender(e,queryInfo,filePath)
|
||||
|
@ -149,7 +162,7 @@ module.exports = function(s,config,lang,app,io){
|
|||
where: frameSelector,
|
||||
limit: 1
|
||||
},async function(){
|
||||
s.setDiskUsedForGroup(e.ke,-(r.size / 1048576),'timelapeFrames')
|
||||
s.setDiskUsedForGroup(e.ke,-(r.size / 1048576),'timelapseFrames')
|
||||
s.file('delete',e.fileLocation)
|
||||
const fileDirectory = getFileDirectory(folderPath);
|
||||
const folderIsEmpty = (await fs.promises.readdir(folderPath)).filter(file => file.indexOf('.jpg') > -1).length === 0;
|
||||
|
|
60
libs/user.js
60
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,
|
||||
|
@ -11,6 +12,7 @@ module.exports = function(s,config,lang){
|
|||
deleteAddStorageVideos,
|
||||
deleteMainVideos,
|
||||
deleteTimelapseFrames,
|
||||
deleteAddStorageTimelapseFrames,
|
||||
deleteFileBinFiles,
|
||||
deleteCloudVideos,
|
||||
deleteCloudTimelapseFrames,
|
||||
|
@ -29,13 +31,16 @@ module.exports = function(s,config,lang){
|
|||
deleteMainVideos(groupKey,() => {
|
||||
s.debugLog(`${groupKey} deleteTimelapseFrames`)
|
||||
deleteTimelapseFrames(groupKey,() => {
|
||||
s.debugLog(`${groupKey} deleteFileBinFiles`)
|
||||
deleteFileBinFiles(groupKey,() => {
|
||||
s.debugLog(`${groupKey} deleteAddStorageVideos`)
|
||||
deleteAddStorageVideos(groupKey,() => {
|
||||
s.group[groupKey].sizePurging = false
|
||||
s.sendDiskUsedAmountToClients(groupKey)
|
||||
callback();
|
||||
s.debugLog(`${groupKey} deleteAddStorageTimelapseFrames`)
|
||||
deleteAddStorageTimelapseFrames(groupKey,() => {
|
||||
s.debugLog(`${groupKey} deleteFileBinFiles`)
|
||||
deleteFileBinFiles(groupKey,() => {
|
||||
s.debugLog(`${groupKey} deleteAddStorageVideos`)
|
||||
deleteAddStorageVideos(groupKey,() => {
|
||||
s.group[groupKey].sizePurging = false
|
||||
s.sendDiskUsedAmountToClients(groupKey)
|
||||
callback();
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -128,22 +133,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
|
||||
|
@ -186,7 +194,7 @@ module.exports = function(s,config,lang){
|
|||
//change global size value
|
||||
cloudDisk.usedSpace = cloudDisk.usedSpace + amount
|
||||
switch(storagePoint){
|
||||
case'timelapeFrames':
|
||||
case'timelapseFrames':
|
||||
cloudDisk.usedSpaceTimelapseFrames += amount
|
||||
break;
|
||||
case'fileBin':
|
||||
|
@ -221,7 +229,7 @@ module.exports = function(s,config,lang){
|
|||
s.group[e.ke].usedSpace += currentChange
|
||||
s.group[e.ke].usedSpace = s.group[e.ke].usedSpace < 0 ? 0 : s.group[e.ke].usedSpace
|
||||
switch(storageType){
|
||||
case'timelapeFrames':
|
||||
case'timelapseFrames':
|
||||
s.group[e.ke].usedSpaceTimelapseFrames += currentChange
|
||||
s.group[e.ke].usedSpaceTimelapseFrames = s.group[e.ke].usedSpaceTimelapseFrames < 0 ? 0 : s.group[e.ke].usedSpaceTimelapseFrames
|
||||
break;
|
||||
|
@ -252,7 +260,7 @@ module.exports = function(s,config,lang){
|
|||
//change global size value
|
||||
storageIndex.usedSpace += currentSize
|
||||
switch(storageType){
|
||||
case'timelapeFrames':
|
||||
case'timelapseFrames':
|
||||
storageIndex.usedSpaceTimelapseFrames += currentSize
|
||||
break;
|
||||
case'fileBin':
|
||||
|
@ -338,6 +346,7 @@ module.exports = function(s,config,lang){
|
|||
if(details.size){formDetails.size = details.size;}
|
||||
if(details.days){formDetails.days = details.days;}
|
||||
}
|
||||
const theGroup = s.group[d.ke]
|
||||
var newSize = parseFloat(formDetails.size) || 10000
|
||||
//load addStorageUse
|
||||
var currentStorageNumber = 0
|
||||
|
@ -361,11 +370,10 @@ module.exports = function(s,config,lang){
|
|||
storageIndex.name = storage.name
|
||||
storageIndex.path = path
|
||||
storageIndex.usedSpace = storageIndex.usedSpace || 0
|
||||
if(detailsContainerAddStorage && detailsContainerAddStorage[path] && detailsContainerAddStorage[path].limit){
|
||||
storageIndex.sizeLimit = parseFloat(detailsContainerAddStorage[path].limit)
|
||||
}else{
|
||||
storageIndex.sizeLimit = newSize
|
||||
}
|
||||
const storageInfoToSave = detailsContainerAddStorage && detailsContainerAddStorage[path] ? detailsContainerAddStorage[path] : {}
|
||||
storageIndex.sizeLimit = parseFloat(storageInfoToSave.limit) || newSize
|
||||
storageIndex.videoPercent = parseFloat(storageInfoToSave.videoPercent) || theGroup.sizeLimitVideoPercent
|
||||
storageIndex.timelapsePercent = parseFloat(storageInfoToSave.timelapsePercent) || theGroup.sizeLimitTimelapseFramesPercent
|
||||
}
|
||||
readStorageArray()
|
||||
///
|
||||
|
|
|
@ -92,13 +92,6 @@ module.exports = (s,config,lang) => {
|
|||
whereGroup.push(queryGroup)
|
||||
fs.rm(fileLocationMid,function(err){
|
||||
++completedCheck
|
||||
if(err){
|
||||
fs.stat(fileLocationMid,function(err){
|
||||
if(!err){
|
||||
fs.unlink(fileLocationMid)
|
||||
}
|
||||
})
|
||||
}
|
||||
const whereGroupLength = whereGroup.length
|
||||
if(whereGroupLength > 0 && whereGroupLength === completedCheck){
|
||||
whereQuery[1] = whereGroup
|
||||
|
@ -115,9 +108,9 @@ module.exports = (s,config,lang) => {
|
|||
s.setDiskUsedForGroupAddStorage(groupKey,{
|
||||
size: -(frame.size/1048576),
|
||||
storageIndex: storageIndex
|
||||
},'timelapeFrames')
|
||||
},'timelapseFrames')
|
||||
}else{
|
||||
s.setDiskUsedForGroup(groupKey,-(frame.size/1048576),'timelapeFrames')
|
||||
s.setDiskUsedForGroup(groupKey,-(frame.size/1048576),'timelapseFrames')
|
||||
}
|
||||
// s.tx({
|
||||
// f: 'timelapse_frame_delete',
|
||||
|
@ -193,7 +186,8 @@ module.exports = (s,config,lang) => {
|
|||
return deleteAddStorageVideos(groupKey,callback)
|
||||
}
|
||||
var currentStorageNumber = 0
|
||||
var readStorageArray = function(){
|
||||
function readStorageArray(){
|
||||
const theGroup = s.group[groupKey]
|
||||
setTimeout(function(){
|
||||
reRunCheck = readStorageArray
|
||||
var storage = s.listOfStorage[currentStorageNumber]
|
||||
|
@ -203,14 +197,15 @@ module.exports = (s,config,lang) => {
|
|||
return
|
||||
}
|
||||
var storageId = storage.value
|
||||
if(storageId === '' || !s.group[groupKey].addStorageUse[storageId]){
|
||||
if(storageId === '' || !theGroup.addStorageUse[storageId]){
|
||||
++currentStorageNumber
|
||||
readStorageArray()
|
||||
return
|
||||
}
|
||||
var storageIndex = s.group[groupKey].addStorageUse[storageId]
|
||||
var storageIndex = theGroup.addStorageUse[storageId]
|
||||
//run purge command
|
||||
if(storageIndex.usedSpace > (storageIndex.sizeLimit * (storageIndex.deleteOffset || config.cron.deleteOverMaxOffset))){
|
||||
const maxSize = (storageIndex.sizeLimit * (storageIndex.videoPercent / 100) * config.cron.deleteOverMaxOffset);
|
||||
if(storageIndex.usedSpaceVideos > maxSize){
|
||||
s.knexQuery({
|
||||
action: "select",
|
||||
columns: "*",
|
||||
|
@ -242,19 +237,62 @@ module.exports = (s,config,lang) => {
|
|||
}
|
||||
readStorageArray()
|
||||
}
|
||||
const deleteAddStorageTimelapseFrames = function(groupKey,callback){
|
||||
const theGroup = s.group[groupKey]
|
||||
reRunCheck = function(){
|
||||
s.debugLog('deleteAddStorageTimelapseFrames')
|
||||
return deleteAddStorageTimelapseFrames(groupKey,callback)
|
||||
}
|
||||
var currentStorageNumber = 0
|
||||
function readStorageArray(){
|
||||
setTimeout(function(){
|
||||
reRunCheck = readStorageArray
|
||||
var storage = s.listOfStorage[currentStorageNumber]
|
||||
if(!storage){
|
||||
//done all checks, move on to next user
|
||||
callback()
|
||||
return
|
||||
}
|
||||
var storageId = storage.value
|
||||
if(storageId === '' || !theGroup.addStorageUse[storageId]){
|
||||
++currentStorageNumber
|
||||
readStorageArray()
|
||||
return
|
||||
}
|
||||
var storageIndex = theGroup.addStorageUse[storageId]
|
||||
//run purge command
|
||||
const maxSize = (storageIndex.sizeLimit * (storageIndex.timelapsePercent / 100) * config.cron.deleteOverMaxOffset);
|
||||
if(storageIndex.usedSpaceTimelapseFrames > maxSize){
|
||||
s.knexQuery({
|
||||
action: "select",
|
||||
columns: "*",
|
||||
table: "Timelapse Frames",
|
||||
where: [
|
||||
['ke','=',groupKey],
|
||||
['details','LIKE',`%"dir":"${storage.value}"%`],
|
||||
],
|
||||
orderBy: ['time','asc'],
|
||||
limit: 3
|
||||
},(err,frames) => {
|
||||
deleteSetOfTimelapseFrames({
|
||||
groupKey: groupKey,
|
||||
err: err,
|
||||
frames: frames,
|
||||
storageIndex: storageIndex,
|
||||
reRunCheck: () => {
|
||||
return readStorageArray()
|
||||
}
|
||||
},callback)
|
||||
})
|
||||
}else{
|
||||
++currentStorageNumber
|
||||
readStorageArray()
|
||||
}
|
||||
})
|
||||
}
|
||||
readStorageArray()
|
||||
}
|
||||
const deleteMainVideos = function(groupKey,callback){
|
||||
// //run purge command
|
||||
// s.debugLog('!!!!!!!!!!!deleteMainVideos')
|
||||
// s.debugLog('s.group[groupKey].usedSpaceVideos > (s.group[groupKey].sizeLimit * (s.group[groupKey].sizeLimitVideoPercent / 100) * config.cron.deleteOverMaxOffset)')
|
||||
// s.debugLog(s.group[groupKey].usedSpaceVideos > (s.group[groupKey].sizeLimit * (s.group[groupKey].sizeLimitVideoPercent / 100) * config.cron.deleteOverMaxOffset))
|
||||
// s.debugLog('s.group[groupKey].usedSpaceVideos')
|
||||
// s.debugLog(s.group[groupKey].usedSpaceVideos)
|
||||
// s.debugLog('s.group[groupKey].sizeLimit * (s.group[groupKey].sizeLimitVideoPercent / 100) * config.cron.deleteOverMaxOffset')
|
||||
// s.debugLog(s.group[groupKey].sizeLimit * (s.group[groupKey].sizeLimitVideoPercent / 100) * config.cron.deleteOverMaxOffset)
|
||||
// s.debugLog('s.group[groupKey].sizeLimitVideoPercent / 100')
|
||||
// s.debugLog(s.group[groupKey].sizeLimitVideoPercent / 100)
|
||||
// s.debugLog('s.group[groupKey].sizeLimit')
|
||||
// s.debugLog(s.group[groupKey].sizeLimit)
|
||||
if(s.group[groupKey].usedSpaceVideos > (s.group[groupKey].sizeLimit * (s.group[groupKey].sizeLimitVideoPercent / 100) * config.cron.deleteOverMaxOffset)){
|
||||
s.knexQuery({
|
||||
action: "select",
|
||||
|
@ -295,7 +333,7 @@ module.exports = (s,config,lang) => {
|
|||
table: "Timelapse Frames",
|
||||
where: [
|
||||
['ke','=',groupKey],
|
||||
['archive','!=',`1`],
|
||||
['details','NOT LIKE',`%"dir"%`],
|
||||
],
|
||||
orderBy: ['time','asc'],
|
||||
limit: 3
|
||||
|
@ -508,6 +546,7 @@ module.exports = (s,config,lang) => {
|
|||
deleteAddStorageVideos: deleteAddStorageVideos,
|
||||
deleteMainVideos: deleteMainVideos,
|
||||
deleteTimelapseFrames: deleteTimelapseFrames,
|
||||
deleteAddStorageTimelapseFrames,
|
||||
deleteFileBinFiles: deleteFileBinFiles,
|
||||
deleteCloudVideos: deleteCloudVideos,
|
||||
deleteCloudTimelapseFrames: deleteCloudTimelapseFrames,
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -10,14 +10,22 @@ $(document).ready(function(){
|
|||
var addStorageData = JSON.parse($user.details.addStorage || '{}')
|
||||
var html = ''
|
||||
$.each(addStorage,function(n,storage){
|
||||
var limit = ""
|
||||
if(addStorageData[storage.path] && addStorageData[storage.path].limit){
|
||||
limit = addStorageData[storage.path].limit
|
||||
}
|
||||
html += `<div class="form-group">
|
||||
<div class="mb-2"><span>${lang['Max Storage Amount']} : ${storage.name}</span></div>
|
||||
<div><input class="form-control" placeholder="10000" addStorageLimit="${storage.path}" value="${limit}"></div>
|
||||
</div>`
|
||||
var theStorage = addStorageData[storage.path]
|
||||
html += `
|
||||
<div addStorageFields="${storage.path}">
|
||||
<div class="form-group">
|
||||
<div class="mb-2"><span>${lang['Max Storage Amount']} : ${storage.name}</span></div>
|
||||
<div><input class="form-control" placeholder="10000" addStorageItem="limit" value="${theStorage.limit || ''}"></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="mb-2"><span>${lang["Video Share"]} : ${storage.name}</span></div>
|
||||
<div><input class="form-control" placeholder="95" addStorageItem="videoPercent" value="${theStorage.videoPercent || ''}"></div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="mb-2"><span>${lang["Timelapse Frames Share"]} : ${storage.name}</span></div>
|
||||
<div><input class="form-control" placeholder="5" addStorageItem="timelapsePercent" value="${theStorage.timelapsePercent || ''}"></div>
|
||||
</div>
|
||||
</div>`
|
||||
})
|
||||
addStorageMaxAmounts.html(html)
|
||||
}catch(err){
|
||||
|
@ -35,20 +43,25 @@ $(document).ready(function(){
|
|||
extender(theForm)
|
||||
})
|
||||
}
|
||||
addStorageMaxAmounts.on('change','[addStorageLimit]',function(){
|
||||
function getAddStorageFields(){
|
||||
var json = {}
|
||||
$.each(addStorage,function(n,storage){
|
||||
var storageId = storage.path
|
||||
var el = addStorageMaxAmounts.find('[addStorageLimit="' + storageId + '"]')
|
||||
var value = el.val()
|
||||
var miniContainer = addStorageMaxAmounts.find(`[addStorageFields="${storageId}"]`)
|
||||
var fields = miniContainer.find('[addStorageItem]')
|
||||
json[storageId] = {
|
||||
name: storage.name,
|
||||
path: storage.path,
|
||||
limit: value
|
||||
}
|
||||
$.each(fields,function(n,el){
|
||||
var field = $(el)
|
||||
var keyName = field.attr('addStorageItem')
|
||||
var value = field.val()
|
||||
json[storageId][keyName] = value
|
||||
})
|
||||
})
|
||||
addStorageMaxAmountsField.val(JSON.stringify(json))
|
||||
})
|
||||
return json
|
||||
}
|
||||
$('body')
|
||||
theForm.find('[detail]').change(onDetailFieldChange)
|
||||
theForm.find('[detail]').change(function(){
|
||||
|
@ -77,6 +90,7 @@ $(document).ready(function(){
|
|||
})
|
||||
var details = getDetailValues(theForm)
|
||||
formData.details = details
|
||||
formData.details.addStorage = getAddStorageFields()
|
||||
accountSettings.onSaveFieldsExtensions.forEach(function(extender){
|
||||
extender(formData)
|
||||
})
|
||||
|
|
|
@ -911,9 +911,13 @@ function drawIndicatorBar(item){
|
|||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="progress">
|
||||
${!item.multiple ? `<div class="progress">
|
||||
<div class="progress-bar progress-bar-warning" role="progressbar" style="width: 0%;"></div>
|
||||
</div>
|
||||
</div>` : `<div class="progress">
|
||||
<div class="progress-bar progress-bar-info" role="progressbar" style="width: 0%;"></div>
|
||||
<div class="progress-bar progress-bar-danger" role="progressbar" style="width: 0%;"></div>
|
||||
<div class="progress-bar progress-bar-warning" role="progressbar" style="width: 0%;"></div>
|
||||
</div>`}
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
|
|
|
@ -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'){
|
||||
|
|
|
@ -45,61 +45,6 @@ $(document).ready(function(){
|
|||
</div>
|
||||
</div>`)
|
||||
}
|
||||
function createMonitorVideosTab(monitor){
|
||||
var startDate = moment().subtract(32, 'hour').utc()
|
||||
var endDate = moment().add(1, 'hour').utc()
|
||||
var newTabId = `monitorVideos-${monitor.mid}`
|
||||
var tabLabel = `<b>${lang['Videos']}</b> : ${monitor.name}`
|
||||
var baseHtml = `<main class="container page-tab" id="tab-${newTabId}">
|
||||
<div class="my-3 p-3 ${definitions.Theme.isDark ? 'bg-dark text-white' : 'bg-light text-dark'} rounded shadow-sm">
|
||||
<h6 class="border-bottom-dotted border-bottom-dark pb-2 mb-0 row">
|
||||
<div class="col-md-8">${lang['Videos']} : ${monitor.name}</div>
|
||||
<div class="col-md-4"><input class="form-control form-control-sm btn-dark text-md-end text-sm-center" type="text" id="daterange-${newTabId}" value="01/01/2018 - 01/15/2018" /></div>
|
||||
</h6>
|
||||
<div class="video-list flex-table flex-table-dark mx-n3 pt-2 px-3 row">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</main>`
|
||||
createNewTab(newTabId,tabLabel,baseHtml,{},null,'videosList')
|
||||
getVideos({
|
||||
monitorId: monitor.mid,
|
||||
startDate: startDate._d,
|
||||
endDate: endDate._d,
|
||||
},function(data){
|
||||
var videos = data.videos
|
||||
if(videos.length === 0){
|
||||
getVideos({
|
||||
monitorId: monitor.mid,
|
||||
limit: 20,
|
||||
},function(data){
|
||||
var videos = data.videos
|
||||
drawVideoRowsToList(`#tab-monitorVideos-${monitor.mid} .video-list`,videos)
|
||||
})
|
||||
}else{
|
||||
drawVideoRowsToList(`#tab-monitorVideos-${monitor.mid} .video-list`,videos)
|
||||
}
|
||||
})
|
||||
$(`#daterange-${newTabId}`).daterangepicker({
|
||||
timePicker: true,
|
||||
startDate: startDate,
|
||||
endDate: endDate,
|
||||
locale: {
|
||||
format: 'YYYY-MM-DD hh:mm:ss A'
|
||||
}
|
||||
}, function(start, end, label) {
|
||||
var startDate = start.clone().utc()
|
||||
var endDate = end.clone().utc()
|
||||
getVideos({
|
||||
monitorId: monitor.mid,
|
||||
startDate: startDate._d,
|
||||
endDate: endDate._d,
|
||||
},function(data){
|
||||
var videos = data.videos
|
||||
drawVideoRowsToList(`#tab-monitorVideos-${monitor.mid} .video-list`,videos)
|
||||
})
|
||||
})
|
||||
}
|
||||
function loadMonitorsFromMemory(options,callback){
|
||||
theList.empty();
|
||||
$.each(getLoadedMonitorsAlphabetically(),function(n,row){
|
||||
|
@ -168,12 +113,6 @@ $(document).ready(function(){
|
|||
console.log(data)
|
||||
})
|
||||
})
|
||||
.on('click','.open-videos',function(){
|
||||
var monitorId = getRowsMonitorId(this)
|
||||
var monitor = loadedMonitors[monitorId]
|
||||
createMonitorVideosTab(monitor)
|
||||
console.log(monitorId)
|
||||
})
|
||||
.on('click','.export-this-monitor-settings',function(){
|
||||
var monitorId = getRowsMonitorId(this)
|
||||
downloadMonitorConfigurationsToDisk([
|
||||
|
|
|
@ -91,6 +91,7 @@ function loadBoxWrappers() {
|
|||
function drawAddStorageIndicators(){
|
||||
$.each(addStorage,function(n,storage){
|
||||
drawIndicatorBar({
|
||||
multiple: true,
|
||||
icon: 'hdd-o',
|
||||
name: storage.name,
|
||||
label: `<span style="text-transform:capitalize">${storage.name}</span> : <span class="value"></span>`,
|
||||
|
@ -199,16 +200,25 @@ onWebSocketEvent(function (d){
|
|||
diskIndicatorBar[2].title = `${lang['FileBin Share']} : ${fileBinPercent}`
|
||||
if(d.addStorage){
|
||||
$.each(d.addStorage,function(n,storage){
|
||||
var percent = parseInt((storage.usedSpace/storage.sizeLimit)*100)+'%'
|
||||
var diskIndicator = loadedIndicators[storage.name]
|
||||
var diskIndicatorBars = diskIndicator.progressBar
|
||||
var diskLimit = storage.sizeLimit
|
||||
var percent = parseDiskUsePercent(storage.usedSpace,diskLimit);
|
||||
var videosPercent = parseDiskUsePercent(storage.usedSpaceVideos,diskLimit);
|
||||
var timelapsePercent = parseDiskUsePercent(storage.usedSpaceTimelapseFrames,diskLimit);
|
||||
//
|
||||
var humanValue = parseFloat(storage.usedSpace)
|
||||
if(humanValue > 1000){
|
||||
humanValue = (humanValue/1000).toFixed(2)+' GB'
|
||||
}else{
|
||||
humanValue = humanValue.toFixed(2)+' MB'
|
||||
}
|
||||
loadedIndicators[storage.name].value.html(humanValue)
|
||||
loadedIndicators[storage.name].percent.html(percent)
|
||||
loadedIndicators[storage.name].progressBar.css('width',percent)
|
||||
diskIndicator.value.html(humanValue)
|
||||
diskIndicator.percent.html(percent)
|
||||
diskIndicatorBars[0].style.width = videosPercent
|
||||
diskIndicatorBars[0].title = `${lang['Video Share']} : ${videosPercent}`
|
||||
diskIndicatorBars[1].style.width = timelapsePercent
|
||||
diskIndicatorBars[1].title = `${lang['Timelapse Frames Share']} : ${timelapsePercent}`
|
||||
})
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -457,7 +457,9 @@ function getVideos(options,callback){
|
|||
var monitorId = options.monitorId
|
||||
var archived = options.archived
|
||||
var customVideoSet = options.customVideoSet
|
||||
var limit = options.limit || 300
|
||||
var limit = options.limit
|
||||
var eventLimit = options.eventLimit || 300
|
||||
var doLimitOnFames = options.doLimitOnFames || false
|
||||
var eventStartTime
|
||||
var eventEndTime
|
||||
// var startDate = options.startDate
|
||||
|
@ -476,14 +478,14 @@ function getVideos(options,callback){
|
|||
if(archived){
|
||||
requestQueries.push(`archived=1`)
|
||||
}
|
||||
$.getJSON(`${getApiPrefix(customVideoSet ? customVideoSet : searchQuery ? `videosByEventTag` : `videos`)}${monitorId ? `/${monitorId}` : ''}?${requestQueries.concat([`noLimit=1`]).join('&')}`,function(data){
|
||||
$.getJSON(`${getApiPrefix(customVideoSet ? customVideoSet : searchQuery ? `videosByEventTag` : `videos`)}${monitorId ? `/${monitorId}` : ''}?${requestQueries.concat([limit ? `limit=${limit}` : `noLimit=1`]).join('&')}`,function(data){
|
||||
var videos = data.videos.map((video) => {
|
||||
return Object.assign({},video,{
|
||||
href: getFullOrigin(true) + video.href
|
||||
})
|
||||
})
|
||||
$.getJSON(`${getApiPrefix(`timelapse`)}${monitorId ? `/${monitorId}` : ''}?${requestQueries.concat([`noLimit=1`]).join('&')}`,function(timelapseFrames){
|
||||
$.getJSON(`${getApiPrefix(`events`)}${monitorId ? `/${monitorId}` : ''}?${requestQueries.concat([`limit=${limit}`]).join('&')}`,function(eventData){
|
||||
$.getJSON(`${getApiPrefix(`events`)}${monitorId ? `/${monitorId}` : ''}?${requestQueries.concat([`limit=${eventLimit}`]).join('&')}`,function(eventData){
|
||||
var theEvents = eventData.events || eventData;
|
||||
var newVideos = applyDataListToVideos(videos,theEvents)
|
||||
newVideos = applyTimelapseFramesListToVideos(newVideos,timelapseFrames.frames || timelapseFrames,'timelapseFrames',true).map((video) => {
|
||||
|
|
Loading…
Reference in New Issue