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)
|
}
|