Files
be.ems/features/event/event.go

249 lines
8.1 KiB
Go

package event
import (
"encoding/json"
"fmt"
"net/http"
"strings"
"time"
"be.ems/lib/config"
"be.ems/lib/core/ctx"
"be.ems/lib/log"
"be.ems/lib/services"
"be.ems/src/framework/database/db"
"be.ems/src/framework/utils/date"
"be.ems/src/framework/utils/parse"
neService "be.ems/src/modules/network_element/service"
wsService "be.ems/src/modules/ws/service"
"github.com/gin-gonic/gin"
)
var (
// 走Gin
UriUEEventAMF = "/upload-ue/v1/:eventType"
// 走Mux
UriUEEvent = config.DefaultUriPrefix + "/logManagement/v1/elementType/{elementTypeValue}/objectType/ueEvent"
CustomUriUEEvent = config.UriPrefix + "/logManagement/v1/elementType/{elementTypeValue}/objectType/ueEvent"
)
// 旧AMF上报处理
func PostUEEventFromAMF(c *gin.Context) {
log.Info("PostUEEventFromAMF processing... ")
eventType := c.Param("eventType")
if eventType == "" {
log.Error("eventType is empty")
services.ResponseNotFound404UriNotExist(c.Writer, c.Request)
return
}
var body map[string]any
if err := c.ShouldBindBodyWithJSON(&body); err != nil {
log.Error("Failed to Unmarshal ueEvent:", err)
services.ResponseInternalServerError500ProcessError(c.Writer, err)
return
}
// 执行插入表
type UEEvent struct {
ID string `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
NeType string `json:"neType" gorm:"column:ne_type"`
NeName string `json:"neName" gorm:"column:ne_name"`
RmUID string `json:"rmUID" gorm:"column:rm_uid"` // 可能没有
Timestamp int64 `json:"timestamp" gorm:"column:timestamp"` // 接收到的timestamp秒级存储毫秒时间戳
EventType string `json:"eventType" gorm:"column:event_type"` // 事件类型 auth-result detach cm-state
EventJSONStr string `json:"eventJSON" gorm:"column:event_json"` // data JSON String
CreatedAt int64 `json:"createdAt" gorm:"column:created_at"` // 记录创建存储毫秒
}
timestamp := time.Now().UnixMilli()
data := UEEvent{
NeType: "AMF",
NeName: "",
RmUID: "",
Timestamp: timestamp,
EventType: eventType,
EventJSONStr: "",
CreatedAt: timestamp,
}
// 从eventJson中获取rmUID
if v, ok := body["rmUID"]; ok {
data.RmUID = fmt.Sprint(v)
} else {
data.RmUID = "4400HXAMF001"
}
if v, ok := body["neName"]; ok {
data.NeName = fmt.Sprint(v)
} else {
data.NeName = "AMF_001"
}
// 是否存在网元
neInfo := neService.NewNeInfo.FindByRmuid(data.RmUID)
if neInfo.NeType != "AMF" || neInfo.RmUID != data.RmUID {
services.ResponseInternalServerError500ProcessError(c.Writer, fmt.Errorf("network element does not exist"))
return
}
// 统一格式
eventJson := map[string]any{"cellID": 0, "gNBID": "", "imsi": "", "onlineNumber": 0, "result": "", "tacID": 0, "timestamp": 0, "time": 0, "type": eventType}
switch eventType {
case "auth-result":
// {"authCode":"200","authMessage":"成功","authTime":"2024-12-07 16:48:37","cellID":"3","gNBID":"1","imsi":"460002082100000","onlineNumber":1,"tacID":"81"}
if v, ok := body["imsi"]; ok {
eventJson["imsi"] = fmt.Sprint(v)
}
if v, ok := body["cellID"]; ok {
eventJson["cellID"] = fmt.Sprint(v)
}
if v, ok := body["gNBID"]; ok {
eventJson["gNBID"] = fmt.Sprint(v)
}
if v, ok := body["tacID"]; ok {
eventJson["tacID"] = fmt.Sprint(v)
}
if v, ok := body["onlineNumber"]; ok {
eventJson["onlineNumber"] = parse.Number(v)
}
if v, ok := body["authCode"]; ok {
eventJson["result"] = fmt.Sprint(v)
}
if v, ok := body["authTime"]; ok {
authTime := date.ParseStrToDate(fmt.Sprint(v), date.YYYY_MM_DD_HH_MM_SS)
eventJson["timestamp"] = authTime.Unix()
eventJson["time"] = fmt.Sprint(v)
}
case "detach":
// {"detachResult":0,"detachTime":"2024-12-07 18:00:47","imsi":"460002082100000"}
if v, ok := body["imsi"]; ok {
eventJson["imsi"] = fmt.Sprint(v)
}
if v, ok := body["detachResult"]; ok {
if fmt.Sprint(v) == "0" {
eventJson["result"] = "200"
} else {
eventJson["result"] = "500"
}
}
if v, ok := body["detachTime"]; ok {
detachTime := date.ParseStrToDate(fmt.Sprint(v), date.YYYY_MM_DD_HH_MM_SS)
eventJson["timestamp"] = detachTime.Unix()
eventJson["time"] = fmt.Sprint(v)
}
case "cm-state":
// {"changeTime":"2024-12-07 17:07:52","imsi":"460002082100000","onlineNumber":1,"status":2}
if v, ok := body["imsi"]; ok {
eventJson["imsi"] = fmt.Sprint(v)
}
if v, ok := body["onlineNumber"]; ok {
eventJson["onlineNumber"] = parse.Number(v)
}
if v, ok := body["status"]; ok {
eventJson["result"] = fmt.Sprint(v)
}
if v, ok := body["changeTime"]; ok {
changeTime := date.ParseStrToDate(fmt.Sprint(v), date.YYYY_MM_DD_HH_MM_SS)
eventJson["timestamp"] = changeTime.Unix()
eventJson["time"] = fmt.Sprint(v)
}
}
ueByte, err := json.Marshal(eventJson)
if err != nil {
services.ResponseInternalServerError500ProcessError(c.Writer, err)
return
}
data.EventJSONStr = string(ueByte)
if err := db.DB("").Table("ue_event_amf").Create(&data).Error; err != nil {
log.Error("Failed to insert ue_event_amf", err)
services.ResponseInternalServerError500ProcessError(c.Writer, err)
return
}
// 推送到ws订阅组
if data.NeType == "AMF" {
wsService.NewWSSend.ByGroupID(wsService.GROUP_AMF_UE, data)
wsService.NewWSSend.ByGroupID(wsService.GROUP_AMF_UE+"_"+neInfo.NeId, data)
}
services.ResponseStatusOK204NoContent(c.Writer)
}
// UE上报处理
func PostUEEvent(w http.ResponseWriter, r *http.Request) {
log.Info("PostUEEvent processing... ")
neType := ctx.GetParam(r, "elementTypeValue")
var body struct {
NeType string `json:"neType" `
NeName string `json:"neName" `
RmUID string `json:"rmUID" `
Timestamp int64 `json:"timestamp" `
EventType string `json:"eventType" `
EventJson map[string]any `json:"eventJSON" `
}
if err := ctx.ShouldBindJSON(r, &body); err != nil {
services.ResponseInternalServerError500ProcessError(w, err)
return
}
neTypeLower := strings.ToLower(body.NeType)
if neType == "" || neType != neTypeLower {
services.ResponseInternalServerError500ProcessError(w, fmt.Errorf("inconsistent network element types"))
return
}
// 是否存在网元
neInfo := neService.NewNeInfo.FindByRmuid(body.RmUID)
if neInfo.NeType != body.NeType || neInfo.RmUID != body.RmUID {
services.ResponseInternalServerError500ProcessError(w, fmt.Errorf("network element does not exist"))
return
}
ueByte, err := json.Marshal(body.EventJson)
if err != nil {
services.ResponseInternalServerError500ProcessError(w, err)
return
}
// 执行插入表
type UEEvent struct {
ID string `json:"-" gorm:"column:id;primaryKey;autoIncrement"`
NeType string `json:"neType" gorm:"column:ne_type"`
NeName string `json:"neName" gorm:"column:ne_name"`
RmUID string `json:"rmUID" gorm:"column:rm_uid"` // 可能没有
Timestamp int64 `json:"timestamp" gorm:"column:timestamp"` // 接收到的timestamp秒级存储毫秒时间戳
EventType string `json:"eventType" gorm:"column:event_type"` // 事件类型 auth-result detach cm-state
EventJSONStr string `json:"eventJSON" gorm:"column:event_json"` // data JSON String
CreatedAt int64 `json:"-" gorm:"column:created_at"` // 记录创建存储毫秒
}
data := UEEvent{
NeType: body.NeType,
NeName: body.NeName,
RmUID: body.RmUID,
Timestamp: int64(body.Timestamp) * 1000,
EventType: body.EventType,
EventJSONStr: string(ueByte),
CreatedAt: time.Now().UnixMilli(),
}
tableName := fmt.Sprintf("ue_event_%s", neTypeLower)
if err := db.DB("").Table(tableName).Create(&data).Error; err != nil {
log.Error("Failed to insert "+tableName, err)
services.ResponseInternalServerError500ProcessError(w, err)
return
}
// 推送到ws订阅组
if body.NeType == "MME" {
wsService.NewWSSend.ByGroupID(wsService.GROUP_MME_UE, data)
wsService.NewWSSend.ByGroupID(wsService.GROUP_MME_UE+"_"+neInfo.NeId, data)
}
if body.NeType == "AMF" {
wsService.NewWSSend.ByGroupID(wsService.GROUP_AMF_UE, data)
wsService.NewWSSend.ByGroupID(wsService.GROUP_AMF_UE+"_"+neInfo.NeId, data)
}
services.ResponseStatusOK204NoContent(w)
}