zhangzengfei
2024-03-30 e9e0c1f3abf1bbf83ebdb933d318caa2a45c15b0
调整代码结构, 精简比对过程
6个文件已删除
7个文件已添加
1 文件已重命名
5个文件已修改
1465 ■■■■■ 已修改文件
Makefile 20 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cache/cache.go 212 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cache/compare.go 360 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cache/db.go 146 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cache/dbWatch.go 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
cache/shardmap/shardmap.go 61 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
compare/compare.go 103 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
compare/faceSdk.go 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
config/compare.yaml 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
config/config.go 53 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
config/config.yaml 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
config/dev.yaml 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
db/base.go 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
db/db.go 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
db/person.go 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
db/personStatus.go 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
discovery/cache.go 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
main.go 112 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
util/util.go 35 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Makefile
@@ -1,26 +1,12 @@
BUILD_TIME := $(shell date "+%F %T")
COMMIT_SHA1 := $(shell git rev-parse HEAD)
APP_NAME := sdkCompare
BUILD_VERSION := 1.0.0
APP_NAME := faceCompare
BUILD_VERSION := 2.0.0
PLATFORM := x86_64
export LD_LIBRARY_PATH=/opt/vasystem/libs/FaceDetect
ifeq ("$(PLATFORM)", "aarch64")
  $(info CUR_PLATFORM:$(PLATFORM))
  export CGO_ENABLED=1
  export GOOS=linux
  export GOARCH=arm64
  export CC=/opt/l4t-gcc/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc
  export CXX=/opt/l4t-gcc/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc
  export CGO_CFLAGS=--sysroot=/opt/l4t-gcc/sysroot-glibc-linaro-2.25-2018.05-aarch64-linux-gnu
  export CGO_CXXFLAGS=--sysroot=/opt/l4t-gcc/sysroot-glibc-linaro-2.25-2018.05-aarch64-linux-gnu
  export CGO_LDFLAGS=--sysroot=/opt/l4t-gcc/sysroot-glibc-linaro-2.25-2018.05-aarch64-linux-gnu -lstdc++
else
  CUR_OS :=$(shell uname -m)
  $(info CUR_PLATFORM:$(CUR_OS))
endif
all:
    go build -a -ldflags "-X 'basic.com/valib/version.git.BuildVersion=${BUILD_VERSION}' -X 'basic.com/valib/version.git.BuildTime=${BUILD_TIME}' -X 'basic.com/valib/version.git.CommitSha1=${COMMIT_SHA1}' -X 'basic.com/valib/version.git.AppName=${APP_NAME}'" -o ${APP_NAME}
    go build -v -ldflags "-X 'basic.com/valib/version.git.BuildVersion=${BUILD_VERSION}' -X 'basic.com/valib/version.git.BuildTime=${BUILD_TIME}' -X 'basic.com/valib/version.git.CommitSha1=${COMMIT_SHA1}' -X 'basic.com/valib/version.git.AppName=${APP_NAME}'" -o ${APP_NAME}
clean:
    rm -f ${APP_NAME}
.PHONY:
cache/cache.go
New file
@@ -0,0 +1,212 @@
package cache
import (
    "flag"
    "sync"
    "time"
    "sdkCompare/cache/shardmap"
    "sdkCompare/db"
    "basic.com/pubsub/protomsg.git"
    "basic.com/valib/logger.git"
)
var querynum = flag.Int("querynum", 3000, "the query number from database")
var threadnum = flag.Int("threadnum", 32, "the number of thread to deal data.")
var (
    Unfiled     = "unfiled"
    PRE_DBTABLE = "dbTable_"
)
type CmapItem struct {
    sync.Mutex
    Area map[string]*shardmap.ShardMap
}
var CacheMap *CmapItem
var doOnce sync.Once
func ReInitDbTablePersonsCache() {
    CacheMap.Lock()
    defer CacheMap.Unlock()
    if CacheMap == nil {
        CacheMap = &CmapItem{
            Area: make(map[string]*shardmap.ShardMap),
        }
    }
    for tableId, _ := range CacheMap.Area {
        delete(CacheMap.Area, tableId)
    }
    initDbTablePersonsCache()
}
func InitDbTablePersons() {
    doOnce.Do(func() {
        flag.Parse()
        CacheMap = &CmapItem{
            Area: make(map[string]*shardmap.ShardMap),
        }
        // 初始化未分类, 没有小区id的档案
        CacheMap.Area[Unfiled] = shardmap.New(uint8(*threadnum))
    })
    initDbTablePersonsCache()
}
func initDbTablePersonsCache() {
    // 缓存底库中的全部人员信息
    var dbpApi db.DbPersons
    total, e := dbpApi.GetPersonTotal("")
    var psApi db.PersonStatus
    accessAreas, _ := psApi.GetPersonAccessedAreas()
    logger.Debugf("所有底库共有%d条记录", total)
    if e == nil && total > 0 {
        queryEachNum := *querynum
        qn := int(total) / *threadnum
        if *querynum < qn {
            queryEachNum = qn
        }
        queryT := int(total) / queryEachNum
        if int(total)%queryEachNum > 0 {
            queryT++
        }
        temptime := time.Now()
        var wg sync.WaitGroup
        for i := 0; i < queryT; i++ {
            j := i * queryEachNum
            wg.Add(1)
            go func(qs int) {
                defer wg.Done()
                dbPersons, err := dbpApi.GetPersonsCompareCacheBase(j, queryEachNum)
                if err != nil {
                    logger.Error(err)
                    return
                }
                logger.Debugf("获取%d条人员信息", len(dbPersons))
                CacheMap.Lock()
                areaId := ""
                for _, value := range dbPersons {
                    areaId = value.AreaId
                    // 没有小区id的人员
                    if areaId == "" {
                        CacheMap.Area[Unfiled].Set(value.Id, value)
                        CacheMap.Area[Unfiled].Settime()
                        continue
                    }
                    for _, areaId := range accessAreas[value.Id] {
                        if _, ok := CacheMap.Area[areaId]; !ok {
                            CacheMap.Area[areaId] = shardmap.New(uint8(*threadnum))
                        }
                        CacheMap.Area[areaId].Set(value.Id, value)
                        CacheMap.Area[areaId].Settime()
                    }
                }
                CacheMap.Unlock()
            }(j)
        }
        wg.Wait()
        logger.Debug("底库人员缓存完成用时:", time.Since(temptime))
    }
}
// UpdateDbPersonsCacheById 更新缓存中的全部人员信息
func UpdateDbPersonsCacheById(id string) {
    var dbpApi db.DbPersons
    info, err := dbpApi.GetPersonsCompareCacheById(id)
    if err != nil {
        logger.Error(err)
        return
    }
    if info.Tableid != "" {
        CacheMap.Lock()
        defer CacheMap.Unlock()
        if _, ok := CacheMap.Area[info.Tableid]; !ok {
            CacheMap.Area[info.Tableid] = shardmap.New(uint8(*threadnum))
        }
        CacheMap.Area[info.Tableid].Set(info.Id, info)
        CacheMap.Area[info.Tableid].Settime()
    }
}
func RealTimeAddPersonInfoToCache(tableId string, id string, faceFeature string, enable int32, carNo string) {
    CacheMap.Lock()
    defer CacheMap.Unlock()
    if _, ok := CacheMap.Area[tableId]; !ok {
        CacheMap.Area[tableId] = shardmap.New(uint8(*threadnum))
    }
    var ei = protomsg.Esinfo{
        Id:          id,
        Tableid:     tableId,
        FaceFeature: faceFeature,
        Enable:      enable,
        CarNo:       carNo,
    }
    CacheMap.Area[tableId].Set(id, &ei)
    logger.Debug("id:", id, ",tableId:", ",len(faceFeature):", len(faceFeature), ",tableId:", tableId, ",enable:", enable)
}
func RealTimeDelPersonFromCache(tableId string, id string) {
    logger.Debug("DelPersonFromCache,tableId:", tableId, ",id:", id)
    CacheMap.Lock()
    defer CacheMap.Unlock()
    if _, ok := CacheMap.Area[tableId]; ok {
        CacheMap.Area[tableId].Del(id)
        logger.Debug("DelPerson ok success")
    } else {
        logger.Error("tableId:", tableId, " not exist")
    }
}
func RealTimeDelTable(tableId string) {
    logger.Debug("RealTimeDelTable tableId:", tableId)
    CacheMap.Lock()
    defer CacheMap.Unlock()
    if dtM, ok := CacheMap.Area[PRE_DBTABLE]; ok {
        dtM.Del(tableId)
    }
    if _, ok := CacheMap.Area[tableId]; ok {
        delete(CacheMap.Area, tableId)
    }
}
// 使底库生效,将底库中的所有生效状态的人特征添加到缓存
func RealTimeUpdateTable(tableId string, enable int32) {
    logger.Debug("RealTimeUpdateTable tableId:", tableId, ",enable:", enable)
    CacheMap.Lock()
    defer CacheMap.Unlock()
    if _, ok := CacheMap.Area[PRE_DBTABLE]; !ok {
        CacheMap.Area[PRE_DBTABLE] = shardmap.New(uint8(*threadnum))
    }
    CacheMap.Area[PRE_DBTABLE].Set(tableId, enable == 1)
}
func UpdateCache(changeMsg *protomsg.EsPersonCacheChange) {
    if changeMsg.Type == protomsg.EsCacheChanged_T_DbTable {
        if changeMsg.Action == protomsg.DbAction_Insert || changeMsg.Action == protomsg.DbAction_Update {
            RealTimeUpdateTable(changeMsg.TableId[0], changeMsg.Enable)
        } else if changeMsg.Action == protomsg.DbAction_Delete {
            RealTimeDelTable(changeMsg.TableId[0])
        }
    } else if changeMsg.Type == protomsg.EsCacheChanged_T_DbTablePerson {
        if changeMsg.Action == protomsg.DbAction_Insert || changeMsg.Action == protomsg.DbAction_Update {
            RealTimeAddPersonInfoToCache(changeMsg.TableId[0], changeMsg.PersonId, changeMsg.Feature, changeMsg.Enable, changeMsg.CarNo)
        } else if changeMsg.Action == protomsg.DbAction_Delete {
            RealTimeDelPersonFromCache(changeMsg.TableId[0], changeMsg.PersonId)
        }
    }
}
cache/compare.go
File was deleted
cache/db.go
File was deleted
cache/dbWatch.go
File was deleted
cache/shardmap/shardmap.go
@@ -4,6 +4,7 @@
import (
    "basic.com/pubsub/protomsg.git"
    "sdkCompare/db"
    "sync"
    //"encoding/json"
    //"fmt"
@@ -89,7 +90,7 @@
    value interface{}
}
func (s *ShardMap) Walk(wf wfOp, sourceFea []byte, baseScore float32, isWebComp bool, target string) (targets []*protomsg.SdkCompareEach) {
func (s *ShardMap) Walk(wf wfOp, sourceFea []byte, baseScore float32) (targets []*protomsg.SdkCompareEach) {
    var wg sync.WaitGroup
    var lock sync.Mutex
    for _, si := range s.shards {
@@ -101,57 +102,25 @@
        wg.Add(1)
        go func(st *shardItem, fw wfOp, sf []byte, baseSec float32, isWeb bool) {
        go func(st *shardItem, fw wfOp, sf []byte, baseSec float32) {
            defer wg.Done()
            for _, feature := range st.data {
                if eif, ok := feature.(*protomsg.Esinfo); ok {
                    if !isWeb { //不会比对抓拍库,只比对有效的人
                        if eif.Enable == 1 {
                            score := float32(0)
                            if target == "car" {
                                if eif.CarNo != "" {
                                    score = strComp(sf, eif.CarNo)
                                } else {
                                    continue
                                }
                            } else {
                                score = fw(sf, eif.FaceFeature)
                            }
                            if score > 0 && score >= baseScore {
                                lock.Lock()
                                targets = append(targets, &protomsg.SdkCompareEach{
                                    Id:           eif.Id,
                                    CompareScore: score,
                                    Tableid:      eif.Tableid,
                                })
                                lock.Unlock()
                            }
                        }
                    } else { //来源是web,会比对抓拍库,不管是否有效都需要比对
                        score := float32(0)
                        if target == "car" {
                            if eif.CarNo != "" {
                                score = strComp(sf, eif.CarNo)
                            } else {
                                continue
                            }
                        } else {
                            score = fw(sf, eif.FaceFeature)
                        }
                        if score > 0 && score >= baseScore {
                            lock.Lock()
                            targets = append(targets, &protomsg.SdkCompareEach{
                                Id:           eif.Id,
                                CompareScore: score,
                                Tableid:      eif.Tableid,
                            })
                            lock.Unlock()
                        }
                if eif, ok := feature.(*db.FeatureCacheBase); ok {
                    score := float32(0)
                    score = fw(sf, eif.FaceFeature)
                    if score > 0 && score >= baseScore {
                        lock.Lock()
                        targets = append(targets, &protomsg.SdkCompareEach{
                            Id:           eif.Id,
                            CompareScore: score,
                            Tableid:      eif.TableId,
                        })
                        lock.Unlock()
                    }
                }
            }
        }(&tempsi, wf, sourceFea, baseScore, isWebComp)
        }(&tempsi, wf, sourceFea, baseScore)
    }
    wg.Wait()
compare/compare.go
New file
@@ -0,0 +1,103 @@
package compare
import (
    "encoding/base64"
    "fmt"
    "strconv"
    "sdkCompare/cache"
    "basic.com/pubsub/protomsg.git"
    "basic.com/valib/logger.git"
    "github.com/golang/protobuf/proto"
)
const thresholdLimit = float32(30)
func GetComparePersonBaseInfo(args protomsg.CompareArgs) []byte {
    if args.FaceFeature == nil {
        return nil
    }
    //指定最低分
    baseScore := thresholdLimit
    if args.CompareThreshold > thresholdLimit {
        baseScore = args.CompareThreshold
    }
    if args.IsCompareAll {
        baseScore = 0
    }
    var scResult protomsg.SdkCompareResult
    var walkedArea = make(map[string]struct{}, 0)
    // 优先比对传入的小区id
    if args.TreeNodes != nil && len(args.TreeNodes) > 0 {
        for _, id := range args.TreeNodes {
            if _, ok := cache.CacheMap.Area[id]; ok {
                targets := cache.CacheMap.Area[id].Walk(DoSdkCompare, args.FaceFeature, baseScore)
                if len(targets) > 0 {
                    scResult.CompareResult = append(scResult.CompareResult, targets...)
                }
                walkedArea[id] = struct{}{}
            }
        }
        if len(scResult.CompareResult) > 0 {
            goto done
        }
    }
    // 比对以外的小区
    if !args.IsCompareAll && len(args.TreeNodes) > 0 {
        baseScore += 20
    }
    for key, val := range cache.CacheMap.Area {
        if _, ok := walkedArea[key]; ok {
            continue
        }
        targets := val.Walk(DoSdkCompare, args.FaceFeature, baseScore)
        if len(targets) > 0 {
            scResult.CompareResult = append(scResult.CompareResult, targets...)
        }
    }
done:
    logger.Debugf("比对结果 %d条", len(scResult.CompareResult))
    buf, err := proto.Marshal(&scResult)
    if err != nil {
        logger.Error("scResult Marshal error!", err)
        return nil
    }
    return buf
}
func DoSdkCompare(ci []byte, co string) float32 {
    co_d, err := base64.StdEncoding.DecodeString(co)
    if err != nil {
        logger.Error("DoSdkCompare err:", err)
        return -1
    }
    sec := DecCompare(ci, co_d)
    //logger.Debug("比对得分为:", sec)
    sec = ParseScore(sec)
    return sec
}
func ParseScore(compareScore float32) float32 {
    if compareScore <= 1 {
        compareScore = compareScore * 100
    }
    if compareScore == 100 {
        return 100
    }
    f, _ := strconv.ParseFloat(fmt.Sprintf("%2.2f", compareScore), 32)
    return float32(f)
}
compare/faceSdk.go
File was renamed from face/faceCompare.go
@@ -1,4 +1,4 @@
package face
package compare
import (
    "unsafe"
config/compare.yaml
New file
@@ -0,0 +1,13 @@
database:
    servePort: 4010
    mysqlAddr: 192.168.20.119
    username: root
    password: c++java123
    database: faceanalysis
    personTable: dbtablepersons
log:
    path: ./log/
    level: -1
    maxSize: 128
    maxBackups: 30
    maxAge: 15
config/config.go
@@ -1,33 +1,14 @@
package config
import (
    "fmt"
    "basic.com/valib/logger.git"
    "github.com/fsnotify/fsnotify"
    "github.com/spf13/viper"
    "log"
)
type server struct {
    AnalyServerId  string `mapstructure:"analyServerId"`
    NetworkAdapter string `mapstructure:"networkAdapter"`
}
var Server = &server{}
type esinfo struct {
    EsIndex esindexlist `mapstructure:"index"`
}
type esindexlist struct {
    AiOcean index `mapstructure:"aiOcean"`
}
type index struct {
    IndexName string `mapstructure:"index"`
    IndexType string `mapstructure:"type"`
}
type dbpersoncompare struct {
type database struct {
    MysqlAddr   string `mapstructure:"mysqlAddr"`
    Username    string `mapstructure:"username"`
    Password    string `mapstructure:"password"`
@@ -36,17 +17,7 @@
    ServePort   int    `mapstructure:"servePort"`
}
type espersoncompare struct {
    ServePort int    `mapstructure:"servePort"`
    ESIP      string `mapstructure:"esip"`
    ESPort    string `mapstructure:"esPort"`
}
var DbPersonCompInfo = &dbpersoncompare{}
var EsCompServerInfo = &espersoncompare{}
var EsInfo = &esinfo{}
var DbPersonCompInfo = &database{}
type LogConfig struct {
    Path       string `mapstructure:"path"`       //日志存储路径
@@ -58,29 +29,31 @@
var LogConf = &LogConfig{}
func Init(env string) {
func Init() error {
    var err error
    v := viper.New()
    v.SetConfigType("yaml")
    v.SetConfigName(env)
    v.SetConfigName("compare")
    v.AddConfigPath("./")
    v.AddConfigPath("./config/")
    err = v.ReadInConfig()
    if err != nil {
        log.Fatal("error on parsing configuration file")
        fmt.Printf("error on parsing configuration file, %s, config file compare.yaml\n", err.Error())
        return err
    }
    read2Conf(v)
    v.WatchConfig()
    v.OnConfigChange(func(in fsnotify.Event) {
        read2Conf(v)
    })
    return nil
}
func read2Conf(v *viper.Viper) {
    v.UnmarshalKey("es", EsInfo)
    v.UnmarshalKey("server", Server)
    v.UnmarshalKey("dbpersoncompare", DbPersonCompInfo)
    v.UnmarshalKey("espersoncompare", EsCompServerInfo)
    v.UnmarshalKey("database", DbPersonCompInfo)
    v.UnmarshalKey("log", LogConf)
    logger.SetLevel(LogConf.Level)
}
config/config.yaml
File was deleted
config/dev.yaml
File was deleted
db/base.go
New file
@@ -0,0 +1,18 @@
package db
type BaseEntity struct {
    Id         string `gorm:"primary_key;column:id" json:"id" example:""`
    CreateTime string `gorm:"column:createTime" json:"createTime,omitempty" example:""`
    UpdateTime string `gorm:"column:updateTime" json:"updateTime,omitempty" example:""`
    CreateBy   string `gorm:"column:createBy" json:"createBy,omitempty" example:""`
    IsDelete   int    `gorm:"column:isDelete" json:"isDelete" example:"0 未删除 1已删除"`
    Enable     int    `gorm:"column:enable" json:"enable" example:" 1生效 0未生效"`
}
type FeatureCacheBase struct {
    Id          string
    AreaId      string
    TableId     string
    FaceFeature string
    Enable      int32
}
db/db.go
New file
@@ -0,0 +1,39 @@
package db
import (
    "fmt"
    "sdkCompare/config"
    "basic.com/valib/logger.git"
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
)
var db *gorm.DB
func ConnectDB() error {
    var err error
    dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4",
        config.DbPersonCompInfo.Username,
        config.DbPersonCompInfo.Password,
        config.DbPersonCompInfo.MysqlAddr,
        config.DbPersonCompInfo.Database)
    db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
        // 禁用外键(指定外键时不会在mysql创建真实的外键约束)
        DisableForeignKeyConstraintWhenMigrating: true,
        //// 指定表前缀
        //NamingStrategy: schema.NamingStrategy{
        //    TablePrefix: config.Conf.Mysql.TablePrefix + "_",
        //},
    })
    if err != nil {
        logger.Error("mysql database open err: %s", err.Error())
        return err
    }
    return nil
}
db/person.go
New file
@@ -0,0 +1,87 @@
package db
import (
    "basic.com/pubsub/protomsg.git"
    "strconv"
)
type DbPersons struct {
    BaseEntity
    TableId            string   `gorm:"column:tableId" json:"tableId" example:"库表id"`
    FaceFeature        string   `gorm:"column:faceFeature" json:"faceFeature" example:"人脸特征值(车主特征)"`
    PersonPicUrl       string   `gorm:"column:personPicUrl" json:"personPicUrl" example:"图片路径,(车主照片)"`
    PersonName         string   `gorm:"column:personName" json:"personName" example:"人员姓名,(车主姓名)"`
    Age                string   `gorm:"column:age" json:"age"  example:"年龄"`
    Sex                string   `gorm:"column:sex" json:"sex" example:"性别 男 女(车主性别)"`
    IdCard             string   `gorm:"column:idCard" json:"idCard" example:"身份证(车主身份证)"`
    PhoneNum           string   `gorm:"column:phoneNum" json:"phoneNum" example:"手机号码"`
    MonitorLevel       string   `gorm:"column:monitorLevel" json:"monitorLevel" example:"等级"`
    PicDesc            string   `gorm:"column:picDesc" json:"picDesc" example:"照片标识"`
    Reserved           string   `gorm:"column:reserved" json:"reserved" example:"其他"`
    FromServerId       string   `gorm:"column:fromServerId" json:"fromServerId,omitempty" example:"入库serverId"`
    ResidentialArea    string   `gorm:"column:residential_area;type:varchar(255)" json:"residentialArea" example:"小区"`
    Community          string   `gorm:"column:community;type:varchar(255)" json:"community" example:"社区"`
    LastAppearanceTime int64    `gorm:"column:last_appearance_time;type:int;not null;default:0" json:"lastAppearanceTime" example:"123456789"`
    SnapshotCount      int      `gorm:"column:snapshot_count;type:varchar(255)" json:"snapshotCount" example:"10" comment:"抓拍次数"`
    DaysAppeared       int      `gorm:"column:days_appeared;type:int(11);not null;default:0" json:"daysAppeared" example:"5" comment:"出现天数"`
    Location           string   `gorm:"column:location;type:varchar(255)" json:"location" example:"建档地点" comment:"建档地点"`
    LastLocation       string   `gorm:"column:last_location;type:varchar(255)" json:"lastLocation" example:"最后出现地点" comment:"最后出现地点"`
    FaceAngleYaw       int      `gorm:"column:face_angle_yaw;type:int(11)" json:"faceAngleYaw" example:"15" comment:"人脸角度偏航角"`
    FaceAngleRoll      int      `gorm:"column:face_angle_roll;type:int(11)" json:"faceAngleRoll" example:"16" comment:"人脸角度滚转角"`
    FaceAnglePitch     int      `gorm:"column:face_angle_pitch;type:int(11)" json:"faceAnglePitch" example:"15" comment:"人脸角度俯仰角"`
    PersonalStatusName string   `gorm:"column:personal_status;type:varchar(31);comment:AI标签" json:"-"` //AI标签
    PersonalStatus     string   `gorm:"-" json:"personalStatus"`                                       //AI标签对应名称
    Labels             []string `gorm:"-" json:"labels"`                                               //手动添加的标签对应名称
    AreaID             string   `json:"areaID" gorm:"index;column:communityID;type:varchar(299);"`     //常驻小区 domain unit ID
    OrgID              string   `json:"orgID" gorm:"index;column:org_id;type:varchar(299);"`           //常驻派出所 domain unit ID
}
func (dbp *DbPersons) GetPersonTotal(tableId string) (total int64, err error) {
    sql := "select count(1) as total from dbtablepersons where isDelete=0 and tableId in (select id from dbtables where isDelete=0)"
    if tableId != "" {
        sql += " and tableId='" + tableId + "'"
    }
    err = db.Raw(sql).Count(&total).Error
    return
}
func (dbp *DbPersons) GetPersonsCompareCacheBase(from int, size int) (arr []*FeatureCacheBase, err error) {
    var persons []DbPersons
    sql := "select id, tableId, faceFeature, communityID, enable from dbtablepersons where isDelete=0 and tableId in (select id from dbtables where isDelete=0)"
    sql += " order by id asc limit " + strconv.Itoa(from) + "," + strconv.Itoa(size)
    err = db.Raw(sql).Find(&persons).Error
    if err != nil {
        return nil, err
    }
    for _, p := range persons {
        if p.FaceFeature != "" {
            arr = append(arr, &FeatureCacheBase{
                Id:          p.Id,
                TableId:     p.TableId,
                AreaId:      p.AreaID,
                FaceFeature: p.FaceFeature,
                Enable:      int32(p.Enable),
            })
        }
    }
    return
}
func (dbp *DbPersons) GetPersonsCompareCacheById(id string) (info *protomsg.Esinfo, err error) {
    sql := "select id,faceFeature,tableId,enable from dbtablepersons where id = \"" + id + "\""
    var p DbPersons
    err = db.Raw(sql).First(&p).Error
    if err != nil {
        return nil, err
    }
    if p.FaceFeature != "" {
        info = &protomsg.Esinfo{
            Id:          p.Id,
            Tableid:     p.TableId,
            FaceFeature: p.FaceFeature,
            Enable:      int32(p.Enable),
        }
    }
    return
}
db/personStatus.go
New file
@@ -0,0 +1,27 @@
package db
type PersonStatus struct {
    CommunityID     string `gorm:"column:communityID;type:varchar(299);"`      //常驻小区
    DocumentNumber  string `gorm:"column:documentNumber;type:varchar(299);"`   //档案编号
    Status          string `gorm:"column:status"`                              //标签
    FrequentAddress string `gorm:"column:frequentAddress; type:varchar(299);"` //常驻地址
}
func (ps *PersonStatus) TableName() string {
    return "person_status"
}
func (ps *PersonStatus) GetPersonAccessedAreas() (map[string][]string, error) {
    var results []PersonStatus
    err := db.Table(ps.TableName()).Find(&results).Error
    if err != nil {
        return nil, err
    }
    var communityMap = make(map[string][]string, 0)
    for _, p := range results {
        communityMap[p.DocumentNumber] = append(communityMap[p.DocumentNumber], p.CommunityID)
    }
    return communityMap, nil
}
discovery/cache.go
File was deleted
main.go
@@ -3,15 +3,15 @@
import (
    "context"
    "flag"
    "os"
    "path"
    "path/filepath"
    "sdkCompare/proto/facecompare"
    "strconv"
    "time"
    "sdkCompare/cache"
    "sdkCompare/compare"
    "sdkCompare/config"
    "sdkCompare/db"
    "sdkCompare/proto/facecompare"
    "basic.com/pubsub/protomsg.git"
    "basic.com/valib/logger.git"
@@ -23,36 +23,27 @@
    "nanomsg.org/go-mangos/transport/tcp"
)
var (
    envirment   string
    procName    string
    targetType1 string
)
const procName = "faceCompare"
func init() {
    flag.StringVar(&envirment, "e", "config", "")
    flag.StringVar(&targetType1, "targetType1", "FaceDetect", "cache feature")
    flag.Parse()
    vaversion.Usage()
}
    config.Init(envirment)
func main() {
    err := config.Init()
    if err != nil {
        return
    }
    procName = filepath.Base(os.Args[0])
    var logFile = path.Join(config.LogConf.Path, procName+".log")
    var logFile = path.Join(config.LogConf.Path, "faceCompare.log")
    // 日志初始化
    logger.InitLogger(logFile, config.LogConf.Level, config.LogConf.MaxSize, config.LogConf.MaxBackups, config.LogConf.MaxAge)
    logger.Info("logger init success !")
}
func main() {
    //esutil.InitLog(logger.Debug)
    logger.Debug("This is a new server about sdk compare, proc name ", procName)
    serveUrl := "tcp://0.0.0.0:"
    if err := cache.ConnectDB(); err != nil {
    if err := db.ConnectDB(); err != nil {
        logger.Error(err.Error())
        return
    }
@@ -60,7 +51,7 @@
    cache.InitDbTablePersons()
    serveUrl = serveUrl + strconv.Itoa(config.DbPersonCompInfo.ServePort)
    logger.Debugf("%s serve url:%s", procName, serveUrl)
    logger.Infof("%s serve url:%s", procName, serveUrl)
    Recv(serveUrl)
}
@@ -73,6 +64,7 @@
    if sock, err = rep.NewSocket(); err != nil {
        logger.Error("new rep socket err:", err)
    }
    sock.AddTransport(ipc.NewTransport())
    sock.AddTransport(tcp.NewTransport())
    if err = sock.Listen(url); err != nil {
@@ -82,54 +74,54 @@
    for {
        select {
        case <-ctx.Done():
            logger.Debug("ctx done")
            logger.Info("ctx done")
            return
        default:
            msg, err = sock.Recv()
            if err != nil {
            if err != nil || len(msg) <= 0 {
                continue
            }
            if len(msg) > 0 {
                var compareType facecompare.CompareRequest
                err = proto.Unmarshal(msg, &compareType)
                if err != nil {
                    logger.Error("compareType json unmarshal error")
            var request facecompare.CompareRequest
            err = proto.Unmarshal(msg, &request)
            if err != nil {
                logger.Warn("CompareRequest json unmarshal error")
                continue
            }
            var result []byte
            if request.CompareType == facecompare.CompareType_Compare {
                var compareArgInfo protomsg.CompareArgs
                var cacheChangeInfo protomsg.EsPersonCacheChange
                if err = proto.Unmarshal(request.Payload, &compareArgInfo); err == nil {
                    timeStart := time.Now()
                    result = compare.GetComparePersonBaseInfo(compareArgInfo)
                    logger.Debug("用时:", time.Since(timeStart))
                } else if err = proto.Unmarshal(request.Payload, &cacheChangeInfo); err == nil {
                    cache.UpdateCache(&cacheChangeInfo)
                } else {
                    logger.Warn("CompareArgs or EsPersonCacheChange json unmarshal error")
                    continue
                }
                var result []byte
                if compareType.CompareType == facecompare.CompareType_Compare {
                    var compareArgInfo protomsg.CompareArgs
                    var cacheChangeInfo protomsg.EsPersonCacheChange
                    if err = proto.Unmarshal(compareType.Payload, &compareArgInfo); err == nil {
                        timeStart := time.Now()
                        result = cache.GetComparePersonBaseInfo(compareArgInfo)
                        logger.Debug("用时:", time.Since(timeStart))
                    } else if err = proto.Unmarshal(compareType.Payload, &cacheChangeInfo); err == nil {
                        cache.UpdateCache(&cacheChangeInfo)
                    } else {
                        logger.Error("CompareArgs or EsPersonCacheChange json unmarshal error")
                        continue
            } else if request.CompareType == facecompare.CompareType_UpdateCache {
                var compareEvent protomsg.CompareEvent
                if err = proto.Unmarshal(request.Payload, &compareEvent); err == nil {
                    if compareEvent.EventType == protomsg.CompareEventType_ReInitCache { //加入集群后重新初始化缓存
                        cache.ReInitDbTablePersonsCache()
                    } else if compareEvent.EventType == protomsg.CompareEventType_UpdateCache { //库中新增更新缓存
                        id := string(compareEvent.Payload)
                        cache.UpdateDbPersonsCacheById(id)
                        logger.Info("--------------更新人员缓存, id: ", id)
                    }
                } else if compareType.CompareType == facecompare.CompareType_UpdateCache {
                    var compareEvent protomsg.CompareEvent
                    if err = proto.Unmarshal(compareType.Payload, &compareEvent); err == nil {
                        if compareEvent.EventType == protomsg.CompareEventType_ReInitCache { //加入集群后重新初始化缓存
                            cache.ReInitDbTablePersonsCache()
                        } else if compareEvent.EventType == protomsg.CompareEventType_UpdateCache { //库中新增更新缓存
                            id := string(compareEvent.Payload)
                            cache.UpdateDbPersonsCacheById(id)
                            logger.Debug("--------------更新人员缓存, id: ", id)
                        }
                    } else {
                        logger.Error("CompareEvent json unmarshal error")
                        continue
                    }
                } else {
                    logger.Warn("CompareEvent json unmarshal error")
                    continue
                }
                err = sock.Send(result)
                if err != nil {
                    logger.Error("send reply err:", err.Error())
                }
            }
            err = sock.Send(result)
            if err != nil {
                logger.Warn("send reply err:", err.Error())
            }
        }
    }
util/util.go
@@ -8,34 +8,34 @@
)
// 获取本机网卡IP
func GetLocalIP(networkName string) (ipv4 string,mask string, err error) {
func GetLocalIP(networkName string) (ipv4 string, mask string, err error) {
    interfaces, err := net.Interfaces()
    if err != nil {
        return "","", err
        return "", "", err
    }
    for _, i := range interfaces {
        byName, err := net.InterfaceByName(i.Name)
        if err != nil {
            return "","", err
            return "", "", err
        }
        addresses, err := byName.Addrs()
        for _, v := range addresses {
            if ipnet, ok:=v.(*net.IPNet);ok && !ipnet.IP.IsLoopback(){
                if ipnet.IP.To4() !=nil{
                    if byName.Name == networkName{
            if ipnet, ok := v.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
                if ipnet.IP.To4() != nil {
                    if byName.Name == networkName {
                        maskStr := ipnet.Mask.String()
                        mask64, _ := strconv.ParseUint(maskStr, 16, 32)
                        return ipnet.IP.String(),IpIntToString(int(mask64)),nil
                        return ipnet.IP.String(), IpIntToString(int(mask64)), nil
                    }
                }
            }
        }
    }
    return "","", errors.New("ipv4 not found")
    return "", "", errors.New("ipv4 not found")
}
func IpIntToString(ipInt int) string{
func IpIntToString(ipInt int) string {
    ipSegs := make([]string, 4)
    var len int = len(ipSegs)
    buffer := bytes.NewBufferString("")
@@ -53,3 +53,20 @@
    }
    return buffer.String()
}
// 判断一个数组是否包含另一个数组的所有元素
func ArrayContains(list []string, arr []string) bool {
    c := 0
    if arr == nil || list == nil {
        return false
    }
    for _, s := range arr {
        for _, t := range list {
            if s == t {
                c++
                break
            }
        }
    }
    return c == len(arr)
}