panlei
2019-09-10 e2aab518eddae165b9a7c517fbaddaf692ac4070
ruleserver/ruleToformula.go
@@ -20,7 +20,7 @@
      // 拿到本摄像机的区域
      cameraPolygons := GetPolygons(args.CameraId)
      // 把所有的sdk提取的数据都按所属摄像机的区域归置
      //logger.Debug("当前摄像机id为:",message.Cid,"当前摄像机执行的任务是:",message.Tasklab.Taskname)
      logger.Debug("当前摄像机id为:",message.Cid,"当前摄像机执行的任务是:",message.Tasklab.Taskname,"--任务id为:",message.Tasklab.Taskid)
      for _, arg := range args.Sdkdata {
         SdkDataFormat(args.CameraId, arg, cameraPolygons)
      }
@@ -64,7 +64,7 @@
   }
}
func RunRule1(args *structure.SdkDatas, groupRule *protomsg.GroupRule, taskId string, message *protomsg.SdkMessage, label structure.Others) bool {
func RunRule(args *SdkDatas, groupRule *protomsg.GroupRule, taskId string, message *protomsg.SdkMessage, label Others) (bool,[]int) {
   defer func() {
      if err := recover(); err != nil {
         logger.Error("比对规则有误", err)
@@ -139,6 +139,18 @@
   return ruleResult
}
func CallMiddleware(args *structure.SdkDatas,rule protomsg.GroupRule) ([]*structure.LittleRuleResult, string, string){
   p,err :=  plugin.Open("./algorithm/middleware.so")
   if err != nil {
      panic(err)
   }
   f,err1 := p.Lookup("Entrance")
   if err1 != nil {
      panic("没有找到中间件入口函数")
   }
   a,b,c := f.(func(args *structure.SdkDatas,rule protomsg.GroupRule)([]*structure.LittleRuleResult, string, string))(args,rule)
   return a,b,c
}
func RunRule(args *structure.SdkDatas, groupRule *protomsg.GroupRule, taskId string, message *protomsg.SdkMessage, label structure.Others) bool {
   defer func() {
      if err := recover(); err != nil {
@@ -151,106 +163,7 @@
   resultSplice := []*structure.LittleRuleResult{}
   sdkNames := ""
   polygonId := ""
   // 先过完条件规则
   for j := 0; j < len(groupRule.Rules); j++ {
      if groupRule.Rules[j].SdkArgAlias == "score" || groupRule.Rules[j].SdkArgAlias == "proportion" || groupRule.Rules[j].SdkArgAlias == "size" {
         for _, sdkData := range args.Sdkdata {
            // 根据规则的sdkId查出其对应的ipcId,用ipcId去找该比对的数据
            sdk, err := cache.GetSdkById(groupRule.Rules[j].SdkId)
            if err != nil {
               logger.Error("没查到sdk的信息---", err)
            }
            ipcId := sdk.IpcId
            sdkName := sdk.SdkName
            //logger.Info("规则的ipcId与sdkData的IpcId:", ipcId, "===", sdkData.IpcId)
            if ipcId == sdkData.IpcId {
               //logger.Info("当前走的规则是--:", sdkName, "---","")
               for _, areaMap := range sdkData.AreaMapList {
                  ruleResult := CallSo(sdk.Id,groupRule.Rules[j],areaMap)
                  if ruleResult.Result != "" {
                     logger.Info("条件规则结果:", ruleResult.Result)
                     // 如果结果为真,把这条规则中的区域置为有效
                     if strings.Contains(ruleResult.Result, "true") {
                        areaMap.IsEffective = true
                     }
                     // 如果此结果为真且当前过的是yolo算法,应记下此规则所对应的sdkName,另外,还要去重 (后加:把此条触碰的区域id也记录下来)
                     if strings.Contains(ruleResult.Result, "true") && ipcId == "02D54B61-0F16-C604-8567-FC4BE493C523" && !strings.Contains(sdkNames, sdkName) {
                        sdkNames = sdkName + ","
                        polygonId = groupRule.Rules[j].PolygonId + ","
                     }
                     if strings.Contains(ruleResult.Result, "true") && ipcId == "02D54B61-0F16-C604-8567-FC4BE493C523" && !strings.Contains(polygonId, groupRule.Rules[j].PolygonId) {
                        polygonId = groupRule.Rules[j].PolygonId + ","
                     }
                     resultSplice = append(resultSplice, &ruleResult)
                  }
               }
            }
         }
      }
   }
   // 再过其他数据 这步直接得到结果(真或假) 过目标数量
   for j := 0; j < len(groupRule.Rules); j++ {
      if groupRule.Rules[j].SdkArgAlias == "objCount" {
         for _, sdkData := range args.Sdkdata {
            // 根据规则的sdkId查出其对应的ipcId,用ipcId去找该比对的数据
            sdk, err := cache.GetSdkById(groupRule.Rules[j].SdkId)
            if err != nil {
               logger.Error("没查到sdk的信息---", err)
            }
            ipcId := sdk.IpcId
            sdkName := sdk.SdkName
            if ipcId == sdkData.IpcId {
               for _, areaMap := range sdkData.AreaMapList {
                  ruleResult := CallSo(sdk.Id,groupRule.Rules[j],areaMap)
                  if ruleResult.Result != "" {
                     if strings.Contains(ruleResult.Result, "true") {
                        areaMap.IsEffective = true
                     }
                     logger.Info("数量规则结果:", ruleResult.Result)
                     if strings.Contains(ruleResult.Result, "true") && ipcId == "02D54B61-0F16-C604-8567-FC4BE493C523" && !strings.Contains(sdkNames, sdkName) {
                        sdkNames = sdkName + ","
                     }
                     if strings.Contains(ruleResult.Result, "true") && ipcId == "02D54B61-0F16-C604-8567-FC4BE493C523" && !strings.Contains(polygonId, groupRule.Rules[j].PolygonId) {
                        polygonId = groupRule.Rules[j].PolygonId + ","
                     }
                     resultSplice = append(resultSplice, &ruleResult)
                  }
               }
            }
         }
      }
   }
   // 这步过的是时间段规则(时间段等)
   for j := 0; j < len(groupRule.Rules); j++ {
      for _, sdkData := range args.Sdkdata {
         sdk, err := cache.GetSdkById(groupRule.Rules[j].SdkId)
         if err != nil {
            logger.Error("没查到sdk的信息---", err)
         }
         ipcId := sdk.IpcId
         sdkName := sdk.SdkName
         if ipcId == sdkData.IpcId {
            for _, areaMap := range sdkData.AreaMapList {
               ruleResult := timeRuleResult(groupRule.Rules[j], areaMap)
               if ruleResult.Result != "" {
                  if strings.Contains(ruleResult.Result, "true") {
                     areaMap.IsEffective = true
                  }
                  logger.Info("时间规则结果:", ruleResult.Result)
                  if strings.Contains(ruleResult.Result, "true") && ipcId == "02D54B61-0F16-C604-8567-FC4BE493C523" && !strings.Contains(sdkNames, sdkName) {
                     sdkNames = sdkName + ","
                  }
                  if strings.Contains(ruleResult.Result, "true") && ipcId == "02D54B61-0F16-C604-8567-FC4BE493C523" && !strings.Contains(polygonId, groupRule.Rules[j].PolygonId) {
                     polygonId = groupRule.Rules[j].PolygonId + ","
                  }
                  resultSplice = append(resultSplice, &ruleResult)
               }
            }
         }
      }
   }
   resultSplice,sdkNames,polygonId = CallMiddleware(args,*groupRule)
   // 将数组按sort排序
   sort.Sort(resultList(resultSplice))
   // 排序后取各自的结果和连接符拼出规则表达式得出结果
@@ -318,6 +231,7 @@
                  }
               }
            }
            logger.Info("face标签的长度:",len(faces))
            //for _,face := range faces  {
            //   //logger.Debug("————————————————________________看看人脸的坐标:",face.Location)
            //}
@@ -338,27 +252,30 @@
            } else {
               islink = false
            }
            var labelTypes []int // 0为yolo标签,1为face标签 2为两者标签
            if sdkNames != "" {
               args.RuleResult["yolo"] = append(args.RuleResult["yolo"].([]structure.Result), structure.Result{taskId, sdkNames, groupRule.GroupId, groupRule.DefenceState, groupRule.AlarmLevel, groupRule.GroupText, locations, polygonId, islink, label,})
               args.RuleResult["yolo"] = append(args.RuleResult["yolo"].([]Result), Result{taskId, sdkNames, groupRule.GroupId, groupRule.DefenceState, groupRule.AlarmLevel, groupRule.GroupText, locations, polygonId, islink,label,})
               labelTypes = append(labelTypes,0)
               //logger.Info("-------------------yolo结果标签长度", len(args.RuleResult["yolo"].([]Result)))
            }
            if faceFlag {
               args.RuleResult["face"] = append(args.RuleResult["face"].([]structure.FaceResult), structure.FaceResult{structure.Result{taskId, sdkNames, groupRule.GroupId, groupRule.DefenceState, groupRule.AlarmLevel, groupRule.GroupText, []structure.Rect{}, polygonId, islink, label,}, faces})
               //logger.Info("-------------------face结果标签", len(args.RuleResult["face"].([]FaceResult)))
               labelTypes = append(labelTypes,1)
            }
            return true
            return true,labelTypes
         } else {
            return false
            return false,[]int{}
         }
      } else {
         // 结果为假时也要走,有时候为假的状态反转数据也需要记录下来
         // 结果为假时也要走,有杀死定时器的操作
         TimerAlarm(&label, groupRule.GroupId, result.(bool))
         //fmt.Println(timeFlag)
         return false
         return false,[]int{}
      }
   } else {
      return false
      return false,[]int{}
   }
}
@@ -423,7 +340,7 @@
      }
   }
   // 往数组里赋值
   isOk := RunRule(args, groupRule, taskId, message, label)
   isOk,labelTypes := RunRule(args, groupRule, taskId, message, label)
   if isOk {
      logger.Info("这帧图像在任务下的一整条规则下(联动任务下就是跟本摄像机像相关的小规则)的判断结果为true")
      // 根据cameraId去更新或者插入结果,然后判断是否数组是否可以得出报警的结论
@@ -496,8 +413,20 @@
      } else {
         logger.Warn("数组不圆满不打标签")
         // 倒是把打的组规则标签给去掉了啊
         lens := len(args.RuleResult["yolo"].([]structure.Result)) - 1
         args.RuleResult["yolo"] = args.RuleResult["yolo"].([]structure.Result)[0:lens]
         for _,val := range labelTypes {
            if val == 0 {
               if len(args.RuleResult["yolo"].([]Result)) >= 1 {
                  lens := len(args.RuleResult["yolo"].([]Result))-1
                  args.RuleResult["yolo"] = args.RuleResult["yolo"].([]Result)[0:lens]
               }
            }
            if val == 1 {
               if len(args.RuleResult["face"].([]FaceResult)) >= 1 {
                  lens := len(args.RuleResult["face"].([]FaceResult))-1
                  args.RuleResult["face"] = args.RuleResult["face"].([]FaceResult)[0:lens]
               }
            }
         }
      }
   } else { // 没有报警,
      //logger.Info("这帧图像在任务下的一整条规则下(联动任务下就是跟本摄像机像相关的小规则)的判断结果为false")
@@ -517,137 +446,6 @@
   }
}
// 过滤规则先筛选出符合条件的目标数量
//func filterRule(rule *protomsg.Rule, am *structure.AreaMap) structure.LittleRuleResult {
//   if rule.SdkId == "812b674b-2375-4589-919a-5c1c3278a97e" || rule.SdkId == "812b674b-2375-4589-919a-5c1c3278a972" {
//      // 处理的是人脸算法 如果这条规则配置的是人脸算法,过滤完条件之后直接得出结果,因为肯定没有数量条件,自己拼接
//      //logger.Info("规则的算法id和区域的算法id:", rule.SdkId, "===", am.sdkId)
//      if rule.PolygonId == am.AreaId { // 算法和区域都得对的上
//
//         if rule.SdkId == "812b674b-2375-4589-919a-5c1c3278a972" && rule.SdkArgAlias != "time_rule" {
//            //logger.Debug("当前小规则是:",rule)
//            flag := "false"
//            // 把没有相似者的人脸从filterData中删除
//            for index := 0; index < len(am.FilterData); {
//               // 将达不到阈值的相似者从相似者数组中删除
//               logger.Info("看看相似者人数:", len(am.FilterData[index].Liker))
//               if len(am.FilterData[index].Liker) == 0 {
//                  // Go 语言中切片删除元素的本质是:以被删除元素为分界点,将前后两个部分的内存重新连接起来。不用怀疑,数组删除元素就这么坑爹
//                  am.FilterData = append(am.FilterData[:index], am.FilterData[index+1:]...)
//               } else {
//                  index++
//               }
//            }
//            if len(am.FilterData) > 0 {
//               flag = "true"
//            }
//            logger.Info("---------人脸比对符合条件的数量为:", len(am.FilterData))
//            return structure.LittleRuleResult{am.SdkName, rule.RuleWithPre + "" + flag, rule.Sort}
//         }
//         if rule.SdkId == "812b674b-2375-4589-919a-5c1c3278a97e" { // 人脸检测
//            //logger.Debug("当前小规则是:",rule)
//            if rule.Operator == "==" || rule.Operator == ">=" || rule.Operator == "<=" || rule.Operator == "<" || rule.Operator == ">" || rule.Operator == "!=" {
//               // 如果是不规矩的连接符统统返回false 规则也只能判断人脸的相似度,所以不存在别的连接符
//               if rule.SdkArgAlias == "score" || rule.SdkArgAlias == "proportion" || rule.SdkArgAlias == "size" { // 判断的是相似值,占比,尺寸等过滤条件,如果再有,还可以再加
//                  logger.Info("-----------------------过规则之前区域内的人脸数量为:", am.TargetNum)
//                  var args []*structure.Arg
//                  if rule.RuleWithPre == "&&" {
//                     args = am.FilterData
//                     //logger.Info("过滤后的args的长度为:",len(args))
//                  } else {
//                     args = am.Args
//                     //logger.Info("没过滤的args的长度为:",len(args))
//                  }
//                  // 先清空过滤后的数据,再往里塞本次过滤后的数据
//                  am.FilterData = am.FilterData[0:0]
//                  //logger.Info("-----------------------人脸过滤的args里的数量:", len(args))
//                  for _, arg := range args {
//                     var formula string
//                     if rule.SdkArgAlias == "score" {
//                        formula = strconv.FormatFloat(arg.Score, 'f', -1, 64) + " " + rule.Operator + " " + rule.SdkArgValue // 得到字符串公式
//                        logger.Info("当前相似度小公式:", formula)
//                     } else if rule.SdkArgAlias == "proportion" {
//                        formula = strconv.FormatFloat(arg.Proportion, 'f', -1, 64) + " " + rule.Operator + " " + rule.SdkArgValue // 得到字符串公式
//                        logger.Info("当前占比小公式:", formula)
//                     } else {
//                        formula = strconv.FormatFloat(arg.Size, 'f', -1, 64) + " " + rule.Operator + " " + rule.SdkArgValue // 得到字符串公式
//                        logger.Info("当前尺寸小公式:", formula)
//                     }
//                     expression, _ := govaluate.NewEvaluableExpression(formula) // 得到数学公式
//                     result, _ := expression.Evaluate(nil)                      // 得到数学公式的结果
//                     if result.(bool) {
//                        am.FilterData = append(am.FilterData, arg) // 得到符合条件的过滤数据
//                     }
//                  }
//                  am.TargetNum = len(am.FilterData) // 把符合条件的目标数量更新到targetNum字段
//                  logger.Info("过完条件后的目标数量为:", am.TargetNum)
//                  if am.TargetNum > 0 {
//                     logger.Info("!!!!!!!!!人脸检测成功")
//                     return structure.LittleRuleResult{am.SdkName, rule.RuleWithPre + "" + "true", rule.Sort}
//                  } else {
//                     return structure.LittleRuleResult{am.SdkName, rule.RuleWithPre + "" + "false", rule.Sort}
//                  }
//               } else {
//                  return structure.LittleRuleResult{}
//               }
//            } else {
//               return structure.LittleRuleResult{}
//            }
//         } else {
//            return structure.LittleRuleResult{}
//         }
//      } else {
//         return structure.LittleRuleResult{}
//      }
//   } else {
//      // 处理的都是yolo数据
//      if rule.PolygonId == am.AreaId { // 首先这条规则得是这个算法的规则,其次规则所对应的区域id要跟区域数据的id对的上
//         if rule.SdkArgAlias == "score" || rule.SdkArgAlias == "proportion" || rule.SdkArgAlias == "size" { // 判断的是相似值,占比,尺寸等过滤条件,如果再有,还可以再加
//            var args []*structure.Arg
//            if rule.RuleWithPre == "&&" {
//               args = am.FilterData
//            } else {
//               args = am.Args
//            }
//            // 先清空过滤后的数据,再往里塞本次过滤后的数据
//            am.FilterData = am.FilterData[0:0]
//            //logger.Debug("看看args:::::", args)
//            for _, arg := range args {
//               var formula string
//               if rule.SdkArgAlias == "score" {
//                  formula = strconv.FormatFloat(arg.Score, 'f', -1, 64) + " " + rule.Operator + " " + rule.SdkArgValue // 得到字符串公式
//                  logger.Info("当前相似度小公式:", formula)
//               } else if rule.SdkArgAlias == "proportion" {
//                  formula = strconv.FormatFloat(arg.Proportion, 'f', -1, 64) + " " + rule.Operator + " " + rule.SdkArgValue // 得到字符串公式
//                  logger.Info("当前占比小公式:", formula)
//               } else {
//                  formula = strconv.FormatFloat(arg.Size, 'f', -1, 64) + " " + rule.Operator + " " + rule.SdkArgValue // 得到字符串公式
//                  logger.Info("当前尺寸小公式:", formula)
//               }
//               expression, _ := govaluate.NewEvaluableExpression(formula) // 得到数学公式
//               result, _ := expression.Evaluate(nil)                      // 得到数学公式的结果
//               if result.(bool) {
//                  am.FilterData = append(am.FilterData, arg) // 得到符合条件的过滤数据
//               }
//            }
//            am.TargetNum = len(am.FilterData) // 把符合条件的目标数量更新到targetNum字段
//            if am.TargetNum > 0 {
//               return structure.LittleRuleResult{am.SdkName, rule.RuleWithPre + "" + "true", rule.Sort}
//            } else {
//               return structure.LittleRuleResult{am.SdkName, rule.RuleWithPre + "" + "false", rule.Sort}
//            }
//
//         } else {
//            return structure.LittleRuleResult{}
//         }
//
//      } else {
//         return structure.LittleRuleResult{}
//      }
//   }
//}
// 如果有持续时间条件维护开启一个定时器
func duration(rule *protomsg.Rule, groupId string, am *structure.AreaMap, args *structure.SdkDatas, message *protomsg.SdkMessage) {
   if rule.PolygonId == am.AreaId { // 首先规则所对应的区域id要跟区域数据的id对的上  配置的算法要对的上
@@ -673,31 +471,6 @@
   }
}
// 给数据库的规则表达式代参 args: 一条子规则,区域数据
//func transferParameters(rule *protomsg.Rule, am *structure.AreaMap) structure.LittleRuleResult {
//   if rule.PolygonId == am.AreaId { // 首先规则所对应的区域id要跟区域数据的id对的上
//      if rule.SdkArgAlias == "objCount" { // 如果参数是要区域内目标数量 即yolo 人脸不会有数量
//         //logger.Info("当前小规则是:---------", rule)
//         //logger.Info("得出结果阶段", "比较的规则是:", rule)
//         if rule.Operator == "" {
//            return structure.LittleRuleResult{am.SdkName, strconv.Itoa(am.TargetNum) + "" + rule.RuleWithPre, rule.Sort} // 如果后面不跟操作符就直接返回数量  比如要跟下一个区域比较数量的就直接返回本区域的数量
//         }
//         //args := am.targetNum     targetNum 已成所有目标的总数量,这里只算yolo的
//         var num int = 0
//         for _, data := range am.FilterData {
//            if data.IsYolo {
//               num++
//            }
//         }
//         formula := strconv.Itoa(num) + " " + rule.Operator + " " + rule.SdkArgValue
//         expression, _ := govaluate.NewEvaluableExpression(formula) // 得到数学公式
//         result, _ := expression.Evaluate(nil)                      // 得到数学公式的结果
//         return structure.LittleRuleResult{am.SdkName, rule.RuleWithPre + " " + strconv.FormatBool(result.(bool)), rule.Sort}
//         // 加上关于算法的判断条件,不能只有关于规则的,有的算法本身就是一个规则,如个体静止,靠右行,所以,拿到当前子规则的sdkid来判断是否是那些特殊的规则
//      }
//   }
//   return structure.LittleRuleResult{}
//}
func timeRuleResult(rule *protomsg.Rule, am *structure.AreaMap) structure.LittleRuleResult {
   if rule.PolygonId == am.AreaId { // 首先规则所对应的区域id要跟区域数据的id对的上
      if rule.SdkArgAlias == "time_rule" { // 判断是否符合时间规