结合GB/T28181规范探讨Android平台设备接入模块心跳实现

​技术背景

好多开发者在用我们Android平台GB28181设备接入模块的时候,更希望跟我们探讨一些协议规范方面,以便在现场对接时,可以知其然知其所以然。比如,有开发者提到,GB28181的状态消息报送这块到底要怎么实现?希望我们能做个基础的普及。本文结合大牛直播SDK的模块,抛砖引玉,做个基础的讲解。

先看GB/T281810-2016规范针对状态消息报文基本要求:

当源设备(包括网关、SIP设备、SIP客户端或联网系统)发现工作异常时,应立即向本 SIP监控域的SIP服务器发送状态信息;无异常时,应定时向本SIP监控域的SIP服务器发送状态信息。

SIP设备 29 GB/T28181---2016宜在状态信息中携带故障子设备描述信,状态信息报送采用IETFRFC 3428中定义的方法 Message实现。

通过周期性的状态信息报送,实现注册服务器与源设备之间的状态检测即心跳机制。 心跳发送方、接收方需统一配置"心跳间隔"参数,按照"心跳间隔"定时发送心跳消息,默认心跳间隔60s

心跳发送方、接收方需统一配置"心跳超时次数"参数,心跳消息连续超时达到"心跳超时次数" 则认为对方下线,默认心跳超时次数3次

为此,我们在Android平台GB28181设备接入模块(SmartGBD)设置的参数如下:

arduino 复制代码
private int gb28181_heartbeat_interval_    = 20; // 心跳间隔GB28181默认是60, 目前调整到20秒
private int gb28181_heartbeat_count_       = 3; // 心跳间隔3次失败,表示和服务器断开了

GB28181设备接入侧初始化initGB28181Agent()的时候,把心跳参数投递下去:

scss 复制代码
// GB28181配置
gb28181_agent_.config(gb28181_reg_expired_, gb28181_heartbeat_interval_, gb28181_heartbeat_count_);

心跳接收方在心跳发送方上线状态下检测到心跳消息连续超时达到商定次数则认为心跳发送方离 线;心跳发送方在心跳接收方上线状态下检测到心跳消息响应消息连续超时达到商定次数则认为心跳接收方离线。

状态信 息 报 送 命 令 应 包 括 命 令 类 型 (CmdType)、设 备/系 统 编 码 (DeviceID)、是 否 正 常 工 作 (Status)等,采用 Message方法的消息体携带。 Message消息的成功和错误应答均无消息体。

周期性的心跳示例

xml 复制代码
MESSAGE sip:34020000002000000001@3402000000 SIP/2.0
Via: SIP/2.0/UDP 192.168.0.120:5070;rport;branch=z9hG4bK1200121904
From: <sip:34020000002000000003@3402000000>;tag=858896904
To: <sip:34020000002000000001@3402000000>
Call-ID: 1700090587
CSeq: 20 MESSAGE
Content-Type: Application/MANSCDP+xml
Max-Forwards: 70
User-Agent: IP Camera
Content-Length:   177

<?xml version="1.0" encoding="GB2312"?>
<Notify>
<CmdType>Keepalive</CmdType>
<SN>33</SN>
<DeviceID>34020000002000000003</DeviceID>
<Status>OK</Status>
<Info>
</Info>
</Notify>

心跳异常处理

基础的心跳,大多数开发者弄的明白,心跳异常处理,需要格外注意,以下是我们针对心跳异常,做的逻辑实现,感兴趣的开发者可以参考:

scss 复制代码
/*
 * CameraPublishActivity.java
 * 心跳异常处理
 * Author: https://daniusdk.com
 * WeChat: xinsheng120
 */
@Override
public void ntsOnHeartBeatException(int exceptionCount,  String lastExceptionInfo) {
	Log.e(TAG, "ntsOnHeartBeatException heart beat timeout count reached, count:" + exceptionCount+
			", exception info:" + (lastExceptionInfo!=null?lastExceptionInfo:""));

	// 停止信令, 然后重启
	handler_.postDelayed(new Runnable() {
		@Override
		public void run() {
			Log.i(TAG, "gb28281_heart_beart_timeout");

			record_executor_.cancel_tasks();

			stopRecordDownloads(true);
			stopPlaybacks(true);

			stopAudioPlayer();
			destoryRTPReceiver();

			gb_broadcast_source_id_ = null;
			gb_broadcast_target_id_ = null;
			btnGB28181AudioBroadcast.setText("GB28181语音广播");
			btnGB28181AudioBroadcast.setEnabled(false);

			stopGB28181Stream();
			destoryRTPSender();

			if (gb28181_agent_ != null) {
				gb28181_agent_.terminateAllAudioBroadcasts(true);
				gb28181_agent_.terminateAllPlays(true);

				Log.i(TAG, "gb28281_heart_beart_timeout sip stop");
				gb28181_agent_.stop();

				String local_ip_addr = IPAddrUtils.getIpAddress(context_);
				if (local_ip_addr != null && !local_ip_addr.isEmpty() ) {
					Log.i(TAG, "gb28281_heart_beart_timeout get local ip addr: " + local_ip_addr);
					gb28181_agent_.setLocalAddress(local_ip_addr);
				}

				record_executor_.cancel_tasks();

				initPlaybacks(null);
				initRecordDownloads(null);

				Log.i(TAG, "gb28281_heart_beart_timeout sip start");
				gb28181_agent_.start();
			}
		}

	},0);
}

总结

以上是GB28181状态信息报送流程,相对其他逻辑实现,比如视频回传、语音广播、历史视音频下载回放等,这块难度不达,需要注意的是心跳异常处理这块,感兴趣的开发者,可以单独跟我沟通。

相关推荐
关键帧Keyframe10 小时前
音视频面试题集锦第 19 期 | 读取纹理数据
ios·图像识别·音视频开发
音视频牛哥14 小时前
RTSP|RTMP直播播放器实时截图使用场景和技术实现
音视频开发·视频编码·直播
音视频牛哥15 小时前
基于Linux平台的多实例RTSP|RTMP直播播放器深度解析与技术实现
音视频开发·视频编码·直播
哔哩哔哩技术14 天前
B站自研的第二代视频连麦系统(上)
webrtc·直播
小智0031 个月前
Android Camera系列(八):MediaCodec视频编码下-OpenGL ES离屏渲染
android·音视频开发·opengl
数据蛙官方软件1 个月前
Win7怎么录屏?4个看完就会的方法
音视频开发
数据蛙官方软件1 个月前
怎么调电脑字体大小?提升工作效率的3招
音视频开发
爱码少年1 个月前
TVbox 手机、智能电视节目一网打尽
apk·直播·点播
AJi2 个月前
Android音视频学习(五):MediaCodec
音视频开发