| | |
| | | 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, |
| | | ReadDuration: readDuration, |
| | | DevName: devName, |
| | | Baud: baud, |
| | | ReadTimeout: readDuration, |
| | | Alive: true, |
| | | HeartbeatTime: time.Now().Unix(), |
| | | } |
| | | } |
| | | |
| | | type Reader struct { |
| | | DevName string |
| | | Baud int |
| | | ReadDuration int |
| | | DevPort *serial.Port |
| | | DevName string |
| | | Baud int |
| | | EPCData string |
| | | ReadTimeout int |
| | | Alive bool |
| | | HeartbeatTime int64 |
| | | DevPort *serial.Port |
| | | } |
| | | |
| | | func (r *Reader) OpenSerial() (err error) { |
| | |
| | | |
| | | func (r *Reader) ReadResponse() (int, error) { |
| | | buf := make([]byte, 1024) // 根据协议最大数据长度调整缓冲区 |
| | | return r.DevPort.Read(buf) |
| | | 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) { |
| | |
| | | |
| | | defer r.StopAutoRead() |
| | | |
| | | stop := time.After(time.Duration(r.ReadDuration) * time.Second) |
| | | stop := time.After(time.Duration(r.ReadTimeout) * time.Second) |
| | | |
| | | // 根据协议最大数据长度调整缓冲区 |
| | | buf := make([]byte, 1024) |
| | |
| | | for { |
| | | select { |
| | | case <-stop: |
| | | fmt.Println("读取已超时") |
| | | return false, nil |
| | | default: |
| | | for i := 0; i < 1024; i++ { |
| | |
| | | if buf[0] != 0x5A { |
| | | continue // 忽略错误帧 |
| | | } |
| | | fmt.Printf("Recive message %x\n", buf[:n]) // 打印协议控制字进行调试 |
| | | fmt.Printf("Recive message %X\n", buf[:n]) // 打印协议控制字进行调试 |
| | | |
| | | // 校验CRC |
| | | //fmt.Printf("Crc %x\n",buf[n-2 : n]) |
| | |
| | | |
| | | // 回调传送epc数据 |
| | | //callBack(buf[9 : 9+epcLength]) |
| | | epcData := fmt.Sprintf("%x", buf[9:9+epcLength]) |
| | | epcData := fmt.Sprintf("%X", buf[9:9+epcLength]) |
| | | if epcData == target { |
| | | scanCount++ |
| | | if scanCount > minCount { |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | 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) |
| | | } |