GB28181协议--校时

news/2024/6/17 15:12:36

1、简介

根据《GB/T 28181 —2016》7.10、9.10的要求,GB28181设备网络校时功能描述如下:
联网系统内的IP 网络服务器设备宜支持 NTP(见IETF RFC2030) 协议的网络统一校时服务。 网络校时设备分为时钟源和客户端, 支持客户/服务器的工作模式; 时钟源应支持 TCP/IP、UDP 及 NTP协议, 能将输入的或自身产生的时间信号以标准的 NTP 信息包格式输出。联网系统内的IP 网络接入设备应支持SIP 信令的统一校时, 接入设备应在注册时接受来自SIP 服务器通过消息头 Date 域携带的授时。

2、基本流程

联网内设备支持基于SIP 方式或 NTP 方式的网络校时功能, 标准时间为北京时间。流程如下所示:
在这里插入图片描述
在注册成功情况下, 注册流程的最后一个 SIP 应答消息200 OK 中的 Date 头域中携带时间信息。采用的格式为 XML 标准格式:Date: yyyy-MM-dd’T’HH: mm:ss.SSS。
若SIP 代理通过注册方式校时, 其注册过期时间宜设置为小于 SIP 代理与 SIP 服务器出现1 s 误差所经过的运行时间。 例如:SIP 代理与SIP 服务器校时后,SIP 代理运行10 h 后设备时间与SIP 服务器时间相差大于1 s, 则宜将注册过期时间设置为10 h(36 000s) , 以保证SIP 代理与SIP 服务器之间时间误差小于1 s。

3、基于SIP的校时

sip信令处理:

int SipReg(GB28181Param_t *pGB28181Param, int isReg)
{
	int ret = 0;
	int len = 0;
	char *msg;
	int expires = 0 ;
	int regState = 0;
	int unAuthorized = 0;
	eXosip_event_t *je = NULL;
	osip_header_t *dest = NULL;
	osip_message_t *reg = NULL;
	long interval = GetSysSec();


	
	if (!pGB28181Param)
	{
		return SIP_FAILED;
	}

	if (isReg)
	{
		expires = strtoul(pGB28181Param->userParam.sipExpires, 0, 0);
	}

	while(GetSysSec() -interval <= MAX_SIP_REG_TIMEOUT_SEC)
	{
		// 先进行不认证注册
		if (0 == unAuthorized)
		{
			ret = SipRegisterUnauthorized(pGB28181Param, expires);
			if (ret < 0)
			{
				if(je)
				{
					eXosip_event_free(je);
				}
				return SIP_FAILED;
			}
			else 
			{
				unAuthorized = 1;
			}
		}

		je = eXosip_event_wait(0, 100);  		/* 等待新消息的到来 */
		if(NULL == je)
		{
			/* 以下语句会导致eXosip_register_send_register失败 */
			eXosip_automatic_action();
			usleep(100*1000);
			continue;
		}

		/* 返回注册失败 */
		if(EXOSIP_REGISTRATION_FAILURE == je->type)
		{
			/* 未认证注册失败,那么使用认证的方式进行注册 */
			if((je->response!=NULL) && (401==je->response->status_code))
			{
				ret = SipRegisterAuthorized(pGB28181Param, je->rid, expires);
				eXosip_event_free(je);
				if(ret != OSIP_SUCCESS)
				{
					return SIP_FAILED;
				}
			}
			else 
			{
				eXosip_event_free(je);
				unAuthorized = 0;			/* 注册失败, 重新走一遍注册流程 */
				if (isReg)
				{
					return SIP_REREG_AFTER_60S;
				}
				return SIP_FAILED;
			}
		}
		else if (EXOSIP_REGISTRATION_SUCCESS == je->type)
		{
			regState = 1;
			/* 收到服务器返回的注册成功 */
			g_SipState.registerID = je->rid;	
			if (MSG_IS_REGISTER(je->request) && je->response)
			{
				if (OSIP_SUCCESS == osip_message_to_str(je->response, &msg, &len))
				{
					if (osip_message_get_date(je->response, 0, &dest) > 0)
					{
						SipSetSystemTime(dest->hvalue);
					}
				}
			}
			
			eXosip_execute();
			eXosip_automatic_action();
			eXosip_event_free(je);
			break;
		}
		else
		{
			eXosip_event_free(je);
		}
	}

	if( (GetSysSec() -interval > MAX_SIP_REG_TIMEOUT_SEC) && (regState == 0))
	{
		return SIP_FAILED;
	}

	pthread_mutex_lock(&g_SipState.mutex);
	// 更新sip的注册状态
	if (isReg)
	{
		g_SipState.sipRegStatus = 1;
		g_SipState.keepliveAckTime = GetSysSec();
	}
	else 
	{
		g_SipState.sipRegStatus = 0;
	}
	pthread_mutex_unlock(&g_SipState.mutex);
	
	return SIP_SUCCESS;
}

设置系统时间接口:

static int SipSetSystemTime(char *timeStr)
{
	char *beginStr = timeStr;
	char *endStr = NULL;
	char tempStr[10] = {0, };
	struct tm st_time = {0, };
	struct timeval tv = {0, };
	uint32_t stime = 0;

	
	if (!timeStr)
	{
		return SIP_FAILED;
	}

	if ((endStr = strstr(beginStr, "-")))
	{
		memset(tempStr, 0, sizeof(tempStr));
		strncpy(tempStr, beginStr, endStr-beginStr);
		beginStr = endStr + 1;
		stime = strtoul(tempStr, NULL, sizeof(tempStr));
		st_time.tm_year = stime - 1900;
	}

	if ((endStr = strstr(beginStr, "-")))
	{
		memset(tempStr, 0, sizeof(tempStr));
		strncpy(tempStr, beginStr, endStr-beginStr);
		beginStr = endStr + 1;
		stime = strtoul(tempStr, NULL, sizeof(tempStr));
		st_time.tm_mon = stime - 1;
	}

	if ((endStr = strstr(beginStr, "T")))
	{
		memset(tempStr, 0, sizeof(tempStr));
		strncpy(tempStr, beginStr, endStr-beginStr);
		beginStr = endStr + 1;
		stime = strtoul(tempStr, NULL, sizeof(tempStr));
		st_time.tm_mday = stime;
	}

	if ((endStr = strstr(beginStr, ":")))
	{
		memset(tempStr, 0, sizeof(tempStr));
		strncpy(tempStr, beginStr, endStr-beginStr);
		beginStr = endStr + 1;
		stime = strtoul(tempStr, NULL, sizeof(tempStr));
		st_time.tm_hour = stime;
	}

	if ((endStr = strstr(beginStr, ":")))
	{
		memset(tempStr, 0, sizeof(tempStr));
		strncpy(tempStr, beginStr, endStr-beginStr);
		beginStr = endStr + 1;
		stime = strtoul(tempStr, NULL, sizeof(tempStr));
		st_time.tm_min = stime;
	}

	if ((endStr = strstr(beginStr, ".")))
	{
		memset(tempStr, 0, sizeof(tempStr));
		strncpy(tempStr, beginStr, endStr-beginStr);
		beginStr = endStr + 1;
		stime = strtoul(tempStr, NULL, sizeof(tempStr));
		st_time.tm_sec = stime;
	}

	// 设置系统时间
	if ((tv.tv_sec = mktime(&st_time)) < 0)
	{
		GB_PrintError("mktime failed\n");
		return SIP_FAILED;
	}

	settimeofday(&tv, NULL);

	// 设置RTC时间
	struct tm *stTime = gmtime(&tv);
	if (SetRtcTime(stTime) < 0)
	{
		return SIP_FAILED;		
	}

	return SIP_SUCCESS;
}

参考资料:
《GBT 28181-2016 公共安全视频监控联网系统信息传输、交换、控制技术要求》
推荐阅读:GB28181协议–设备注册和注销


http://www.niftyadmin.cn/n/1721691.html

相关文章

linux下solr管理界面授权登录

solr默认可以直接访问管理界面&#xff0c;这样很危险&#xff0c;因此需要给配置上登录授权。 说明&#xff1a;以下操作中是我本地机器的目录&#xff0c;实际中要对应你们自己的路径。 1、创建role.properties文件&#xff0c; 进入/picclife/soft/solr-7.4.0/server/etc…

linux下weblogic12c漏洞修复打补丁基本操作

日常运维工作中我们有时需要给weblogic打补丁&#xff0c;补丁文件是oracle官方发布的zip包。下面均为我本地的目录结构&#xff0c;实际操作中以你实际的目录为准。 1、上传补丁并解压 cd /picclife/software/psu -----指定一个存放的目录 上传补丁&#xff1a;p30386660_1…

操作系统--freeRTOS 双向链表解读(list)

1、简介 本文依据的freeRTOS版本是V9.0.0版本&#xff0c;本文将分析链表文件的结构体&#xff0c;主要根据其list.c和list.h文件; 2、list.h文件解析 /** FreeRTOS Kernel V9.0.0a* Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.** Permi…

linux下批量删除redis集群中指定前缀的key

在redis集群的维护中&#xff0c;我们可能需要批量删除某个固定前缀的key。来降低redis的内存使用空间或者是清理无用的垃圾数据。 在一次维护工作中&#xff0c;我就接收到这样的工作&#xff0c;当时就写了两个脚本来完成的&#xff0c;下面给大家介绍一下。 一、首先是找出…

Java导出可执行的jar文件

在日常运维工作中&#xff0c;我们可需要写一些java工具类配合linux脚本一起使用&#xff0c;实现某个功能&#xff0c;为了代码的完整性&#xff0c;我们有时需要将写好的java代码导出为一个可执行的jar文件&#xff0c;然后在linux下直接运行。之前做了一个监控日志错误&…

GB28181协议--报警

1、简介 根据《GBT 28181-2016 公共安全视频监控联网系统信息传输、交换、控制技术要求》9.4节的《报警事件通知和分发基本要求》描述&#xff1a; 发生报警事件时, 源设备应将报警信息发送给 SIP 服务器;SIP 服务器接收到报警事件后, 将报警信息分发给目标设备。 报警事件通…

Oracle语句小集

--时间加2秒 select sysdate,sysdate(2/(60*60*24)) from dual; --oracle随机数10-99之间 SELECT round(dbms_random.value(10,99))FROM dual; --计算年龄 select floor(months_between(SYSDATE,date1986-11-09)/12) 年龄 from dual; --复制表 不要数据 create table empin…

修改序列初始值-oracle

通过Increment By来实现修改初始值。 select 1-1000000000017 from dual; --1是想设置的初始值&#xff0c; 1000000000017当前值 alter sequence SEQ_OID increment by -1000000000016; 想设置的初始值-当前值 select SEQ_OID.nextval from dual; alter sequence SE…