fix: catalog get channellist

This commit is contained in:
pg
2025-03-03 09:23:57 +08:00
committed by pggiroro
parent 8c47c5b513
commit 0cf80cedbf
3 changed files with 261 additions and 211 deletions

View File

@@ -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 构建通道信息

View File

@@ -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 // 国标-信令安全模式

View File

@@ -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(`<?xml version="1.0" encoding="GB2312"?>
// 添加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(`<?xml version="1.0" encoding="GB2312"?>
<Response>
<CmdType>Catalog</CmdType>
<SN>%s</SN>
<DeviceID>%s</DeviceID>
<SumNum>0</SumNum>
<DeviceList Num="0">
</DeviceList>
</Response>`, 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(`<?xml version="1.0" encoding="GB2312"?>
<Response>
<CmdType>Catalog</CmdType>
<SN>%s</SN>
<DeviceID>%s</DeviceID>
<SumNum>%d</SumNum>
<DeviceList Num="%d">
<DeviceList Num="1">
%s
</DeviceList>
</Response>`, sn, p.PlatformModel.DeviceGBID, len(channels), len(channels), p.buildChannelList(channels))))
_, err := p.Client.Do(p, request)
return err
</Response>`, 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(`<?xml version="1.0" encoding="UTF-8"?>
<Response>
<CmdType>Catalog</CmdType>
<SN>%s</SN>
<DeviceChannelList Num="0">
</DeviceChannelList>
</Response>`, 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(`<Item>
<DeviceID>%s</DeviceID>
<Name>%s</Name>
<Manufacturer>%s</Manufacturer>
<Model>%s</Model>
<Owner>%s</Owner>
<Address>%s</Address>
<RegisterWay>%d</RegisterWay>
<Secrecy>%d</Secrecy>
<ParentID>%s</ParentID>
<Parental>%d</Parental>
<SafetyWay>%d</SafetyWay>
<Status>ON</Status>
<Info>
</Info>
</Item>`, 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(`<Item>
<DeviceID>%s</DeviceID>
<Name>%s</Name>
<Manufacturer>%s</Manufacturer>
<Model>%s</Model>
<Owner>%s</Owner>
<Address>%s</Address>
<RegisterWay>%d</RegisterWay>
<Secrecy>%d</Secrecy>
<ParentID>%s</ParentID>
<Parental>%d</Parental>
<SafetyWay>%d</SafetyWay>
<Status>ON</Status>
<Info>
</Info>
</Item>
`, 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)