From 4ca3791590a7bf50222aa5f80e53edf04739108a Mon Sep 17 00:00:00 2001
From: zhangzengfei <zhangzengfei@smartai.com>
Date: 星期二, 22 十月 2024 17:20:23 +0800
Subject: [PATCH] fix 1400 post floor farmat

---
 rfid/rw.go |  231 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 219 insertions(+), 12 deletions(-)

diff --git a/rfid/rw.go b/rfid/rw.go
index 79d95d2..4cb8d2d 100644
--- a/rfid/rw.go
+++ b/rfid/rw.go
@@ -1,9 +1,11 @@
 package rfid
 
 import (
+	"context"
 	"encoding/binary"
 	"encoding/hex"
 	"fmt"
+	"io"
 	"time"
 
 	"github.com/tarm/serial"
@@ -11,17 +13,22 @@
 
 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) {
@@ -76,7 +83,10 @@
 
 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) {
@@ -87,7 +97,7 @@
 
 	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)
@@ -95,7 +105,6 @@
 	for {
 		select {
 		case <-stop:
-			fmt.Println("璇诲彇宸茶秴鏃�")
 			return false, nil
 		default:
 			for i := 0; i < 1024; i++ {
@@ -115,7 +124,7 @@
 			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])
@@ -141,7 +150,7 @@
 
 			// 鍥炶皟浼犻�乪pc鏁版嵁
 			//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 {
@@ -153,3 +162,201 @@
 		}
 	}
 }
+
+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
+
+			// 瑙f瀽鍗忚鎺у埗瀛�
+			controlWord := binary.BigEndian.Uint32(buf[1:5])
+
+			switch controlWord {
+			case ControlWordDeviceInfo:
+				parseDeviceInfo(buf)
+			case ControlWordEPCReadResponse6C:
+				// 瑙f瀽EPC鏁版嵁闀垮害
+				epcLength := binary.BigEndian.Uint16(buf[7:9])
+
+				r.EPCData = fmt.Sprintf("%X", buf[9:9+epcLength])
+
+				// 鍥炶皟浼犻�乪pc鏁版嵁
+				//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
+
+	// 瑙f瀽鍗忚鎺у埗瀛�
+	controlWord := bytes[offset : offset+4]
+	offset += 4
+
+	// 瑙f瀽鏁版嵁闀垮害
+	dataLength := int(bytes[offset])*256 + int(bytes[offset+1])
+	offset += 2
+
+	// 瑙f瀽璇诲啓鍣ㄥ簭鍒楀彿
+	serialNumberLen := int(bytes[offset])*256 + int(bytes[offset+1])
+	offset += 2
+	serialNumber := bytes[offset : offset+serialNumberLen]
+	offset += serialNumberLen
+
+	// 瑙f瀽涓婄數鏃堕棿锛�4瀛楄妭锛�
+	upTimeBytes := bytes[offset : offset+4]
+	offset += 4
+
+	// 瑙f瀽鍩哄甫缂栬瘧鏃堕棿闀垮害锛�2瀛楄妭锛�
+	baseBandTimeLen := int(bytes[offset])*256 + int(bytes[offset+1])
+	offset += 2
+
+	// 瑙f瀽鍩哄甫缂栬瘧鏃堕棿锛堟牴鎹暱搴﹀瓧娈佃В鏋愶級
+	baseBandTime := bytes[offset : offset+baseBandTimeLen]
+	offset += baseBandTimeLen
+
+	// 瑙f瀽搴旂敤杞欢鐗堟湰锛�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])
+
+	// 瑙f瀽涓婄數鏃堕棿锛堝皢瀛楄妭鏁扮粍杞负鏁存暟锛�
+	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)
+}

--
Gitblit v1.8.0