当前位置: 首页 > news >正文

GB28181国标设备注册源码实现

本文将讲解在VSS中国标设备REGISTER的接入流程:从 gosip 收包、types.Request构建,到RegisterLogic鉴权、DeviceUpsert落库,以及上线/注销后触发的 Catalog、设备信息、心跳等下游任务。实现以VSS仓库源码为准。

相关文档:2.4.1.2 信令发送流水线(注册后 Catalog /SendLogic)、2.4.1.3 设备与通道在线状态(在线状态与SetDeviceOnline)。

项目源码地址https://github.com/openskeye/go-vss


1. 在Vss架构中的位置

说明
传输UDP/TCP 等由 gosip 监听;Via 中携带 transport,解析见getTransportProtocol
路由internal/handler/gbs_sip/routers.gosip.REGISTERsip2.DO(..., new(gbssip.RegisterLogic))
解析ParseToRequestinternal/pkg/sip/utils.go)把sip.Request转成types.Request
业务RegisterLogic.DOinternal/logic/gbs_sip/register.go)。
持久化RPCDevice.DeviceUpsert(注册与注销统一走 upsert)。

注册成功后,后续MESSAGE(Catalog、DeviceInfo、Keepalive)SUBSCRIBEINVITE等信令,都依赖SipCatalogLoopMap中缓存的types.Request(与注册报文对齐的 From/Via/传输等),见 2.4.1.2。


2. 请求转为types.Request

入口sip_handler.run在调用具体 Logic 前执行ParseToRequest(h.req);失败则400

ParseToRequest核心字段(节选):

func ParseToRequest(req sip.Request) (*types.Request, error) { from, ok := req.From() if !ok || from.Address == nil { return nil, errors.New("OnRegister, no from") } return &types.Request{ ID: from.Address.User().String(), Source: req.Source(), Body: req.Body(), Original: req, DeviceAddr: sip.Address{ DisplayName: from.DisplayName, Uri: from.Address, }, Authorization: req.GetHeaders("Authorization"), TransportProtocol: getTransportProtocol(req), }, nil }
字段含义
IDFrom URI 的 user 部分,作为平台侧20 位设备国标编码(实际长度校验在 Logic 内)。
Sourcereq.Source(),用于devices.AddressName等等价「注册来源/对端地址串」。
Original完整 SIP 请求
Authorization鉴权头,使用UsePassword时参与校验。
TransportProtocol由 Via 推断UDP/TCP/TLS/WS/WSS,默认 UDP。

3.RegisterLogic.DO流程

3.1 流程图

失败

成功

失败

成功

REGISTER 入站

len ID >= 18?

return nil --> sip_handler 回 200 OK 默认成功

UsePassword 且无 Authorization?

401 Unauthorized

解析 Expires 头

解析失败?

401 Unauthorized

UsePassword?

Digest auth 校验

401 Unauthorized

组装 record

expire == 0?

Online=0 注销

Online=1 上线

DeviceUpsert

500 系 Error 响应

Online?

CatalogLoop Offline + HeartbeatLoop 仅 ID

return 200

异步 1s 后: CatalogLoop / SipSendCatalog / SipSendDeviceInfo / HeartbeatLoop

3.2 关键步骤

1)设备 ID 长度

func (l *RegisterLogic) DO() *types.Response { if len(l.req.ID) < 18 { return nil
  • <18:当前实现直接return nil。在sip_handler.successres == nil时仍会回复200 OK。若需拒绝非法 ID,应改为显式BadRequest/Unauthorized(避免「静默成功」),这里需要自行修改。

2)密码与鉴权

  • Config.Sip.UsePassword == true无 Authorization401,提示 Authorization 为空。
  • 有 Authorization 时:authDigest与配置Sip.Password比对,REGISTER参与CalcResponse,失败401

3)Expires

  • Expires头取值:当前代码用strings.Split(header.String(), ":")取第二段再Atoi。格式需与库打印的 header 字符串一致,否则解析失败走401expire 已过期文案实为解析失败分支)。
  • expire == 0注销record.Online = 0

4)入库字段(默认上线)

var ( now = functions.NewTimer().Now() record = &devices.Item{ Devices: &devices.Devices{ Name: l.req.Source, AccessProtocol: devices.AccessProtocol_4, DeviceUniqueId: l.req.ID, State: 1, Online: 1, Expire: uint64(now) + uint64(expire), Address: l.req.Source, RegisterAt: uint64(now), }, }
  • AccessProtocol_4:固定为GB28181
  • Expire:当前 Unix 秒 + 注册生存期(秒)。
  • 注册不经过SetDeviceOnline:在线状态由DeviceUpsert一并写入;与心跳里的SetDeviceOnline队列(见 2.4.1.3)是不同路径。

5)200 OK与附加 SIP 头(BeforeResponse

  • 若存在Authorization且匹配成功,在响应中附加Expires/User-Agent/Server,并RemoveHeader("Allow")(与设备交互兼容相关,以现网设备为准)。
  • 未带 Authorization时,BeforeResponseok == false可能不追加上述头,依赖设备是否要求 Expires。

6)注销(expire == 0

  • SipCatalogLoopOnline: falseCatalogLoopLogicSipCatalogLoopMap移除该设备。
  • SipHeartbeatLoop:仅ID,用于更新/清理心跳 map 中条目(与上线时携带Now/RegisterExpireAt的完整结构不同)。

7)上线成功后的异步任务(Sleep 1s

go func() { time.Sleep(1 * time.Second) l.svcCtx.SipCatalogLoop <- &types.SipCatalogLoopReq{ Req: l.req, Online: true, Now: now } l.req.Caller = functions.CallerFile(1) l.svcCtx.SipSendCatalog <- l.req l.svcCtx.SipSendDeviceInfo <- l.req l.svcCtx.SipHeartbeatLoop <- &types.SipHeartbeatLoopReq{ ID: record.DeviceUniqueId, Now: now, RegisterExpireAt: now + int64(expire), } }()
action作用
SipCatalogLoop+Now注册定时 Catalog(判据见catalog_loop.go,信令发送流水线中已经说明可能与预期不一致)。
SipSendCatalog立即拉目录(经SendLogicGBSSender.Catalog)。
SipSendDeviceInfo立即拉设备信息
SipHeartbeatLoopHeartbeatOfflineLogic每秒扫描;RegisterExpireAt本次注册到期 Unix 秒,与HeartbeatTimeout等配合判定异常下线。

延迟 1 秒:降低被对端或中间网络丢弃的概率,这里属于折中方案,可以优化。


4. 调试与排障建议

现象可查点
注册成功但无目录SipSendCatalog是否积压、SendLogic日志、SipCatalogLoopMap是否在注销时被清掉。
一直 401UsePassword、Authorization 格式、密码与设备配置、Expires解析是否失败
ID 过短仍「成功」len(l.req.ID) < 18返回 nil导致200;这里可以明确错误码,目前我返回的为200 ok。
出站信令报设备未注册业务接口常查SipCatalogLoopMap;设备须先完成注册流水线把Request放进 map

5. 源码索引

文件说明
core/app/sev/vss/internal/handler/gbs_sip/routers.goREGISTER 路由
core/app/sev/vss/internal/logic/gbs_sip/register.goRegisterLogic
core/app/sev/vss/internal/pkg/sip/utils.goParseToRequest、传输协议
core/app/sev/vss/internal/pkg/sip/sip_handler.go统一DO/响应码
core/app/sev/vss/internal/types/types.goRequestSipCatalogLoopReqSipHeartbeatLoopReq
core/app/sev/vss/internal/logic/gbs_proc/catalog_loop.goCatalog 定时器
core/app/sev/vss/internal/logic/gbs_proc/heartbeat_offline_loop.go注册到期与心跳超时下线
http://www.jsqmd.com/news/561366/

相关文章:

  • 深度神经网络的底层数学原理
  • 无人机电调DIY改造指南:从MOSFET选型到散热优化(附实测数据)
  • 影刀RPA与Python变量管理:全局与局部变量的实战应用
  • 基于Fish-Speech-1.5的智能客服语音合成实战
  • AI率降到20%以内用哪个平台检测最准?知网/维普/万方深度对比
  • 大数据领域数据标准化:促进数据驱动创新
  • 海外短剧系统开发全案:多语言 + 多支付 + 全球 CDN 一站式交付
  • S3Browser跨域配置实战:从复制示例到调试成功的完整避坑指南
  • 医药行业全终端销售分析:从院内到院外,构建全景监控体系
  • Stata小白必看:手把手教你搞定ivreghdfe离线安装(附Windows/Mac路径设置避坑)
  • 免费工具能把AI率降到20%以内吗?免费vs付费效果实测对比
  • PingFangSC字体实战指南:跨平台字体解决方案的最佳实践
  • 防盗门焕新纪实
  • Calibre电子书管理:如何从数据混乱到智能分类的蜕变?
  • SEM图像质量提升秘籍:二次电子与背散射电子的9种信号特性全解析
  • 从ENIAC到SoC:聊聊PLA在数字电路发展史中的位置与局限
  • 2026年市面上比较好的雨棚厂商口碑推荐,封阳台/雨棚/系统窗/凉亭/系统门窗/肯德基门/阳光房,雨棚公司推荐分析 - 品牌推荐师
  • GaaS-2026年最赚钱的软件商业模式
  • 【苍穹外卖】从零到一:项目架构解析与开发环境一站式搭建指南
  • S32K144实战:如何用SDK实现Bootloader与APP的无缝跳转(附完整代码)
  • Windows平台APK安装神器:5分钟实现安卓应用跨平台运行
  • 2026年3月份中国访客一体机厂家品牌以粤神盾ysdun为代表的标杆企业深度解析 - 智能硬件-产品评测
  • 终极免费跨平台网络资源下载利器:res-downloader完全使用指南
  • AudioLDM-S与LangGraph:构建音效生成工作流引擎
  • 别再只盯着GPS了!手把手教你用Python仿真UWB定位,30厘米精度是怎么来的?
  • Dirsearch字典玄学:从默认字典到AI生成,我的扫描效率提升300%的秘密
  • Java程序员6年焦虑,转行AI后薪资暴涨40%!这8个岗位,普通人也能入局?年薪百万不是梦!
  • 实战对比:用Docker封装OpenVINO推理环境,一键部署iGPU和NPU加速(附Dockerfile)
  • 美航自动化,珠三角机器人打磨抛光设备源头厂家,布局广东等地 - 十大品牌榜
  • 2026春招AI岗高薪指南:避开3大误区,这3类岗位轻松拿7万+月薪!