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,
|
}
|
}
|
|
type Reader struct {
|
DevName string
|
Baud int
|
ReadDuration int
|
EPCData string
|
ReadTimestamp 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) // 根据协议最大数据长度调整缓冲区
|
return r.DevPort.Read(buf)
|
}
|
|
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.ReadDuration) * 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
|
}
|
|
// 根据协议最大数据长度调整缓冲区
|
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
|
//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])
|
r.EPCData = fmt.Sprintf("%X", buf[9:9+epcLength])
|
r.ReadTimestamp = time.Now().Unix()
|
|
fmt.Printf("read epc %s\n", r.EPCData)
|
}
|
}
|
}
|