Files
jx-callback/business/jxstore/event/event_tcp.go
2021-07-01 11:48:05 +08:00

393 lines
12 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 = "<br>" //换行
signCenter = "<center>" //居中
signLeft = "<left>" //居左
signRight = "<right>" //居右
signBig = "<b>" //字体放大
signHighBig = "<hb>" //字体纵向放大
signWideBig = "<wb>" //字体横向放大
signQrCenter = "<qrc>" //二维码居中
signQrLeft = "<qrl>" //二维码居左
signQrRight = "<qrr>" //二维码居右
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)
}