|
|
package service
|
|
|
|
|
|
import (
|
|
|
"bytes"
|
|
|
"fmt"
|
|
|
"github.com/beego/beego/v2/adapter/utils"
|
|
|
"github.com/gookit/event"
|
|
|
"github.com/linmadan/egglib-go/core/application"
|
|
|
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/factory"
|
|
|
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/application/terminal/command"
|
|
|
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/domain"
|
|
|
"gitlab.fjmaimaimai.com/allied-creation/allied-creation-user/pkg/log"
|
|
|
"io"
|
|
|
)
|
|
|
|
|
|
var GlobalTerminalManager *TerminalManager
|
|
|
|
|
|
func init() {
|
|
|
GlobalTerminalManager = NewTerminalManager()
|
|
|
event.On(domain.UserCreateEvent, event.ListenerFunc(GlobalTerminalManager.SyncUser))
|
|
|
event.On(domain.UserUpdateEvent, event.ListenerFunc(GlobalTerminalManager.SyncUser))
|
|
|
event.On(domain.UserEnableEvent, event.ListenerFunc(GlobalTerminalManager.EnableUser))
|
|
|
event.On(domain.UserSyncEvent, event.ListenerFunc(GlobalTerminalManager.SyncUser))
|
|
|
event.On(DownEntityEvent, event.ListenerFunc(GlobalTerminalManager.DownEntityEvent))
|
|
|
}
|
|
|
|
|
|
type TerminalService struct {
|
|
|
}
|
|
|
|
|
|
func NewTerminalService(options map[string]interface{}) *TerminalService {
|
|
|
newUserService := &TerminalService{}
|
|
|
return newUserService
|
|
|
}
|
|
|
|
|
|
func (svr *TerminalService) TerminalReport(cmd *command.TerminalReportCommand) (interface{}, error) {
|
|
|
if err := cmd.ValidateCommand(); err != nil {
|
|
|
return nil, application.ThrowError(application.ARG_ERROR, err.Error())
|
|
|
}
|
|
|
transactionContext, err := factory.CreateTransactionContext(nil)
|
|
|
if err != nil {
|
|
|
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
|
|
|
}
|
|
|
if err := transactionContext.StartTransaction(); err != nil {
|
|
|
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
|
|
|
}
|
|
|
defer func() {
|
|
|
transactionContext.RollbackTransaction()
|
|
|
}()
|
|
|
response, err := terminalReport(cmd, transactionContext)
|
|
|
if err != nil {
|
|
|
log.Logger.Error(err.Error())
|
|
|
return nil, err
|
|
|
}
|
|
|
if err := transactionContext.CommitTransaction(); err != nil {
|
|
|
return nil, application.ThrowError(application.TRANSACTION_ERROR, err.Error())
|
|
|
}
|
|
|
return response, nil
|
|
|
}
|
|
|
|
|
|
func terminalReport(cmd *command.TerminalReportCommand, transactionContext application.TransactionContext) (interface{}, error) {
|
|
|
var (
|
|
|
response string = "OK"
|
|
|
)
|
|
|
log.Logger.Debug(fmt.Sprintf("【TerminalManager】 收到上行命令 command:%v table:%v content:%v", cmd.Command, cmd.Table, cmd.Content))
|
|
|
switch cmd.Command {
|
|
|
case "getrequest":
|
|
|
device, ok := GlobalTerminalManager.GetDevice(cmd.TerminalId, cmd.CompanyId)
|
|
|
if !ok || device == nil {
|
|
|
break
|
|
|
}
|
|
|
if downEntity, ok := device.PopDownEntity(); ok && downEntity != nil {
|
|
|
response = downEntity.DownCommand()
|
|
|
}
|
|
|
break
|
|
|
case "cdata":
|
|
|
parseEntities := ParseData(cmd)
|
|
|
var (
|
|
|
down DownEntity
|
|
|
err error
|
|
|
handler Handler = ZKClockHandler{TransactionContext: transactionContext}
|
|
|
)
|
|
|
for _, entity := range parseEntities {
|
|
|
switch TableType(cmd.Table) {
|
|
|
case AttLOG:
|
|
|
down, err = handler.Attendance(entity.(AttLOGUpEntity))
|
|
|
case BIODATA:
|
|
|
down, err = handler.BioData(entity.(BIODATAEntity))
|
|
|
case OPERLOG:
|
|
|
//if v, ok := entity.(USEREntity); ok {
|
|
|
// down, err = handler.ReportUser(v)
|
|
|
//}
|
|
|
if v, ok := entity.(BIODATAEntity); ok {
|
|
|
down, err = handler.BioData(v)
|
|
|
}
|
|
|
}
|
|
|
if err != nil {
|
|
|
log.Logger.Error(err.Error())
|
|
|
continue
|
|
|
}
|
|
|
if down != nil {
|
|
|
response = down.DownCommand()
|
|
|
}
|
|
|
break
|
|
|
}
|
|
|
case "devicecmd":
|
|
|
}
|
|
|
|
|
|
return map[string]interface{}{
|
|
|
"response": response,
|
|
|
}, nil
|
|
|
}
|
|
|
|
|
|
func ParseData(cmd *command.TerminalReportCommand) []interface{} {
|
|
|
result := make([]interface{}, 0)
|
|
|
buf := bytes.NewBufferString(cmd.Content)
|
|
|
for {
|
|
|
line, err := buf.ReadBytes('\n')
|
|
|
if err == io.EOF {
|
|
|
break
|
|
|
}
|
|
|
if err != nil {
|
|
|
log.Logger.Error(err.Error())
|
|
|
break
|
|
|
}
|
|
|
|
|
|
switch TableType(cmd.Table) {
|
|
|
case AttLOG:
|
|
|
columns := bytes.Split(line, ([]byte)("\t"))
|
|
|
if len(columns) != 11 { //10 + 1 空格
|
|
|
continue
|
|
|
}
|
|
|
result = append(result, AttLOGUpEntity{
|
|
|
Pin: string(columns[0]),
|
|
|
CompanyId: cmd.CompanyId,
|
|
|
OrgId: cmd.OrgId,
|
|
|
})
|
|
|
case BIODATA:
|
|
|
/*BIODATA Pin=3\tNo=0\tIndex=0\tValid=1\tDuress=0\tType=9\tMajorVer=39\tMinorVer=1\tFormat=
|
|
|
0\tTmp=apUBEBABQo4JACcBAWiOADA7dP4pU9F31Uxom7NAGjM4eO/8X5Ee4uahkIT11c3188+VguMsd3oCO0O29efRyxofdLiohI4QL7woK3U*/
|
|
|
columns := readLineToMap(line, "BIODATA")
|
|
|
result = append(result, BIODATAEntity{
|
|
|
Pin: columns["Pin"],
|
|
|
No: columns["No"],
|
|
|
Index: columns["Index"],
|
|
|
Duress: columns["Duress"],
|
|
|
Type: columns["Type"],
|
|
|
MinorVer: columns["MinorVer"],
|
|
|
MajorVer: columns["MajorVer"],
|
|
|
Format: columns["Format"],
|
|
|
Tmp: columns["Tmp"],
|
|
|
CompanyId: cmd.CompanyId,
|
|
|
OrgId: cmd.OrgId,
|
|
|
})
|
|
|
case OPERLOG:
|
|
|
if bytes.HasPrefix(line, []byte("FP")) {
|
|
|
/*
|
|
|
FP PIN=3 FID=6 Size=1336 Valid=1 TMP=SqtTUzIxAAAD6O8ECA
|
|
|
*/
|
|
|
columns := readLineToMap(line, "FP")
|
|
|
result = append(result, BIODATAEntity{
|
|
|
Pin: columns["PIN"],
|
|
|
Type: fmt.Sprintf("%v", BioDataType1),
|
|
|
Tmp: columns["TMP"],
|
|
|
CompanyId: cmd.CompanyId,
|
|
|
OrgId: cmd.OrgId,
|
|
|
})
|
|
|
} else if bytes.HasPrefix(line, []byte("USER")) {
|
|
|
/*
|
|
|
USER PIN=3 Name=杨xx Pri=14 Passwd= Card=3731588478 Grp=1 TZ=0000000100000000 Verify=-1 ViceCard= StartDatetime=0 EndDatetime=0
|
|
|
*/
|
|
|
columns := readLineToMap(line, "USER")
|
|
|
name := columns["Name"] //GbkToUtf8(columns["Name"])
|
|
|
result = append(result, USEREntity{
|
|
|
OPERLOGType: "USER",
|
|
|
Pin: columns["PIN"],
|
|
|
Name: name,
|
|
|
CompanyId: cmd.CompanyId,
|
|
|
OrgId: cmd.OrgId,
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
return result
|
|
|
}
|
|
|
|
|
|
func readLineToMap(line []byte, prefix string) map[string]string {
|
|
|
var result = make(map[string]string)
|
|
|
line = bytes.TrimLeft(line, prefix)
|
|
|
line = bytes.TrimSpace(line)
|
|
|
columns := bytes.Fields(line)
|
|
|
for i := range columns {
|
|
|
kv := bytes.SplitN(columns[i], []byte("="), 2)
|
|
|
if len(kv) < 2 {
|
|
|
continue
|
|
|
}
|
|
|
//if string(kv[0]) == "Name" {
|
|
|
// log.Logger.Debug(fmt.Sprintf("%x", kv[1]))
|
|
|
// log.Logger.Debug(fmt.Sprintf("%v", kv[1]))
|
|
|
// log.Logger.Debug(fmt.Sprintf("%s", string(kv[1])))
|
|
|
//}
|
|
|
result[string(kv[0])] = string(kv[1])
|
|
|
}
|
|
|
return result
|
|
|
}
|
|
|
|
|
|
type Handler interface {
|
|
|
Attendance(entity AttLOGUpEntity) (DownEntity, error)
|
|
|
BioData(entity BIODATAEntity) (DownEntity, error)
|
|
|
ReportUser(entity USEREntity) (DownEntity, error)
|
|
|
}
|
|
|
|
|
|
type ZKClockHandler struct {
|
|
|
TransactionContext application.TransactionContext
|
|
|
}
|
|
|
|
|
|
func (handler ZKClockHandler) Attendance(entity AttLOGUpEntity) (DownEntity, error) {
|
|
|
var (
|
|
|
userRepository, _, _ = factory.FastPgUser(handler.TransactionContext, 0)
|
|
|
userBaseRepository, _, _ = factory.FastPgUserBase(handler.TransactionContext, 0)
|
|
|
user *domain.User
|
|
|
userBase *domain.UserBase
|
|
|
err error
|
|
|
)
|
|
|
if user, err = userRepository.FindOne(map[string]interface{}{"companyId": entity.CompanyId, "orgId": entity.OrgId, "icCardNumber": entity.Pin}); err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
if userBase, err = userBaseRepository.FindOne(map[string]interface{}{"userBaseId": user.UserBaseId}); err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
var sendQuery bool
|
|
|
// 请求 人脸识别-用户画像
|
|
|
if len(userBase.UserInfo.FacePortrait) == 0 {
|
|
|
sendQuery = true
|
|
|
//event.Fire(DownEntityEvent, map[string]interface{}{"entity": NewQueryBIODATADownEntity(generateSn(), entity.Pin, BioDataType2)})
|
|
|
}
|
|
|
// 请求 人脸识别-指纹
|
|
|
if len(userBase.UserInfo.FingerprintPortrait) == 0 {
|
|
|
// sendQuery = true
|
|
|
}
|
|
|
if sendQuery {
|
|
|
event.Fire(DownEntityEvent, map[string]interface{}{"entity": NewQueryUserInfoDownEntity(generateSn(), entity.Pin, entity.CompanyId)})
|
|
|
}
|
|
|
return nil, nil
|
|
|
}
|
|
|
|
|
|
func (handler ZKClockHandler) BioData(entity BIODATAEntity) (DownEntity, error) {
|
|
|
var (
|
|
|
userRepository, _, _ = factory.FastPgUser(handler.TransactionContext, 0)
|
|
|
userBaseRepository, _, _ = factory.FastPgUserBase(handler.TransactionContext, 0)
|
|
|
user *domain.User
|
|
|
userBase *domain.UserBase
|
|
|
err error
|
|
|
updateFlag bool
|
|
|
)
|
|
|
if user, err = userRepository.FindOne(map[string]interface{}{"companyId": entity.CompanyId, "orgId": entity.OrgId, "icCardNumber": entity.Pin}); err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
if userBase, err = userBaseRepository.FindOne(map[string]interface{}{"userBaseId": user.UserBaseId}); err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
// 请求 人脸识别-用户画像
|
|
|
if len(entity.Tmp) > 0 && entity.Type == "9" {
|
|
|
userBase.UserInfo.FacePortrait = entity.Tmp
|
|
|
updateFlag = true
|
|
|
if len(GlobalTerminalManager.TerminalDeviceList) >= 1 { //TODO:后期移除掉,多台设备时才进行广播
|
|
|
event.Fire(DownEntityEvent, map[string]interface{}{"entity": NewUpdateUserFacePortraitDownEntity(generateSn(), entity.Pin, entity.Tmp, entity.CompanyId)})
|
|
|
}
|
|
|
}
|
|
|
// 请求 人脸识别-指纹
|
|
|
if len(entity.Tmp) > 0 && entity.Type == "1" {
|
|
|
userBase.UserInfo.FingerprintPortrait = entity.Tmp
|
|
|
updateFlag = true
|
|
|
if len(GlobalTerminalManager.TerminalDeviceList) >= 1 {
|
|
|
event.Fire(DownEntityEvent, map[string]interface{}{"entity": NewUpdateUserFingerprintPortraitDownEntity(generateSn(), entity.Pin, entity.Tmp, entity.CompanyId)})
|
|
|
}
|
|
|
}
|
|
|
if updateFlag {
|
|
|
_, err = userBaseRepository.Save(userBase)
|
|
|
if err != nil {
|
|
|
log.Logger.Error(err.Error())
|
|
|
}
|
|
|
}
|
|
|
return nil, err
|
|
|
}
|
|
|
|
|
|
func (handler ZKClockHandler) ReportUser(entity USEREntity) (DownEntity, error) {
|
|
|
var (
|
|
|
userRepository, _, _ = factory.FastPgUser(handler.TransactionContext, 0)
|
|
|
userBaseRepository, _, _ = factory.FastPgUserBase(handler.TransactionContext, 0)
|
|
|
user *domain.User
|
|
|
userBase *domain.UserBase
|
|
|
err error
|
|
|
updateFlag bool
|
|
|
)
|
|
|
if user, err = userRepository.FindOne(map[string]interface{}{"companyId": entity.CompanyId, "orgId": entity.OrgId, "icCardNumber": entity.Pin}); err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
if userBase, err = userBaseRepository.FindOne(map[string]interface{}{"userBaseId": user.UserBaseId}); err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
// 请求 人脸识别-用户画像
|
|
|
//if len(entity.Pin) > 0 && userBase.UserInfo.Pin != entity.Pin {
|
|
|
// updateFlag = true
|
|
|
// userBase.UserInfo.Pin = entity.Pin
|
|
|
//}
|
|
|
if updateFlag {
|
|
|
_, err = userBaseRepository.Save(userBase)
|
|
|
}
|
|
|
return nil, err
|
|
|
}
|
|
|
|
|
|
func generateSn() string {
|
|
|
return string(utils.RandomCreateBytes(10))
|
|
|
} |
...
|
...
|
|