package service import ( "fmt" "strconv" "strings" "be.ems/src/framework/redis" "be.ems/src/modules/network_data/model" "be.ems/src/modules/network_data/repository" neService "be.ems/src/modules/network_element/service" ) // 实例化服务层 UDMSubUser 结构体 var NewUDMSubUser = &UDMSubUser{ udmSubRepository: repository.NewUDMSub, udmUserInfoRepository: repository.NewUDMUserInfo, } // UDM签约信息 服务层处理 type UDMSubUser struct { udmSubRepository *repository.UDMSubUser // UDM签约信息数据信息 udmUserInfoRepository *repository.UDMUserInfo // UDM用户IMSI信息数据信息 } // dataByRedis UDM签约用户 db:0 中 udm-sd:* func (r *UDMSubUser) dataByRedis(imsi, neId string) []model.UDMSubUser { arr := []model.UDMSubUser{} key := fmt.Sprintf("udm-sd:%s", imsi) source := fmt.Sprintf("UDM_%s", neId) // 网元主机的Redis客户端 redisClient, err := neService.NewNeInfo.NeRunRedisClient("UDM", neId) if err != nil { return arr } defer func() { redisClient.Close() redis.ConnectPush(source, nil) }() redis.ConnectPush(source, redisClient.Client) udmsdArr, err := redis.GetKeys(source, key) if err != nil { return arr } for _, key := range udmsdArr { m, err := redis.GetHash(source, key) if err != nil { continue } a := model.UDMSubUser{ IMSI: key[7:], // udm-sd:360000100000130 MSISDN: m["gpsi"], // 8612300000130 NeId: neId, SmfSel: m["smf-sel"], // def_snssai SmData: m["sm-dat"], // 1-000001&cmnet&ims&3gnet Cag: m["cag"], // def_cag } // def_ambr,def_nssai,0,def_arfb,def_sar,3,1,12000,1,1000,0,1,- if v, ok := m["am-dat"]; ok { arr := strings.Split(v, ",") a.AmDat = v a.UeAmbrTpl = arr[0] a.NssaiTpl = arr[1] a.RatRestrictions = arr[2] a.AreaForbiddenTpl = arr[3] a.ServiceAreaRestrictionTpl = arr[4] a.CnTypeRestrictions = arr[5] a.RfspIndex = arr[6] a.SubsRegTime = arr[7] a.UeUsageType = arr[8] a.ActiveTime = arr[9] a.MicoAllowed = "0" // arr[10] a.OdbPs = "1" // arr[11] a.GroupId = "-" // arr[12] if len(arr) > 10 { a.MicoAllowed = arr[10] } if len(arr) > 11 { a.OdbPs = arr[11] } if len(arr) > 12 && arr[12] != "-" { a.GroupId = arr[12] } } // 1,64,24,65,def_eps,1,2,010200000000,- if v, ok := m["eps-dat"]; ok { arr := strings.Split(v, ",") // 跳过非常规数据 if len(arr) > 9 { continue } a.EpsDat = v a.EpsFlag = arr[0] a.EpsOdb = arr[1] a.HplmnOdb = arr[2] a.Ard = arr[3] a.Epstpl = arr[4] a.ContextId = arr[5] a.ApnNum = arr[6] // 导入和导出不用 a.ApnContext = arr[7] if len(arr) >= 9 { a.StaticIp = arr[8] } } arr = append(arr, a) } return arr } // ResetData 重置鉴权用户数据,清空数据库重新同步Redis数据 func (r *UDMSubUser) ResetData(neId string) int64 { subArr := r.dataByRedis("*", neId) // 数据清空后添加 go r.udmSubRepository.ClearAndInsert(neId, subArr) return int64(len(subArr)) } // ParseInfo 解析单个用户imsi签约信息 data从命令MML得到的结果 func (r *UDMSubUser) ParseInfo(imsi, neId string, data map[string]string) model.UDMSubUser { u := r.udmSubRepository.SelectByIMSIAndNeID(imsi, neId) cnType, _ := strconv.ParseInt(data["CNType"][:4], 0, 64) // 0x03(EPC|5GC) rat, _ := strconv.ParseInt(data["RAT"][:4], 0, 64) // 0x00(VIRTUAL|WLAN|EUTRA|NR) msisdn := data["MSISDN"] if imsMsisdnLen := strings.Index(msisdn, ","); imsMsisdnLen != -1 { msisdn = msisdn[:imsMsisdnLen] } // 用于更新 u.IMSI = imsi u.MSISDN = msisdn u.NeId = neId u.UeAmbrTpl = data["AMBR"] u.NssaiTpl = data["NSSAI"] u.AreaForbiddenTpl = data["AreaForbidden"] u.ServiceAreaRestrictionTpl = data["ServiceAreaRestriction"] u.CnTypeRestrictions = fmt.Sprint(cnType) u.RatRestrictions = fmt.Sprint(rat) u.MicoAllowed = data["MICO"] u.SmData = data["SM-Data(snssai+dnn[1..n])"] u.SmfSel = data["Smf-Selection"] u.Cag = data["cag"] // 1,64,24,65,def_eps,1,2,010200000000,- if v, ok := data["EPS-Data"]; ok { u.EpsDat = v arr := strings.Split(v, ",") u.EpsFlag = arr[0] u.EpsOdb = arr[1] u.HplmnOdb = arr[2] u.Ard = arr[3] u.Epstpl = arr[4] u.ContextId = arr[5] u.ApnNum = arr[6] // 导入和导出不用 u.ApnContext = arr[7] u.StaticIp = arr[8] } // 补充用户拓展信息 info := r.udmUserInfoRepository.SelectByIMSIAndNeID(imsi, neId) if info.IMSI == imsi { u.Remark = info.Remark } return u } // SelectPage 分页查询数据库 func (r *UDMSubUser) SelectPage(query map[string]any) map[string]any { return r.udmSubRepository.SelectPage(query) } // SelectList 查询数据库 func (r *UDMSubUser) SelectList(u model.UDMSubUser) []model.UDMSubUser { return r.udmSubRepository.SelectList(u) } // Insert 从数据中读取后删除imsi再存入数据库 // imsi长度15,ki长度32,opc长度0或者32 func (r *UDMSubUser) Insert(neId string, u model.UDMSubUser) int64 { uArr := r.dataByRedis(u.IMSI, neId) if len(uArr) > 0 { r.udmSubRepository.Delete(u.IMSI, neId) // 新增到拓展信息 if u.Remark != "" { r.udmUserInfoRepository.Delete(u.IMSI, neId) r.udmUserInfoRepository.Inserts([]model.UDMUserInfo{{ IMSI: u.IMSI, MSISDN: u.MSISDN, NeId: u.NeId, Remark: u.Remark, }}) } return r.udmSubRepository.Inserts(uArr) } return 0 } // InsertData 导入文件数据 dataType目前两种:txt/csv func (r *UDMSubUser) InsertData(neId, dataType string, data any) int64 { // imsi截取前缀,重新获取部分数据 prefixes := make(map[string]struct{}) if dataType == "csv" { for _, v := range data.([]map[string]string) { imsi := v["imsi"] if len(imsi) < 6 { continue } prefix := imsi[:len(imsi)-4] prefixes[prefix] = struct{}{} } } if dataType == "txt" { for _, v := range data.([][]string) { imsi := v[0] if len(imsi) < 6 { continue } prefix := imsi[:len(imsi)-4] prefixes[prefix] = struct{}{} } } // 根据前缀重新加载插入 var num int64 = 0 for prefix := range prefixes { // keys udm-sd:4600001000004* arr := r.dataByRedis(prefix+"*", neId) if len(arr) > 0 { r.udmSubRepository.DeletePrefixByIMSI(prefix, neId) num += r.udmSubRepository.Inserts(arr) } } return num } // Delete 删除单个不重新加载 func (r *UDMSubUser) Delete(neId, imsi string) int64 { // 删除拓展信息 r.udmUserInfoRepository.Delete(imsi, neId) return r.udmSubRepository.Delete(imsi, neId) } // LoadData 重新加载从imsi开始num的数据 // remark不为空,则新增到拓展信息,删除标记为-(Deleted)- func (r *UDMSubUser) LoadData(neId, imsi, num, remark string) { startIMSI, _ := strconv.ParseInt(imsi, 10, 64) subNum, _ := strconv.ParseInt(num, 10, 64) var i int64 for i = 0; i < subNum; i++ { keyIMSI := fmt.Sprintf("%015d", startIMSI+i) // 删除原数据 r.udmSubRepository.Delete(keyIMSI, neId) if remark == "-(Deleted)-" { r.udmUserInfoRepository.Delete(keyIMSI, neId) } // 加载数据 arr := r.dataByRedis(keyIMSI, neId) if len(arr) < 1 { continue } r.udmSubRepository.Inserts(arr) // 拓展信息 if remark != "" { uarr := make([]model.UDMUserInfo, 0, len(arr)) for _, v := range arr { uarr = append(uarr, model.UDMUserInfo{ IMSI: v.IMSI, MSISDN: v.MSISDN, NeId: v.NeId, Remark: remark, }) } r.udmUserInfoRepository.Delete(keyIMSI, neId) r.udmUserInfoRepository.Inserts(uarr) } } } // ParseCommandParams 解析数据组成命令参数 msisdn=xx,xx=xx,... func (r *UDMSubUser) ParseCommandParams(item model.UDMSubUser) string { var conditions []string if item.MSISDN != "" { conditions = append(conditions, fmt.Sprintf("msisdn=%s", item.MSISDN)) } // AmData if item.UeAmbrTpl != "" { conditions = append(conditions, fmt.Sprintf("ambr=%s", item.UeAmbrTpl)) } if item.NssaiTpl != "" { conditions = append(conditions, fmt.Sprintf("nssai=%s", item.NssaiTpl)) } if item.AreaForbiddenTpl != "" { conditions = append(conditions, fmt.Sprintf("arfb=%s", item.AreaForbiddenTpl)) } if item.ServiceAreaRestrictionTpl != "" { conditions = append(conditions, fmt.Sprintf("sar=%s", item.ServiceAreaRestrictionTpl)) } if item.RatRestrictions != "" { conditions = append(conditions, fmt.Sprintf("rat=%s", item.RatRestrictions)) } if item.CnTypeRestrictions != "" { conditions = append(conditions, fmt.Sprintf("cn=%s", item.CnTypeRestrictions)) } if item.MicoAllowed != "" { conditions = append(conditions, fmt.Sprintf("mico=%s", item.MicoAllowed)) } // EpsDat // if item.EpsDat != "" { // conditions = append(conditions, fmt.Sprintf("eps_dat=%s", item.EpsDat)) // } if item.EpsFlag != "" { conditions = append(conditions, fmt.Sprintf("eps_flag=%s", item.EpsFlag)) } if item.EpsOdb != "" { conditions = append(conditions, fmt.Sprintf("eps_odb=%s", item.EpsOdb)) } if item.HplmnOdb != "" { conditions = append(conditions, fmt.Sprintf("hplmn_odb=%s", item.HplmnOdb)) } if item.Epstpl != "" { conditions = append(conditions, fmt.Sprintf("epstpl=%s", item.Epstpl)) } if item.Ard != "" { conditions = append(conditions, fmt.Sprintf("ard=%s", item.Ard)) } if item.ContextId != "" { conditions = append(conditions, fmt.Sprintf("context_id=%s", item.ContextId)) } if item.ApnContext != "" { conditions = append(conditions, fmt.Sprintf("apn_context=%s", item.ApnContext)) } if item.StaticIp != "" { conditions = append(conditions, fmt.Sprintf("static_ip=%s", item.StaticIp)) } // 其他 if item.SmfSel != "" { conditions = append(conditions, fmt.Sprintf("smf_sel=%s", item.SmfSel)) } if item.SmData != "" { conditions = append(conditions, fmt.Sprintf("sm_data=%s", item.SmData)) } if item.Cag != "" { conditions = append(conditions, fmt.Sprintf("cag=%s", item.Cag)) } return strings.Join(conditions, ",") }