feature: add platform and ready to send register to server

This commit is contained in:
pg
2025-02-14 14:43:33 +08:00
committed by pggiroro
parent 827a0f3fc1
commit bb92152c15
9 changed files with 2802 additions and 500 deletions

View File

@@ -5,8 +5,10 @@ import (
"fmt"
"net/http"
"os"
"strconv"
"strings"
"sync"
"time"
"github.com/emiago/sipgo"
"github.com/emiago/sipgo/sip"
@@ -451,3 +453,414 @@ func (gb *GB28181ProPlugin) StartPlay(ctx context.Context, req *pb.PlayRequest)
gb.Info("StartPlay success", "deviceId", req.DeviceId, "channelId", req.ChannelId, "ssrc", ssrc)
return resp, nil
}
// AddPlatform 实现添加平台信息
func (gb *GB28181ProPlugin) AddPlatform(ctx context.Context, req *pb.Platform) (*pb.BaseResponse, error) {
resp := &pb.BaseResponse{}
if gb.DB == nil {
resp.Code = 500
resp.Message = "database not initialized"
return resp, nil
}
// 必填字段校验
if req.Name == "" {
resp.Code = 400
resp.Message = "平台名称不可为空"
return resp, nil
}
if req.ServerGBId == "" {
resp.Code = 400
resp.Message = "上级平台国标编号不可为空"
return resp, nil
}
if req.ServerIp == "" {
resp.Code = 400
resp.Message = "上级平台IP不可为空"
return resp, nil
}
if req.ServerPort <= 0 || req.ServerPort > 65535 {
resp.Code = 400
resp.Message = "上级平台端口异常"
return resp, nil
}
if req.DeviceGBId == "" {
resp.Code = 400
resp.Message = "本平台国标编号不可为空"
return resp, nil
}
// 检查平台是否已存在
var existingPlatform gb28181.Platform
if err := gb.DB.Where("server_gb_id = ?", req.ServerGBId).First(&existingPlatform).Error; err == nil {
resp.Code = 400
resp.Message = fmt.Sprintf("平台 %s 已存在", req.ServerGBId)
return resp, nil
}
// 设置默认值
if req.ServerGBDomain == "" {
req.ServerGBDomain = req.ServerGBId[:6] // 取前6位作为域
}
if req.Expires <= 0 {
req.Expires = 3600 // 默认3600秒
}
if req.KeepTimeout <= 0 {
req.KeepTimeout = 60 // 默认60秒
}
if req.Transport == "" {
req.Transport = "UDP" // 默认UDP
}
if req.CharacterSet == "" {
req.CharacterSet = "GB2312" // 默认GB2312
}
// 设置创建时间和更新时间
currentTime := time.Now().Format("2006-01-02 15:04:05")
req.CreateTime = currentTime
req.UpdateTime = currentTime
// 将proto消息转换为数据库模型
platform := &gb28181.Platform{
Enable: req.Enable,
Name: req.Name,
ServerGBID: req.ServerGBId,
ServerGBDomain: req.ServerGBDomain,
ServerIP: req.ServerIp,
ServerPort: int(req.ServerPort),
DeviceGBID: req.DeviceGBId,
DeviceIP: req.DeviceIp,
DevicePort: int(req.DevicePort),
Username: req.Username,
Password: req.Password,
Expires: int(req.Expires),
KeepTimeout: int(req.KeepTimeout),
Transport: req.Transport,
CharacterSet: req.CharacterSet,
PTZ: req.Ptz,
RTCP: req.Rtcp,
Status: req.Status,
ChannelCount: int(req.ChannelCount),
CatalogSubscribe: req.CatalogSubscribe,
AlarmSubscribe: req.AlarmSubscribe,
MobilePositionSubscribe: req.MobilePositionSubscribe,
CatalogGroup: int(req.CatalogGroup),
UpdateTime: req.UpdateTime,
CreateTime: req.CreateTime,
AsMessageChannel: req.AsMessageChannel,
SendStreamIP: req.SendStreamIp,
AutoPushChannel: &req.AutoPushChannel,
CatalogWithPlatform: int(req.CatalogWithPlatform),
CatalogWithGroup: int(req.CatalogWithGroup),
CatalogWithRegion: int(req.CatalogWithRegion),
CivilCode: req.CivilCode,
Manufacturer: req.Manufacturer,
Model: req.Model,
Address: req.Address,
RegisterWay: int(req.RegisterWay),
Secrecy: int(req.Secrecy),
}
// 保存到数据库
if err := gb.DB.Create(platform).Error; err != nil {
resp.Code = 500
resp.Message = fmt.Sprintf("failed to create platform: %v", err)
return resp, nil
}
// 如果平台启用,则启动注册任务
if platform.Enable {
// 获取本地SIP端口
localPort := 5060 // 默认端口
if len(gb.Sip.ListenAddr) > 0 {
if port, err := strconv.Atoi(strings.Split(gb.Sip.ListenAddr[0], ":")[1]); err == nil {
localPort = port
}
}
// 创建平台命令器
commander := gb28181.NewSIPPlatformCommander(platform, gb.GetPublicIP(platform.ServerIP), localPort)
if err := commander.InitializeSIPClient(gb.ua); err != nil {
gb.Error("初始化SIP客户端失败", "error", err)
resp.Code = 500
resp.Message = fmt.Sprintf("初始化SIP客户端失败: %v", err)
return resp, nil
}
// 启动注册任务
commander.StartRegisterTask(gb)
}
resp.Code = 0
resp.Message = "success"
return resp, nil
}
// GetPlatform 实现获取平台信息
func (gb *GB28181ProPlugin) GetPlatform(ctx context.Context, req *pb.GetPlatformRequest) (*pb.PlatformResponse, error) {
resp := &pb.PlatformResponse{}
if gb.DB == nil {
resp.Code = 500
resp.Message = "database not initialized"
return resp, nil
}
var platform gb28181.Platform
if err := gb.DB.First(&platform, req.Id).Error; err != nil {
resp.Code = 404
resp.Message = "platform not found"
return resp, nil
}
// 将数据库模型转换为proto消息
resp.Data = &pb.Platform{
Id: int32(platform.ID),
Enable: platform.Enable,
Name: platform.Name,
ServerGBId: platform.ServerGBID,
ServerGBDomain: platform.ServerGBDomain,
ServerIp: platform.ServerIP,
ServerPort: int32(platform.ServerPort),
DeviceGBId: platform.DeviceGBID,
DeviceIp: platform.DeviceIP,
DevicePort: int32(platform.DevicePort),
Username: platform.Username,
Password: platform.Password,
Expires: int32(platform.Expires),
KeepTimeout: int32(platform.KeepTimeout),
Transport: platform.Transport,
CharacterSet: platform.CharacterSet,
Ptz: platform.PTZ,
Rtcp: platform.RTCP,
Status: platform.Status,
ChannelCount: int32(platform.ChannelCount),
CatalogSubscribe: platform.CatalogSubscribe,
AlarmSubscribe: platform.AlarmSubscribe,
MobilePositionSubscribe: platform.MobilePositionSubscribe,
CatalogGroup: int32(platform.CatalogGroup),
UpdateTime: platform.UpdateTime,
CreateTime: platform.CreateTime,
AsMessageChannel: platform.AsMessageChannel,
SendStreamIp: platform.SendStreamIP,
AutoPushChannel: platform.AutoPushChannel != nil && *platform.AutoPushChannel,
CatalogWithPlatform: int32(platform.CatalogWithPlatform),
CatalogWithGroup: int32(platform.CatalogWithGroup),
CatalogWithRegion: int32(platform.CatalogWithRegion),
CivilCode: platform.CivilCode,
Manufacturer: platform.Manufacturer,
Model: platform.Model,
Address: platform.Address,
RegisterWay: int32(platform.RegisterWay),
Secrecy: int32(platform.Secrecy),
}
resp.Code = 0
resp.Message = "success"
return resp, nil
}
// UpdatePlatform 实现更新平台信息
func (gb *GB28181ProPlugin) UpdatePlatform(ctx context.Context, req *pb.Platform) (*pb.BaseResponse, error) {
resp := &pb.BaseResponse{}
if gb.DB == nil {
resp.Code = 500
resp.Message = "database not initialized"
return resp, nil
}
// 检查平台是否存在
var platform gb28181.Platform
if err := gb.DB.First(&platform, req.Id).Error; err != nil {
resp.Code = 404
resp.Message = "platform not found"
return resp, nil
}
// 记录之前的启用状态
wasEnabled := platform.Enable
// 更新平台信息
platform.Enable = req.Enable
platform.Name = req.Name
platform.ServerGBID = req.ServerGBId
platform.ServerGBDomain = req.ServerGBDomain
platform.ServerIP = req.ServerIp
platform.ServerPort = int(req.ServerPort)
platform.DeviceGBID = req.DeviceGBId
platform.DeviceIP = req.DeviceIp
platform.DevicePort = int(req.DevicePort)
platform.Username = req.Username
platform.Password = req.Password
platform.Expires = int(req.Expires)
platform.KeepTimeout = int(req.KeepTimeout)
platform.Transport = req.Transport
platform.CharacterSet = req.CharacterSet
platform.PTZ = req.Ptz
platform.RTCP = req.Rtcp
platform.Status = req.Status
platform.ChannelCount = int(req.ChannelCount)
platform.CatalogSubscribe = req.CatalogSubscribe
platform.AlarmSubscribe = req.AlarmSubscribe
platform.MobilePositionSubscribe = req.MobilePositionSubscribe
platform.CatalogGroup = int(req.CatalogGroup)
platform.UpdateTime = req.UpdateTime
platform.AsMessageChannel = req.AsMessageChannel
platform.SendStreamIP = req.SendStreamIp
platform.AutoPushChannel = &req.AutoPushChannel
platform.CatalogWithPlatform = int(req.CatalogWithPlatform)
platform.CatalogWithGroup = int(req.CatalogWithGroup)
platform.CatalogWithRegion = int(req.CatalogWithRegion)
platform.CivilCode = req.CivilCode
platform.Manufacturer = req.Manufacturer
platform.Model = req.Model
platform.Address = req.Address
platform.RegisterWay = int(req.RegisterWay)
platform.Secrecy = int(req.Secrecy)
if err := gb.DB.Save(&platform).Error; err != nil {
resp.Code = 500
resp.Message = fmt.Sprintf("failed to update platform: %v", err)
return resp, nil
}
// 处理平台启用状态变化
if !wasEnabled && platform.Enable {
// 获取本地SIP端口
localPort := 5060 // 默认端口
if len(gb.Sip.ListenAddr) > 0 {
if port, err := strconv.Atoi(strings.Split(gb.Sip.ListenAddr[0], ":")[1]); err == nil {
localPort = port
}
}
// 平台从禁用变为启用,启动注册任务
commander := gb28181.NewSIPPlatformCommander(&platform, gb.GetPublicIP(platform.ServerIP), localPort)
if err := commander.InitializeSIPClient(gb.ua); err != nil {
gb.Error("初始化SIP客户端失败", "error", err)
resp.Code = 500
resp.Message = fmt.Sprintf("初始化SIP客户端失败: %v", err)
return resp, nil
}
commander.StartRegisterTask(gb)
} else if wasEnabled && !platform.Enable {
// TODO: 平台从启用变为禁用,需要处理注销逻辑
// 这里可以添加注销相关的代码
}
resp.Code = 0
resp.Message = "success"
return resp, nil
}
// DeletePlatform 实现删除平台信息
func (gb *GB28181ProPlugin) DeletePlatform(ctx context.Context, req *pb.DeletePlatformRequest) (*pb.BaseResponse, error) {
resp := &pb.BaseResponse{}
if gb.DB == nil {
resp.Code = 500
resp.Message = "database not initialized"
return resp, nil
}
// 删除平台
if err := gb.DB.Delete(&gb28181.Platform{}, req.Id).Error; err != nil {
resp.Code = 500
resp.Message = fmt.Sprintf("failed to delete platform: %v", err)
return resp, nil
}
resp.Code = 0
resp.Message = "success"
return resp, nil
}
// ListPlatforms 实现获取平台列表
func (gb *GB28181ProPlugin) ListPlatforms(ctx context.Context, req *pb.ListPlatformsRequest) (*pb.PlatformsPageInfo, error) {
resp := &pb.PlatformsPageInfo{}
if gb.DB == nil {
resp.Code = 500
resp.Message = "database not initialized"
return resp, nil
}
var platforms []gb28181.Platform
var total int64
// 构建查询条件
query := gb.DB.Model(&gb28181.Platform{})
if req.Query != "" {
query = query.Where("name LIKE ? OR server_gb_id LIKE ? OR device_gb_id LIKE ?",
"%"+req.Query+"%", "%"+req.Query+"%", "%"+req.Query+"%")
}
if req.Status {
query = query.Where("status = ?", true)
}
// 获取总数
if err := query.Count(&total).Error; err != nil {
resp.Code = 500
resp.Message = fmt.Sprintf("failed to count platforms: %v", err)
return resp, nil
}
// 分页查询
if err := query.Offset(int(req.Page-1) * int(req.Count)).
Limit(int(req.Count)).
Find(&platforms).Error; err != nil {
resp.Code = 500
resp.Message = fmt.Sprintf("failed to list platforms: %v", err)
return resp, nil
}
// 转换为proto消息
var pbPlatforms []*pb.Platform
for _, p := range platforms {
pbPlatforms = append(pbPlatforms, &pb.Platform{
Id: int32(p.ID),
Enable: p.Enable,
Name: p.Name,
ServerGBId: p.ServerGBID,
ServerGBDomain: p.ServerGBDomain,
ServerIp: p.ServerIP,
ServerPort: int32(p.ServerPort),
DeviceGBId: p.DeviceGBID,
DeviceIp: p.DeviceIP,
DevicePort: int32(p.DevicePort),
Username: p.Username,
Password: p.Password,
Expires: int32(p.Expires),
KeepTimeout: int32(p.KeepTimeout),
Transport: p.Transport,
CharacterSet: p.CharacterSet,
Ptz: p.PTZ,
Rtcp: p.RTCP,
Status: p.Status,
ChannelCount: int32(p.ChannelCount),
CatalogSubscribe: p.CatalogSubscribe,
AlarmSubscribe: p.AlarmSubscribe,
MobilePositionSubscribe: p.MobilePositionSubscribe,
CatalogGroup: int32(p.CatalogGroup),
UpdateTime: p.UpdateTime,
CreateTime: p.CreateTime,
AsMessageChannel: p.AsMessageChannel,
SendStreamIp: p.SendStreamIP,
AutoPushChannel: p.AutoPushChannel != nil && *p.AutoPushChannel,
CatalogWithPlatform: int32(p.CatalogWithPlatform),
CatalogWithGroup: int32(p.CatalogWithGroup),
CatalogWithRegion: int32(p.CatalogWithRegion),
CivilCode: p.CivilCode,
Manufacturer: p.Manufacturer,
Model: p.Model,
Address: p.Address,
RegisterWay: int32(p.RegisterWay),
Secrecy: int32(p.Secrecy),
})
}
resp.Total = int32(total)
resp.List = pbPlatforms
resp.Code = 0
resp.Message = "success"
return resp, nil
}

View File

@@ -74,6 +74,7 @@ type Device struct {
fromHDR sip.FromHeader
toHDR sip.ToHeader
plugin *GB28181ProPlugin
abc *sip.ClientTransaction
}
func (d *Device) TableName() string {

View File

@@ -143,7 +143,7 @@ type GB28181ProPlugin struct {
m7s.Plugin
AutoInvite bool `default:"true" desc:"自动邀请"`
Serial string `default:"34020000002000000001" desc:"sip 服务 id"` //sip 服务器 id, 默认 34020000002000000001
Realm string `default:"3402000000" desc:"sip 服务域"` //sip 服务器域,默认 3402000000
Realm string `default:"3402000000" desc:"sip 服务域"` //sip 服务器域,默认 3402000000
Username string
Password string
Sip SipConfig
@@ -208,6 +208,7 @@ func (gb *GB28181ProPlugin) OnInit() (err error) {
if gb.DB != nil {
gb.DB.AutoMigrate(&Device{})
gb.DB.AutoMigrate(&gb28181.ChannelInfo{})
gb.DB.AutoMigrate(&gb28181.Platform{})
}
}
if gb.Parent != "" {

File diff suppressed because it is too large Load Diff

View File

@@ -1342,6 +1342,198 @@ func local_request_Api_GetRawChannel_0(ctx context.Context, marshaler runtime.Ma
}
func request_Api_AddPlatform_0(ctx context.Context, marshaler runtime.Marshaler, client ApiClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq Platform
var metadata runtime.ServerMetadata
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.AddPlatform(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Api_AddPlatform_0(ctx context.Context, marshaler runtime.Marshaler, server ApiServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq Platform
var metadata runtime.ServerMetadata
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.AddPlatform(ctx, &protoReq)
return msg, metadata, err
}
func request_Api_GetPlatform_0(ctx context.Context, marshaler runtime.Marshaler, client ApiClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq GetPlatformRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.Id, err = runtime.Int32(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := client.GetPlatform(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Api_GetPlatform_0(ctx context.Context, marshaler runtime.Marshaler, server ApiServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq GetPlatformRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.Id, err = runtime.Int32(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := server.GetPlatform(ctx, &protoReq)
return msg, metadata, err
}
func request_Api_UpdatePlatform_0(ctx context.Context, marshaler runtime.Marshaler, client ApiClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq Platform
var metadata runtime.ServerMetadata
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.UpdatePlatform(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Api_UpdatePlatform_0(ctx context.Context, marshaler runtime.Marshaler, server ApiServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq Platform
var metadata runtime.ServerMetadata
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil && err != io.EOF {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.UpdatePlatform(ctx, &protoReq)
return msg, metadata, err
}
func request_Api_DeletePlatform_0(ctx context.Context, marshaler runtime.Marshaler, client ApiClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq DeletePlatformRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.Id, err = runtime.Int32(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := client.DeletePlatform(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Api_DeletePlatform_0(ctx context.Context, marshaler runtime.Marshaler, server ApiServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq DeletePlatformRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.Id, err = runtime.Int32(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := server.DeletePlatform(ctx, &protoReq)
return msg, metadata, err
}
var (
filter_Api_ListPlatforms_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
)
func request_Api_ListPlatforms_0(ctx context.Context, marshaler runtime.Marshaler, client ApiClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq ListPlatformsRequest
var metadata runtime.ServerMetadata
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Api_ListPlatforms_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.ListPlatforms(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Api_ListPlatforms_0(ctx context.Context, marshaler runtime.Marshaler, server ApiServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq ListPlatformsRequest
var metadata runtime.ServerMetadata
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Api_ListPlatforms_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.ListPlatforms(ctx, &protoReq)
return msg, metadata, err
}
// RegisterApiHandlerServer registers the http handlers for service Api to "mux".
// UnaryRPC :call ApiServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
@@ -1949,6 +2141,131 @@ func RegisterApiHandlerServer(ctx context.Context, mux *runtime.ServeMux, server
})
mux.Handle("POST", pattern_Api_AddPlatform_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gb28181pro.Api/AddPlatform", runtime.WithHTTPPathPattern("/gb28181/api/platform/add"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Api_AddPlatform_0(annotatedContext, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_Api_AddPlatform_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Api_GetPlatform_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gb28181pro.Api/GetPlatform", runtime.WithHTTPPathPattern("/gb28181/api/platform/{id}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Api_GetPlatform_0(annotatedContext, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_Api_GetPlatform_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_Api_UpdatePlatform_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gb28181pro.Api/UpdatePlatform", runtime.WithHTTPPathPattern("/gb28181/api/platform/update"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Api_UpdatePlatform_0(annotatedContext, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_Api_UpdatePlatform_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("DELETE", pattern_Api_DeletePlatform_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gb28181pro.Api/DeletePlatform", runtime.WithHTTPPathPattern("/gb28181/api/platform/{id}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Api_DeletePlatform_0(annotatedContext, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_Api_DeletePlatform_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Api_ListPlatforms_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/gb28181pro.Api/ListPlatforms", runtime.WithHTTPPathPattern("/gb28181/api/platform/list"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Api_ListPlatforms_0(annotatedContext, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_Api_ListPlatforms_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
@@ -2518,6 +2835,116 @@ func RegisterApiHandlerClient(ctx context.Context, mux *runtime.ServeMux, client
})
mux.Handle("POST", pattern_Api_AddPlatform_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gb28181pro.Api/AddPlatform", runtime.WithHTTPPathPattern("/gb28181/api/platform/add"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Api_AddPlatform_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_Api_AddPlatform_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Api_GetPlatform_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gb28181pro.Api/GetPlatform", runtime.WithHTTPPathPattern("/gb28181/api/platform/{id}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Api_GetPlatform_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_Api_GetPlatform_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_Api_UpdatePlatform_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gb28181pro.Api/UpdatePlatform", runtime.WithHTTPPathPattern("/gb28181/api/platform/update"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Api_UpdatePlatform_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_Api_UpdatePlatform_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("DELETE", pattern_Api_DeletePlatform_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gb28181pro.Api/DeletePlatform", runtime.WithHTTPPathPattern("/gb28181/api/platform/{id}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Api_DeletePlatform_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_Api_DeletePlatform_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Api_ListPlatforms_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
var err error
var annotatedContext context.Context
annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/gb28181pro.Api/ListPlatforms", runtime.WithHTTPPathPattern("/gb28181/api/platform/list"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Api_ListPlatforms_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_Api_ListPlatforms_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
@@ -2569,6 +2996,16 @@ var (
pattern_Api_GetAllSSRC_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"gb28181", "api", "play", "ssrc"}, ""))
pattern_Api_GetRawChannel_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"gb28181", "api", "channel", "raw"}, ""))
pattern_Api_AddPlatform_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"gb28181", "api", "platform", "add"}, ""))
pattern_Api_GetPlatform_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"gb28181", "api", "platform", "id"}, ""))
pattern_Api_UpdatePlatform_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"gb28181", "api", "platform", "update"}, ""))
pattern_Api_DeletePlatform_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"gb28181", "api", "platform", "id"}, ""))
pattern_Api_ListPlatforms_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"gb28181", "api", "platform", "list"}, ""))
)
var (
@@ -2619,4 +3056,14 @@ var (
forward_Api_GetAllSSRC_0 = runtime.ForwardResponseMessage
forward_Api_GetRawChannel_0 = runtime.ForwardResponseMessage
forward_Api_AddPlatform_0 = runtime.ForwardResponseMessage
forward_Api_GetPlatform_0 = runtime.ForwardResponseMessage
forward_Api_UpdatePlatform_0 = runtime.ForwardResponseMessage
forward_Api_DeletePlatform_0 = runtime.ForwardResponseMessage
forward_Api_ListPlatforms_0 = runtime.ForwardResponseMessage
)

View File

@@ -184,6 +184,43 @@ service api {
get: "/gb28181/api/channel/raw"
};
}
// 添加平台信息
rpc AddPlatform (Platform) returns (BaseResponse) {
option (google.api.http) = {
post: "/gb28181/api/platform/add"
body: "*"
};
}
// 获取平台信息
rpc GetPlatform (GetPlatformRequest) returns (PlatformResponse) {
option (google.api.http) = {
get: "/gb28181/api/platform/{id}"
};
}
// 更新平台信息
rpc UpdatePlatform (Platform) returns (BaseResponse) {
option (google.api.http) = {
post: "/gb28181/api/platform/update"
body: "*"
};
}
// 删除平台信息
rpc DeletePlatform (DeletePlatformRequest) returns (BaseResponse) {
option (google.api.http) = {
delete: "/gb28181/api/platform/{id}"
};
}
// 获取平台列表
rpc ListPlatforms (ListPlatformsRequest) returns (PlatformsPageInfo) {
option (google.api.http) = {
get: "/gb28181/api/platform/list"
};
}
}
// 请求和响应消息定义
@@ -431,4 +468,79 @@ message SSRCListResponse {
string message = 2;
repeated SSRCInfo data = 3;
int32 count = 4;
}
// Platform消息定义
message Platform {
int32 id = 1; // ID(数据库中)
bool enable = 2; // 是否启用
string name = 3; // 名称
string serverGBId = 4; // SIP服务国标编码
string serverGBDomain = 5; // SIP服务国标域
string serverIp = 6; // SIP服务IP
int32 serverPort = 7; // SIP服务端口
string deviceGBId = 8; // 设备国标编号
string deviceIp = 9; // 设备ip
int32 devicePort = 10; // 设备端口
string username = 11; // SIP认证用户名
string password = 12; // SIP认证密码
int32 expires = 13; // 注册周期(秒)
int32 keepTimeout = 14; // 心跳周期(秒)
string transport = 15; // 传输协议
string characterSet = 16; // 字符集
bool ptz = 17; // 允许云台控制
bool rtcp = 18; // RTCP流保活
bool status = 19; // 在线状态
int32 channelCount = 20; // 通道数量
bool catalogSubscribe = 21; // 已被订阅目录信息
bool alarmSubscribe = 22; // 已被订阅报警信息
bool mobilePositionSubscribe = 23; // 已被订阅移动位置信息
int32 catalogGroup = 24; // 目录分组大小
string updateTime = 25; // 最后更新时间
string createTime = 26; // 创建时间
bool asMessageChannel = 27; // 是否作为消息通道
string sendStreamIp = 28; // 点播回复200OK使用的IP
bool autoPushChannel = 29; // 是否自动推送通道变化
int32 catalogWithPlatform = 30; // 目录信息包含平台信息
int32 catalogWithGroup = 31; // 目录信息包含分组信息
int32 catalogWithRegion = 32; // 目录信息包含行政区划
string civilCode = 33; // 行政区划代码
string manufacturer = 34; // 平台厂商
string model = 35; // 平台型号
string address = 36; // 平台安装地址
int32 registerWay = 37; // 注册方式
int32 secrecy = 38; // 保密属性
}
// 获取平台请求
message GetPlatformRequest {
int32 id = 1;
}
// 删除平台请求
message DeletePlatformRequest {
int32 id = 1;
}
// 平台列表请求
message ListPlatformsRequest {
int32 page = 1;
int32 count = 2;
string query = 3;
bool status = 4;
}
// 平台响应
message PlatformResponse {
int32 code = 1;
string message = 2;
Platform data = 3;
}
// 平台分页信息
message PlatformsPageInfo {
int32 code = 1;
string message = 2;
int32 total = 3;
repeated Platform list = 4;
}

View File

@@ -46,6 +46,11 @@ const (
Api_StopBroadcast_FullMethodName = "/gb28181pro.api/StopBroadcast"
Api_GetAllSSRC_FullMethodName = "/gb28181pro.api/GetAllSSRC"
Api_GetRawChannel_FullMethodName = "/gb28181pro.api/GetRawChannel"
Api_AddPlatform_FullMethodName = "/gb28181pro.api/AddPlatform"
Api_GetPlatform_FullMethodName = "/gb28181pro.api/GetPlatform"
Api_UpdatePlatform_FullMethodName = "/gb28181pro.api/UpdatePlatform"
Api_DeletePlatform_FullMethodName = "/gb28181pro.api/DeletePlatform"
Api_ListPlatforms_FullMethodName = "/gb28181pro.api/ListPlatforms"
)
// ApiClient is the client API for Api service.
@@ -100,6 +105,16 @@ type ApiClient interface {
GetAllSSRC(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*SSRCListResponse, error)
// 国标通道编辑时的数据回显
GetRawChannel(ctx context.Context, in *GetRawChannelRequest, opts ...grpc.CallOption) (*Channel, error)
// 添加平台信息
AddPlatform(ctx context.Context, in *Platform, opts ...grpc.CallOption) (*BaseResponse, error)
// 获取平台信息
GetPlatform(ctx context.Context, in *GetPlatformRequest, opts ...grpc.CallOption) (*PlatformResponse, error)
// 更新平台信息
UpdatePlatform(ctx context.Context, in *Platform, opts ...grpc.CallOption) (*BaseResponse, error)
// 删除平台信息
DeletePlatform(ctx context.Context, in *DeletePlatformRequest, opts ...grpc.CallOption) (*BaseResponse, error)
// 获取平台列表
ListPlatforms(ctx context.Context, in *ListPlatformsRequest, opts ...grpc.CallOption) (*PlatformsPageInfo, error)
}
type apiClient struct {
@@ -350,6 +365,56 @@ func (c *apiClient) GetRawChannel(ctx context.Context, in *GetRawChannelRequest,
return out, nil
}
func (c *apiClient) AddPlatform(ctx context.Context, in *Platform, opts ...grpc.CallOption) (*BaseResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(BaseResponse)
err := c.cc.Invoke(ctx, Api_AddPlatform_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *apiClient) GetPlatform(ctx context.Context, in *GetPlatformRequest, opts ...grpc.CallOption) (*PlatformResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(PlatformResponse)
err := c.cc.Invoke(ctx, Api_GetPlatform_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *apiClient) UpdatePlatform(ctx context.Context, in *Platform, opts ...grpc.CallOption) (*BaseResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(BaseResponse)
err := c.cc.Invoke(ctx, Api_UpdatePlatform_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *apiClient) DeletePlatform(ctx context.Context, in *DeletePlatformRequest, opts ...grpc.CallOption) (*BaseResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(BaseResponse)
err := c.cc.Invoke(ctx, Api_DeletePlatform_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *apiClient) ListPlatforms(ctx context.Context, in *ListPlatformsRequest, opts ...grpc.CallOption) (*PlatformsPageInfo, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(PlatformsPageInfo)
err := c.cc.Invoke(ctx, Api_ListPlatforms_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// ApiServer is the server API for Api service.
// All implementations must embed UnimplementedApiServer
// for forward compatibility.
@@ -402,6 +467,16 @@ type ApiServer interface {
GetAllSSRC(context.Context, *emptypb.Empty) (*SSRCListResponse, error)
// 国标通道编辑时的数据回显
GetRawChannel(context.Context, *GetRawChannelRequest) (*Channel, error)
// 添加平台信息
AddPlatform(context.Context, *Platform) (*BaseResponse, error)
// 获取平台信息
GetPlatform(context.Context, *GetPlatformRequest) (*PlatformResponse, error)
// 更新平台信息
UpdatePlatform(context.Context, *Platform) (*BaseResponse, error)
// 删除平台信息
DeletePlatform(context.Context, *DeletePlatformRequest) (*BaseResponse, error)
// 获取平台列表
ListPlatforms(context.Context, *ListPlatformsRequest) (*PlatformsPageInfo, error)
mustEmbedUnimplementedApiServer()
}
@@ -484,6 +559,21 @@ func (UnimplementedApiServer) GetAllSSRC(context.Context, *emptypb.Empty) (*SSRC
func (UnimplementedApiServer) GetRawChannel(context.Context, *GetRawChannelRequest) (*Channel, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetRawChannel not implemented")
}
func (UnimplementedApiServer) AddPlatform(context.Context, *Platform) (*BaseResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method AddPlatform not implemented")
}
func (UnimplementedApiServer) GetPlatform(context.Context, *GetPlatformRequest) (*PlatformResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetPlatform not implemented")
}
func (UnimplementedApiServer) UpdatePlatform(context.Context, *Platform) (*BaseResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdatePlatform not implemented")
}
func (UnimplementedApiServer) DeletePlatform(context.Context, *DeletePlatformRequest) (*BaseResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method DeletePlatform not implemented")
}
func (UnimplementedApiServer) ListPlatforms(context.Context, *ListPlatformsRequest) (*PlatformsPageInfo, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListPlatforms not implemented")
}
func (UnimplementedApiServer) mustEmbedUnimplementedApiServer() {}
func (UnimplementedApiServer) testEmbeddedByValue() {}
@@ -937,6 +1027,96 @@ func _Api_GetRawChannel_Handler(srv interface{}, ctx context.Context, dec func(i
return interceptor(ctx, in, info, handler)
}
func _Api_AddPlatform_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Platform)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ApiServer).AddPlatform(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Api_AddPlatform_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ApiServer).AddPlatform(ctx, req.(*Platform))
}
return interceptor(ctx, in, info, handler)
}
func _Api_GetPlatform_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetPlatformRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ApiServer).GetPlatform(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Api_GetPlatform_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ApiServer).GetPlatform(ctx, req.(*GetPlatformRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Api_UpdatePlatform_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Platform)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ApiServer).UpdatePlatform(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Api_UpdatePlatform_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ApiServer).UpdatePlatform(ctx, req.(*Platform))
}
return interceptor(ctx, in, info, handler)
}
func _Api_DeletePlatform_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DeletePlatformRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ApiServer).DeletePlatform(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Api_DeletePlatform_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ApiServer).DeletePlatform(ctx, req.(*DeletePlatformRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Api_ListPlatforms_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListPlatformsRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ApiServer).ListPlatforms(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Api_ListPlatforms_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ApiServer).ListPlatforms(ctx, req.(*ListPlatformsRequest))
}
return interceptor(ctx, in, info, handler)
}
// Api_ServiceDesc is the grpc.ServiceDesc for Api service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
@@ -1040,6 +1220,26 @@ var Api_ServiceDesc = grpc.ServiceDesc{
MethodName: "GetRawChannel",
Handler: _Api_GetRawChannel_Handler,
},
{
MethodName: "AddPlatform",
Handler: _Api_AddPlatform_Handler,
},
{
MethodName: "GetPlatform",
Handler: _Api_GetPlatform_Handler,
},
{
MethodName: "UpdatePlatform",
Handler: _Api_UpdatePlatform_Handler,
},
{
MethodName: "DeletePlatform",
Handler: _Api_DeletePlatform_Handler,
},
{
MethodName: "ListPlatforms",
Handler: _Api_ListPlatforms_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "gb28181.proto",

View File

@@ -0,0 +1,112 @@
// Package gb28181 实现了GB28181协议相关的功能
package gb28181
import (
"github.com/emiago/sipgo"
"github.com/emiago/sipgo/sip"
)
// Platform 表示GB28181平台的配置信息。
// 包含了平台的基本信息、SIP服务配置、设备信息、认证信息等。
// 用于存储和管理GB28181平台的所有相关参数。
type Platform struct {
ID int `gorm:"primaryKey;autoIncrement" json:"id"` // ID表示数据库中的唯一标识符
Enable bool `gorm:"column:enable" json:"enable"` // Enable表示该平台配置是否启用
Name string `gorm:"column:name" json:"name"` // Name表示平台的名称
ServerGBID string `gorm:"column:server_gb_id" json:"serverGBId"` // ServerGBID表示SIP服务器的国标编码
ServerGBDomain string `gorm:"column:server_gb_domain" json:"serverGBDomain"` // ServerGBDomain表示SIP服务器的国标域
ServerIP string `gorm:"column:server_ip" json:"serverIp"` // ServerIP表示SIP服务器的IP地址
ServerPort int `gorm:"column:server_port" json:"serverPort"` // ServerPort表示SIP服务器的端口号
DeviceGBID string `gorm:"column:device_gb_id" json:"deviceGBId"` // DeviceGBID表示设备的国标编号
DeviceIP string `gorm:"column:device_ip" json:"deviceIp"` // DeviceIP表示设备的IP地址
DevicePort int `gorm:"column:device_port" json:"devicePort"` // DevicePort表示设备的端口号
Username string `gorm:"column:username" json:"username"` // Username表示SIP认证的用户名默认使用设备国标编号
Password string `gorm:"column:password" json:"password"` // Password表示SIP认证的密码
Expires int `gorm:"column:expires" json:"expires"` // Expires表示注册的过期时间单位为秒
KeepTimeout int `gorm:"column:keep_timeout" json:"keepTimeout"` // KeepTimeout表示心跳超时时间单位为秒
Transport string `gorm:"column:transport" json:"transport"` // Transport表示传输协议类型
CharacterSet string `gorm:"column:character_set" json:"characterSet"` // CharacterSet表示字符集编码
PTZ bool `gorm:"column:ptz" json:"ptz"` // PTZ表示是否允许云台控制
RTCP bool `gorm:"column:rtcp" json:"rtcp"` // RTCP表示是否启用RTCP流保活
Status bool `gorm:"column:status" json:"status"` // Status表示平台当前的在线状态
ChannelCount int `gorm:"column:channel_count" json:"channelCount"` // ChannelCount表示通道数量
CatalogSubscribe bool `gorm:"column:catalog_subscribe" json:"catalogSubscribe"` // CatalogSubscribe表示是否已订阅目录信息
AlarmSubscribe bool `gorm:"column:alarm_subscribe" json:"alarmSubscribe"` // AlarmSubscribe表示是否已订阅报警信息
MobilePositionSubscribe bool `gorm:"column:mobile_position_subscribe" json:"mobilePositionSubscribe"` // MobilePositionSubscribe表示是否已订阅移动位置信息
CatalogGroup int `gorm:"column:catalog_group" json:"catalogGroup"` // CatalogGroup表示目录分组大小每次向上级发送通道数量
UpdateTime string `gorm:"column:update_time" json:"updateTime"` // UpdateTime表示最后更新时间
CreateTime string `gorm:"column:create_time" json:"createTime"` // CreateTime表示创建时间
AsMessageChannel bool `gorm:"column:as_message_channel" json:"asMessageChannel"` // AsMessageChannel表示是否作为消息通道使用
SendStreamIP string `gorm:"column:send_stream_ip" json:"sendStreamIp"` // SendStreamIP表示点播回复200OK时使用的IP地址
AutoPushChannel *bool `gorm:"column:auto_push_channel" json:"autoPushChannel"` // AutoPushChannel表示是否自动推送通道变化
CatalogWithPlatform int `gorm:"column:catalog_with_platform" json:"catalogWithPlatform"` // CatalogWithPlatform表示目录信息是否包含平台信息(0:关闭,1:打开)
CatalogWithGroup int `gorm:"column:catalog_with_group" json:"catalogWithGroup"` // CatalogWithGroup表示目录信息是否包含分组信息(0:关闭,1:打开)
CatalogWithRegion int `gorm:"column:catalog_with_region" json:"catalogWithRegion"` // CatalogWithRegion表示目录信息是否包含行政区划(0:关闭,1:打开)
CivilCode string `gorm:"column:civil_code" json:"civilCode"` // CivilCode表示行政区划代码
Manufacturer string `gorm:"column:manufacturer" json:"manufacturer"` // Manufacturer表示平台厂商
Model string `gorm:"column:model" json:"model"` // Model表示平台型号
Address string `gorm:"column:address" json:"address"` // Address表示平台安装地址
RegisterWay int `gorm:"column:register_way" json:"registerWay"` // RegisterWay表示注册方式(1:标准认证注册,2:口令认证,3:数字证书双向认证,4:数字证书单向认证)
Secrecy int `gorm:"column:secrecy" json:"secrecy"` // Secrecy表示保密属性(0:不涉密,1:涉密)
// 运行时字段,不存储到数据库
KeepAliveReply int `gorm:"-" json:"keepAliveReply"` // KeepAliveReply表示心跳未回复次数
RegisterAliveReply int `gorm:"-" json:"registerAliveReply"` // RegisterAliveReply表示注册未回复次数
CallID string `gorm:"-" json:"callId"` // CallID表示SIP会话的标识符
// SIP相关字段不存储到数据库
Client *sipgo.Client `gorm:"-" json:"-"` // SIP客户端
DialogClient *sipgo.DialogClient `gorm:"-" json:"-"` // SIP对话客户端
ContactHDR sip.ContactHeader `gorm:"-" json:"-"` // 联系人头部
FromHDR sip.FromHeader `gorm:"-" json:"-"` // From头部
CurrentSession *sipgo.DialogClientSession `gorm:"-" json:"-"` // 当前会话
}
// TableName 指定数据库表名
func (p *Platform) TableName() string {
return "platform_gb28181pro"
}
// NewPlatform 创建并返回一个新的Platform实例。
// 该函数会初始化Platform结构体并设置一些默认值
// - RegisterWay默认设置为1标准认证注册模式
// - Secrecy默认设置为0不涉密
// 返回值为指向新创建的Platform实例的指针。
func NewPlatform() *Platform {
return &Platform{
RegisterWay: 1, // 默认使用标准认证注册模式
Secrecy: 0, // 默认为不涉密
KeepAliveReply: 0,
RegisterAliveReply: 0,
}
}
// ResetKeepAliveReply 重置心跳未回复次数
func (p *Platform) ResetKeepAliveReply() {
p.KeepAliveReply = 0
}
// IncrementKeepAliveReply 增加心跳未回复次数
func (p *Platform) IncrementKeepAliveReply() {
p.KeepAliveReply++
}
// ResetRegisterAliveReply 重置注册未回复次数
func (p *Platform) ResetRegisterAliveReply() {
p.RegisterAliveReply = 0
}
// IncrementRegisterAliveReply 增加注册未回复次数
func (p *Platform) IncrementRegisterAliveReply() {
p.RegisterAliveReply++
}
// SetCallID 设置SIP会话标识符
func (p *Platform) SetCallID(callID string) {
p.CallID = callID
}
// GetCallID 获取SIP会话标识符
func (p *Platform) GetCallID() string {
return p.CallID
}

View File

@@ -0,0 +1,265 @@
package gb28181
import (
"context"
"fmt"
"strings"
"time"
"github.com/emiago/sipgo"
"github.com/emiago/sipgo/sip"
"github.com/icholy/digest"
)
// InitializeSIPClient 初始化SIP客户端
func (p *Platform) InitializeSIPClient(ua *sipgo.UserAgent, localIP string) error {
var err error
p.Client, err = sipgo.NewClient(ua, sipgo.WithClientHostname(localIP))
if err != nil {
return fmt.Errorf("failed to create sip client: %v", err)
}
// 设置联系人头部,使用本地平台的信息
p.ContactHDR = sip.ContactHeader{
Address: sip.Uri{
User: p.DeviceGBID,
Host: p.DeviceIP,
Port: p.DevicePort,
},
}
// 设置From头部使用本地平台的信息
p.FromHDR = sip.FromHeader{
Address: sip.Uri{
User: p.DeviceGBID,
Host: p.ServerGBDomain,
},
Params: sip.NewParams(),
}
p.FromHDR.Params.Add("tag", sip.GenerateTagN(16))
// 创建对话客户端
p.DialogClient = sipgo.NewDialogClient(p.Client, p.ContactHDR)
return nil
}
// Register 发送注册请求到上级平台
func (p *Platform) Register(ctx context.Context, plugin interface{}) (*sipgo.DialogClientSession, error) {
// 创建注册请求的目标URI使用上级平台的信息
recipient := sip.Uri{
User: p.ServerGBID,
Host: p.ServerIP,
Port: p.ServerPort,
}
// 创建基本的REGISTER请求
req := sip.NewRequest(sip.REGISTER, recipient)
// 添加Contact头部
contactStr := fmt.Sprintf("<sip:%s@%s:%d>", p.DeviceGBID, p.DeviceIP, p.DevicePort)
req.AppendHeader(sip.NewHeader("Contact", contactStr))
// 添加From头部
fromHeader := sip.FromHeader{
Address: sip.Uri{
User: p.DeviceGBID,
Host: p.ServerGBDomain,
},
Params: sip.NewParams(),
}
fromHeader.Params.Add("tag", sip.GenerateTagN(16))
req.AppendHeader(&fromHeader)
// 添加To头部
toHeader := sip.ToHeader{
Address: sip.Uri{
User: p.DeviceGBID,
Host: p.ServerGBDomain,
},
}
req.AppendHeader(&toHeader)
// 添加Expires头部
req.AppendHeader(sip.NewHeader("Expires", fmt.Sprintf("%d", p.Expires)))
// 设置传输协议
req.SetTransport(strings.ToUpper(p.Transport))
// 发送请求并获取响应
tx, err := p.Client.TransactionRequest(ctx, req, sipgo.ClientRequestAddVia)
if err != nil {
return nil, fmt.Errorf("创建事务失败: %v", err)
}
defer tx.Terminate()
// 获取响应
res, err := p.getResponse(tx)
if err != nil {
return nil, fmt.Errorf("获取响应失败: %v", err)
}
// 处理401未授权响应
if res.StatusCode == 401 {
// 获取WWW-Authenticate头部
wwwAuth := res.GetHeader("WWW-Authenticate")
if wwwAuth == nil {
return nil, fmt.Errorf("未收到认证质询")
}
// 解析认证质询
chal, err := digest.ParseChallenge(wwwAuth.Value())
if err != nil {
return nil, fmt.Errorf("解析认证质询失败: %v", err)
}
// 生成认证响应
cred, _ := digest.Digest(chal, digest.Options{
Method: req.Method.String(),
URI: recipient.Host,
Username: p.Username,
Password: p.Password,
})
// 创建新的带认证信息的请求
newReq := req.Clone()
newReq.RemoveHeader("Via") // 必须由传输层重新生成
newReq.AppendHeader(sip.NewHeader("Authorization", cred.String()))
// 发送认证请求
tx, err = p.Client.TransactionRequest(ctx, newReq, sipgo.ClientRequestAddVia)
if err != nil {
return nil, fmt.Errorf("创建认证事务失败: %v", err)
}
defer tx.Terminate()
// 获取认证响应
res, err = p.getResponse(tx)
if err != nil {
return nil, fmt.Errorf("获取认证响应失败: %v", err)
}
}
// 检查最终响应状态
if res.StatusCode != 200 {
return nil, fmt.Errorf("注册失败,状态码: %d", res.StatusCode)
}
// 注册成功,不需要维护会话状态
return nil, nil
}
// getResponse 从事务中获取响应
func (p *Platform) getResponse(tx sip.ClientTransaction) (*sip.Response, error) {
select {
case <-tx.Done():
return nil, fmt.Errorf("事务已终止")
case res := <-tx.Responses():
return res, nil
}
}
// Keepalive 发送心跳请求到上级平台
func (p *Platform) Keepalive(ctx context.Context, plugin interface{}) (*sipgo.DialogClientSession, error) {
// TODO: 实现心跳逻辑
return nil, nil
}
// Unregister 发送注销请求到上级平台
func (p *Platform) Unregister(ctx context.Context, plugin interface{}) (*sipgo.DialogClientSession, error) {
// 创建注销请求的目标URI
recipient := sip.Uri{
User: p.ServerGBID,
Host: p.ServerIP,
Port: p.ServerPort,
}
// 创建基本的REGISTER请求
req := sip.NewRequest(sip.REGISTER, recipient)
// 添加Contact头部
contactStr := fmt.Sprintf("<sip:%s@%s:%d>", p.DeviceGBID, p.DeviceIP, p.DevicePort)
req.AppendHeader(sip.NewHeader("Contact", contactStr))
// 添加From头部
fromHeader := sip.FromHeader{
Address: sip.Uri{
User: p.DeviceGBID,
Host: p.ServerGBDomain,
},
Params: sip.NewParams(),
}
fromHeader.Params.Add("tag", sip.GenerateTagN(16))
req.AppendHeader(&fromHeader)
// 添加To头部
toHeader := sip.ToHeader{
Address: sip.Uri{
User: p.DeviceGBID,
Host: p.ServerGBDomain,
},
}
req.AppendHeader(&toHeader)
// 添加Expires头部设置为0表示注销
req.AppendHeader(sip.NewHeader("Expires", "0"))
// 设置传输协议
req.SetTransport(strings.ToUpper(p.Transport))
// 发送请求并获取响应
tx, err := p.Client.TransactionRequest(ctx, req, sipgo.ClientRequestAddVia)
if err != nil {
return nil, fmt.Errorf("创建事务失败: %v", err)
}
defer tx.Terminate()
// 获取响应
res, err := p.getResponse(tx)
if err != nil {
return nil, fmt.Errorf("获取响应失败: %v", err)
}
// 检查响应状态
if res.StatusCode != 200 {
return nil, fmt.Errorf("注销失败,状态码: %d", res.StatusCode)
}
return nil, nil
}
// StartRegisterTask 启动注册任务
// 这个方法会在平台启用时被调用,负责处理注册和保活
func (p *Platform) StartRegisterTask(plugin interface{}) {
ctx := context.Background()
// 首次注册
session, err := p.Register(ctx, plugin)
if err != nil {
// TODO: 处理注册失败
return
}
// 保存当前会话
p.CurrentSession = session
// 启动保活协程
go func() {
ticker := time.NewTicker(time.Duration(p.KeepTimeout) * time.Second)
defer ticker.Stop()
for range ticker.C {
if !p.Enable {
// 如果平台被禁用,发送注销请求并退出
_, _ = p.Unregister(ctx, plugin)
return
}
// 发送心跳
_, err := p.Keepalive(ctx, plugin)
if err != nil {
// TODO: 处理心跳失败
}
}
}()
}