123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- // 协议栈上行模块模块
- // 秒寻科技
- // 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
- }
|