package uhf import ( "errors" "fmt" "github.com/tarm/serial" "io" "os" "time" ) type SerialReader struct { COMPort string BaudRate int port *serial.Port isConnected bool readBufSize int } // 初始化串口 func NewSerialReader(comPort string, baudRate int) *SerialReader { return &SerialReader{ COMPort: comPort, BaudRate: baudRate, readBufSize: 1024, // 足够容纳设备响应 } } // Connect 建立串口连接(显式配置8数据位,和工具一致) func (s *SerialReader) Connect() error { cfg := &serial.Config{ Name: s.COMPort, Baud: s.BaudRate, ReadTimeout: 1 * time.Second, // 读超时1秒,核心超时配置 Size: 8, // 8位数据位(必须显式配置!) Parity: serial.ParityNone, StopBits: serial.Stop1, } port, err := serial.OpenPort(cfg) if err != nil { s.isConnected = false return fmt.Errorf("打开串口失败: %v", err) } s.port = port s.isConnected = true return nil } // Disconnect 断开连接 func (s *SerialReader) Disconnect() error { if s.port != nil { err := s.port.Close() s.isConnected = false return err } return nil } // IsConnected 检查状态 func (s *SerialReader) IsConnected() bool { return s.isConnected } // SendData 发送串口数据(移除无效的Flush断言,保留核心发送逻辑) func (s *SerialReader) SendData(data []byte) error { if !s.isConnected { return errors.New("串口连接未建立") } // 完整写入所有字节 n, err := s.port.Write(data) if err != nil { return fmt.Errorf("发送数据失败: %v", err) } // 校验是否发送完整(核心:确保指令全部发出) if n != len(data) { return fmt.Errorf("发送字节数不完整,发送%d/预期%d", n, len(data)) } // ✅ 移除无效的Flush断言(tarm/serial的Port无此方法) // 注:tarm/serial的Write本身会立即写入串口,无需手动Flush return nil } // ReadData 循环读取串口数据(无SetReadDeadline,依赖ReadTimeout) func (s *SerialReader) ReadData() ([]byte, error) { if !s.isConnected { return nil, errors.New("串口连接未建立") } buf := make([]byte, s.readBufSize) var resp []byte // 循环读取,直到超时/拿到完整响应 for { n, err := s.port.Read(buf) if err != nil { // 超时/EOF是正常结束(ReadTimeout触发) if err == io.EOF || os.IsTimeout(err) { break } s.isConnected = false return nil, fmt.Errorf("读取数据失败: %v", err) } if n > 0 { resp = append(resp, buf[:n]...) // 检测到完整响应(帧头0xCF+最小长度7),提前退出 if len(resp) >= 7 && resp[0] == 0xCF { break } } } return resp, nil } // SendAndRecv 串口发送并等待响应(增加发送后延迟,核心优化) func (s *SerialReader) SendAndRecv(data []byte) ([]byte, error) { if err := s.SendData(data); err != nil { return nil, err } // 发送后延迟100ms,给设备处理指令的时间(工具也有此隐性延迟) time.Sleep(100 * time.Millisecond) // 读取响应 return s.ReadData() }