package rfid import ( "context" "encoding/binary" "encoding/hex" "fmt" "io" "time" "github.com/tarm/serial" ) func NewReader(devName string, baud, readDuration int) *Reader { return &Reader{ DevName: devName, Baud: baud, ReadTimeout: readDuration, Alive: true, HeartbeatTime: time.Now().Unix(), } } type Reader struct { DevName string Baud int EPCData string ReadTimeout int Alive bool HeartbeatTime int64 DevPort *serial.Port } func (r *Reader) OpenSerial() (err error) { config := &serial.Config{ Name: r.DevName, Baud: r.Baud, ReadTimeout: 2 * time.Second, } r.DevPort, err = serial.OpenPort(config) return err } func (r *Reader) CloseSerial() error { return r.DevPort.Close() } // AutoReadStart 开启自动读取, 返回写入的指令长度和错误 func (r *Reader) StartAutoRead() error { cmd := "5A0001010B00100001000B0001021000050000000101005EE2" data, _ := hex.DecodeString(cmd) _, err := r.DevPort.Write(data) if err != nil { return nil } // todo parse response r.ReadResponse() return err } // StopAutoRead 停止读取 func (r *Reader) StopAutoRead() error { cmd := "5A000102FF0000885A" data, _ := hex.DecodeString(cmd) _, err := r.DevPort.Write(data) if err != nil { return nil } // todo parse response r.ReadResponse() return err } func (r *Reader) ReadResponse() (int, error) { buf := make([]byte, 1024) // 根据协议最大数据长度调整缓冲区 n, err := r.DevPort.Read(buf) fmt.Printf("Recive message %X\n", buf[:n]) return n, err } func (r *Reader) ScanSpecificEPC(target string, minCount int) (bool, error) { err := r.StartAutoRead() if err != nil { return false, err } defer r.StopAutoRead() stop := time.After(time.Duration(r.ReadTimeout) * time.Second) // 根据协议最大数据长度调整缓冲区 buf := make([]byte, 1024) scanCount := 0 for { select { case <-stop: return false, nil default: for i := 0; i < 1024; i++ { buf[i] = 0 // 清零或其他处理 } n, err := r.DevPort.Read(buf) if err != nil { return false, err } if n == 0 || n < 8 { continue // 如果没有读取到数据 } // 检查帧头 if buf[0] != 0x5A { continue // 忽略错误帧 } fmt.Printf("Recive message %X\n", buf[:n]) // 打印协议控制字进行调试 // 校验CRC //fmt.Printf("Crc %x\n",buf[n-2 : n]) receivedCrc := binary.BigEndian.Uint16(buf[n-2 : n]) computedCrc := CRC16XMODEM(buf[1 : n-2]) if receivedCrc != (computedCrc & 0xFFFF) { fmt.Println("CRC check failed") continue } // 解析协议控制字 (仅在需要时使用) //fmt.Printf("Control Word: %x\n", buf[1:5]) // 打印协议控制字进行调试 controlWord := binary.BigEndian.Uint32(buf[1:5]) if controlWord != ControlWordEPCReadResponse6C { fmt.Printf("Control Word: %d, rec word %d\n", ControlWordEPCReadResponse6C, controlWord) continue } // 解析EPC数据长度 epcLength := binary.BigEndian.Uint16(buf[7:9]) //fmt.Printf("EPC length %d, EPC %x \n", epcLength, buf[9:9+epcLength]) // 回调传送epc数据 //callBack(buf[9 : 9+epcLength]) epcData := fmt.Sprintf("%X", buf[9:9+epcLength]) if epcData == target { scanCount++ if scanCount > minCount { return true, nil } } fmt.Printf("read epc %s, target epc: %s\n", epcData, target) } } } func (r *Reader) ReadEPCData(ctx context.Context) error { err := r.StartAutoRead() if err != nil { return err } go func() { for { err := r.SendAck() if err != nil { fmt.Println("send ack.", err.Error()) } time.Sleep(30 * time.Second) if time.Now().Unix()-r.HeartbeatTime > 120 { r.Alive = false } } }() // 根据协议最大数据长度调整缓冲区 buf := make([]byte, 1024) for { select { case <-ctx.Done(): return nil default: for i := 0; i < 1024; i++ { buf[i] = 0 // 清零或其他处理 } n, err := r.DevPort.Read(buf) if err != nil && err != io.EOF { return err } if n == 0 || n < 8 { continue // 如果没有读取到数据 } // 检查帧头 if buf[0] != 0x5A { continue // 忽略错误帧 } fmt.Printf("Read message %X\n", buf[:n]) // 打印协议控制字进行调试 // 校验CRC receivedCrc := binary.BigEndian.Uint16(buf[n-2 : n]) computedCrc := CRC16XMODEM(buf[1 : n-2]) if receivedCrc != (computedCrc & 0xFFFF) { fmt.Println("CRC check failed") continue } r.HeartbeatTime = time.Now().Unix() r.Alive = true // 解析协议控制字 controlWord := binary.BigEndian.Uint32(buf[1:5]) switch controlWord { case ControlWordDeviceInfo: parseDeviceInfo(buf) case ControlWordEPCReadResponse6C: // 解析EPC数据长度 epcLength := binary.BigEndian.Uint16(buf[7:9]) r.EPCData = fmt.Sprintf("%X", buf[9:9+epcLength]) // 回调传送epc数据 //callBack(buf[9 : 9+epcLength]) fmt.Printf("Read epc %s\n", r.EPCData) } } } } func (r *Reader) GetPower() error { cmd := "5A0001020200002959" data, _ := hex.DecodeString(cmd) _, err := r.DevPort.Write(data) if err != nil { return err } // todo parse response r.ReadResponse() return nil } func (r *Reader) SendAck() error { cmd := "5A000101000000DCE5" //cmd := "5A000111120004000000015FFB" data, _ := hex.DecodeString(cmd) _, err := r.DevPort.Write(data) return err } func (r *Reader) SetPower(val int) error { if val < 10 || val > 33 { return fmt.Errorf("value out of range, must be between 0 and 255") } frame := []byte{0x5A, 0x00, 0x01, 0x02, 0x01, 0x00, 0x02, 0x01} frame = append(frame, byte(val)) crc := CRC16XMODEM(frame[1:]) crcBytes := make([]byte, 2) binary.BigEndian.PutUint16(crcBytes, crc) frame = append(frame, crcBytes...) fmt.Printf("set power %d, cmd %2X\n", val, frame) _, err := r.DevPort.Write(frame) if err != nil { return nil } // todo parse response r.ReadResponse() return err } func (r *Reader) SetBuzzer(enable bool) error { cmd := "5A0001011E000100653D" if !enable { cmd = "5A0001011E000101751C" } data, _ := hex.DecodeString(cmd) _, err := r.DevPort.Write(data) if err != nil { return err } // todo parse response r.ReadResponse() return nil } func parseDeviceInfo(bytes []byte) { // 初始化解析的偏移量 offset := 1 // 解析协议控制字 controlWord := bytes[offset : offset+4] offset += 4 // 解析数据长度 dataLength := int(bytes[offset])*256 + int(bytes[offset+1]) offset += 2 // 解析读写器序列号 serialNumberLen := int(bytes[offset])*256 + int(bytes[offset+1]) offset += 2 serialNumber := bytes[offset : offset+serialNumberLen] offset += serialNumberLen // 解析上电时间(4字节) upTimeBytes := bytes[offset : offset+4] offset += 4 // 解析基带编译时间长度(2字节) baseBandTimeLen := int(bytes[offset])*256 + int(bytes[offset+1]) offset += 2 // 解析基带编译时间(根据长度字段解析) baseBandTime := bytes[offset : offset+baseBandTimeLen] offset += baseBandTimeLen // 解析应用软件版本(4字节) appVer := bytes[offset : offset+4] offset += 4 // 将字节数组转换为可读字符串 serialNumberStr := string(serialNumber) baseBandTimeStr := string(baseBandTime) appVerStr := fmt.Sprintf("%d.%d.%d.%d", appVer[0], appVer[1], appVer[2], appVer[3]) // 解析上电时间(将字节数组转为整数) upTime := int(upTimeBytes[0])<<24 + int(upTimeBytes[1])<<16 + int(upTimeBytes[2])<<8 + int(upTimeBytes[3]) // 打印结果 fmt.Printf("协议控制字: %X\n", controlWord) fmt.Printf("数据长度: %d\n", dataLength) fmt.Printf("读写器序列号: %s\n", serialNumberStr) fmt.Printf("读写器上电时间: %d秒\n", upTime) fmt.Printf("基带编译时间: %s\n", baseBandTimeStr) fmt.Printf("应用软件版本: %s\n", appVerStr) }