Android平台GB28181设备接入侧注册|注销流程和注册失败可能原因探究

123 篇文章 20 订阅
120 篇文章 1 订阅

GB28181注册、注销流程

注册流程

  • 发起注册请求
    • SIP 客户端(如 Android 设备)向 SIP 服务器发起 REGISTER 请求。请求中包含设备的相关信息,如设备 ID、用户名、密码、设备类型等,这些信息用于 SIP 服务器对设备进行认证和识别。例如,设备的 REGISTER 请求消息头可能如下:
        REGISTER sip:server_ip:port SIP/2.0
        From: <sip:device_id@domain>;tag=xxxx
        To: <sip:device_id@domain>
        Call-ID: xxxxxxxx
        CSeq: 1 REGISTER
        Max-Forwards: 70
        User-Agent: device_agent_info
        Expires: xxx  // 注册有效期

其中,From 字段中的 device_id 是设备的唯一标识,domain 是设备所属的域;Expires 字段表示注册的有效期。

服务器认证

  • SIP 服务器收到注册请求后,对设备进行认证。认证方式支持数字摘要认证方式,高安全级别的还支持数字证书的认证方式。如果服务器需要对设备进行认证,可能会返回 401 Unauthorized 响应,要求设备在后续的注册请求中包含认证信息。
  • 设备收到 401 Unauthorized 响应后,根据服务器要求的认证方式,重新生成包含认证信息的 REGISTER 请求并发送给服务器。例如,在 Authorization 字段中添加认证信息:
        REGISTER sip:server_ip:port SIP/2.0
        From: <sip:device_id@domain>;tag=xxxx
        To: <sip:device_id@domain>
        Call-ID: xxxxxxxx
        CSeq: 2 REGISTER
        Max-Forwards: 70
        User-Agent: device_agent_info
        Expires: xxx
        Authorization: Digest username="device_username", realm="server_realm", nonce="nonce_value", uri="sip:server_ip:port", response="response_value"
  • 注册成功或失败响应
    • 如果设备认证通过且注册信息正确,SIP 服务器会返回 200 OK 响应,表示注册成功。设备注册成功后,SIP 服务器认为该设备为在线状态,设备也认为 SIP 服务器为在线状态。同时,服务器会在响应中告知设备下次刷新注册的时间。例如:
        SIP/2.0 200 OK
        From: <sip:device_id@domain>;tag=xxxx
        To: <sip:device_id@domain>
        Call-ID: xxxxxxxx
        CSeq: 2 REGISTER
        Contact: <sip:device_id@device_ip:port>;expires=next_expires_time

其中,Contact 字段中的 expires 表示下次刷新注册的时间。

  • 如果注册失败,SIP 服务器可能返回 403 Forbidden500 Internal Server Error 等错误响应。设备应间隔一定时间(一般情况下不应短于 60s)后继续发起注册过程。

注销流程

  • 设备想要注销时,向 SIP 服务器发送 REGISTER 请求,将 Expires 字段的值设置为 0,表示立即注销。例如:
    REGISTER sip:server_ip:port SIP/2.0
    From: <sip:device_id@domain>;tag=xxxx
    To: <sip:device_id@domain>
    Call-ID: xxxxxxxx
    CSeq: 3 REGISTER
    Max-Forwards: 70
    User-Agent: device_agent_info
    Expires: 0
  • SIP 服务器收到注销请求后,返回 200 OK 响应,表示注销成功。设备注销后,SIP 服务器认为该设备为离线状态。

协议接口

  • SIP 接口:SIP(Session Initiation Protocol)是 GB28181 中用于会话控制的协议。在注册和注销过程中,设备和服务器之间通过 SIP 消息进行通信,如 REGISTER401 Unauthorized200 OK 等消息。这些消息的格式和字段含义遵循 SIP 协议的规范1。
  • 认证接口:用于设备和服务器之间的认证。常见的认证方式有数字摘要认证,涉及到对用户名、密码、随机数等信息进行计算生成认证信息。在 Java 中,可以使用相关的加密库来实现数字摘要算法,如 MessageDigest 类进行 MD5 等算法的计算。
  • 网络传输接口:GB28181 规定网络层应支持 IP 协议,传输层应支持 TCP 和 UDP 协议。在 Android 平台上,可以使用 Java 的 Socket 类或相关的网络库来实现 TCP 或 UDP 连接,与 SIP 服务器进行通信。
  1. 技术实现(以 Android 平台为例)
    • 协议栈实现:在 Android 设备上需要实现 GB28181 协议栈,包括 SIP 协议的解析和封装、RTP/RTCP 协议的处理等。可以使用开源的 SIP 协议库或者自行实现 SIP 协议的相关功能1。
    • 网络通信:使用 Android 的网络编程技术,建立与 SIP 服务器的网络连接。根据实际需求选择 TCP 或 UDP 传输层协议,并处理网络通信中的异常情况,如网络断开、连接超时等。
    • 数据存储和管理:设备需要存储注册信息,如用户名、密码、设备 ID、注册有效期等,以便在下次启动时自动进行注册。可以使用 Android 的 SharedPreferences、数据库等方式进行数据的存储和管理。
    • 心跳机制:为了保持设备与服务器之间的连接状态,设备需要定期向服务器发送心跳消息。在 Android 中,可以使用定时器或者后台服务来实现心跳机制。

相关技术实现

本文以大牛直播SDK的Android平台GB28181设备接入模块为例,功能设计如下:

  •  [视频格式]H.264/H.265(Android H.265硬编码);
  •  [音频格式]G.711 A律、AAC;
  •  [音量调节]Android平台采集端支持实时音量调节;
  •  [H.264硬编码]支持H.264特定机型硬编码;
  •  [H.265硬编码]支持H.265特定机型硬编码;
  •  [软硬编码参数配置]支持gop间隔、帧率、bit-rate设置;
  •  [软编码参数配置]支持软编码profile、软编码速度、可变码率设置;
  •  支持横屏、竖屏推流;
  •  Android平台支持后台service推送屏幕(推送屏幕需要5.0+版本);
  • 支持纯视频、音视频PS打包传输;
  • 支持RTP OVER UDP和RTP OVER TCP被动模式(TCP媒体流传输客户端);
  • 支持信令通道网络传输协议TCP/UDP设置;
  • 支持注册、注销,支持注册刷新及注册有效期设置;
  • 支持设备目录查询应答;
  • 支持心跳机制,支持心跳间隔、心跳检测次数设置;
  • 支持移动设备位置(MobilePosition)订阅和通知;
  •  适用国家标准:GB/T 28181—2016;
  • 支持语音广播;
  • 支持语音对讲;
  • 支持图像抓拍;
  • 支持历史视音频文件检索;
  • 支持历史视音频文件下载;
  • 支持历史视音频文件回放;
  • 支持云台控制和预置位查询;
  •  [实时水印]支持动态文字水印、png水印;
  •  [镜像]Android平台支持前置摄像头实时镜像功能;
  •  [实时静音]支持实时静音/取消静音;
  •  [实时快照]支持实时快照;
  •  [降噪]支持环境音、手机干扰等引起的噪音降噪处理、自动增益、VAD检测;
  •  [外部编码前视频数据对接]支持YUV数据对接;
  •  [外部编码前音频数据对接]支持PCM对接;
  •  [外部编码后视频数据对接]支持外部H.264数据对接;
  •  [外部编码后音频数据对接]外部AAC数据对接;
  •  [扩展录像功能]支持和录像SDK组合使用,录像相关功能。

代码实现如下:


    /*
     * CameraPublishActivity.java
     * initGB28181Agent 初始化参数
     * Author: daniusdk.com
     * WeChat: xinsheng120
     */

    private boolean initGB28181Agent() {
        if ( gb28181_agent_ != null )
            return  true;

        getLocation(context_);

        String local_ip_addr = IPAddrUtils.getIpAddress(context_);
        Log.i(TAG, "initGB28181Agent local ip addr: " + local_ip_addr);

        if ( local_ip_addr == null || local_ip_addr.isEmpty() ) {
            Log.e(TAG, "initGB28181Agent local ip is empty");
            return  false;
        }

        gb28181_agent_ = GBSIPAgentFactory.getInstance().create();
        if ( gb28181_agent_ == null ) {
            Log.e(TAG, "initGB28181Agent create agent failed");
            return false;
        }

        gb28181_agent_.addListener(this);

        // 必填信息
        gb28181_agent_.setLocalAddress(local_ip_addr);
        gb28181_agent_.setServerParameter(gb28181_sip_server_addr_, gb28181_sip_server_port_, gb28181_sip_server_id_, gb28181_sip_domain_);
        gb28181_agent_.setUserInfo(gb28181_sip_username_, gb28181_sip_password_);

        // 可选参数
        gb28181_agent_.setUserAgent(gb28181_sip_user_agent_filed_);
        gb28181_agent_.setTransportProtocol(gb28181_sip_trans_protocol_==0?"UDP":"TCP");

        // GB28181配置
        gb28181_agent_.config(gb28181_reg_expired_, gb28181_heartbeat_interval_, gb28181_heartbeat_count_);

        //com.gb.ntsignalling.Device gb_device = new com.gb.ntsignalling.Device("34020000001380000001", "安卓测试设备", Build.MANUFACTURER, Build.MODEL,
        //            "宇宙","火星1","火星", true);

        com.gb.ntsignalling.Device gb_device = new com.gb.ntsignalling.Device("33010752991327811433", "安卓测试设备", Build.MANUFACTURER, Build.MODEL,
                "宇宙","火星1","火星", true);


        if (mLongitude != null && mLatitude != null) {
            com.gb.ntsignalling.DevicePosition device_pos = new com.gb.ntsignalling.DevicePosition();

            device_pos.setTime(mLocationTime);
            device_pos.setLongitude(mLongitude);
            device_pos.setLatitude(mLatitude);
            gb_device.setPosition(device_pos);

            gb_device.setSupportMobilePosition(true); // 设置支持移动位置上报
        }

        gb28181_agent_.addDevice(gb_device);

/*
        com.gb28181.ntsignalling.Device gb_device1 = new com.gb28181.ntsignalling.Device("34020000001380000002", "安卓测试设备2", Build.MANUFACTURER, Build.MODEL,
                "宇宙","火星1","火星", true);

        if (mLongitude != null && mLatitude != null) {
            com.gb28181.ntsignalling.DevicePosition device_pos = new com.gb28181.ntsignalling.DevicePosition();

            device_pos.setTime(mLocationTime);
            device_pos.setLongitude(mLongitude);
            device_pos.setLatitude(mLatitude);
            gb_device1.setPosition(device_pos);

            gb_device1.setSupportMobilePosition(true);
        }

        gb28181_agent_.addDevice(gb_device1);


 */

        if (!gb28181_agent_.createSipStack()) {
            gb28181_agent_ = null;
            Log.e(TAG, "initGB28181Agent gb28181_agent_.createSipStack failed.");
            return  false;
        }

        boolean is_bind_local_port_ok = false;

        // 最多尝试5000个端口
        int try_end_port = gb28181_sip_local_port_base_ + 5000;
        try_end_port = try_end_port > 65536 ?65536: try_end_port;

        for (int i = gb28181_sip_local_port_base_; i < try_end_port; ++i) {
            if (gb28181_agent_.bindLocalPort(i)) {
                is_bind_local_port_ok = true;
                break;
            }
        }

        if (!is_bind_local_port_ok) {
            gb28181_agent_.releaseSipStack();
            gb28181_agent_ = null;
            Log.e(TAG, "initGB28181Agent gb28181_agent_.bindLocalPort failed.");
            return  false;
        }

        if (!gb28181_agent_.initialize()) {
            gb28181_agent_.unBindLocalPort();
            gb28181_agent_.releaseSipStack();
            gb28181_agent_ = null;
            Log.e(TAG, "initGB28181Agent gb28181_agent_.initialize failed.");
            return  false;
        }

        return true;
    }

initGB28181Agent() 完成基础化参数配置后,就开始发Register;

和注册相关的状态反馈如下:

    @Override
    public void ntsRegisterOK(String dateString) {
        Log.i(TAG, "ntsRegisterOK Date: " + (dateString!= null? dateString : ""));
    }

    @Override
    public void ntsRegisterTimeout() {
        Log.e(TAG, "ntsRegisterTimeout");
    }

    @Override
    public void ntsRegisterTransportError(String errorInfo) {
        Log.e(TAG, "ntsRegisterTransportError error:" + (errorInfo != null?errorInfo :""));
    }

注销的话,Expires字段的值为0即可。

GB28181设备注册失败可能原因

一、设备信息配置问题

  1. 设备 ID 错误

    • 设备 ID 可能不符合 GB28181 协议的规范要求。设备 ID 通常由一定的规则组成,如包含特定的前缀、编码方式等。如果设备 ID 格式不正确,服务器可能无法识别该设备,导致注册失败。
    • 检查设备 ID 的生成方式和格式是否符合协议要求,并确保在注册请求中正确地填写了设备 ID。
  2. 用户名或密码错误

    • 注册时使用的用户名和密码可能不正确。这可能是由于输入错误、配置错误或服务器端的用户信息不一致导致的。
    • 确认用户名和密码的正确性,并确保与服务器端的配置一致。可以尝试重新输入用户名和密码,或者在服务器端检查用户信息是否正确。
  3. 设备类型设置错误

    • GB28181 协议对不同类型的设备有特定的标识和分类。如果设备类型设置错误,服务器可能无法正确处理注册请求。
    • 检查设备类型的设置是否与实际设备相符,并按照协议要求进行正确的设置。

二、网络连接问题

  1. 网络不通

    • 设备无法连接到 GB28181 服务器可能是由于网络故障导致的。检查设备的网络连接状态,确保设备能够正常访问网络。
    • 可以尝试使用其他网络连接方式,如切换 Wi-Fi 或移动数据网络,以确定是否是网络问题导致注册失败。
  2. 端口被占用或阻止

    • GB28181 协议通常使用特定的端口进行通信。如果这些端口被其他应用程序占用或被防火墙阻止,设备可能无法与服务器建立连接。
    • 检查设备上是否有其他应用程序占用了 GB28181 所需的端口,并确保防火墙没有阻止这些端口的通信。可以尝试关闭可能占用端口的应用程序,或者在防火墙设置中允许 GB28181 通信的端口。
  3. IP 地址错误或动态 IP 变化

    • 如果设备的 IP 地址设置错误或使用了动态 IP 地址,而在注册时没有正确更新 IP 地址信息,服务器可能无法找到设备,导致注册失败。
    • 确认设备的 IP 地址设置正确,并确保在动态 IP 环境下能够及时更新 IP 地址信息。可以考虑使用动态域名解析(DDNS)服务来解决动态 IP 问题。

三、服务器配置问题

  1. 服务器地址错误

    • 注册请求中填写的服务器地址可能不正确。确保服务器地址的准确性,包括 IP 地址、端口号和域名等信息。
    • 可以尝试使用其他设备或工具来验证服务器地址是否可访问,以确定是否是服务器地址错误导致注册失败。
  2. 服务器故障或不可用

    • 服务器可能出现故障、维护或其他问题,导致无法接收设备的注册请求。
    • 联系服务器管理员或技术支持人员,确认服务器的状态和可用性。可以尝试在其他时间或使用其他服务器进行注册,以确定是否是服务器问题导致注册失败。
  3. 服务器端配置错误

    • 服务器端的 GB28181 配置可能存在错误,导致无法正确处理设备的注册请求。这可能包括设备认证设置、信令处理规则等方面的问题。
    • 检查服务器端的 GB28181 配置,确保与设备的注册请求相匹配。可以参考服务器的配置文档或咨询服务器管理员,以解决配置错误问题。

四、协议兼容性问题

  1. 协议版本不匹配

    • 设备和服务器使用的 GB28181 协议版本可能不匹配。不同版本的协议可能在消息格式、功能支持等方面存在差异,导致注册失败。
    • 确认设备和服务器使用的协议版本,并确保它们相互兼容。可以尝试升级设备或服务器的协议版本,以解决版本不匹配问题。
  2. 协议实现差异

    • 即使使用相同版本的协议,不同的设备和服务器实现可能存在差异。这些差异可能导致注册过程中的信令交互出现问题。
    • 参考 GB28181 协议规范,检查设备和服务器的信令交互过程,查找可能的差异点。可以与设备和服务器的供应商或技术支持人员沟通,以解决协议实现差异问题。

五、其他问题

  1. 设备硬件或软件故障

    • 设备本身可能存在硬件或软件故障,影响注册过程。例如,摄像头故障、编码模块错误等可能导致媒体流无法正常发送,从而导致注册失败。
    • 检查设备的硬件和软件状态,确保设备正常运行。可以尝试重启设备、更新驱动程序或软件版本,以解决可能的故障问题。
  2. 时间同步问题

    • GB28181 协议要求设备和服务器的时间保持同步。如果时间不同步,可能会导致注册失败或信令交互出现问题。
    • 确保设备的时间与服务器的时间保持同步。可以使用网络时间协议(NTP)或其他时间同步方法来实现时间同步。

总结

在Android 平台上支持GB28181时,设备注册失败可能是由于设备信息配置问题、网络连接问题、服务器配置问题、协议兼容性问题或其他问题导致的。通过仔细检查和排除这些可能的原因,可以提高设备注册的成功率。感兴趣的开发者可以单独跟我沟通探讨。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值