From 2fc94ba7b517125a7ed9771b48bb5d383021bc91 Mon Sep 17 00:00:00 2001
From: zhangzengfei <zhangzengfei@smartai.com>
Date: 星期日, 20 十月 2024 01:57:09 +0800
Subject: [PATCH] 优化楼层数据获取

---
 nvcs/osd.go               |   52 +-
 rfid/rw.go                |  170 +++++++++--
 nvcs/nvcs.go              |   55 +++
 rfid/client.go            |   21 +
 nvcs/a3.go                |   57 +++
 controller/nvcsCtl.go     |    6 
 /dev/null                 |    5 
 nvcs/a2.go                |  122 ++++++++
 nvcs/a1.go                |  228 +++++++++++++++
 nvcs/rfid.go              |   49 +++
 rfid/proto.go             |    2 
 repository/captureRepo.go |   14 
 nvcs/queue.go             |   20 +
 main.go                   |    3 
 nvcs/cache.go             |   85 +++++
 15 files changed, 816 insertions(+), 73 deletions(-)

diff --git a/controller/nvcsCtl.go b/controller/nvcsCtl.go
index 089d8fe..c1ef35d 100644
--- a/controller/nvcsCtl.go
+++ b/controller/nvcsCtl.go
@@ -1,7 +1,7 @@
 package controller
 
 import (
-	"gat1400Exchange/service"
+	"gat1400Exchange/nvcs"
 	"github.com/gin-gonic/gin"
 	"net/http"
 )
@@ -18,9 +18,9 @@
 
 func (n NVCSController) RunStatus(c *gin.Context) {
 	var runStatus = make(map[string]string, 0)
-	runStatus["floor"] = service.ElevatorRunFloor
+	runStatus["floor"] = nvcs.ElevatorRunFloor
 
-	switch service.ElevatorRunState {
+	switch nvcs.ElevatorRunState {
 	case 0:
 		runStatus["status"] = "鍋�"
 	case 1:
diff --git a/main.go b/main.go
index 5d71a57..7a6d792 100644
--- a/main.go
+++ b/main.go
@@ -3,6 +3,7 @@
 import (
 	"context"
 	"fmt"
+	"gat1400Exchange/nvcs"
 	"net/http"
 	"os"
 	"os/signal"
@@ -54,7 +55,7 @@
 	go client.Init1400Client(ctx)
 
 	// 鍚姩缃戠粶瑙嗛瀛楃鍙犲姞鍣ㄦ湇鍔�
-	go service.StartNVCSServer()
+	go nvcs.StartNVCSServer()
 
 	go service.InitSubscribeNotificationTasks()
 
diff --git a/nvcs/a1.go b/nvcs/a1.go
new file mode 100644
index 0000000..a13b7fe
--- /dev/null
+++ b/nvcs/a1.go
@@ -0,0 +1,228 @@
+package nvcs
+
+import (
+	"bytes"
+	"encoding/binary"
+	"encoding/hex"
+	"encoding/json"
+	"fmt"
+	"io/ioutil"
+	"net"
+	"time"
+
+	"gat1400Exchange/config"
+	"gat1400Exchange/pkg/logger"
+	"gat1400Exchange/rfid"
+
+	"github.com/google/uuid"
+	"golang.org/x/text/encoding/simplifiedchinese"
+	"golang.org/x/text/transform"
+)
+
+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"`
+	RunDir      int    `json:"RunDir"`
+	Speed       string `json:"Speed"`
+}
+
+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 []a1Elevator `json:"Elevator"`
+}
+
+var gRunningCorrectTaskId string
+
+func a1CorrectFloor() {
+	if gRunningCorrectTaskId != "" || config.RFIDConf.EPC == "" {
+		return
+	}
+
+	taskId := uuid.New().String()
+	gRunningCorrectTaskId = 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 && gRunningCorrectTaskId == taskId {
+		frame := newA1SetFloorFrame(config.NVCSConf.Mac, config.RFIDConf.Position)
+		address := "192.168.10.253:50000"
+		err := a1SendFrame(frame, address)
+		if err != nil {
+			logger.Warn(err.Error())
+		} else {
+			logger.Debug("The floor has been calibrated.")
+		}
+	}
+}
+
+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 a1UDPServer() {
+	// 鎸囧畾鐩戝惉鐨勭鍙�
+	port := config.ServeConf.Port
+
+	// 鍒涘缓涓�涓猆DP鍦板潃
+	address, err := net.ResolveUDPAddr("udp", fmt.Sprintf(":%s", port))
+	if err != nil {
+		logger.Error("Error resolving address:", err)
+		return
+	}
+
+	// 鍒涘缓涓�涓猆DP杩炴帴
+	conn, err := net.ListenUDP("udp", address)
+	if err != nil {
+		logger.Error("Error listening:", err)
+		return
+	}
+	defer conn.Close()
+
+	logger.Info("UDP server listening on port %s...", port)
+
+	// 鏃犻檺寰幆绛夊緟鎺ユ敹鏁版嵁
+	for {
+		// 鍒涘缓涓�涓紦鍐插尯鏉ュ瓨鍌ㄦ帴鏀剁殑鏁版嵁
+		buffer := make([]byte, 256)
+
+		// 浠庤繛鎺ヤ腑璇诲彇鏁版嵁
+		numBytes, clientAddr, err := conn.ReadFromUDP(buffer)
+		if err != nil {
+			logger.Warn("Error reading from UDP connection:%s", err.Error())
+			continue
+		}
+
+		// 璁惧涓婁紶鐨勪腑鏂囨暟鎹负GBK缂栫爜, 杞崲涓簎tf8
+		decoder := simplifiedchinese.GBK.NewDecoder()
+		reader := transform.NewReader(bytes.NewReader(buffer[:numBytes]), decoder)
+		decodedBytes, err := ioutil.ReadAll(reader)
+
+		var data a1ElevatorData
+		err = json.Unmarshal(decodedBytes, &data)
+		if err != nil {
+			logger.Warn("ElevatorData unmarshal error:%s", err.Error())
+			continue
+		}
+		logger.Debug("Received %d bytes from %s, %+v", numBytes, clientAddr, data)
+
+		if len(data.Elevator) == 0 {
+			continue
+		}
+
+		elevator := data.Elevator[0]
+
+		// 绋嬪簭閮ㄧ讲鍦ㄨ澶囩, 瀛楃鍙犲姞鍣ㄤ笂鎶ョ殑鍚嶇О鍏佽涓虹┖. 鍦ㄤ簯绔�, 鍚嶇О蹇呴』涓庢憚鍍忔満鐩稿悓
+		if elevator.Name == "" {
+			elevator.Name = "1"
+		}
+
+		var runState = elevatorRunData{
+			Device:    elevator.Name,
+			Timestamp: time.Now().Unix(),
+			Floor:     elevator.Status.FloorName,
+			RunState:  elevator.Status.RunDir,
+		}
+
+		// correct floor when elevator stopped.
+		//if elevator.Status.RunDir == 0 {
+		//	go A1CorrectFloor()
+		//} else {
+		//	RunningCorrectTaskId = ""
+		//}
+
+		queue.enqueue(runState)
+	}
+}
diff --git a/nvcs/a2.go b/nvcs/a2.go
new file mode 100644
index 0000000..224b290
--- /dev/null
+++ b/nvcs/a2.go
@@ -0,0 +1,122 @@
+package nvcs
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"strings"
+	"time"
+
+	"gat1400Exchange/config"
+	"gat1400Exchange/pkg/logger"
+	"gat1400Exchange/util"
+
+	"github.com/gin-gonic/gin"
+)
+
+/*
+A2 娆� 鏁版嵁涓婃姤鏍煎紡
+
+	{
+		"id": "10c8a1b0051607361c",
+		"State": {
+		"Floor": "-1",
+		"Floor_flag": "宸叉牎鍑�",
+		"JZ_flag": "宸叉牎鍑�,",
+		"JZ_i": 7,
+		"Pressure": "99766",
+		"Speed": "0.000",
+		"Status": "鍋滄顒�1",
+		"TFloor": 7,
+		"T_acc": "0.062",
+		"X_acc": "1.175",
+		"Y_acc": "-1.129",
+		"Z_acc": "8.344"
+	}
+*/
+type a2ElevatorData struct {
+	Id    string `json:"id"`
+	State struct {
+		Floor  string `json:"Floor"`
+		Status string `json:"Status"`
+		TFloor int64  `json:"TFloor"`
+		Speed  string `json:"Speed"`
+	} `json:"State"`
+}
+
+type a2ElevatorConfig struct {
+	FloorData []string `json:"floordata"`
+}
+
+var a2TopFloor string
+var a2BottomFloor string
+
+func getA2ElevatorConfig() {
+	url := "http://192.168.10.253/cgi-bin/liftnum.cgi"
+	payload := []byte("{\"display\":1}")
+	header := map[string]string{
+		"Cookie": "eyJuYW1lIjoiYWRtaW4iLCAicGFzZCI6ImFkbWluMTIzIn0=",
+	}
+
+	rsp, err := util.HttpPost(url, header, payload)
+	if err != nil {
+		logger.Warn("Get A2 floor data failure,%s", err.Error())
+		return
+	}
+
+	var configData a2ElevatorConfig
+	err = json.Unmarshal(rsp, &configData)
+	if err != nil {
+		logger.Warn("Unmarshal A2 floor data failure,%s", err.Error())
+		return
+	}
+
+	if len(configData.FloorData) > 0 {
+		a2BottomFloor, a2TopFloor = configData.FloorData[0], configData.FloorData[len(configData.FloorData)-1]
+	}
+
+	logger.Info("A2 floor config total:%d, bottomFloor:%s, topFloor:%s", len(configData.FloorData), a2BottomFloor, a2TopFloor)
+}
+
+func a2WebServer() {
+	// 鍏堣幏鍙栨�绘ゼ灞傛暟, 璁板綍鏈�楂樺眰
+	//GetA2ElevatorConfig()
+
+	r := gin.Default()
+
+	r.POST("/", func(c *gin.Context) {
+		var req a2ElevatorData
+		var iRunState int
+
+		err := c.BindJSON(&req)
+		if err != nil {
+			c.JSON(http.StatusBadRequest, nil)
+			return
+		}
+
+		logger.Debug("Received A2 report data %+v", req)
+
+		// 璁板綍鐢垫杩愯鐘舵��
+		if strings.Contains(req.State.Status, "涓�") {
+			iRunState = RunUp
+		} else if strings.Contains(req.State.Status, "涓�") {
+			iRunState = RunDown
+		}
+
+		var runState = elevatorRunData{
+			Device:    req.Id,
+			Timestamp: time.Now().Unix(),
+			Floor:     req.State.Floor,
+			RunState:  iRunState,
+		}
+
+		queue.enqueue(runState)
+
+		c.JSON(http.StatusOK, "ok")
+	})
+
+	err := r.Run(fmt.Sprintf(":%s", config.NVCSConf.Port))
+	if err != nil {
+		logger.Warn("Start NVCS WebServer error, %s", err.Error())
+	}
+}
diff --git a/nvcs/a3.go b/nvcs/a3.go
new file mode 100644
index 0000000..519e68b
--- /dev/null
+++ b/nvcs/a3.go
@@ -0,0 +1,57 @@
+package nvcs
+
+import (
+	"fmt"
+	"net/http"
+	"time"
+
+	"gat1400Exchange/config"
+	"gat1400Exchange/pkg/logger"
+
+	"github.com/gin-gonic/gin"
+)
+
+/*
+485骞冲眰浼犳劅鍣� + 485杞互澶綉妯″潡
+*/
+type a3ElevatorData struct {
+	Id     string `json:"id"`
+	Time   string `json:"time"`
+	Total  int    `json:"total"`
+	Status int    `json:"status"`
+	Floor  int    `json:"floor"`
+}
+
+func a3WebServer() {
+	r := gin.Default()
+
+	r.POST("/", func(c *gin.Context) {
+		var req a3ElevatorData
+
+		err := c.BindJSON(&req)
+		if err != nil {
+			c.JSON(http.StatusBadRequest, nil)
+			return
+		}
+
+		logger.Debug("Received A3 report data %+v", req)
+
+		floor := fmt.Sprintf("%dF", req.Floor)
+
+		var runState = elevatorRunData{
+			Device:    req.Id,
+			Timestamp: time.Now().Unix(),
+			Floor:     floor,
+			RunState:  req.Status,
+		}
+
+		queue.enqueue(runState)
+
+		c.JSON(http.StatusOK, "ok")
+	})
+
+	err := r.Run(fmt.Sprintf(":%s", config.NVCSConf.Port))
+	if err != nil {
+		logger.Warn("Start NVCS WebServer error, %s", err.Error())
+	}
+}
diff --git a/nvcs/cache.go b/nvcs/cache.go
new file mode 100644
index 0000000..e792c55
--- /dev/null
+++ b/nvcs/cache.go
@@ -0,0 +1,85 @@
+package nvcs
+
+import (
+	"fmt"
+	"time"
+
+	"gat1400Exchange/config"
+	"gat1400Exchange/models"
+	"gat1400Exchange/pkg/logger"
+)
+
+type simpleCache struct {
+	data       map[int64]elevatorRunData
+	expiration time.Duration
+}
+
+func newCache(expiration time.Duration) *simpleCache {
+	return &simpleCache{
+		data:       make(map[int64]elevatorRunData),
+		expiration: expiration,
+	}
+}
+
+// 瀛樺偍鏁版嵁鍒扮紦瀛樹腑
+func (c *simpleCache) store(data elevatorRunData) {
+	if config.RFIDConf.ReadFloor && gRFIDFloor != data.Floor {
+		if data.RunState == RunStop {
+			logger.Warn("A floor error has occurred rfid epc %s, nvcs floor %s", gRFIDFloor, data.Floor)
+		}
+
+		data.Floor = gRFIDFloor
+	}
+
+	// 濡傛灉妤煎眰鐩稿悓锛屽苟涓旀暟鎹湪1绉掑唴锛屽垯蹇界暐
+	if existingData, ok := c.data[data.Timestamp]; ok {
+		if existingData.Floor == data.Floor {
+			return
+		}
+	}
+
+	// 鏁版嵁搴撲繚瀛樹竴浠�
+	go func() {
+		var d = models.Positions{
+			DeviceId:   data.Device,
+			Pos:        data.Floor,
+			RunDir:     data.RunState,
+			CreateTime: time.Now().Unix(),
+			TimeString: time.Now().Format("2006-01-02 15:04:05"),
+		}
+
+		err := d.Save()
+		if err != nil {
+			logger.Warn("Device position update error:%s", err.Error())
+		}
+	}()
+
+	// 鍐橭SD
+	var runStateStr string
+	if config.NVCSConf.RunState {
+		if data.RunState == RunUp {
+			runStateStr = "涓�"
+		} else if data.RunState == RunDown {
+			runStateStr = "涓�"
+		}
+	}
+
+	// 璁剧疆osd  鏍煎紡 "1F涓� 鍥� 鏋�"
+	if config.NVCSConf.OSD != "" {
+		floorText := fmt.Sprintf("%s%s %s", data.Floor, runStateStr, config.NVCSConf.OSD)
+
+		// 璋冪敤hik api 灏嗘枃瀛楁坊鍔犲埌osd鐨勫乏涓嬭
+		go addFloorToOSD(floorText)
+	}
+
+	c.data[data.Timestamp] = data
+}
+
+// 鍒犻櫎杩囨湡鏁版嵁
+func (c *simpleCache) cleanExpired() {
+	for t := range c.data {
+		if time.Since(time.Unix(t, 0)) > c.expiration {
+			delete(c.data, t)
+		}
+	}
+}
diff --git a/nvcs/nvcs.go b/nvcs/nvcs.go
new file mode 100644
index 0000000..bf6ccd8
--- /dev/null
+++ b/nvcs/nvcs.go
@@ -0,0 +1,55 @@
+package nvcs
+
+import (
+	"context"
+	"gat1400Exchange/config"
+	"time"
+)
+
+const (
+	RunStop = iota
+	RunUp
+	RunDown
+)
+
+// 鏁版嵁缁撴瀯
+type elevatorRunData struct {
+	Device    string
+	Timestamp int64
+	Floor     string
+	RunState  int
+}
+
+var queue = newChQueue(100)
+var cache = newCache(5 * time.Minute)
+
+func StartNVCSServer(ctx context.Context) {
+
+	go listenQueue()
+
+	if config.RFIDConf.ReadFloor {
+		go readRFID(ctx)
+	}
+
+	if config.NVCSConf.Model == "A1" {
+		go a1UDPServer()
+	}
+
+	if config.NVCSConf.Model == "A2" {
+		go a2WebServer()
+	}
+
+	if config.NVCSConf.Model == "A3" {
+		go a3WebServer()
+	}
+}
+
+func listenQueue() {
+	for {
+		data := queue.dequeue()
+		cache.store(data)
+
+		// 娓呯悊杩囨湡鏁版嵁
+		cache.cleanExpired()
+	}
+}
diff --git a/service/osd.go b/nvcs/osd.go
similarity index 64%
rename from service/osd.go
rename to nvcs/osd.go
index 3961ca3..5608cf6 100644
--- a/service/osd.go
+++ b/nvcs/osd.go
@@ -1,24 +1,26 @@
-package service
+package nvcs
 
 import (
 	"encoding/xml"
-	"gat1400Exchange/pkg/logger"
-	dac "github.com/xinsnake/go-http-digest-auth-client"
 	"io/ioutil"
+
+	"gat1400Exchange/pkg/logger"
+
+	dac "github.com/xinsnake/go-http-digest-auth-client"
 )
 
 // 璁剧疆鍏朵粬瀛楃鐨勭涓�涓�, 浣嶇疆鍥哄畾浣�7
 // 鎽勫儚鏈轰俊鎭殏鏃跺浐瀹�, 閬垮厤娉勯湶
 const (
-	HikISAPIOverlaySetUrl = "/ISAPI/System/Video/inputs/channels/1/overlays/text/7"
-	CameraWebAddr         = "http://192.168.10.11:40080"
-	CameraWebUser         = "admin"
-	CameraWebPassword     = "a1234567"
+	hikISAPIOverlay7SetUrl = "/ISAPI/System/Video/inputs/channels/1/overlays/text/7"
+	cameraWebAddr          = "http://192.168.10.11:40080"
+	cameraWebUser          = "admin"
+	cameraWebPassword      = "a1234567"
 )
 
-var overlayText TextOverlay
+var overlayText textOverlay
 
-type TextOverlay struct {
+type textOverlay struct {
 	Id               int64  `xml:"id"`
 	Enabled          bool   `xml:"enabled"`
 	PositionX        int64  `xml:"positionX"`
@@ -28,12 +30,24 @@
 	IsPersistentText bool   `xml:"isPersistentText"`
 }
 
-func AddFloorToOSD(osdText string) {
-	overlay7Url := CameraWebAddr + HikISAPIOverlaySetUrl
+func hikISAPIRequest(username, password, method, url, body string) ([]byte, error) {
+	dr := dac.NewRequest(username, password, method, url, body)
+	resp, err := dr.Execute()
+	if err != nil {
+		return nil, err
+	}
+
+	defer resp.Body.Close()
+
+	return ioutil.ReadAll(resp.Body)
+}
+
+func addFloorToOSD(osdText string) {
+	overlay7Url := cameraWebAddr + hikISAPIOverlay7SetUrl
 
 	// 鑾峰彇宸︿笅瑙掔涓�涓瓧绗︾殑浣嶇疆
 	if overlayText.DisplayText == "" {
-		rsp, err := ISAPIRequest(CameraWebUser, CameraWebPassword, "GET", overlay7Url, "")
+		rsp, err := hikISAPIRequest(cameraWebUser, cameraWebPassword, "GET", overlay7Url, "")
 		if err != nil {
 			logger.Warn("Get osd info failure")
 			return
@@ -48,21 +62,9 @@
 
 	overlayText.DisplayText = osdText
 	body, _ := xml.Marshal(overlayText)
-	_, err := ISAPIRequest(CameraWebUser, CameraWebPassword, "PUT", overlay7Url, string(body))
+	_, err := hikISAPIRequest(cameraWebUser, cameraWebPassword, "PUT", overlay7Url, string(body))
 	if err != nil {
 		logger.Warn("Camera osd set failure!!")
 		return
 	}
-}
-
-func ISAPIRequest(username, password, method, url, body string) ([]byte, error) {
-	dr := dac.NewRequest(username, password, method, url, body)
-	resp, err := dr.Execute()
-	if err != nil {
-		return nil, err
-	}
-
-	defer resp.Body.Close()
-
-	return ioutil.ReadAll(resp.Body)
 }
diff --git a/nvcs/queue.go b/nvcs/queue.go
new file mode 100644
index 0000000..423c65d
--- /dev/null
+++ b/nvcs/queue.go
@@ -0,0 +1,20 @@
+package nvcs
+
+type chQueue struct {
+	data chan elevatorRunData
+}
+
+func newChQueue(size int) *chQueue {
+	return &chQueue{
+		data: make(chan elevatorRunData, size),
+	}
+}
+
+func (q *chQueue) enqueue(data elevatorRunData) {
+	q.data <- data
+}
+
+func (q *chQueue) dequeue() elevatorRunData {
+	data := <-q.data
+	return data
+}
diff --git a/nvcs/rfid.go b/nvcs/rfid.go
new file mode 100644
index 0000000..0a39412
--- /dev/null
+++ b/nvcs/rfid.go
@@ -0,0 +1,49 @@
+package nvcs
+
+import (
+	"context"
+	"time"
+
+	"gat1400Exchange/config"
+	"gat1400Exchange/pkg/logger"
+	"gat1400Exchange/rfid"
+)
+
+var gRFIDFloor string
+
+func readRFID(ctx context.Context) {
+	rfidReader := rfid.NewReader(config.RFIDConf.DevName, 115200, 5)
+	defer rfidReader.CloseSerial()
+
+	err := rfidReader.OpenSerial()
+	if err != nil {
+		logger.Error("open rfid. %s", err.Error())
+		return
+	}
+
+	go func() {
+		err := rfidReader.ReadEPCData(ctx)
+		if err != nil {
+			logger.Error("rfid read. %s", err.Error())
+		}
+	}()
+
+	for {
+		select {
+		case <-ctx.Done():
+			return
+		default:
+			if rfidReader.Alive {
+				floor, _ := rfid.Parse2Floor(rfidReader.EPCData)
+
+				if floor != gRFIDFloor {
+					gRFIDFloor = floor
+					logger.Debug("rfid read epc floor %s", gRFIDFloor)
+				}
+
+			}
+
+			time.Sleep(200 * time.Millisecond)
+		}
+	}
+}
diff --git a/repository/captureRepo.go b/repository/captureRepo.go
index bb82cf5..9941a4a 100644
--- a/repository/captureRepo.go
+++ b/repository/captureRepo.go
@@ -3,6 +3,7 @@
 import (
 	"encoding/base64"
 	"encoding/json"
+	"gat1400Exchange/nvcs"
 	"time"
 
 	"gat1400Exchange/client"
@@ -10,7 +11,6 @@
 	"gat1400Exchange/models"
 	"gat1400Exchange/pkg"
 	"gat1400Exchange/pkg/logger"
-	"gat1400Exchange/service"
 	"gat1400Exchange/util"
 	"gat1400Exchange/vo"
 )
@@ -224,11 +224,11 @@
 			var dbPos models.Positions
 			if err := dbPos.FindMovePosition(faceAppearTime.Unix()+5, floor); err == nil {
 				switch dbPos.RunDir {
-				case service.RunUp:
+				case nvcs.RunUp:
 					runDir = "in"
-				case service.RunDown:
+				case nvcs.RunDown:
 					runDir = "out"
-				case service.RunStop:
+				case nvcs.RunStop:
 					runDir = ""
 				}
 
@@ -291,11 +291,11 @@
 			var dbPos models.Positions
 			if err := dbPos.FindMovePosition(faceAppearTime.Unix()+5, floor); err == nil {
 				switch dbPos.RunDir {
-				case service.RunUp:
+				case nvcs.RunUp:
 					runDir = "1"
-				case service.RunDown:
+				case nvcs.RunDown:
 					runDir = "2"
-				case service.RunStop:
+				case nvcs.RunStop:
 					runDir = "0"
 				}
 
diff --git a/rfid/client.go b/rfid/client.go
new file mode 100644
index 0000000..06581a4
--- /dev/null
+++ b/rfid/client.go
@@ -0,0 +1,21 @@
+package rfid
+
+import (
+	"time"
+
+	"github.com/tarm/serial"
+)
+
+func OpenSerial(devName string, baud, timeout int) (*serial.Port, error){
+	config := &serial.Config{
+		Name: devName,
+		Baud: baud,
+		ReadTimeout: time.Duration(timeout) * time.Second,
+	}
+
+	return serial.OpenPort(config)
+}
+
+func CloseSerial(port *serial.Port) error {
+	return port.Close()
+}
diff --git a/rfid/proto.go b/rfid/proto.go
index 10f208c..e6b11b2 100644
--- a/rfid/proto.go
+++ b/rfid/proto.go
@@ -9,6 +9,8 @@
 
 const (
 	ControlWordEPCReadResponse6C uint32 = 0x00011200
+	ControlWordConnectionStatus  uint32 = 0x00011112
+	ControlWordDeviceInfo        uint32 = 0x00010100
 )
 
 func Parse2Floor(input string) (string, error) {
diff --git a/rfid/rw.go b/rfid/rw.go
index 2df132f..4cb8d2d 100644
--- a/rfid/rw.go
+++ b/rfid/rw.go
@@ -13,18 +13,21 @@
 
 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
 	EPCData       string
-	ReadTimestamp int64
+	ReadTimeout   int
+	Alive         bool
+	HeartbeatTime int64
 	DevPort       *serial.Port
 }
 
@@ -81,7 +84,7 @@
 func (r *Reader) ReadResponse() (int, error) {
 	buf := make([]byte, 1024) // 鏍规嵁鍗忚鏈�澶ф暟鎹暱搴﹁皟鏁寸紦鍐插尯
 	n, err := r.DevPort.Read(buf)
-	fmt.Printf("Recive message %x\n", buf[:n])
+	fmt.Printf("Recive message %X\n", buf[:n])
 
 	return n, err
 }
@@ -94,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)
@@ -121,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])
@@ -147,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 {
@@ -165,6 +168,20 @@
 	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)
@@ -190,10 +207,10 @@
 			if buf[0] != 0x5A {
 				continue // 蹇界暐閿欒甯�
 			}
-			fmt.Printf("Read message %x\n", buf[:n]) // 鎵撳嵃鍗忚鎺у埗瀛楄繘琛岃皟璇�
+
+			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) {
@@ -201,25 +218,26 @@
 				continue
 			}
 
-			// 瑙f瀽鍗忚鎺у埗瀛� (浠呭湪闇�瑕佹椂浣跨敤)
-			//fmt.Printf("Control Word: %x\n", buf[1:5]) // 鎵撳嵃鍗忚鎺у埗瀛楄繘琛岃皟璇�
+			r.HeartbeatTime = time.Now().Unix()
+			r.Alive = true
 
+			// 瑙f瀽鍗忚鎺у埗瀛�
 			controlWord := binary.BigEndian.Uint32(buf[1:5])
-			if controlWord != ControlWordEPCReadResponse6C {
-				fmt.Printf("Control Word: %d, rec word %d\n", ControlWordEPCReadResponse6C, controlWord)
-				continue
+
+			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)
 			}
-
-			// 瑙f瀽EPC鏁版嵁闀垮害
-			epcLength := binary.BigEndian.Uint16(buf[7:9])
-			//fmt.Printf("EPC length %d, EPC %x \n", epcLength, buf[9:9+epcLength])
-
-			// 鍥炶皟浼犻�乪pc鏁版嵁
-			//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)
 		}
 	}
 }
@@ -230,6 +248,41 @@
 
 	_, 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
 	}
 
@@ -239,18 +292,71 @@
 	return err
 }
 
-func (r *Reader) SetPower20() error {
-	cmd := "5A0001020100020132D230"
-
+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 nil
+		return err
 	}
 
 	// todo parse response
 	r.ReadResponse()
 
-	return err
+	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)
 }
diff --git a/service/nvcs.go b/service/nvcs.go
deleted file mode 100644
index 6c331de..0000000
--- a/service/nvcs.go
+++ /dev/null
@@ -1,526 +0,0 @@
-package service
-
-import (
-	"bytes"
-	"context"
-	"encoding/binary"
-	"encoding/hex"
-	"encoding/json"
-	"fmt"
-	"io/ioutil"
-	"net"
-	"net/http"
-	"strings"
-	"time"
-
-	"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 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"`
-	RunDir      int    `json:"RunDir"`
-	Speed       string `json:"Speed"`
-}
-
-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 []A1Elevator `json:"Elevator"`
-}
-
-const (
-	RunStop = iota
-	RunUp
-	RunDown
-)
-
-var ElevatorRunState int
-var ElevatorRunFloor string
-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.Warn(err.Error())
-		} else {
-			logger.Debug("The floor has been calibrated.")
-		}
-	}
-}
-
-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() {
-	// 鎸囧畾鐩戝惉鐨勭鍙�
-	port := config.ServeConf.Port
-
-	// 鍒涘缓涓�涓猆DP鍦板潃
-	address, err := net.ResolveUDPAddr("udp", fmt.Sprintf(":%s", port))
-	if err != nil {
-		logger.Error("Error resolving address:", err)
-		return
-	}
-
-	// 鍒涘缓涓�涓猆DP杩炴帴
-	conn, err := net.ListenUDP("udp", address)
-	if err != nil {
-		logger.Error("Error listening:", err)
-		return
-	}
-	defer conn.Close()
-
-	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 {
-		// 鍒涘缓涓�涓紦鍐插尯鏉ュ瓨鍌ㄦ帴鏀剁殑鏁版嵁
-		buffer := make([]byte, 256)
-
-		// 浠庤繛鎺ヤ腑璇诲彇鏁版嵁
-		numBytes, clientAddr, err := conn.ReadFromUDP(buffer)
-		if err != nil {
-			logger.Warn("Error reading from UDP connection:%s", err.Error())
-			continue
-		}
-
-		// 璁惧涓婁紶鐨勪腑鏂囨暟鎹负GBK缂栫爜, 杞崲涓簎tf8
-		decoder := simplifiedchinese.GBK.NewDecoder()
-		reader := transform.NewReader(bytes.NewReader(buffer[:numBytes]), decoder)
-		decodedBytes, err := ioutil.ReadAll(reader)
-
-		var data A1ElevatorData
-		err = json.Unmarshal(decodedBytes, &data)
-		if err != nil {
-			logger.Warn("ElevatorData unmarshal error:%s", err.Error())
-			continue
-		}
-		logger.Debug("Received %d bytes from %s, %+v", numBytes, clientAddr, data)
-
-		if len(data.Elevator) == 0 {
-			continue
-		}
-
-		elevator := data.Elevator[0]
-
-		var runStateStr string
-		if config.NVCSConf.RunState {
-			if elevator.Status.RunDir == RunUp {
-				runStateStr = "涓�"
-			} else if elevator.Status.RunDir == RunDown {
-				runStateStr = "涓�"
-			}
-		}
-
-		if !config.NVCSConf.RunState {
-			runStateStr = ""
-		}
-
-		// correct floor when elevator stopped.
-		//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"
-		}
-
-		ElevatorRunState = elevator.Status.RunDir
-		ElevatorRunFloor = elevator.Status.FloorName
-		if config.RFIDConf.ReadFloor && rfidReader.EPCData != "" {
-			ElevatorRunFloor, _ = rfid.Parse2Floor(rfidReader.EPCData)
-			logger.Debug("rfid read epc floor %s", ElevatorRunFloor)
-			if elevator.Status.RunDir == RunStop && ElevatorRunFloor != elevator.Status.FloorName {
-				logger.Warn("A floor error has occurred rfid epc %s, nvcs floor %s", ElevatorRunFloor, elevator.Status.FloorName)
-			}
-		}
-
-		// 璁剧疆osd  鏍煎紡 "1F涓� 鍥� 鏋�"
-		if config.NVCSConf.OSD != "" {
-			floorText := fmt.Sprintf("%s%s %s", ElevatorRunFloor, runStateStr, config.NVCSConf.OSD)
-
-			// 璋冪敤hik api 灏嗘枃瀛楁坊鍔犲埌osd鐨勫乏涓嬭
-			AddFloorToOSD(floorText)
-		}
-
-		go func() {
-			var d = models.Positions{
-				DeviceId:   elevator.Name,
-				Pos:        ElevatorRunFloor,
-				RunDir:     ElevatorRunState,
-				CreateTime: time.Now().Unix(),
-				TimeString: time.Now().Format("2006-01-02 15:04:05"),
-			}
-
-			err = d.Save()
-			if err != nil {
-				logger.Warn("Device position update error:%s", err.Error())
-			}
-		}()
-	}
-}
-
-/*
-A2 娆� 鏁版嵁涓婃姤鏍煎紡
-
-	{
-		"id": "10c8a1b0051607361c",
-		"State": {
-		"Floor": "-1",
-		"Floor_flag": "宸叉牎鍑�",
-		"JZ_flag": "宸叉牎鍑�,",
-		"JZ_i": 7,
-		"Pressure": "99766",
-		"Speed": "0.000",
-		"Status": "鍋滄顒�1",
-		"TFloor": 7,
-		"T_acc": "0.062",
-		"X_acc": "1.175",
-		"Y_acc": "-1.129",
-		"Z_acc": "8.344"
-	}
-*/
-type A2ElevatorData struct {
-	Id    string `json:"id"`
-	State struct {
-		Floor  string `json:"Floor"`
-		Status string `json:"Status"`
-		TFloor int64  `json:"TFloor"`
-		Speed  string `json:"Speed"`
-	} `json:"State"`
-}
-
-type A2ElevatorConfig struct {
-	FloorData []string `json:"floordata"`
-}
-
-var A2TopFloor string
-var A2BottomFloor string
-
-func GetA2ElevatorConfig() {
-	url := "http://192.168.10.253/cgi-bin/liftnum.cgi"
-	payload := []byte("{\"display\":1}")
-	header := map[string]string{
-		"Cookie": "eyJuYW1lIjoiYWRtaW4iLCAicGFzZCI6ImFkbWluMTIzIn0=",
-	}
-
-	rsp, err := util.HttpPost(url, header, payload)
-	if err != nil {
-		logger.Warn("Get A2 floor data failure,%s", err.Error())
-		return
-	}
-
-	var configData A2ElevatorConfig
-	err = json.Unmarshal(rsp, &configData)
-	if err != nil {
-		logger.Warn("Unmarshal A2 floor data failure,%s", err.Error())
-		return
-	}
-
-	if len(configData.FloorData) > 0 {
-		A2BottomFloor, A2TopFloor = configData.FloorData[0], configData.FloorData[len(configData.FloorData)-1]
-	}
-
-	logger.Info("A2 floor config total:%d, bottomFloor:%s, topFloor:%s", len(configData.FloorData), A2BottomFloor, A2TopFloor)
-}
-
-func NVCSA2WebServer() {
-	// 鍏堣幏鍙栨�绘ゼ灞傛暟, 璁板綍鏈�楂樺眰
-	//GetA2ElevatorConfig()
-
-	r := gin.Default()
-
-	r.POST("/", func(c *gin.Context) {
-		var req A2ElevatorData
-		var runState string
-		var iRunState int
-
-		err := c.BindJSON(&req)
-		if err != nil {
-			c.JSON(http.StatusBadRequest, nil)
-			return
-		}
-
-		logger.Debug("Received A2 report data %+v", req)
-
-		// 璁板綍鐢垫杩愯鐘舵��
-		if strings.Contains(req.State.Status, "涓�") {
-			runState = "涓�"
-			iRunState = RunUp
-		} else if strings.Contains(req.State.Status, "涓�") {
-			runState = "涓�"
-			iRunState = RunDown
-		}
-
-		ElevatorRunState = iRunState
-		ElevatorRunFloor = req.State.Floor
-
-		//// 宸插埌鏈�涓嬪眰
-		//if req.State.Floor == A2BottomFloor {
-		//	runState = "涓�"
-		//	iRunState = RunUp
-		//}
-		//if req.State.Floor == A2TopFloor {
-		//	runState = "涓�"
-		//	iRunState = RunDown
-		//}
-
-		if !config.NVCSConf.RunState {
-			runState = ""
-		}
-
-		if config.NVCSConf.OSD != "" {
-			floorText := fmt.Sprintf("%s%s %s", req.State.Floor, runState, config.NVCSConf.OSD)
-
-			// 璋冪敤hik api 灏嗘枃瀛楁坊鍔犲埌osd鐨勫乏涓嬭
-			AddFloorToOSD(floorText)
-		}
-
-		var d = models.Positions{
-			DeviceId:   req.Id,
-			Pos:        req.State.Floor,
-			RunDir:     iRunState,
-			CreateTime: time.Now().Unix(),
-			TimeString: time.Now().Format("2006-01-02 15:04:05"),
-		}
-
-		err = d.Save()
-		if err != nil {
-			logger.Warn("Device position update error:%s", err.Error())
-		}
-
-		c.JSON(http.StatusOK, "ok")
-	})
-
-	err := r.Run(fmt.Sprintf(":%s", config.NVCSConf.Port))
-	if err != nil {
-		logger.Warn("Start NVCS WebServer error, %s", err.Error())
-	}
-}
-
-type A3ElevatorData struct {
-	Id     string `json:"id"`
-	Time   string `json:"time"`
-	Total  int    `json:"total"`
-	Status int    `json:"status"`
-	Floor  int    `json:"floor"`
-}
-
-func NVCSA3WebServer() {
-	r := gin.Default()
-
-	r.POST("/", func(c *gin.Context) {
-		var req A3ElevatorData
-		var runState string
-		var iRunState int
-
-		err := c.BindJSON(&req)
-		if err != nil {
-			c.JSON(http.StatusBadRequest, nil)
-			return
-		}
-
-		iRunState = req.Status
-		ElevatorRunState = req.Status
-		ElevatorRunFloor = fmt.Sprintf("%dF", req.Floor)
-		logger.Debug("Received A2 report data %+v", req)
-
-		// 璁板綍鐢垫杩愯鐘舵��
-		if iRunState == RunUp {
-			runState = "涓�"
-		} else if iRunState == RunDown {
-			runState = "涓�"
-		}
-
-		if !config.NVCSConf.RunState {
-			runState = ""
-		}
-
-		if config.NVCSConf.OSD != "" {
-			floorText := fmt.Sprintf("%dF%s %s", req.Floor, runState, config.NVCSConf.OSD)
-
-			// 璋冪敤hik api 灏嗘枃瀛楁坊鍔犲埌osd鐨勫乏涓嬭
-			AddFloorToOSD(floorText)
-		}
-
-		var d = models.Positions{
-			DeviceId:   req.Id,
-			Pos:        fmt.Sprintf("%dF", req.Floor),
-			RunDir:     iRunState,
-			CreateTime: time.Now().Unix(),
-			TimeString: time.Now().Format("2006-01-02 15:04:05"),
-		}
-
-		err = d.Save()
-		if err != nil {
-			logger.Warn("Device position update error:%s", err.Error())
-		}
-
-		c.JSON(http.StatusOK, "ok")
-	})
-
-	err := r.Run(fmt.Sprintf(":%s", config.NVCSConf.Port))
-	if err != nil {
-		logger.Warn("Start NVCS WebServer error, %s", err.Error())
-	}
-}
-
-func StartNVCSServer() {
-	if config.NVCSConf.Model == "A1" {
-		go NVCSA1UDPServer()
-	}
-
-	if config.NVCSConf.Model == "A2" {
-		go NVCSA2WebServer()
-	}
-
-	if config.NVCSConf.Model == "A3" {
-		go NVCSA3WebServer()
-	}
-}
diff --git a/service/rfid.go b/service/rfid.go
deleted file mode 100644
index 4c546fc..0000000
--- a/service/rfid.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package service
-
-type RFIDReader struct {
-	TagDetected bool // 鏄惁妫�娴嬪埌RFID鏍囩
-}

--
Gitblit v1.8.0