国标GB28181协议客户端EasyGBS国标视频平台级联EasyNVR:EasyNVR到EasyGBS上是如何注册及注销的?

时间:2022-07-23
本文章向大家介绍国标GB28181协议客户端EasyGBS国标视频平台级联EasyNVR:EasyNVR到EasyGBS上是如何注册及注销的?,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

我们知道TSINGSEE青犀视频EasyGBS国标平台可以作为上级平台或下级平台,可以与支持国标协议的平台进行级联,上文提到与宇视等平台进行级联(EasyGBS如何实现视频流的向上级联)就是一个很好的案例。其实除了与市面上支持的国标平台做级联,Easy系列产品之间也可以与EasyGBS做级联。最近,有客户需要同时使用EasyGBS和EasyNVR两个平台融合使用,此时我们就可以将EasyNVR接入到EasyGBS中,使其方便管理。

由于文章内容比较多,我们分两块来讲一下这个配置过程。本文详细描述了EasyNVR平台到国标EasyGBS上的注册和注销。

EasyNVR视频监控直播解决方案

EasyGBS国标视频云直播解决方案

EasyGBS采用gb28181协议接入摄像头,我们将EasyNVR当作边缘设备,通过gb28181协议和EasyGBS平台进行对接。

EasyGBS有级联注册到其他EasyGBS的功能,EasyNVR接入到EasyGBS中其实就是将EasyNVR注册到EasyGBS中,我们可以仿照现有的EasyGBS级联注册功能仿写。从EasyGBS中找到级联注册功能那块代码,仿写EasyNVR的代码。此处是EasyNVR与EasyGBS交互的客户端:

func NewClient(cascade Cascade) *Client {
   client := &Client{
      Stoped:        false,
      Cascade:       cascade,
      AckTimeout:    cascade.AckTimeout,
      LocalHost:     cascade.LocalHost,
      LocalPort:     cascade.LocalPort,
      LocalWanIP:    "",
      LocalSerial:   cascade.LocalSerial,
      handleMap:     make(map[string][]HandleFunc),
      dispatcher:    events.NewDispatcher(),
      KeepAliveQuit: make(chan bool, 0),
      RegisterQuit:  make(chan bool, 0),
      DevCache:      cache.New(time.Duration(cascade.KeepaliveTimeout)*time.Second, 10*time.Second),
   }
   return client
}

以上我们已经完成了客户端的配置,接下来就可以启动客户端正式与EasyGBS交互了。

func (c *Client) Run() {
   if c.LocalPort == 0 {
      log.Println("没有可用的UDP级联端口")
      return
   }
   lUdpAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf(":%d", c.LocalPort))
   if err != nil {
      return
   }
   rUdpAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", c.Cascade.Host, c.Cascade.Port))
   if err != nil {
      return
   }
   c.udpConn, err = net.DialUDP("udp", lUdpAddr, rUdpAddr)
   if err != nil {
      log.Printf("uac start error:%v", err)
      return
   }
   if e := c.udpConn.SetReadBuffer(UDP_BUF_SIZE); e != nil {
      log.Printf("sip udp set connection read buffer[%d] error, %v", UDP_BUF_SIZE, e)
   }
   if e := c.udpConn.SetWriteBuffer(UDP_BUF_SIZE); e != nil {
      log.Printf("sip udp set connection write buffer[%d] error, %v", UDP_BUF_SIZE, e)
   }
   defer c.udpConn.Close()
   c.Transport = c.NewUDPTransport(rUdpAddr, c.udpConn)
   go c.Register(false)
   log.Printf("uac start ok:%s", c.udpConn.LocalAddr().String())
   c.Stoped = false
   c.Handle("MESSAGE", HandleMessage)
   c.Handle("INVITE", HandleInvite)
   c.Handle("BYE", HandleBye)
   c.Handle("INFO", HandleInfo)
   for !c.Stoped {
      bufUDP := make([]byte, UDP_BUF_SIZE)
      n, _, err := c.udpConn.ReadFromUDP(bufUDP)
      if err != nil {
         log.Printf("udp read error, %v", err)
         continue
      }
      sipBuf := bufUDP[:n]
      sipRaw := string(sipBuf)
      sipMsg := siprocket.Parse(sipBuf)
      statusCode := string(sipMsg.Req.StatusCode)
      contentLen, _ := strconv.Atoi(string(sipMsg.ContLen.Value))
      header := sipRaw[:len(sipRaw)-contentLen]
      body := sipRaw[len(sipRaw)-contentLen:]
      Logf("级联消息:[%s]<<<<<<[%s]<<<<<<rn%v", c.udpConn.LocalAddr().String(), c.udpConn.RemoteAddr().String(), sipRaw)
      if statusCode == "" { // request
         req, err := UnmarshalRequest(header, body)
         if err != nil {
            log.Printf("unmarshal request failed, %v", err)
            continue
         }
         req.FixVia(c.Transport)
         c.HandleRequest(req, &sipMsg)
      } else { // response
         res, err := UnmarshalResponse(header, body)
         if err != nil {
            log.Printf("unmarshal response failed, %v", err)
            continue
         }
         callid := res.HeaderMap["Call-ID"]
         cseq := res.HeaderMap["CSeq"]
         c.dispatcher.Dispatch(fmt.Sprintf("%s:%s", callid, cseq), res)
      }
   }
}

上面两段代码都是实现EasyNVR注册到EasyGBS中,然后就需要将其整合到一起。

func Start() {
   cascade := GetGbsConfig()
   if cascade.Enable != 0 {
      client = NewClient(cascade)
      go client.Run()
   }
   return
}
 
func Stop() {
   if client != nil {
      if !client.Stoped {
         client.Stoped = true
         client.RegisterQuit <- true
         client.KeepAliveQuit <- true
      }
      client = nil
      log.Println("级联stop")
   }
}

实现后效果如下:

这个设备就是虚拟构造的EasyNVR设备。我们接入的是16通道的EasyNVR,所以此处应该显示16个通道,然而现在注册上来并没有显示通道,所以我们还需要继续配置EasyGBS级联调阅EasyNVR的通道列表:EasyGBS如何实现调阅EasyNVR的视频通道。