package comm import ( "bytes" "encoding/binary" "encoding/hex" "fmt" MQTT "github.com/eclipse/paho.mqtt.golang" "github.com/jacobsa/go-serial/serial" "github.com/kptyun/KPTCOMM/pkg/setting" "github.com/kptyun/KPTCOMM/routers/restful" "github.com/recoilme/slowpoke" "github.com/siddontang/go-log/log" "math" //"github.com/xormplus/xorm" "io" "net" "strings" "sync" "time" ) // 一个已经被关闭的channel不会阻塞,已经被关闭的channel会实时返回 // goroutine退出,关闭done来进行广播 var needEscape int var my_comport io.ReadWriteCloser var my_Controlcomport io.ReadWriteCloser var SrcAdd []byte var commop string = "" var delaysendcommop int = 0 var Boastaddr *net.UDPAddr var Logger *log.Logger var StopCharP chan int // var ProcessKeyP chan []byte var ProcessKeyPstr chan []string var BroadcastBuf chan []byte var file string var RunTMRList sync.Map var MbTable = []uint16{ 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040} func CheckSum(data []byte) uint16 { var crc16 uint16 crc16 = 0xffff for _, v := range data { n := uint8(uint16(v) ^ crc16) crc16 >>= 8 crc16 ^= MbTable[n] } return crc16 } func getBoastaddr() *net.UDPAddr { tempaddr, err := net.ResolveUDPAddr("udp4", "255.255.255.255:8800") if err != nil { Logger.Errorf("%s \r\n", err) return tempaddr } if strings.TrimSpace(setting.ServerSetting.Netcard) != "" { interfaces, err := net.Interfaces() if err != nil { Logger.Errorf("%s \r\n", err) return tempaddr } for _, i := range interfaces { byName, err := net.InterfaceByName(i.Name) if err != nil { Logger.Errorf("%s \r\n", err) return tempaddr } if byName.Name == strings.TrimSpace(setting.ServerSetting.Netcard) { addresses, _ := byName.Addrs() for _, v := range addresses { if ipnet, ok := v.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { if ipnet.IP.To4() != nil { ipmask := fmt.Sprintf("%d.%d.%d.%d:%d", ipnet.IP[12], ipnet.IP[13], ipnet.IP[14], 255, setting.ServerSetting.Broadcast) tempaddr, err = net.ResolveUDPAddr("udp4", ipmask) if err != nil { tempaddr, err = net.ResolveUDPAddr("udp4", "255.255.255.255:8800") if err != nil { Logger.Errorf("%s \r\n", err) return tempaddr } } else { //Logger.Infof("%s %s \r\n", "发现本机IP:", fmt.Sprintf("%d.%d.%d.%d", ipnet.IP[12], ipnet.IP[13], ipnet.IP[14], ipnet.IP[15])) return tempaddr break } } } } } } } return tempaddr } func CommStrValidate(rebus []byte) bool { var ResI byte ResI = 0 for i, value := range rebus { if i < len(rebus)-1 { ResI = ResI + value } } ResI = 0xFF - ResI return ResI == rebus[len(rebus)-1] } func getDateTime(buf []byte) time.Time { dataTime := time.Date(2000+int(buf[0]>>2), time.Month(((buf[0]&0x03)<<2)|(buf[1]>>6)), int((buf[1]&0x3E)>>1), int(((buf[1]&0x01)<<4)|(buf[2]>>4)), int(((buf[2]&0x0F)<<2)|(buf[3]>>6)), int(buf[3]&0x3F), 0, time.Local) return dataTime } func getWeight(buf1, byte2, byte3 byte) float64 { ws := int16((byte3 & 96) >> 5) x := int16(buf1)<<8 | int16(byte2) if (byte3 >> 7) == 1 { x = -1 * x } s := float64(x) for i := int16(0); i < ws; i++ { s = s / 10 } return s } func getSendTailer() byte { key := []byte("SendTailer") val, err := slowpoke.Get(file, key) if err != nil { val, err = slowpoke.Get(file, key) } if val == nil { val = make([]byte, 1) val[0] = 1 } else { val[0] = val[0] + 1 if val[0] > 0x0F { val[0] = 0 } } err = slowpoke.Set(file, key, val) if err != nil { Logger.Errorf("%s \r\n", err) } return val[0] } func getF8(InSrcAddr byte, OriSendId byte) []byte { var p1, p2, p3, p4, temps byte year := byte(time.Now().Local().Year() % 2000) month := byte(time.Now().Local().Month()) day := byte(time.Now().Local().Day()) hour := byte(time.Now().Local().Hour()) minute := byte(time.Now().Local().Minute()) second := byte(time.Now().Local().Second()) p1 = (year << 2) | (month >> 2) p2 = ((month & 0x03) << 6) | ((day & 0x1F) << 1) | ((hour & 0x3F) >> 4) p3 = ((hour & 0x0F) << 4) | ((minute & 0x3F) >> 2) p4 = ((minute & 0x03) << 6) | (second & 0x3F) buf := make([]byte, 0) buf = append(buf, 0x7e) buf = append(buf, 0x08) buf = append(buf, InSrcAddr) buf = append(buf, 0x18) buf = append(buf, p1) buf = append(buf, p2) buf = append(buf, p3) buf = append(buf, p4) tempTailer := getSendTailer() buf = append(buf, ((OriSendId&0x0F)<<8)|(tempTailer&0x0F)) temps = 0 for _, i2 := range buf { temps = temps + i2 } buf = append(buf, 0xFF-temps) return buf } func duplicateValidate(recbuf []byte) ([]byte, []byte, bool) { key := make([]byte, 1) val := make([]byte, 2) key[0] = recbuf[2] if recbuf[3] < 240 { val[1] = recbuf[3] + 16 } else { val[1] = recbuf[3] } if recbuf[1] < byte(len(recbuf)) { val[0] = recbuf[recbuf[1]] } oldval, err := slowpoke.Get(file, key) if err != nil { Logger.Errorf("%s %s\r\n", file, err) oldval, err = slowpoke.Get(file, key) } if oldval == nil { val[0] = 0 val[1] = 0 return key, val, true } return key, val, (oldval[0] != val[0]) || (oldval[1] != val[1]) } func saveduplicateValidate(key []byte, val []byte) { err := slowpoke.Set(file, key, val) if err != nil { Logger.Errorf("%s \r\n", err) } } func processWeight(InSrcAddr byte, recbuf []byte) error { sParams := make([]interface{}, 0) sParams = append(sParams, InSrcAddr) sParams = append(sParams, getDateTime(recbuf[:4])) sParams = append(sParams, getWeight(recbuf[4], recbuf[5], recbuf[6])) _, err := restful.ExecQuerySqlx("select ProcTimeWeight(?,?,?)", sParams) if err != nil { Logger.Errorf("%s \r\n", err) } return err } func RunsendBuf() { defer func() { // 发生宕机时,获取panic传递的上下文并打印 if err := recover(); err != nil { fmt.Println("RunsendBuf出错:", err) StopCharP <- 1 } }() for { tmpstr := <-ProcessKeyPstr if len(tmpstr[0]) > 0 { err := sendBuf(tmpstr, nil) //println("recbuf",tmpstr) if err != nil { //goto openSerial StopCharP <- 1 time.Sleep(10 * time.Millisecond) //RunTMRList = make(map[byte]int, 200) go OpenComm() } } } } func RunbroadBuf() { var err error var conn *net.UDPConn var intvalue int errT := 0 for { recbuf := <-BroadcastBuf if setting.ServerSetting.ControlComm > 0 { my_Controlcomport, err = serial.Open(*setting.ControlCommSetting) if err != nil { Logger.Errorf("%s %s %s %s\r\n", setting.ControlCommSetting.PortName, "打开继电器串口错误: ", setting.CommSetting.PortName, err) if setting.DatabaseSetting.Showlog { fmt.Println(time.Now().Format("2006-01-02 15:04:05"), "打开继电器串口错误: ", setting.CommSetting.PortName, err) } } else { // Logger.Infof("%s %s\r\n", setting.ControlCommSetting.PortName, "打开继电器成功") if (recbuf[6] == 0xCB) && (recbuf[7] == 0xAE) { intvalue = 0 for i := 0; i <= 5; i++ { if recbuf[21-i] != 0x20 { intvalue = intvalue + int(recbuf[21-i]-0x30)*int(math.Floor(math.Pow10(i))) } else { break } } _, err = my_Controlcomport.Write(SetCoil(1, recbuf[2]-1, (recbuf[14] == 0xC9) && (recbuf[15] == 0xD9) && (intvalue > setting.ServerSetting.RelayDev))) if err != nil { Logger.Errorf("%s %s: %s\r\n", "写继电器串口错误: ", setting.ControlCommSetting.PortName, err) if setting.DatabaseSetting.Showlog { fmt.Println(time.Now().Format("2006-01-02 15:04:05"), "写继电器串口错误: ", setting.ControlCommSetting.PortName, err) } } if setting.DatabaseSetting.Showlog { fmt.Println(time.Now().Format("2006-01-02 15:04:05"), recbuf[2]-1, " ", intvalue, " ", setting.ServerSetting.RelayDev, " ", (recbuf[14] == 0xC9) && (recbuf[15] == 0xD9) && (intvalue > setting.ServerSetting.RelayDev)) } } else { _, err = my_Controlcomport.Write(SetCoil(1, recbuf[2]-1, false)) if err != nil { Logger.Errorf("%s %s: %s\r\n", "写继电器串口错误: ", setting.ControlCommSetting.PortName, err) if setting.DatabaseSetting.Showlog { fmt.Println(time.Now().Format("2006-01-02 15:04:05"), "写继电器串口错误: ", setting.ControlCommSetting.PortName, err) } } } _ = my_Controlcomport.Close() } } if setting.ServerSetting.Broadcast > 0 { Boastaddr, err = net.ResolveUDPAddr("udp4", fmt.Sprintf("%s:%d", setting.ServerSetting.BroadcastAddr, setting.ServerSetting.Broadcast)) if err != nil && errT == 0 { Boastaddr = getBoastaddr() } } if Boastaddr != nil { if errT == 0 { conn, err = net.DialUDP("udp4", nil, Boastaddr) if err != nil { Logger.Errorf("%s \r\n", err) errT = 1 } else { if len(recbuf) > 0 { _, err := conn.Write(recbuf) if err != nil { Logger.Errorf("%s \r\n", err) errT = 1 _ = conn.Close() } } } } } } } func processKey0(recbuf []byte) error { var err error InSrcAddr := recbuf[2] s := time.Now() if recbuf[3] == 0xF0 || recbuf[3] == 0xE0 { for i := 0; i < int((recbuf[1]-4)/7); i++ { err = processWeight(InSrcAddr, recbuf[4+(i*7):4+(i+1)*7]) // break } } if setting.DatabaseSetting.ShowXormlog { println("processKey0=================", time.Now().Sub(s).Milliseconds()) } return err } func processKey1(recbuf []byte) (string, error) { sParams := make([]interface{}, 0) s := time.Now() InSrcAddr := recbuf[2] InTime := getDateTime(recbuf[4:8]) BeginWeight := getWeight(recbuf[8], recbuf[9], recbuf[12]) endWeight := getWeight(recbuf[10], recbuf[11], recbuf[12]) InButtonType := recbuf[3] OriSendId := recbuf[15] LastSortID := recbuf[13] LastInorOut := recbuf[14] sParams = append(sParams, InSrcAddr) sParams = append(sParams, InTime) sParams = append(sParams, endWeight) _, err := restful.ExecQuerySqlx("select ProcTimeWeight(?,?,?)", sParams) if err != nil { Logger.Errorf("%s \r\n", err) } sParams = append(sParams[:0]) sParams = append(sParams, InSrcAddr) sParams = append(sParams, InTime) sParams = append(sParams, InButtonType) sParams = append(sParams, OriSendId) sParams = append(sParams, BeginWeight) sParams = append(sParams, endWeight) sParams = append(sParams, LastSortID) sParams = append(sParams, LastInorOut) //InObjAddr INTEGER, InSrcAddr INTEGER,InTime DATETIME,InButtonType INTEGER,OriSendId INTEGER, // OldWeight DOUBLE,NewestWeight DOUBLE,LastSortID INTEGER,LastInorOut INTEGER queryResult, err := restful.QueryByListv2Sqlx("select ProcNewButton(0,?,?,?,?,?,?,?,?) as resultstr", 0, 1, sParams) if err == nil { returnmsgmap, _ := queryResult.(map[string]interface{}) returnmsgmap1, _ := returnmsgmap["rows"].([]map[string]interface{}) if len(returnmsgmap1) > 0 { switch returnmsgmap1[0]["resultstr"].(type) { case string: if setting.DatabaseSetting.ShowXormlog { println("processKey1=================", time.Now().Sub(s).Milliseconds()) } return returnmsgmap1[0]["resultstr"].(string), nil } } } return "", err } func delcommop(lastCommop string) error { tx, err := restful.Dbs.Beginx() if err != nil { fmt.Println("GetT error:", err) } defer func() { switch { case err != nil: fmt.Println("__error:", err) if tx != nil { tx.Rollback() } default: if tx != nil { err = tx.Commit() } } }() sParams := make([]interface{}, 0) sParams = append(sParams, lastCommop) _, err = restful.ExecQueryT("delete from `commop` where `Cont`= ?", sParams, tx) if err == nil { commop = "" } return err } func getcommop() string { queryResult, err := restful.QueryByListSqlx("SELECT `Cont` as resultstr,ID FROM `commop` ", 0, 1, nil) if err == nil { returnmsgmap, _ := queryResult.(map[string]interface{}) returnmsgmap1, _ := returnmsgmap["rows"].(map[string][]interface{}) if len(returnmsgmap1["resultstr"]) > 0 { sParams := make([]interface{}, 0) sParams = append(sParams, returnmsgmap1["ID"][0]) //restful.ExecQuery("update commop set `SendTimes`=`SendTimes` + 1 where id = ?", sParams) //restful.ExecQuery("delete from commop where `SendTimes`>= 5 and id = ?", sParams) restful.ExecQuerySqlx("update commop set `SendTimes`=`SendTimes` + 1 where id = ?", sParams) restful.ExecQuerySqlx("delete from commop where `SendTimes`>= 5 and id = ?", sParams) return returnmsgmap1["resultstr"][0].(string) } } else { Logger.Errorf("%s \r\n", err) } return "" } func getnextOperate() string { queryResult, err := restful.QueryByListSqlx("SELECT `Cont` as resultstr,ID FROM `commop` ", 0, 1, nil) if err == nil { returnmsgmap, _ := queryResult.(map[string]interface{}) returnmsgmap1, _ := returnmsgmap["lists"].(map[string][]interface{}) if len(returnmsgmap1["resultstr"]) > 0 { sParams := make([]interface{}, 0) sParams = append(sParams, returnmsgmap1["ID"][0]) return returnmsgmap1["resultstr"][0].(string) } } else { Logger.Errorf("%s \r\n", err) } return "" } func processChar(inbyte byte, recLength, dataLength, state uint8, recbuf []byte) (uint8, uint8, uint8, bool, []byte) { //7E 15 01 F1 7E 45 C8 AB CC EC BD E1 CA F8 20 20 20 20 20 20 20 30 1C switch state { case 0: //头判断 if inbyte == 0x7E { state = 1 recLength = 1 recbuf = recbuf[:0] recbuf = append(recbuf, inbyte) } case 1: //接收长度数据 if inbyte == 0x7E { state = 1 recLength = 1 recbuf = recbuf[:0] recbuf = append(recbuf, inbyte) } else { state = 2 recLength = 2 dataLength = inbyte + 2 recbuf = append(recbuf, inbyte) } case 2: //接收数据中 recbuf = append(recbuf, inbyte) recLength++ if recLength == dataLength { state = 0 recLength = 0 return recLength, dataLength, state, true, recbuf } } return recLength, dataLength, state, false, recbuf } func processCharApi(inbyte byte, recLength, dataLength, state uint8, recbuf []byte) (uint8, uint8, uint8, bool, []byte) { //7E 15 01 F1 7E 45 C8 AB CC EC BD E1 CA F8 20 20 20 20 20 20 20 30 1C switch state { case 0: //头判断 if inbyte == 0x7E { state = 1 recLength = 1 recbuf = recbuf[:0] recbuf = append(recbuf, inbyte) } case 1: //头判断 if inbyte == 0x7E { state = 1 recLength = 1 recbuf = recbuf[:0] recbuf = append(recbuf, inbyte) } else if inbyte == 0x00 { state = 2 recLength = 2 recbuf = append(recbuf, inbyte) } else { state = 0 recLength = 0 recbuf = recbuf[:0] } case 2: //接收数据中 if inbyte == 0x7E { state = 1 recLength = 1 recbuf = recbuf[:0] recbuf = append(recbuf, inbyte) } else { if inbyte == 0x7D { needEscape = 1 } else { state = 3 recLength = 3 dataLength = inbyte + 4 if needEscape == 1 { needEscape = 0 recbuf = append(recbuf, inbyte^0x20) } else { recbuf = append(recbuf, inbyte) } } } case 3: //接收数据中 if inbyte == 0x7D { needEscape = 1 } else { recLength++ if needEscape == 1 { needEscape = 0 recbuf = append(recbuf, inbyte^0x20) } else { recbuf = append(recbuf, inbyte) } } if recLength == dataLength { state = 0 recLength = 0 if recbuf[3] == 0x90 && len(recbuf) > 16 && len(recbuf) > int(recbuf[16]+17) { SrcAdd = recbuf[4:12] recbuf = recbuf[15 : recbuf[16]+17] //recbuf = append(recbuf[4:12], recbuf[15:recbuf[16]+17]...) } return recLength, dataLength, state, true, recbuf } } return recLength, dataLength, state, false, recbuf } func getOutbytes(inbuf string, srcAdd string) ([]byte, error) { var tmpsum byte inbuf = strings.ToLower(inbuf) d, err := hex.DecodeString(inbuf) if err != nil { return nil, err } for i, i2 := range d { if i < len(d)-1 { tmpsum = tmpsum + i2 } else { d[len(d)-1] = 0xFF - tmpsum } } if d[3] != 0xAA { Logger.Infof("O:\t% X \r\n", d) } if setting.DatabaseSetting.Showlog && (d[3] != 0xAA) { fmt.Printf("%s O:\t% X \r\n", time.Now().Format("2006-01-02 15:04:05"), d) } if setting.ServerSetting.UseAPI == 1 { if d[3] == 0x18 { Logger.Infof("sent to:\t% X \r\n", SrcAdd) } d = XbeeMake(d, srcAdd, d[3] == 0xA2) //d = XbeeMake(d, srcAdd, true) } return d, nil } // 保护方式允许一个函数 func ProtectRun() { CurrentPath, _ := setting.GetCurrentPath() h, _ := log.NewRotatingFileHandler(CurrentPath+"Plog.log", 40*1024*1024, 10) if setting.DatabaseSetting.Showline { Logger = log.New(h, log.Ltime|log.Lfile) } else { Logger = log.New(h, log.Ltime) } Logger.SetLevelByName("info") //ProcessKeyP = make(chan []byte, 100) ProcessKeyPstr = make(chan []string, 100) BroadcastBuf = make(chan []byte, 100) //RunTMRList = make(map[byte]int, 200) go RunsendBuf() //if setting.ServerSetting.Broadcast > 0 { go RunbroadBuf() //} for { err := OpenComm() if err != nil { if strings.Compare(err.Error(), "一分钟未收到数据") < 0 { Logger.Errorln(err) } } time.Sleep(1 * time.Second) } } func XbeeMake(inbuf []byte, srcAdd string, boast bool) []byte { //7E 00 0F 10 01 00 00 00 00 00 00 FF FF FF FE 00 C0 01 32 var CheckSum byte var localSrcAdd []byte var er error buf := make([]byte, 0) buf1 := make([]byte, 0) inbuflen := len(inbuf) + 14 if len(srcAdd) > 0 { localSrcAdd, er = hex.DecodeString(srcAdd) } if er != nil || len(srcAdd) == 0 { localSrcAdd = localSrcAdd[:0] localSrcAdd = append(buf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF) } buf = append(buf, 0x7e, 0x00, byte(inbuflen&0xFF), 0x10, 0x01) if boast { buf = append(buf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF) } else { for _, i2 := range localSrcAdd { buf = append(buf, i2) } } buf = append(buf, 0xFF, 0xFE, 0x00, 0xC0) for _, i2 := range inbuf { buf = append(buf, i2) } CheckSum = 0x00 for i := 3; i < len(buf); i++ { CheckSum = CheckSum + buf[i] } buf = append(buf, 0xFF-CheckSum) buf1 = append(buf1, 0x7E) for i := 1; i < len(buf); i++ { if buf[i] == 0x7E || buf[i] == 0x7D || buf[i] == 0x11 || buf[i] == 0x13 { buf1 = append(buf1, 0x7D, buf[i]^0x20) } else { buf1 = append(buf1, buf[i]) } } return buf1 } func writeComm(tempstr string, srcAdd string) error { if len(tempstr) == 0 { return nil } buftmp, err := getOutbytes(tempstr, srcAdd) if err == nil { _, err = my_comport.Write(buftmp) if err != nil { Logger.Errorf("%s %s\r\n", "串口写入错误: ", err) time.Sleep(1 * time.Second) _ = my_comport.Close() return err } } return nil } func sendBuf(tmpstr []string, client MQTT.Client) error { var tmepstr2, tempstr1 string tmepstr2 = "" d, err := hex.DecodeString(tmpstr[0]) if err == nil { mylength1 := int(d[1] + 2) if len(d) > mylength1 { tempstr1 = hex.EncodeToString(d[0:mylength1]) tmepstr2 = hex.EncodeToString(d[mylength1:]) } else { tempstr1 = tmpstr[0] } if client != nil { MQPublish(client, tempstr1) MQPublish(client, tmepstr2) } else { if len(tempstr1) > 0 { err = writeComm(tempstr1, tmpstr[1]) if err != nil { return err } } if len(tmepstr2) > 0 { err = writeComm(tmepstr2, tmpstr[1]) if err != nil { return err } } } } return nil } func ProcessBuf(rebuff []byte) string { var err error var tmpstr string tmpstr = "" if CommStrValidate(rebuff) { if rebuff[3] == 0xA4 { if setting.DatabaseSetting.Showlog { fmt.Printf("%s I:\t% X \n", time.Now().Format("2006-01-02 15:04:05"), rebuff) } Logger.Infof("I:\t% X \r\n", rebuff) tmpcommop_, err := hex.DecodeString(commop) if err == nil && len(tmpcommop_) > 5 { if rebuff[2]&0x1F == tmpcommop_[2]&0x1F { delcommop(commop) } } } else if rebuff[3] == 0xA1 { // if setting.ServerSetting.Broadcast > 0 { select { case BroadcastBuf <- rebuff: default: Logger.Errorf("%s\r\n", "BroadcastBuf通道已满") } // } } else if rebuff[3]&0xF0 == 0xA0 { if setting.DatabaseSetting.Showlog { fmt.Printf("%s A0:\t% X \n", time.Now().Format("2006-01-02 15:04:05"), rebuff) } } else { if setting.DatabaseSetting.Showlog { fmt.Printf("%s I:\t% X \n", time.Now().Format("2006-01-02 15:04:05"), rebuff) } Logger.Infof("I:\t% X \r\n", rebuff) key, val, valresul := duplicateValidate(rebuff) if valresul { if rebuff[3]&0xF0 == 0xE0 { rebuff[3] = rebuff[3] + 0x10 } if rebuff[3] == 0xF0 { err = processKey0(rebuff) if err == nil { tmpstr = fmt.Sprintf("7E04%02x10%02x00", rebuff[2], rebuff[rebuff[1]]) } } else if rebuff[3] == 0xF1 || rebuff[3] == 0xF2 || rebuff[3] == 0xF3 || rebuff[3] == 0xF4 || rebuff[3] == 0xF5 { // err = processKey0(rebuff) tmpstr, err = processKey1(rebuff) } else if rebuff[3] == 0xF8 { tmpstr = hex.EncodeToString(getF8(rebuff[2], rebuff[4])) } } else { fmt.Printf("%s duplicateValidate:\t%s \n", time.Now().Format("2006-01-02 15:04:05"), "重复数据") if rebuff[3] == 0xE1 || rebuff[3] == 0xE2 || rebuff[3] == 0xE3 { //tmpstr = fmt.Sprintf("7E04%02x11%02x00", rebuff[2], rebuff[rebuff[1]]) tmpstr, _ = processKey1(rebuff) } else if rebuff[3] == 0xE0 { tmpstr = fmt.Sprintf("7E04%02x10%02x00", rebuff[2], rebuff[rebuff[1]]) } else if rebuff[3] == 0xF8 || rebuff[3] == 0xE8 { tmpstr = hex.EncodeToString(getF8(rebuff[2], rebuff[4])) } else if rebuff[3] == 0xF4 || rebuff[3] == 0xE4 || rebuff[3] == 0xF5 || rebuff[3] == 0xE5 { if rebuff[3]&0xF0 == 0xE0 { rebuff[3] = rebuff[3] + 0x10 } tmpstr, _ = processKey1(rebuff) } } if len(tmpstr) > 0 { saveduplicateValidate(key, val) } } } return tmpstr } func SetCoil(Addr byte, KAddr byte, State bool) []byte { m_data := []byte{0x01, 0x05, 0x00, 0x01, 0x00, 0x00} m_data[0] = Addr m_data[3] = KAddr if State { m_data[4] = 0xFF } checksum := CheckSum(m_data) int16buf := new(bytes.Buffer) binary.Write(int16buf, binary.LittleEndian, checksum) m_data = append(m_data, int16buf.Bytes()...) //fmt.Printf("output-after:%X \n",m_data) return m_data } func SetMulCoil(Addr byte, value int16) []byte { m_data := []byte{0x01, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00} m_data[0] = Addr m_data[3] = 0 m_data[5] = 16 m_data[7] = byte(value & 0xFF) m_data[8] = byte((value >> 8) & 0xFF) checksum := CheckSum(m_data) int16buf := new(bytes.Buffer) binary.Write(int16buf, binary.LittleEndian, checksum) m_data = append(m_data, int16buf.Bytes()...) fmt.Printf("output-after:%X \n", m_data) return m_data } func coil(i int) int16 { return 1 << (i - 1) } func OpenComm() (err error) { var monitorBegin, monitorend time.Time var recLength, dataLength, state uint8 var processok bool SrcAdd = make([]byte, 8) defer slowpoke.CloseAll() defer func() { // 发生宕机时,获取panic传递的上下文并打印 if err := recover(); err != nil { fmt.Println("OpenComm出错:", err) } }() //a := 0 // //b :=1/a //println(b) fmt.Println("启动时间:", time.Now().Local().Format("2006-01-02 15:04:05")) //2019-07-31 13:57:52 file = setting.CurrentPath + "rectailer" buf := make([]byte, 32) recbuf := make([]byte, 1) SrcAdd = make([]byte, 8) openserial: my_comport, err = serial.Open(*setting.CommSetting) recLength = 0 dataLength = 0 state = 0 if err != nil { Logger.Errorf("%s %s %s %s\r\n", setting.CommSetting.PortName, "打开错误: ", setting.CommSetting.PortName, err) if setting.DatabaseSetting.Showlog { fmt.Println(time.Now().Format("2006-01-02 15:04:05"), setting.CommSetting.PortName, "打开错误: ", setting.CommSetting.PortName, err) } time.Sleep(1 * time.Second) goto openserial } Logger.Infof("%s %s\r\n", setting.CommSetting.PortName, "打开成功") // my_comport.Write(SetCoil(1,1, true)) // my_comport.Write(SetMulCoil(1,(coil(1)|coil(3)|coil(5)|coil(7)))) // my_comport.Write(SetMulCoil(1,(coil(2)|coil(4)|coil(6)|coil(8)))) if setting.DatabaseSetting.Showlog { fmt.Println(time.Now().Format("2006-01-02 15:04:05"), setting.CommSetting.PortName, "打开成功") } sendcommopBegin := time.Now() sendLoraBegin := time.Now() monitorBegin = time.Now() defer my_comport.Close() for { select { case <-StopCharP: Logger.Infof("%s\r\n", "服务被停止") break default: n, err := my_comport.Read(buf) if (err != io.EOF) && (err != nil) { Logger.Errorf("%s %s\r\n", "串口读写错误: ", err) time.Sleep(1 * time.Second) _ = my_comport.Close() panic(err) } else if n > 0 { monitorBegin = time.Now() buf = buf[:n] //fmt.Printf("% X ",buf) for _, value := range buf { if setting.ServerSetting.UseAPI == 1 { recLength, dataLength, state, processok, recbuf = processCharApi(value, recLength, dataLength, state, recbuf) } else { recLength, dataLength, state, processok, recbuf = processChar(value, recLength, dataLength, state, recbuf) } if processok { var recbuftem = make([]byte, len(recbuf)) copy(recbuftem, recbuf) go func(recbuftem []byte, tempSrcAdd string) { if (len(recbuftem) > 3) && (recbuftem[2] < 30) { b := recbuftem[2] key, mapok := RunTMRList.Load(b) if !mapok { key = 0 } if key == 0 { tmpstr := make([]string, 2) begin := time.Now() RunTMRList.Store(b, 1) tmpstr[0] = ProcessBuf(recbuftem) tmpstr[1] = tempSrcAdd end := time.Now() // fmt.Printf(tmpstr[0]) if len(tmpstr) > 0 && end.Sub(begin).Seconds() < 30 { select { case ProcessKeyPstr <- tmpstr: default: Logger.Errorf("%s\r\n", "ProcessKeyPstr通道已满") } } else { Logger.Errorf("%s\r\n", "ProcessBuf 为空或超过30秒") } RunTMRList.Store(b, 0) } recbuftem = recbuftem[:0] } }(recbuftem, hex.EncodeToString(SrcAdd)) } } } else { sendcommopEnd := time.Now() if (sendcommopEnd.Sub(sendLoraBegin).Milliseconds() > setting.ServerSetting.SendRoute) && (setting.ServerSetting.SendRoute > 0) { sendLoraBegin = time.Now() tempsend := make([]string, 2) tempsend[0] = "7E03FFAA00" tempsend[1] = "" select { case ProcessKeyPstr <- tempsend: default: Logger.Errorf("%s\r\n", "commop_ProcessKeyPstr通道已满") } } else if sendcommopEnd.Sub(sendcommopBegin).Seconds() > 1 { sendcommopBegin = time.Now() delaysendcommop = 0 commop = getcommop() if len(commop) > 0 { tempTailer := getSendTailer() tempCommopstr, er := hex.DecodeString(commop) if er == nil { tempCommopstr[tempCommopstr[1]] = (tempCommopstr[tempCommopstr[1]] & 0xF0) | (tempTailer & 0x0F) tempsend := make([]string, 2) tempsend[0] = hex.EncodeToString(tempCommopstr) tempsend[1] = "" select { case ProcessKeyPstr <- tempsend: default: Logger.Errorf("%s\r\n", "commop_ProcessKeyPstr通道已满") } } } } else { monitorend = time.Now() if monitorend.Sub(monitorBegin).Minutes() > 1 { time.Sleep(1 * time.Second) _ = my_comport.Close() panic("一分钟未收到数据") } time.Sleep(10 * time.Microsecond) } } } } }