panlei
2019-07-13 43876595ecbbf6c41fafc8293713347e8ed4014d
ruleserver/ruleToformula.go
@@ -122,14 +122,14 @@
type SdkDatas struct {
   CameraId   string
   Sdkdata    []*SdkData
   RuleResult map[string]interface{} // 过完规则后打的标签 face: []Arg  yolo: []Result
   RuleResult map[string]interface{} // 过完规则后打的标签 face: []Arg, yolo: []Result, cacheData: SdkDatas, timeLabel: 0,1,2,3,4,5
}
// 将传递过来的参数转化为
//protomsg.SdkMessage.TaskLabel.SdkmsgWithTask.sdkdata
type ResultMsg struct {
   protomsg.SdkMessage
   *protomsg.SdkMessage
   RuleResult map[string]interface{} // 过完规则后打的标签
}
@@ -186,7 +186,7 @@
}
// 对单帧图像的判断 thisSdkDatas  当前传入的这帧数据,cacheSdkData 定时器里缓存的一帧数据 没有就返回nil  (thisSdkDatas SdkDatas, cacheSdkDatas SdkDatas)
func Judge(args *SdkDatas) {
func Judge(args *SdkDatas,message *protomsg.SdkMessage) {
   if len(args.Sdkdata) > 0 {
      // 拿到本摄像机的区域
      cameraPolygons := GetPolygons(args.CameraId)
@@ -212,10 +212,10 @@
               if len(temp) > 0 {
                  if ruleList[i].SetType == "linkTask" {
                     // groupId中含有link则为联动任务
                     LinkTask(args, ruleList[i], taskId)
                     LinkTask(args, ruleList[i], taskId,message)
                  } else {
                     // 独立任务的处理
                     RunRule(args, ruleList[i], taskId)
                     RunRule(args, ruleList[i], taskId,message)
                  }
               }
            }
@@ -232,7 +232,7 @@
   if err1 != nil {
      logger.Error("getBaseInfo解压错误", err1)
   }
   logger.Info("----------------------------------------map是", m)
   //logger.Info("----------------------------------------map是", m)
   for key, val := range m {
      baseinfo, err1 := esutil.Dbpersoninfosbyid(key)
      if err1 != nil {
@@ -306,7 +306,7 @@
      }
   }
}
func RunRule(args *SdkDatas, groupRule *protomsg.GroupRule, taskId string) bool {
func RunRule(args *SdkDatas, groupRule *protomsg.GroupRule, taskId string,message *protomsg.SdkMessage) bool {
   defer func() {
      if err := recover(); err != nil {
         logger.Error("比对规则有误", err.(string))
@@ -417,7 +417,7 @@
         if ipcId == sdkData.IpcId {
            for _, areaMap := range sdkData.AreaMapList {
               // 去开启一个定时器
               duration(groupRule.Rules[j], groupRule.GroupId, areaMap, args)
               duration(groupRule.Rules[j], groupRule.GroupId, areaMap, args,message)
            }
         }
      }
@@ -449,86 +449,108 @@
         panic("规则有误,得到的数学公式不可解析")
      }
      result, _ := expression.Evaluate(nil) // 得到数学公式的结果
      if !result.(bool) {
         // 给这帧数据打上规则组标签
         //args.RuleResult = append(args.RuleResult, Result{TaskId: taskId, RuleGroupId: groupRule.GroupId})
         for k, timeEle := range TimeEleList {
            if strings.Contains(k, groupRule.GroupId) {
               timeEle.N = timeEle.InitN // 重置定时器
      // 进行定时器的处理和判断
      timeFlag := TimerAlarm(args,groupRule.GroupId,result.(bool))
      if timeFlag == "01" || timeFlag == "10" || timeFlag == "11" {
         // 最后成功报警才把符合条件的人脸数据塞进结果标签里
         // 配了人脸的算法才把人脸的数据甩出来打标签
         faces := []Arg{}
         faceFlag := false
         for j := 0; j < len(groupRule.Rules); j++ {
            if groupRule.Rules[j].SdkId == "812b674b-2375-4589-919a-5c1c3278a97e" || groupRule.Rules[j].SdkId == "812b674b-2375-4589-919a-5c1c3278a972" {
               faceFlag = true
            }
         }
         logger.Info("-------------------重置相关的定时器并返回false---------------")
         return false
         for _, sdkData := range args.Sdkdata {
            if sdkData.IpcId == "A8B73405-373D-4F23-CED2-A617EBD7EC55" && faceFlag { // sdkData里有人脸数据且配置了算法才把符合条件的数据塞进标签里去
               for _, areaMap := range sdkData.AreaMapList {
                  faces = append(faces, putFaceToResult(areaMap)...)
               }
            }
         }
         if faceFlag {
            args.RuleResult["face"] = faces
         }
         logger.Warn("___________________________________________________________________________终于走完万里长征")
         // 把他们的位置数据也传下去
         locations := []Rect{}
         for _, sdkData := range args.Sdkdata {
            if sdkData.IpcId == "02D54B61-0F16-C604-8567-FC4BE493C523" && sdkNames != "" { // 把yolo数据的各个目标的坐标输出方便后面画框
               for _, areaMap := range sdkData.AreaMapList {
                  locations = append(locations, putYolosToResult(areaMap)...)
               }
            }
         }
         logger.Debug("------locations的内容:",locations)
         if sdkNames != "" {
            args.RuleResult["yolo"] = append(args.RuleResult["yolo"].([]Result), Result{taskId, sdkNames, groupRule.GroupId, groupRule.AlarmLevel, groupRule.GroupText, locations,polygonId})
            logger.Info("-------------------yolo结果标签长度", len(args.RuleResult["yolo"].([]Result)))
         }
         if args.RuleResult["face"] != nil {
            logger.Info("-------------------face结果标签", len(args.RuleResult["face"].([]Arg)))
         }
         return true
      } else {
         // 判断持续时间条件,去看池子里是否有与本帧数据有关的定时器,如果有,看此时是否走到0,没有此定时器或有定时器走到0的话返回成功报警
         var flag bool = true
         for k, timeEle := range TimeEleList {
            if strings.Contains(k, groupRule.GroupId) {
               if timeEle.N != 0 { // 这组规则的定时器要全部等于0
                  logger.Info("———————————-------------不冤,你是被定时器打败的:")
                  flag = false
               }
            }
         }
         if flag {
            // 最后成功报警才把符合条件的人脸数据塞进结果标签里
            // 配了人脸的算法才把人脸的数据甩出来打标签
            faces := []Arg{}
            faceFlag := false
            for j := 0; j < len(groupRule.Rules); j++ {
               if groupRule.Rules[j].SdkId == "812b674b-2375-4589-919a-5c1c3278a97e" || groupRule.Rules[j].SdkId == "812b674b-2375-4589-919a-5c1c3278a972" {
                  faceFlag = true
               }
            }
            for _, sdkData := range args.Sdkdata {
               if sdkData.IpcId == "A8B73405-373D-4F23-CED2-A617EBD7EC55" && faceFlag { // sdkData里有人脸数据且配置了算法才把符合条件的数据塞进标签里去
                  for _, areaMap := range sdkData.AreaMapList {
                     faces = append(faces, putFaceToResult(areaMap)...)
                  }
               }
            }
            if faceFlag {
               args.RuleResult["face"] = faces
            }
            logger.Warn("___________________________________________________________________________终于走完万里长征")
            // 把他们的位置数据也传下去
            locations := []Rect{}
            for _, sdkData := range args.Sdkdata {
               if sdkData.IpcId == "02D54B61-0F16-C604-8567-FC4BE493C523" && sdkNames != "" { // 把yolo数据的各个目标的坐标输出方便后面画框
                  for _, areaMap := range sdkData.AreaMapList {
                     locations = append(locations, putYolosToResult(areaMap)...)
                  }
               }
            }
            if sdkNames != "" {
               args.RuleResult["yolo"] = append(args.RuleResult["yolo"].([]Result), Result{taskId, sdkNames, groupRule.GroupId, groupRule.AlarmLevel, groupRule.GroupText, locations,polygonId})
               logger.Info("-------------------yolo结果标签长度", len(args.RuleResult["yolo"].([]Result)))
            }
            if args.RuleResult["face"] != nil {
               logger.Info("-------------------face结果标签", len(args.RuleResult["face"].([]Arg)))
            }
            return true
         } else {
            return false
         }
         return false
      }
   } else {
      return false
   }
}
func TimerAlarm(groupId string) (int) {
   var flagTime int = 0
   for k, timeEle := range TimeEleList {
// 判断是否符合定时器条件
func TimerAlarm(args *SdkDatas,groupId string,result bool) (string) {
   var flagTime string  //
   // 判断有无此规则组的定时器
   flag := false
   for k,_ := range TimeEleList {
      logger.Debug("-----------------看看这个key和groupId",k,groupId)
      if strings.Contains(k, groupId) {
         if timeEle.N == 0 && !timeEle.AlarmFlag { // 这组规则的定时器要全部等于0   暂且认为一组规则只有一个定时器
            logger.Info("———————————-------------首次符合持续时间规则并报警")
            flagTime = 1
            timeEle.AlarmFlag = true
         flag = true
      }
   }
   if flag {     // 有定时器
      if result { // 结果为真
         for k, timeEle := range TimeEleList {
            if strings.Contains(k, groupId) {
               if timeEle.N == 0 && timeEle.AlarmFlag {
                  logger.Debug("-------------------------符合持续时间规则但并不是首次,不报警")
                  flagTime = "11"
                  args.RuleResult["timeLabel"] = flagTime
               }
               if timeEle.N == 0 && !timeEle.AlarmFlag { // 这组规则的定时器要全部等于0   暂且认为一组规则只有一个定时器
                  logger.Debug("———————————-------------首次符合持续时间规则并报警")
                  flagTime = "10"
                  timeEle.AlarmFlag = true
                  args.RuleResult["cacheData"] = timeEle.CacheSdkData
                  args.RuleResult["timeLabel"] = flagTime
               }
               if timeEle.N != 0 {
                  flagTime = "00"
                  logger.Debug("------------------------结果为真但计数器不到0,不报警,此时的计数器的值为:",timeEle.N)
               }
            }
         }
         if timeEle.N == 0 && timeEle.AlarmFlag {
            logger.Info("-------------------------符合持续时间规则但并不是首次,不报警")
            flagTime = 2
      } else { // 结果为假
         for k, timeEle := range TimeEleList {
            if strings.Contains(k, groupId) {
               if timeEle.AlarmFlag {
                  logger.Debug("------------------------------杀死定时器,报警此帧状态改变的数据,此时的计数器的值为",timeEle.N)
                  flagTime = "12"
                  args.RuleResult["timeLabel"] = flagTime
                  delete(TimeEleList,k)
               } else {
                  delete(TimeEleList,k)
               }
            }
         }
      }
   } else { // 无定时器
      if result {
         flagTime = "01"
         args.RuleResult["timeLabel"] = flagTime
      } else {
         flagTime = "00"
      }
   }
   return flagTime
@@ -611,7 +633,7 @@
}
// 联动任务的处理
func LinkTask(args *SdkDatas, groupRule *protomsg.GroupRule, taskId string) {
func LinkTask(args *SdkDatas, groupRule *protomsg.GroupRule, taskId string,message *protomsg.SdkMessage) {
   // new一个定时器,如果以此groupId为标志的定时器不存在的话
   logger.Info("------------------------------------------当前是联动任务,规则是:", groupRule.GroupText)
   var flag bool = true
@@ -641,7 +663,7 @@
      }
   }
   // 往数组里赋值
   isOk := RunRule(args, groupRule, taskId)
   isOk := RunRule(args, groupRule, taskId,message)
   if isOk {
      logger.Info("这帧图像在任务下的一整条规则下(联动任务下就是跟本摄像机像相关的小规则)的判断结果为true")
      // 根据cameraId去更新或者插入结果,然后判断是否数组是否可以得出报警的结论
@@ -714,7 +736,7 @@
            for _, obj := range am.filterData {
               for index := 0; index < len(obj.Liker); {
                  // 将达不到阈值的相似者从相似者数组中删除
                  logger.Warn("=======================相似值:", float64(obj.Liker[index].CompareScore*100))
                  logger.Debug("=======================相似值:", float64(obj.Liker[index].CompareScore*100))
                  if float64(obj.Liker[index].CompareScore*100) < argValue {
                     // Go 语言中切片删除元素的本质是:以被删除元素为分界点,将前后两个部分的内存重新连接起来。不用怀疑,数组删除元素就这么坑爹
                     obj.Liker = append(obj.Liker[:index], obj.Liker[index+1:]...)
@@ -742,7 +764,7 @@
            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("---------------------------终于等到你")
                  //logger.Info("---------------------------终于等到你")
                  var args []*Arg
                  if rule.RuleWithPre == "&&" {
                     args = am.filterData
@@ -751,7 +773,7 @@
                  }
                  // 先清空过滤后的数据,再往里塞本次过滤后的数据
                  am.filterData = am.filterData[0:0]
                  logger.Info("-----------------------人脸过滤的args里的数量:", len(args))
                  //logger.Info("-----------------------人脸过滤的args里的数量:", len(args))
                  for _, arg := range args {
                     var formula string
                     if rule.SdkArgAlias == "score" {
@@ -800,6 +822,7 @@
            }
            // 先清空过滤后的数据,再往里塞本次过滤后的数据
            am.filterData = am.filterData[0:0]
            logger.Debug("看看args:::::",args)
            for _, arg := range args {
               var formula string
               if rule.SdkArgAlias == "score" {
@@ -836,7 +859,7 @@
}
// 如果有持续时间条件维护开启一个定时器
func duration(rule *protomsg.Rule, groupId string, am *AreaMap, args *SdkDatas) {
func duration(rule *protomsg.Rule, groupId string, am *AreaMap, args *SdkDatas,message *protomsg.SdkMessage) {
   if rule.PolygonId == am.areaId { // 首先规则所对应的区域id要跟区域数据的id对的上  配置的算法要对的上
      if rule.SdkArgAlias == "duration" { //
         // 先看看定时器元素队列中是否有这个摄像机这个区域的定时器,如果有就不能再次创建了
@@ -850,7 +873,7 @@
         if flag {
            timeLength, _ := strconv.Atoi(rule.SdkArgValue)
            timeEle := TimeElement{N: timeLength, InitN: timeLength, AlarmFlag: false, CacheSdkData: *args} // 扔进去一个定时器元素(并缓存当前画面帧数据)
            timeEle := TimeElement{N: timeLength, InitN: timeLength, AlarmFlag: false, CacheSdkData: &ResultMsg{message,args.RuleResult}} // 扔进去一个定时器元素(并缓存当前画面帧数据)
            //TimeEleList = make(map[string]timeElement)
            TimeEleList[groupId+" "+rule.Id] = &timeEle // 定时器元素以摄像机id拼接区域id为键
            logger.Info("创建了计数器并且计数器集合为:", TimeEleList)