add Event Counting engine 0.1

build-default-monitor-config-from-definitions
Moe 2020-05-23 22:12:42 -07:00
parent f35136b46c
commit 664a30ee32
5 changed files with 169 additions and 39 deletions

View File

@ -8,33 +8,16 @@ var SAT = require('sat')
var V = SAT.Vector;
var P = SAT.Polygon;
// Matrix In Region Libs />
var objectCountTimeouts = {}
module.exports = function(s,config,lang){
const clearCountedObjectsForMonitor = async (groupKey,monitorId) => {
Object.keys(objectCountTimeouts[groupKey][monitorId]).forEach((objectId) => {
clearTimeout(objectCountTimeouts[groupKey][monitorId][objectId])
})
s.group[groupKey].activeMonitors[monitorId].eventsCounted = {}
}
const countObjectSetTimeout = async (event,matrixId) => {
const eventsCounted = s.group[event.ke].activeMonitors[event.id].eventsCounted || {}
if(!objectCountTimeouts[event.ke])objectCountTimeouts[event.ke] = {}
if(!objectCountTimeouts[event.ke][event.id])objectCountTimeouts[event.ke][event.id] = {}
clearTimeout(objectCountTimeouts[event.ke][event.id][matrixId])
objectCountTimeouts[event.ke][event.id][matrixId] = setTimeout(() => {
delete(eventsCounted[matrixId])
},10000)
}
const countObjects = async (event) => {
const matrices = event.details.matrices
const eventsCounted = s.group[event.ke].activeMonitors[event.id].eventsCounted || {}
if(matrices){
const currentTime = new Date()
matrices.forEach((matrix)=>{
const id = !isNaN(matrix.id) ? matrix.id + '_' + matrix.tag : matrix.tag
if(!eventsCounted[id])eventsCounted[id] = 0
++eventsCounted[id]
// countObjectSetTimeout(event,id)
if(!eventsCounted[id])eventsCounted[id] = {times: [], count: 0}
++eventsCounted[id].count
eventsCounted[id].times.push(new Date().getTime())
})
}
return eventsCounted
@ -483,5 +466,4 @@ module.exports = function(s,config,lang){
// item.process.kill('SIGTERM');
// })
}
s.clearCountedObjectsForMonitor = clearCountedObjectsForMonitor
}

View File

@ -11,6 +11,7 @@ var SoundDetection = require('shinobi-sound-detection')
var async = require("async");
var URL = require('url')
module.exports = function(s,config,lang){
var objectCountIntervals = {}
const startMonitorInQueue = async.queue(function(action, callback) {
setTimeout(function(){
action(callback)
@ -401,6 +402,7 @@ module.exports = function(s,config,lang){
delete(activeMonitor.detectorFrameSaveBuffer);
clearTimeout(activeMonitor.recordingSnapper);
clearInterval(activeMonitor.getMonitorCpuUsage);
clearInterval(objectCountIntervals[e.ke][e.id]);
if(activeMonitor.onChildNodeExit){
activeMonitor.onChildNodeExit()
}
@ -1009,6 +1011,42 @@ module.exports = function(s,config,lang){
},1000 * 60)
}
}
const createEventCounter = function(monitor){
if(monitor.details.detector_obj_count === '1'){
const activeMonitor = s.group[monitor.ke].activeMonitors[monitor.id]
activeMonitor.eventsCountStartTime = new Date()
const eventsCounted = activeMonitor.eventsCounted || {}
if(!objectCountIntervals[monitor.ke])objectCountIntervals[monitor.ke] = {}
if(!objectCountIntervals[monitor.ke][monitor.id])objectCountIntervals[monitor.ke][monitor.id] = {}
clearInterval(objectCountIntervals[monitor.ke][monitor.id])
objectCountIntervals[monitor.ke][monitor.id] = setInterval(() => {
const countsToSave = Object.assign(eventsCounted,{})
activeMonitor.eventsCounted = {}
const groupKey = monitor.ke
const monitorId = monitor.id
const startTime = new Date(activeMonitor.eventsCountStartTime + 0)
const endTime = new Date()
const countedKeys = Object.keys(countsToSave)
activeMonitor.eventsCountStartTime = new Date()
if(countedKeys.length > 0)countedKeys.forEach((tag) => {
const tagInfo = countsToSave[tag]
const count = tagInfo.count
const times = tagInfo.times
s.sqlQuery('INSERT INTO `Events Counts` (ke,mid,details,time,end,count,tag) VALUES (?,?,?,?,?,?,?)',[
groupKey,
monitorId,
JSON.stringify({
times: times
}),
startTime,
endTime,
count,
tag
])
})
},60000) //every minute
}
}
const createCameraStreamHandlers = function(e){
s.group[e.ke].activeMonitors[e.id].spawn.stdio[5].on('data',function(data){
resetStreamCheck(e)
@ -1442,6 +1480,7 @@ module.exports = function(s,config,lang){
try{
createCameraFfmpegProcess(e)
createCameraStreamHandlers(e)
createEventCounter(e)
if(e.type === 'dashcam'){
setTimeout(function(){
activeMonitor.allowStdinWrite = true

View File

@ -140,7 +140,7 @@ module.exports = function(s,config){
if(err)console.error(err)
},true)
//add Cloud Timelapse Frames table, will remove in future
s.sqlQuery('CREATE TABLE IF NOT EXISTS `Cloud Timelapse Frames` (`ke` varchar(50) NOT NULL,`mid` varchar(50) NOT NULL,`href` text NOT NULL,`details` longtext,`filename` varchar(50) NOT NULL,`time` timestamp NULL DEFAULT NULL,`size` int(11) NOT NULL)' + mySQLtail + ';',[],function(err){
s.sqlQuery('CREATE TABLE `Events Counts` (`ke` varchar(50) NOT NULL,`mid` varchar(50) NOT NULL,`details` longtext NOT NULL,`time` timestamp NOT NULL DEFAULT current_timestamp(),`end` timestamp NOT NULL DEFAULT current_timestamp(),`count` int(10) NOT NULL DEFAULT 1,`tag` varchar(30) DEFAULT NULL)' + mySQLtail + ';',[],function(err){
if(err)console.error(err)
},true)
//create Files table

View File

@ -1793,25 +1793,9 @@ module.exports = function(s,config,lang,app,io){
},res,req);
})
/**
* API : Object Detection Counter Reset
*/
app.get(config.webPaths.apiPrefix+':auth/counterReset/:ke/:id', function (req,res){
res.setHeader('Content-Type', 'application/json');
s.auth(req.params,function(user){
if(user.permissions.watch_videos==="0"||user.details.sub&&user.details.allmonitors!=='1'&&user.details.monitors.indexOf(req.params.id)===-1){
res.end(user.lang['Not Permitted'])
return
}
s.clearCountedObjectsForMonitor(req.params.ke,req.params.id)
res.end(s.prettyPrint({
ok: true
}))
},res,req);
})
/**
* API : Object Detection Counter Status
*/
app.get(config.webPaths.apiPrefix+':auth/counterStatus/:ke/:id', function (req,res){
app.get(config.webPaths.apiPrefix+':auth/eventCountStatus/:ke/:id', function (req,res){
res.setHeader('Content-Type', 'application/json');
s.auth(req.params,function(user){
if(user.permissions.watch_videos==="0"||user.details.sub&&user.details.allmonitors!=='1'&&user.details.monitors.indexOf(req.params.id)===-1){
@ -1827,6 +1811,120 @@ module.exports = function(s,config,lang,app,io){
},res,req);
})
/**
* API : Object Detection Counter Status
*/
app.get([
config.webPaths.apiPrefix+':auth/eventCounts/:ke',
config.webPaths.apiPrefix+':auth/eventCounts/:ke/:id'
], function (req,res){
res.setHeader('Content-Type', 'application/json')
s.auth(req.params,function(user){
var hasRestrictions = user.details.sub && user.details.allmonitors !== '1'
if(
user.permissions.watch_videos==="0" ||
hasRestrictions && (!user.details.video_view || user.details.video_view.indexOf(req.params.id)===-1)
){
res.end(s.prettyPrint([]))
return
}
var origURL = req.originalUrl.split('/')
var videoParam = origURL[origURL.indexOf(req.params.auth) + 1]
req.sql = 'SELECT * FROM `Events Counts` WHERE ke=?';req.ar=[req.params.ke];
req.count_sql='SELECT COUNT(*) FROM `Events Counts` WHERE ke=?';req.count_ar=[req.params.ke];
if(req.query.archived=='1'){
req.sql+=' AND details LIKE \'%"archived":"1"\''
req.count_sql+=' AND details LIKE \'%"archived":"1"\''
}
if(!req.params.id){
if(user.details.sub&&user.details.monitors&&user.details.allmonitors!=='1'){
try{user.details.monitors=JSON.parse(user.details.monitors);}catch(er){}
req.or=[];
user.details.monitors.forEach(function(v,n){
req.or.push('mid=?');req.ar.push(v)
})
req.sql+=' AND ('+req.or.join(' OR ')+')'
req.count_sql+=' AND ('+req.or.join(' OR ')+')'
}
}else{
if(!user.details.sub||user.details.allmonitors!=='0'||user.details.monitors.indexOf(req.params.id)>-1){
req.sql+=' and mid=?';req.ar.push(req.params.id)
req.count_sql+=' and mid=?';req.count_ar.push(req.params.id)
}else{
res.end('[]');
return;
}
}
if(req.query.start||req.query.end){
if(req.query.start && req.query.start !== ''){
req.query.start = s.stringToSqlTime(req.query.start)
}
if(req.query.end && req.query.end !== ''){
req.query.end = s.stringToSqlTime(req.query.end)
}
if(!req.query.startOperator||req.query.startOperator==''){
req.query.startOperator='>='
}
if(!req.query.endOperator||req.query.endOperator==''){
req.query.endOperator='<='
}
var endIsStartTo
var theEndParameter = '`end`'
if(req.query.endIsStartTo){
endIsStartTo = true
theEndParameter = '`time`'
}
switch(true){
case(req.query.start&&req.query.start!==''&&req.query.end&&req.query.end!==''):
req.sql+=' AND `time` '+req.query.startOperator+' ? AND '+theEndParameter+' '+req.query.endOperator+' ?';
req.count_sql+=' AND `time` '+req.query.startOperator+' ? AND '+theEndParameter+' '+req.query.endOperator+' ?';
req.ar.push(req.query.start)
req.ar.push(req.query.end)
req.count_ar.push(req.query.start)
req.count_ar.push(req.query.end)
break;
case(req.query.start&&req.query.start!==''):
req.sql+=' AND `time` '+req.query.startOperator+' ?';
req.count_sql+=' AND `time` '+req.query.startOperator+' ?';
req.ar.push(req.query.start)
req.count_ar.push(req.query.start)
break;
case(req.query.end&&req.query.end!==''):
req.sql+=' AND '+theEndParameter+' '+req.query.endOperator+' ?';
req.count_sql+=' AND '+theEndParameter+' '+req.query.endOperator+' ?';
req.ar.push(req.query.end)
req.count_ar.push(req.query.end)
break;
}
}
req.sql+=' ORDER BY `time` DESC';
if(!req.query.limit||req.query.limit==''){
req.query.limit='100'
}
if(req.query.limit!=='0'){
req.sql+=' LIMIT '+req.query.limit
}
s.sqlQuery(req.sql,req.ar,function(err,r){
if(!r){
res.end(s.prettyPrint({total:0,limit:req.query.limit,skip:0,counts:[]}));
return
}
r.forEach((row) => {
row.details = JSON.parse(row.details)
})
s.sqlQuery(req.count_sql,req.count_ar,function(err,count){
if(req.query.limit.indexOf(',')>-1){
req.skip=parseInt(req.query.limit.split(',')[0])
req.query.limit=parseInt(req.query.limit.split(',')[1])
}else{
req.skip=0
req.query.limit=parseInt(req.query.limit)
}
res.end(s.prettyPrint({isUTC:config.useUTC,total:count[0]['COUNT(*)'],limit:req.query.limit,skip:req.skip,counts:r,endIsStartTo:endIsStartTo}));
})
})
},res,req);
})
/**
* API : Camera PTZ Controller
*/
app.get(config.webPaths.apiPrefix+':auth/control/:ke/:id/:direction', function (req,res){

View File

@ -158,6 +158,17 @@ CREATE TABLE IF NOT EXISTS `Timelapse Frames` (
`size` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Dumping structure for table ccio.Events Counts
CREATE TABLE `Events Counts` (
`ke` varchar(50) NOT NULL,
`mid` varchar(50) NOT NULL,
`details` longtext NOT NULL,
`time` timestamp NOT NULL DEFAULT current_timestamp(),
`end` timestamp NOT NULL DEFAULT current_timestamp(),
`count` int(10) NOT NULL DEFAULT 1,
`tag` varchar(30) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- Data exporting was unselected.
/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */;