diff --git a/plugin/gb28181pro/pkg/commongbchannel.go b/plugin/gb28181pro/pkg/commongbchannel.go
index 9eeed05..9bd1615 100644
--- a/plugin/gb28181pro/pkg/commongbchannel.go
+++ b/plugin/gb28181pro/pkg/commongbchannel.go
@@ -7,133 +7,133 @@ import (
// CommonGBChannel 通用国标通道信息
type CommonGBChannel struct {
// 数据库自增ID
- GbID int `json:"gbId" gorm:"column:gb_id"`
+ GbID int `json:"gb_id" gorm:"column:gb_id"`
// 国标编码
- GbDeviceID string `json:"gbDeviceId" gorm:"column:gb_device_id"`
+ GbDeviceID string `json:"gb_device_id" gorm:"column:gb_device_id;default:null"`
// 国标名称
- GbName string `json:"gbName" gorm:"column:gb_name"`
+ GbName string `json:"gb_name" gorm:"column:gb_name;default:null"`
// 国标设备厂商
- GbManufacturer string `json:"gbManufacturer" gorm:"column:gb_manufacturer"`
+ GbManufacturer string `json:"gb_manufacturer" gorm:"column:gb_manufacturer;default:null"`
// 国标设备型号
- GbModel string `json:"gbModel" gorm:"column:gb_model"`
+ GbModel string `json:"gb_model" gorm:"column:gb_model;default:null"`
// 国标设备归属
- GbOwner string `json:"gbOwner" gorm:"column:gb_owner"`
+ GbOwner string `json:"gb_owner" gorm:"column:gb_owner;default:null"`
// 国标行政区域
- GbCivilCode string `json:"gbCivilCode" gorm:"column:gb_civil_code"`
+ GbCivilCode string `json:"gb_civil_code" gorm:"column:gb_civil_code"`
// 国标警区
- GbBlock string `json:"gbBlock" gorm:"column:gb_block"`
+ GbBlock string `json:"gb_block" gorm:"column:gb_block"`
// 国标安装地址
- GbAddress string `json:"gbAddress" gorm:"column:gb_address"`
+ GbAddress string `json:"gb_address" gorm:"column:gb_address;default:null"`
// 国标是否有子设备
- GbParental int `json:"gbParental" gorm:"column:gb_parental"`
+ GbParental int `json:"gb_parental" gorm:"column:gb_parental"`
// 国标父节点ID
- GbParentID string `json:"gbParentId" gorm:"column:gb_parent_id"`
+ GbParentID string `json:"gb_parent_id" gorm:"column:gb_parent_id"`
// 国标信令安全模式
- GbSafetyWay int `json:"gbSafetyWay" gorm:"column:gb_safety_way"`
+ GbSafetyWay int `json:"gb_safety_way" gorm:"column:gb_safety_way"`
// 国标注册方式
- GbRegisterWay int `json:"gbRegisterWay" gorm:"column:gb_register_way"`
+ GbRegisterWay int `json:"gb_register_way" gorm:"column:gb_register_way"`
// 国标证书序列号
- GbCertNum string `json:"gbCertNum" gorm:"column:gb_cert_num"`
+ GbCertNum string `json:"gb_cert_num" gorm:"column:gb_cert_num"`
// 国标证书有效标识
- GbCertifiable int `json:"gbCertifiable" gorm:"column:gb_certifiable"`
+ GbCertifiable int `json:"gb_certifiable" gorm:"column:gb_certifiable"`
// 国标无效原因码
- GbErrCode int `json:"gbErrCode" gorm:"column:gb_err_code"`
+ GbErrCode int `json:"gb_err_code" gorm:"column:gb_err_code"`
// 国标证书终止有效期
- GbEndTime string `json:"gbEndTime" gorm:"column:gb_end_time"`
+ GbEndTime string `json:"gb_end_time" gorm:"column:gb_end_time"`
// 国标保密属性
- GbSecrecy int `json:"gbSecrecy" gorm:"column:gb_secrecy"`
+ GbSecrecy int `json:"gb_secrecy" gorm:"column:gb_secrecy"`
// 国标IP地址
- GbIPAddress string `json:"gbIpAddress" gorm:"column:gb_ip_address"`
+ GbIPAddress string `json:"gb_ip_address" gorm:"column:gb_ip_address"`
// 国标端口
- GbPort int `json:"gbPort" gorm:"column:gb_port"`
+ GbPort int `json:"gb_port" gorm:"column:gb_port"`
// 国标密码
- GbPassword string `json:"gbPassword" gorm:"column:gb_password"`
+ GbPassword string `json:"gb_password" gorm:"column:gb_password"`
// 国标状态
- GbStatus string `json:"gbStatus" gorm:"column:gb_status"`
+ GbStatus string `json:"gb_status" gorm:"column:gb_status"`
// 国标经度
- GbLongitude float64 `json:"gbLongitude" gorm:"column:gb_longitude"`
+ GbLongitude float64 `json:"gb_longitude" gorm:"column:gb_longitude"`
// 国标纬度
- GbLatitude float64 `json:"gbLatitude" gorm:"column:gb_latitude"`
+ GbLatitude float64 `json:"gb_latitude" gorm:"column:gb_latitude"`
// 国标业务分组ID
- GbBusinessGroupID string `json:"gbBusinessGroupId" gorm:"column:gb_business_group_id"`
+ GbBusinessGroupID string `json:"gb_business_group_id" gorm:"column:gb_business_group_id"`
// 国标云台类型
- GbPTZType int `json:"gbPtzType" gorm:"column:gb_ptz_type"`
+ GbPTZType int `json:"gb_ptz_type" gorm:"column:gb_ptz_type"`
// 国标位置类型
- GbPositionType int `json:"gbPositionType" gorm:"column:gb_position_type"`
+ GbPositionType int `json:"gb_position_type" gorm:"column:gb_position_type"`
// 国标房间类型
- GbRoomType int `json:"gbRoomType" gorm:"column:gb_room_type"`
+ GbRoomType int `json:"gb_room_type" gorm:"column:gb_room_type"`
// 国标用途类型
- GbUseType int `json:"gbUseType" gorm:"column:gb_use_type"`
+ GbUseType int `json:"gb_use_type" gorm:"column:gb_use_type"`
// 国标补光类型
- GbSupplyLightType int `json:"gbSupplyLightType" gorm:"column:gb_supply_light_type"`
+ GbSupplyLightType int `json:"gb_supply_light_type" gorm:"column:gb_supply_light_type"`
// 国标方向类型
- GbDirectionType int `json:"gbDirectionType" gorm:"column:gb_direction_type"`
+ GbDirectionType int `json:"gb_direction_type" gorm:"column:gb_direction_type"`
// 国标分辨率
- GbResolution string `json:"gbResolution" gorm:"column:gb_resolution"`
+ GbResolution string `json:"gb_resolution" gorm:"column:gb_resolution"`
// 国标下载速度
- GbDownloadSpeed string `json:"gbDownloadSpeed" gorm:"column:gb_download_speed"`
+ GbDownloadSpeed string `json:"gb_download_speed" gorm:"column:gb_download_speed"`
// 国标空域编码能力
- GbSvcSpaceSupportMod int `json:"gbSvcSpaceSupportMod" gorm:"column:gb_svc_space_support_mod"`
+ GbSvcSpaceSupportMod int `json:"gb_svc_space_support_mod" gorm:"column:gb_svc_space_support_mod"`
// 国标时域编码能力
- GbSvcTimeSupportMode int `json:"gbSvcTimeSupportMode" gorm:"column:gb_svc_time_support_mode"`
+ GbSvcTimeSupportMode int `json:"gb_svc_time_support_mode" gorm:"column:gb_svc_time_support_mode"`
// 关联的国标设备数据库ID
- GbDeviceDbID int `json:"gbDeviceDbId" gorm:"column:gb_device_db_id"`
+ GbDeviceDbID int `json:"gb_device_db_id" gorm:"column:gb_device_db_id"`
// 二进制保存的录制计划
- RecordPlan int64 `json:"recordPlan" gorm:"column:record_plan"`
+ RecordPlan int64 `json:"record_plan" gorm:"column:record_plan"`
// 关联的推流ID
- StreamPushID int `json:"streamPushId" gorm:"column:stream_push_id"`
+ StreamPushID int `json:"stream_push_id" gorm:"column:stream_push_id"`
// 关联的拉流代理ID
- StreamProxyID int `json:"streamProxyId" gorm:"column:stream_proxy_id"`
+ StreamProxyID int `json:"stream_proxy_id" gorm:"column:stream_proxy_id"`
// 创建时间
- CreateTime string `json:"createTime" gorm:"column:create_time"`
+ CreateTime string `json:"create_time" gorm:"column:create_time"`
// 更新时间
- UpdateTime string `json:"updateTime" gorm:"column:update_time"`
+ UpdateTime string `json:"update_time" gorm:"column:update_time"`
// 流ID,存在表示正在推流
- StreamID string `json:"streamId" xml:"-"`
+ StreamID string `json:"stream_id" xml:"-"`
// 是否含有音频
- HasAudio bool `json:"hasAudio" xml:"-"`
+ HasAudio bool `json:"has_audio" xml:"-"`
}
// Build 构建通道信息
diff --git a/plugin/gb28181pro/pkg/platformchannel.go b/plugin/gb28181pro/pkg/platformchannel.go
index 889e6f3..0a64bf6 100644
--- a/plugin/gb28181pro/pkg/platformchannel.go
+++ b/plugin/gb28181pro/pkg/platformchannel.go
@@ -7,14 +7,14 @@ type PlatformChannel struct {
Id int // 数据库自增长ID
PlatformId int // 平台ID
DeviceChannelId int // 设备通道ID
- CustomDeviceId string // 国标-编码
- CustomName string // 国标-名称
- CustomManufacturer string // 国标-设备厂商
- CustomModel string // 国标-设备型号
- CustomOwner string // 国标-设备归属
+ CustomDeviceId string `gorm:"default:null"` // 国标-编码
+ CustomName string `gorm:"default:null"` // 国标-名称
+ CustomManufacturer string `gorm:"default:null"` // 国标-设备厂商
+ CustomModel string `gorm:"default:null"` // 国标-设备型号
+ CustomOwner string `gorm:"default:null"` // 国标-设备归属
CustomCivilCode string // 国标-行政区域
CustomBlock string // 国标-警区
- CustomAddress string // 国标-安装地址
+ CustomAddress string `gorm:"default:null"` // 国标-安装地址
CustomParental int // 国标-是否有子设备
CustomParentId string // 国标-父节点ID
CustomSafetyWay int // 国标-信令安全模式
diff --git a/plugin/gb28181pro/platform.go b/plugin/gb28181pro/platform.go
index a21686a..5a80ff1 100644
--- a/plugin/gb28181pro/platform.go
+++ b/plugin/gb28181pro/platform.go
@@ -38,9 +38,11 @@ type Platform struct {
eventChan chan any
// 插件配置
plugin *GB28181ProPlugin
+ ctx context.Context
}
func (p *Platform) init() {
+ p.ctx = context.Background()
client, err := sipgo.NewClient(p.plugin.ua, sipgo.WithClientHostname(p.PlatformModel.DeviceIP), sipgo.WithClientPort(p.PlatformModel.DevicePort))
if err != nil {
p.Error("failed to create sip client: %v", err)
@@ -212,7 +214,7 @@ func (p *Platform) Unregister(ctx context.Context) (*sipgo.DialogClientSession,
req.SetTransport(strings.ToUpper(p.PlatformModel.Transport))
// 发送请求并获取响应
- tx, err := p.Client.TransactionRequest(ctx, req, sipgo.ClientRequestAddVia)
+ tx, err := p.Client.TransactionRequest(ctx, req)
if err != nil {
return nil, fmt.Errorf("创建事务失败: %v", err)
}
@@ -308,6 +310,9 @@ func (p *Platform) handleCatalog(req *sip.Request, tx sip.ServerTransaction, msg
fromTag, _ := req.From().Params.Get("tag")
p.plugin.Info("catalog", "sn", sn, "fromTag", fromTag)
+ // 打印平台ID
+ p.plugin.Info("catalog query platform_id", "platform_id", p.PlatformModel.ID)
+
// 查询通道列表
var channels []gb28181.CommonGBChannel
if p.plugin.DB != nil {
@@ -318,40 +323,40 @@ func (p *Platform) handleCatalog(req *sip.Request, tx sip.ServerTransaction, msg
c.stream_proxy_id,
c.create_time,
c.update_time,
- COALESCE(pc.custom_device_id, c.gb_device_id, c.device_id) as gb_device_id,
- COALESCE(pc.custom_name, c.gb_name, c.name) as gb_name,
- COALESCE(pc.custom_manufacturer, c.gb_manufacturer, c.manufacturer) as gb_manufacturer,
- COALESCE(pc.custom_model, c.gb_model, c.model) as gb_model,
- COALESCE(pc.custom_owner, c.gb_owner, c.owner) as gb_owner,
- COALESCE(pc.custom_civil_code, c.gb_civil_code, c.civil_code) as gb_civil_code,
- COALESCE(pc.custom_block, c.gb_block, c.block) as gb_block,
- COALESCE(pc.custom_address, c.gb_address, c.address) as gb_address,
- COALESCE(pc.custom_parental, c.gb_parental, c.parental) as gb_parental,
- COALESCE(pc.custom_parent_id, c.gb_parent_id, c.parent_id) as gb_parent_id,
- COALESCE(pc.custom_safety_way, c.gb_safety_way, c.safety_way) as gb_safety_way,
- COALESCE(pc.custom_register_way, c.gb_register_way, c.register_way) as gb_register_way,
- COALESCE(pc.custom_cert_num, c.gb_cert_num, c.cert_num) as gb_cert_num,
- COALESCE(pc.custom_certifiable, c.gb_certifiable, c.certifiable) as gb_certifiable,
- COALESCE(pc.custom_err_code, c.gb_err_code, c.err_code) as gb_err_code,
- COALESCE(pc.custom_end_time, c.gb_end_time, c.end_time) as gb_end_time,
- COALESCE(pc.custom_secrecy, c.gb_secrecy, c.secrecy) as gb_secrecy,
- COALESCE(pc.custom_ip_address, c.gb_ip_address, c.ip_address) as gb_ip_address,
- COALESCE(pc.custom_port, c.gb_port, c.port) as gb_port,
- COALESCE(pc.custom_password, c.gb_password, c.password) as gb_password,
- COALESCE(pc.custom_status, c.gb_status, c.status) as gb_status,
- COALESCE(pc.custom_longitude, c.gb_longitude, c.longitude) as gb_longitude,
- COALESCE(pc.custom_latitude, c.gb_latitude, c.latitude) as gb_latitude,
- COALESCE(pc.custom_ptz_type, c.gb_ptz_type, c.ptz_type) as gb_ptz_type,
- COALESCE(pc.custom_position_type, c.gb_position_type, c.position_type) as gb_position_type,
- COALESCE(pc.custom_room_type, c.gb_room_type, c.room_type) as gb_room_type,
- COALESCE(pc.custom_use_type, c.gb_use_type, c.use_type) as gb_use_type,
- COALESCE(pc.custom_supply_light_type, c.gb_supply_light_type, c.supply_light_type) as gb_supply_light_type,
- COALESCE(pc.custom_direction_type, c.gb_direction_type, c.direction_type) as gb_direction_type,
- COALESCE(pc.custom_resolution, c.gb_resolution, c.resolution) as gb_resolution,
- COALESCE(pc.custom_business_group_id, c.gb_business_group_id, c.business_group_id) as gb_business_group_id,
- COALESCE(pc.custom_download_speed, c.gb_download_speed, c.download_speed) as gb_download_speed,
- COALESCE(pc.custom_svc_space_support_mod, c.gb_svc_space_support_mod, c.svc_space_support_mod) as gb_svc_space_support_mod,
- COALESCE(pc.custom_svc_time_support_mode, c.gb_svc_time_support_mode, c.svc_time_support_mode) as gb_svc_time_support_mode`).
+ COALESCE(nullif(pc.custom_device_id,''), nullif(c.gb_device_id,''), nullif(c.device_id,'')) as gb_device_id,
+ COALESCE(nullif(pc.custom_name,''), nullif(c.gb_name,''), nullif(c.name,'')) as gb_name,
+ COALESCE(nullif(pc.custom_manufacturer,''), nullif(c.gb_manufacturer,''), nullif(c.manufacturer,'')) as gb_manufacturer,
+ COALESCE(nullif(pc.custom_model,''), nullif(c.gb_model,''), nullif(c.model,'')) as gb_model,
+ COALESCE(nullif(pc.custom_owner,''), nullif(c.gb_owner,''), nullif(c.owner,'')) as gb_owner,
+ COALESCE(nullif(pc.custom_civil_code,''), nullif(c.gb_civil_code,''), nullif(c.civil_code,'')) as gb_civil_code,
+ COALESCE(nullif(pc.custom_block,''), nullif(c.gb_block,''), nullif(c.block,'')) as gb_block,
+ COALESCE(nullif(pc.custom_address,''), nullif(c.gb_address,''), nullif(c.address,'')) as gb_address,
+ COALESCE(nullif(pc.custom_parental,''), nullif(c.gb_parental,''), nullif(c.parental,'')) as gb_parental,
+ COALESCE(nullif(pc.custom_parent_id,''), nullif(c.gb_parent_id,''), nullif(c.parent_id,'')) as gb_parent_id,
+ COALESCE(nullif(pc.custom_safety_way,''), nullif(c.gb_safety_way,''), nullif(c.safety_way,'')) as gb_safety_way,
+ COALESCE(nullif(pc.custom_register_way,''), nullif(c.gb_register_way,''), nullif(c.register_way,'')) as gb_register_way,
+ COALESCE(nullif(pc.custom_cert_num,''), nullif(c.gb_cert_num,''), nullif(c.cert_num,'')) as gb_cert_num,
+ COALESCE(nullif(pc.custom_certifiable,''), nullif(c.gb_certifiable,''), nullif(c.certifiable,'')) as gb_certifiable,
+ COALESCE(nullif(pc.custom_err_code,''), nullif(c.gb_err_code,''), nullif(c.err_code,'')) as gb_err_code,
+ COALESCE(nullif(pc.custom_end_time,''), nullif(c.gb_end_time,''), nullif(c.end_time,'')) as gb_end_time,
+ COALESCE(nullif(pc.custom_secrecy,''), nullif(c.gb_secrecy,''), nullif(c.secrecy,'')) as gb_secrecy,
+ COALESCE(nullif(pc.custom_ip_address,''), nullif(c.gb_ip_address,''), nullif(c.ip_address,'')) as gb_ip_address,
+ COALESCE(nullif(pc.custom_port,''), nullif(c.gb_port,''), nullif(c.port,'')) as gb_port,
+ COALESCE(nullif(pc.custom_password,''), nullif(c.gb_password,''), nullif(c.password,'')) as gb_password,
+ COALESCE(nullif(pc.custom_status,''), nullif(c.gb_status,''), nullif(c.status,'')) as gb_status,
+ COALESCE(nullif(pc.custom_longitude,''), nullif(c.gb_longitude,''), nullif(c.longitude,'')) as gb_longitude,
+ COALESCE(nullif(pc.custom_latitude,''), nullif(c.gb_latitude,''), nullif(c.latitude,'')) as gb_latitude,
+ COALESCE(nullif(pc.custom_ptz_type,''), nullif(c.gb_ptz_type,''), nullif(c.ptz_type,'')) as gb_ptz_type,
+ COALESCE(nullif(pc.custom_position_type,''), nullif(c.gb_position_type,''), nullif(c.position_type,'')) as gb_position_type,
+ COALESCE(nullif(pc.custom_room_type,''), nullif(c.gb_room_type,''), nullif(c.room_type,'')) as gb_room_type,
+ COALESCE(nullif(pc.custom_use_type,''), nullif(c.gb_use_type,''), nullif(c.use_type,'')) as gb_use_type,
+ COALESCE(nullif(pc.custom_supply_light_type,''), nullif(c.gb_supply_light_type,''), nullif(c.supply_light_type,'')) as gb_supply_light_type,
+ COALESCE(nullif(pc.custom_direction_type,''), nullif(c.gb_direction_type,''), nullif(c.direction_type,'')) as gb_direction_type,
+ COALESCE(nullif(pc.custom_resolution,''), nullif(c.gb_resolution,''), nullif(c.resolution,'')) as gb_resolution,
+ COALESCE(nullif(pc.custom_business_group_id,''), nullif(c.gb_business_group_id,''), nullif(c.business_group_id,'')) as gb_business_group_id,
+ COALESCE(nullif(pc.custom_download_speed,''), nullif(c.gb_download_speed,''), nullif(c.download_speed,'')) as gb_download_speed,
+ COALESCE(nullif(pc.custom_svc_space_support_mod,''), nullif(c.gb_svc_space_support_mod,''), nullif(c.svc_space_support_mod,'')) as gb_svc_space_support_mod,
+ COALESCE(nullif(pc.custom_svc_time_support_mode,''), nullif(c.gb_svc_time_support_mode,''), nullif(c.svc_time_support_mode,'')) as gb_svc_time_support_mode`).
Joins("left join platform_channel_gb28181pro pc on c.id = pc.device_channel_id").
Where("pc.platform_id = ?", p.PlatformModel.ID).
Find(&channels).Error; err != nil {
@@ -359,13 +364,9 @@ func (p *Platform) handleCatalog(req *sip.Request, tx sip.ServerTransaction, msg
}
}
- // 发送目录响应
- if len(channels) > 0 {
- p.Info("get channels success", channels)
- return p.sendCatalogResponse(req, sn, fromTag, channels)
- } else {
- return p.sendEmptyCatalogResponse(req, sn, fromTag)
- }
+ // 发送目录响应,无论是否有通道
+ p.plugin.Info("get channels success", channels)
+ return p.sendCatalogResponse(req, sn, fromTag, channels)
}
// CreateRequest 创建 SIP 请求
@@ -377,76 +378,185 @@ func (p *Platform) CreateRequest(method string) *sip.Request {
// sendCatalogResponse 发送目录响应
func (p *Platform) sendCatalogResponse(req *sip.Request, sn string, fromTag string, channels []gb28181.CommonGBChannel) error {
- request := p.CreateRequest("MESSAGE")
+ // 如果没有通道,发送一个空的目录列表
+ if len(channels) == 0 {
+ request := p.CreateRequest("MESSAGE")
- // 设置From头部
- fromHeader := sip.FromHeader{
- Address: sip.Uri{
- User: p.PlatformModel.DeviceGBID,
- Host: p.PlatformModel.ServerGBDomain,
- },
- Params: sip.NewParams(),
- }
- fromHeader.Params.Add("tag", fromTag)
- request.AppendHeader(&fromHeader)
- // 添加To头部
- toHeader := sip.ToHeader{
- Address: sip.Uri{
- User: p.PlatformModel.ServerGBID,
- Host: p.PlatformModel.ServerGBDomain,
- },
- }
- req.AppendHeader(&toHeader)
- // 添加Via头部
- viaHeader := sip.ViaHeader{
- ProtocolName: "SIP",
- ProtocolVersion: "2.0",
- Transport: p.PlatformModel.Transport,
- Host: p.PlatformModel.DeviceIP,
- Port: p.PlatformModel.DevicePort,
- Params: sip.NewParams(),
- }
- viaHeader.Params.Add("branch", sip.GenerateBranchN(16)).Add("rport", "")
- req.AppendHeader(&viaHeader)
+ // 设置From头部
+ fromHeader := sip.FromHeader{
+ Address: sip.Uri{
+ User: p.PlatformModel.DeviceGBID,
+ Host: p.PlatformModel.ServerGBDomain,
+ },
+ Params: sip.NewParams(),
+ }
+ fromHeader.Params.Add("tag", fromTag)
+ request.AppendHeader(&fromHeader)
- //request.SetSource(req.Source())
- //request.SetDestination(req.Destination())
- request.SetTransport(req.Transport())
- contentTypeHeader := sip.ContentTypeHeader("Application/MANSCDP+xml")
- request.AppendHeader(&contentTypeHeader)
- request.SetBody([]byte(fmt.Sprintf(`
+ // 添加To头部
+ toHeader := sip.ToHeader{
+ Address: sip.Uri{
+ User: p.PlatformModel.ServerGBID,
+ Host: p.PlatformModel.ServerGBDomain,
+ },
+ }
+ request.AppendHeader(&toHeader)
+
+ // 添加Via头部
+ viaHeader := sip.ViaHeader{
+ ProtocolName: "SIP",
+ ProtocolVersion: "2.0",
+ Transport: p.PlatformModel.Transport,
+ Host: p.PlatformModel.DeviceIP,
+ Port: p.PlatformModel.DevicePort,
+ Params: sip.NewParams(),
+ }
+ viaHeader.Params.Add("branch", sip.GenerateBranchN(16)).Add("rport", "")
+ request.AppendHeader(&viaHeader)
+
+ request.SetTransport(req.Transport())
+ contentTypeHeader := sip.ContentTypeHeader("Application/MANSCDP+xml")
+ request.AppendHeader(&contentTypeHeader)
+
+ // 空目录列表XML
+ xmlContent := fmt.Sprintf(`
+
+Catalog
+%s
+%s
+0
+
+
+`, sn, p.PlatformModel.DeviceGBID)
+ request.SetBody([]byte(xmlContent))
+ _, err := p.Client.Do(p.ctx, request)
+ if err != nil {
+ p.plugin.Error("p.Client.Do", err)
+ }
+ return err
+ }
+
+ // 有通道时,为每个通道单独发送一个XML
+ for i, channel := range channels {
+ request := p.CreateRequest("MESSAGE")
+
+ // 设置From头部
+ fromHeader := sip.FromHeader{
+ Address: sip.Uri{
+ User: p.PlatformModel.DeviceGBID,
+ Host: p.PlatformModel.ServerGBDomain,
+ },
+ Params: sip.NewParams(),
+ }
+ fromHeader.Params.Add("tag", fromTag)
+ request.AppendHeader(&fromHeader)
+
+ // 添加To头部
+ toHeader := sip.ToHeader{
+ Address: sip.Uri{
+ User: p.PlatformModel.ServerGBID,
+ Host: p.PlatformModel.ServerGBDomain,
+ },
+ }
+ request.AppendHeader(&toHeader)
+
+ // 添加Via头部
+ viaHeader := sip.ViaHeader{
+ ProtocolName: "SIP",
+ ProtocolVersion: "2.0",
+ Transport: p.PlatformModel.Transport,
+ Host: p.PlatformModel.DeviceIP,
+ Port: p.PlatformModel.DevicePort,
+ Params: sip.NewParams(),
+ }
+ viaHeader.Params.Add("branch", sip.GenerateBranchN(16)).Add("rport", "")
+ request.AppendHeader(&viaHeader)
+
+ request.SetTransport(req.Transport())
+ contentTypeHeader := sip.ContentTypeHeader("Application/MANSCDP+xml")
+ request.AppendHeader(&contentTypeHeader)
+
+ // 为单个通道创建XML
+ channelXML := p.buildChannelItem(channel)
+ xmlContent := fmt.Sprintf(`
Catalog
%s
%s
%d
-
+
%s
-`, sn, p.PlatformModel.DeviceGBID, len(channels), len(channels), p.buildChannelList(channels))))
- _, err := p.Client.Do(p, request)
- return err
+`, sn, p.PlatformModel.DeviceGBID, len(channels), channelXML)
+
+ request.SetBody([]byte(xmlContent))
+ _, err := p.Client.Do(p.ctx, request)
+ if err != nil {
+ p.Error("send catalog response", "error", err.Error(), "channel_index", i)
+ return err
+ }
+
+ // 添加短暂延迟以防止发送过快
+ time.Sleep(time.Millisecond * 50)
+ }
+
+ return nil
}
-// sendEmptyCatalogResponse 发送空目录响应
-func (p *Platform) sendEmptyCatalogResponse(req *sip.Request, sn string, fromTag string) error {
- request := p.CreateRequest("MESSAGE")
- request.From().Params.Add("tag", fromTag)
- request.To().Params.Add("tag", fromTag)
- request.SetSource(req.Source())
- request.SetDestination(req.Destination())
- request.SetTransport(req.Transport())
- contentTypeHeader := sip.ContentTypeHeader("Application/MANSCDP+xml")
- request.AppendHeader(&contentTypeHeader)
- request.SetBody([]byte(fmt.Sprintf(`
-
-Catalog
-%s
-
-
-`, sn)))
- _, err := p.Client.Do(p, request)
- return err
+// buildChannelItem 构建单个通道的XML项
+func (p *Platform) buildChannelItem(channel gb28181.CommonGBChannel) string {
+ // 确保字符串字段不为空
+ deviceID := channel.GbDeviceID
+ if deviceID == "" {
+ deviceID = "unknown_device" // 如果没有设备ID,使用默认值
+ }
+ name := channel.GbName
+ if name == "" {
+ name = "未命名设备"
+ }
+ manufacturer := channel.GbManufacturer
+ if manufacturer == "" {
+ manufacturer = "未知厂商"
+ }
+ model := channel.GbModel
+ if model == "" {
+ model = "未知型号"
+ }
+ owner := channel.GbOwner
+ if owner == "" {
+ owner = "未知所有者"
+ }
+ address := channel.GbAddress
+ if address == "" {
+ address = "未知地址"
+ }
+ parentID := channel.GbParentID
+ if parentID == "" {
+ parentID = p.PlatformModel.DeviceGBID // 使用平台ID作为父ID
+ }
+
+ return fmt.Sprintf(`-
+%s
+%s
+%s
+%s
+%s
+%s
+%d
+%d
+%s
+%d
+%d
+ON
+
+
+
`, deviceID, name, manufacturer, model,
+ owner, address,
+ channel.GbRegisterWay, // 直接使用整数值
+ channel.GbSecrecy, // 直接使用整数值
+ parentID,
+ channel.GbParental, // 直接使用整数值
+ channel.GbSafetyWay) // 直接使用整数值
}
// handleDeviceControl 处理设备控制请求
@@ -592,66 +702,6 @@ func (p *Platform) handleMobilePosition(req *sip.Request, tx sip.ServerTransacti
return tx.Respond(response)
}
-func (p *Platform) buildChannelList(channels []gb28181.CommonGBChannel) string {
- var content string
- for _, channel := range channels {
- // 确保字符串字段不为空
- deviceID := channel.GbDeviceID
- if deviceID == "" {
- deviceID = "unknown_device" // 如果没有设备ID,使用默认值
- }
- name := channel.GbName
- if name == "" {
- name = "未命名设备"
- }
- manufacturer := channel.GbManufacturer
- if manufacturer == "" {
- manufacturer = "未知厂商"
- }
- model := channel.GbModel
- if model == "" {
- model = "未知型号"
- }
- owner := channel.GbOwner
- if owner == "" {
- owner = "未知所有者"
- }
- address := channel.GbAddress
- if address == "" {
- address = "未知地址"
- }
- parentID := channel.GbParentID
- if parentID == "" {
- parentID = p.PlatformModel.DeviceGBID // 使用平台ID作为父ID
- }
-
- content += fmt.Sprintf(`-
-%s
-%s
-%s
-%s
-%s
-%s
-%d
-%d
-%s
-%d
-%d
-ON
-
-
-
-`, deviceID, name, manufacturer, model,
- owner, address,
- channel.GbRegisterWay, // 直接使用整数值
- channel.GbSecrecy, // 直接使用整数值
- parentID,
- channel.GbParental, // 直接使用整数值
- channel.GbSafetyWay) // 直接使用整数值
- }
- return content
-}
-
// GetKey 返回平台的唯一标识符
func (p *Platform) GetKey() uint32 {
return p.PlatformModel.ID
@@ -720,7 +770,7 @@ func (p *Platform) DoRegister(ctx context.Context) error {
// 设置传输协议
req.SetTransport(strings.ToUpper(p.PlatformModel.Transport))
- tx, err := p.Client.TransactionRequest(ctx, req, sipgo.ClientRequestAddVia)
+ tx, err := p.Client.TransactionRequest(ctx, req)
if err != nil {
p.Error("register", "error", err.Error())
return fmt.Errorf("创建事务失败: %v", err)