feat: gb28181 support update channel name,channelid

This commit is contained in:
pggiroro
2025-08-06 18:01:40 +08:00
parent a070dc64f8
commit eba62c4054
9 changed files with 822 additions and 484 deletions
+92 -5
View File
@@ -84,11 +84,16 @@ func (gb *GB28181Plugin) List(ctx context.Context, req *pb.GetDevicesRequest) (*
// 从设备的内存通道集合中获取通道信息
d.channels.Range(func(channel *Channel) bool {
if channel.ID == "34020000001320000109_34020000001310000109" {
gb.Info("channel", "id", channel.ID)
d.Info("channel", "id", channel.ID)
}
pbChannels = append(pbChannels, &pb.Channel{
DeviceId: channel.ChannelId,
ChannelId: channel.ChannelId,
Id: channel.ID,
DeviceId: channel.CustomChannelId,
ChannelId: channel.CustomChannelId,
ParentId: d.DeviceId,
Name: channel.Name,
Name: channel.CustomName,
Manufacturer: channel.Manufacturer,
Model: channel.Model,
Owner: channel.Owner,
@@ -109,7 +114,7 @@ func (gb *GB28181Plugin) List(ctx context.Context, req *pb.GetDevicesRequest) (*
pbDevices = append(pbDevices, &pb.Device{
DeviceId: d.DeviceId,
Name: d.Name,
Name: d.CustomName,
Manufacturer: d.Manufacturer,
Model: d.Model,
Status: string(d.Status),
@@ -499,7 +504,7 @@ func (gb *GB28181Plugin) UpdateDevice(ctx context.Context, req *pb.Device) (*pb.
// 更新基本字段
if req.Name != "" {
d.Name = req.Name
d.CustomName = req.Name
}
if req.Manufacturer != "" {
d.Manufacturer = req.Manufacturer
@@ -2944,3 +2949,85 @@ func (gb *GB28181Plugin) ReceiveAlarm(ctx context.Context, req *pb.AlarmInfoRequ
resp.Message = "告警信息接收成功"
return resp, nil
}
// UpdateChannel 实现更新通道信息
func (gb *GB28181Plugin) UpdateChannel(ctx context.Context, req *pb.UpdateChannelRequest) (*pb.BaseResponse, error) {
resp := &pb.BaseResponse{}
// 参数校验
if req.Id == "" {
resp.Code = 400
resp.Message = "通道复合ID不能为空"
return resp, nil
}
if req.Channel == nil {
resp.Code = 400
resp.Message = "通道信息不能为空"
return resp, nil
}
// 直接使用 id 查找通道
parts := strings.Split(req.Id, "_")
if len(parts) != 2 {
resp.Code = 400
resp.Message = "通道复合ID格式错误,应为 deviceId_channelId"
return resp, nil
}
// 查找通道
channel, ok := gb.channels.Get(req.Id)
if !ok {
resp.Code = 404
resp.Message = "通道不存在"
return resp, nil
}
// 从请求中获取自定义通道ID
customChannelId := req.Channel.ChannelId
if customChannelId != "" && customChannelId != channel.DeviceChannel.CustomChannelId {
// 检查自定义通道ID是否已存在(全局唯一性检查)
hasConflict := false
// 遍历所有通道检查是否有重复的 customChannelId
gb.channels.Range(func(ch *Channel) bool {
// 跳过当前正在更新的通道
if ch.DeviceChannel.ID == req.Id {
return true
}
// 检查其他通道是否已使用该自定义ID
if ch.DeviceChannel.CustomChannelId == customChannelId {
hasConflict = true
return false
}
return true
})
// 如果有冲突,返回错误
if hasConflict {
resp.Code = 409
resp.Message = "自定义通道ID已存在,请使用其他ID"
return resp, nil
}
// 更新自定义通道ID
channel.DeviceChannel.CustomChannelId = customChannelId
}
// 从请求中获取自定义名称
if req.Channel.Name != "" {
channel.DeviceChannel.CustomName = req.Channel.Name
}
// 记录日志
gb.Info("通道信息已更新",
"通道ID", req.Id,
"自定义通道ID", channel.DeviceChannel.CustomChannelId,
"自定义名称", channel.DeviceChannel.CustomName)
// 返回成功响应
resp.Code = 0
resp.Message = "通道信息更新成功"
return resp, nil
}
+66 -23
View File
@@ -62,6 +62,7 @@ type Device struct {
task.Job `gorm:"-:all"`
DeviceId string `gorm:"primaryKey"` // 设备国标编号
Name string // 设备名
CustomName string // 自定义名称
Manufacturer string // 生产厂商
Model string // 型号
Firmware string // 固件版本
@@ -136,6 +137,7 @@ func (d *Device) Dispose() {
if channel.PullProxyTask != nil {
channel.PullProxyTask.ChangeStatus(m7s.PullProxyStatusOffline)
}
d.channels.RemoveByKey(channel.ID)
d.plugin.channels.RemoveByKey(channel.ID)
return true
})
@@ -199,6 +201,9 @@ func (d *Device) onMessage(req *sip.Request, tx sip.ServerTransaction, msg *gb28
switch msg.CmdType {
case "Keepalive":
d.KeepaliveInterval = int(time.Since(d.KeepaliveTime).Seconds())
if d.KeepaliveInterval < 60 {
d.KeepaliveInterval = 60
}
d.KeepaliveTime = time.Now()
d.Debug("into keeplive,deviceid is ", d.DeviceId, "d.KeepaliveTime is", d.KeepaliveTime, "d.KeepaliveInterval is", d.KeepaliveInterval)
if d.plugin.DB != nil {
@@ -227,30 +232,46 @@ func (d *Device) onMessage(req *sip.Request, tx sip.ServerTransaction, msg *gb28
isFirst := catalogReq.AddResponse()
// 更新设备信息到数据库
if d.plugin.DB != nil {
// 如果是第一个响应,先清空现有通道
if isFirst {
d.Trace("清空现有通道", "deviceId", d.DeviceId)
// 清空内存中的通道缓存
d.channels.Clear()
}
// 更新通道信息
for _, c := range msg.DeviceChannelList {
// 设置关联的设备数据库ID
c.ChannelId = c.DeviceId
c.DeviceId = d.DeviceId
c.ID = d.DeviceId + "_" + c.ChannelId
// 使用 Save 进行 upsert 操作
d.addOrUpdateChannel(c)
}
// 更新当前设备的通道数
d.ChannelCount = msg.SumNum
d.UpdateTime = time.Now()
d.Debug("save channel", "deviceid", d.DeviceId, " d.channels.Length", d.channels.Length, "d.ChannelCount", d.ChannelCount, "d.UpdateTime", d.UpdateTime)
// 如果是第一个响应,将所有通道状态标记为OFF
if isFirst {
d.Trace("将所有通道状态标记为OFF", "deviceId", d.DeviceId)
// 标记所有通道为OFF状态
d.channels.Range(func(channel *Channel) bool {
if channel.DeviceChannel != nil {
channel.DeviceChannel.Status = gb28181.ChannelOffStatus
}
return true
})
}
// 更新通道信息
for _, c := range msg.DeviceChannelList {
// 设置关联的设备数据库ID
c.ChannelId = c.DeviceId
c.DeviceId = d.DeviceId
c.ID = d.DeviceId + "_" + c.ChannelId
if c.CustomChannelId == "" {
c.CustomChannelId = c.ChannelId
}
// 使用 Save 进行 upsert 操作
d.addOrUpdateChannel(c)
}
// 更新当前设备的通道数
d.ChannelCount = msg.SumNum
d.UpdateTime = time.Now()
d.Debug("save channel", "deviceid", d.DeviceId, " d.channels.Length", d.channels.Length, "d.ChannelCount", d.ChannelCount, "d.UpdateTime", d.UpdateTime)
// 删除所有状态为OFF的通道
// d.channels.Range(func(channel *Channel) bool {
// if channel.DeviceChannel != nil && channel.DeviceChannel.Status == gb28181.ChannelOffStatus {
// d.Debug("删除不存在的通道", "channelId", channel.ID)
// d.channels.RemoveByKey(channel.ID)
// d.plugin.channels.RemoveByKey(channel.ID)
// }
// return true
// })
// 在所有通道都添加完成后,检查是否完成接收
if catalogReq.IsComplete(d.channels.Length) {
catalogReq.Resolve()
@@ -344,8 +365,11 @@ func (d *Device) onMessage(req *sip.Request, tx sip.ServerTransaction, msg *gb28
case "DeviceInfo":
// 主设备信息
d.Info("DeviceInfo message", "body", req.Body(), "d.Name", d.Name, "d.DeviceId", d.DeviceId, "msg.DeviceName", msg.DeviceName)
if d.Name == "" && msg.DeviceName != "" {
if msg.DeviceName != "" {
d.Name = msg.DeviceName
if d.CustomName == "" {
d.CustomName = msg.DeviceName
}
}
d.Manufacturer = msg.Manufacturer
d.Model = msg.Model
@@ -569,9 +593,28 @@ func (d *Device) frontEndCmdString(cmdCode int32, parameter1 int32, parameter2 i
}
func (d *Device) addOrUpdateChannel(c gb28181.DeviceChannel) {
// 设置通道状态为在线
c.Status = gb28181.ChannelOnStatus
if channel, ok := d.channels.Get(c.ID); ok {
// 通道已存在,保留自定义字段
if channel.DeviceChannel != nil {
// 保存原有的自定义字段
customName := channel.DeviceChannel.CustomName
customChannelId := channel.DeviceChannel.CustomChannelId
// 如果原有字段有值,则保留
if customName != "" {
c.CustomName = customName
}
if customChannelId != "" {
c.CustomChannelId = customChannelId
}
}
// 更新通道信息
channel.DeviceChannel = &c
} else {
// 创建新通道
channel = &Channel{
Device: d,
Logger: d.Logger.With("channel", c.ID),
+6 -1
View File
@@ -88,9 +88,14 @@ func (d *Dialog) Start() (err error) {
var device *Device
if deviceTmp, ok := d.gb.devices.Get(deviceId); ok {
device = deviceTmp
d.StreamMode = device.StreamMode
if channel, ok := deviceTmp.channels.Get(deviceId + "_" + channelId); ok {
d.Channel = channel
d.StreamMode = device.StreamMode
} else if channel, ok := deviceTmp.channels.Find(func(c *Channel) bool {
return c.CustomChannelId == channelId
}); ok {
channelId = channel.ChannelId
d.Channel = channel
} else {
return fmt.Errorf("channel %s not found", channelId)
}
+8 -1
View File
@@ -6,6 +6,7 @@ import (
"net"
"net/http"
"os"
"regexp"
"slices"
"strconv"
"strings"
@@ -486,7 +487,13 @@ func (gb *GB28181Plugin) RegisterHandler() map[string]http.HandlerFunc {
func (gb *GB28181Plugin) OnRegister(req *sip.Request, tx sip.ServerTransaction) {
from := req.From()
if from == nil || from.Address.User == "" {
gb.Error("OnRegister", "error", "no user")
gb.Error("OnRegister", "invaliad from", from)
return
}
// 验证设备ID是否为20位数字
matched, err := regexp.MatchString("^\\d{20}$", from.Address.User)
if err != nil || !matched {
gb.Error("OnRegister", "invalid deviceId", from.Address.User)
return
}
deviceId := from.Address.User
File diff suppressed because it is too large Load Diff
+81
View File
@@ -2709,6 +2709,48 @@ func local_request_Api_UploadJpeg_0(ctx context.Context, marshaler runtime.Marsh
return msg, metadata, err
}
func request_Api_UpdateChannel_0(ctx context.Context, marshaler runtime.Marshaler, client ApiClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq UpdateChannelRequest
metadata runtime.ServerMetadata
err error
)
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.Channel); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
val, ok := pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := client.UpdateChannel(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Api_UpdateChannel_0(ctx context.Context, marshaler runtime.Marshaler, server ApiServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq UpdateChannelRequest
metadata runtime.ServerMetadata
err error
)
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.Channel); err != nil && !errors.Is(err, io.EOF) {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
val, ok := pathParams["id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id")
}
protoReq.Id, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err)
}
msg, err := server.UpdateChannel(ctx, &protoReq)
return msg, metadata, err
}
var filter_Api_PlaybackPause_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
func request_Api_PlaybackPause_0(ctx context.Context, marshaler runtime.Marshaler, client ApiClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
@@ -4258,6 +4300,26 @@ func RegisterApiHandlerServer(ctx context.Context, mux *runtime.ServeMux, server
}
forward_Api_UploadJpeg_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodPost, pattern_Api_UpdateChannel_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)
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/gb28181pro.Api/UpdateChannel", runtime.WithHTTPPathPattern("/gb28181/api/channel/update/{id}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Api_UpdateChannel_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_UpdateChannel_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodGet, pattern_Api_PlaybackPause_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
@@ -5479,6 +5541,23 @@ func RegisterApiHandlerClient(ctx context.Context, mux *runtime.ServeMux, client
}
forward_Api_UploadJpeg_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodPost, pattern_Api_UpdateChannel_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)
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/gb28181pro.Api/UpdateChannel", runtime.WithHTTPPathPattern("/gb28181/api/channel/update/{id}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Api_UpdateChannel_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_UpdateChannel_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodGet, pattern_Api_PlaybackPause_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
@@ -5774,6 +5853,7 @@ var (
pattern_Api_AddPlatformChannel_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 2, 4}, []string{"gb28181", "api", "platform", "channel", "add"}, ""))
pattern_Api_Recording_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 1, 0, 4, 1, 5, 4, 1, 0, 4, 1, 5, 5}, []string{"gb28181", "api", "recording", "cmdType", "deviceId", "channelId"}, ""))
pattern_Api_UploadJpeg_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"gb28181", "api", "snap", "upload"}, ""))
pattern_Api_UpdateChannel_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"gb28181", "api", "channel", "update", "id"}, ""))
pattern_Api_PlaybackPause_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"gb28181", "api", "playback", "pause"}, ""))
pattern_Api_PlaybackResume_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"gb28181", "api", "playback", "resume"}, ""))
pattern_Api_PlaybackSeek_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"gb28181", "api", "playback", "seek"}, ""))
@@ -5844,6 +5924,7 @@ var (
forward_Api_AddPlatformChannel_0 = runtime.ForwardResponseMessage
forward_Api_Recording_0 = runtime.ForwardResponseMessage
forward_Api_UploadJpeg_0 = runtime.ForwardResponseMessage
forward_Api_UpdateChannel_0 = runtime.ForwardResponseMessage
forward_Api_PlaybackPause_0 = runtime.ForwardResponseMessage
forward_Api_PlaybackResume_0 = runtime.ForwardResponseMessage
forward_Api_PlaybackSeek_0 = runtime.ForwardResponseMessage
+13
View File
@@ -392,6 +392,14 @@ service api {
};
}
//
rpc UpdateChannel (UpdateChannelRequest) returns (BaseResponse) {
option (google.api.http) = {
post: "/gb28181/api/channel/update/{id}"
body: "channel"
};
}
//
rpc PlaybackPause (PlaybackPauseRequest) returns (BaseResponse) {
option (google.api.http) = {
@@ -658,6 +666,11 @@ message AlarmInfo {
string alarmDescription = 5;
}
message UpdateChannelRequest {
string id = 1; // ID deviceId_channelId
Channel channel = 2;
}
message GetSyncStatusRequest {
string deviceId = 1;
}
+40
View File
@@ -75,6 +75,7 @@ const (
Api_AddPlatformChannel_FullMethodName = "/gb28181pro.api/AddPlatformChannel"
Api_Recording_FullMethodName = "/gb28181pro.api/Recording"
Api_UploadJpeg_FullMethodName = "/gb28181pro.api/UploadJpeg"
Api_UpdateChannel_FullMethodName = "/gb28181pro.api/UpdateChannel"
Api_PlaybackPause_FullMethodName = "/gb28181pro.api/PlaybackPause"
Api_PlaybackResume_FullMethodName = "/gb28181pro.api/PlaybackResume"
Api_PlaybackSeek_FullMethodName = "/gb28181pro.api/PlaybackSeek"
@@ -201,6 +202,8 @@ type ApiClient interface {
Recording(ctx context.Context, in *RecordingRequest, opts ...grpc.CallOption) (*BaseResponse, error)
// 接收JPEG文件
UploadJpeg(ctx context.Context, in *UploadJpegRequest, opts ...grpc.CallOption) (*BaseResponse, error)
// 更新通道信息
UpdateChannel(ctx context.Context, in *UpdateChannelRequest, opts ...grpc.CallOption) (*BaseResponse, error)
// 回放暂停
PlaybackPause(ctx context.Context, in *PlaybackPauseRequest, opts ...grpc.CallOption) (*BaseResponse, error)
// 回放恢复
@@ -768,6 +771,16 @@ func (c *apiClient) UploadJpeg(ctx context.Context, in *UploadJpegRequest, opts
return out, nil
}
func (c *apiClient) UpdateChannel(ctx context.Context, in *UpdateChannelRequest, opts ...grpc.CallOption) (*BaseResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(BaseResponse)
err := c.cc.Invoke(ctx, Api_UpdateChannel_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *apiClient) PlaybackPause(ctx context.Context, in *PlaybackPauseRequest, opts ...grpc.CallOption) (*BaseResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(BaseResponse)
@@ -1018,6 +1031,8 @@ type ApiServer interface {
Recording(context.Context, *RecordingRequest) (*BaseResponse, error)
// 接收JPEG文件
UploadJpeg(context.Context, *UploadJpegRequest) (*BaseResponse, error)
// 更新通道信息
UpdateChannel(context.Context, *UpdateChannelRequest) (*BaseResponse, error)
// 回放暂停
PlaybackPause(context.Context, *PlaybackPauseRequest) (*BaseResponse, error)
// 回放恢复
@@ -1214,6 +1229,9 @@ func (UnimplementedApiServer) Recording(context.Context, *RecordingRequest) (*Ba
func (UnimplementedApiServer) UploadJpeg(context.Context, *UploadJpegRequest) (*BaseResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method UploadJpeg not implemented")
}
func (UnimplementedApiServer) UpdateChannel(context.Context, *UpdateChannelRequest) (*BaseResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method UpdateChannel not implemented")
}
func (UnimplementedApiServer) PlaybackPause(context.Context, *PlaybackPauseRequest) (*BaseResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method PlaybackPause not implemented")
}
@@ -2231,6 +2249,24 @@ func _Api_UploadJpeg_Handler(srv interface{}, ctx context.Context, dec func(inte
return interceptor(ctx, in, info, handler)
}
func _Api_UpdateChannel_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(UpdateChannelRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ApiServer).UpdateChannel(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: Api_UpdateChannel_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ApiServer).UpdateChannel(ctx, req.(*UpdateChannelRequest))
}
return interceptor(ctx, in, info, handler)
}
func _Api_PlaybackPause_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(PlaybackPauseRequest)
if err := dec(in); err != nil {
@@ -2702,6 +2738,10 @@ var Api_ServiceDesc = grpc.ServiceDesc{
MethodName: "UploadJpeg",
Handler: _Api_UploadJpeg_Handler,
},
{
MethodName: "UpdateChannel",
Handler: _Api_UpdateChannel_Handler,
},
{
MethodName: "PlaybackPause",
Handler: _Api_PlaybackPause_Handler,
+5 -3
View File
@@ -17,11 +17,13 @@ const (
type DeviceChannel struct {
//CommonGBChannel // 通过组合继承 CommonGBChannel 的字段
ID string `gorm:"primaryKey" json:"ID"` // 数据库自增长ID
ChannelId string `json:"channelID" xml:"ChannelID"`
DeviceId string `json:"deviceID" xml:"DeviceID"` // 设备国标编号
ID string `gorm:"primaryKey" json:"Id"` // 数据库自增长ID
ChannelId string `json:"channelId" xml:"ChannelID"`
CustomChannelId string `json:"customChannelId" xml:"CustomChannelID"` // 自定义通道ID
DeviceId string `json:"deviceId" xml:"DeviceID"` // 设备国标编号
ParentId string `json:"parentId" xml:"ParentID"` // 父节点ID
Name string `json:"name" xml:"Name"` // 通道名称
CustomName string `json:"customName" xml:"CustomName"` // 自定义名称
Manufacturer string `json:"manufacturer" xml:"Manufacturer"` // 设备厂商
Model string `json:"model" xml:"Model"` // 设备型号
Owner string `json:"owner" xml:"Owner"` // 设备归属