Allow Mass Config Changes by API (monitorStates) and more

- Unlike /configureMonitor/ this method, /monitorSates/, can take single veriables for a monitor edit.
+ clean /configureMonitor/'s addEdit portion and make it a separate function
+ add "raw" catch. if "raw" not found another database init will be requested
+ fix "undefined" monitor status for Disabled monitors on Shinobi start
+ fix color threshold save for region editor
+add fallback for snapBuffer failure
merge-requests/37/head
Moe 2018-11-10 19:59:02 -08:00
parent eb65330fa8
commit a0ec9afc87
9 changed files with 321 additions and 113 deletions

View File

@ -34,13 +34,13 @@ loadLib('ffmpeg')(s,config,function(){
//express web server with ejs
var app = loadLib('webServer')(s,config,lang,io)
//web server routes : page handling..
loadLib('webServerPaths')(s,config,lang,app)
loadLib('webServerPaths')(s,config,lang,app,io)
//web server routes for streams : streams..
loadLib('webServerStreamPaths')(s,config,lang,app)
loadLib('webServerStreamPaths')(s,config,lang,app,io)
//web server admin routes : create sub accounts, share monitors, share videos
loadLib('webServerAdminPaths')(s,config,lang,app)
loadLib('webServerAdminPaths')(s,config,lang,app,io)
//web server superuser routes : create admin accounts and manage system functions
loadLib('webServerSuperPaths')(s,config,lang,app)
loadLib('webServerSuperPaths')(s,config,lang,app,io)
//websocket connection handlers : login and streams..
loadLib('socketio')(s,config,lang,io)
//user and group functions

View File

@ -577,6 +577,8 @@
"Monitor is now Disabled": "Monitor is now Disabled",
"Monitor is now Watching": "Monitor is now Watching",
"Monitor is now Recording": "Monitor is now Recording",
"Space Used": "Space Used",
"Processor": "Processor",
"coProcessor": "coProcessor",
"coProcessor Stopped": "coProcessor Stopped",
"coProcessor Started": "coProcessor Started",
@ -647,7 +649,14 @@
"Thumbnail": "Thumbnail",
"Host Type": "Host Type",
"Edit": "Edit",
"No Monitor ID Present in Form": "No Monitor ID Present in Form",
"State Configuration has no monitors associated": "State Configuration has no monitors associated",
"State Configuration Not Found": "State Configuration Not Found",
"Inserted State Configuration": "Inserted State Configuration",
"Edited State Configuration": "Edited State Configuration",
"Deleted State Configuration": "Deleted State Configuration",
"Dashboard Language": "Dashboard Language",
"Form Data Not Found": "Form Data Not Found",
"File Not Found": "File Not Found",
"File Not Found in Filesystem": "File Not Found in Filesystem",
"File Not Found in Database": "File Not Found in Database",

View File

@ -73,6 +73,16 @@ module.exports = function(s,config,lang){
if(noPath !== true)url += e.path
return url
}
s.cleanMonitorObjectForDatabase = function(dirtyMonitor){
var cleanMonitor = {}
var acceptedFields = ['mid','ke','name','shto','shfr','details','type','ext','protocol','host','path','port','fps','mode','width','height']
Object.keys(dirtyMonitor).forEach(function(key){
if(acceptedFields.indexOf(key) > -1){
cleanMonitor[key] = dirtyMonitor[key]
}
})
return cleanMonitor
}
s.cleanMonitorObject = function(e){
x={keys:Object.keys(e),ar:{}};
x.keys.forEach(function(v){
@ -89,24 +99,28 @@ module.exports = function(s,config,lang){
}
var url
var runExtraction = function(){
var snapBuffer = []
var snapProcess = spawn(config.ffmpegDir,('-loglevel quiet -re -i '+url+options+' -frames:v 1 -f image2pipe pipe:1').split(' '),{detached: true})
snapProcess.stdout.on('data',function(data){
snapBuffer.push(data)
});
snapProcess.stderr.on('data',function(data){
console.log(data.toString())
});
snapProcess.on('exit',function(data){
clearTimeout(snapProcessTimeout)
snapBuffer = Buffer.concat(snapBuffer)
callback(snapBuffer,false)
})
var snapProcessTimeout = setTimeout(function(){
snapProcess.stdin.setEncoding('utf8')
snapProcess.stdin.write('q')
delete(snapProcessTimeout)
},5000)
try{
var snapBuffer = []
var snapProcess = spawn(config.ffmpegDir,('-loglevel quiet -re -i '+url+options+' -frames:v 1 -f image2pipe pipe:1').split(' '),{detached: true})
snapProcess.stdout.on('data',function(data){
snapBuffer.push(data)
})
snapProcess.stderr.on('data',function(data){
console.log(data.toString())
})
snapProcess.on('exit',function(data){
clearTimeout(snapProcessTimeout)
snapBuffer = Buffer.concat(snapBuffer)
callback(snapBuffer,false)
})
var snapProcessTimeout = setTimeout(function(){
snapProcess.stdin.setEncoding('utf8')
snapProcess.stdin.write('q')
delete(snapProcessTimeout)
},5000)
}catch(err){
callback(fs.readFileSync(config.defaultMjpeg,'binary'),false)
}
}
var checkExists = function(localStream,callback){
fs.stat(localStream,function(err){
@ -384,7 +398,7 @@ module.exports = function(s,config,lang){
}
}
//create onvif connection
if(!s.group[e.ke].mon[e.id].onvifConnection){
if(!s.group[e.ke].mon[e.id].onvifConnection || !s.group[e.ke].mon[e.id].onvifConnection.current_profile || !s.group[e.ke].mon[e.id].onvifConnection.current_profile.token){
s.group[e.ke].mon[e.id].onvifConnection = new onvif.OnvifDevice({
xaddr : 'http://' + controlURLOptions.host + ':' + controlURLOptions.port + '/onvif/device_service',
user : controlURLOptions.username,
@ -1209,6 +1223,92 @@ module.exports = function(s,config,lang){
}catch(err){}
return false
}
s.addOrEditMonitor = function(form,callback,user){
var endData = {
ok: false
}
if(!form.mid){
endData.msg = lang['No Monitor ID Present in Form']
callback(endData)
return
}
form.mid = form.mid.replace(/[^\w\s]/gi,'').replace(/ /g,'')
form = s.cleanMonitorObjectForDatabase(form)
s.sqlQuery('SELECT * FROM Monitors WHERE ke=? AND mid=?',[form.ke,form.mid],function(er,r){
var affectMonitor = false
var monitorQuery = []
var monitorQueryValues = []
var txData = {
f: 'monitor_edit',
mid: form.mid,
ke: form.ke,
mon: form
}
if(r&&r[0]){
txData.new = false
Object.keys(form).forEach(function(v){
if(form[v]&&form[v]!==''){
monitorQuery.push(v+'=?')
if(form[v] instanceof Object){
form[v] = s.s(form[v])
}
monitorQueryValues.push(form[v])
}
})
monitorQuery = monitorQuery.join(',')
monitorQueryValues.push(form.ke)
monitorQueryValues.push(form.mid)
s.userLog(form,{type:'Monitor Updated',msg:'by user : '+user.uid})
endData.msg = user.lang['Monitor Updated by user']+' : '+user.uid
s.sqlQuery('UPDATE Monitors SET '+monitorQuery+' WHERE ke=? AND mid=?',monitorQueryValues)
affectMonitor = true
}else if(
!s.group[form.ke].init.max_camera ||
s.group[form.ke].init.max_camera === '' ||
Object.keys(s.group[form.ke].mon).length <= parseInt(s.group[form.ke].init.max_camera)
){
txData.new = true
monitorQueryInsertValues = []
Object.keys(form).forEach(function(v){
if(form[v] && form[v] !== ''){
monitorQuery.push(v)
monitorQueryInsertValues.push('?')
if(form[v] instanceof Object){
form[v] = s.s(form[v])
}
monitorQueryValues.push(form[v])
}
})
monitorQuery = monitorQuery.join(',')
monitorQueryInsertValues = monitorQueryInsertValues.join(',')
s.userLog(form,{type:'Monitor Added',msg:'by user : '+user.uid})
endData.msg = user.lang['Monitor Added by user']+' : '+user.uid
s.sqlQuery('INSERT INTO Monitors ('+monitorQuery+') VALUES ('+monitorQueryInsertValues+')',monitorQueryValues)
affectMonitor = true
}else{
txData.f = 'monitor_edit_failed'
txData.ff = 'max_reached'
endData.msg = user.lang.monitorEditFailedMaxReached
}
if(affectMonitor === true){
form.details = JSON.parse(form.details)
endData.ok = true
s.initiateMonitorObject({mid:form.mid,ke:form.ke})
s.group[form.ke].mon_conf[form.mid] = s.cleanMonitorObject(form)
if(form.mode === 'stop'){
s.camera('stop',form)
}else{
s.camera('stop',form)
setTimeout(function(){
s.camera(form.mode,form)
},5000)
}
s.tx(txData,'STR_'+form.ke)
}
s.tx(txData,'GRP_'+form.ke)
callback(!endData.ok,endData)
})
}
s.camera = function(x,e,cn){
// x = function or mode
// e = monitor object

View File

@ -50,6 +50,9 @@ module.exports = function(s,config){
if(!onMoveOn){onMoveOn=function(){}}
var mergedQuery = s.mergeQueryValues(query,values)
s.debugLog('s.sqlQuery QUERY',mergedQuery)
if(!s.databaseEngine || !s.databaseEngine.raw){
s.connectDatabase()
}
return s.databaseEngine
.raw(query,values)
.asCallback(function(err,r){
@ -70,11 +73,18 @@ module.exports = function(s,config){
}
})
}
s.connectDatabase = function(){
s.databaseEngine = require('knex')(s.databaseOptions)
}
s.preQueries = function(){
//add Cloud Videos table, will remove in future
s.sqlQuery('CREATE TABLE IF NOT EXISTS `Cloud Videos` (`mid` varchar(50) NOT NULL,`ke` varchar(50) DEFAULT NULL,`href` text NOT NULL,`size` float DEFAULT NULL,`time` timestamp NULL DEFAULT NULL,`end` timestamp NULL DEFAULT NULL,`status` int(1) DEFAULT \'0\' COMMENT \'0:Complete,1:Read,2:Archive\',`details` text) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;',[],function(err){
// if(err)console.log(err)
},true)
//add monitorStates to Preset ENUM
s.sqlQuery('ALTER TABLE `Presets` CHANGE COLUMN `type` `type` VARCHAR(50) NULL DEFAULT NULL AFTER `details`;',[],function(err){
// if(err)console.log(err)
},true)
//create Files table
s.sqlQuery('CREATE TABLE IF NOT EXISTS `Files` (`ke` varchar(50) NOT NULL,`mid` varchar(50) NOT NULL,`name` tinytext NOT NULL,`size` float NOT NULL DEFAULT \'0\',`details` text NOT NULL,`status` int(1) NOT NULL DEFAULT \'0\') ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;',[],function(err){
// if(err)console.log(err)

View File

@ -29,6 +29,7 @@ module.exports = function(s,config,lang,io){
orphanedVideosForMonitors[monitor.ke][monitor.mid] += orphanedFilesCount
}
s.group[monitor.ke].mon_conf[monitor.mid] = monitor
s.sendMonitorStatus({id:monitor.mid,ke:monitor.ke,status:'Stopped'});
var monObj = Object.assign(monitor,{id : monitor.mid})
s.camera(monitor.mode,monObj)
++loadCompleted

View File

@ -155,7 +155,9 @@ module.exports = function(s,config,lang,app){
config.webPaths.adminApiPrefix+':auth/configureMonitor/:ke/:id',
config.webPaths.adminApiPrefix+':auth/configureMonitor/:ke/:id/:f'
], function (req,res){
req.ret={ok:false};
var endData = {
ok: false
}
res.setHeader('Content-Type', 'application/json');
res.header("Access-Control-Allow-Origin",req.headers.origin);
s.auth(req.params,function(user){
@ -163,88 +165,28 @@ module.exports = function(s,config,lang,app){
if(req.params.f !== 'delete'){
var form = s.getPostData(req)
if(!form){
req.ret.msg = user.lang.monitorEditText1;
res.end(s.prettyPrint(req.ret))
return
endData.msg = user.lang.monitorEditText1;
res.end(s.prettyPrint(endData))
return
}
form.mid = req.params.id.replace(/[^\w\s]/gi,'').replace(/ /g,'')
if(!user.details.sub ||
user.details.allmonitors === '1' ||
hasRestrictions && user.details.monitor_edit.indexOf(form.mid) >- 1 ||
hasRestrictions && user.details.monitor_create === '1'){
if(form&&form.mid&&form.name){
req.set=[],req.ar=[];
form.mid=req.params.id.replace(/[^\w\s]/gi,'').replace(/ /g,'');
try{
JSON.parse(form.details)
}catch(er){
if(!form.details||!form.details.stream_type){
req.ret.msg=user.lang.monitorEditText2;
res.end(s.prettyPrint(req.ret))
return
}else{
form.details=JSON.stringify(form.details)
}
}
form.ke=req.params.ke
req.logObject={details:JSON.parse(form.details),ke:req.params.ke,mid:req.params.id}
s.sqlQuery('SELECT * FROM Monitors WHERE ke=? AND mid=?',[form.ke,form.mid],function(er,r){
req.tx={f:'monitor_edit',mid:form.mid,ke:form.ke,mon:form};
if(r&&r[0]){
req.tx.new=false;
Object.keys(form).forEach(function(v){
if(form[v]&&form[v]!==''){
req.set.push(v+'=?'),req.ar.push(form[v]);
}
})
req.set=req.set.join(',');
req.ar.push(form.ke),req.ar.push(form.mid);
s.userLog(form,{type:'Monitor Updated',msg:'by user : '+user.uid});
req.ret.msg=user.lang['Monitor Updated by user']+' : '+user.uid;
s.sqlQuery('UPDATE Monitors SET '+req.set+' WHERE ke=? AND mid=?',req.ar)
req.finish=1;
}else{
if(!s.group[form.ke].init.max_camera||s.group[form.ke].init.max_camera==''||Object.keys(s.group[form.ke].mon).length <= parseInt(s.group[form.ke].init.max_camera)){
req.tx.new=true;
req.st=[];
Object.keys(form).forEach(function(v){
if(form[v]&&form[v]!==''){
req.set.push(v),req.st.push('?'),req.ar.push(form[v]);
}
})
// req.set.push('ke'),req.st.push('?'),req.ar.push(form.ke);
req.set=req.set.join(','),req.st=req.st.join(',');
s.userLog(form,{type:'Monitor Added',msg:'by user : '+user.uid});
req.ret.msg=user.lang['Monitor Added by user']+' : '+user.uid;
s.sqlQuery('INSERT INTO Monitors ('+req.set+') VALUES ('+req.st+')',req.ar)
req.finish=1;
}else{
req.tx.f='monitor_edit_failed';
req.tx.ff='max_reached';
req.ret.msg=user.lang.monitorEditFailedMaxReached;
}
}
if(req.finish===1){
form.details=JSON.parse(form.details)
req.ret.ok=true;
s.initiateMonitorObject({mid:form.mid,ke:form.ke});
s.group[form.ke].mon_conf[form.mid]=s.cleanMonitorObject(form);
if(form.mode==='stop'){
s.camera('stop',form);
}else{
s.camera('stop',form);setTimeout(function(){s.camera(form.mode,form);},5000)
};
s.tx(req.tx,'STR_'+form.ke);
};
s.tx(req.tx,'GRP_'+form.ke);
res.end(s.prettyPrint(req.ret))
})
if(form && form.name){
s.checkDetails(form)
form.ke = req.params.ke
s.addOrEditMonitor(form,function(err,endData){
res.end(s.prettyPrint(endData))
},user)
}else{
req.ret.msg=user.lang.monitorEditText1;
res.end(s.prettyPrint(req.ret))
endData.msg = user.lang.monitorEditText1;
res.end(s.prettyPrint(endData))
}
}else{
req.ret.msg=user.lang['Not Permitted'];
res.end(s.prettyPrint(req.ret))
endData.msg = user.lang['Not Permitted']
res.end(s.prettyPrint(endData))
}
}else{
if(!user.details.sub || user.details.allmonitors === '1' || user.details.monitor_edit.indexOf(req.params.id) > -1 || hasRestrictions && user.details.monitor_create === '1'){
@ -277,12 +219,12 @@ module.exports = function(s,config,lang,app){
}
})
}
req.ret.ok=true;
req.ret.msg='Monitor Deleted by user : '+user.uid
res.end(s.prettyPrint(req.ret))
endData.ok=true;
endData.msg='Monitor Deleted by user : '+user.uid
res.end(s.prettyPrint(endData))
}else{
req.ret.msg=user.lang['Not Permitted'];
res.end(s.prettyPrint(req.ret))
endData.msg=user.lang['Not Permitted'];
res.end(s.prettyPrint(endData))
}
}
},res,req)
@ -421,4 +363,139 @@ module.exports = function(s,config,lang,app){
})
},res,req)
})
/**
* API : Administrator : Change Group Preset. Currently affects Monitors only.
*/
app.all([
config.webPaths.apiPrefix+':auth/monitorStates/:ke/:stateName',
config.webPaths.apiPrefix+':auth/monitorStates/:ke/:stateName/:action',
config.webPaths.adminApiPrefix+':auth/monitorStates/:ke/:stateName',
config.webPaths.adminApiPrefix+':auth/monitorStates/:ke/:stateName/:action',
],function (req,res){
s.auth(req.params,function(user){
var endData = {
ok : false
}
if(user.details.sub){
endData.msg = user.lang['Not Permitted']
s.closeJsonResponse(res,endData)
return
}
var findPreset = function(callback){
s.sqlQuery("SELECT * FROM Presets WHERE ke=? AND type=? AND name=? LIMIT 1",[req.params.ke,'monitorStates',req.params.stateName],function(err,presets){
var preset
var notFound = false
if(presets && presets[0]){
preset = presets[0]
s.checkDetails(preset)
}else{
notFound = true
}
callback(notFound,preset)
})
}
switch(req.params.action){
case'insert':case'edit':
var form = s.getPostData(req)
s.checkDetails(form)
if(!form || !form.monitors){
endData.msg = user.lang['Form Data Not Found']
s.closeJsonResponse(res,endData)
return
}
findPreset(function(notFound,preset){
if(notFound === true){
endData.msg = lang["Inserted State Configuration"]
var details = {
monitors : form.monitors
}
var insertData = {
ke: req.params.ke,
name: req.params.stateName,
details: s.s(details),
type: 'monitorStates'
}
s.sqlQuery('INSERT INTO Presets ('+Object.keys(insertData).join(',')+') VALUES (?,?,?,?)',Object.values(insertData))
s.tx({
f: 'add_group_state',
details: details,
ke: req.params.ke,
name: req.params.stateName
},'GRP_'+req.params.ke)
}else{
endData.msg = lang["Edited State Configuration"]
var details = Object.assign(preset.details,{
monitors : form.monitors
})
s.sqlQuery('UPDATE Presets SET details=? WHERE ke=? AND name=?',[s.s(details),req.params.ke,req.params.stateName])
s.tx({
f: 'edit_group_state',
details: details,
ke: req.params.ke,
name: req.params.stateName
},'GRP_'+req.params.ke)
}
endData.ok = true
s.closeJsonResponse(res,endData)
})
break;
case'delete':
findPreset(function(notFound,preset){
if(notFound === true){
endData.msg = user.lang['State Configuration Not Found']
s.closeJsonResponse(res,endData)
}else{
s.sqlQuery('DELETE FROM Presets WHERE ke=? AND name=?',[req.params.ke,req.params.stateName],function(err){
if(!err){
endData.msg = lang["Deleted State Configuration"]
endData.ok = true
}
s.closeJsonResponse(res,endData)
})
}
})
break;
default://change monitors according to state
findPreset(function(notFound,preset){
if(notFound === false){
var sqlQuery = 'SELECT * FROM Monitors WHERE ke=? AND '
var monitorQuery = []
var sqlQueryValues = [req.params.ke]
var monitorPresets = {}
preset.details.monitors.forEach(function(monitor){
monitorQuery.push('mid=?')
sqlQueryValues.push(monitor.mid)
monitorPresets[monitor.mid] = monitor
})
sqlQuery += '('+monitorQuery.join(' OR ')+')'
s.sqlQuery(sqlQuery,sqlQueryValues,function(err,monitors){
if(monitors && monitors[0]){
monitors.forEach(function(monitor){
s.checkDetails(monitor)
s.checkDetails(monitorPresets[monitor.mid])
var monitorPreset = monitorPresets[monitor.mid]
monitorPreset.details = Object.assign(monitor.details,monitorPreset.details)
monitor = s.cleanMonitorObjectForDatabase(Object.assign(monitor,monitorPreset))
monitor.details = JSON.stringify(monitor.details)
s.addOrEditMonitor(Object.assign(monitor,{}),function(err,endData){
},user)
})
endData.ok = true
s.tx({f:'change_group_state',ke:req.params.ke,name:req.params.stateName},'GRP_'+req.params.ke)
s.closeJsonResponse(res,endData)
}else{
endData.msg = user.lang['State Configuration has no monitors associated']
s.closeJsonResponse(res,endData)
}
})
}else{
endData.msg = user.lang['State Configuration Not Found']
s.closeJsonResponse(res,endData)
}
})
break;
}
},res,req)
})
}

View File

@ -11,7 +11,7 @@ var httpProxy = require('http-proxy');
var proxy = httpProxy.createProxyServer({})
var ejs = require('ejs');
var CircularJSON = require('circular-json');
module.exports = function(s,config,lang,app){
module.exports = function(s,config,lang,app,io){
if(config.productType==='Pro'){
var LdapAuth = require('ldapauth-fork');
}
@ -69,7 +69,7 @@ module.exports = function(s,config,lang,app){
app.set('views', s.mainDirectory + '/web');
app.set('view engine','ejs');
//add template handler
if(config.renderPaths.handler!==undefined){require(s.mainDirectory+'/web/'+config.renderPaths.handler+'.js').addHandlers(s,app,io)}
if(config.renderPaths.handler!==undefined){require(s.mainDirectory+'/web/'+config.renderPaths.handler+'.js').addHandlers(s,app,io,config)}
/**
* API : Logout
@ -337,7 +337,7 @@ module.exports = function(s,config,lang,app){
r.details=JSON.parse(r.details);
r.lang=s.getLanguageFile(r.details.lang)
req.factorAuth=function(cb){
if(r.details.factorAuth==="1"){
if(r.details.factorAuth === "1"){
if(!r.details.acceptedMachines||!(r.details.acceptedMachines instanceof Object)){
r.details.acceptedMachines={}
}

View File

@ -7,7 +7,11 @@ window.chartColors = {
purple: 'rgb(153, 102, 255)',
grey: 'rgb(201, 203, 207)'
};
$user.details=JSON.parse($user.details)
try{
$user.details = JSON.parse($user.details)
}catch(err){
}
$.ccio={
fr:$('#files_recent'),
mon:{}
@ -1876,7 +1880,7 @@ switch($user.details.lang){
return ii.o
}
//websocket functions
$.users={}
$.users = {}
$.ccio.globalWebsocket=function(d,user){
if(d.f!=='monitor_frame'&&d.f!=='os'&&d.f!=='video_delete'&&d.f!=='detector_trigger'&&d.f!=='detector_record_timeout_start'&&d.f!=='log'){$.ccio.log(d);}
if(!user){
@ -2460,7 +2464,9 @@ $.ccio.globalWebsocket=function(d,user){
}
$.ccio.init('monitorInfo',d)
$.gR.drawList();
$.ccio.init('note',{title:'Monitor Saved',text:'<b>'+d.mon.name+'</b> <small>'+d.mon.mid+'</small> has been saved.',type:'success'});
if(!d.silenceNote){
$.ccio.init('note',{title:'Monitor Saved',text:'<b>'+d.mon.name+'</b> <small>'+d.mon.mid+'</small> has been saved.',type:'success'});
}
break;
case'monitor_starting':
// switch(d.mode){case'start':d.mode='Watch';break;case'record':d.mode='Record';break;}
@ -2991,6 +2997,7 @@ $.zO.initCanvas=function(){
$.zO.f.find('[name="sensitivity"]').val('')
$.zO.f.find('[name="max_sensitivity"]').val('')
$.zO.f.find('[name="threshold"]').val('')
$.zO.f.find('[name="color_threshold"]').val('')
$.zO.rp.empty()
}else{
e.cord=$.zO.regionViewerDetails.cords[e.val];
@ -3006,6 +3013,7 @@ $.zO.initCanvas=function(){
$.zO.f.find('[name="sensitivity"]').val(e.cord.sensitivity)
$.zO.f.find('[name="max_sensitivity"]').val(e.cord.max_sensitivity)
$.zO.f.find('[name="threshold"]').val(e.cord.threshold)
$.zO.f.find('[name="color_threshold"]').val(e.cord.color_threshold)
$.zO.e.find('.canvas_holder canvas').remove();
$.zO.initLiveStream()
@ -3110,7 +3118,7 @@ $.zO.e.on('click','.add',function(e){
}
})
$.zO.regionViewerDetails.cords=e.save;
$.zO.regionViewerDetails.cords[e.gid]={name:e.gid,sensitivity:0.0005,max_sensitivity:'',threshold:1,points:[[0,0],[0,100],[100,0]]};
$.zO.regionViewerDetails.cords[e.gid]={name:e.gid,sensitivity:0.0005,max_sensitivity:'',threshold:1,color_threshold:9,points:[[0,0],[0,100],[100,0]]};
$.zO.rl.append('<option value="'+e.gid+'">'+e.gid+'</option>');
$.zO.rl.val(e.gid)
$.zO.rl.change();
@ -3566,6 +3574,7 @@ $.aM.generateDefaultMonitorSettings=function(){
"detector_sensitivity": "",
"detector_max_sensitivity": "",
"detector_threshold": "1",
"detector_color_threshold": "",
"cords": "[]",
"detector_buffer_vcodec": "auto",
"detector_buffer_fps": "",
@ -5689,7 +5698,7 @@ $('body')
}
if(!e.d.cords||e.d.cords===''){
e.d.cords={
red:{ name:"red",sensitivity:0.0005, max_sensitivity:"",points:[[0,0],[0,100],[100,0]] },
red:{ name:"red",sensitivity:0.0005, max_sensitivity:"",color_threshold:"",points:[[0,0],[0,100],[100,0]] },
}
}
$.zO.regionViewerDetails=e.d;
@ -6098,14 +6107,14 @@ $('body')
})
}
//set dropdown toggle preferences
e.o=$.ccio.op().dropdown_toggle;
e.o = $.ccio.op().dropdown_toggle
if(e.o){
$.each(e.o,function(n,v){
$('[dropdown_toggle="'+n+'"]').val(v).change()
})
}
//set localStorage input values
e.o=$.ccio.op();
e.o = $.ccio.op()
if(e.o){
$.each(e.o,function(n,v){
if(typeof v==='string'){

2
web/templates/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
black
argon