zoukankan      html  css  js  c++  java
  • 国标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]<<<<<<
    %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的视频通道

  • 相关阅读:
    activiti app 6.0 乱码
    扫盲--CRM系统和ERP系统的区别
    GraphQL实战-第四篇-构建开发框架
    GraphQL实战-第三篇-spring Boot 实现
    GraphQL实战-第二篇-java实现及分析
    GraphQL实战-第一篇-GraphQL介绍
    @PostConstruct及跳坑记录
    jmeter元件的介绍
    Docker之5. 容器的操作
    Docker之4. 镜像的操作
  • 原文地址:https://www.cnblogs.com/EasyNVR/p/13552465.html
Copyright © 2011-2022 走看看