zhangzengfei
2024-09-13 eff59c389fd046a75bb67b45e2e52dcc712413d9
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"),
      }