zhangzengfei
2024-10-17 7a19301f6972e0b81490e57200a634e4e3731a4c
完善rfid读取楼层
2个文件已添加
4个文件已修改
268 ■■■■■ 已修改文件
config/config.go 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
controller/nvcsCtl.go 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rfid/doc.go 48 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rfid/proto.go 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
rfid/rw.go 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
service/nvcs.go 59 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
config/config.go
@@ -69,10 +69,11 @@
}
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 {
controller/nvcsCtl.go
New file
@@ -0,0 +1,33 @@
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"})
}
rfid/doc.go
New file
@@ -0,0 +1,48 @@
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
*/
rfid/proto.go
@@ -1,5 +1,47 @@
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
}
rfid/rw.go
@@ -1,9 +1,11 @@
package rfid
import (
    "context"
    "encoding/binary"
    "encoding/hex"
    "fmt"
    "io"
    "time"
    "github.com/tarm/serial"
@@ -18,10 +20,12 @@
}
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) {
@@ -95,7 +99,6 @@
    for {
        select {
        case <-stop:
            fmt.Println("读取已超时")
            return false, nil
        default:
            for i := 0; i < 1024; i++ {
@@ -153,3 +156,67 @@
        }
    }
}
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)
        }
    }
}
service/nvcs.go
@@ -2,6 +2,7 @@
import (
    "bytes"
    "context"
    "encoding/binary"
    "encoding/hex"
    "encoding/json"
@@ -73,6 +74,7 @@
)
var ElevatorRunState int
var ElevatorRunFloor string
var RunningCorrectTaskId string
func A1CorrectFloor() {
@@ -185,7 +187,28 @@
    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 {
        // 创建一个缓冲区来存储接收的数据
@@ -239,27 +262,38 @@
        }
        // 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"),
            }
@@ -364,6 +398,9 @@
            iRunState = RunDown
        }
        ElevatorRunState = iRunState
        ElevatorRunFloor = req.State.Floor
        //// 已到最下层
        //if req.State.Floor == A2BottomFloor {
        //    runState = "上"
@@ -430,6 +467,8 @@
        }
        iRunState = req.Status
        ElevatorRunState = req.Status
        ElevatorRunFloor = fmt.Sprintf("%dF", req.Floor)
        logger.Debug("Received A2 report data %+v", req)
        // 记录电梯运行状态