feat: 网元直连接口补充AMF/SMF/MME/IMS

This commit is contained in:
TsMask
2024-12-18 15:26:29 +08:00
parent c4a3b3bc50
commit 9ddae2cb90
9 changed files with 412 additions and 3 deletions

View File

@@ -15,6 +15,7 @@ import (
"be.ems/src/framework/vo/result"
"be.ems/src/modules/network_data/model"
neDataService "be.ems/src/modules/network_data/service"
neFetchlink "be.ems/src/modules/network_element/fetch_link"
neService "be.ems/src/modules/network_element/service"
sysService "be.ems/src/modules/system/service"
"github.com/gin-gonic/gin"
@@ -206,3 +207,36 @@ func (s *AMFController) UEExport(c *gin.Context) {
c.FileAttachment(saveFilePath, fileName)
}
// 接入基站信息列表
//
// GET /nb/list
func (s *AMFController) NbInfoList(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var query struct {
NeId string `form:"neId" binding:"required"`
NbId string `form:"nbId"`
}
if err := c.ShouldBindQuery(&query); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 查询网元信息
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("AMF", query.NeId)
if neInfo.NeId != query.NeId || neInfo.IP == "" {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 网元直连
data, err := neFetchlink.AMFNbInfoList(neInfo, map[string]string{
"nbId": query.NbId,
})
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
c.JSON(200, result.OkData(data))
}

View File

@@ -16,6 +16,7 @@ import (
"be.ems/src/framework/vo/result"
"be.ems/src/modules/network_data/model"
neDataService "be.ems/src/modules/network_data/service"
neFetchlink "be.ems/src/modules/network_element/fetch_link"
neService "be.ems/src/modules/network_element/service"
sysService "be.ems/src/modules/system/service"
"github.com/gin-gonic/gin"
@@ -215,3 +216,68 @@ func (s *IMSController) CDRExport(c *gin.Context) {
c.FileAttachment(saveFilePath, fileName)
}
// 在线会话用户数量
//
// GET /session/num
func (s *IMSController) UeSessionNum(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var query struct {
NeId string `form:"neId" binding:"required"`
}
if err := c.ShouldBindQuery(&query); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 查询网元信息
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("IMS", query.NeId)
if neInfo.NeId != query.NeId || neInfo.IP == "" {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 网元直连
num, err := neFetchlink.IMSUeSessionNum(neInfo)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
c.JSON(200, result.OkData(num))
}
// 在线会话用户列表信息
//
// GET /session/list
func (s *IMSController) UeSessionList(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var query struct {
NeId string `form:"neId" binding:"required"`
IMSI string `form:"imsi"`
MSISDN string `form:"msisdn"`
}
if err := c.ShouldBindQuery(&query); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 查询网元信息
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("IMS", query.NeId)
if neInfo.NeId != query.NeId || neInfo.IP == "" {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 网元直连
data, err := neFetchlink.IMSUeSessionList(neInfo, map[string]string{
"imsi": query.IMSI,
"msisdn": query.MSISDN,
})
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
c.JSON(200, result.OkData(data))
}

View File

@@ -16,6 +16,7 @@ import (
"be.ems/src/framework/vo/result"
"be.ems/src/modules/network_data/model"
neDataService "be.ems/src/modules/network_data/service"
neFetchlink "be.ems/src/modules/network_element/fetch_link"
neService "be.ems/src/modules/network_element/service"
sysService "be.ems/src/modules/system/service"
"github.com/gin-gonic/gin"
@@ -196,3 +197,36 @@ func (s *MMEController) UEExport(c *gin.Context) {
c.FileAttachment(saveFilePath, fileName)
}
// 接入基站信息列表
//
// GET /nb/list
func (s *MMEController) NbInfoList(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var query struct {
NeId string `form:"neId" binding:"required"`
NbId string `form:"nbId"`
}
if err := c.ShouldBindQuery(&query); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 查询网元信息
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("MME", query.NeId)
if neInfo.NeId != query.NeId || neInfo.IP == "" {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 网元直连
data, err := neFetchlink.MMENbInfoList(neInfo, map[string]string{
"nbId": query.NbId,
})
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
c.JSON(200, result.OkData(data))
}

View File

@@ -317,9 +317,39 @@ func (s *SMFController) CDRExport(c *gin.Context) {
c.FileAttachment(saveFilePath, fileName)
}
// 在线订阅用户数量
//
// GET /sub/num
func (s *SMFController) SubUserNum(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var query struct {
NeId string `form:"neId" binding:"required"`
}
if err := c.ShouldBindQuery(&query); err != nil {
c.JSON(400, result.CodeMsg(400, i18n.TKey(language, "app.common.err400")))
return
}
// 查询网元信息
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("SMF", query.NeId)
if neInfo.NeId != query.NeId || neInfo.IP == "" {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))
return
}
// 网元直连
num, err := neFetchlink.SMFSubNum(neInfo)
if err != nil {
c.JSON(200, result.ErrMsg(err.Error()))
return
}
c.JSON(200, result.OkData(num))
}
// 在线订阅用户列表信息
//
// GET /subscribers
// GET /sub/list
func (s *SMFController) SubUserList(c *gin.Context) {
language := ctx.AcceptLanguage(c)
var query struct {
@@ -334,7 +364,7 @@ func (s *SMFController) SubUserList(c *gin.Context) {
return
}
// 查询网元信息 rmUID
// 查询网元信息
neInfo := s.neInfoService.SelectNeInfoByNeTypeAndNeID("SMF", query.NeId)
if neInfo.NeId != query.NeId || neInfo.IP == "" {
c.JSON(200, result.ErrMsg(i18n.TKey(language, "app.common.noNEInfo")))

View File

@@ -59,6 +59,14 @@ func Setup(router *gin.Engine) {
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.imsCDR", collectlogs.BUSINESS_TYPE_EXPORT)),
controller.NewIMS.CDRExport,
)
imsGroup.GET("/session/num",
middleware.PreAuthorize(nil),
controller.NewIMS.UeSessionNum,
)
imsGroup.GET("/session/list",
middleware.PreAuthorize(nil),
controller.NewIMS.UeSessionList,
)
}
// 网元SMSC
@@ -97,7 +105,11 @@ func Setup(router *gin.Engine) {
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.smfCDR", collectlogs.BUSINESS_TYPE_EXPORT)),
controller.NewSMF.CDRExport,
)
smfGroup.GET("/subscribers",
smfGroup.GET("/sub/num",
middleware.PreAuthorize(nil),
controller.NewSMF.SubUserNum,
)
smfGroup.GET("/sub/list",
middleware.PreAuthorize(nil),
controller.NewSMF.SubUserList,
)
@@ -120,6 +132,10 @@ func Setup(router *gin.Engine) {
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.amfUE", collectlogs.BUSINESS_TYPE_EXPORT)),
controller.NewAMF.UEExport,
)
amfGroup.GET("/nb/list",
middleware.PreAuthorize(nil),
controller.NewAMF.NbInfoList,
)
}
// 网元UPF
@@ -256,5 +272,9 @@ func Setup(router *gin.Engine) {
collectlogs.OperateLog(collectlogs.OptionNew("log.operate.title.mmeUE", collectlogs.BUSINESS_TYPE_EXPORT)),
controller.NewMME.UEExport,
)
mmeGroup.GET("/nb/list",
middleware.PreAuthorize(nil),
controller.NewMME.NbInfoList,
)
}
}

View File

@@ -0,0 +1,50 @@
package fetchlink
import (
"encoding/json"
"fmt"
"strings"
"be.ems/src/framework/logger"
"be.ems/src/framework/utils/fetch"
"be.ems/src/modules/network_element/model"
)
// AMFNbInfoList AMF基站信息
//
// 查询参数 {"nbId":"7"}
//
// 返回结果 []
func AMFNbInfoList(neInfo model.NeInfo, data map[string]string) ([]map[string]any, error) {
neUrl := fmt.Sprintf("http://%s:%d/api/rest/ueManagement/v1/elementType/amf/objectType/nbInfo", neInfo.IP, neInfo.Port)
// 查询参数拼接
query := []string{}
if v, ok := data["nbId"]; ok && v != "" {
query = append(query, fmt.Sprintf("nbId=%s", v))
}
if len(query) > 0 {
neUrl = fmt.Sprintf("%s?%s", neUrl, strings.Join(query, "&"))
}
var resData map[string]any
resBytes, err := fetch.Get(neUrl, nil, 60_000)
if err != nil {
errStr := err.Error()
logger.Warnf("AMFNbInfoList Get \"%s\"", neUrl)
logger.Errorf("AMFNbInfoList %s", errStr)
return nil, fmt.Errorf("NeService AMF API Error")
}
// 序列化结果 {"data":[{"id":"7","name":"NR-SA-GNB","address":"192.168.5.100:60110","ueNum":0}]}
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("AMFNbInfoList Unmarshal %s", err.Error())
return nil, err
}
// 固定返回字段,方便前端解析
if v, ok := resData["data"]; ok && v != nil {
return v.([]map[string]any), nil
}
return []map[string]any{}, nil
}

View File

@@ -0,0 +1,94 @@
package fetchlink
import (
"encoding/json"
"fmt"
"strings"
"be.ems/src/framework/logger"
"be.ems/src/framework/utils/fetch"
"be.ems/src/framework/utils/parse"
"be.ems/src/modules/network_element/model"
)
// IMSUeSessionNum IMS会话数量
//
// 返回结果 0
func IMSUeSessionNum(neInfo model.NeInfo) (int64, error) {
neUrl := fmt.Sprintf("http://%s:%d/api/rest/ueManagement/v1/elementType/ims/objectType/ueNum", neInfo.IP, neInfo.Port)
resBytes, err := fetch.Get(neUrl, nil, 60_000)
if err != nil {
errStr := err.Error()
logger.Warnf("IMSUeSessionNum Get \"%s\"", neUrl)
logger.Errorf("IMSUeSessionNum %s", errStr)
return 0, fmt.Errorf("NeService IMS API Error")
}
// 序列化结果 {"data":{"ueNum":0}}
var resData map[string]any
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("IMSUeSessionNum Unmarshal %s", err.Error())
return 0, err
}
// 固定返回字段,方便前端解析
var ueNum int64 = 0
if v, ok := resData["data"]; ok && v != nil {
if num := v.(map[string]any)["ueNum"]; num != nil {
ueNum = parse.Number(num)
}
}
return ueNum, nil
}
// IMSUeSessionList IMS会话列表
//
// 查询参数 {"imsi":"460001230000002","msisdn":"12307551232"}
//
// 返回结果 []
func IMSUeSessionList(neInfo model.NeInfo, data map[string]string) ([]map[string]any, error) {
neUrl := fmt.Sprintf("http://%s:%d/api/rest/ueManagement/v1/elementType/ims/objectType/ueInfo", neInfo.IP, neInfo.Port)
// 查询参数拼接
query := []string{}
if v, ok := data["imsi"]; ok && v != "" {
query = append(query, fmt.Sprintf("imsi=%s", v))
}
if v, ok := data["msisdn"]; ok && v != "" {
query = append(query, fmt.Sprintf("msisdn=%s", v))
}
if len(query) > 0 {
neUrl = fmt.Sprintf("%s?%s", neUrl, strings.Join(query, "&"))
}
resBytes, err := fetch.Get(neUrl, nil, 60_000)
if err != nil {
errStr := err.Error()
logger.Warnf("IMSUeSessionList Get \"%s\"", neUrl)
logger.Errorf("IMSUeSessionList %s", errStr)
return nil, fmt.Errorf("NeService IMS API Error")
}
// 序列化结果
// { "data":[
// {
// "activeTime": "2023-11-29 17:04:54",
// "barring": 0,
// "impu": "sip:12307551232@ims.mnc000.mcc460.3gppnetwork.org",
// "imsi": "460001230000002",
// "msisdn": "12307551232",
// "regState": 1
// }
// ] }
var resData map[string]any
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("IMSUeSessionList Unmarshal %s", err.Error())
return nil, err
}
// 固定返回字段,方便前端解析
if v, ok := resData["data"]; ok && v != nil {
return v.([]map[string]any), nil
}
return []map[string]any{}, nil
}

View File

@@ -0,0 +1,50 @@
package fetchlink
import (
"encoding/json"
"fmt"
"strings"
"be.ems/src/framework/logger"
"be.ems/src/framework/utils/fetch"
"be.ems/src/modules/network_element/model"
)
// MMENbInfoList AMF基站信息
//
// 查询参数 {"nbId":"7"}
//
// 返回结果 []
func MMENbInfoList(neInfo model.NeInfo, data map[string]string) ([]map[string]any, error) {
neUrl := fmt.Sprintf("http://%s:%d/api/rest/ueManagement/v1/elementType/mme/objectType/nbInfo", neInfo.IP, neInfo.Port)
// 查询参数拼接
query := []string{}
if v, ok := data["nbId"]; ok && v != "" {
query = append(query, fmt.Sprintf("nbId=%s", v))
}
if len(query) > 0 {
neUrl = fmt.Sprintf("%s?%s", neUrl, strings.Join(query, "&"))
}
var resData map[string]any
resBytes, err := fetch.Get(neUrl, nil, 60_000)
if err != nil {
errStr := err.Error()
logger.Warnf("MMENbInfoList Get \"%s\"", neUrl)
logger.Errorf("MMENbInfoList %s", errStr)
return nil, fmt.Errorf("NeService AMF API Error")
}
// 序列化结果 {"data":[{"id":"7","name":"NR-SA-GNB","address":"192.168.5.100:60110","ueNum":0}]}
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("MMENbInfoList Unmarshal %s", err.Error())
return nil, err
}
// 固定返回字段,方便前端解析
if v, ok := resData["data"]; ok && v != nil {
return v.([]map[string]any), nil
}
return []map[string]any{}, nil
}

View File

@@ -7,9 +7,40 @@ import (
"be.ems/src/framework/logger"
"be.ems/src/framework/utils/fetch"
"be.ems/src/framework/utils/parse"
"be.ems/src/modules/network_element/model"
)
// SMFSubNum SMF在线订阅用户数量 只含5G用户数据
//
// 返回结果 0
func SMFSubNum(neInfo model.NeInfo) (int64, error) {
neUrl := fmt.Sprintf("http://%s:%d/api/rest/ueManagement/v1/elementType/smf/objectType/ueNum", neInfo.IP, neInfo.Port)
resBytes, err := fetch.Get(neUrl, nil, 60_000)
if err != nil {
errStr := err.Error()
logger.Warnf("SMFSubNum Get \"%s\"", neUrl)
logger.Errorf("SMFSubNum %s", errStr)
return 0, fmt.Errorf("NeService SMF API Error")
}
// 序列化结果 {"data":{"ueNum":0}}
var resData map[string]any
err = json.Unmarshal(resBytes, &resData)
if err != nil {
logger.Errorf("IMSUeSession Unmarshal %s", err.Error())
return 0, err
}
// 固定返回字段,方便前端解析
var ueNum int64 = 0
if v, ok := resData["data"]; ok && v != nil {
if num := v.(map[string]any)["ueNum"]; num != nil {
ueNum = parse.Number(num)
}
}
return ueNum, nil
}
// SMFSubInfoList SMF在线订阅用户列表信息
//
// 查询参数 {"imsi":"360000100000130","msisdn":"8612300000130","upstate":"Inactive","pageNum":"1"}