// 协议栈上行模块模块 // 秒寻科技 // zt 2024-08-31 package psul import ( "encoding/binary" "errors" "fmt" "ipsomc/core/dao/redis/redisapi" "ipsomc/module/oam" "ipsomc/module/ps/ap" "ipsomc/module/ps/mcp" "ipsomc/module/ps/mcpb" "ipsomc/module/ps/psdl" "ipsomc/module/ps/psmodel" "ipsomc/module/socket/socketmodel" "ipsomc/util" "net" ) type PsUl struct { psDlApi psdl.PsDl apApi ap.Ap mcpApi mcp.Mcp mcpbApi mcpb.McpB oamReportApi oam.OamReport } // 协议栈上行模块 // udpAddress:客户端地址 // dataList:数据队列 // dataListLen:数据队列长度 func (obj *PsUl) PsUl(udpAddress *net.UDPAddr, dataList []byte, dataListLen int) error { var dwLen int = dataListLen var wStopIndex = 0 var redisObj redisapi.RedisApi var clientAddr socketmodel.ClientAddr //AP层处理 pstHeadModel, pstTailModel, err := obj.apApi.ApUl(dataList, &dwLen) if err != nil { return err } //更新redis中的客户端连接 myViper := util.GetViper() expireTime := myViper.GetInt("token.pc_expire") if expireTime <= 0 { expireTime = 10 //10分钟 } //保存客户端IP和端口资料 redisKey := fmt.Sprintf("%08X", int(pstHeadModel.StVpHead.ProjectID)) + "-" + fmt.Sprintf("%08X", int(pstHeadModel.StVpHead.DeviceID)) ip := udpAddress.IP clientAddr.IP = append(clientAddr.IP, ip[0]) clientAddr.IP = append(clientAddr.IP, ip[1]) clientAddr.IP = append(clientAddr.IP, ip[2]) clientAddr.IP = append(clientAddr.IP, ip[3]) clientAddr.Port = udpAddress.Port clientAddr.Zone = udpAddress.Zone redisObj.SetModelData(redisKey, &clientAddr, uint16(expireTime)) //VP层处理 wStopIndex = dwLen - 3 if err := obj.VpUl(pstHeadModel, pstTailModel, dataList[14:wStopIndex], dwLen-psmodel.PS_FRAME_MIN_LEN); err != nil { return err } return nil } // 协议栈上行模块 // tcpAddress:客户端地址 // dataList:数据队列 // dataListLen:数据队列长度 func (obj *PsUl) PsUlTcp(clientAddress string, dataList []byte, dataListLen int) error { var dwLen int = dataListLen var wStopIndex = 0 var redisObj redisapi.RedisApi var clientAddr socketmodel.ClientAddr //AP层处理 pstHeadModel, pstTailModel, err := obj.apApi.ApUl(dataList, &dwLen) if err != nil { return err } //更新redis中的客户端连接 myViper := util.GetViper() expireTime := myViper.GetInt("token.pc_expire") if expireTime <= 0 { expireTime = 10 //10分钟 } //保存客户端IP和端口资料 redisKey := fmt.Sprintf("%08X", int(pstHeadModel.StVpHead.ProjectID)) + "-" + fmt.Sprintf("%08X", int(pstHeadModel.StVpHead.DeviceID)) clientAddr.Address = clientAddress redisObj.SetModelData(redisKey, &clientAddr, uint16(expireTime)) //VP层处理 wStopIndex = dwLen - 3 if err := obj.VpUl(pstHeadModel, pstTailModel, dataList[14:wStopIndex], dwLen-psmodel.PS_FRAME_MIN_LEN); err != nil { return err } return nil } // VP层上行 func (obj *PsUl) VpUl(stHeadModel *psmodel.PS_HEAD_T, stTailModel *psmodel.PS_TAIL_T, dataList []byte, dwLen int) error { vpModel := &stHeadModel.StVpHead //vp层解析 if vpModel.McpType == psmodel.MCP_A { //MCP-A switch vpModel.VpFlag { case psmodel.VP_CMMD: //MCP-A命令 if err := obj.McpUlCmdA(stHeadModel, stTailModel, dataList, dwLen); err != nil { return err } case psmodel.VP_RESP: //MCP-A应答 obj.McpUlRespA(stHeadModel, dataList, dwLen) default: return errors.New("VP层格式错误") } } else if vpModel.McpType == psmodel.MCP_B { //MCP-B if vpModel.VpFlag == psmodel.VP_RESP { obj.mcpbApi.McpUlRespB(stHeadModel, dataList, dwLen) } } else { return errors.New("MCP层格式错误") } return nil } // MCP-A设置命令 // dataList:MCP层数据队列 // wLen:数据队列长度 func (obj *PsUl) McpUlCmdA(stHeadModel *psmodel.PS_HEAD_T, stTailModel *psmodel.PS_TAIL_T, dataList []byte, wLen int) error { var wCurrentLen uint16 = 0 var wLtvLen uint16 = 0 var wCommand uint16 = 0 ltvData := make([]byte, psmodel.PS_MCP_A_DATA_LEN) var byRespFlag uint8 = 0 //遍历数据队列 for { if wCurrentLen >= uint16(wLen) { break } //组织一个ltv数据 wLtvLen = uint16(binary.LittleEndian.Uint16(dataList[wCurrentLen : wCurrentLen+2])) //长度 wCommand = uint16(binary.LittleEndian.Uint16(dataList[wCurrentLen+2 : wCurrentLen+4])) //命令 copy(ltvData, dataList[wCurrentLen+4:wCurrentLen+wLtvLen]) //数据 //根据监控命令处理 if wCommand >= 0x0201 && wCommand <= 0x02FF { // 上报 obj.oamReportApi.OamReportCmd(stHeadModel, wCommand, ltvData, wLtvLen-4) byRespFlag = 1 } //数据后移 wCurrentLen += wLtvLen } //发送上行命令的应答 if byRespFlag == 1 { if err := obj.psDlApi.PsDlResp(stHeadModel, dataList); err != nil { return err } } return nil } // MCP-A层上行应答 // stHeadModel:协议头 // dataList:MCP层数据队列 // dataListLen:数据队列长度 func (obj *PsUl) McpUlRespA(stHeadModel *psmodel.PS_HEAD_T, dataList []byte, dwLen int) error { mcpModel := stHeadModel.StMcpHead //应答标识符检查 if mcpModel.Resp != psmodel.MCP_RESP_SUCC { return errors.New("响应消息失败") } //MCP命令检查 switch mcpModel.Comd { case psmodel.MCP_A_REPORT: //上报 case psmodel.MCP_A_QUERY: //查询 obj.mcpApi.McpAUlRespQuery(stHeadModel, dataList, dwLen) //响应 case psmodel.MCP_A_CONFIGURE: //配置 obj.mcpApi.McpAUlRespSet(stHeadModel, dataList, dwLen) //响应 default: return errors.New("MCP命令类型错误") } return nil }