• GB28181学习(十三)——订阅与通知


    事件订阅

    要求

    • 事件订阅应使用SUBSCRIBE方法;
    • 事件源接收事件订阅时,事件源应向事件观察者发送确认消息;
    • 事件源:
      • 联网系统
      • SIP服务器
      • 报警设备
      • 移动设备
      • 被集成的卡口系统等
    • 事件观察者
      • 联网系统
      • SIP服务器
      • 客户端
    • 事件:
      • 报警事件
      • 移动设备位置通知事件
      • PTZ精准位置变化事件等

    流程

    在这里插入图片描述

    协议接口

    • MESSAGE消息头Content-type头域为Content-type:Application/MANSCDP+xml
    • 报警事件订阅流程中请求命令消息体采用MANSCDP协议格式定义:请求命令消息体采用XML封装;
    • 移动位置上报事件订阅流程中请求命令消息体采用MANSCDP协议格式定义:请求命令消息体采用XML封装;
    • PTZ精准位置变化事件订阅流程中请求命令消息体采用MANSCDP协议格式定义:请求命令消息体采用XML封装;

    事件通知

    要求

    • 事件源接受事件订阅后,在事件触发后应立即通知事件观察者,事件观察者应向事件源发送事件收到的确认消息;
    • 事件通知使用NOTIFY方法;
    • 事件源:
      • 联网系统
      • SIP服务器
      • 报警设备
      • 移动设备
      • 被集成的卡口系统等
    • 事件观察者
      • 联网系统
      • SIP服务器
      • 客户端
    • 事件
      • 报警事件
      • 移动设备位置通知事件
      • PTZ精准位置变化事件等

    流程

    在这里插入图片描述

    协议接口

    • MESSAGE消息头Content-type头域为Content-type:Application/MANSCDP+xml
    • 报警事件订阅流程中请求命令消息体采用MANSCDP协议格式定义:请求命令消息体采用XML封装;
    • 移动位置上报事件订阅流程中请求命令消息体采用MANSCDP协议格式定义:请求命令消息体采用XML封装;
    • PTZ精准位置变化事件订阅流程中请求命令消息体采用MANSCDP协议格式定义:请求命令消息体采用XML封装;

    目录订阅

    要求

    • 目录订阅应使用SUBSCRIBE方法;
    • 目录拥有者接收目录订阅后,应向目录订阅者发送请求确认消息;
    • 目录拥有者
      • 联网系统
      • 有子设备的设备
      • 代理设备网关
    • 目录接收者
      • 联网系统
      • 有子设备的设备
      • 代理设备网关

    流程

    在这里插入图片描述

    协议接口

    • MESSAGE消息头Content-type头域为Content-type:Application/MANSCDP+xml
    • 目录订阅订阅流程中请求命令消息体采用MANSCDP协议格式定义:请求命令消息体采用XML封装;

    目录通知

    要求

    • 目录拥有者接收目录订阅后,当目录发生变化时立即通知目录接收者,目录接收者应向目录拥有者发送目录收到的确认消息;
    • 目录通知应使用NOTIFY方法;
    • 目录拥有者
      • 联网系统
      • 有子设备的设备
      • 代理设备网关
    • 目录接收者
      • 联网系统
      • 有子设备的设备
      • 代理设备网关
    • 域间目录订阅通知

    流程

    在这里插入图片描述

    协议接口

    • MESSAGE消息头Content-type头域为Content-type:Application/MANSCDP+xml
    • 目录订阅订阅流程中请求命令消息体采用MANSCDP协议格式定义:请求命令消息体采用XML封装;

    代码实现

    • 订阅初始化
    pj_init();
    pjlib_util_init();
    pj_caching_pool_init(&m_cachingPool, &pj_pool_factory_default_policy, 0);
    pjsip_endpt_create(&m_cachingPool.factory, nullptr, &m_endPoint);
    pjsip_tsx_layer_init_module(m_endPoint);
    pjsip_ua_init_module(m_endPoint, nullptr);
    
    // 订阅相关
    pjsip_evsub_init_module(m_endPoint);
    pjsip_pres_init_module(m_endPoint, pjsip_evsub_instance());
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 创建报警订阅请求
    std::string CMySipMedia::CreateAlarmXmlText_(const std::string& eventName, const GBSubscribeContext& subContext)
    {
    	char szAlarmInfo[500] = { 0 };
    	pj_ansi_snprintf(szAlarmInfo, 500,
    		"\n"
    		"\n"
    		"%s\n"
    		"130\n"
    		"%s\n"
    		"0\n"
    		"0\n"
    		"0\n"
    		"%s\n"
    		"%s\n"
    		"\n", eventName.c_str()
    		, subContext.GetDeviceId().c_str()
    		, subContext.GetSubStartTime().c_str()
    		, subContext.GetSubEndTime().c_str()
    	);
    
    	return szAlarmInfo;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 订阅
    static pjsip_evsub_user pres_user = {
        &pres_on_evsub_state,
        &pres_on_evsub_tsx_state,
        &pres_on_evsub_rx_refresh,
        &pres_on_evsub_rx_notify,
        &pres_on_evsub_client_refresh,
        &pres_on_evsub_server_timeout,
    };
    
    // 接收NOTIFY消息
    static void pres_on_evsub_rx_notify(pjsip_evsub* sub,
    	pjsip_rx_data* rdata,
    	int* p_st_code,
    	pj_str_t** p_st_text,
    	pjsip_hdr* res_hdr,
    	pjsip_msg_body** p_body)
    {
    }
    
    bool CMySipContext::Subscribe(pjsip_dialog* dlg, pjsip_evsub_user* pres_user, const std::string& eventName, const std::string& xmlText, const GBSubscribeContext& subContext)
    {
        // 创建uac
    	pjsip_evsub* sub = nullptr;
    	static const pj_str_t STR_PRESENCE = { (char*)"presence", 8 };
    	pj_status_t status = pjsip_evsub_create_uac(dlg, pres_user, &STR_PRESENCE, 0, &sub);
    	if (PJ_SUCCESS != status)
    		return false;
    
        // 初始化
    	pjsip_tx_data* tdata = nullptr;
    	status = pjsip_evsub_initiate(sub, nullptr, subContext.GetExpires(), &tdata);
    	if (PJ_SUCCESS != status)
    		return false;
    
        // 构造Body
    	pjsip_media_type type;
    	type.type = pj_str((char*)"application");
    	type.subtype = pj_str((char*)"MANSCDP+xml");
    	auto text = pj_str(const_cast(xmlText.c_str()));
    	tdata->msg->body = pjsip_msg_body_create(m_pool, &type.type, &type.subtype, &text);
    
    	auto hName = pj_str((char*)"Subject");
    	auto subjectUrl = subContext.GetDeviceId() + ":" + SiralNum + "," + GetCode() + ":" + SiralNum;
    	auto hValue = pj_str(const_cast(subjectUrl.c_str()));
    	auto hdr = pjsip_generic_string_hdr_create(m_pool, &hName, &hValue);
    	pjsip_msg_add_hdr(tdata->msg, reinterpret_cast(hdr));
    
        // 消息发送
    	status = pjsip_evsub_send_request(sub, tdata);
    	if (PJ_SUCCESS != status)
    		return false;
    
    	return true;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    抓包

    1. 报警订阅
    SUBSCRIBE sip:xxx@192.168.0.111:5060 SIP/2.0
    Via: SIP/2.0/UDP 192.168.0.107:5060;rport;branch=xxx
    Max-Forwards: 70
    From: sip:xxx@192.168.0.107;tag=xxx
    To: sip:xxx@192.168.0.111
    Contact: <sip:xxx@192.168.0.107:5060>
    Call-ID: xxx
    CSeq: 18467 SUBSCRIBE
    Event: presence;id=xxx
    Expires: 300
    Supported: 100rel
    Accept: application/pidf+xml, application/xpidf+xml
    Allow-Events: presence
    Subject: xxx:xxx,xxx:xxx
    Content-Type: application/MANSCDP+xml
    Content-Length:   327
    
    <?xml version="1.0" encoding="UTF-8"?>
    <Query>
    <CmdType>Alarm</CmdType>
    <SN>130</SN>
    <DeviceID>xxx</DeviceID>
    <StartAlarmPrority>0</StartAlarmPrority>
    <EndAlarmPrority>0</EndAlarmPrority>
    <AlarmMethod>0</AlarmMethod>
    <StartTime>2023-10-24T00:00:00</StartTime>
    <EndTime>2023-10-24T23:00:00</EndTime>
    </Query>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    1. 报警订阅结果
    SIP/2.0 200 OK
    Call-ID: xxx
    Contact: <sip:xxx@192.168.0.111:5060>
    Content-Length: 0
    CSeq: 18467 SUBSCRIBE
    Event: presence;id=xxx
    Expires: 300
    From: <sip:xxx@192.168.0.107>;tag=xxx
    To: <sip:xxx@192.168.0.111>;tag=xxx
    User-Agent: SIP UAS V.2016.xxxx
    Via: SIP/2.0/UDP 192.168.0.107:5060;rport=5060;branch=xxx
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    1. 报警通知
    NOTIFY sip:xxx@192.168.0.107:5060 SIP/2.0
    Call-ID: xxx
    Contact: <sip:xxx@192.168.0.111:5060>
    Content-Length: 416
    Content-Type: Application/MANSCDP+xml
    CSeq: 2 NOTIFY
    Event: presence;id=xxx
    From: <sip:xxx@192.168.0.111>;tag=xxx
    Max-Forwards: 70
    Subscription-State: active;expires=294
    To: <sip:xxx@192.168.0.107>;tag=xxx
    User-Agent: SIP UAS V.2016.xxxx
    Via: SIP/2.0/UDP 192.168.0.111:5060;rport;branch=xxx
    
    <?xml version="1.0" encoding="GB2312" standalone="yes" ?>
    <Notify>
    <CmdType>Alarm</CmdType>
    <SN>29</SN>
    <DeviceID>xxx</DeviceID>
    <AlarmPriority>1</AlarmPriority>
    <AlarmMethod>5</AlarmMethod>
    <AlarmTime>2023-10-24T10:17:45</AlarmTime>
    <AlarmDescription>........</AlarmDescription>
    <AlarmInfo>11</AlarmInfo>
    <Info>
    <AlarmType>2</AlarmType>
    <AlarmTypeParam>
    <EventType>1</EventType>
    </AlarmTypeParam>
    </Info>
    </Notify>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    1. 报警通知返回
    SIP/2.0 200 OK
    Via: SIP/2.0/UDP 192.168.0.111:5060;rport=5060;received=192.168.0.111;branch=xxx
    Call-ID: xxx
    From: <sip:xxx@192.168.0.111>;tag=xxx
    To: <sip:xxx@192.168.0.107>;tag=xxx
    CSeq: 2 NOTIFY
    Content-Length:  0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    1. 取消订阅
    SUBSCRIBE sip:xxx@192.168.0.111:5060 SIP/2.0
    Via: SIP/2.0/UDP 192.168.0.107:5060;rport;branch=xxx
    Max-Forwards: 70
    From: sip:xxx@192.168.0.107;tag=xxx
    To: sip:xxx@192.168.0.111
    Contact: <sip:xxx@192.168.0.107:5060>
    Call-ID: xxx
    CSeq: 26500 SUBSCRIBE
    Event: presence;id=xxx
    Expires: 0
    Supported: 100rel
    Accept: application/pidf+xml, application/xpidf+xml
    Allow-Events: presence
    Subject: xxx:xx,xxx:xx
    Content-Type: application/MANSCDP+xml
    Content-Length:   327
    
    <?xml version="1.0" encoding="UTF-8"?>
    <Query>
    <CmdType>Alarm</CmdType>
    <SN>130</SN>
    <DeviceID>xxx</DeviceID>
    <StartAlarmPrority>0</StartAlarmPrority>
    <EndAlarmPrority>0</EndAlarmPrority>
    <AlarmMethod>0</AlarmMethod>
    <StartTime>2023-10-24T00:00:00</StartTime>
    <EndTime>2023-10-24T23:00:00</EndTime>
    </Query>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    1. 取消订阅返回
    SIP/2.0 200 OK
    Call-ID: xxx
    Contact: <sip:xxx@192.168.0.111:5060>
    Content-Length: 0
    CSeq: 26500 SUBSCRIBE
    Event: presence;id=xxx
    Expires: 0
    From: <sip:xxx@192.168.0.107>;tag=xxx
    To: <sip:xxx@192.168.0.111>;tag=xxx
    User-Agent: SIP UAS V.2016.xxxx
    Via: SIP/2.0/UDP 192.168.0.107:5060;rport=5060;branch=xxx
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    界面展示在这里插入图片描述

  • 相关阅读:
    SpringCloud--Nacos解析
    MySQL InnoDB 表不存在问题修复
    c盘清除文件
    开题报告 PPT 应该怎么做
    SSM之Spring注解式缓存Redis
    C51--开发环境
    驱动比例多路阀控制器
    REASONING ON GRAPHS: FAITHFUL AND INTERPRETABLE LARGE LANGUAGE MODEL REASONING
    SpringMVC之JSON数据返回与异常处理机制---全方面讲解
    ThreadLocal
  • 原文地址:https://blog.csdn.net/www_dong/article/details/134022082