You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

687 lines
18 KiB
Go

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package FLXNetworkController
import (
"bytes"
"encoding/binary"
"fmt"
"io/ioutil"
"net"
"strconv"
"strings"
log "github.com/sirupsen/logrus"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/transform"
)
type FlxNetworkCmdReader struct {
BufferMaxLength int //最大缓冲长度
TCPClientConnect *net.Conn
CurrentSocket *net.TCPConn //TCP连接
BackUpSocket *net.TCPConn //备份TCP连接
RecThreadIsWorking bool //是否开始接受
TCPWorking bool
tmpRecDataBuffer []byte //缓冲字节
tmpRecBackUpDataBuffer []byte //缓冲字节
InvokeOnReviceData func(Compacket) //外部委托
// IfUse bool
// TranBuffer []byte //
// TranPosion int
}
func (para *FlxNetworkCmdReader) InitPara() {
defer func() {
if r := recover(); r != nil {
log.Error("InitPara:", r)
}
}()
/// <summary>缓冲区大小</summary>
//protected const int BufferMaxLength = 51200;
para.BufferMaxLength = 4096
/// <summary>端口数据处理锁</summary>
//para.CheckLock = new Object();
// para.TranBuffer = make([]byte, para.BufferMaxLength)
// para.TranPosion = 0
// /// <summary>接收到业务数据后触发事件</summary>
// public event BusinessDataReciveEventHandler OnBusinessDataReciveEventHandler;
// /// <summary>读端口数据时发生的日志信息</summary>
// public event DataReciveLogHandler OnDataReciveLogHandler;
// public event DataReciveHandler OnDataReciveHandler;
// para.IfUse = false
}
var ClientPort int = 9668
// UDP监听
func (para *FlxNetworkCmdReader) UPDStart() {
defer func() {
if r := recover(); r != nil {
log.Error("UPDStart:", r)
}
}()
// 创建监听
socket, err := net.ListenUDP("udp4", &net.UDPAddr{
IP: net.IPv4(0, 0, 0, 0),
Port: ClientPort,
})
if err != nil {
fmt.Println("监听失败!", err)
return
}
defer socket.Close()
for para.RecThreadIsWorking {
// 读取数据
data := make([]byte, 4096)
read, remoteAddr, err := socket.ReadFromUDP(data)
if err != nil {
fmt.Println("读取数据失败!", err)
continue
}
fmt.Println("接收到UDP数据长度为", read, "--远程IP:", remoteAddr)
fmt.Printf("%s\n\n", data)
curIndex := 0
length := 0
RecvBuffer := data[:read]
for curIndex <= len(RecvBuffer)-7 {
//判断是否出现 7E开头
if RecvBuffer[curIndex] == FlxNetworkComPara_CMD_HEAD {
if RecvBuffer[curIndex+3] > 8 {
curIndex++
continue
}
length = int(RecvBuffer[curIndex+3])*256 + int(RecvBuffer[curIndex+4]) + 7
if length <= len(RecvBuffer)-curIndex {
para.UDPValidateRecvBuffer(length, RecvBuffer, curIndex, remoteAddr.IP.String())
curIndex = curIndex + length
} else {
break
}
} else {
curIndex++
}
}
}
}
func (para *FlxNetworkCmdReader) UDPValidateRecvBuffer(packLen int, RecvBuffer []byte, startIndex int, ReIP string) bool {
defer func() {
if r := recover(); r != nil {
log.Error("UDPValidateRecvBuffer:", r)
}
}()
PackBuff := make([]byte, packLen)
PackBuff = RecvBuffer[startIndex : startIndex+packLen]
//校验CRC
CRCBuff := CRCCheck12(PackBuff[:packLen-2])
if CRCBuff[0] != PackBuff[packLen-2] || CRCBuff[1] != PackBuff[packLen-1] {
//InvokeOnDataReciveLogHandler(string.Format(FlxNetCCUConstantText.ReciveDataBufferImperfect_Error, "飞利信网口中控机")); //--写日志
return false
} else {
para.InvokeOnReviceData(CreatCMDPack(ReIP, PackBuff))
// para.InvokeOnReviceData(CreatCMDPack(PackBuff, packLen-2))
//外发事件。
return true
}
}
func (para *FlxNetworkCmdReader) InitCoon(socket *net.TCPConn, backupsocket *net.TCPConn) {
defer func() {
if r := recover(); r != nil {
log.Error("InitCoon:", r)
}
}()
para.CurrentSocket = socket
para.BackUpSocket = backupsocket
}
// 事件
// protected void InvokeOnDataReciveLogHandler(string logMessage)
// {
// if (OnDataReciveLogHandler != null) OnDataReciveLogHandler(logMessage);
// }
// protected void InvokeOnBusinessDataReviceData(ComPacket comPacket)
// {
// if (OnBusinessDataReciveEventHandler != null)
// OnBusinessDataReciveEventHandler(comPacket);
// }
// 端口数据的处理
// func CreatCMDPack(rcvBuff []byte, length int) Compacket {
// var packet Compacket
// if length >= 12 {
// packet.CmdType = rcvBuff[1]
// packet.ChnlID = rcvBuff[2]
// packet.Addr = rcvBuff[3]
// packet.Cmd = rcvBuff[4]
// packet.Const = rcvBuff[5]
// packet.ACmdData1 = rcvBuff[6]
// packet.ACmdData2 = rcvBuff[7]
// packet.ACmdData3 = rcvBuff[8]
// packet.ACmdData4 = rcvBuff[9]
// //if (true)
// //{
// // packet.ChnlID = packet.ACmdData4;
// //}
// packet.LenH = rcvBuff[10]
// packet.LenL = rcvBuff[11]
// if length > 12 {
// index := 12
// packet.Data = make([]byte, length-index)
// for i := 0; index < length; index++ {
// packet.Data[i] = rcvBuff[index]
// i++
// }
// }
// return packet
// }
// return packet
// }
func CreatCMDPack(reip string, rcvBuff []byte) Compacket {
defer func() {
if r := recover(); r != nil {
log.Error("CreatCMDPack:", r)
}
}()
var packet Compacket
if len(rcvBuff) < 5 {
return packet
}
reips := strings.Split(reip, ".")
packet.CmdType = 0x01
ip2, _ := strconv.Atoi(reips[2])
packet.ChnlID = byte(ip2)
ip3, _ := strconv.Atoi(reips[3])
packet.Addr = byte(ip3)
packet.IPAddress = reip
packet.Cmd = rcvBuff[1]
packet.Const = rcvBuff[2]
packet.LenH = rcvBuff[3]
packet.LenL = rcvBuff[4]
if len(rcvBuff) <= 7 {
return packet
}
packet.Data = make([]byte, packet.LenH*255+packet.LenL)
packet.Data = rcvBuff[5 : packet.LenH*255+packet.LenL+5]
return packet
}
func (para *FlxNetworkCmdReader) ProcessRecvBuff(RecvBuffer []byte, ReIP string) {
defer func() {
if r := recover(); r != nil {
log.Error("ProcessRecvBuff:", r)
}
}()
startIndex := 0
curIndex := 0
length := 0
//判断是否大于14字节
for curIndex <= len(RecvBuffer)-7 {
//判断是否出现 7E开头
if RecvBuffer[curIndex] == FlxNetworkComPara_CMD_HEAD {
if RecvBuffer[curIndex+3] > 8 {
//System.Windows.Forms.CMessageBox.Show("数据出错!");
curIndex++
continue
}
length = int(RecvBuffer[curIndex+3])*256 + int(RecvBuffer[curIndex+4]) + 7
if length <= len(RecvBuffer)-curIndex {
para.ValidateRecvBuffer(length, RecvBuffer, curIndex, ReIP)
curIndex = curIndex + length
startIndex = curIndex
} else {
para.tmpRecDataBuffer = append(para.tmpRecDataBuffer, RecvBuffer[curIndex:]...)
startIndex = -1
}
} else {
curIndex++
}
}
if startIndex >= 0 && startIndex < len(RecvBuffer) {
para.tmpRecDataBuffer = append(para.tmpRecDataBuffer, RecvBuffer[curIndex:]...)
}
}
func (para *FlxNetworkCmdReader) ValidateRecvBuffer(packLen int, RecvBuffer []byte, startIndex int, ReIP string) bool {
defer func() {
if r := recover(); r != nil {
log.Error("ValidateRecvBuffer:", r)
}
}()
PackBuff := make([]byte, packLen)
PackBuff = RecvBuffer[startIndex : startIndex+packLen]
//校验CRC
// data := []byte{0x7E, 0x30, 0x11, 0x00, 0x00}
// CRCBuff := CRCCheck12(data)
para.InvokeOnReviceData(CreatCMDPack(ReIP, PackBuff))
//cpcs发的时候没验证 先去掉
// CRCBuff := CRCCheck12(PackBuff[:packLen-2])
// if CRCBuff[0] != PackBuff[packLen-2] || CRCBuff[1] != PackBuff[packLen-1] {
// //InvokeOnDataReciveLogHandler(string.Format(FlxNetCCUConstantText.ReciveDataBufferImperfect_Error, "飞利信网口中控机")); //--写日志
// return false
// } else {
// // para.InvokeOnReviceData(CreatCMDPack(PackBuff, packLen-2))
// //外发事件。
// return true
// }
return true
}
// /TCP接收数据
func (para *FlxNetworkCmdReader) TCPCallbackHandler() {
defer func() {
if r := recover(); r != nil {
log.Error("TCPCallbackHandler:", r)
}
}()
//waitReadPackLen := 0 //待读的字节长度
//length := 0 //放入缓冲区的长度。
//tmpStr := "" //日志字符串。
reciveData := make([]byte, 65535)
for para.TCPWorking {
//读取
waitReadPackLen, err := para.CurrentSocket.Read(reciveData)
if err != nil {
fmt.Println("TCP接受出现问题", err)
para.TCPWorking = false
}
if waitReadPackLen == 0 {
fmt.Println(err)
}
// data := make([]byte, waitReadPackLen)
data := reciveData[:waitReadPackLen]
// dataLen := binary.LittleEndian.Uint32(data[4:8])
// data = data[8 : 8+dataLen]
//当前包接收长度 加上 上次接收半包的长度
recvBuffer := make([]byte, len(para.tmpRecDataBuffer)+waitReadPackLen) //从端口读取数据的缓冲区
fmt.Println("接收到TCP数据长度为", waitReadPackLen, "--远程IP:", para.CurrentSocket.RemoteAddr())
//上次如果为半包
if len(para.tmpRecDataBuffer) > 0 {
recvBuffer = insertToSlice(0, para.tmpRecDataBuffer, recvBuffer)
}
recvBuffer = insertToSlice(len(para.tmpRecDataBuffer), data, recvBuffer)
para.tmpRecDataBuffer = para.tmpRecDataBuffer[0:0]
// recvBuffer = append(para.tmpRecDataBuffer, data...)
//读取当前包的数据
//Array.Copy(data, 0, recvBuffer, index, waitReadPackLen) //读来的数据先零时放入这个缓冲区
para.ProcessRecvBuff(recvBuffer, strings.Split(para.CurrentSocket.RemoteAddr().String(), ":")[0])
}
}
// /TCP接收数据
func (para *FlxNetworkCmdReader) BackUpTCPCallbackHandler() {
defer func() {
if r := recover(); r != nil {
log.Error("BackUpTCPCallbackHandler:", r)
}
}()
//waitReadPackLen := 0 //待读的字节长度
//length := 0 //放入缓冲区的长度。
//tmpStr := "" //日志字符串。
reciveData := make([]byte, 65535)
for para.TCPWorking {
//读取
waitReadPackLen, err := para.BackUpSocket.Read(reciveData)
if err != nil {
fmt.Println("备份TCP接受出现问题", err)
para.RecThreadIsWorking = false
}
if waitReadPackLen == 0 {
fmt.Println(err)
}
data := make([]byte, waitReadPackLen)
data = reciveData[:waitReadPackLen]
//当前包接收长度 加上 上次接收半包的长度
recvBuffer := make([]byte, len(para.tmpRecBackUpDataBuffer)+waitReadPackLen) //从端口读取数据的缓冲区
//上次如果为半包
if len(para.tmpRecBackUpDataBuffer) > 0 {
recvBuffer = insertToSlice(0, para.tmpRecBackUpDataBuffer, recvBuffer)
}
recvBuffer = insertToSlice(len(para.tmpRecBackUpDataBuffer), data, recvBuffer)
para.tmpRecBackUpDataBuffer = para.tmpRecBackUpDataBuffer[0:0]
// recvBuffer = append(para.tmpRecDataBuffer, data...)
//读取当前包的数据
//Array.Copy(data, 0, recvBuffer, index, waitReadPackLen) //读来的数据先零时放入这个缓冲区
para.BackUpProcessRecvBuff(recvBuffer, strings.Split(para.BackUpSocket.RemoteAddr().String(), ":")[0])
}
}
func (para *FlxNetworkCmdReader) BackUpProcessRecvBuff(RecvBuffer []byte, ReIP string) {
defer func() {
if r := recover(); r != nil {
log.Error("BackUpProcessRecvBuff:", r)
}
}()
startIndex := 0
curIndex := 0
length := 0
//判断是否大于14字节
for curIndex <= len(RecvBuffer)-7 {
//判断是否出现 7E开头
if RecvBuffer[curIndex] == FlxNetworkComPara_CMD_HEAD {
if RecvBuffer[curIndex+3] > 8 {
//System.Windows.Forms.CMessageBox.Show("数据出错!");
curIndex++
continue
}
length = int(RecvBuffer[curIndex+3])*256 + int(RecvBuffer[curIndex+4]) + 7
if length <= len(RecvBuffer)-curIndex {
para.BackUpValidateRecvBuffer(length, RecvBuffer, curIndex, ReIP)
curIndex = curIndex + length
startIndex = curIndex
} else {
para.tmpRecBackUpDataBuffer = append(para.tmpRecBackUpDataBuffer, RecvBuffer[curIndex:]...)
startIndex = -1
}
} else {
curIndex++
}
}
if startIndex >= 0 && startIndex < len(RecvBuffer) {
para.tmpRecBackUpDataBuffer = append(para.tmpRecBackUpDataBuffer, RecvBuffer[curIndex:]...)
}
}
func (para *FlxNetworkCmdReader) BackUpValidateRecvBuffer(packLen int, RecvBuffer []byte, startIndex int, ReIP string) bool {
defer func() {
if r := recover(); r != nil {
log.Error("BackUpValidateRecvBuffer:", r)
}
}()
PackBuff := make([]byte, packLen)
PackBuff = RecvBuffer[startIndex : startIndex+packLen]
//校验CRC
CRCBuff := CRCCheck12(PackBuff[:packLen-2])
if CRCBuff[0] != PackBuff[packLen-2] || CRCBuff[1] != PackBuff[packLen-1] {
//InvokeOnDataReciveLogHandler(string.Format(FlxNetCCUConstantText.ReciveDataBufferImperfect_Error, "飞利信网口中控机")); //--写日志
return false
} else {
// para.InvokeOnReviceData(CreatCMDPack(PackBuff, packLen-2))
para.InvokeOnReviceData(CreatCMDPack(ReIP, PackBuff))
//外发事件。
return true
}
}
func (para *FlxNetworkCmdReader) Start() bool {
defer func() {
if r := recover(); r != nil {
log.Error("Start:", r)
}
}()
para.RecThreadIsWorking = true
fmt.Println("数据接收开启")
go para.UPDStart()
return true
}
func (para *FlxNetworkCmdReader) StartTCP() bool {
defer func() {
if r := recover(); r != nil {
log.Error("StartTCP:", r)
}
}()
para.TCPWorking = true
go para.TCPCallbackHandler()
// go para.BackUpTCPCallbackHandler()
return true
}
func (para *FlxNetworkCmdReader) StartBackUpTCP() bool {
defer func() {
if r := recover(); r != nil {
log.Error("StartBackUpTCP:", r)
}
}()
para.TCPWorking = true
go para.BackUpTCPCallbackHandler()
return true
}
func (para *FlxNetworkCmdReader) StopTCP() bool {
defer func() {
if r := recover(); r != nil {
log.Error("StopTCP:", r)
}
}()
para.TCPWorking = false
return true
}
func (para *FlxNetworkCmdReader) Stop() bool {
defer func() {
if r := recover(); r != nil {
log.Error("Stop:", r)
}
}()
para.RecThreadIsWorking = false
return true
}
// insertSlice 插入
func insertSlice(index int, newstr []byte, src []byte) (ns []byte) {
defer func() {
if r := recover(); r != nil {
log.Error("insertSlice:", r)
}
}()
ns = append(ns, src[:index]...) // 切片后加..., 相当于拆包成单个元素
ns = append(ns, newstr...)
ns = append(ns, src[index+len(newstr):]...)
return
}
func insertToSlice(index int, newstr []byte, src []byte) (ns []byte) {
defer func() {
if r := recover(); r != nil {
log.Error("insertToSlice:", r)
}
}()
ns = append(ns, src[:index]...) // 切片后加..., 相当于拆包成单个元素
ns = append(ns, newstr...)
ns = append(ns, src[index:]...)
return
}
// FullCheckSum CRC校验
// @description CRC校验
// @auth 刘富彦 时间2020/5/26 10:57
// @param 要检验的数据 []byte "解释"
// @return 合并后的数据 []byte "解释"
func FullCheckSum(buf []byte) []byte {
defer func() {
if r := recover(); r != nil {
log.Error("FullCheckSum:", r)
}
}()
buf = buf[:len(buf)-2]
var checksum uint16
checksum = 0xffff
for _, v := range buf {
n := uint8(uint16(v) ^ checksum)
//右移运算符(>>将一个数的各二进制位全部右移若干位正数左补0负数左补1右边丢弃,操作数每右移一位相当于该数除以2,左补0 or 补1得看被移数是正还是负
checksum >>= 8
//异或运算 0^0=0 0^1=1 1^0=1 1^1=0
checksum ^= MbTable[n]
}
int16buf := new(bytes.Buffer)
binary.Write(int16buf, binary.LittleEndian, checksum)
return append(buf, int16buf.Bytes()...)
}
func CRCCheck12(buf []byte) []byte {
defer func() {
if r := recover(); r != nil {
log.Error("CRCCheck12:", r)
}
}()
var checksum uint16
checksum = 0xffff
for _, v := range buf {
n := uint8(uint16(v) ^ checksum)
checksum >>= 8
checksum ^= MbTable[n]
}
int16buf := new(bytes.Buffer)
binary.Write(int16buf, binary.LittleEndian, checksum)
return int16buf.Bytes()
}
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, 0x8080}
/// 初始化
/// <summary>发送设备切换成主命令</summary>
/// <summary>发送设备查询命令,由阅读类接收状态信息</summary>
//public virtual void ScanDevices()
//{
// var ary = make([]byte,12) ;
//
// ary[index++] = FLXNetCCUCompara_CMD_HEAD;
// ary[index++] = FLXNetCCUCompara_CMD_TYPE01;
// ary[index++] = CMD_CHANEL;
// ary[index++] = FLXNetCCUCompara_CMD_BROAD;
// ary[index++] = Data_Device_Query; //cmd
// gb2312 能识别更多汉字, 担心utf8不能转换签到门硬件里面出来的汉字因此转gb2312
func UTF8GBK(s []byte) ([]byte, error) {
defer func() {
if r := recover(); r != nil {
log.Error("UTF8GBK:", r)
}
}()
reader := transform.NewReader(bytes.NewReader(s), simplifiedchinese.GBK.NewEncoder())
d, e := ioutil.ReadAll(reader)
if e != nil {
return nil, e
}
return d, nil
}