技术专栏
rv1126 GB28181报警订阅及信息上报
1.下级域上级域说明
1.上级域:采用的是第三方的试用软件,livegbs。
2.下级域:运行于rv1126上的国标客户端测试程序。
2.流程及信令
2.1流程
1.报警订阅或者取消订阅:上级域发送 SUBSCRIBE 请求。
2.订阅或者取消订阅结果:下级域回复 200OK 。
3.报警事件通知:下级域发送 NOTIFY 请求。
4.通知的结果:上级域回复 200OK 。
2.2信令及代码实现
2.2.1报警(取消)订阅及结果
1.报警订阅或者取消订阅信令
- GBT 28181-2016规范里面的示范
Via:SIP/2.0/UDP 事件观察者域名或IP地址
Max-Forwards:70
From:显示名<sip:事件观察者编码@事件观察者域名或IP地址>;tag=BK32B1U8DKDrB
To:显示名<sip:事件源编码@事件源域名或IP地址>
Call-ID:17250
CSeq:1SUBSCRIBE
Expires:90
Event:presence
Content-type:Application/MANSCDP+XML
Content-Length:消息实体的字节长度
<? xmlversion="1.0"?>
<Query>
<CmdType>Alarm </CmdType>
<SN>17430</SN>
<DeviceID>64010000001340000001</DeviceID>
<StartAlarmPriority>1</StartAlarmPriority>
<EndAlarmPriority>4</EndAlarmPriority>
<AlarmMethod>0</AlarmMethod>
<StartTime>2010-11-11T00:00:00</StartTime>
<EndTime>2010-12-11T00:00:00</EndTime>
</Query>
- 实际抓包信令
SUBSCRIBE sip:37010200541180000001@192.168.0.104:5688 SIP/2.0
Via: SIP/2.0/UDP 192.168.0.161:15060;rport;branch=z9hG4bK227103246
From: <sip:34020000002000000001@3402000000>;tag=716882610
To: <sip:37010200541180000001@192.168.0.104:5688>;tag=894131619
Call-ID: 573882610
CSeq: 52 SUBSCRIBE
Content-Type: Application/MANSCDP+xml
Contact: <sip:34020000002000000001@192.168.0.161:15060>
Max-Forwards: 70
User-Agent: LiveGBS v221009
Expires: 3900
Event: presence
Content-Length: 275
<?xml version="1.0" encoding="GB2312"?>
<Query>
<CmdType>Alarm</CmdType>
<SN>680103246</SN>
<DeviceID>37010200541180000001</DeviceID>
<StartAlarmPriority>0</StartAlarmPriority>
<EndAlarmPriority>0</EndAlarmPriority>
<AlarmMethod>0</AlarmMethod>
</Query>
说明:
上述是报警订阅的信令示范及实际抓包的数据,从上面信息中可以看到 Expires 值不为零,这时就是报警订阅。如果要取消订阅,就是 Expires 值为 0。
2.结果信令
- GBT 28181-2016规范里面的示范
Via:SIP/2.0/UDP 事件观察者域名或IP地址
From:显示名<sip:事件观察者编码@事件观察者域名或IP地址>;tag=BK32B1U8DKDrB
To:显示名<sip:事件源编码@事件源域名或IP地址>
Call-ID:17250
CSeq:1SUBSCRIBE
Expires:90
Event:presence
Content-type:Application/MANSCDP+XML
Content-Length:消息实体的字节长度
<? xmlversion="1.0"?>
<Response>
<CmdType>Alarm </CmdType>
<SN>17430</SN>
<DeviceID>64010000001340000001</DeviceID>
<Result>OK</Result>
</Response>
- 实际抓包信令
SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.0.161:15060;rport=15060;branch=z9hG4bK227103246
From: <sip:34020000002000000001@3402000000>;tag=716882610
To: <sip:37010200541180000001@192.168.0.104:5688>;tag=894131619
Call-ID: 573882610
CSeq: 52 SUBSCRIBE
Contact: <sip:37010200541180000001@192.168.0.104:5688>
Content-Type: Application/MANSCDP+xml
Event: presence
User-Agent: eXosip/4.1.0
Expires: 3900
Content-Length: 176
<?xml version="1.0" encoding="GB2312"?>
<Response>
<CmdType>Alarm</CmdType>
<SN>680103246</SN>
<DeviceID>37010200541180000001</DeviceID>
<Result>OK</Result>
</Response>
2.2.2代码实现
下级域解析 SUBSCRIBE 及 200OK 回复的代码片段实现如下:
- 收到 SUBSCRIBE 事件,判断命令类型是否为 Alarm。
case eXosip_event_type::EXOSIP_IN_SUBSCRIPTION_NEW:
{
LOG_INFO("EXOSIP_IN_SUBSCRIPTION_NEW method:%s\n", evt->request->sip_method);
LOG_INFO("EXOSIP_IN_SUBSCRIPTION_NEW username:%s\n", evt->request->to->url->username);
if (MSG_IS_SUBSCRIBE(evt->request))
{
osip_body_t *meg_body = nullptr;
osip_message_get_body(evt->request, 0, &meg_body);
if (meg_body != nullptr)
{
LOG_INFO("subscription request: %s\n", meg_body->body);
}
auto cmd_sn = this->get_cmd(meg_body->body);
string cmd = get<0>(cmd_sn);
if ("Alarm" == cmd)
{
osip_header_t *dest = nullptr;
osip_message_get_expires(evt->request, 0, &dest);
if (dest != nullptr)
{
LOG_INFO("dest->hname:%s,dest->hvalue:%s\n", dest->hname, dest->hvalue);
}
if ((meg_body != nullptr) && (dest != nullptr))
{
process_subscription_query(evt, meg_body->body, dest->hname, dest->hvalue);
}
}
}
}
- 解析及 200OK 回复
void Device::process_subscription_query(shared_ptr<eXosip_event_t> evt, const char *body, const char *hname, const char *hvalue)
{
pugi::xml_document document;
if (!document.load_string(body))
{
LOG_ERROR("cannot parse the xml\n");
return;
}
pugi::xml_node root_node = document.first_child();
if (!root_node)
{
LOG_ERROR("cannot get root node of xml\n");
return;
}
auto DeviceID = root_node.child("DeviceID");
if (!DeviceID)
{
LOG_ERROR("cannot get the device id\n");
return;
}
string deviceID = DeviceID.child_value();
if (root_node.child("CmdType"))
{
auto cmdType = root_node.child("CmdType");
string sCmdType = cmdType.child_value();
auto SN = root_node.child("SN");
string sSN = SN.child_value();
if (!sCmdType.compare("Alarm"))
{
LOG_INFO("Alarm\n");
osip_message_t *msg = nullptr;
eXosip_insubscription_build_answer(sip_context, evt->tid, 200, &msg);
if (msg != NULL)
{
stringstream ss;
ss << "<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n";
ss << "<Response>\r\n";
ss << "<CmdType>Alarm</CmdType>\r\n";
ss << "<SN>" << sSN << "</SN>\r\n";
ss << "<DeviceID>" << deviceID << "</DeviceID>\r\n";
ss << "<Result>OK</Result>\r\n";
ss << "</Response>\r\n";
LOG_INFO("set subscribe msg\n");
osip_message_set_content_type(msg, "Application/MANSCDP+xml");
osip_message_set_body(msg, ss.str().c_str(), strlen(ss.str().c_str()));
}
send_response_subscribe(evt, msg);
if (memcmp(hname, "expires", strlen("expires")) == 0)
{
int value = stoi(hvalue);
LOG_INFO("expires:%d\n", value);
if (value == 0)
{
// 报警订阅取消,此时expires值为0
expiresAlarm = value / 60;
alarmOpen = false;
}
else
{
// 报警订阅,expires值为有效时间,单位秒
expiresAlarm = value / 60;
alarmOpen = true;
did = evt->did;
}
}
}
else
{
LOG_INFO("other cmdtype:%s\n", body);
}
}
}
2.2.3报警事件通知及结果
1.报警事件通知
- GBT 28181-2016规范里面的示范
Via:SIP/2.0/UDP 事件源域名或IP地址
Max-Forwards:70
From:显示名<sip:事件源编码@事件源域名或IP地址>;tag=BK32B1U8DKDrB
To:显示名<sip:事件观察者编码@事件观察者域名或IP地址>
Call-ID:17250
CSeq:1NOTIFY
Subscription-State:active;expires=90;retry-after=0
Event:presence
Content-type:Application/MANSCDP+XML
Content-Length:消息实体的字节长度
<? xmlversion="1.0"?>
<Notify>
<CmdType>Alarm</CmdType>
<SN>1</SN>
<DeviceID>64010000001340000001</DeviceID>
<AlarmPriority>4</AlarmPriority>
<AlarmMethod>2</AlarmMethod>
<AlarmTime>2009-12-04T16:23:32</AlarmTime>
<AlarmDescription>警情描述</AlarmDescription>
<Longitude>171.3</Longitude>
<Latitude>34.2</Latitude>
</Notify>
- 实际抓包信令
jaK.jaK.jaK.NOTIFY sip:34020000002000000001@192.168.0.161:15060 SIP/2.0
Via: SIP/2.0/UDP 192.168.0.104:5688;rport;branch=z9hG4bK259082348
From: <sip:37010200541180000001@192.168.0.104>;tag=618421060
To: <sip:34020000002000000001@192.168.0.161:15060>
Call-ID: 1323924525
CSeq: 20 NOTIFY
Content-Type: Application/MANSCDP+xml
Max-Forwards: 70
User-Agent: eXosip/4.1.0
Event: presence;id=1984
Subscription-State: active;retry-after=0
Expires: 3780
Content-Length: 459
<?xml version="1.0" encoding="GB2312"?>
<Notify>
<CmdType>Alarm</CmdType>
<SN>247</SN>
<DeviceID>44010200491180000002</DeviceID>
<AlarmPriority>4</AlarmPriority>
<AlarmMethod>5</AlarmMethod>
<AlarmTime>2022-10-13T10:36:04</AlarmTime>
<AlarmDescription>test</AlarmDescription>
<Info>
<AlarmType>6</AlarmType>
<AlarmTypeParam>
<EventType>1</EventType>
</AlarmTypeParam>
</Info>
<Longitude>171.3</Longitude>
<Latitude>34.2</Latitude>
</Notify>
2.结果
- GBT 28181-2016规范里面的示范
Via:SIP/2.0/UDP 事件源域名或IP地址
From:显示名<sip:事件源编码@事件源域名或IP地址>;tag=BK32B1U8DKDrB
To:显示名<sip:事件观察者编码@事件观察者域名或IP地址>
Call-ID:17250
CSeq:1NOTIFY
Content-type:Application/MANSCDP+XML
Content-Length:消息实体的字节长度
<? xmlversion="1.0"?>
<Response>
<CmdType>Alarm </CmdType>
<SN>1</SN>
<DeviceID>64010000001340000001</DeviceID>
<Result>OK</Result>
</Response>
- 实际抓包信令
SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.0.104:5688;rport=5688;received=192.168.0.104;branch=z9hG4bK259082348
From: <sip:37010200541180000001@192.168.0.104>;tag=618421060
To: <sip:34020000002000000001@192.168.0.161:15060>;tag=786220740
CSeq: 20 NOTIFY
Call-ID: 1323924525
User-Agent: LiveGBS v221009
Content-Length: 185
Content-Type: Application/MANSCDP+xml
<?xml version="1.0" encoding="UTF-8"?>
<Response>
<CmdType>Alarm</CmdType>
<SN>247</SN>
<DeviceID>44010200491180000002</DeviceID>
<Result>OK</Result>
</Response>
2.2.4代码实现
报警事件通知的代码实现:
void Device::alarmNotify(string DeviceId, int iAlarmPriority, int iAlarmMethod, int iAlarmType)
{
osip_message_t *requestAlarm = nullptr;
auto status = eXosip_message_build_request(sip_context, &requestAlarm, "NOTIFY", to_sip.c_str(), from_sip.c_str(), nullptr);
if (OSIP_SUCCESS != status)
{
LOG_ERROR("build requestAlarm failed: %d\n", status);
}
// osip_message_set_header(requestAlarm, "Event", "id=1984");
osip_message_set_header(requestAlarm, "Event", "presence;id=1984");
osip_message_set_header(requestAlarm, "Subscription-State", "active;retry-after=0");
char buf[5] = {0};
int timeAlarm = 0;
timeAlarm = expiresAlarm * 60;
sprintf(buf, "%d", timeAlarm);
osip_message_set_header(requestAlarm, "Expires", buf);
if (requestAlarm != NULL)
{
struct timeval curTime;
gettimeofday(&curTime, NULL);
char buffer[80] = {0};
struct tm nowTime;
localtime_r(&curTime.tv_sec, &nowTime);
strftime(buffer, sizeof(buffer), "%Y-%m-%dT%H:%M:%S", &nowTime);
string alarmTime = buffer;
LOG_INFO("alarmTime:%s\n", alarmTime.c_str());
stringstream ssAlarm;
ssAlarm << "<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n";
ssAlarm << "<Notify>\r\n";
ssAlarm << "<CmdType>Alarm</CmdType>\r\n"; /*命令类型(必选):报警通知*/
ssAlarm << "<SN>" << get_sn() << "</SN>\r\n"; /*命令序列号(必选)*/
ssAlarm << "<DeviceID>" << DeviceId << "</DeviceID>\r\n"; /*设备编码(必选):如果是NVR,就是通道编码*/
ssAlarm << "<AlarmPriority>" << iAlarmPriority << "</AlarmPriority>\r\n"; /*报警级别(必选):1为一级警情, 2为二级警情, 3为三级警情, 4为四级警情*/
ssAlarm << "<AlarmMethod>" << iAlarmMethod << "</AlarmMethod>\r\n"; /*报警方式(必选):1为电话报警, 2为设备报警, 3为短信报警, 4为GPS报警, 5为视频报警, 6为设备故障报警, 7其他报警*/
ssAlarm << "<AlarmTime>" << alarmTime << "</AlarmTime>\r\n"; /*报警时间(必选)*/
ssAlarm << "<AlarmDescription>test</AlarmDescription>\r\n"; /*警情描述(可选)*/
ssAlarm << "<Info>\r\n"; /*扩展Info项(可选):携带报警类型、报警类型参数字段*/
ssAlarm << "<AlarmType>" << iAlarmType << "</AlarmType>\r\n"; /*报警类型(可选):依赖报警方式,有三种情况。*/
if (iAlarmType == 6)
{
int iEventType = 1;
ssAlarm << "<AlarmTypeParam>\r\n"; /*报警类型扩展参数(可选):在入侵检测报警时可携带<EventType>节点。*/
ssAlarm << "<EventType>" << iEventType << "</EventType>\r\n"; /*事件类型(可选): 1-进入区域; 2-离开区域*/
ssAlarm << "</AlarmTypeParam>\r\n";
}
ssAlarm << "</Info>\r\n";
ssAlarm << "<Longitude>171.3</Longitude>\r\n"; /*经度信息(可选)*/
ssAlarm << "<Latitude>34.2</Latitude>\r\n"; /*纬度信息(可选)*/
ssAlarm << "</Notify>\r\n";
osip_message_set_content_type(requestAlarm, "Application/MANSCDP+xml");
osip_message_set_body(requestAlarm, ssAlarm.str().c_str(), strlen(ssAlarm.str().c_str()));
send_request(requestAlarm);
}
}
报警事件通知各个字段的含义见 附录。
3.附录
3.1报警通知各个字段的含义
1.Notify消息体:
| 字段名 | 字段值 | 是否必选 | 含义 |
|---|---|---|---|
| CmdType | Alarm | 必选 | 命令类型:报警通知 |
| SN | 十进制整数 | 必选 | 命令序列号 |
| DeviceID | 20位十进制字符串 | 必选 | 设备编号 |
| AlarmPriority | 字符串 | 必选 | 报警级别: 1:一级警情, 2:二级警情, 3:三级警情, 4:四级警情 |
| AlarmMethod | 字符串 | 必选 | 报警方式: 1:电话报警, 2:设备报警, 3:短信报警, 4:GPS报警, 5:视频报警, 6:设备故障报警, 7:其他报警 |
| AlarmTime | 2009-12-04T16:23:32 | 必选 | 报警时间 |
| AlarmDescription | 字符串 | 可选 | 报警内容描述 |
| Longitude | double | 可选 | 经度信息 |
| Latitude | double | 可选 | 纬度信息 |
| Info | XML节点 | 可选 | 扩展Info项携带报警类型、 报警类型参数字段 |
2.Notify的扩展信息Info消息体:
| 二级XML节点 | 三级XML节点 | 字段值 | 是否必选 | 含义 |
|---|---|---|---|---|
| AlarmType | 整数 | 可选 | 报警类型,依赖报警方式, 有三种情况。 | |
| AlarmTypeParam | XML节点 | 可选 | 报警类型扩展参数, 在入侵检测报警时 可携带 | |
| EventType | 整数 | 可选 | 事件类型: 1:进入区域 2:离开区域 |
关于AlarmType字段的含义解释:
- 报警方式(AlarmMethod)为 2 时
1.不携带AlarmType为默认的报警设备报警;
2.携带AlarmType取值及对应报警类型:1-视频丢失报警; 2-设备防拆报警; 3-存储设备磁盘满报警; 4-设 备高温报警; 5-设备低温报警。 - 报警方式(AlarmMethod)为 5 时
取值如下:1-人工视频报警; 2-运动目标检测报警; 3-遗留物检测报警; 4-物体移除检测报警; 5-绊线检测报警;6-入侵检测报警; 7-逆行检测报警; 8-徘徊检测报警; 9-流量统计报警; 10-密度检测报警; 11-视频异常检测报警; 12-快速移动报警。 - 报警方式(AlarmMethod)为 6 时
取值如下: 1-存储设备磁盘故障报警; 2-存储设备风扇故障报警。
声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
红包
点赞
收藏
评论
打赏
- 分享
- 举报
评论
0个
手气红包
暂无数据相关专栏
-
浏览量:2039次2024-10-18 13:03:27
-
浏览量:2803次2024-09-29 19:03:11
-
浏览量:1932次2024-10-18 13:05:10
-
浏览量:516次2026-06-30 14:43:19
-
浏览量:2321次2024-10-18 13:07:07
-
浏览量:8157次2020-09-07 14:18:26
-
浏览量:3657次2024-01-08 16:40:50
-
2020-09-28 11:34:56
-
浏览量:19215次2020-09-28 11:08:13
-
浏览量:3348次2023-11-13 17:48:03
-
浏览量:6513次2024-01-05 14:11:13
-
浏览量:5195次2024-01-05 14:15:33
-
浏览量:8434次2021-04-01 17:04:01
-
浏览量:2250次2023-11-21 17:56:50
-
浏览量:8608次2020-09-21 16:29:50
-
浏览量:3094次2024-02-24 13:49:46
-
浏览量:2267次2023-08-30 18:37:06
-
浏览量:3840次2023-12-29 17:51:55
-
浏览量:2512次2024-01-02 09:46:50
置顶时间设置
结束时间
删除原因
-
广告/SPAM
-
恶意灌水
-
违规内容
-
文不对题
-
重复发帖
打赏作者
林
您的支持将鼓励我继续创作!
打赏金额:
¥1
¥5
¥10
¥50
¥100
支付方式:
微信支付
举报反馈
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明
审核成功
发布时间设置
发布时间:
请选择发布时间设置
是否关联周任务-专栏模块
审核失败
失败原因
请选择失败原因
备注
请输入备注

微信扫码分享
QQ好友