| | |
| | | } |
| | | |
| | | type rfid struct { |
| | | DevName string `mapstructure:"dev"` |
| | | Baud int `mapstructure:"baud"` |
| | | EPC string `mapstructure:"epc"` |
| | | Position uint8 `mapstructure:"position"` |
| | | DevName string `mapstructure:"dev"` |
| | | Baud int `mapstructure:"baud"` |
| | | ReadFloor bool `mapstructure:"read-floor"` |
| | | EPC string `mapstructure:"epc"` |
| | | Position uint8 `mapstructure:"position"` |
| | | } |
| | | |
| | | type rateLimit struct { |
New file |
| | |
| | | package controller |
| | | |
| | | import ( |
| | | "gat1400Exchange/service" |
| | | "github.com/gin-gonic/gin" |
| | | "net/http" |
| | | ) |
| | | |
| | | type NVCSController struct { |
| | | } |
| | | |
| | | // 构造函数 |
| | | func NewNVCSController() SubPlatformController { |
| | | controller := SubPlatformController{} |
| | | |
| | | return controller |
| | | } |
| | | |
| | | func (n NVCSController) RunStatus(c *gin.Context) { |
| | | var runStatus = make(map[string]string, 0) |
| | | runStatus["floor"] = service.ElevatorRunFloor |
| | | |
| | | switch service.ElevatorRunState { |
| | | case 0: |
| | | runStatus["status"] = "停" |
| | | case 1: |
| | | runStatus["status"] = "上" |
| | | case 2: |
| | | runStatus["status"] = "下" |
| | | } |
| | | |
| | | c.JSON(http.StatusOK, gin.H{"success": true, "data": runStatus, "msg": "ok"}) |
| | | } |
New file |
| | |
| | | package rfid |
| | | |
| | | /* |
| | | E250019506C06104002d3446 -4F |
| | | E250019506C06103002d3346 -3F |
| | | E250019506C06102002d3246 -2F |
| | | E250019506C06102002d3146 -1F |
| | | E250019506C0400100003146 1F |
| | | E250019506C0400200003246 2F |
| | | E250019506C0400300003346 3F |
| | | E250019506C0400400003446 4F |
| | | E250019506C0400500003546 5F |
| | | E250019506C0400600003646 6F |
| | | E250019506C0400700003746 7F |
| | | E250019506C0400800003846 8F |
| | | E250019506C0400900003946 9F |
| | | E250019506C0601000313046 10F |
| | | E250019506C0601100313146 11F |
| | | E250019506C0601200313246 12F |
| | | E250019506C0601300313346 13F |
| | | E250019506C0601400313446 14F |
| | | E250019506C0601500313546 15F |
| | | E250019506C0601600313646 16F |
| | | E250019506C0601700313746 17F |
| | | E250019506C0601800313846 18F |
| | | E250019506C0601900313946 19F |
| | | E250019506C0602000323046 20F |
| | | E250019506C0602100323146 21F |
| | | E250019506C0602200323246 22F |
| | | E250019506C0602300323346 23F |
| | | E250019506C0602400323446 24F |
| | | E250019506C0602500323546 25F |
| | | E250019506C0602600323646 26F |
| | | E250019506C0602700323746 27F |
| | | E250019506C0602800323846 28F |
| | | E250019506C0602900323946 29F |
| | | E250019506C0603000333046 30F |
| | | E250019506C0603100333146 31F |
| | | E250019506C0603200333246 32F |
| | | E250019506C0603300333346 33F |
| | | E250019506C0603400333446 34F |
| | | E250019506C0603500333546 35F |
| | | E250019506C0603600333646 36F |
| | | E250019506C0603700333746 37F |
| | | E250019506C0603800333846 38F |
| | | E250019506C0603900333946 39F |
| | | E250019506C0604000343046 40F |
| | | */ |
| | |
| | | package rfid |
| | | |
| | | import ( |
| | | "encoding/hex" |
| | | "fmt" |
| | | "strconv" |
| | | "strings" |
| | | ) |
| | | |
| | | const ( |
| | | ControlWordEPCReadResponse6C uint32 = 0x00011200 |
| | | ) |
| | | |
| | | func Parse2Floor(input string) (string, error) { |
| | | // 定义前缀 |
| | | prefix := "E250019506C" |
| | | |
| | | // 检查字符串是否包含指定前缀 |
| | | if !strings.HasPrefix(input, prefix) { |
| | | return "", fmt.Errorf("字符串没有以指定前缀 %s 开始", prefix) |
| | | } |
| | | |
| | | // 提取长度部分的字符串并转换成整数 |
| | | lengthStr := input[len(prefix) : len(prefix)+2] |
| | | length, err := strconv.Atoi(lengthStr) |
| | | if err != nil { |
| | | return "", fmt.Errorf("长度解析错误: %v", err) |
| | | } |
| | | |
| | | //fmt.Println("data len ", length) |
| | | |
| | | // 获取末尾的字符,按照指定长度进行截取 |
| | | if len(input) < len(prefix)+2+length { // 每个字符是2个十六进制字符表示 |
| | | return "", fmt.Errorf("字符串长度不足") |
| | | } |
| | | |
| | | hexSection := input[len(input)-length:] |
| | | |
| | | // 将十六进制字符串转换为字节数组 |
| | | bytes, err := hex.DecodeString(hexSection) |
| | | if err != nil { |
| | | return "", fmt.Errorf("十六进制解析错误: %v", err) |
| | | } |
| | | |
| | | // 将字节数组转换为字符串 |
| | | return string(bytes), nil |
| | | } |
| | |
| | | package rfid |
| | | |
| | | import ( |
| | | "context" |
| | | "encoding/binary" |
| | | "encoding/hex" |
| | | "fmt" |
| | | "io" |
| | | "time" |
| | | |
| | | "github.com/tarm/serial" |
| | |
| | | } |
| | | |
| | | type Reader struct { |
| | | DevName string |
| | | Baud int |
| | | ReadDuration int |
| | | DevPort *serial.Port |
| | | DevName string |
| | | Baud int |
| | | ReadDuration int |
| | | EPCData string |
| | | ReadTimestamp int64 |
| | | DevPort *serial.Port |
| | | } |
| | | |
| | | func (r *Reader) OpenSerial() (err error) { |
| | |
| | | for { |
| | | select { |
| | | case <-stop: |
| | | fmt.Println("读取已超时") |
| | | return false, nil |
| | | default: |
| | | for i := 0; i < 1024; i++ { |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | 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) |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | import ( |
| | | "bytes" |
| | | "context" |
| | | "encoding/binary" |
| | | "encoding/hex" |
| | | "encoding/json" |
| | |
| | | ) |
| | | |
| | | var ElevatorRunState int |
| | | var ElevatorRunFloor string |
| | | var RunningCorrectTaskId string |
| | | |
| | | func A1CorrectFloor() { |
| | |
| | | |
| | | logger.Info("UDP server listening on port %s...", port) |
| | | |
| | | rfidReader := rfid.NewReader(config.RFIDConf.DevName, 115200, 5) |
| | | if config.RFIDConf.ReadFloor { |
| | | defer rfidReader.CloseSerial() |
| | | |
| | | err := rfidReader.OpenSerial() |
| | | if err != nil { |
| | | logger.Error("open rfid. %s", err.Error()) |
| | | return |
| | | } |
| | | |
| | | ctx, _ := context.WithCancel(context.Background()) |
| | | |
| | | go func() { |
| | | err := rfidReader.ReadEPCData(ctx) |
| | | if err != nil { |
| | | logger.Error("rfid read. %s", err.Error()) |
| | | } |
| | | }() |
| | | } |
| | | |
| | | var lastFloor int |
| | | var lastSaveTime int64 |
| | | // 无限循环等待接收数据 |
| | | for { |
| | | // 创建一个缓冲区来存储接收的数据 |
| | |
| | | } |
| | | |
| | | // correct floor when elevator stopped. |
| | | if elevator.Status.RunDir == 0 { |
| | | go A1CorrectFloor() |
| | | } else { |
| | | RunningCorrectTaskId = "" |
| | | if lastFloor == elevator.Status.Floor { |
| | | continue |
| | | } |
| | | //if elevator.Status.RunDir == 0 { |
| | | // go A1CorrectFloor() |
| | | //} else { |
| | | // RunningCorrectTaskId = "" |
| | | //} |
| | | |
| | | if lastFloor == elevator.Status.Floor && (time.Now().Unix()-lastSaveTime < 2) { |
| | | continue |
| | | } |
| | | lastFloor = elevator.Status.Floor |
| | | lastSaveTime = time.Now().Unix() |
| | | |
| | | // 程序部署在设备端, 字符叠加器上报的名称允许为空. 在云端, 名称必须与摄像机相同 |
| | | if elevator.Name == "" { |
| | | elevator.Name = "1" |
| | | } |
| | | |
| | | lastFloor = elevator.Status.Floor |
| | | ElevatorRunState = elevator.Status.RunDir |
| | | ElevatorRunFloor = elevator.Status.FloorName |
| | | if config.RFIDConf.ReadFloor && rfidReader.EPCData != "" { |
| | | ElevatorRunFloor, _ = rfid.Parse2Floor(rfidReader.EPCData) |
| | | |
| | | if ElevatorRunFloor != elevator.Status.FloorName { |
| | | logger.Warn("rfid epc %s, nvcs floor %s", ElevatorRunFloor, elevator.Status.FloorName) |
| | | } |
| | | } |
| | | |
| | | go func() { |
| | | var d = models.Positions{ |
| | | DeviceId: elevator.Name, |
| | | Pos: elevator.Status.FloorName, |
| | | RunDir: elevator.Status.RunDir, |
| | | Pos: ElevatorRunFloor, |
| | | RunDir: ElevatorRunState, |
| | | CreateTime: time.Now().Unix(), |
| | | TimeString: time.Now().Format("2006-01-02 15:04:05"), |
| | | } |
| | |
| | | iRunState = RunDown |
| | | } |
| | | |
| | | ElevatorRunState = iRunState |
| | | ElevatorRunFloor = req.State.Floor |
| | | |
| | | //// 已到最下层 |
| | | //if req.State.Floor == A2BottomFloor { |
| | | // runState = "上" |
| | |
| | | } |
| | | |
| | | iRunState = req.Status |
| | | ElevatorRunState = req.Status |
| | | ElevatorRunFloor = fmt.Sprintf("%dF", req.Floor) |
| | | logger.Debug("Received A2 report data %+v", req) |
| | | |
| | | // 记录电梯运行状态 |