更新镜像

This commit is contained in:
xugo
2025-03-17 02:19:21 +08:00
parent 6d2f457fde
commit 41b709a6f0
17 changed files with 235 additions and 99 deletions

View File

@@ -1,5 +1,7 @@
FROM alpine:latest FROM alpine:latest
ARG TARGETARCH
ENV TZ=Asia/Shanghai ENV TZ=Asia/Shanghai
RUN apk --no-cache add ca-certificates \ RUN apk --no-cache add ca-certificates \
@@ -7,7 +9,7 @@ RUN apk --no-cache add ca-certificates \
WORKDIR /app WORKDIR /app
ADD ./build/linux_amd64/bin ./ ADD ./build/linux_${TARGETARCH}/bin ./
ADD ./configs/config.toml /app/configs/config.toml ADD ./configs/config.toml /app/configs/config.toml
ADD ./www /app/www ADD ./www /app/www

View File

@@ -158,6 +158,12 @@ BUILD_LINUX_AMD64_DIR := ./build/linux_amd64
build/linux: build/linux:
$(eval GOARCH := amd64) $(eval GOARCH := amd64)
$(eval GOOS := linux) $(eval GOOS := linux)
$(eval dir := $(BUILD_DIR_ROOT)/$(GOOS)_$(GOARCH))
@make build/local GOOS=$(GOOS) GOARCH=$(GOARCH)
$(eval GOARCH := arm64)
$(eval GOOS := linux)
$(eval dir := $(BUILD_DIR_ROOT)/$(GOOS)_$(GOARCH))
@make build/local GOOS=$(GOOS) GOARCH=$(GOARCH) @make build/local GOOS=$(GOOS) GOARCH=$(GOARCH)
## build/windows: 构建 windows 应用 ## build/windows: 构建 windows 应用
@@ -178,7 +184,10 @@ docker/push:
@docker push $(IMAGE_NAME) @docker push $(IMAGE_NAME)
docker/build/full: docker/build/full:
@docker build --force-rm=true --platform linux/amd64 -t $(IMAGE_NAME) -f Dockerfile_full . @docker build --force-rm=true --push --platform linux/amd64,linux/arm64 -t $(IMAGE_NAME) -f Dockerfile_full .
docker/build/gowvp: build/clean build/linux
@docker build --force-rm=true --push --platform linux/amd64,linux/arm64 -t registry.cn-shanghai.aliyuncs.com/ixugo/gowvp:latest -f Dockerfile .
# ==================================================================================== # # ==================================================================================== #

View File

@@ -36,8 +36,6 @@ go wvp 是 Go 语言实现的开源 GB28181 解决方案,基于 GB28181-2022
项目框架基于 @ixugo [goweb](https://github.com/ixugo/goweb) 项目框架基于 @ixugo [goweb](https://github.com/ixugo/goweb)
Java 语言 WVP @648540858 [wvp-GB28181-pro](https://github.com/648540858/wvp-GB28181-pro)
## QA ## QA
> 怎么没有前端资源? 如何加载网页呢? > 怎么没有前端资源? 如何加载网页呢?
@@ -92,9 +90,54 @@ ZLM使用文档 [github.com/ZLMediaKit/ZLMediaKit](https://github.com/ZLMediaKit
## Docker ## Docker
### 视频指南
[如何构建或运行项目](https://www.bilibili.com/video/BV1QLQeYHEXb)
[如何用 docker compose 部署项目](https://www.bilibili.com/video/BV112QYY3EZX)
[docker hub](https://hub.docker.com/r/gospace/gowvp) [docker hub](https://hub.docker.com/r/gospace/gowvp)
** gowvp & zlmediakit 融合镜像** ** gowvp & zlmediakit 分开镜像(推荐)**
```yml
services:
gowvp:
image: registry.cn-shanghai.aliyuncs.com/ixugo/gowvp:latest
ports:
- 15123:15123 # 管理平台 http 端口
- 15060:15060 # gb28181 sip tcp 端口
- 15060:15060/udp # gb28181 sip udp 端口
volumes:
# - ./logs:/app/logs # 如果需要持久化日志,请取消注释
- ./configs:/app/configs
depends_on:
- zlm
zlm:
image: zlmediakit/zlmediakit:master
restart: always
# 推荐 linux 主机使用 host 模式
# network_mode: host
ports:
- 1935:1935 # rtmp
- 554:554 # rtsp
- 8080:80 # api
- 8443:443
- 10000:10000
- 10000:10000/udp
- 8000:8000/udp
- 9000:9000/udp
- 20050-20100:20050-20100
- 20050-20100:20050-20100/udp
volumes:
- ./configs:/opt/media/conf
```
** gowvp & zlmediakit 融合镜像(不推荐)**
docker-compose.yml docker-compose.yml
```yml ```yml
services: services:
@@ -119,39 +162,6 @@ services:
- ./zlm.conf:/opt/media/conf - ./zlm.conf:/opt/media/conf
``` ```
** gowvp & zlmediakit 分开镜像**
```yml
services:
gowvp:
image: registry.cn-shanghai.aliyuncs.com/ixugo/gowvp:latest
ports:
- 15123:15123 # 管理平台 http 端口
- 15060:15060 # gb28181 sip tcp 端口
- 15060:15060/udp # gb28181 sip udp 端口
volumes:
- ./logs:/app/logs
- ./configs:/app/configs
zlm:
image: zlmediakit/zlmediakit:master
restart: always
# 推荐 linux 主机使用 host 模式
# network_mode: host
ports:
- 1935:1935 # rtmp
- 554:554 # rtsp
- 8080:80 # api
- 8443:443
- 10000:10000
- 10000:10000/udp
- 8000:8000/udp
- 9000:9000/udp
- 20050-20100:20050-20100
- 20050-20100:20050-20100/udp
volumes:
- ./conf:/opt/media/conf
```

View File

@@ -8,6 +8,7 @@ import (
"os" "os"
"os/signal" "os/signal"
"path/filepath" "path/filepath"
"regexp"
"strconv" "strconv"
"syscall" "syscall"
"time" "time"
@@ -45,6 +46,7 @@ func main() {
var bc conf.Bootstrap var bc conf.Bootstrap
// 获取配置目录绝对路径 // 获取配置目录绝对路径
fileDir, _ := abs(*configDir) fileDir, _ := abs(*configDir)
os.MkdirAll(fileDir, 0o755)
filePath := filepath.Join(fileDir, "config.toml") filePath := filepath.Join(fileDir, "config.toml")
configIsNotExistWrite(filePath) configIsNotExistWrite(filePath)
if err := conf.SetupConfig(&bc, filePath); err != nil { if err := conf.SetupConfig(&bc, filePath); err != nil {
@@ -76,6 +78,14 @@ func main() {
})) }))
} }
secret, err := getSecret(*configDir)
if err == nil {
slog.Info("发现 zlm 配置,已赋值,未回写配置文件", "secret", secret)
bc.Media.Secret = secret
} else {
slog.Info("未发现 zlm 配置,请检查 config.ini 文件", "err", err)
}
handler, cleanUp, err := wireApp(&bc, log) handler, cleanUp, err := wireApp(&bc, log)
if err != nil { if err != nil {
slog.Error("程序构建失败", "err", err) slog.Error("程序构建失败", "err", err)
@@ -125,3 +135,17 @@ func configIsNotExistWrite(path string) {
} }
} }
} }
// 读取 config.ini 文件,通过正则表达式,获取 secret 的值
func getSecret(configDir string) (string, error) {
content, err := os.ReadFile(filepath.Join(system.Getwd(), configDir, "config.ini"))
if err != nil {
return "", err
}
re := regexp.MustCompile(`secret=(\w+)`)
matches := re.FindStringSubmatch(string(content))
if len(matches) < 2 {
return "", fmt.Errorf("secret not found")
}
return matches[1], nil
}

View File

@@ -1,16 +1,25 @@
version = 1
[Server] [Server]
rtmpSecret = "123" Debug = false
[Server.HTTP] # rtmp 推流秘钥
Port = 15123 RTMPSecret = '123'
JwtSecret = ""
Timeout = "60s"
[Server.HTTP.Pprof] # 对外提供的服务,建议由 nginx 代理
[Server.HTTP]
# http 端口
Port = 15123
# 请求超时时间
Timeout = '1m0s'
# jwt 秘钥,空串时,每次启动程序将随机赋值
JwtSecret = ''
[Server.HTTP.PProf]
# 是否启用 pprof, 建议设置为 true
Enabled = true Enabled = true
# 访问白名单
AccessIps = ['::1', '127.0.0.1'] AccessIps = ['::1', '127.0.0.1']
[Data] [Data]
# 数据库支持 sqlite 和 postgres 两种,使用 sqlite 时 dsn 应当填写文件存储路径
[Data.Database] [Data.Database]
Dsn = './configs/data.db' Dsn = './configs/data.db'
MaxIdleConns = 1 MaxIdleConns = 1
@@ -18,20 +27,6 @@ version = 1
ConnMaxLifetime = '6h0m0s' ConnMaxLifetime = '6h0m0s'
SlowThreshold = '200ms' SlowThreshold = '200ms'
[Sip]
Port = 15060
ID = "3402000000200000001"
Domain = "3402000000"
Password = ""
[Media]
IP = "127.0.0.1"
HTTPPort = 8080
Secret = "s1kPE7bzqKeHUaVcp8dCA0jeB8yxyFq4"
WebHookIP = "192.168.1.10"
RTPPortRange = "20000-20500"
SDPIP = "192.168.1.10"
[Log] [Log]
# 日志存储目录,不能使用特殊符号 # 日志存储目录,不能使用特殊符号
Dir = './logs' Dir = './logs'
@@ -42,4 +37,28 @@ version = 1
# 多久时间,分割一个新的日志文件 # 多久时间,分割一个新的日志文件
RotationTime = '12h0m0s' RotationTime = '12h0m0s'
# 多大文件,分割一个新的日志文件(MB) # 多大文件,分割一个新的日志文件(MB)
RotationSize = 50 RotationSize = 50
[Sip]
# 服务监听的 tcp/udp 端口号
Port = 15060
# gb/t28181 20 位国标 ID
ID = '3402000000200000001'
# 域
Domain = '3402000000'
# 注册密码
Password = ''
[Media]
# 媒体服务器 IP
IP = '127.0.0.1'
# 媒体服务器 HTTP 端口
HTTPPort = 8080
# 媒体服务器密钥
Secret = ''
# 用于流媒体 webhook 回调
WebHookIP = '192.168.1.10'
# 媒体服务器 RTP 端口范围
RTPPortRange = '20000-20500'
# 媒体服务器 SDP IP
SDPIP = '192.168.1.10'

View File

@@ -5,4 +5,29 @@ services:
context: . context: .
dockerfile: ./Dockerfile dockerfile: ./Dockerfile
ports: ports:
- 18082:18081 - 15123:15123 # 管理平台 http 端口
- 15060:15060 # gb28181 sip tcp 端口
- 15060:15060/udp # gb28181 sip udp 端口
volumes:
- ./logs:/app/logs
- ./configs:/app/configs
depends_on:
- zlm
zlm:
image: zlmediakit/zlmediakit:master
restart: always
# 推荐 linux 主机使用 host 模式
# network_mode: host
ports:
- 1935:1935 # rtmp
- 554:554 # rtsp
- 8080:80 # api
- 8443:443
- 10000:10000
- 10000:10000/udp
- 8000:8000/udp
- 9000:9000/udp
- 20050-20100:20050-20100
- 20050-20100:20050-20100/udp
volumes:
- ./conf:/opt/media/conf

View File

@@ -1,21 +1,24 @@
services: services:
gowvp: gowvp:
image: gb28181 image: registry.cn-shanghai.aliyuncs.com/ixugo/gowvp:latest
build:
context: .
dockerfile: ./Dockerfile
ports: ports:
- 15123:15123 # 管理平台 http 端口 - 15123:15123 # 管理平台 http 端口
- 15060:15060 # gb28181 sip tcp 端口 - 15060:15060 # gb28181 sip tcp 端口
- 15060:15060/udp # gb28181 sip udp 端口 - 15060:15060/udp # gb28181 sip udp 端口
volumes: volumes:
- ./logs:/app/logs # - ./logs:/app/logs # 如果需要持久化日志,请取消注释
- ./configs:/app/configs - ./configs:/app/configs
networks:
- gowvp-network
depends_on:
- zlm
zlm: zlm:
image: zlmediakit/zlmediakit:master image: zlmediakit/zlmediakit:master
restart: always restart: always
# 推荐 linux 主机使用 host 模式 # 推荐 linux 主机使用 host 模式
# network_mode: host # network_mode: host
networks:
- gowvp-network
ports: ports:
- 1935:1935 # rtmp - 1935:1935 # rtmp
- 554:554 # rtsp - 554:554 # rtsp
@@ -28,4 +31,9 @@ services:
- 20050-20100:20050-20100 - 20050-20100:20050-20100
- 20050-20100:20050-20100/udp - 20050-20100:20050-20100/udp
volumes: volumes:
- ./conf:/opt/media/conf - ./configs:/opt/media/conf
# 如果不使用 host 模式,可以使用下面的配置
networks:
gowvp-network:
driver: bridge

View File

@@ -88,8 +88,9 @@ func (c *Cache) Change(deviceID string, changeFn func(*gb28181.Device), changeFn
dev2.LastKeepaliveAt = dev.KeepaliveAt.Time dev2.LastKeepaliveAt = dev.KeepaliveAt.Time
dev2.LastRegisterAt = dev.RegisteredAt.Time dev2.LastRegisterAt = dev.RegisteredAt.Time
dev2.Expires = dev.Expires dev2.Expires = dev.Expires
dev2.Password = dev.Password
dev2.Address = dev.Address
changeFn2(dev2) changeFn2(dev2)
if !dev2.IsOnline { if !dev2.IsOnline {
if err := c.Storer.Channel().BatchEdit(context.TODO(), "is_online", false, orm.Where("did=?", dev.ID)); err != nil { if err := c.Storer.Channel().BatchEdit(context.TODO(), "is_online", false, orm.Where("did=?", dev.ID)); err != nil {
slog.Error("更新通道离线状态失败", "error", err) slog.Error("更新通道离线状态失败", "error", err)

View File

@@ -2,6 +2,7 @@ package gb28181cache
import ( import (
"context" "context"
"log/slog"
"github.com/gowvp/gb28181/internal/core/gb28181" "github.com/gowvp/gb28181/internal/core/gb28181"
"github.com/gowvp/gb28181/pkg/gbs" "github.com/gowvp/gb28181/pkg/gbs"
@@ -12,7 +13,7 @@ import (
var _ gb28181.DeviceStorer = &Device{} var _ gb28181.DeviceStorer = &Device{}
type Device Cache type Device = Cache
// Add implements gb28181.DeviceStorer. // Add implements gb28181.DeviceStorer.
func (d *Device) Add(ctx context.Context, dev *gb28181.Device) error { func (d *Device) Add(ctx context.Context, dev *gb28181.Device) error {
@@ -47,7 +48,23 @@ func (d *Device) Del(ctx context.Context, dev *gb28181.Device, opts ...orm.Query
// Edit implements gb28181.DeviceStorer. // Edit implements gb28181.DeviceStorer.
func (d *Device) Edit(ctx context.Context, dev *gb28181.Device, changeFn func(*gb28181.Device), opts ...orm.QueryOption) error { func (d *Device) Edit(ctx context.Context, dev *gb28181.Device, changeFn func(*gb28181.Device), opts ...orm.QueryOption) error {
return d.Storer.Device().Edit(ctx, dev, changeFn, opts...) if err := d.Storer.Device().Edit(ctx, dev, changeFn, opts...); err != nil {
return err
}
dev2, ok := d.devices.Load(dev.DeviceID)
if !ok {
panic("edit device not found")
}
// 密码修改,设备需要重新注册
if dev2.Password != dev.Password && dev.Password != "" {
slog.Info("修改密码,设备离线")
d.Change(dev.DeviceID, func(d *gb28181.Device) {
d.Password = dev.Password
d.IsOnline = false
}, func(d *gbs.Device) {
})
}
return nil
} }
// Find implements gb28181.DeviceStorer. // Find implements gb28181.DeviceStorer.

View File

@@ -54,7 +54,7 @@ func (c *Core) AddMediaServer(ctx context.Context, in *AddMediaServerInput) (*Me
} }
// EditMediaServer Update object information // EditMediaServer Update object information
func (c *Core) EditMediaServer(ctx context.Context, in *EditMediaServerInput, id string) (*MediaServer, error) { func (c *Core) EditMediaServer(ctx context.Context, in *EditMediaServerInput, id string, serverPort int) (*MediaServer, error) {
var out MediaServer var out MediaServer
if err := c.storer.MediaServer().Edit(ctx, &out, func(b *MediaServer) { if err := c.storer.MediaServer().Edit(ctx, &out, func(b *MediaServer) {
if err := copier.Copy(b, in); err != nil { if err := copier.Copy(b, in); err != nil {
@@ -63,6 +63,7 @@ func (c *Core) EditMediaServer(ctx context.Context, in *EditMediaServerInput, id
}, orm.Where("id=?", id)); err != nil { }, orm.Where("id=?", id)); err != nil {
return nil, web.ErrDB.Withf(`Edit err[%s]`, err.Error()) return nil, web.ErrDB.Withf(`Edit err[%s]`, err.Error())
} }
c.connection(&out, serverPort)
return &out, nil return &out, nil
} }

View File

@@ -13,7 +13,7 @@ type MediaServer struct {
CreatedAt orm.Time `gorm:"column:created_at;notNull;default:CURRENT_TIMESTAMP" json:"created_at"` CreatedAt orm.Time `gorm:"column:created_at;notNull;default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt orm.Time `gorm:"column:updated_at;notNull;default:CURRENT_TIMESTAMP" json:"updated_at"` UpdatedAt orm.Time `gorm:"column:updated_at;notNull;default:CURRENT_TIMESTAMP" json:"updated_at"`
HookIP string `gorm:"column:hook_ip;notNull;default:''" json:"hook_ip"` HookIP string `gorm:"column:hook_ip;notNull;default:''" json:"hook_ip"`
SDPIP string `gorm:"column:sdpip;notNull;default:''" json:"sdpip"` SDPIP string `gorm:"column:sdp_ip;notNull;default:''" json:"sdp_ip"`
StreamIP string `gorm:"column:stream_ip;notNull;default:''" json:"stream_ip"` StreamIP string `gorm:"column:stream_ip;notNull;default:''" json:"stream_ip"`
Ports MediaServerPorts `gorm:"column:ports;notNull;default:'{}';type:jsonb" json:"ports"` Ports MediaServerPorts `gorm:"column:ports;notNull;default:'{}';type:jsonb" json:"ports"`
AutoConfig bool `gorm:"column:auto_config;notNull;default:FALSE" json:"auto_config"` AutoConfig bool `gorm:"column:auto_config;notNull;default:FALSE" json:"auto_config"`

View File

@@ -30,25 +30,25 @@ type FindMediaServerInput struct {
} }
type EditMediaServerInput struct { type EditMediaServerInput struct {
IP string `json:"ip"` IP string `json:"ip"`
HookIP string `json:"hook_ip"` HookIP string `json:"hook_ip"`
SDPIP string `json:"sdpip"` SDPIP string `json:"sdpip"`
StreamIP string `json:"stream_ip"` // StreamIP string `json:"stream_ip"`
Ports MediaServerPorts `json:"ports"` // Ports MediaServerPorts `json:"ports"`
AutoConfig bool `json:"auto_config"` // AutoConfig bool `json:"auto_config"`
Secret string `json:"secret"` Secret string `json:"secret"`
HookAliveInterval int `json:"hook_alive_interval"` // HookAliveInterval int `json:"hook_alive_interval"`
RTPEnable bool `json:"rtpenable"` // RTPEnable bool `json:"rtpenable"`
Status bool `json:"status"` // Status bool `json:"status"`
RTPPortRange string `json:"rtpport_range"` // RTPPortRange string `json:"rtpport_range"`
SendRTPPortRange string `json:"send_rtpport_range"` // SendRTPPortRange string `json:"send_rtpport_range"`
RecordAssistPort int `json:"record_assist_port"` // RecordAssistPort int `json:"record_assist_port"`
LastKeepaliveAt orm.Time `json:"last_keepalive_at"` // LastKeepaliveAt orm.Time `json:"last_keepalive_at"`
IsDefault bool `json:"is_default"` // IsDefault bool `json:"is_default"`
RecordDay int `json:"record_day"` // RecordDay int `json:"record_day"`
RecordPath string `json:"record_path"` // RecordPath string `json:"record_path"`
Type string `json:"type"` // Type string `json:"type"`
TranscodeSuffix string `json:"transcode_suffix"` // TranscodeSuffix string `json:"transcode_suffix"`
} }
type AddMediaServerInput struct { type AddMediaServerInput struct {

View File

@@ -126,10 +126,10 @@ func (n *NodeManager) connection(server *MediaServer, serverPort int) {
log.Info("ZLM 服务节点连接中") log.Info("ZLM 服务节点连接中")
for { for i := range 10 {
resp, err := engine.GetServerConfig() resp, err := engine.GetServerConfig()
if err != nil { if err != nil {
log.Error("ZLM 服务节点连接失败", "err", err) log.Error("ZLM 服务节点连接失败", "err", err, "retry", i)
time.Sleep(10 * time.Second) time.Sleep(10 * time.Second)
continue continue
} }

View File

@@ -23,6 +23,7 @@ var startRuntime = time.Now()
func setupRouter(r *gin.Engine, uc *Usecase) { func setupRouter(r *gin.Engine, uc *Usecase) {
uc.GB28181API.uc = uc uc.GB28181API.uc = uc
uc.SMSAPI.uc = uc
go stat.LoadTop(system.Getwd(), func(m map[string]any) { go stat.LoadTop(system.Getwd(), func(m map[string]any) {
_ = m _ = m
}) })
@@ -70,6 +71,7 @@ func setupRouter(r *gin.Engine, uc *Usecase) {
registerGB28181(r, uc.GB28181API) registerGB28181(r, uc.GB28181API)
registerProxy(r, uc.ProxyAPI) registerProxy(r, uc.ProxyAPI)
registerConfig(r, uc.ConfigAPI) registerConfig(r, uc.ConfigAPI)
registerSms(r, uc.SMSAPI)
} }
type playOutput struct { type playOutput struct {

View File

@@ -13,6 +13,7 @@ import (
type SmsAPI struct { type SmsAPI struct {
smsCore sms.Core smsCore sms.Core
uc *Usecase
} }
func NewSMSCore(db *gorm.DB, cfg *conf.Bootstrap) sms.Core { func NewSMSCore(db *gorm.DB, cfg *conf.Bootstrap) sms.Core {
@@ -31,10 +32,11 @@ func registerSms(g gin.IRouter, api SmsAPI, handler ...gin.HandlerFunc) {
{ {
group := g.Group("/media_servers", handler...) group := g.Group("/media_servers", handler...)
group.GET("", web.WarpH(api.findMediaServer)) group.GET("", web.WarpH(api.findMediaServer))
group.GET("/:id", web.WarpH(api.getMediaServer))
group.PUT("/:id", web.WarpH(api.editMediaServer)) group.PUT("/:id", web.WarpH(api.editMediaServer))
group.POST("", web.WarpH(api.addMediaServer))
group.DELETE("/:id", web.WarpH(api.delMediaServer)) // group.GET("/:id", web.WarpH(api.getMediaServer))
// group.POST("", web.WarpH(api.addMediaServer))
// group.DELETE("/:id", web.WarpH(api.delMediaServer))
} }
} }
@@ -52,7 +54,20 @@ func (a SmsAPI) getMediaServer(c *gin.Context, _ *struct{}) (any, error) {
func (a SmsAPI) editMediaServer(c *gin.Context, in *sms.EditMediaServerInput) (any, error) { func (a SmsAPI) editMediaServer(c *gin.Context, in *sms.EditMediaServerInput) (any, error) {
mediaServerID := c.Param("id") mediaServerID := c.Param("id")
return a.smsCore.EditMediaServer(c.Request.Context(), in, mediaServerID) out, err := a.smsCore.EditMediaServer(c.Request.Context(), in, mediaServerID, a.uc.Conf.Server.HTTP.Port)
if err != nil {
return nil, err
}
if mediaServerID == "local" {
a.uc.Conf.Media.IP = out.IP
a.uc.Conf.Media.SDPIP = out.SDPIP
a.uc.Conf.Media.Secret = out.Secret
a.uc.Conf.Media.WebHookIP = out.HookIP
if err := conf.WriteConfig(a.uc.Conf, a.uc.Conf.ConfigPath); err != nil {
return nil, web.ErrServer.Msg(err.Error())
}
}
return out, err
} }
func (a SmsAPI) addMediaServer(c *gin.Context, in *sms.AddMediaServerInput) (any, error) { func (a SmsAPI) addMediaServer(c *gin.Context, in *sms.AddMediaServerInput) (any, error) {

View File

@@ -29,6 +29,7 @@ type Device struct {
IsOnline bool IsOnline bool
Address string Address string
Password string
conn sip.Connection conn sip.Connection
source net.Addr source net.Addr
@@ -63,6 +64,7 @@ func NewDevice(conn sip.Connection, d *gb28181.Device) *Device {
LastKeepaliveAt: d.KeepaliveAt.Time, LastKeepaliveAt: d.KeepaliveAt.Time,
LastRegisterAt: d.RegisteredAt.Time, LastRegisterAt: d.RegisteredAt.Time,
IsOnline: d.IsOnline, IsOnline: d.IsOnline,
Password: d.Password,
} }
return &c return &c

View File

@@ -48,8 +48,9 @@ func (e Engine) SetConfig(cfg Config) Engine {
} }
func (e *Engine) post(path string, data map[string]any, out any) error { func (e *Engine) post(path string, data map[string]any, out any) error {
bodyMap := map[string]any{ bodyMap := make(map[string]any)
"secret": e.cfg.Secret, if e.cfg.Secret != "" {
bodyMap["secret"] = e.cfg.Secret
} }
maps.Copy(bodyMap, data) maps.Copy(bodyMap, data)
body, _ := json.Marshal(bodyMap) body, _ := json.Marshal(bodyMap)