From dbc038d5318d53ac7c14e26386588c48c621a591 Mon Sep 17 00:00:00 2001
From: zhangzengfei <zhangzengfei@smartai.com>
Date: 星期五, 13 九月 2024 11:51:45 +0800
Subject: [PATCH] fix config

---
 service/nvcs.go |  353 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 333 insertions(+), 20 deletions(-)

diff --git a/service/nvcs.go b/service/nvcs.go
index 7a4605b..fbff0ac 100644
--- a/service/nvcs.go
+++ b/service/nvcs.go
@@ -2,20 +2,52 @@
 
 import (
 	"bytes"
+	"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 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"`
@@ -23,19 +55,116 @@
 	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 ElevatorData struct {
-	Elevator []Elevator `json:"Elevator"`
+type A1ElevatorData struct {
+	Elevator []A1Elevator `json:"Elevator"`
+}
+
+const (
+	RunStop = iota
+	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.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 NVCSServer() {
+func NVCSA1UDPServer() {
 	// 鎸囧畾鐩戝惉鐨勭鍙�
 	port := config.ServeConf.Port
 
@@ -54,8 +183,9 @@
 	}
 	defer conn.Close()
 
-	logger.Debug("UDP server listening on port %s...", port)
+	logger.Info("UDP server listening on port %s...", port)
 
+	var lastFloor int
 	// 鏃犻檺寰幆绛夊緟鎺ユ敹鏁版嵁
 	for {
 		// 鍒涘缓涓�涓紦鍐插尯鏉ュ瓨鍌ㄦ帴鏀剁殑鏁版嵁
@@ -73,32 +203,215 @@
 		reader := transform.NewReader(bytes.NewReader(buffer[:numBytes]), decoder)
 		decodedBytes, err := ioutil.ReadAll(reader)
 
-		var data ElevatorData
-		// Unmarshal JSON into the struct
+		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 d = models.Device{
-			Id:  elevator.Name,
-			Pos: elevator.Status.FloorName,
-			Ip:  elevator.IP,
+
+		var runStateStr string
+		if config.NVCSConf.RunState {
+			if elevator.Status.RunDir == RunUp {
+				runStateStr = "涓�"
+			} else if elevator.Status.RunDir == RunDown {
+				runStateStr = "涓�"
+			}
 		}
 
-		err = d.Upsert()
+		if !config.NVCSConf.RunState {
+			runStateStr = ""
+		}
+
+		// 璁剧疆osd  鏍煎紡 "1F涓� 鍥� 鏋�"
+		if config.NVCSConf.OSD != "" {
+			floorText := fmt.Sprintf("%s%s %s", data.Elevator[0].Status.FloorName, runStateStr, config.NVCSConf.OSD)
+
+			// 璋冪敤hik api 灏嗘枃瀛楁坊鍔犲埌osd鐨勫乏涓嬭
+			AddFloorToOSD(floorText)
+		}
+
+		// correct floor when elevator stopped.
+		if elevator.Status.RunDir == 0 {
+			go A1CorrectFloor()
+		} else {
+			RunningCorrectTaskId = ""
+			if lastFloor == elevator.Status.Floor {
+				continue
+			}
+		}
+
+		// 绋嬪簭閮ㄧ讲鍦ㄨ澶囩, 瀛楃鍙犲姞鍣ㄤ笂鎶ョ殑鍚嶇О鍏佽涓虹┖. 鍦ㄤ簯绔�, 鍚嶇О蹇呴』涓庢憚鍍忔満鐩稿悓
+		if elevator.Name == "" {
+			elevator.Name = "1"
+		}
+
+		lastFloor = elevator.Status.Floor
+
+		go func() {
+			var d = models.Positions{
+				DeviceId:   elevator.Name,
+				Pos:        elevator.Status.FloorName,
+				RunDir:     elevator.Status.RunDir,
+				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 {
-			logger.Warn("Device db update error:%s", err.Error())
+			c.JSON(http.StatusBadRequest, nil)
+			return
 		}
 
-		deviceAliveCache.Add(elevator.Name, true)
+		logger.Debug("Received A2 report data %+v", req)
 
-		logger.Debug("Received %d bytes from %s, %+v", numBytes, clientAddr, data)
+		// 璁板綍鐢垫杩愯鐘舵��
+		if strings.Contains(req.State.Status, "涓�") {
+			runState = "涓�"
+			iRunState = RunUp
+		} else if strings.Contains(req.State.Status, "涓�") {
+			runState = "涓�"
+			iRunState = RunDown
+		}
+
+		//// 宸插埌鏈�涓嬪眰
+		//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())
+	}
+}
+
+func StartNVCSServer() {
+	if config.NVCSConf.Model == "A1" {
+		go NVCSA1UDPServer()
+	}
+	if config.NVCSConf.Model == "A2" {
+		go NVCSA2WebServer()
 	}
 }

--
Gitblit v1.8.0