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