package FLXCheckInController import ( "encoding/hex" "flx/Common" FLXDevice "flx/Device" "fmt" "io" "time" log "github.com/sirupsen/logrus" serial "github.com/tarm/goserial" ) type FlxCheckInDeviceController struct { FirstRun bool IsRunning bool IsOpen bool IsOnline bool OldSData string SerialPort *io.ReadWriteCloser Reader FlxCheckInCmdReader Sender FlxCheckInCmdSender ComPackets chan []byte previousBuffer []byte HasDataIsReturned bool deviceGUID string regsterEvent_SeatInfos []FLXDevice.SeatChangeEventArg DataReciveSave []string InvokeDeviceEventHandler func(FLXDevice.EventArgSource, FLXDevice.EventArgType, []FLXDevice.SeatChangeEventArg) } func (para *FlxCheckInDeviceController) FlxCheckInDeviceController() { defer func() { if r := recover(); r != nil { log.Error("FlxCheckInDeviceController:", r) } }() para.InitControllerBusnissInfo() } func (para *FlxCheckInDeviceController) InitControllerBusnissInfo() { defer func() { if r := recover(); r != nil { log.Error("InitControllerBusnissInfo:", r) } }() para.ComPackets = make(chan []byte, 600) para.Sender.init(para.SerialPort) // Sender.defualtDelayed = configKeys.OneTimeDataPackedDelayed; // Sender.OnDataSendLogHandler += Sender_OnDataSendLogHandler; para.Reader.InitPara(para.SerialPort) para.Reader.InvokeOnBusinessDataReviceData = para.Reader_OnDataReciveEventHandler para.Reader.OnConnectStatusHandler = para.Reader_OnConnectStatusHandler } func (para *FlxCheckInDeviceController) Reader_OnConnectStatusHandler(dtLastRecived time.Time) { defer func() { if r := recover(); r != nil { log.Error("Reader_OnConnectStatusHandler:", r) } }() ts := time.Now().Sub(dtLastRecived) //判断报到机是否已达3秒没有向上位机发送数据 if ts.Seconds() >= 3 { //尝试获取报到机系统信息,如果报到机无数据返回,视为离线,否则,作在线处理 para.Sender.SendHeartBeat() revBuffer := para.Reader.ReadResponseData() if revBuffer == nil { if para.IsOnline { para.IsOnline = false } } else { para.Reader.dtLastRecivedDateTime = time.Now() if !para.IsOnline { if para.FirstRun { para.FirstRun = false } else { //发送蜂鸣指令 para.Sender.SendBeep(1) } para.IsOnline = true } } } } // / // /D7-D6:表示控制蜂鸣器操作模式 // /00:表示不对蜂鸣器进行控制操作 // /01:表示有人通过即提示 // /10:表示有人无卡提示 // /11:表示有人有卡提示 // /D5-D4:表示控制灯的操作模式 // /00:表示不对灯进行控制操作 // /01:表示有人通过即提示 // /10:表示有人无卡提示 // /11:表示有人有卡提示 // /D3-D0:表示时钟周期 // / func (para *FlxCheckInDeviceController) InitEStatus() byte { defer func() { if r := recover(); r != nil { log.Error("InitEStatus:", r) } }() var eTmp byte = 0 eTmp += 0xC0 eTmp += 0x30 return eTmp } // func Sender_OnDataSendLogHandler(string logMessage) { // RequestDebugMessage(this, logMessage); // } // func Reader_OnDataReciveLogHandler(string logMessage) { // RequestDebugMessage(this, logMessage); // } func (para *FlxCheckInDeviceController) OpenDevice() bool { defer func() { if r := recover(); r != nil { log.Error("OpenDevice:", r) } }() // getCommlist2() // c := &serial.Config{Name: "COM3", Baud: 19200} // s, err := serial.OpenPort(c) // if err != nil { // fmt.Println(err) // } // n, err := s.Write([]byte("012345")) // if err != nil { // fmt.Println(err) // } // fmt.Printf("Read %d Bytes\r\n", n) cfig := Common.LoadConfig() c := &serial.Config{Name: cfig.CheckInDoor.PortName, Baud: cfig.CheckInDoor.BaudRate} // var err error fmt.Println("enterging OpenDevice ") cport, err := serial.OpenPort(c) if err != nil { fmt.Println("打开串口驱动报错:") fmt.Println(err) return false } else { para.IsOpen = true } para.SerialPort = &cport para.Sender.init(para.SerialPort) para.Reader.InitPara(para.SerialPort) para.Sender.InitDoor() // para.Sender.SendBeep(1) // if nil != para.Reader.ReadResponseData() { para.Sender.DownLoadEStatus(para.InitEStatus()) para.Sender.SendBeep(1) para.Reader.Start() time.Sleep(500) para.CreatEventHandleThread() fmt.Println(OpenSerialPort_Success) return true // } // fmt.Println(ReciveDataFromCOM_Error) // return false } func (para *FlxCheckInDeviceController) CloseDevice() bool { defer func() { if r := recover(); r != nil { log.Error("CloseDevice:", r) } }() if para.IsOpen { para.Sender.SendBeep(1) para.Reader.Stop() time.Sleep(20 * time.Millisecond) para.KillEventHandleThread() // (*para.SerialPort).Close() if err := (*para.SerialPort).Close(); err != nil { fmt.Println(CloseSerialPort_Faild, ":", err) return false } } para.IsOpen = false if !para.IsOpen { fmt.Println(CloseSerialPort_Success) return true } else { fmt.Println(CloseSerialPort_Faild) return false } } func (para *FlxCheckInDeviceController) CheckInStartAll() { defer func() { if r := recover(); r != nil { log.Error("CheckInStartAll:", r) } }() if !para.IsOpen { para.OpenDevice() } } func (para *FlxCheckInDeviceController) CheckInStopAll() { defer func() { if r := recover(); r != nil { log.Error("CheckInStopAll:", r) } }() para.CloseDevice() } func (para *FlxCheckInDeviceController) StartCardReadIn() { defer func() { if r := recover(); r != nil { log.Error("StartCardReadIn:", r) } }() para.Reader.Start() time.Sleep(5 * time.Microsecond) para.CreatEventHandleThread() } func (para *FlxCheckInDeviceController) StopCardReadIn() { defer func() { if r := recover(); r != nil { log.Error("StopCardReadIn:", r) } }() para.Reader.Stop() time.Sleep(500) para.KillEventHandleThread() } func (para *FlxCheckInDeviceController) BeepOn(msec int) bool { defer func() { if r := recover(); r != nil { log.Error("BeepOn:", r) } }() var bRetValue bool = false if para.IsOpen { //Sender.SendAlarm(msec); for index := 0; index < msec; index++ { para.Sender.SendAlarm(1) time.Sleep(1 * time.Microsecond) } bRetValue = true } return bRetValue //return true; } func (para *FlxCheckInDeviceController) BeepOff() bool { defer func() { if r := recover(); r != nil { log.Error("BeepOff:", r) } }() return true } func (para *FlxCheckInDeviceController) LightOn() bool { defer func() { if r := recover(); r != nil { log.Error("LightOn:", r) } }() return true } func (para *FlxCheckInDeviceController) LightOff() bool { defer func() { if r := recover(); r != nil { log.Error("LightOff:", r) } }() return true } func (para *FlxCheckInDeviceController) Reader_OnDataReciveEventHandler(compacket []byte) { defer func() { if r := recover(); r != nil { log.Error("Reader_OnDataReciveEventHandler:", r) } }() fmt.Println(compacket) for i := 0; i < len(para.DataReciveSave); i++ { if para.DataReciveSave[i] == string(compacket) { //避免返回相同卡号 return } } para.DataReciveSave = append(para.DataReciveSave, string(compacket)) para.HasDataIsReturned = true if compacket != nil && len(compacket) > 5 { if compacket[0] == CMD_HEAD && compacket[len(compacket)-1] == CMD_Tail { para.ComPackets <- compacket } } go func() { time.Sleep(time.Second * 5) para.DataReciveSave = para.DataReciveSave[1:] }() } // / 消息队列 func (para *FlxCheckInDeviceController) TimerCallbackHandler() { defer func() { if r := recover(); r != nil { log.Error("TimerCallbackHandler:", r) } }() for para.IsRunning { para.regsterEvent_SeatInfos = para.regsterEvent_SeatInfos[0:0] comPacket := <-para.ComPackets if para.OldSData == hex.EncodeToString(comPacket) { continue } var seatInfo FLXDevice.SeatChangeEventArg if len(comPacket) > 2 { seatInfo.DeviceGUID = para.deviceGUID switch comPacket[1] { case Read_Reader_State: seatInfo.EventValue = FLXDevice.EventArgValue_RegistrStatus seatInfo.Value_ExtraInt = int(comPacket[2]) para.InvokeDeviceEventHandler(FLXDevice.EventArgSource_SivtChecker, FLXDevice.EventArgType_DeviceQueryEvent, []FLXDevice.SeatChangeEventArg{seatInfo}) case Read_SeriaNo: if !EqualsByteArray(para.previousBuffer, comPacket) { if comPacket[2] != 2 && comPacket[2] != 1 { para.previousBuffer = comPacket // Console.WriteLine("1赋值" + DeviceUtil.ByteArrayToString(previousBuffer, 0, previousBuffer.Length)) // Console.WriteLine("1 " + DeviceUtil.ByteArrayToString(comPacket, 0, comPacket.Length)) } // var cardNo string // for i := 3; i < len(comPacket)-1; i++ { // cardNo += comPacket[i].ToString("X2") // } cardNo := hex.EncodeToString(comPacket[3:]) seatInfo.EventValue = FLXDevice.EventArgValue_Register //不论进出检测到卡即为报到。 switch comPacket[2] { case 2: seatInfo.Value_ExtraInt = CheckInDirection_Out case 1: seatInfo.Value_ExtraInt = CheckInDirection_In default: seatInfo.Value_ExtraInt = CheckInDirection_In } seatInfo.Value_ExtraStr = cardNo var isExist bool = false for _, arg := range para.regsterEvent_SeatInfos { if arg.Value_ExtraStr == seatInfo.Value_ExtraStr { isExist = true break } } if !isExist { para.regsterEvent_SeatInfos = append(para.regsterEvent_SeatInfos, seatInfo) } fmt.Println(InvokeCaredNo_Processed) } case Read_In_State: if !EqualsByteArray(para.previousBuffer, comPacket) { seatInfo.EventValue = FLXDevice.EventArgValue_Register //不论进出检测到卡即为报到。 switch comPacket[2] { case 2: seatInfo.Value_ExtraInt = CheckInDirection_Out case 1: seatInfo.Value_ExtraInt = CheckInDirection_In default: seatInfo.Value_ExtraInt = CheckInDirection_Unkown } seatInfo.Value_ExtraStr = "" para.regsterEvent_SeatInfos = append(para.regsterEvent_SeatInfos, seatInfo) fmt.Println(InvokeCaredNo_Processed) } } } if seatInfo.Value_ExtraInt != 2 && seatInfo.Value_ExtraInt != 1 { para.previousBuffer = comPacket // Console.WriteLine("2赋值" + DeviceUtil.ByteArrayToString(previousBuffer, 0, previousBuffer.Length)) // Console.WriteLine("2 " + DeviceUtil.ByteArrayToString(comPacket, 0, comPacket.Length)) } if len(para.regsterEvent_SeatInfos) > 0 { // Console.WriteLine("触发事件" + regsterEvent_SeatInfos.Count + "个数据") para.InvokeDeviceEventHandler(FLXDevice.EventArgSource_SivtChecker, FLXDevice.EventArgType_RegisterEvent, para.regsterEvent_SeatInfos) } } } func EqualsByteArray(sorBuf []byte, argBuf []byte) bool { defer func() { if r := recover(); r != nil { log.Error("EqualsByteArray:", r) } }() if len(sorBuf) != len(argBuf) { return false } else { for i := 0; i < len(sorBuf); i++ { if sorBuf[i] != argBuf[i] { return false } } } return true } func (para *FlxCheckInDeviceController) CreatEventHandleThread() bool { defer func() { if r := recover(); r != nil { log.Error("CreatEventHandleThread:", r) } }() para.IsRunning = true go para.TimerCallbackHandler() fmt.Println("串口创建线程:" + CreateThread) return true } func (para *FlxCheckInDeviceController) KillEventHandleThread() bool { defer func() { if r := recover(); r != nil { log.Error("KillEventHandleThread:", r) } }() para.IsRunning = false fmt.Println("串口消毁线程:" + ClosedThread) return true }