---
panlei
2019-12-16 b9d95191e0326a1a75f3809d75b94638c47c3d43
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
package ruleserver
 
import (
    "basic.com/pubsub/protomsg.git"
    "github.com/knetic/govaluate"
    "plugin"
    "ruleprocess/cache"
    "basic.com/valib/logger.git"
    "ruleprocess/structure"
    "sort"
    "strconv"
    "sync"
)
 
 
var rw sync.RWMutex // 读写锁
 
// 对单帧图像的判断 thisSdkDatas  当前传入的这帧数据,cacheSdkData 定时器里缓存的一帧数据 没有就返回nil  (thisSdkDatas SdkDatas, cacheSdkDatas SdkDatas)
func Judge(args *structure.SdkDatas, message *protomsg.SdkMessage) {
    defer func() {
        if err := recover(); err != nil {
            logger.Error("规则模块儿的异常捕获:",err)
        }
    }()
    if len(args.Sdkdata) > 0 {
        // 拿到本摄像机的区域
        cameraPolygons := GetPolygons(args.CameraId)
        // 把所有的sdk提取的数据都按所属摄像机的区域归置
        logger.Debug("当前摄像机id为:",message.Cid,"当前摄像机执行的任务是:",message.Tasklab.Taskname,"--任务id为:",message.Tasklab.Taskid)
        CallReadyData(args,cameraPolygons)
        // 跑本摄像机的所有规则组 一组一组跑
        taskGroup := GetRuleGroup(args.CameraId, args.TaskId) // 本摄像机本任务下所有规则组
        //logger.Println("看下摄像机下的任务组:",taskRuleList)
        // 得到属于该摄像机的若干组任务的完整规则(跟每一条完整规则比较之后得出本张图像对于某个规则是否报警的结果。放进map,比如本帧图像的id,所碰撞成功的规则id)
        args.RuleResult = make(map[string]interface{})
        args.RuleResult["yolo"] = []structure.Result{}
        args.RuleResult["face"] = []structure.Result{}
        args.RuleResult["target"] = []structure.Result{}
        args.RuleResult["plate"] = []structure.Result{}
        args.RuleResult["track"] = []structure.Result{}
        //logger.Warn("传进去之前是什么德行:",args.RuleResult["yolo"])
        if taskGroup != nil && len(taskGroup.GroupRules) > 0 {
            // 先过独立,再过联动
            for _, group := range taskGroup.GroupRules {
                //logger.Println("------------------------------任务规则:",taskRule)
                taskId := taskGroup.TaskId
                //logger.Println("------------本组任务下的规则组的数量:",len(ruleList))
                temp := group.Rules // temp为一组完整规则 在此需要判断规则是否是联动规则
                label := structure.Others{}
                if len(temp) > 0 {
                    if group.SetType != "linkTask" {
                        // 独立任务的处理
                        RunRule(args, group, taskId, message, label)
                    }
                }
            }
            for _, group := range taskGroup.GroupRules {
                //logger.Println("------------------------------任务规则:",taskRule)
                taskId := taskGroup.TaskId
                //logger.Println("------------本组任务下的规则组的数量:",len(ruleList))
                temp := group.Rules // temp为一组完整规则 在此需要判断规则是否是联动规则
                label := structure.Others{}
                if len(temp) > 0 {
                    if group.SetType == "linkTask" {
                        // groupId中含有link则为联动任务
                        LinkTask(args, group, taskId, message, label)
                    }
                }
            }
            // 人体追踪
            // 如果标签中含有持续时间首次报警的timeLabel的话则不需要过人体追踪,不然就没的插入了
            fk := TrackOrNot(args.RuleResult)
            if !fk {
                BodyIsSame(args,message)
            }
        }
    }
}
 
func CallMiddleware(args *structure.SdkDatas,rule protomsg.GroupRule,lable *structure.Others,message *protomsg.SdkMessage) (bool, 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,label *structure.Others,message *protomsg.SdkMessage)(bool,string, string))(args,rule,lable,message)
    return a,b,c
}
 
func CallReadyData(args *structure.SdkDatas,cameraPolygons []protomsg.CameraPolygon) {
    p,err :=  plugin.Open("./algorithm/middleware.so")
    if err != nil {
        panic(err)
    }
    f,err1 := p.Lookup("ReadData")
    if err1 != nil {
        panic("没有找到中间件的数据准备函数")
    }
    f.(func(args *structure.SdkDatas,cameraPolygons []protomsg.CameraPolygon)())(args,cameraPolygons)
}
 
func RunRule(args *structure.SdkDatas, groupRule *protomsg.GroupRule, taskId string, message *protomsg.SdkMessage, label structure.Others) (bool,[]int) {
    defer func() {
        if err := recover(); err != nil {
            logger.Error("比对规则有误", err)
        }
    }()
    logger.Info("+++++++++++规则开始运行+++++++++++++++++当前大规则--:", (*groupRule).GroupText)
    //logger.Warn("传进去之后是什么德行:",args.RuleResult["yolo"])
    Compare(args, groupRule)
    result := false
    sdkNames := ""
    polygonId := ""
 
    // 把一帧数据和一组规则发给算法部分,得出判断结果
    result,sdkNames,polygonId = CallMiddleware(args,*groupRule,&label,message)
 
    if result {
 
        // 最后过持续时间等时间维度的条件   把时间规则位置调整到这个位置是为了缓存数据         !!!!!ps: 对画面中单个目标做定时器的不用再过画面定时器
        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
                if ipcId == sdkData.IpcId {
                    for _, areaMap := range sdkData.AreaMapList {
                        // 去开启一个定时器
                        duration(groupRule.Rules[j], groupRule.GroupId, areaMap, args, message,label)
                    }
                }
            }
        }
        // 进行定时器的处理和判断
        timeFlag := TimerAlarm(&label, groupRule.GroupId, result)
        if timeFlag == "01" || timeFlag == "10" || timeFlag == "11"{ // 没有定时器或者满足定时器条件
            labelTypes := AssembResultLabel(args,groupRule,sdkNames,taskId,polygonId,label)
            return true,labelTypes
        } else {
            return false,[]int{}
        }
 
    } else {
        // 结果为假时也要走,有杀死定时器的操作
        TimerAlarm(&label, groupRule.GroupId, result)
        //fmt.Println(timeFlag)
        //logger.Info("不符合规则")
        return false,[]int{}
    }
}
 
func putFaceToResult(am *structure.AreaMap, faceList []*structure.Arg) []*structure.Arg {
    faces := []*structure.Arg{}
    if len(am.FilterData) > 0 {
        for _, data := range am.FilterData {
            flag := true
            for _, face := range faceList {
                if data.Location.X == face.Location.X && data.Location.Y == face.Location.Y && data.Location.Width == face.Location.Width && data.Location.Height == face.Location.Height {
                    flag = false
                }
            }
            if flag {
                faces = append(faces, data)
            }
        }
    }
    return faces
}
 
func putYolosToResult(am *structure.AreaMap) []*structure.Arg {
    locations := []*structure.Arg{}
    if len(am.FilterData) > 0 {
        locations = am.FilterData
    }
    return locations
}
func putTargetsToResult(am *structure.AreaMap) []*structure.Arg {
    locations := []*structure.Arg{}
    if len(am.AlarmObj) > 0 {
        locations = am.AlarmObj
    }
    return locations
}
// 联动任务的处理
func LinkTask(args *structure.SdkDatas, groupRule *protomsg.GroupRule, taskId string, message *protomsg.SdkMessage, label structure.Others) {
    // new一个定时器,如果以此groupId为标志的定时器不存在的话
    logger.Info("------------------------------------------当前是联动任务,规则是:", groupRule.GroupText)
    var flag bool = true
    var timeEle = TimeElement{N: 2, InitN: 2, GroupId: groupRule.GroupId}
    rw.Lock()
    for k, timeEle1 := range TimeEleList {
        if k == groupRule.GroupId {
            flag = false // 已经有了这个定时器就置为false 不再新增
            timeEle = *timeEle1
        }
    }
    //for _,ruleRe := range timeEle.RuleResults {
    //    logger.Info("联动数组里的数据----",ruleRe.CameraId,ruleRe.Sort)
    //}
    if flag { // 如果还没有这个定时器元素就新增一个
        //timeEle := TimeElement{N: 2, InitN: 2, GroupId: groupRule.GroupId} // 扔进去一个定时器元素
        //TimeEleList = make(map[string]timeElement)
        TimeEleList[groupRule.GroupId] = &timeEle // 定时器元素以规则组id为键
        //logger.Info("---------------------------------------------联动任务创建了计数器并且计数器集合为:", TimeEleList)
        // 得出这组完整规则里涉及到几个摄像机,决定着数组里有几个结构体,去重添加方式
        for j := 0; j < len(groupRule.Rules); j++ {
            var flag1 bool = true
            //logger.Info("规则组信息:",groupRule.Rules[j].CameraId)
            for _, ruleRes := range TimeEleList[groupRule.GroupId].RuleResults {
                //logger.Info("联动数组里的数据:",ruleRes.CameraId,ruleRes.Sort)
                if groupRule.Rules[j].CameraId == ruleRes.CameraId {
                    flag1 = false
                }
            }
            if flag1 {
                TimeEleList[groupRule.GroupId].RuleResults = append(TimeEleList[groupRule.GroupId].RuleResults, &RuleResult{groupRule.Rules[j].CameraId, groupRule.Rules[j].Sort, "", groupRule.Rules[j].RuleWithPre, structure.ResultMsg{}})
            }
        }
    }
    rw.Unlock()
    // 往数组里赋值
    isOk,labelTypes := RunRule(args, groupRule, taskId, message, label)
    if isOk {
        logger.Info("这帧图像在任务下的一整条规则下(联动任务下就是跟本摄像机像相关的小规则)的判断结果为true")
        // 根据cameraId去更新或者插入结果,然后判断是否数组是否可以得出报警的结论
        // 往联动任务的结果数组里放值或更新
        for _, va := range timeEle.RuleResults {
            if va.CameraId == args.CameraId {
                va.Result = strconv.FormatBool(isOk)
                tempMap := make(map[string]interface{})
                for k, result := range args.RuleResult {
                    if k == "yolo" {
                        tempMap[k] = []structure.Result{}
                        for _, res := range result.([]structure.Result) {
                            tempMap[k] = append(tempMap[k].([]structure.Result), res)
                        }
                    }
                    if k == "face" {
                        tempMap[k] = []structure.Result{}
                        for _, res := range result.([]structure.Result) {
                            tempMap[k] = append(tempMap[k].([]structure.Result), res)
                        }
                    }
                }
                va.CacheData = structure.ResultMsg{message, tempMap}
                //logger.Info("这个摄像机--", args.CameraId, "--被赋予了result", va.Result)
            }
        }
        // 判断结果数组是否完满(即被赋值完毕)可得出报警结果
        var isPerfect = true
        for _, va := range timeEle.RuleResults {
            //logger.Info("---------------------瞅瞅当前数组________________:", *va)
            if va.Result == "" && va.RuleWithPre != "||" {
                isPerfect = false
            }
        }
        if isPerfect {
            logger.Debug("数组完满了,联动任务可以成功报警了!")
            // 将数组按sort排序
            sort.Sort(SubList(timeEle.RuleResults))
            // 排序后取各自的结果和连接符拼出规则表达式得出结果
            completeFormula := ""
            for _, va := range timeEle.RuleResults {
                completeFormula = completeFormula + va.RuleWithPre + "" + va.Result
            }
            //logger.Info("---------------------------联动任务的公式", completeFormula)
            if completeFormula != "" {
                expression, _ := govaluate.NewEvaluableExpression(completeFormula)
                result, _ := expression.Evaluate(nil) // 得到数学公式的结果
                if result.(bool) {
                    //logger.Info("___________________________________________________________________联动任务报警")
                    rw.RLock()
                    if TimeEleList[groupRule.GroupId] != nil {  // 极偶尔有情况会等于nil,不知道为啥,做个判断以防宕机
                        // 把数组里缓存的数据取出来一起报警
                        label.LinkCache = []structure.ResultMsg{}
                        for _, ruleRes := range TimeEleList[groupRule.GroupId].RuleResults {
                            label.LinkCache = append(label.LinkCache, ruleRes.CacheData)
                        }
 
                        for i := 0; i < len(args.RuleResult["yolo"].([]structure.Result)); i++ {
                            if args.RuleResult["yolo"].([]structure.Result)[i].RuleGroupId == groupRule.GroupId { // 把联动数据追加上
                                args.RuleResult["yolo"].([]structure.Result)[i].Others.LinkCache = label.LinkCache
                            }
                        }
                        for i := 0; i < len(args.RuleResult["face"].([]structure.Result)); i++ {
                            if args.RuleResult["face"].([]structure.Result)[i].RuleGroupId == groupRule.GroupId { // 把联动数据追加上
                                args.RuleResult["face"].([]structure.Result)[i].Others.LinkCache = label.LinkCache
                            }
                        }
                    }
                    rw.RUnlock()
                }
            }
        } else {
            //logger.Warn("数组不圆满不打标签")
            // 倒是把打的组规则标签给去掉了啊
            for _,val := range labelTypes {
                if val == 0 {
                    if len(args.RuleResult["yolo"].([]structure.Result)) >= 1 {
                        lens := len(args.RuleResult["yolo"].([]structure.Result))-1
                        args.RuleResult["yolo"] = args.RuleResult["yolo"].([]structure.Result)[0:lens]
                    }
                }
                if val == 1 {
                    if len(args.RuleResult["face"].([]structure.Result)) >= 1 {
                        lens := len(args.RuleResult["face"].([]structure.Result))-1
                        args.RuleResult["face"] = args.RuleResult["face"].([]structure.Result)[0:lens]
                    }
                }
            }
        }
    } else { // 没有报警,
        //logger.Info("这帧图像在任务下的一整条规则下(联动任务下就是跟本摄像机像相关的小规则)的判断结果为false")
        // 所以也要去结果数组里放值或更新   07/30备注:  不应放值,应删除定时器,等为true时再度开启
        //for _, va := range timeEle.RuleResults {
        //    if args.CameraId != "" && va.CameraId == args.CameraId {
        //        va.Result = strconv.FormatBool(isOk)
        //    }
        //}
        rw.Lock()
        for k, _ := range TimeEleList {
            if k == groupRule.GroupId {
                delete(TimeEleList, k)
                //logger.Debug("因为定时器的一帧数据结果为false,干掉定时器")
            }
        }
        rw.Unlock()
        // 因为本帧数据不符合规则,所以也不用统计结果数组里的东西
    }
}
 
// 如果有持续时间条件维护开启一个定时器
func duration(rule *protomsg.Rule, groupId string, am *structure.AreaMap, args *structure.SdkDatas, message *protomsg.SdkMessage, label structure.Others){
    // cacheId := ""
    if rule.PolygonId == am.AreaId { // 首先规则所对应的区域id要跟区域数据的id对的上  配置的算法要对的上
        if rule.SdkId == "812b674b-2375-4589-919a-5c1c3278a977" {  // 排除对画面中单个目标的算法,个体静止以及靠右行这种
            return
        }
        if rule.SdkArgAlias == "duration" {
            //logger.Info("当前小规则是:---------", rule)
            // 先看看定时器元素队列中是否有这条规则的定时器,如果有就不能再次创建了
            rw.Lock()
            var flag bool = true
            for k, _ := range TimeEleList {
                if k == groupId+"+"+rule.Id {
                    flag = false // 有就置为false
                    //logger.Info("有这个定时器,不再创建了:")
                }
            }
 
            if flag {
                m := make(map[string]interface{})
                m["yolo"] = []structure.Result{}
                m["yolo"] = append(m["yolo"].([]structure.Result), structure.Result{args.TaskId, "", "", true, 0, "", am.FilterData,am.AreaJson, false,label})
                timeLength, _ := strconv.Atoi(rule.SdkArgValue)
                timeEle := TimeElement{N: timeLength, InitN: timeLength, AlarmFlag: false, BufferFlag: 10, CacheSdkData: structure.ResultMsg{message, m}} // 扔进去一个定时器元素(并缓存当前画面帧数据)
                //TimeEleList = make(map[string]timeElement)
                TimeEleList[groupId+"+"+rule.Id] = &timeEle // 定时器元素以当前持续时间小规则id为键
                //logger.Info("创建了计数器")
                //cacheId = groupId+"+"+rule.Id
            }
            rw.Unlock()
        }
    }
    return
}
 
func AssembResultLabel(args *structure.SdkDatas, groupRule *protomsg.GroupRule,sdkNames string,taskId string,polygonId string,label structure.Others) []int{
 
    faces := []*structure.Arg{}
    yolos := []*structure.Arg{}
    targets := []*structure.Arg{}
    personTrack := []*structure.Arg{}
    cars := []*structure.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 {
        switch sdkData.IpcId {
        case "A8B73405-373D-4F23-CED2-A617EBD7EC55" :
            if faceFlag { // sdkData里有人脸数据且配置了算法才把符合条件的数据塞进标签里去
                for _, areaMap := range sdkData.AreaMapList {
                    if areaMap.IsEffective {
                        faces = append(faces, putFaceToResult(areaMap, faces)...)
                    }
                }
            }
        case "02D54B61-0F16-C604-8567-FC4BE493C523":
            if sdkNames != "" { // 把yolo数据的各个目标的坐标输出方便后面画框
                for _, areaMap := range sdkData.AreaMapList {
                    if areaMap.IsEffective {
                        yolos = append(yolos, putYolosToResult(areaMap)...)
                        // 处理目标定时数据
                        targets = append(targets, putTargetsToResult(areaMap)...)
                    }
                }
            }
        case "91d923ef-6200-4549-ab1b-8e773e85d729":
            // 车辆数据
            for _, areaMap := range sdkData.AreaMapList {
                if areaMap.IsEffective {
                    cars = append(cars, putFaceToResult(areaMap, cars)...)
                }
            }
        case "807bac1b-4501-4c52-b450-0aeb75a68ded":
            // 跟踪目标
            for _, areaMap := range sdkData.AreaMapList {
                if areaMap.IsEffective {
                    personTrack = append(personTrack, putFaceToResult(areaMap, personTrack)...)
                }
            }
        }
    }
 
    var islink bool
    if groupRule.SetType == "linkTask" {
        islink = true
    } else {
        islink = false
    }
    //logger.Info("触发的区域id:",polygonId)
    var labelTypes []int // 0为yolo标签,1为face标签 2为两者标签
    if sdkNames != "" && len(targets) == 0 {
        args.RuleResult["yolo"] = append(args.RuleResult["yolo"].([]structure.Result), structure.Result{taskId, sdkNames, groupRule.GroupId, groupRule.DefenceState, groupRule.AlarmLevel, groupRule.GroupText, yolos,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.Result), structure.Result{taskId, sdkNames, groupRule.GroupId, groupRule.DefenceState, groupRule.AlarmLevel, groupRule.GroupText, faces,polygonId, islink,label})
        //logger.Info("-------------------face结果标签", len(args.RuleResult["face"].([]structure.Result)))
        labelTypes = append(labelTypes,1)
    }
    if len(targets) > 0 {
        args.RuleResult["target"] = append(args.RuleResult["target"].([]structure.Result), structure.Result{taskId, sdkNames, groupRule.GroupId, groupRule.DefenceState, groupRule.AlarmLevel, groupRule.GroupText, targets, polygonId, islink,label})
        //logger.Info("-------------------目标持续结果标签", len(args.RuleResult["target"].([]structure.Result)))
        labelTypes = append(labelTypes,2)
    }
    if len(cars) > 0 {
        args.RuleResult["plate"] = append(args.RuleResult["plate"].([]structure.Result), structure.Result{taskId, sdkNames, groupRule.GroupId, groupRule.DefenceState, groupRule.AlarmLevel, groupRule.GroupText, cars, polygonId, islink,label})
        //logger.Info("-------------------车牌结果标签", len(args.RuleResult["plate"].([]structure.Result)))
        labelTypes = append(labelTypes,3)
    }
    if len(personTrack) > 0 {
        args.RuleResult["track"] = append(args.RuleResult["track"].([]structure.Result), structure.Result{taskId, sdkNames, groupRule.GroupId, groupRule.DefenceState, groupRule.AlarmLevel, groupRule.GroupText, personTrack, polygonId, islink,label})
        //logger.Info("-------------------车牌结果标签", len(args.RuleResult["plate"].([]structure.Result)))
        labelTypes = append(labelTypes,4)
    }
    return labelTypes
}