zlm api 测试
补充部分注释
This commit is contained in:
parent
7909229664
commit
529e9fc375
@ -11,6 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func GenerateConfig() error {
|
func GenerateConfig() error {
|
||||||
|
// 生成配置文件
|
||||||
p, _ := filepath.Abs("./config.toml")
|
p, _ := filepath.Abs("./config.toml")
|
||||||
|
|
||||||
flag := os.O_RDWR
|
flag := os.O_RDWR
|
||||||
@ -35,6 +36,7 @@ func GenerateConfig() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ReadClientConfig() (*ClientConfig, error) {
|
func ReadClientConfig() (*ClientConfig, error) {
|
||||||
|
// 读取客户端配置文件,如果不存在则生成示例配置
|
||||||
viper.SetConfigName(constants.ConfigFileName)
|
viper.SetConfigName(constants.ConfigFileName)
|
||||||
viper.SetConfigType(constants.ConfigType)
|
viper.SetConfigType(constants.ConfigType)
|
||||||
for _, path := range constants.ConfigPaths {
|
for _, path := range constants.ConfigPaths {
|
||||||
|
@ -9,17 +9,28 @@ import (
|
|||||||
"github.com/emiago/sipgo/sip"
|
"github.com/emiago/sipgo/sip"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// messageHandler 是一个处理SIP消息的函数类型
|
||||||
type messageHandler = func(client *sipgo.Client, clientConfig *config.ClientConfig, req *sip.Request, tx sip.ServerTransaction)
|
type messageHandler = func(client *sipgo.Client, clientConfig *config.ClientConfig, req *sip.Request, tx sip.ServerTransaction)
|
||||||
|
|
||||||
|
// handlers 是一个存储消息处理器的映射,键为命令类型,值为消息处理器函数
|
||||||
var handlers = make(map[string]messageHandler)
|
var handlers = make(map[string]messageHandler)
|
||||||
|
|
||||||
|
// SetupMessageHandler 设置SIP服务器的消息处理器,根据消息的命令类型调用相应的处理器
|
||||||
func SetupMessageHandler(srv *sipgo.Server, client *sipgo.Client, clientConfig *config.ClientConfig) {
|
func SetupMessageHandler(srv *sipgo.Server, client *sipgo.Client, clientConfig *config.ClientConfig) {
|
||||||
srv.OnMessage(func(req *sip.Request, tx sip.ServerTransaction) {
|
srv.OnMessage(func(req *sip.Request, tx sip.ServerTransaction) {
|
||||||
body := req.Body()
|
body := req.Body()
|
||||||
|
if len(body) == 0 {
|
||||||
|
log.Log().Warn().Msgf("消息体为空")
|
||||||
|
_ = tx.Respond(sip.NewResponseFromRequest(req, sip.StatusOK, "OK", nil))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
message := new(manscdp.MessageReq)
|
message := new(manscdp.MessageReq)
|
||||||
err := utils.XMLUnmarshal(body, message)
|
err := utils.XMLUnmarshal(body, message)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Log().Error().Msgf("XML Unmarshal error: %v", err)
|
log.Log().Error().Msgf("XML Unmarshal error: %v", err)
|
||||||
|
_ = tx.Respond(sip.NewResponseFromRequest(req, sip.StatusBadRequest, "Bad Request", nil))
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
handlers, ok := handlers[message.CmdType]
|
handlers, ok := handlers[message.CmdType]
|
||||||
|
@ -2,6 +2,7 @@ package manscdp
|
|||||||
|
|
||||||
import "encoding/xml"
|
import "encoding/xml"
|
||||||
|
|
||||||
|
// CatalogReq 定义了查询目录的请求结构
|
||||||
type CatalogReq struct {
|
type CatalogReq struct {
|
||||||
XMLName xml.Name `xml:"Query"`
|
XMLName xml.Name `xml:"Query"`
|
||||||
CmdType string `xml:"CmdType"`
|
CmdType string `xml:"CmdType"`
|
||||||
@ -9,6 +10,7 @@ type CatalogReq struct {
|
|||||||
DeviceID string `xml:"DeviceID"`
|
DeviceID string `xml:"DeviceID"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CatalogResp 定义了查询目录的响应结构
|
||||||
type CatalogResp struct {
|
type CatalogResp struct {
|
||||||
XMLName xml.Name `xml:"Response"`
|
XMLName xml.Name `xml:"Response"`
|
||||||
CmdType string `xml:"CmdType"`
|
CmdType string `xml:"CmdType"`
|
||||||
@ -18,12 +20,14 @@ type CatalogResp struct {
|
|||||||
DeviceID string `xml:"DeviceID"`
|
DeviceID string `xml:"DeviceID"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CateLogDeviceList 定义了设备列表的结构
|
||||||
type CateLogDeviceList struct {
|
type CateLogDeviceList struct {
|
||||||
XMLName xml.Name `xml:"DeviceList"`
|
XMLName xml.Name `xml:"DeviceList"`
|
||||||
Num string `xml:"Num,attr"`
|
Num string `xml:"Num,attr"`
|
||||||
Item []CateLogDevice `xml:"Item"`
|
Item []CateLogDevice `xml:"Item"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CateLogDevice 定义了单个设备的详细信息结构
|
||||||
type CateLogDevice struct {
|
type CateLogDevice struct {
|
||||||
XMLName xml.Name `xml:"Item"`
|
XMLName xml.Name `xml:"Item"`
|
||||||
Name string `xml:"Name"`
|
Name string `xml:"Name"`
|
||||||
|
@ -2,6 +2,7 @@ package manscdp
|
|||||||
|
|
||||||
import "encoding/xml"
|
import "encoding/xml"
|
||||||
|
|
||||||
|
// MessageReq 定义了查询消息的请求结构体,使用XML格式进行序列化和反序列化
|
||||||
type MessageReq struct {
|
type MessageReq struct {
|
||||||
XMLName xml.Name `xml:"Query"`
|
XMLName xml.Name `xml:"Query"`
|
||||||
CmdType string `xml:"CmdType"`
|
CmdType string `xml:"CmdType"`
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package zlmediakit
|
package zlmediakit
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"git.skcks.cn/Shikong/go-gb28181/pkg/services/zlmediakit/types"
|
||||||
"github.com/go-resty/resty/v2"
|
"github.com/go-resty/resty/v2"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -22,3 +24,51 @@ func SetupZLMediaKitService(config *Config) {
|
|||||||
client: client,
|
client: client,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetZLMediaKitService() *ZLMediaKit {
|
||||||
|
return zLMediaKitService
|
||||||
|
}
|
||||||
|
|
||||||
|
func (z *ZLMediaKit) GetApiList() (data *types.Data[[]string], err error) {
|
||||||
|
resp, err := z.client.R().Get("/index/api/getApiList")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
data = new(types.Data[[]string])
|
||||||
|
err = json.Unmarshal(resp.Body(), data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (z *ZLMediaKit) GetServerConfig() (data *types.ServerConfigResp, err error) {
|
||||||
|
resp, err := z.client.R().Get("/index/api/getServerConfig")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
data = new(types.ServerConfigResp)
|
||||||
|
err = json.Unmarshal(resp.Body(), data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (z *ZLMediaKit) SetServerConfig(config *types.ServerConfig) (data *types.SetServerConfigResp, err error) {
|
||||||
|
resp, err := z.client.R().
|
||||||
|
SetBody(config).
|
||||||
|
Post("/index/api/setServerConfig")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
data = new(types.SetServerConfigResp)
|
||||||
|
err = json.Unmarshal(resp.Body(), data)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return data, nil
|
||||||
|
}
|
||||||
|
@ -5,18 +5,22 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"git.skcks.cn/Shikong/go-gb28181/pkg/services/zlmediakit/types"
|
"git.skcks.cn/Shikong/go-gb28181/pkg/services/zlmediakit/types"
|
||||||
"github.com/duke-git/lancet/v2/convertor"
|
"github.com/duke-git/lancet/v2/convertor"
|
||||||
|
"github.com/duke-git/lancet/v2/formatter"
|
||||||
"github.com/duke-git/lancet/v2/netutil"
|
"github.com/duke-git/lancet/v2/netutil"
|
||||||
"github.com/go-resty/resty/v2"
|
"github.com/go-resty/resty/v2"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestZLMediaKit(t *testing.T) {
|
func TestZLMediaKit(t *testing.T) {
|
||||||
|
// 设置ZLMediaKit服务,传入配置信息
|
||||||
SetupZLMediaKitService(&Config{
|
SetupZLMediaKitService(&Config{
|
||||||
Id: "amrWMKmbKqoBjRQ9",
|
Id: "amrWMKmbKqoBjRQ9",
|
||||||
Url: "http://10.10.10.200:5081",
|
Url: "http://10.10.10.200:5081",
|
||||||
Secret: "4155cca6-2f9f-11ee-85e6-8de4ce2e7333",
|
Secret: "4155cca6-2f9f-11ee-85e6-8de4ce2e7333",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 获取媒体列表并检查响应
|
||||||
resp, err := zLMediaKitService.client.R().Get("/index/api/getMediaList")
|
resp, err := zLMediaKitService.client.R().Get("/index/api/getMediaList")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -27,6 +31,67 @@ func TestZLMediaKit(t *testing.T) {
|
|||||||
for _, datum := range data.Data {
|
for _, datum := range data.Data {
|
||||||
t.Logf("%+v\n", datum)
|
t.Logf("%+v\n", datum)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取ZLMediaKit服务实例
|
||||||
|
service := GetZLMediaKitService()
|
||||||
|
|
||||||
|
// 获取API列表并打印数据
|
||||||
|
apiList, err := service.GetApiList()
|
||||||
|
printData(apiList, err, t)
|
||||||
|
|
||||||
|
// 打印分隔线
|
||||||
|
t.Log(strings.Repeat("=", 50))
|
||||||
|
|
||||||
|
// 获取服务器配置并打印数据
|
||||||
|
getConfigResp, err := service.GetServerConfig()
|
||||||
|
printData(getConfigResp, err, t)
|
||||||
|
|
||||||
|
// 深度克隆配置并修改SRT超时时间,然后设置服务器配置
|
||||||
|
config := convertor.DeepClone(getConfigResp.Data[0])
|
||||||
|
config.SrtTimeoutSec = "5"
|
||||||
|
serverConfigResp, err := service.SetServerConfig(&config)
|
||||||
|
printResp(serverConfigResp, err, t)
|
||||||
|
|
||||||
|
// 再次获取服务器配置并打印数据,以验证修改是否成功
|
||||||
|
getConfigResp, err = service.GetServerConfig()
|
||||||
|
printData(getConfigResp, err, t)
|
||||||
|
|
||||||
|
// 打印分隔线
|
||||||
|
t.Log(strings.Repeat("=", 50))
|
||||||
|
}
|
||||||
|
|
||||||
|
func printResp[T any](data *T, err error, t *testing.T) {
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
} else {
|
||||||
|
pretty, _ := formatter.Pretty(data)
|
||||||
|
t.Log(pretty)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func printData[T any](data *types.Data[T], err error, t *testing.T) {
|
||||||
|
if err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
} else {
|
||||||
|
|
||||||
|
switch x := interface{}(data.Data).(type) {
|
||||||
|
case string, int, int64, float32, float64, bool, nil, []byte:
|
||||||
|
t.Log(x)
|
||||||
|
|
||||||
|
case []any:
|
||||||
|
for _, s := range x {
|
||||||
|
t.Logf("\t%+v\n", s)
|
||||||
|
}
|
||||||
|
case []string:
|
||||||
|
for _, s := range x {
|
||||||
|
t.Logf("\t%+v\n", s)
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
result, _ := formatter.Pretty(x)
|
||||||
|
t.Logf("%s\n", result)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestZLMediaKit_API(t *testing.T) {
|
func TestZLMediaKit_API(t *testing.T) {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package types
|
package types
|
||||||
|
|
||||||
|
// Data 是一个泛型结构体,用于封装 API 响应的数据
|
||||||
type Data[T any] struct {
|
type Data[T any] struct {
|
||||||
Code int `json:"code"`
|
Code int `json:"code"`
|
||||||
Data T `json:"data"`
|
Data T `json:"data"`
|
||||||
|
@ -4,6 +4,11 @@ type ServerConfigResp = Data[ServerConfigRespRaw]
|
|||||||
|
|
||||||
type ServerConfigRespRaw = []ServerConfig
|
type ServerConfigRespRaw = []ServerConfig
|
||||||
|
|
||||||
|
type SetServerConfigResp struct {
|
||||||
|
Code int `json:"code"`
|
||||||
|
Changed int `json:"changed"`
|
||||||
|
}
|
||||||
|
|
||||||
type ServerConfig struct {
|
type ServerConfig struct {
|
||||||
ApiApiDebug string `json:"api.apiDebug"`
|
ApiApiDebug string `json:"api.apiDebug"`
|
||||||
ApiDefaultSnap string `json:"api.defaultSnap"`
|
ApiDefaultSnap string `json:"api.defaultSnap"`
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// XMLMarshalString 将给定的对象v序列化为XML字符串,并指定字符集charset
|
||||||
func XMLMarshalString(v interface{}, charset string) (string, error) {
|
func XMLMarshalString(v interface{}, charset string) (string, error) {
|
||||||
marshal, err := XMLMarshal(v, charset)
|
marshal, err := XMLMarshal(v, charset)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -20,6 +21,7 @@ func XMLMarshalString(v interface{}, charset string) (string, error) {
|
|||||||
return string(marshal), nil
|
return string(marshal), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XMLMarshal 将给定的对象obj序列化为XML格式的字节数组,并指定字符集charset
|
||||||
func XMLMarshal(obj interface{}, charset string) ([]byte, error) {
|
func XMLMarshal(obj interface{}, charset string) ([]byte, error) {
|
||||||
marshal := &bytes.Buffer{}
|
marshal := &bytes.Buffer{}
|
||||||
encoder := xml.NewEncoder(marshal)
|
encoder := xml.NewEncoder(marshal)
|
||||||
@ -69,6 +71,7 @@ func XMLMarshal(obj interface{}, charset string) ([]byte, error) {
|
|||||||
return xmlBytes.Bytes(), nil
|
return xmlBytes.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XMLUnmarshal 将XML格式的字节数组data反序列化为对象obj
|
||||||
func XMLUnmarshal(data []byte, obj interface{}) error {
|
func XMLUnmarshal(data []byte, obj interface{}) error {
|
||||||
decoder := xml.NewDecoder(bytes.NewReader(data))
|
decoder := xml.NewDecoder(bytes.NewReader(data))
|
||||||
decoder.CharsetReader = func(c string, input io.Reader) (io.Reader, error) {
|
decoder.CharsetReader = func(c string, input io.Reader) (io.Reader, error) {
|
||||||
|
Loading…
Reference in New Issue
Block a user