Ver Fonte

登录校准时间

chengqian há 6 meses atrás
pai
commit
0e3b2d04af

+ 2 - 0
server/api/v1/devices/dev_screens.go

@@ -81,6 +81,7 @@ func (s *ScreensApi) AddScreens(c *gin.Context) {
 	screens := devices.Screens{
 		ScreensName:   sc.ScreensName,
 		ScreensCode:   sc.ScreensCode,
+		Sn:            sc.Sn,
 		ScreensBrand:  sc.ScreensBrand,
 		ScreensModel:  sc.ScreensModel,
 		IPAddress:     sc.IpAddress,
@@ -117,6 +118,7 @@ func (s *ScreensApi) UpdateScreens(c *gin.Context) {
 		ID:            sc.ID,
 		ScreensName:   sc.ScreensName,
 		ScreensCode:   sc.ScreensCode,
+		Sn:            sc.Sn,
 		ScreensBrand:  sc.ScreensBrand,
 		ScreensModel:  sc.ScreensModel,
 		IPAddress:     sc.IpAddress,

+ 3 - 1
server/dao/devices/dev_screens.go

@@ -11,6 +11,7 @@ type Screens struct {
 	ID            int            `gorm:"primarykey" json:"ID"`                    //主键ID
 	ScreensName   string         `gorm:"type:varchar(64)" json:"screensName"`     //设备名称
 	ScreensCode   string         `gorm:"type:varchar(64)" json:"screensCode"`     //设备编码
+	Sn            string         `gorm:"type:varchar(64)" json:"sn"`              //设备sn
 	GatewayId     int            `gorm:"type:int" json:"gatewayId"`               //所属网关
 	ScreensBrand  string         `gorm:"type:varchar(60)" json:"screensBrand"`    //屏幕品牌
 	ScreensModel  string         `gorm:"type:varchar(60)" json:"screensModel"`    //屏幕型号
@@ -50,11 +51,12 @@ func (s Screens) AddScreens() error {
 
 func (s Screens) UpdateScreens() error {
 	err := global.GVA_DB.Model(&s).
-		Select("screens_name", "screens_code", "gateway_id", "screens_brand", "screens_model", "ip_address", "install_time", "shunt", "shunt_describe", "resolution_id", "screens_size_id").
+		Select("screens_name", "screens_code", "sn", "gateway_id", "screens_brand", "screens_model", "ip_address", "install_time", "shunt", "shunt_describe", "resolution_id", "screens_size_id").
 		Where("id=?", s.ID).
 		Updates(map[string]interface{}{
 			"screens_name":    s.ScreensName,
 			"screens_code":    s.ScreensCode,
+			"sn":              s.Sn,
 			"gateway_id":      s.GatewayId,
 			"screens_brand":   s.ScreensBrand,
 			"screens_model":   s.ScreensModel,

+ 1 - 0
server/go.mod

@@ -126,6 +126,7 @@ require (
 	github.com/tklauser/numcpus v0.6.0 // indirect
 	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
 	github.com/ugorji/go/codec v1.2.11 // indirect
+	github.com/valyala/bytebufferpool v1.0.0 // indirect
 	github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
 	github.com/yusufpapurcu/wmi v1.2.3 // indirect
 	go.uber.org/atomic v1.9.0 // indirect

+ 2 - 0
server/go.sum

@@ -456,6 +456,8 @@ github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4d
 github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
 github.com/unrolled/secure v1.13.0 h1:sdr3Phw2+f8Px8HE5sd1EHdj1aV3yUwed/uZXChLFsk=
 github.com/unrolled/secure v1.13.0/go.mod h1:BmF5hyM6tXczk3MpQkFf1hpKSRqCyhqcbiQtiAF7+40=
+github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
+github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
 github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
 github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
 github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=

+ 1 - 0
server/model/devices/dev_screens.go

@@ -15,6 +15,7 @@ type ReqScreens struct {
 	ID            int       `json:"id"`            //ID
 	ScreensName   string    `json:"screensName"`   //名称
 	ScreensCode   string    `json:"screensCode"`   //设备编号
+	Sn            string    `json:"sn"`            //sn
 	ScreensBrand  string    `json:"screensBrand"`  //品牌
 	ScreensModel  string    `json:"screensModel"`  //型号
 	IpAddress     string    `json:"ipAddress"`     //IP地址

+ 28 - 0
server/protocol/radar_test.go

@@ -0,0 +1,28 @@
+package protocol
+
+import (
+	"encoding/hex"
+	"fmt"
+	"testing"
+)
+
+//buf.Write([]byte{0xFE, 0x5C, 0x4B, 0x89, 0x2A, 0x00, 0x00, 0x00})
+//fmt.Println("buf", buf.Bytes())
+//
+//fmt.Println("转换", hex.EncodeToString(buf.Bytes()))
+//
+//reply, _ := hex.DecodeString(
+//"fe5c4b892a000000")
+//fmt.Println("reply", reply)
+
+func Test_verify(t *testing.T) {
+	login := AuthDataPack{}.AuthLogin()
+	//fe5c4b89 2a000000 62 00000000 17000000 31 23 32303234 30393237 3035 3137 3230 3031 23 303630 23ffff
+	//fe5c4b89 2a000000 62 00000000 17000000 31 23 32303234 30393239 3037 3137 3237 3535 23 303630 23ffff
+
+	fmt.Println("loginBuf", login.Bytes())
+	toString := hex.EncodeToString(login.Bytes())
+	fmt.Println("toString", toString)
+	reply, _ := hex.DecodeString(toString)
+	fmt.Println("reply", reply)
+}

+ 40 - 0
server/protocol/screens_model.go

@@ -0,0 +1,40 @@
+package protocol
+
+// 请求包结构体
+type ReqDataPack struct {
+	Head    []byte //包头 固定值0xFE 0x5C 0x4B 0x89
+	Len     []byte //报文总长度
+	Type    byte   //消息类型
+	Id      []byte //发送ID
+	DataLen []byte //控制指令长度
+	Data    []byte //控制指令内容
+	End     []byte //包尾固定值 0xFF 0xFF
+}
+
+// 答复包结构体
+type RspDataPack struct {
+	Head      []byte //包头
+	Len       []byte //报文总长度
+	Type      byte   //消息类型
+	Id        []byte //消息ID
+	DataLen   []byte //消息内容长度
+	Confirm   byte   //确认内容
+	Separator byte   //分隔符
+	End       []byte //包尾
+}
+
+// 认证登录结构体
+type AuthDataPack struct {
+	Head         []byte //包头
+	Len          []byte //报文总长度
+	Type         byte   //消息类型
+	Id           []byte //发送ID
+	DataLen      []byte //控制指令长度
+	Result       byte   //请求结果
+	Separator1   byte   //分隔符1
+	Time         []byte //年月日周时分秒
+	Separator2   byte   //分隔符2
+	HeartBeat    []byte //心跳包时间
+	EndSeparator byte   //结束分隔符
+	End          []byte //包尾
+}

+ 71 - 0
server/protocol/screens_service.go

@@ -0,0 +1,71 @@
+package protocol
+
+import (
+	"fmt"
+	"github.com/valyala/bytebufferpool"
+	"strconv"
+	"time"
+)
+
+// 认证登录 (这里设置了默认心跳时间为60s)
+func (x AuthDataPack) AuthLogin() *bytebufferpool.ByteBuffer {
+	buf := bytebufferpool.Get()
+	x.Head = []byte{0xFE, 0x5C, 0x4B, 0x89}
+	x.Len = []byte{0x2A, 0x00, 0x00, 0x00}
+	x.Type = 0x62
+	x.Id = []byte{0x00, 0x00, 0x00, 0x00}
+	x.DataLen = []byte{0x17, 0x00, 0x00, 0x00}
+	x.Result = 0x31
+	x.Separator1 = 0x23
+	x.Separator2 = 0x23
+	x.HeartBeat = []byte{0x30, 0x36, 0x30} //默认060, 60秒发一次心跳
+	x.EndSeparator = 0x23
+	x.End = []byte{0xFF, 0xFF}
+	buf.Write(x.Head)
+	buf.Write(x.Len)
+	buf.WriteByte(x.Type)
+	buf.Write(x.Id)
+	buf.Write(x.DataLen)
+	buf.WriteByte(x.Result)
+	buf.WriteByte(x.Separator1)
+
+	slice := GetNowDate()
+	TmpData := make([]byte, len(slice))
+	for i, s := range slice {
+		TmpData[i] = byte(s) + 0x30
+	}
+	x.Time = TmpData
+	buf.Write(x.Time)
+	buf.WriteByte(x.Separator2)
+	buf.Write(x.HeartBeat)
+	buf.WriteByte(x.EndSeparator)
+	buf.Write(x.End)
+	//fmt.Println("TmpData: ", hex.EncodeToString(buf.Bytes()))
+	//fmt.Println("TmpData: ", buf.Bytes())
+	return buf
+}
+
+func GetNowDate() (dateSlice [16]int) {
+	now := time.Now()
+	year, month, day := now.Date()
+	hour, minute, second := now.Clock()
+	weekday := int(now.Weekday()) // 0表示星期天,1表示星期一,依此类推
+	if weekday == 0 {
+		weekday = 7 // 将星期天设为07
+	}
+	// 格式化
+	Y := fmt.Sprintf("%d", year)
+	M := fmt.Sprintf("%02d", month)    // 将月份转换为两位数字
+	D := fmt.Sprintf("%02d", day)      // 将日期转换为两位数字
+	H := fmt.Sprintf("%02d", hour)     // 将小时转换为两位数字
+	Min := fmt.Sprintf("%02d", minute) // 将分钟转换为两位数字
+	S := fmt.Sprintf("%02d", second)   // 将秒数转换为两位数字
+	W := fmt.Sprintf("%02d", weekday)  // 将星期几转换为两位数字
+
+	dateStr := Y + M + D + W + H + Min + S
+	for i, _ := range dateStr {
+		num, _ := strconv.Atoi(string(dateStr[i]))
+		dateSlice[i] = num
+	}
+	return dateSlice
+}

+ 2 - 2
server/task/devices.go

@@ -14,8 +14,8 @@ func GatewayRoutingInspection() {
 		if (gateway.RecentOnline == time.Time{} || currentTime.Sub(gateway.RecentOnline).Minutes() > 15) { //如果上次在线时间与当前时间对比超过十五分钟则离线
 			//离线 && 修改网关下所有设备的状态为离线
 			status = 0
-			_ = devices.UpdateCameraStatusByGatewayId(gateway.ID, status)
-			_ = devices.UpdateScreensStatusByGatewayId(gateway.ID, status)
+			//_ = devices.UpdateCameraStatusByGatewayId(gateway.ID, status)
+			//_ = devices.UpdateScreensStatusByGatewayId(gateway.ID, status)
 			//_ = devices.UpdateRadarStatusByGatewayId(gateway.ID, status)
 		}
 		_ = devices.UpdateGatewayStatus(gateway.GatewayCode, status)

+ 20 - 10
server/tcp/deviceMgr.go

@@ -7,11 +7,14 @@ import (
 	"server/dao/devices"
 	Dev "server/dao/devices"
 	"server/model/common/request"
+	"server/protocol"
 	"server/utils/logger"
 	"strings"
 	"time"
 )
 
+var ScreenList []devices.Screens
+
 type Device struct {
 	info     devices.Screens
 	conn     net.Conn
@@ -37,21 +40,28 @@ func (s *Device) Process() {
 			break
 		}
 		data := hex.EncodeToString(buf[:n])
-		if len(data) > 51 {
-			logger.Logger.Debugf("led sn = %v", data[34:50])
-		}
 		if !strings.Contains(strings.ToLower(data), "fe5c4b89") {
 			continue
 		}
+		if len(data) > 51 {
+			logger.Logger.Debugf("led sn = %v", data[34:50])
+			ScreenList = devices.QueryAllScreens()
+			for _, v := range ScreenList {
+				if v.Sn == data[34:50] {
+					s.info = v
+					break
+				}
+			}
+		}
 		switch data[16:18] {
 		case "61":
 			logger.Logger.Debug("登录")
-			reply, _ := hex.DecodeString(
-				"fe5c4b892a0000006200000000170000003123323032333035313530313038333431352330363023ffff")
-			s.conn.Write(reply)
+			// fe5c4b89 2a000000 62 00000000 17000000 31 23 32303233(年) 3035(月) 3135(日) 3031(星期) 3038(时) 3334(分) 3135(秒) 23 303630(心跳包时间) 23 ffff
+			buffer := protocol.AuthDataPack{}.AuthLogin()
+			s.conn.Write(buffer.Bytes())
 		case "91":
 			logger.Logger.Debug("心跳")
-			if data[34:50] != s.info.ScreensCode {
+			if data[34:50] != s.info.Sn {
 				continue
 			}
 			s.UpdateInfo(data[82:84], data[86:88], data[90:92])
@@ -91,13 +101,13 @@ func (s *Device) Handle() {
 
 func (s *Device) UpdateInfo(playStatus, displayStatus, sourceStatus string) {
 	play, display, source := 0, 0, 0
-	if playStatus != "31" {
+	if playStatus == "31" {
 		play = 1
 	}
-	if displayStatus != "30" {
+	if displayStatus == "30" {
 		display = 1
 	}
-	if sourceStatus != "30" {
+	if sourceStatus == "30" {
 		source = 1
 	}
 	s.info.Status = 1

+ 64 - 13
server/tcp/tcp.go

@@ -3,13 +3,12 @@ package tcp
 import (
 	"errors"
 	"net"
-	"server/dao/devices"
 	"server/utils/logger"
 	"strings"
+	"sync"
+	"time"
 )
 
-var ScreenList []devices.Screens
-
 func ListenTcp() {
 	// 监听当前的tcp连接
 	listen, err := net.Listen("tcp", "0.0.0.0:9200")
@@ -17,30 +16,82 @@ func ListenTcp() {
 		logger.Logger.Errorf("listen failed, err:%v", err)
 		return
 	}
+
+	tracker := NewConnectionTracker() //创建连接检测器
+
 	for {
-		conn, err := listen.Accept() // 建立连接
+		conn, err := listen.Accept()
 		if err != nil {
 			logger.Logger.Errorf("Accept failed, err:%v", err)
 			continue
 		}
-		err = CheckConn(conn)
+		err = CheckConn(conn, tracker)
 		if err != nil {
+			conn.Close() // 如果是恶意连接,则关闭连接
 			continue
 		}
 	}
 }
 
-func CheckConn(conn net.Conn) error {
+func CheckConn(conn net.Conn, tracker *ConnectionTracker) error {
 	logger.Logger.Debugf("StartDevice addr:%s", conn.RemoteAddr().String())
 	arr := strings.Split(conn.RemoteAddr().String(), ":")
 	ip := arr[0]
-	ScreenList = devices.QueryAllScreens()
-	for _, v := range ScreenList {
-		if v.IPAddress == ip {
-			dev := Device{info: v}
-			dev.Start(conn)
-			return nil
+	// 记录连接
+	tracker.recordConnection(ip)
+
+	// 检查是否为恶意连接
+	if tracker.isMalicious(ip) {
+		logger.Logger.Debugf("恶意连接检测到 ip: %s\n", ip)
+		return errors.New("connection is Malicious")
+	}
+	device := Device{}
+	device.Start(conn)
+	return nil
+}
+
+type ConnectionTracker struct {
+	mu          sync.Mutex
+	connections map[string][]time.Time // 存储每个 IP 的连接时间戳
+}
+
+func NewConnectionTracker() *ConnectionTracker {
+	return &ConnectionTracker{
+		connections: make(map[string][]time.Time),
+	}
+}
+
+func (ct *ConnectionTracker) recordConnection(ip string) {
+	ct.mu.Lock()
+	defer ct.mu.Unlock()
+
+	now := time.Now()
+	ct.connections[ip] = append(ct.connections[ip], now)
+
+	// 清理过期的连接记录
+	ct.cleanUpExpired(ip, now)
+}
+
+func (ct *ConnectionTracker) cleanUpExpired(ip string, now time.Time) {
+	threshold := now.Add(-3 * time.Minute)
+	if timestamps, exists := ct.connections[ip]; exists {
+		var filtered []time.Time
+		for _, t := range timestamps {
+			if t.After(threshold) { // 检查时间戳是否在三分钟内
+				filtered = append(filtered, t) // 如果在范围内,保存到 filtered 列表
+			}
 		}
+		ct.connections[ip] = filtered
+	}
+}
+
+// 判断是否是恶意连接
+func (ct *ConnectionTracker) isMalicious(ip string) bool {
+	ct.mu.Lock()
+	defer ct.mu.Unlock()
+
+	if timestamps, exists := ct.connections[ip]; exists {
+		return len(timestamps) >= 10 // 定义恶意连接的阈值
 	}
-	return errors.New("not found")
+	return false
 }