package uhf import ( "errors" "net" "time" ) type TCPReader struct { IP string Port int conn net.Conn isConnected bool buffer []byte // 内部拼包缓冲区(关键修复) } // 实现 Reader 接口的继电器方法(不再panic) func (t *TCPReader) CloseRelay1(validTime byte) error { frame := buildRelayFrame(0x0077, 1, RELAY_OP_CLOSE, validTime) _, err := t.SendAndRecv(frame) return err } func (t *TCPReader) ReleaseRelay1() error { frame := buildRelayFrame(0x0077, 1, RELAY_OP_RELEASE, 0) _, err := t.SendAndRecv(frame) return err } func (t *TCPReader) CloseRelay2(validTime byte) error { frame := buildRelayFrame(0x0078, 2, RELAY_OP_CLOSE, validTime) _, err := t.SendAndRecv(frame) return err } func (t *TCPReader) ReleaseRelay2() error { frame := buildRelayFrame(0x0078, 2, RELAY_OP_RELEASE, 0) _, err := t.SendAndRecv(frame) return err } func NewTCPReader(ip string, port int) *TCPReader { return &TCPReader{ IP: ip, Port: port, } } func (t *TCPReader) Connect() error { addr := net.JoinHostPort(t.IP, string(rune(t.Port))) conn, err := net.DialTimeout("tcp", addr, 5*time.Second) if err != nil { t.isConnected = false return err } t.conn = conn t.isConnected = true return nil } func (t *TCPReader) Disconnect() error { if t.conn != nil { _ = t.conn.Close() } t.isConnected = false t.buffer = nil return nil } func (t *TCPReader) IsConnected() bool { return t.isConnected } func (t *TCPReader) SendData(data []byte) error { if !t.isConnected { return errors.New("TCP未连接") } _, err := t.conn.Write(data) if err != nil { t.isConnected = false } return err } // ============================== // 🔥 关键修复:TCP 自动拼包,返回完整25字节帧 // ============================== func (t *TCPReader) ReadData() ([]byte, error) { if !t.isConnected { return nil, errors.New("TCP未连接") } // 读超时,防止永久阻塞 t.conn.SetReadDeadline(time.Now().Add(3 * time.Second)) buf := make([]byte, 1024) n, err := t.conn.Read(buf) if err != nil { t.isConnected = false return nil, err } // 加入缓冲区 t.buffer = append(t.buffer, buf[:n]...) // 找完整帧:0xCF 开头 + 25字节 for len(t.buffer) >= 25 { if t.buffer[0] == 0xCF { frame := t.buffer[:25] t.buffer = t.buffer[25:] return frame, nil } else { t.buffer = t.buffer[1:] } } return nil, errors.New("等待完整帧") } func (t *TCPReader) SendAndRecv(data []byte) ([]byte, error) { if err := t.SendData(data); err != nil { return nil, err } t.conn.SetReadDeadline(time.Now().Add(3 * time.Second)) return t.ReadData() }