From eff59c389fd046a75bb67b45e2e52dcc712413d9 Mon Sep 17 00:00:00 2001 From: zhangzengfei <zhangzengfei@smartai.com> Date: 星期五, 13 九月 2024 01:19:38 +0800 Subject: [PATCH] add rfid --- service/nvcs.go | 162 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 files changed, 141 insertions(+), 21 deletions(-) diff --git a/service/nvcs.go b/service/nvcs.go index d5b1f41..3e21a84 100644 --- a/service/nvcs.go +++ b/service/nvcs.go @@ -2,6 +2,8 @@ import ( "bytes" + "encoding/binary" + "encoding/hex" "encoding/json" "fmt" "io/ioutil" @@ -13,14 +15,39 @@ "gat1400Exchange/config" "gat1400Exchange/models" "gat1400Exchange/pkg/logger" + "gat1400Exchange/rfid" "gat1400Exchange/util" "github.com/gin-gonic/gin" + "github.com/google/uuid" "golang.org/x/text/encoding/simplifiedchinese" "golang.org/x/text/transform" ) -type ElevatorStatus struct { +type A1SetFloorFrame struct { + Header [16]byte // Fixed 16-byte header + Command byte // 1 byte command + MAC [6]byte // 6 bytes MAC address + DataLength uint16 // 2 bytes data length + Data []byte // Data area, length defined by DataLength + Checksum uint16 // 2 bytes CRC16 checksum +} + +// Convert frame to byte slice +func (f *A1SetFloorFrame) toBytes(includeChecksum bool) []byte { + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, f.Header) + binary.Write(buf, binary.LittleEndian, f.Command) + binary.Write(buf, binary.LittleEndian, f.MAC) + binary.Write(buf, binary.LittleEndian, f.DataLength) + buf.Write(f.Data) + if includeChecksum { + binary.Write(buf, binary.LittleEndian, f.Checksum) + } + return buf.Bytes() +} + +type A1ElevatorStatus struct { TotalFloors int `json:"TotalFloors"` Floor int `json:"Floor"` FloorName string `json:"FloorName"` @@ -28,15 +55,15 @@ Speed string `json:"Speed"` } -type Elevator struct { - Name string `json:"Name"` - IP string `json:"IP"` - Status ElevatorStatus `json:"Status"` - Alarm []interface{} `json:"Alarm"` // You might want to define a specific type for alarms +type A1Elevator struct { + Name string `json:"Name"` + IP string `json:"IP"` + Status A1ElevatorStatus `json:"Status"` + Alarm []interface{} `json:"Alarm"` // You might want to define a specific type for alarms } type A1ElevatorData struct { - Elevator []Elevator `json:"Elevator"` + Elevator []A1Elevator `json:"Elevator"` } const ( @@ -44,6 +71,97 @@ RunUp RunDown ) + +var ElevatorRunState int +var RunningCorrectTaskId string + +func A1CorrectFloor() { + if RunningCorrectTaskId != "" || config.RFIDConf.EPC == "" { + return + } + + taskId := uuid.New().String() + RunningCorrectTaskId = taskId + + rfidReader := rfid.NewReader(config.RFIDConf.DevName, 115200, 5) + defer rfidReader.CloseSerial() + + err := rfidReader.OpenSerial() + if err != nil { + logger.Error(err.Error()) + return + } + + isFind, err := rfidReader.ScanSpecificEPC(config.RFIDConf.EPC, 5) + if isFind && RunningCorrectTaskId == taskId { + frame := NewA1SetFloorFrame(config.NVCSConf.Mac, config.RFIDConf.Position) + address := "192.168.10.253:50000" + err := A1SendFrame(frame, address) + if err != nil { + logger.Debug("The floor has been calibrated.") + } else { + logger.Warn(err.Error()) + } + } +} + +func calculateCRC16(data []byte) uint16 { + var crc16 uint16 = 0xFFFF + + for i := 0; i < len(data); i++ { + crc16 ^= uint16(data[i]) + for j := 0; j < 8; j++ { + if crc16&0x0001 != 0 { + crc16 >>= 1 + crc16 ^= 0xA001 + } else { + crc16 >>= 1 + } + } + } + + return crc16 +} + +// Create a new frame based on provided data +func NewA1SetFloorFrame(macAddr string, floor uint8) *A1SetFloorFrame { + b, err := hex.DecodeString(macAddr) + if err != nil { + return nil + } + + if len(b) != 6 { + return nil + } + + var mac [6]byte + copy(mac[:], b) + + //b, err = hex.DecodeString(floor) + frame := &A1SetFloorFrame{ + Header: [16]byte{0x45, 0x4c, 0x45, 0x56, 0x41, 0x54, 0x4f, 0x52, 0x2d, 0x53, 0x45, 0x4e, 0x53, 0x4f, 0x52, 0x00}, + Command: 0x0c, + MAC: mac, + DataLength: 1, + Data: []byte{floor}, + } + + frame.Checksum = calculateCRC16(frame.toBytes(false)) // Calculate CRC without including the checksum itself + + return frame +} + +func A1SendFrame(frame *A1SetFloorFrame, address string) error { + conn, err := net.Dial("udp", address) + if err != nil { + return err + } + defer conn.Close() + + // Send frame + _, err = conn.Write(frame.toBytes(true)) + return err +} // 瀵规帴缃戠粶瑙嗛瀛楃鍙犲姞鍣�,鎺ユ敹udp鍙戦�佺殑妤煎眰淇℃伅, 鏇存柊device鍦板潃 func NVCSA1UDPServer() { @@ -96,36 +214,38 @@ continue } - var runState string - var iRunSate int + elevator := data.Elevator[0] // 璁板綍鐢垫杩愯鐘舵�� - iRunSate = data.Elevator[0].Status.RunDir + ElevatorRunState = elevator.Status.RunDir + + var runStateStr string if config.NVCSConf.RunState { - if data.Elevator[0].Status.RunDir == RunUp { - runState = "涓�" - } else if data.Elevator[0].Status.RunDir == RunDown { - runState = "涓�" + if elevator.Status.RunDir == RunUp { + runStateStr = "涓�" + } else if elevator.Status.RunDir == RunDown { + runStateStr = "涓�" } } if !config.NVCSConf.RunState { - runState = "" + runStateStr = "" } // 璁剧疆osd 鏍煎紡 "1F涓� 鍥� 鏋�" if config.NVCSConf.OSD != "" { - floorText := fmt.Sprintf("%s%s %s", data.Elevator[0].Status.FloorName, runState, config.NVCSConf.OSD) + floorText := fmt.Sprintf("%s%s %s", data.Elevator[0].Status.FloorName, runStateStr, config.NVCSConf.OSD) // 璋冪敤hik api 灏嗘枃瀛楁坊鍔犲埌osd鐨勫乏涓嬭 AddFloorToOSD(floorText) } - if data.Elevator[0].Status.RunDir > 0 { - continue + // correct floor when elevator stopped. + if ElevatorRunState == 0 { + A1CorrectFloor() + } else { + RunningCorrectTaskId = "" } - - elevator := data.Elevator[0] // 绋嬪簭閮ㄧ讲鍦ㄨ澶囩, 瀛楃鍙犲姞鍣ㄤ笂鎶ョ殑鍚嶇О鍏佽涓虹┖. 鍦ㄤ簯绔�, 鍚嶇О蹇呴』涓庢憚鍍忔満鐩稿悓 if elevator.Name == "" { @@ -135,7 +255,7 @@ var d = models.Positions{ DeviceId: elevator.Name, Pos: elevator.Status.FloorName, - RunDir: iRunSate, + RunDir: elevator.Status.RunDir, CreateTime: time.Now().Unix(), TimeString: time.Now().Format("2006-01-02 15:04:05"), } -- Gitblit v1.8.0