Skip to content

Commit eba62c4

Browse files
committed
feat: gb28181 support update channel name,channelid
1 parent a070dc6 commit eba62c4

File tree

9 files changed

+820
-482
lines changed

9 files changed

+820
-482
lines changed

plugin/gb28181/api.go

Lines changed: 92 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,16 @@ func (gb *GB28181Plugin) List(ctx context.Context, req *pb.GetDevicesRequest) (*
8484

8585
// 从设备的内存通道集合中获取通道信息
8686
d.channels.Range(func(channel *Channel) bool {
87+
if channel.ID == "34020000001320000109_34020000001310000109" {
88+
gb.Info("channel", "id", channel.ID)
89+
d.Info("channel", "id", channel.ID)
90+
}
8791
pbChannels = append(pbChannels, &pb.Channel{
88-
DeviceId: channel.ChannelId,
89-
ChannelId: channel.ChannelId,
92+
Id: channel.ID,
93+
DeviceId: channel.CustomChannelId,
94+
ChannelId: channel.CustomChannelId,
9095
ParentId: d.DeviceId,
91-
Name: channel.Name,
96+
Name: channel.CustomName,
9297
Manufacturer: channel.Manufacturer,
9398
Model: channel.Model,
9499
Owner: channel.Owner,
@@ -109,7 +114,7 @@ func (gb *GB28181Plugin) List(ctx context.Context, req *pb.GetDevicesRequest) (*
109114

110115
pbDevices = append(pbDevices, &pb.Device{
111116
DeviceId: d.DeviceId,
112-
Name: d.Name,
117+
Name: d.CustomName,
113118
Manufacturer: d.Manufacturer,
114119
Model: d.Model,
115120
Status: string(d.Status),
@@ -499,7 +504,7 @@ func (gb *GB28181Plugin) UpdateDevice(ctx context.Context, req *pb.Device) (*pb.
499504

500505
// 更新基本字段
501506
if req.Name != "" {
502-
d.Name = req.Name
507+
d.CustomName = req.Name
503508
}
504509
if req.Manufacturer != "" {
505510
d.Manufacturer = req.Manufacturer
@@ -2944,3 +2949,85 @@ func (gb *GB28181Plugin) ReceiveAlarm(ctx context.Context, req *pb.AlarmInfoRequ
29442949
resp.Message = "告警信息接收成功"
29452950
return resp, nil
29462951
}
2952+
2953+
// UpdateChannel 实现更新通道信息
2954+
func (gb *GB28181Plugin) UpdateChannel(ctx context.Context, req *pb.UpdateChannelRequest) (*pb.BaseResponse, error) {
2955+
resp := &pb.BaseResponse{}
2956+
2957+
// 参数校验
2958+
if req.Id == "" {
2959+
resp.Code = 400
2960+
resp.Message = "通道复合ID不能为空"
2961+
return resp, nil
2962+
}
2963+
2964+
if req.Channel == nil {
2965+
resp.Code = 400
2966+
resp.Message = "通道信息不能为空"
2967+
return resp, nil
2968+
}
2969+
2970+
// 直接使用 id 查找通道
2971+
parts := strings.Split(req.Id, "_")
2972+
if len(parts) != 2 {
2973+
resp.Code = 400
2974+
resp.Message = "通道复合ID格式错误,应为 deviceId_channelId"
2975+
return resp, nil
2976+
}
2977+
2978+
// 查找通道
2979+
channel, ok := gb.channels.Get(req.Id)
2980+
if !ok {
2981+
resp.Code = 404
2982+
resp.Message = "通道不存在"
2983+
return resp, nil
2984+
}
2985+
2986+
// 从请求中获取自定义通道ID
2987+
customChannelId := req.Channel.ChannelId
2988+
if customChannelId != "" && customChannelId != channel.DeviceChannel.CustomChannelId {
2989+
// 检查自定义通道ID是否已存在(全局唯一性检查)
2990+
hasConflict := false
2991+
2992+
// 遍历所有通道检查是否有重复的 customChannelId
2993+
gb.channels.Range(func(ch *Channel) bool {
2994+
// 跳过当前正在更新的通道
2995+
if ch.DeviceChannel.ID == req.Id {
2996+
return true
2997+
}
2998+
2999+
// 检查其他通道是否已使用该自定义ID
3000+
if ch.DeviceChannel.CustomChannelId == customChannelId {
3001+
hasConflict = true
3002+
return false
3003+
}
3004+
return true
3005+
})
3006+
3007+
// 如果有冲突,返回错误
3008+
if hasConflict {
3009+
resp.Code = 409
3010+
resp.Message = "自定义通道ID已存在,请使用其他ID"
3011+
return resp, nil
3012+
}
3013+
3014+
// 更新自定义通道ID
3015+
channel.DeviceChannel.CustomChannelId = customChannelId
3016+
}
3017+
3018+
// 从请求中获取自定义名称
3019+
if req.Channel.Name != "" {
3020+
channel.DeviceChannel.CustomName = req.Channel.Name
3021+
}
3022+
3023+
// 记录日志
3024+
gb.Info("通道信息已更新",
3025+
"通道ID", req.Id,
3026+
"自定义通道ID", channel.DeviceChannel.CustomChannelId,
3027+
"自定义名称", channel.DeviceChannel.CustomName)
3028+
3029+
// 返回成功响应
3030+
resp.Code = 0
3031+
resp.Message = "通道信息更新成功"
3032+
return resp, nil
3033+
}

plugin/gb28181/device.go

Lines changed: 64 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ type Device struct {
6262
task.Job `gorm:"-:all"`
6363
DeviceId string `gorm:"primaryKey"` // 设备国标编号
6464
Name string // 设备名
65+
CustomName string // 自定义名称
6566
Manufacturer string // 生产厂商
6667
Model string // 型号
6768
Firmware string // 固件版本
@@ -136,6 +137,7 @@ func (d *Device) Dispose() {
136137
if channel.PullProxyTask != nil {
137138
channel.PullProxyTask.ChangeStatus(m7s.PullProxyStatusOffline)
138139
}
140+
d.channels.RemoveByKey(channel.ID)
139141
d.plugin.channels.RemoveByKey(channel.ID)
140142
return true
141143
})
@@ -199,6 +201,9 @@ func (d *Device) onMessage(req *sip.Request, tx sip.ServerTransaction, msg *gb28
199201
switch msg.CmdType {
200202
case "Keepalive":
201203
d.KeepaliveInterval = int(time.Since(d.KeepaliveTime).Seconds())
204+
if d.KeepaliveInterval < 60 {
205+
d.KeepaliveInterval = 60
206+
}
202207
d.KeepaliveTime = time.Now()
203208
d.Debug("into keeplive,deviceid is ", d.DeviceId, "d.KeepaliveTime is", d.KeepaliveTime, "d.KeepaliveInterval is", d.KeepaliveInterval)
204209
if d.plugin.DB != nil {
@@ -227,30 +232,46 @@ func (d *Device) onMessage(req *sip.Request, tx sip.ServerTransaction, msg *gb28
227232
isFirst := catalogReq.AddResponse()
228233

229234
// 更新设备信息到数据库
230-
if d.plugin.DB != nil {
231-
// 如果是第一个响应,先清空现有通道
232-
if isFirst {
233-
d.Trace("清空现有通道", "deviceId", d.DeviceId)
234-
// 清空内存中的通道缓存
235-
d.channels.Clear()
236-
}
235+
// 如果是第一个响应,将所有通道状态标记为OFF
236+
if isFirst {
237+
d.Trace("将所有通道状态标记为OFF", "deviceId", d.DeviceId)
238+
// 标记所有通道为OFF状态
239+
d.channels.Range(func(channel *Channel) bool {
240+
if channel.DeviceChannel != nil {
241+
channel.DeviceChannel.Status = gb28181.ChannelOffStatus
242+
}
243+
return true
244+
})
245+
}
237246

238-
// 更新通道信息
239-
for _, c := range msg.DeviceChannelList {
240-
// 设置关联的设备数据库ID
241-
c.ChannelId = c.DeviceId
242-
c.DeviceId = d.DeviceId
243-
c.ID = d.DeviceId + "_" + c.ChannelId
244-
// 使用 Save 进行 upsert 操作
245-
d.addOrUpdateChannel(c)
247+
// 更新通道信息
248+
for _, c := range msg.DeviceChannelList {
249+
// 设置关联的设备数据库ID
250+
c.ChannelId = c.DeviceId
251+
c.DeviceId = d.DeviceId
252+
c.ID = d.DeviceId + "_" + c.ChannelId
253+
if c.CustomChannelId == "" {
254+
c.CustomChannelId = c.ChannelId
246255
}
247-
248-
// 更新当前设备的通道数
249-
d.ChannelCount = msg.SumNum
250-
d.UpdateTime = time.Now()
251-
d.Debug("save channel", "deviceid", d.DeviceId, " d.channels.Length", d.channels.Length, "d.ChannelCount", d.ChannelCount, "d.UpdateTime", d.UpdateTime)
256+
// 使用 Save 进行 upsert 操作
257+
d.addOrUpdateChannel(c)
252258
}
253259

260+
// 更新当前设备的通道数
261+
d.ChannelCount = msg.SumNum
262+
d.UpdateTime = time.Now()
263+
d.Debug("save channel", "deviceid", d.DeviceId, " d.channels.Length", d.channels.Length, "d.ChannelCount", d.ChannelCount, "d.UpdateTime", d.UpdateTime)
264+
265+
// 删除所有状态为OFF的通道
266+
// d.channels.Range(func(channel *Channel) bool {
267+
// if channel.DeviceChannel != nil && channel.DeviceChannel.Status == gb28181.ChannelOffStatus {
268+
// d.Debug("删除不存在的通道", "channelId", channel.ID)
269+
// d.channels.RemoveByKey(channel.ID)
270+
// d.plugin.channels.RemoveByKey(channel.ID)
271+
// }
272+
// return true
273+
// })
274+
254275
// 在所有通道都添加完成后,检查是否完成接收
255276
if catalogReq.IsComplete(d.channels.Length) {
256277
catalogReq.Resolve()
@@ -344,8 +365,11 @@ func (d *Device) onMessage(req *sip.Request, tx sip.ServerTransaction, msg *gb28
344365
case "DeviceInfo":
345366
// 主设备信息
346367
d.Info("DeviceInfo message", "body", req.Body(), "d.Name", d.Name, "d.DeviceId", d.DeviceId, "msg.DeviceName", msg.DeviceName)
347-
if d.Name == "" && msg.DeviceName != "" {
368+
if msg.DeviceName != "" {
348369
d.Name = msg.DeviceName
370+
if d.CustomName == "" {
371+
d.CustomName = msg.DeviceName
372+
}
349373
}
350374
d.Manufacturer = msg.Manufacturer
351375
d.Model = msg.Model
@@ -569,9 +593,28 @@ func (d *Device) frontEndCmdString(cmdCode int32, parameter1 int32, parameter2 i
569593
}
570594

571595
func (d *Device) addOrUpdateChannel(c gb28181.DeviceChannel) {
596+
// 设置通道状态为在线
597+
c.Status = gb28181.ChannelOnStatus
598+
572599
if channel, ok := d.channels.Get(c.ID); ok {
600+
// 通道已存在,保留自定义字段
601+
if channel.DeviceChannel != nil {
602+
// 保存原有的自定义字段
603+
customName := channel.DeviceChannel.CustomName
604+
customChannelId := channel.DeviceChannel.CustomChannelId
605+
606+
// 如果原有字段有值,则保留
607+
if customName != "" {
608+
c.CustomName = customName
609+
}
610+
if customChannelId != "" {
611+
c.CustomChannelId = customChannelId
612+
}
613+
}
614+
// 更新通道信息
573615
channel.DeviceChannel = &c
574616
} else {
617+
// 创建新通道
575618
channel = &Channel{
576619
Device: d,
577620
Logger: d.Logger.With("channel", c.ID),

plugin/gb28181/dialog.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,14 @@ func (d *Dialog) Start() (err error) {
8888
var device *Device
8989
if deviceTmp, ok := d.gb.devices.Get(deviceId); ok {
9090
device = deviceTmp
91+
d.StreamMode = device.StreamMode
9192
if channel, ok := deviceTmp.channels.Get(deviceId + "_" + channelId); ok {
9293
d.Channel = channel
93-
d.StreamMode = device.StreamMode
94+
} else if channel, ok := deviceTmp.channels.Find(func(c *Channel) bool {
95+
return c.CustomChannelId == channelId
96+
}); ok {
97+
channelId = channel.ChannelId
98+
d.Channel = channel
9499
} else {
95100
return fmt.Errorf("channel %s not found", channelId)
96101
}

plugin/gb28181/index.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"net"
77
"net/http"
88
"os"
9+
"regexp"
910
"slices"
1011
"strconv"
1112
"strings"
@@ -486,7 +487,13 @@ func (gb *GB28181Plugin) RegisterHandler() map[string]http.HandlerFunc {
486487
func (gb *GB28181Plugin) OnRegister(req *sip.Request, tx sip.ServerTransaction) {
487488
from := req.From()
488489
if from == nil || from.Address.User == "" {
489-
gb.Error("OnRegister", "error", "no user")
490+
gb.Error("OnRegister", "invaliad from", from)
491+
return
492+
}
493+
// 验证设备ID是否为20位数字
494+
matched, err := regexp.MatchString("^\\d{20}$", from.Address.User)
495+
if err != nil || !matched {
496+
gb.Error("OnRegister", "invalid deviceId", from.Address.User)
490497
return
491498
}
492499
deviceId := from.Address.User

0 commit comments

Comments
 (0)