package stc import ( "bufio" "bytes" "encoding/binary" "fmt" "log" "net" "os" stc "pbx-api-gin/internal/app/stc/operation" "syscall" "time" ) // Protocol 定义协议数据结构 type Protocol struct { StartBytes [3]byte // 协议开始符 SourceID uint8 // 源设备号 DestinationID uint8 // 目的设备号 MessageID uint8 // 消息号 DataLength uint16 // 数据长度 Data []byte // 数据 Checksum uint8 // 异或校验码 EndByte uint8 // 协议结束符 } // NewProtocol 创建一个新的 Protocol 实例 func NewProtocol() *Protocol { return &Protocol{ StartBytes: [3]byte{0x7F, 0x8E, 0x9D}, EndByte: 0xFE, } } func ConnectStc(ServerAddr string, Port int) { //================================================= // connect server conn := connectServer(ServerAddr, Port) defer conn.Close() //read msg go func(conn net.Conn) { readMsg(conn) }(conn) // send msg sendMsg(conn) } func connectServer(ServerAddr string, Port int) net.Conn { // connect server conn, err := net.DialTCP("tcp", &net.TCPAddr{ IP: net.ParseIP("0.0.0.0"), Port: 0, }, &net.TCPAddr{ IP: net.ParseIP(ServerAddr), Port: Port, }) if err != nil { fmt.Println("Error conn server:", err) log.Fatal(err) } fileDesc, _ := conn.File() fd := fileDesc.Fd() syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) return conn } func Sendheartbeat(conn net.Conn) { var count uint8 //init heartbeat data protocol := NewProtocol() protocol.SourceID = 0x02 protocol.DestinationID = 0x01 protocol.MessageID = 0x21 protocol.DataLength = 0x04 ticker := time.NewTicker(2 * time.Second) defer ticker.Stop() for range ticker.C { count = count + 1 protocol.Data = []byte{count, 0x00, 0x00, 0x00} encoded, errEn := protocol.Encode() if errEn != nil { fmt.Println("Encode error:", errEn) return } _, err := conn.Write(encoded) if err != nil { fmt.Println("send heartbeat err:", err) return } } } func readMsg(conn net.Conn) { for { buffer := make([]byte, 1024) n, err := conn.Read(buffer) if err != nil { fmt.Println("Error reading from server:", err) return } fmt.Println("Received from server:", string(buffer[:n])) switch buffer[5] { case 0x01: //heartbeat case 0x02: //STN stc.StationAnn([4]byte{buffer[8], buffer[9], buffer[10], buffer[11]}) case 0x03: //ACTIVE stc.Active([1]byte{buffer[8]}) case 0x05: //SPC stc.SpecialAnn([4]byte{buffer[8], buffer[9], buffer[10], buffer[11]}) case 0x06: //EMG stc.EmgMsg([4]byte{buffer[8], buffer[9], buffer[10], buffer[11]}) case 0x07: //STOP stc.AnnStop([4]byte{buffer[8], buffer[9], buffer[10], buffer[11]}) case 0x08: //DCS stc.DcsAnn([4]byte{buffer[8], buffer[9], buffer[10], buffer[11]}) case 0x09: //SELF CHECK stc.SelfCheck([4]byte{buffer[8], buffer[9], buffer[10], buffer[11]}) case 0x0a: // stc.AlarmHandle([4]byte{buffer[8], buffer[9], buffer[10], buffer[11]}) case 0x0b: // stc.AlarmResetAll([4]byte{buffer[8], buffer[9], buffer[10], buffer[11]}) case 0x0c: // stc.RecordStorageConf([4]byte{buffer[8], buffer[9], buffer[10], buffer[11]}) } } } func sendMsg(conn net.Conn) { //heartbeat go func(conn net.Conn) { Sendheartbeat(conn) }(conn) scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { text := scanner.Text() _, err := conn.Write([]byte(text + "\n")) if err != nil { fmt.Println("send msg err:", err) return } } } // Encode 将 Protocol 结构体编码为字节切片 func (p *Protocol) Encode() ([]byte, error) { // 初始化字节缓冲区 var buf bytes.Buffer // 写入协议开始符 buf.Write(p.StartBytes[:]) // 写入源设备号、目的设备号和消息号 binary.Write(&buf, binary.BigEndian, p.SourceID) binary.Write(&buf, binary.BigEndian, p.DestinationID) binary.Write(&buf, binary.BigEndian, p.MessageID) // 写入数据长度 binary.Write(&buf, binary.BigEndian, p.DataLength) // 写入数据 buf.Write(p.Data[:]) // 计算校验码 checksum := p.CalculateChecksum() p.Checksum = checksum // 写入校验码 binary.Write(&buf, binary.BigEndian, p.Checksum) // 写入协议结束符 binary.Write(&buf, binary.BigEndian, p.EndByte) return buf.Bytes(), nil } // CalculateChecksum 计算校验码 func (p *Protocol) CalculateChecksum() uint8 { // 初始化校验码 checksum := uint8(0) // 跳过协议开始符 data := append([]byte{byte(p.SourceID), byte(p.DestinationID), byte(p.MessageID)}, append([]byte{byte(p.DataLength >> 8), byte(p.DataLength)}, p.Data...)...) // 计算校验码 for _, b := range data { checksum ^= b } return checksum } // Decode 解码字节切片为 Protocol 结构体 func Decode(data []byte) (*Protocol, error) { if len(data) < 10 { // 最小长度:3(StartBytes) +1(SourceID) +1(DestinationID) +1(MessageID) +2(DataLength) +1(Checksum) +1(EndByte) return nil, fmt.Errorf("data too short") } p := NewProtocol() // 读取协议开始符 copy(p.StartBytes[:], data[:3]) // 读取源设备号、目的设备号和消息号 p.SourceID = data[3] p.DestinationID = data[4] p.MessageID = data[5] // 读取数据长度 p.DataLength = binary.BigEndian.Uint16(data[6:8]) // 读取数据 dataLength := int(p.DataLength) if len(data) < 10+dataLength { return nil, fmt.Errorf("data length mismatch") } p.Data = data[8 : 8+dataLength] // 读取校验码 p.Checksum = data[8+dataLength] // 读取协议结束符 p.EndByte = data[9+dataLength] // 验证校验码 if p.Checksum != p.CalculateChecksum() { return nil, fmt.Errorf("checksum mismatch") } return p, nil }