Merge branch 'dev-region-testing' into 'dev'

Add support for Region Name testing into detection filters

See merge request Shinobi-Systems/Shinobi!203
merge-requests/210/head
Moe 2020-06-24 18:26:43 +00:00
commit 98bc29e8eb
1 changed files with 149 additions and 48 deletions

View File

@ -53,6 +53,31 @@ module.exports = function(s,config,lang){
if(callback)callback(foundInRegion,collisions)
return foundInRegion
}
const scanMatricesforCollisions = function(region,matrices){
var matrixPoints = []
var collisions = []
if (!region || !matrices){
if(callback)callback(collisions)
return collisions
}
var polyPoints = []
region.points.forEach(function(point){
polyPoints.push(new V(parseInt(point[0]),parseInt(point[1])))
})
var regionPoly = new P(new V(0,0), polyPoints)
matrices.forEach(function(matrix){
if (matrix){
var matrixPoly = new B(new V(matrix.x, matrix.y), matrix.width, matrix.height).toPolygon()
var response = new SAT.Response()
var collided = SAT.testPolygonPolygon(matrixPoly, regionPoly, response)
if(collided === true){
collisions.push(matrix)
}
}
})
return collisions
}
const nonEmpty = (element) => element.length !== 0;
const moveLock = {}
const getLargestMatrix = (matrices) => {
var largestMatrix = {width: 0, height: 0}
@ -161,13 +186,14 @@ module.exports = function(s,config,lang){
s.onEventTriggerBeforeFilterExtensions.forEach(function(extender){
extender(d,filter)
})
var detailString = JSON.stringify(d.details);
if(!s.group[d.ke]||!s.group[d.ke].activeMonitors[d.id]){
return s.systemLog(lang['No Monitor Found, Ignoring Request'])
}
d.mon=s.group[d.ke].rawMonitorConfigurations[d.id];
var currentConfig = s.group[d.ke].rawMonitorConfigurations[d.id].details
var hasMatrices = (d.details.matrices && d.details.matrices.length > 0)
var allMatrices = d.details.matrices
var matchedMatrices = []
//read filters
if(
currentConfig.use_detector_filters === '1' &&
@ -192,74 +218,126 @@ module.exports = function(s,config,lang){
}
return newVal
}
var defaultDrop = true; // forces unmatched events to be dropped
var testMatrices = [...allMatrices] // default
var filters = currentConfig.detector_filters
var hasFilters = (filters.length > 0)
Object.keys(filters).forEach(function(key){
var conditionChain = {}
testMatrices = [...allMatrices] // for new filter reset the matrices to be tested against
var dFilter = filters[key]
dFilter.where.forEach(function(condition,place){
conditionChain[place] = {ok:false,next:condition.p4,matrixCount:0}
if(d.details.matrices)conditionChain[place].matrixCount = d.details.matrices.length
if(testMatrices)conditionChain[place].matrixCount = testMatrices.length
var modifyFilters = function(toCheck,matrixPosition){
var param = toCheck[condition.p1]
var pass = function(){
if(matrixPosition && dFilter.actions.halt === '1'){
delete(d.details.matrices[matrixPosition])
}else{
conditionChain[place].ok = true
}
conditionChain[place].ok = true
}
var fail = function(){
if (matrixPosition !== undefined) delete(testMatrices[matrixPosition])
}
switch(condition.p2){
case'indexOf':
if(param.indexOf(condition.p3) > -1){
pass()
} else {
fail()
}
break;
case'!indexOf':
if(param.indexOf(condition.p3) === -1){
pass()
} else {
fail()
}
break;
default:
if(eval('param '+condition.p2+' "'+condition.p3.replace(/"/g,'\\"')+'"')){
pass()
} else {
fail()
}
break;
}
}
switch(condition.p1){
case'tag':
case'x':
case'y':
case'height':
case'width':
case'confidence':
if(d.details.matrices){
d.details.matrices.forEach(function(matrix,position){
modifyFilters(matrix,position)
})
}
break;
case'time':
var timeNow = new Date()
var timeCondition = new Date()
var doAtTime = condition.p3.split(':')
var atHour = parseInt(doAtTime[0]) - 1
var atHourNow = timeNow.getHours()
var atMinuteNow = timeNow.getMinutes()
var atSecondNow = timeNow.getSeconds()
if(atHour){
var atMinute = parseInt(doAtTime[1]) - 1 || timeNow.getMinutes()
var atSecond = parseInt(doAtTime[2]) - 1 || timeNow.getSeconds()
var nowAddedInSeconds = atHourNow * 60 * 60 + atMinuteNow * 60 + atSecondNow
var conditionAddedInSeconds = atHour * 60 * 60 + atMinute * 60 + atSecond
if(eval('nowAddedInSeconds '+condition.p2+' conditionAddedInSeconds')){
conditionChain[place].ok = true
if (testMatrices.some(nonEmpty)){
switch(condition.p1){
case'tag':
case'x':
case'y':
case'height':
case'width':
case'confidence':
if(testMatrices){
testMatrices.forEach(function(matrix,position){
if (matrix) modifyFilters(matrix,position)
})
}
}
break;
default:
modifyFilters(d.details)
break;
break;
case'name':
if (testMatrices){
var regions = s.group[d.ke].activeMonitors[d.id].parsedObjects.cords
regions.forEach(function(region,position){
switch(condition.p2){
case'indexOf':
if(region.name.indexOf(condition.p3) > -1){
testMatrices = testMatrices.concat(scanMatricesforCollisions(region,testMatrices));
if(testMatrices.some(nonEmpty)) conditionChain[place].ok = true; // default is false
}
break;
case'!indexOf':
if(region.name.indexOf(condition.p3) === -1){
testMatrices = testMatrices.concat(scanMatricesforCollisions(region,testMatrices));
if(testMatrices.some(nonEmpty)) conditionChain[place].ok = true; // default is false
}
break;
case'===':
if(region.name === condition.p3){
testMatrices = scanMatricesforCollisions(region,testMatrices);
if(testMatrices.some(nonEmpty)) conditionChain[place].ok = true; // default is false
}
break;
case'!==':
if(region.name !== condition.p3){
testMatrices = testMatrices.concat(scanMatricesforCollisions(region,testMatrices));
if(testMatrices.some(nonEmpty)) conditionChain[place].ok = true; // default is false
}
break;
default:
//s.systemLog(lang['Numeric criteria unsupported for Region tests, Ignoring Conditional'])
s.systemLog('Numeric criteria unsupported for Region tests, Ignoring Conditional')
break;
}
});
}
break;
case'time':
var timeNow = new Date()
var timeCondition = new Date()
var doAtTime = condition.p3.split(':')
var atHour = parseInt(doAtTime[0]) - 1
var atHourNow = timeNow.getHours()
var atMinuteNow = timeNow.getMinutes()
var atSecondNow = timeNow.getSeconds()
if(atHour){
var atMinute = parseInt(doAtTime[1]) - 1 || timeNow.getMinutes()
var atSecond = parseInt(doAtTime[2]) - 1 || timeNow.getSeconds()
var nowAddedInSeconds = atHourNow * 60 * 60 + atMinuteNow * 60 + atSecondNow
var conditionAddedInSeconds = atHour * 60 * 60 + atMinute * 60 + atSecond
if(eval('nowAddedInSeconds '+condition.p2+' conditionAddedInSeconds')){
conditionChain[place].ok = true
}
}
break;
default:
modifyFilters(d.details)
break;
}
}
if (condition.p4 === '||' || dFilter.where.length-1 === place){
if (testMatrices.length > 0) matchedMatrices = matchedMatrices.concat(testMatrices)
testMatrices = [...allMatrices] // reset matrices for next group of conditions
}
})
var conditionArray = Object.values(conditionChain)
@ -277,19 +355,28 @@ module.exports = function(s,config,lang){
var value = dFilter.actions[key]
filter[key] = parseValue(key,value)
})
defaultDrop = false;
}else{
filter.halt = true
}
}
})
if(d.details.matrices && d.details.matrices.length === 0 || filter.halt === true){
if(filter.halt === true){
return
}else if(hasMatrices){
var reviewedMatrix = []
d.details.matrices.forEach(function(matrix){
if(matrix)reviewedMatrix.push(matrix)
})
d.details.matrices = reviewedMatrix
// remove empty elements
matchedMatrices = matchedMatrices.filter(value => Object.keys(value).length !== 0)
// remove duplicate matches
matchedMatrices = matchedMatrices.filter((matrix, index, self) =>
index === self.findIndex((t) => (
t.x === matrix.x && t.y === matrix.y && t.tag === matrix.tag && t.confidence === matrix.confidence
))
)
d.details.matrices = matchedMatrices
}
// -- delayed decision here --
if (defaultDrop && hasFilters) {
return;
}
}
var eventTime = new Date()
@ -325,8 +412,21 @@ module.exports = function(s,config,lang){
// check if object should be in region
if(hasMatrices && currentConfig.detector_obj_region === '1'){
var regions = s.group[d.ke].activeMonitors[d.id].parsedObjects.cords
var isMatrixInRegions = isAtleastOneMatrixInRegion(regions,d.details.matrices)
if(isMatrixInRegions){
testMatrices = d.details.matrices // matrices that made it passed filters
matchedMatrices = []
regions.forEach(function(region,position){
matchedMatrices = matchedMatrices.concat(scanMatricesforCollisions(region,testMatrices));
})
if (matchedMatrices.length > 2){
// remove duplicate matches
matchedMatrices = matchedMatrices.filter((matrix, index, self) =>
index === self.findIndex((t) => (
t.x === matrix.x && t.y === matrix.y && t.tag === matrix.tag && t.confidence === matrix.confidence
))
)
}
d.details.matrices = matchedMatrices // pass matrices that are within a region
if(d.details.matrices && d.details.matrices.length > 0){
s.debugLog('Matrix in region!')
if(filter.countObjects && currentConfig.detector_obj_count === '1' && currentConfig.detector_obj_count_in_region === '1' && !didCountingAlready){
countObjects(d)
@ -369,6 +469,7 @@ module.exports = function(s,config,lang){
}
//save this detection result in SQL, only coords. not image.
if(forceSave || (filter.save && currentConfig.detector_save === '1')){
var detailString = JSON.stringify(d.details);
s.sqlQuery('INSERT INTO Events (ke,mid,details,time) VALUES (?,?,?,?)',[d.ke,d.id,detailString,eventTime])
}
if(currentConfig.detector === '1' && currentConfig.detector_notrigger === '1'){