package event import ( "encoding/hex" "fmt" "git.rosy.net.cn/jx-callback/business/jxutils" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/business/model/dao" "git.rosy.net.cn/jx-callback/globals" "io" "net" "strconv" "strings" "sync" "time" ) const ( heartText = "1e000f02000151" printText = "1e00180200" printSuccessText = "1e001802000150" printErrWithoutPaper = "05" printMsgAlreadySend = 2 //已经发出打印消息 printMsgSuccess = 1 //打印成功 printMsgWait = 0 //待打印 printMsgFail = -1 //打印失败(打印机报出) printMsgErr = -2 //京西报出 heartErrWithoutPaper = "04" //心跳错,缺纸 heartErrHot = "08" //过热 printerStatusOnlineWithoutPaper = 2 //在线缺纸 printerStatusOnline = 1 //在线 printerStatusOffline = -1 //离线 ) //标签 const ( signBR = "
" //换行 signCenter = "
" //居中 signLeft = "" //居左 signRight = "" //居右 signBig = "" //字体放大 signHighBig = "" //字体纵向放大 signWideBig = "" //字体横向放大 signQrCenter = "" //二维码居中 signQrLeft = "" //二维码居左 signQrRight = "" //二维码居右 hexSignCenter = "1b6101" hexSignLeft = "1b6100" hexSignRight = "1b6102" hexSignNormal = "1b2100" hexSignBig = "1b2130" hexSignHighBig = "1b2110" hexSignWideBig = "1b2120" hexSignQrCenter = "1d5802" hexSignQrLeft = "1d5800" hexSignQrRight = "1d5804" hexSignQr = "1b5a0001061600" hexSignQrEnd = "000a0a0a1b40" byteSignBR = "3c62723e" //换行 byteSignCenter = "3c63656e7465723e" //居中 byteSignLeft = "3c6c6566743e" //居左 byteSignRight = "3c72696768743e" //居右 byteSignBig = "3c623e" //字体放大 byteSignHighBig = "3c68623e" //字体纵向放大 byteSignWideBig = "3c77623e" //字体横向放大 byteSignQrCenter = "3c7172633e" byteSignQrLeft = "3c71726c3e" byteSignQrRight = "3c7172723e" byteSignCenterE = "3c2f63656e7465723e" //居中 byteSignLeftE = "3c2f6c6566743e" //居左 byteSignRightE = "3c2f72696768743e" //居右 byteSignBigE = "3c2f623e" //字体放大 byteSignHighBigE = "3c2f68623e" //字体纵向放大 byteSignWideBigE = "3c2f77623e" //字体横向放大 byteSignQrCenterE = "3c2f7172633e" byteSignQrLeftE = "3c2f71726c3e" byteSignQrRightE = "3c2f7172723e" ) var ( tcpClient = &TcpClient{} printErrMap = map[string]string{ printErrWithoutPaper: "打印机缺纸!", } signMap = map[string]string{ byteSignBR: "0a", } ) //连接的客户端,吧每个客户端都放进来 type TcpClient struct { Clients map[string]net.Conn s *sync.RWMutex } func ListenTcp() { tcpClient.Clients = make(map[string]net.Conn) l, err := net.Listen("tcp", ":8000") if err != nil { fmt.Println("listen error:", err) return } globals.SugarLogger.Debugf("begin listenTcp port 8000......") go HandleTcpMessages() for { c, err := l.Accept() if err != nil { fmt.Println("accept error:", err) break } go handleConn(c) } } func handleConn(c net.Conn) { var ( printNo string //打印机编号 ) if c == nil { globals.SugarLogger.Debugf("conn is nil") return } defer c.Close() buffer := make([]byte, 1024) for { n, err := c.Read(buffer) if err != nil { if err == io.EOF { fmt.Println("connection close") } else { fmt.Println("ReadString err", err) } return } //看是心跳还是打印返回 data := hex.EncodeToString(buffer[:n]) //证明是心跳 if strings.Contains(data, heartText) { globals.SugarLogger.Debugf("handleConn heart: %v", data) printNoData, _ := hex.DecodeString(data[len(heartText) : len(data)-8]) printNo = string(printNoData) globals.SugarLogger.Debugf("handleConn printno :[%v]", printNo) if tcpClient.Clients[printNo] == nil { tcpClient.Clients[printNo] = c } else { //改变打印机状态 changePrinterStatus(printNo, printerStatusOnline) } } else if strings.Contains(data, printText) { globals.SugarLogger.Debugf("handleConn print: %v", data) changePrintMsg(data) } } } func changePrintMsg(data string) (err error) { var ( db = dao.GetDB() printNo, comment string orderNo int64 status int printMsg = &model.PrintMsg{} ) //1、先找出打印机编号和订单序列号,这两个确定唯一一条消息 orderNo = h8l82int(data[len(data)-6:len(data)-4], data[len(data)-4:len(data)-2]) printNoData, _ := hex.DecodeString(data[len(printSuccessText) : len(data)-6]) printNo = string(printNoData) //2、打印成功改变打印表的状态 if strings.Contains(data, printSuccessText) { //1e001802000150323032313036313530303030313000013c status = printMsgSuccess } else { //打印失败也改变状态并更新失败原因 status = printMsgFail comment = printErrMap[data[12:14]] } if tcpClient.Clients[printNo] == nil { return err } if printMsg, err = dao.GetPrintMsg(db, printNo, orderNo); err != nil { globals.SugarLogger.Debugf("changePrintMsg err :[%v]", err) return } else if printMsg == nil { globals.SugarLogger.Debugf("changePrintMsg err ,not found printMsg printNo:[%v], orderNo :[%v]", printNo, orderNo) } else if printMsg.Status != status { printMsg.Comment = comment printMsg.Status = status dao.UpdateEntity(db, printMsg, "Comment", "Status") } return err } func HandleTcpMessages() { var ( db = dao.GetDB() offset, pageSize = 0, 10 ) for { //一直读? var err error time.Sleep(time.Second / 2) prints, _ := dao.GetPrintMsgs(db, printMsgWait, offset, pageSize) for _, printMsg := range prints { var ( data []byte c net.Conn ) if printMsg != nil { if err = checkPrintMsg(printMsg); err == nil { if tcpClient.Clients[printMsg.PrintNo] != nil { c = tcpClient.Clients[printMsg.PrintNo] data, err = buildMsg(printMsg) } else { changePrinterStatus(printMsg.PrintNo, printerStatusOffline) } } } else { err = fmt.Errorf("未查询到此printMsg") } if err != nil { printMsg.Status = printMsgErr printMsg.Comment = err.Error() dao.UpdateEntity(db, printMsg, "Status", "Comment") delete(tcpClient.Clients, printMsg.PrintNo) c.Close() } else { if c != nil { if _, err = c.Write(data); err != nil { globals.SugarLogger.Debugf("handleTcpMessages err [%v]", err) delete(tcpClient.Clients, printMsg.PrintNo) c.Close() } else { globals.SugarLogger.Debugf("handleTcpMessages success, data: %v", hex.EncodeToString(data)) printMsg.Status = printMsgAlreadySend dao.UpdateEntity(db, printMsg, "Status", "Comment") } } } } } } func changePrinterStatus(printNo string, status int) (err error) { var ( printer = &model.Printer{} db = dao.GetDB() ) sql := ` SELECT * FROM printer WHERE print_no = ? ` sqlParams := []interface{}{printNo} if err = dao.GetRow(db, printer, sql, sqlParams); err == nil { if printer.ID != 0 { if printer.Status != status { dao.UpdateEntity(db, printer, "Status") } } } return err } func buildMsg(printMsg *model.PrintMsg) (data []byte, err error) { var ( content = printMsg.Content orderNo = printMsg.OrderNo str = "1e" const1 = "0200ff50" printInit = "1b40" //打印机初始化 voice = "1b59415501" //语音响一次 check = "ff" qr = "1d58021b5a0001061600747470733a2f2f7777772e62616964752e636f6d2f1b000A0A0A1B400a0a1b402d2d2d2d2d2d2d2d62626161616161616161" orderNoHexH, orderNoHexL, printData string ) //写入数据 orderNoHexH, orderNoHexL = int2h8l8(int64(orderNo)) printDataGBK, _ := jxutils.Utf8ToGbk([]byte(content)) printData = hex.EncodeToString(printDataGBK) printData = replaceContent(printData) lenData := int64(len(str) + len(const1) + len(orderNoHexH) + len(orderNoHexL) + len(printInit) + len(voice) + len(check) + 4 + len(printData) + len(qr)) x1, x2 := int2h8l8(lenData / 2) dataStr := str + x1 + x2 + const1 + orderNoHexH + orderNoHexL + printInit + voice + printData + qr + check return jxutils.Hextob(dataStr), err } //内容中的标签替换成指令 func replaceContent(content string) (result string) { result = content for k, v := range signMap { if strings.Contains(result, k) { result = strings.ReplaceAll(result, k, v) } } if strings.Contains(result, byteSignCenter) && strings.Contains(result, byteSignCenterE) { result = strings.ReplaceAll(result, byteSignCenter, hexSignCenter) result = strings.ReplaceAll(result, byteSignCenterE, hexSignLeft) } if strings.Contains(result, byteSignLeft) && strings.Contains(result, byteSignLeftE) { result = strings.ReplaceAll(result, byteSignLeft, hexSignLeft) result = strings.ReplaceAll(result, byteSignLeftE, hexSignLeft) } if strings.Contains(result, byteSignRight) && strings.Contains(result, byteSignRightE) { result = strings.ReplaceAll(result, byteSignRight, hexSignRight) result = strings.ReplaceAll(result, byteSignRightE, hexSignLeft) } if strings.Contains(result, byteSignBig) && strings.Contains(result, byteSignBigE) { result = strings.ReplaceAll(result, byteSignBig, hexSignBig) result = strings.ReplaceAll(result, byteSignBigE, hexSignNormal) } if strings.Contains(result, byteSignHighBig) && strings.Contains(result, byteSignHighBigE) { result = strings.ReplaceAll(result, byteSignHighBig, hexSignHighBig) result = strings.ReplaceAll(result, byteSignHighBigE, hexSignNormal) } if strings.Contains(result, byteSignWideBig) && strings.Contains(result, byteSignWideBigE) { result = strings.ReplaceAll(result, byteSignWideBig, hexSignWideBig) result = strings.ReplaceAll(result, byteSignWideBigE, hexSignNormal) } if strings.Contains(result, byteSignQrCenter) && strings.Contains(result, byteSignQrCenterE) { result = strings.ReplaceAll(result, byteSignQrCenter, hexSignQrCenter+hexSignQr) result = strings.ReplaceAll(result, byteSignQrCenterE, hexSignQrEnd) } if strings.Contains(result, byteSignQrLeft) && strings.Contains(result, byteSignQrLeftE) { result = strings.ReplaceAll(result, byteSignQrLeft, hexSignQrLeft+hexSignQr) result = strings.ReplaceAll(result, byteSignQrLeftE, hexSignQrEnd) } if strings.Contains(result, byteSignQrRight) && strings.Contains(result, byteSignQrRightE) { result = strings.ReplaceAll(result, byteSignQrRight, hexSignQrRight+hexSignQr) result = strings.ReplaceAll(result, byteSignQrRightE, hexSignQrEnd) } return result } func checkPrintMsg(printMsg *model.PrintMsg) (err error) { if printMsg.Content == "" { return fmt.Errorf("此打印信息内容为空!printMsg printNo:[%v], orderNo :[%v]", printMsg.PrintNo, printMsg.OrderNo) } if printMsg.PrintNo == "" { return fmt.Errorf("此打印信息打印机编号为空!printMsg printNo:[%v], orderNo :[%v]", printMsg.PrintNo, printMsg.OrderNo) } if printMsg.OrderNo == 0 { return fmt.Errorf("此打印信息订单序号为空!printMsg printNo:[%v], orderNo :[%v]", printMsg.PrintNo, printMsg.OrderNo) } return err } func int2h8l8(i int64) (h, l string) { origin2 := fmt.Sprintf("%b", i) flag := 16 - len(origin2) for i := 0; i < flag; i++ { origin2 = "0" + origin2 } begin8 := origin2[:8] end8 := origin2[8:] r1, _ := strconv.ParseInt(begin8, 2, 32) r2, _ := strconv.ParseInt(end8, 2, 32) h = fmt.Sprintf("%x", r1) l = fmt.Sprintf("%x", r2) if len(h) < 2 { h = "0" + h } if len(l) < 2 { l = "0" + l } return h, l } func h8l82int(h, l string) (i int64) { s1, s2 := xtob(h), xtob(l) flag1 := 8 - len(s1) flag2 := 8 - len(s2) for m := 0; m < flag1; m++ { s1 = "0" + s1 } for j := 0; j < flag2; j++ { s2 = "0" + s2 } i, _ = strconv.ParseInt(s1+s2, 2, 10) return i } func xtob(x string) string { base, _ := strconv.ParseInt(x, 16, 10) return strconv.FormatInt(base, 2) }