Loading go-apps/meep-vis/sbi/vis-sbi.go +20 −27 Original line number Diff line number Diff line Loading @@ -402,6 +402,7 @@ func initializeV2xMessageDistribution() (err error) { log.Info("+++ poaNameList: ", poaNameList) var validPoaNameList []string var ecgi_s []string var ecgi_location_s [][]float32 for _, poaName := range poaNameList { node := sbi.activeModel.GetNode(poaName) log.Info("+++ Processing node: ", node) Loading @@ -413,10 +414,11 @@ func initializeV2xMessageDistribution() (err error) { mnc := "" // TODO Apply numerical conversion directly, -1 if not initialized mcc := "" cellId := "" cellName := "" ecgi := "" zone := "" var zoneCell []float32 switch nl.Type_ { case mod.NodeTypePoa4G, mod.NodeTypePoa5G: case mod.NodeTypePoa4G, mod.NodeTypePoa5G: // Extract PLMN poaParent := sbi.activeModel.GetNodeParent(poaName) log.Info("+++ poaParent: ", poaParent) if zone, ok := poaParent.(*dataModel.Zone); ok { Loading @@ -428,9 +430,12 @@ func initializeV2xMessageDistribution() (err error) { mnc = domain.CellularDomainConfig.Mnc mcc = domain.CellularDomainConfig.Mcc cellId = domain.CellularDomainConfig.DefaultCellId // TODO FSCOM Set broker at Zone node level } } } zoneCell = nl.GeoData.Location.Coordinates // e.g. [ 7.420433, 43.729942 ] cellName = nl.Name if nl.Poa4GConfig != nil { cellId = nl.Poa4GConfig.CellId } else if nl.Poa5GConfig != nil { Loading @@ -439,10 +444,11 @@ func initializeV2xMessageDistribution() (err error) { if len(cellId)%2 != 0 { cellId = "0" + cellId } log.Info("=================> cellName: ", cellName) log.Info("=================> cellId: ", cellId) log.Info("=================> mnc: ", mnc) log.Info("=================> mcc: ", mcc) log.Info("=================> mcc: ", zone) log.Info("=================> zoneCell: ", zoneCell) // Calculate Ecgi cellId_num, err := strconv.Atoi(cellId) if err != nil { Loading Loading @@ -483,11 +489,14 @@ func initializeV2xMessageDistribution() (err error) { log.Info("initializeV2xMessageDistribution: ecgi= ", ecgi) } // End of 'switch' statement ecgi_s = append(ecgi_s, ecgi) ecgi_location_s = append(ecgi_location_s, zoneCell) } } } // End of 'for' statement log.Info("initializeV2xMessageDistribution: ecgi_s= ", ecgi_s) err = sbi.trafficMgr.InitializeV2xMessageDistribution(sbi.poaList, validPoaNameList, ecgi_s) log.Info("initializeV2xMessageDistribution: ecgi_location_s= ", ecgi_location_s) err = sbi.trafficMgr.InitializeV2xMessageDistribution(sbi.poaList, validPoaNameList, ecgi_s, ecgi_location_s) if err != nil { log.Error(err.Error()) return err Loading Loading @@ -526,6 +535,13 @@ func GetPredictedPowerValues(hour int32, inRsrp int32, inRsrq int32, poaName str return outRsrp, outRsrq, err } /* * GetInfoUuUnicast process the uu_unicast_provisioning_info GETT request and sends the response * @param {struct} params HTTP request parameters * @param {struct} num_item contains the number of paraneters * @return {struct} UuUnicastProvisioningInfoProInfoUuUnicast initialized data structure * @see ETSI GS MEC 030 V3.1.1 (2023-03) Clause 7.3.3.1 GET */ func GetInfoUuUnicast(params []string, num_item int) (proInfoUuUnicast UuUnicastProvisioningInfoProInfoUuUnicast_list, err error) { proInfoUuUnicast = nil resp, err := sbi.trafficMgr.GetInfoUuUnicast(params, num_item) Loading Loading @@ -589,29 +605,6 @@ func GetInfoUuUnicast(params []string, num_item int) (proInfoUuUnicast UuUnicast } } // End of 'for' statement } // } else if params[0] == "latitude" { // // var geocoordinatesList gisClient.GeoCoordinateList // // geocoordinatesList.GeoCoordinates = geocoordinates // // powerResp, _, err := gisAppClient.GeospatialDataApi.GetGeoDataPowerValues(context.TODO(), geocoordinatesList) // // log.Info("GetInfoUuUnicast: powerResp= ", powerResp) // // if err != nil { // // err = errors.New("GetInfoUuUnicast: GetGeoDataPowerValues failed") // // log.Error(err.Error()) // // return proInfoUuUnicast, err // // } // proInfoUuUnicast = make([]UuUnicastProvisioningInfoProInfoUuUnicast, len(resp)) // proInfoUuUnicast[0].LocationInfo = new(LocationInfo) // proInfoUuUnicast[0].LocationInfo.Ecgi = nil // proInfoUuUnicast[0].LocationInfo.GeoArea = nil // proInfoUuUnicast[0].NeighbourCellInfo = nil // err = errors.New("GetInfoUuUnicast: Location not supported yet") // log.Error(err.Error()) // return proInfoUuUnicast, err // } else { // err = errors.New("GetInfoUuUnicast: Invalid parameter: " + params[0]) // log.Error(err.Error()) // return proInfoUuUnicast, err // } log.Info("GetInfoUuUnicast: proInfoUuUnicast= ", proInfoUuUnicast) return proInfoUuUnicast, err Loading go-apps/meep-vis/server/vis.go +768 −752 File changed.Preview size limit exceeded, changes collapsed. Show changes go-apps/meep-vis/server/vis_test.go +3 −3 Original line number Diff line number Diff line Loading @@ -2210,8 +2210,8 @@ func TestFailV2xMsgDistributionServerPost(t *testing.T) { } fmt.Println("Request done") expected_v2xMsgDistributionServerInfo.V2xMsgDistributionServer[0].infoProtocol.msgProtocol = make([]int32, 0) // No message protocol body, err := json.Marshal(expected_v2xMsgDistributionServerInfo) // Error: InfoConnection field is present :( expected_v2xMsgDistributionServerInfo.V2xMsgDistributionServer[0].InfoProtocol.MsgProtocol = make([]int32, 0) // No message protocol body, err = json.Marshal(expected_v2xMsgDistributionServerInfo) // Error: InfoConnection field is present :( if err != nil { t.Fatalf(err.Error()) } Loading @@ -2222,7 +2222,7 @@ func TestFailV2xMsgDistributionServerPost(t *testing.T) { fmt.Println("Request done") expected_v2xMsgDistributionServerInfo.V2xMsgDistributionServer = make([]V2xMsgDistributionServer, 0) // No V2xMsgDistributionServer body, err := json.Marshal(expected_v2xMsgDistributionServerInfo) // Error: InfoConnection field is present :( body, err = json.Marshal(expected_v2xMsgDistributionServerInfo) // Error: InfoConnection field is present :( if err != nil { t.Fatalf(err.Error()) } Loading go-packages/meep-vis-traffic-mgr/traffic-mgr.go +151 −31 Original line number Diff line number Diff line Loading @@ -150,6 +150,7 @@ type V2xServerUsdTmgi struct { var brokerRunning bool = false var v2xPoaListMap map[string]string = nil var cellName2CellIdMap map[string]string = nil var cellId2LocationMap map[string][]float32 = nil var cellId2CellNameMap map[string]string = nil // DB Config Loading Loading @@ -790,10 +791,11 @@ func (tm *TrafficMgr) GetPoaCategory(longitude float32, latitude float32) (categ return category, err } func (tm *TrafficMgr) InitializeV2xMessageDistribution(v2xPoaList []string, poaNameList []string, ecgi_s []string) (err error) { func (tm *TrafficMgr) InitializeV2xMessageDistribution(v2xPoaList []string, poaNameList []string, ecgi_s []string, location_s [][]float32) (err error) { log.Info(">>> InitializeV2xMessageDistribution: v2xPoaList: ", v2xPoaList) log.Info(">>> InitializeV2xMessageDistribution: poaNameList: ", poaNameList) log.Info(">>> InitializeV2xMessageDistribution: ecgi_s: ", ecgi_s) log.Info(">>> InitializeV2xMessageDistribution: location_s: ", location_s) // Validate input if poaNameList == nil { Loading @@ -809,13 +811,15 @@ func (tm *TrafficMgr) InitializeV2xMessageDistribution(v2xPoaList []string, poaN cellName2CellIdMap = make(map[string]string, len(ecgi_s)) cellId2CellNameMap = make(map[string]string, len(ecgi_s)) v2xPoaListMap = make(map[string]string, len(ecgi_s)) cellId2LocationMap = make(map[string][]float32, len(ecgi_s)) for i := 0; i < len(ecgi_s); i++ { if ecgi_s[i] != "" { idx := sort.Search(len(tm.poa_list), func(j int) bool { return poaNameList[i] <= tm.poa_list[j] }) if idx < len(tm.poa_list) { cellName2CellIdMap[poaNameList[i]] = ecgi_s[i] cellId2LocationMap[ecgi_s[i]] = location_s[i] cellId2CellNameMap[ecgi_s[i]] = poaNameList[i] // FIXME FSCOM Build the ist of V2X compliant PoA // FIXME FSCOM Build the list of V2X compliant PoA res := func() bool { for _, s := range v2xPoaList { if s == poaNameList[i] { Loading @@ -824,13 +828,14 @@ func (tm *TrafficMgr) InitializeV2xMessageDistribution(v2xPoaList []string, poaN } // End of 'for' statement return false }() if res == true { if res { v2xPoaListMap[ecgi_s[i]] = poaNameList[i] } } } } // End of 'for' statement log.Info("InitializeV2xMessageDistribution: cellName2CellIdMap: ", cellName2CellIdMap) log.Info("InitializeV2xMessageDistribution: cellId2LocationMap: ", cellId2LocationMap) log.Info("InitializeV2xMessageDistribution: cellId2CellNameMap: ", cellId2CellNameMap) log.Info("InitializeV2xMessageDistribution: v2xPoaListMap: ", v2xPoaListMap) } else { Loading Loading @@ -932,43 +937,45 @@ func findReducedSignalStrength(inRsrp int32, inRsrq int32, users int32, averageL } } /* * GetInfoUuUnicast process the uu_unicast_provisioning_info GETT request and sends the response * @param {struct} params HTTP request parameters * @param {struct} num_item contains the number of paraneters * @see ETSI GS MEC 030 V3.1.1 (2023-03) Clause 7.3.3.1 GET */ func (tm *TrafficMgr) GetInfoUuUnicast(params []string, num_item int) (proInfoUuUnicast UuUnicastProvisioningInfoProInfoUuUnicast_list, err error) { log.Info(">>> GetInfoUuUnicast: params: ", params) log.Info(">>> GetInfoUuUnicast: num_item: ", num_item) proInfoUuUnicast = make([]UuUnicastProvisioningInfoProInfoUuUnicast, num_item) if params[0] == "ecgi" { for i := 1; i <= num_item; i++ { for i := 1; i <= num_item; i++ { // Same brocker for all Zone. // TODO To be enhance to have one broker per zone confgured in Zone node log.Info("GetInfoUuUnicast: Processing index #", i) ecgi_num, err := strconv.Atoi(params[i]) // Find the ecgi in table var location_map []float32 if val, ok := cellId2LocationMap[params[i]]; ok { location_map = val log.Info("GetInfoUuUnicast: location= ", location_map) } else { err = errors.New("Cannot find cell " + params[i]) log.Error(err.Error()) return nil, err } log.Info("GetInfoUuUnicast: location= ", location_map) ecgi, err := build_ecgi(params[i]) if err != nil { log.Error(err.Error()) return nil, err } log.Info("GetInfoUuUnicast: ecgi_num= ", ecgi_num) // Extract Poa CellId according to v2x_msg GS MEC 030 Clause 6.5.5 Type: Ecgi TwentyEigthBits := 0xFFFFFFF // TS 36.413: E-UTRAN Cell Identity (ECI) and E-UTRAN Cell Global Identification (ECGI) eci := ecgi_num & TwentyEigthBits log.Info("GetInfoUuUnicast: eci= ", int(eci)) // Extract Poa Plmn according to v2x_msg GS MEC 030 Clause 6.5.4 Type: Plmn plmn_num := int(ecgi_num >> 28) //log.Info("GetInfoUuUnicast: plmn= ", plmn_num) //mcc_num := int((plmn_num / 1000) & 0xFFFFFF) //mnc_num := int((plmn_num - mcc_num * 1000) & 0xFFFFFF) mcc_num := int(plmn_num / 1000) mnc_num := int(plmn_num - mcc_num*1000) //log.Info("GetInfoUuUnicast: mcc_num= ", mcc_num) //log.Info("GetInfoUuUnicast: mnc_num= ", mnc_num) // FIXME FSCOM How to manage neighbour cellIs uuUniNeighbourCellInfo := make([]UuUniNeighbourCellInfo, 0) //uuUniNeighbourCellInfo := make([]UuUniNeighbourCellInfo, 1) //uuUniNeighbourCellInfo[0] = UuUniNeighbourCellInfo{&ecgi, nil, 0, &plmn, nil} ecgi := Ecgi{ CellId: &CellId{CellId: strconv.Itoa(int(eci))}, Plmn: &Plmn{Mcc: strconv.Itoa(int(mcc_num)), Mnc: strconv.Itoa(int(mnc_num))}, } plmn := Plmn{Mcc: strconv.Itoa(int(mcc_num)), Mnc: strconv.Itoa(int(mnc_num))} uuUniNeighbourCellInfo := make([]UuUniNeighbourCellInfo, 1) uuUniNeighbourCellInfo[0] = UuUniNeighbourCellInfo{&ecgi, nil, 0, &plmn, nil} var v2xApplicationServer *V2xApplicationServer = nil if _, found := cellId2CellNameMap[params[i]]; found { u, err := url.ParseRequestURI(tm.broker) Loading @@ -982,17 +989,57 @@ func (tm *TrafficMgr) GetInfoUuUnicast(params []string, num_item int) (proInfoUu UdpPort: u.Port(), } } proInfoUuUnicast[i-1] = UuUnicastProvisioningInfoProInfoUuUnicast{nil, uuUniNeighbourCellInfo, v2xApplicationServer} locationInfoGeoArea := &LocationInfoGeoArea{location_map[1], location_map[0]} locationInfo := &LocationInfo{&ecgi, locationInfoGeoArea} proInfoUuUnicast[i-1] = UuUnicastProvisioningInfoProInfoUuUnicast{locationInfo, uuUniNeighbourCellInfo, v2xApplicationServer} } // End of 'for' statement } else if params[0] == "latitude" { log.Info("GetInfoUuUnicast: Params is latitude") // FIXME Add logic based on position: // FIXME FSCOM Add logic based on position: // 1) Find the POA closest to the position // 2) Verify if it provides V2X services // 3) Uodate the data structures accordingly for i := 1; i <= num_item; i++ { log.Info("GetInfoUuUnicast: Processing index #", i) log.Info("GetInfoUuUnicast: params[i]: ", params[i]) log.Info("GetInfoUuUnicast: params[i + num_item + 1]: ", params[i+num_item+1]) lat, err := strconv.ParseFloat(params[i], 32) if err != nil { log.Error(err.Error()) return nil, err } long, err := strconv.ParseFloat(params[i+num_item+1], 32) if err != nil { log.Error(err.Error()) return nil, err } var min_distance float64 = math.MaxFloat64 var selected_ecgi string = "" for idx, coord := range cellId2LocationMap { dist := distance_gps_distance_in_meters(float64(lat), float64(long), float64(coord[1]), float64(coord[0])) if dist < min_distance { min_distance = dist selected_ecgi = idx log.Info("GetInfoUuUnicast: min_distance: ", min_distance) log.Info("GetInfoUuUnicast: selected_ecgi: ", selected_ecgi) } } // End of 'for'statement if selected_ecgi == "" { err = errors.New("Failed to get the closest cell") log.Error(err.Error()) return nil, err } ecgi, err := build_ecgi(selected_ecgi) if err != nil { log.Error(err.Error()) return nil, err } locationInfoGeoArea := &LocationInfoGeoArea{cellId2LocationMap[selected_ecgi][1], cellId2LocationMap[selected_ecgi][0]} locationInfo := &LocationInfo{&ecgi, locationInfoGeoArea} var v2xApplicationServer *V2xApplicationServer = nil u, err := url.ParseRequestURI(tm.broker) log.Info("GetInfoUuUnicast: u: ", u) Loading @@ -1006,17 +1053,90 @@ func (tm *TrafficMgr) GetInfoUuUnicast(params []string, num_item int) (proInfoUu UdpPort: u.Port(), } log.Info("GetInfoUuUnicast: v2xApplicationServer: ", *v2xApplicationServer) proInfoUuUnicast[i-1] = UuUnicastProvisioningInfoProInfoUuUnicast{nil, make([]UuUniNeighbourCellInfo, 0), v2xApplicationServer} proInfoUuUnicast[i-1] = UuUnicastProvisioningInfoProInfoUuUnicast{locationInfo, make([]UuUniNeighbourCellInfo, 0), v2xApplicationServer} } // End of 'for' statement } else { err = errors.New("GetInfoUuUnicast: Invalid parameter: " + params[0]) proInfoUuUnicast = nil return nil, err } log.Info("GetInfoUuUnicast: proInfoUuUnicast= ", proInfoUuUnicast) log.Info("<<< GetInfoUuUnicast: proInfoUuUnicast= ", proInfoUuUnicast) return proInfoUuUnicast, nil } /* * build_ecgi build an Ecgi data structure based on the ECGI name * @param {string} ecgi_str the ECGI name * @return {struct} an initialized Ecgi data structure */ func build_ecgi(ecgi_str string) (ecgi Ecgi, err error) { log.Info(">>> build_ecgi: ecgi_str= ", ecgi_str) ecgi_num, err := strconv.Atoi(ecgi_str) if err != nil { log.Error(err.Error()) return ecgi, err } log.Info("build_ecgi: ecgi_num= ", ecgi_num) // Extract Poa CellId according to v2x_msg GS MEC 030 Clause 6.5.5 Type: Ecgi TwentyEigthBits := 0xFFFFFFF // TS 36.413: E-UTRAN Cell Identity (ECI) and E-UTRAN Cell Global Identification (ECGI) eci := ecgi_num & TwentyEigthBits log.Info("build_ecgi: eci= ", int(eci)) // Extract Poa Plmn according to v2x_msg GS MEC 030 Clause 6.5.4 Type: Plmn plmn_num := int(ecgi_num >> 28) //log.Info("build_ecgi: plmn= ", plmn_num) //mcc_num := int((plmn_num / 1000) & 0xFFFFFF) //mnc_num := int((plmn_num - mcc_num * 1000) & 0xFFFFFF) mcc_num := int(plmn_num / 1000) mnc_num := int(plmn_num - mcc_num*1000) //log.Info("build_ecgi: mcc_num= ", mcc_num) //log.Info("build_ecgi: mnc_num= ", mnc_num) plmn := Plmn{Mcc: strconv.Itoa(int(mcc_num)), Mnc: strconv.Itoa(int(mnc_num))} ecgi = Ecgi{ CellId: &CellId{CellId: strconv.Itoa(int(eci))}, Plmn: &plmn, } log.Info("<<< build_ecgi: ecgi= ", ecgi) return ecgi, nil } const EarthRadius float64 = 6378.1370 const Degrees2Rads float64 = math.Pi / float64(180.0) /* * distance_gps_distance_in_km compute the heavyside distance in km between two GPS points (faster than addressing meep-gis-asset-mgr) * @param {float64} lat1 the latitude of point #1 * @param {float64} long1 the longitude of point #1 * @param {float64} lat2 the latitude of point #2 * @param {float64} long2 the longitude of point #2 * @return {float64} The distance in meter */ func distance_gps_distance_in_meters(lat1 float64, long1 float64, lat2 float64, long2 float64) float64 { return float64(1000.0) * distance_gps_distance_in_km(lat1, long1, lat2, long2) } /* * distance_gps_distance_in_km compute the heavyside distance in km between two GPS points (faster than addressing meep-gis-asset-mgr) * @param {float64} lat1 the latitude of point #1 * @param {float64} long1 the longitude of point #1 * @param {float64} lat2 the latitude of point #2 * @param {float64} long2 the longitude of point #2 * @return {float64} The distance in kmeter */ func distance_gps_distance_in_km(lat1 float64, long1 float64, lat2 float64, long2 float64) float64 { log.Info(">>> distance_gps_distance_in_km") dlong := float64((long2 - long1) * Degrees2Rads) dlat := float64((lat2 - lat1) * Degrees2Rads) a := math.Pow(math.Sin(dlat/2.0), 2.0) + math.Cos(lat1*Degrees2Rads)*math.Cos(lat2*Degrees2Rads)*math.Pow(math.Sin(dlong/2.0), 2.0) c := 2.0 * math.Atan2(math.Sqrt(a), math.Sqrt(1.0-a)) d := EarthRadius * c log.Info("<<< distance_gps_distance_in_km: ", d) return d } func (tm *TrafficMgr) GetInfoUuMbmscast(params []string, num_item int) (proInfoUuMbmscast UuMbmsProvisioningInfoProInfoUuMbms_list, err error) { log.Info(">>> GetInfoUuMbmscast: params: ", params) log.Info(">>> GetInfoUuMbmscast: num_item: ", num_item) Loading Loading
go-apps/meep-vis/sbi/vis-sbi.go +20 −27 Original line number Diff line number Diff line Loading @@ -402,6 +402,7 @@ func initializeV2xMessageDistribution() (err error) { log.Info("+++ poaNameList: ", poaNameList) var validPoaNameList []string var ecgi_s []string var ecgi_location_s [][]float32 for _, poaName := range poaNameList { node := sbi.activeModel.GetNode(poaName) log.Info("+++ Processing node: ", node) Loading @@ -413,10 +414,11 @@ func initializeV2xMessageDistribution() (err error) { mnc := "" // TODO Apply numerical conversion directly, -1 if not initialized mcc := "" cellId := "" cellName := "" ecgi := "" zone := "" var zoneCell []float32 switch nl.Type_ { case mod.NodeTypePoa4G, mod.NodeTypePoa5G: case mod.NodeTypePoa4G, mod.NodeTypePoa5G: // Extract PLMN poaParent := sbi.activeModel.GetNodeParent(poaName) log.Info("+++ poaParent: ", poaParent) if zone, ok := poaParent.(*dataModel.Zone); ok { Loading @@ -428,9 +430,12 @@ func initializeV2xMessageDistribution() (err error) { mnc = domain.CellularDomainConfig.Mnc mcc = domain.CellularDomainConfig.Mcc cellId = domain.CellularDomainConfig.DefaultCellId // TODO FSCOM Set broker at Zone node level } } } zoneCell = nl.GeoData.Location.Coordinates // e.g. [ 7.420433, 43.729942 ] cellName = nl.Name if nl.Poa4GConfig != nil { cellId = nl.Poa4GConfig.CellId } else if nl.Poa5GConfig != nil { Loading @@ -439,10 +444,11 @@ func initializeV2xMessageDistribution() (err error) { if len(cellId)%2 != 0 { cellId = "0" + cellId } log.Info("=================> cellName: ", cellName) log.Info("=================> cellId: ", cellId) log.Info("=================> mnc: ", mnc) log.Info("=================> mcc: ", mcc) log.Info("=================> mcc: ", zone) log.Info("=================> zoneCell: ", zoneCell) // Calculate Ecgi cellId_num, err := strconv.Atoi(cellId) if err != nil { Loading Loading @@ -483,11 +489,14 @@ func initializeV2xMessageDistribution() (err error) { log.Info("initializeV2xMessageDistribution: ecgi= ", ecgi) } // End of 'switch' statement ecgi_s = append(ecgi_s, ecgi) ecgi_location_s = append(ecgi_location_s, zoneCell) } } } // End of 'for' statement log.Info("initializeV2xMessageDistribution: ecgi_s= ", ecgi_s) err = sbi.trafficMgr.InitializeV2xMessageDistribution(sbi.poaList, validPoaNameList, ecgi_s) log.Info("initializeV2xMessageDistribution: ecgi_location_s= ", ecgi_location_s) err = sbi.trafficMgr.InitializeV2xMessageDistribution(sbi.poaList, validPoaNameList, ecgi_s, ecgi_location_s) if err != nil { log.Error(err.Error()) return err Loading Loading @@ -526,6 +535,13 @@ func GetPredictedPowerValues(hour int32, inRsrp int32, inRsrq int32, poaName str return outRsrp, outRsrq, err } /* * GetInfoUuUnicast process the uu_unicast_provisioning_info GETT request and sends the response * @param {struct} params HTTP request parameters * @param {struct} num_item contains the number of paraneters * @return {struct} UuUnicastProvisioningInfoProInfoUuUnicast initialized data structure * @see ETSI GS MEC 030 V3.1.1 (2023-03) Clause 7.3.3.1 GET */ func GetInfoUuUnicast(params []string, num_item int) (proInfoUuUnicast UuUnicastProvisioningInfoProInfoUuUnicast_list, err error) { proInfoUuUnicast = nil resp, err := sbi.trafficMgr.GetInfoUuUnicast(params, num_item) Loading Loading @@ -589,29 +605,6 @@ func GetInfoUuUnicast(params []string, num_item int) (proInfoUuUnicast UuUnicast } } // End of 'for' statement } // } else if params[0] == "latitude" { // // var geocoordinatesList gisClient.GeoCoordinateList // // geocoordinatesList.GeoCoordinates = geocoordinates // // powerResp, _, err := gisAppClient.GeospatialDataApi.GetGeoDataPowerValues(context.TODO(), geocoordinatesList) // // log.Info("GetInfoUuUnicast: powerResp= ", powerResp) // // if err != nil { // // err = errors.New("GetInfoUuUnicast: GetGeoDataPowerValues failed") // // log.Error(err.Error()) // // return proInfoUuUnicast, err // // } // proInfoUuUnicast = make([]UuUnicastProvisioningInfoProInfoUuUnicast, len(resp)) // proInfoUuUnicast[0].LocationInfo = new(LocationInfo) // proInfoUuUnicast[0].LocationInfo.Ecgi = nil // proInfoUuUnicast[0].LocationInfo.GeoArea = nil // proInfoUuUnicast[0].NeighbourCellInfo = nil // err = errors.New("GetInfoUuUnicast: Location not supported yet") // log.Error(err.Error()) // return proInfoUuUnicast, err // } else { // err = errors.New("GetInfoUuUnicast: Invalid parameter: " + params[0]) // log.Error(err.Error()) // return proInfoUuUnicast, err // } log.Info("GetInfoUuUnicast: proInfoUuUnicast= ", proInfoUuUnicast) return proInfoUuUnicast, err Loading
go-apps/meep-vis/server/vis.go +768 −752 File changed.Preview size limit exceeded, changes collapsed. Show changes
go-apps/meep-vis/server/vis_test.go +3 −3 Original line number Diff line number Diff line Loading @@ -2210,8 +2210,8 @@ func TestFailV2xMsgDistributionServerPost(t *testing.T) { } fmt.Println("Request done") expected_v2xMsgDistributionServerInfo.V2xMsgDistributionServer[0].infoProtocol.msgProtocol = make([]int32, 0) // No message protocol body, err := json.Marshal(expected_v2xMsgDistributionServerInfo) // Error: InfoConnection field is present :( expected_v2xMsgDistributionServerInfo.V2xMsgDistributionServer[0].InfoProtocol.MsgProtocol = make([]int32, 0) // No message protocol body, err = json.Marshal(expected_v2xMsgDistributionServerInfo) // Error: InfoConnection field is present :( if err != nil { t.Fatalf(err.Error()) } Loading @@ -2222,7 +2222,7 @@ func TestFailV2xMsgDistributionServerPost(t *testing.T) { fmt.Println("Request done") expected_v2xMsgDistributionServerInfo.V2xMsgDistributionServer = make([]V2xMsgDistributionServer, 0) // No V2xMsgDistributionServer body, err := json.Marshal(expected_v2xMsgDistributionServerInfo) // Error: InfoConnection field is present :( body, err = json.Marshal(expected_v2xMsgDistributionServerInfo) // Error: InfoConnection field is present :( if err != nil { t.Fatalf(err.Error()) } Loading
go-packages/meep-vis-traffic-mgr/traffic-mgr.go +151 −31 Original line number Diff line number Diff line Loading @@ -150,6 +150,7 @@ type V2xServerUsdTmgi struct { var brokerRunning bool = false var v2xPoaListMap map[string]string = nil var cellName2CellIdMap map[string]string = nil var cellId2LocationMap map[string][]float32 = nil var cellId2CellNameMap map[string]string = nil // DB Config Loading Loading @@ -790,10 +791,11 @@ func (tm *TrafficMgr) GetPoaCategory(longitude float32, latitude float32) (categ return category, err } func (tm *TrafficMgr) InitializeV2xMessageDistribution(v2xPoaList []string, poaNameList []string, ecgi_s []string) (err error) { func (tm *TrafficMgr) InitializeV2xMessageDistribution(v2xPoaList []string, poaNameList []string, ecgi_s []string, location_s [][]float32) (err error) { log.Info(">>> InitializeV2xMessageDistribution: v2xPoaList: ", v2xPoaList) log.Info(">>> InitializeV2xMessageDistribution: poaNameList: ", poaNameList) log.Info(">>> InitializeV2xMessageDistribution: ecgi_s: ", ecgi_s) log.Info(">>> InitializeV2xMessageDistribution: location_s: ", location_s) // Validate input if poaNameList == nil { Loading @@ -809,13 +811,15 @@ func (tm *TrafficMgr) InitializeV2xMessageDistribution(v2xPoaList []string, poaN cellName2CellIdMap = make(map[string]string, len(ecgi_s)) cellId2CellNameMap = make(map[string]string, len(ecgi_s)) v2xPoaListMap = make(map[string]string, len(ecgi_s)) cellId2LocationMap = make(map[string][]float32, len(ecgi_s)) for i := 0; i < len(ecgi_s); i++ { if ecgi_s[i] != "" { idx := sort.Search(len(tm.poa_list), func(j int) bool { return poaNameList[i] <= tm.poa_list[j] }) if idx < len(tm.poa_list) { cellName2CellIdMap[poaNameList[i]] = ecgi_s[i] cellId2LocationMap[ecgi_s[i]] = location_s[i] cellId2CellNameMap[ecgi_s[i]] = poaNameList[i] // FIXME FSCOM Build the ist of V2X compliant PoA // FIXME FSCOM Build the list of V2X compliant PoA res := func() bool { for _, s := range v2xPoaList { if s == poaNameList[i] { Loading @@ -824,13 +828,14 @@ func (tm *TrafficMgr) InitializeV2xMessageDistribution(v2xPoaList []string, poaN } // End of 'for' statement return false }() if res == true { if res { v2xPoaListMap[ecgi_s[i]] = poaNameList[i] } } } } // End of 'for' statement log.Info("InitializeV2xMessageDistribution: cellName2CellIdMap: ", cellName2CellIdMap) log.Info("InitializeV2xMessageDistribution: cellId2LocationMap: ", cellId2LocationMap) log.Info("InitializeV2xMessageDistribution: cellId2CellNameMap: ", cellId2CellNameMap) log.Info("InitializeV2xMessageDistribution: v2xPoaListMap: ", v2xPoaListMap) } else { Loading Loading @@ -932,43 +937,45 @@ func findReducedSignalStrength(inRsrp int32, inRsrq int32, users int32, averageL } } /* * GetInfoUuUnicast process the uu_unicast_provisioning_info GETT request and sends the response * @param {struct} params HTTP request parameters * @param {struct} num_item contains the number of paraneters * @see ETSI GS MEC 030 V3.1.1 (2023-03) Clause 7.3.3.1 GET */ func (tm *TrafficMgr) GetInfoUuUnicast(params []string, num_item int) (proInfoUuUnicast UuUnicastProvisioningInfoProInfoUuUnicast_list, err error) { log.Info(">>> GetInfoUuUnicast: params: ", params) log.Info(">>> GetInfoUuUnicast: num_item: ", num_item) proInfoUuUnicast = make([]UuUnicastProvisioningInfoProInfoUuUnicast, num_item) if params[0] == "ecgi" { for i := 1; i <= num_item; i++ { for i := 1; i <= num_item; i++ { // Same brocker for all Zone. // TODO To be enhance to have one broker per zone confgured in Zone node log.Info("GetInfoUuUnicast: Processing index #", i) ecgi_num, err := strconv.Atoi(params[i]) // Find the ecgi in table var location_map []float32 if val, ok := cellId2LocationMap[params[i]]; ok { location_map = val log.Info("GetInfoUuUnicast: location= ", location_map) } else { err = errors.New("Cannot find cell " + params[i]) log.Error(err.Error()) return nil, err } log.Info("GetInfoUuUnicast: location= ", location_map) ecgi, err := build_ecgi(params[i]) if err != nil { log.Error(err.Error()) return nil, err } log.Info("GetInfoUuUnicast: ecgi_num= ", ecgi_num) // Extract Poa CellId according to v2x_msg GS MEC 030 Clause 6.5.5 Type: Ecgi TwentyEigthBits := 0xFFFFFFF // TS 36.413: E-UTRAN Cell Identity (ECI) and E-UTRAN Cell Global Identification (ECGI) eci := ecgi_num & TwentyEigthBits log.Info("GetInfoUuUnicast: eci= ", int(eci)) // Extract Poa Plmn according to v2x_msg GS MEC 030 Clause 6.5.4 Type: Plmn plmn_num := int(ecgi_num >> 28) //log.Info("GetInfoUuUnicast: plmn= ", plmn_num) //mcc_num := int((plmn_num / 1000) & 0xFFFFFF) //mnc_num := int((plmn_num - mcc_num * 1000) & 0xFFFFFF) mcc_num := int(plmn_num / 1000) mnc_num := int(plmn_num - mcc_num*1000) //log.Info("GetInfoUuUnicast: mcc_num= ", mcc_num) //log.Info("GetInfoUuUnicast: mnc_num= ", mnc_num) // FIXME FSCOM How to manage neighbour cellIs uuUniNeighbourCellInfo := make([]UuUniNeighbourCellInfo, 0) //uuUniNeighbourCellInfo := make([]UuUniNeighbourCellInfo, 1) //uuUniNeighbourCellInfo[0] = UuUniNeighbourCellInfo{&ecgi, nil, 0, &plmn, nil} ecgi := Ecgi{ CellId: &CellId{CellId: strconv.Itoa(int(eci))}, Plmn: &Plmn{Mcc: strconv.Itoa(int(mcc_num)), Mnc: strconv.Itoa(int(mnc_num))}, } plmn := Plmn{Mcc: strconv.Itoa(int(mcc_num)), Mnc: strconv.Itoa(int(mnc_num))} uuUniNeighbourCellInfo := make([]UuUniNeighbourCellInfo, 1) uuUniNeighbourCellInfo[0] = UuUniNeighbourCellInfo{&ecgi, nil, 0, &plmn, nil} var v2xApplicationServer *V2xApplicationServer = nil if _, found := cellId2CellNameMap[params[i]]; found { u, err := url.ParseRequestURI(tm.broker) Loading @@ -982,17 +989,57 @@ func (tm *TrafficMgr) GetInfoUuUnicast(params []string, num_item int) (proInfoUu UdpPort: u.Port(), } } proInfoUuUnicast[i-1] = UuUnicastProvisioningInfoProInfoUuUnicast{nil, uuUniNeighbourCellInfo, v2xApplicationServer} locationInfoGeoArea := &LocationInfoGeoArea{location_map[1], location_map[0]} locationInfo := &LocationInfo{&ecgi, locationInfoGeoArea} proInfoUuUnicast[i-1] = UuUnicastProvisioningInfoProInfoUuUnicast{locationInfo, uuUniNeighbourCellInfo, v2xApplicationServer} } // End of 'for' statement } else if params[0] == "latitude" { log.Info("GetInfoUuUnicast: Params is latitude") // FIXME Add logic based on position: // FIXME FSCOM Add logic based on position: // 1) Find the POA closest to the position // 2) Verify if it provides V2X services // 3) Uodate the data structures accordingly for i := 1; i <= num_item; i++ { log.Info("GetInfoUuUnicast: Processing index #", i) log.Info("GetInfoUuUnicast: params[i]: ", params[i]) log.Info("GetInfoUuUnicast: params[i + num_item + 1]: ", params[i+num_item+1]) lat, err := strconv.ParseFloat(params[i], 32) if err != nil { log.Error(err.Error()) return nil, err } long, err := strconv.ParseFloat(params[i+num_item+1], 32) if err != nil { log.Error(err.Error()) return nil, err } var min_distance float64 = math.MaxFloat64 var selected_ecgi string = "" for idx, coord := range cellId2LocationMap { dist := distance_gps_distance_in_meters(float64(lat), float64(long), float64(coord[1]), float64(coord[0])) if dist < min_distance { min_distance = dist selected_ecgi = idx log.Info("GetInfoUuUnicast: min_distance: ", min_distance) log.Info("GetInfoUuUnicast: selected_ecgi: ", selected_ecgi) } } // End of 'for'statement if selected_ecgi == "" { err = errors.New("Failed to get the closest cell") log.Error(err.Error()) return nil, err } ecgi, err := build_ecgi(selected_ecgi) if err != nil { log.Error(err.Error()) return nil, err } locationInfoGeoArea := &LocationInfoGeoArea{cellId2LocationMap[selected_ecgi][1], cellId2LocationMap[selected_ecgi][0]} locationInfo := &LocationInfo{&ecgi, locationInfoGeoArea} var v2xApplicationServer *V2xApplicationServer = nil u, err := url.ParseRequestURI(tm.broker) log.Info("GetInfoUuUnicast: u: ", u) Loading @@ -1006,17 +1053,90 @@ func (tm *TrafficMgr) GetInfoUuUnicast(params []string, num_item int) (proInfoUu UdpPort: u.Port(), } log.Info("GetInfoUuUnicast: v2xApplicationServer: ", *v2xApplicationServer) proInfoUuUnicast[i-1] = UuUnicastProvisioningInfoProInfoUuUnicast{nil, make([]UuUniNeighbourCellInfo, 0), v2xApplicationServer} proInfoUuUnicast[i-1] = UuUnicastProvisioningInfoProInfoUuUnicast{locationInfo, make([]UuUniNeighbourCellInfo, 0), v2xApplicationServer} } // End of 'for' statement } else { err = errors.New("GetInfoUuUnicast: Invalid parameter: " + params[0]) proInfoUuUnicast = nil return nil, err } log.Info("GetInfoUuUnicast: proInfoUuUnicast= ", proInfoUuUnicast) log.Info("<<< GetInfoUuUnicast: proInfoUuUnicast= ", proInfoUuUnicast) return proInfoUuUnicast, nil } /* * build_ecgi build an Ecgi data structure based on the ECGI name * @param {string} ecgi_str the ECGI name * @return {struct} an initialized Ecgi data structure */ func build_ecgi(ecgi_str string) (ecgi Ecgi, err error) { log.Info(">>> build_ecgi: ecgi_str= ", ecgi_str) ecgi_num, err := strconv.Atoi(ecgi_str) if err != nil { log.Error(err.Error()) return ecgi, err } log.Info("build_ecgi: ecgi_num= ", ecgi_num) // Extract Poa CellId according to v2x_msg GS MEC 030 Clause 6.5.5 Type: Ecgi TwentyEigthBits := 0xFFFFFFF // TS 36.413: E-UTRAN Cell Identity (ECI) and E-UTRAN Cell Global Identification (ECGI) eci := ecgi_num & TwentyEigthBits log.Info("build_ecgi: eci= ", int(eci)) // Extract Poa Plmn according to v2x_msg GS MEC 030 Clause 6.5.4 Type: Plmn plmn_num := int(ecgi_num >> 28) //log.Info("build_ecgi: plmn= ", plmn_num) //mcc_num := int((plmn_num / 1000) & 0xFFFFFF) //mnc_num := int((plmn_num - mcc_num * 1000) & 0xFFFFFF) mcc_num := int(plmn_num / 1000) mnc_num := int(plmn_num - mcc_num*1000) //log.Info("build_ecgi: mcc_num= ", mcc_num) //log.Info("build_ecgi: mnc_num= ", mnc_num) plmn := Plmn{Mcc: strconv.Itoa(int(mcc_num)), Mnc: strconv.Itoa(int(mnc_num))} ecgi = Ecgi{ CellId: &CellId{CellId: strconv.Itoa(int(eci))}, Plmn: &plmn, } log.Info("<<< build_ecgi: ecgi= ", ecgi) return ecgi, nil } const EarthRadius float64 = 6378.1370 const Degrees2Rads float64 = math.Pi / float64(180.0) /* * distance_gps_distance_in_km compute the heavyside distance in km between two GPS points (faster than addressing meep-gis-asset-mgr) * @param {float64} lat1 the latitude of point #1 * @param {float64} long1 the longitude of point #1 * @param {float64} lat2 the latitude of point #2 * @param {float64} long2 the longitude of point #2 * @return {float64} The distance in meter */ func distance_gps_distance_in_meters(lat1 float64, long1 float64, lat2 float64, long2 float64) float64 { return float64(1000.0) * distance_gps_distance_in_km(lat1, long1, lat2, long2) } /* * distance_gps_distance_in_km compute the heavyside distance in km between two GPS points (faster than addressing meep-gis-asset-mgr) * @param {float64} lat1 the latitude of point #1 * @param {float64} long1 the longitude of point #1 * @param {float64} lat2 the latitude of point #2 * @param {float64} long2 the longitude of point #2 * @return {float64} The distance in kmeter */ func distance_gps_distance_in_km(lat1 float64, long1 float64, lat2 float64, long2 float64) float64 { log.Info(">>> distance_gps_distance_in_km") dlong := float64((long2 - long1) * Degrees2Rads) dlat := float64((lat2 - lat1) * Degrees2Rads) a := math.Pow(math.Sin(dlat/2.0), 2.0) + math.Cos(lat1*Degrees2Rads)*math.Cos(lat2*Degrees2Rads)*math.Pow(math.Sin(dlong/2.0), 2.0) c := 2.0 * math.Atan2(math.Sqrt(a), math.Sqrt(1.0-a)) d := EarthRadius * c log.Info("<<< distance_gps_distance_in_km: ", d) return d } func (tm *TrafficMgr) GetInfoUuMbmscast(params []string, num_item int) (proInfoUuMbmscast UuMbmsProvisioningInfoProInfoUuMbms_list, err error) { log.Info(">>> GetInfoUuMbmscast: params: ", params) log.Info(">>> GetInfoUuMbmscast: num_item: ", num_item) Loading