Loading go-apps/meep-gis-engine/server/gis-engine.go +81 −64 Original line number Diff line number Diff line Loading @@ -758,6 +758,7 @@ func setAutomation(automationType string, state bool) (err error) { } func runAutomation() { // Movement if ge.automation[AutoTypeMovement] { log.Debug("Auto Movement: updating UE positions") Loading @@ -776,11 +777,31 @@ func runAutomation() { ge.updateTime = currentTime } // Cache asset snapshot ueMap, err := ge.assetMgr.GetAllUe() if err != nil { log.Error(err.Error()) return } // for _, ue := range ueMap { // ue. // } // poaMap, err := ge.assetMgr.GetAllPoa() // if err != nil { // log.Error(err.Error()) // return // } // computeMap, err := ge.assetMgr.GetAllCompute() // if err != nil { // log.Error(err.Error()) // return // } // Mobility & POA In Range if ge.automation[AutoTypeMobility] || ge.automation[AutoTypePoaInRange] { // Get all UE POA information ueMap, err := ge.assetMgr.GetAllUe() if err == nil { // Loop through UEs for _, ue := range ueMap { // Get stored UE info ueInfo, isNew := getUeInfo(ue.Name) Loading Loading @@ -849,10 +870,6 @@ func runAutomation() { delete(ge.ueInfo, ueName) } } } else { log.Error(err.Error()) } } // Net Char Loading go-packages/meep-gis-asset-mgr/asset-mgr.go +136 −35 Original line number Diff line number Diff line Loading @@ -296,7 +296,7 @@ func (am *AssetMgr) CreateTables() (err error) { log.Error(err.Error()) return err } log.Info("Created UE Mearuements table: ", UeMeasurementTable) log.Info("Created UE Measurements table: ", UeMeasurementTable) // POA Table _, err = am.db.Exec(`CREATE TABLE ` + PoaTable + ` ( Loading Loading @@ -818,9 +818,11 @@ func (am *AssetMgr) GetUe(name string) (ue *Ue, err error) { rows, err = am.db.Query(` SELECT id, name, ST_AsGeoJSON(position), ST_AsGeoJSON(path), path_mode, path_velocity, path_length, path_increment, path_fraction, poa, poa_distance, poa_in_range, poa_type_prio, connected FROM `+UeTable+` WHERE name = ($1)`, name) poa, poa_distance, poa_in_range, poa_type_prio, connected, meas.poa, meas.type, meas.radius, meas.distance, meas.in_range, meas.rssi, meas.rsrp, meas.rsrq FROM `+UeTable+` AS ue LEFT JOIN `+UeMeasurementTable+` AS meas ON (ue.name = meas.ue) WHERE ue.name = ($1)`, name) if err != nil { log.Error(err.Error()) return nil, err Loading @@ -829,22 +831,35 @@ func (am *AssetMgr) GetUe(name string) (ue *Ue, err error) { // Scan result for rows.Next() { ue = new(Ue) ueEntry := new(Ue) ueMeas := new(UeMeasurement) path := new(string) err = rows.Scan(&ue.Id, &ue.Name, &ue.Position, &path, &ue.PathMode, &ue.PathVelocity, &ue.PathLength, &ue.PathIncrement, &ue.PathFraction, &ue.Poa, &ue.PoaDistance, pq.Array(&ue.PoaInRange), pq.Array(&ue.PoaTypePrio), &ue.Connected) // Fill UE err = rows.Scan(&ueEntry.Id, &ueEntry.Name, &ueEntry.Position, &path, &ueEntry.PathMode, &ueEntry.PathVelocity, &ueEntry.PathLength, &ueEntry.PathIncrement, &ueEntry.PathFraction, &ueEntry.Poa, &ueEntry.PoaDistance, pq.Array(&ueEntry.PoaInRange), pq.Array(&ueEntry.PoaTypePrio), &ueEntry.Connected, &ueMeas.Poa, &ueMeas.SubType, &ueMeas.Radius, &ueMeas.Distance, &ueMeas.InRange, &ueMeas.Rssi, &ueMeas.Rsrp, &ueMeas.Rsrq) if err != nil { log.Error(err.Error()) return nil, err } // Store path // Create new UE if not set if ue == nil { ue = ueEntry ue.Measurements = make(map[string]*UeMeasurement) if path != nil { ue.Path = *path } } // Set UE measurement if in range if ueMeas.InRange { ue.Measurements[ueMeas.Poa] = ueMeas } } err = rows.Err() if err != nil { log.Error(err) Loading Loading @@ -950,10 +965,12 @@ func (am *AssetMgr) GetAllUe() (ueMap map[string]*Ue, err error) { // Get UE entries var rows *sql.Rows rows, err = am.db.Query(` SELECT id, name, ST_AsGeoJSON(position), ST_AsGeoJSON(path), path_mode, path_velocity, path_length, path_increment, path_fraction, poa, poa_distance, poa_in_range, poa_type_prio, connected FROM ` + UeTable) SELECT ue.id, ue.name, ST_AsGeoJSON(ue.position), ST_AsGeoJSON(ue.path), ue.path_mode, ue.path_velocity, ue.path_length, ue.path_increment, ue.path_fraction, ue.poa, ue.poa_distance, ue.poa_in_range, ue.poa_type_prio, ue.connected, meas.poa, meas.type, meas.radius, meas.distance, meas.in_range, meas.rssi, meas.rsrp, meas.rsrq FROM ` + UeTable + ` AS ue LEFT JOIN ` + UeMeasurementTable + ` AS meas ON (ue.name = meas.ue)`) if err != nil { log.Error(err.Error()) return ueMap, err Loading @@ -962,26 +979,37 @@ func (am *AssetMgr) GetAllUe() (ueMap map[string]*Ue, err error) { // Scan results for rows.Next() { ue := new(Ue) ueEntry := new(Ue) ueMeas := new(UeMeasurement) path := new(string) // Fill UE err = rows.Scan(&ue.Id, &ue.Name, &ue.Position, &path, &ue.PathMode, &ue.PathVelocity, &ue.PathLength, &ue.PathIncrement, &ue.PathFraction, &ue.Poa, &ue.PoaDistance, pq.Array(&ue.PoaInRange), pq.Array(&ue.PoaTypePrio), &ue.Connected) err = rows.Scan(&ueEntry.Id, &ueEntry.Name, &ueEntry.Position, &path, &ueEntry.PathMode, &ueEntry.PathVelocity, &ueEntry.PathLength, &ueEntry.PathIncrement, &ueEntry.PathFraction, &ueEntry.Poa, &ueEntry.PoaDistance, pq.Array(&ueEntry.PoaInRange), pq.Array(&ueEntry.PoaTypePrio), &ueEntry.Connected, &ueMeas.Poa, &ueMeas.SubType, &ueMeas.Radius, &ueMeas.Distance, &ueMeas.InRange, &ueMeas.Rssi, &ueMeas.Rsrp, &ueMeas.Rsrq) if err != nil { log.Error(err.Error()) return ueMap, err } // Store path // Get UE entry from UE map (create new entry if not found) ue := ueMap[ueEntry.Name] if ue == nil { ue = ueEntry ue.Measurements = make(map[string]*UeMeasurement) if path != nil { ue.Path = *path } // Add UE to map ueMap[ue.Name] = ue } // Set UE measurement if in range if ueMeas.InRange { ue.Measurements[ueMeas.Poa] = ueMeas } } err = rows.Err() if err != nil { log.Error(err) Loading Loading @@ -1458,6 +1486,8 @@ func (am *AssetMgr) resetUePoaInfo(name string, ueMap map[string]*Ue) (err error // Update all UE Poa Info func (am *AssetMgr) updateUeInfo(ueMap map[string]*Ue) (err error) { // start := time.Now() // Begin Update Transaction tx, err := am.db.Begin() if err != nil { Loading @@ -1481,7 +1511,7 @@ func (am *AssetMgr) updateUeInfo(ueMap map[string]*Ue) (err error) { poa_distance = $3, poa_in_range = $4 WHERE name = ($1)` _, err = am.db.Exec(query, ueName, selectedPoa, distance, pq.Array(ue.PoaInRange)) _, err = tx.Exec(query, ueName, selectedPoa, distance, pq.Array(ue.PoaInRange)) if err != nil { log.Error(err.Error()) return err Loading @@ -1489,19 +1519,17 @@ func (am *AssetMgr) updateUeInfo(ueMap map[string]*Ue) (err error) { // Update UE measurements for poaName, meas := range ue.Measurements { // Calculate power measurements rssi := 1.1 rsrp := 2.2 rsrq := -3.3 rssi, rsrp, rsrq := calculatePower(meas.SubType, meas.Radius, meas.Distance) query := `INSERT INTO ` + UeMeasurementTable + ` (ue, poa, type, radius, distance, in_range, rssi, rsrp, rsrq) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) // Add new entry or update existing one id := ueName + "-" + poaName query := `INSERT INTO ` + UeMeasurementTable + ` (id, ue, poa, type, radius, distance, in_range, rssi, rsrp, rsrq) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) ON CONFLICT (id) DO UPDATE SET radius = $4, distance = $5, in_range = $6, rssi = $7, rsrp = $8, rsrq = $9 WHERE ue = ($1) AND poa = ($2)` log.Error(query) _, err = am.db.Exec(query, ueName, poaName, meas.SubType, meas.Radius, meas.Distance, meas.InRange, rssi, rsrp, rsrq) DO UPDATE SET radius = $5, distance = $6, in_range = $7, rssi = $8, rsrp = $9, rsrq = $10 WHERE ` + UeMeasurementTable + `.ue = ($2) AND ` + UeMeasurementTable + `.poa = ($3)` _, err = tx.Exec(query, id, ueName, poaName, meas.SubType, meas.Radius, meas.Distance, meas.InRange, rssi, rsrp, rsrq) if err != nil { log.Error(err.Error()) return err Loading @@ -1509,6 +1537,9 @@ func (am *AssetMgr) updateUeInfo(ueMap map[string]*Ue) (err error) { } } // finish := time.Now() // log.Error("UPDATE DURATION: ", finish.Sub(start)) return nil } Loading Loading @@ -1589,3 +1620,73 @@ func getPoaTypePriority(poaType string, poaTypePrio []string) int { } return priority } func calculatePower(subtype string, radius float32, distance float32) (rssi float32, rsrp float32, rsrq float32) { switch subtype { case PoaTypeCell4g: rsrp, rsrq = calculateCell4gPower(radius, distance) case PoaTypeCell5g: rsrp, rsrq = calculateCell5gPower(radius, distance) case PoaTypeWifi: rssi = calculateWifiPower(radius, distance) default: } return rssi, rsrp, rsrq } // 4G Cellular signal strength calculator // RSRP power range: -156 dBm to -44 dBm // Equivalent RSRP range: -17 to 97 // RSRQ power range: -34 dBm to 2.5 dBm // Equivalent RSRQ range: -30 to 46 // Algorithm: Linear proportion to distance over radius, if in range const minCell4gRsrp = float32(-17) const maxCell4gRsrp = float32(97) const minCell4gRsrq = float32(-30) const maxCell4gRsrq = float32(46) func calculateCell4gPower(radius float32, distance float32) (rsrp float32, rsrq float32) { rsrp = minCell4gRsrp rsrq = minCell4gRsrq if distance < radius { rsrp = float32(int(minCell4gRsrp + ((maxCell4gRsrp - minCell4gRsrp) * (1 - (distance / radius))))) rsrq = float32(int(minCell4gRsrq + ((maxCell4gRsrq - minCell4gRsrq) * (1 - (distance / radius))))) } return rsrp, rsrq } // 5G Cellular signal strength calculator // RSRP power range: -156 dBm to -31 dBm // Equivalent RSRP range: 0 to 127 // RSRQ power range: -43 dBm to 20 dBm // Equivalent RSRQ range: 0 to 127 // Algorithm: Linear proportion to distance over radius, if in range const minCell5gRsrp = float32(0) const maxCell5gRsrp = float32(127) const minCell5gRsrq = float32(0) const maxCell5gRsrq = float32(127) func calculateCell5gPower(radius float32, distance float32) (rsrp float32, rsrq float32) { rsrp = minCell5gRsrp rsrq = minCell5gRsrq if distance < radius { rsrp = float32(int(minCell5gRsrp + ((maxCell5gRsrp - minCell5gRsrp) * (1 - (distance / radius))))) rsrq = float32(int(minCell5gRsrq + ((maxCell5gRsrq - minCell5gRsrq) * (1 - (distance / radius))))) } return rsrp, rsrq } // WiFi signal strength calculator // Signal power range: -113 dBm to -10 dBm // Equivalent RSSI range: 0 to 100 // Algorithm: Linear proportion to distance over radius, if in range const minWifiRssi = float32(0) const maxWifiRssi = float32(100) func calculateWifiPower(radius float32, distance float32) (rssi float32) { rssi = minWifiRssi if distance < radius { rssi = float32(int(minWifiRssi + ((maxWifiRssi - minWifiRssi) * (1 - (distance / radius))))) } return rssi } go-packages/meep-gis-asset-mgr/go.mod +0 −1 Original line number Diff line number Diff line Loading @@ -4,7 +4,6 @@ go 1.12 require ( github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-logger v0.0.0 github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-postgis v0.0.0-20200703133018-94138d8210a3 // indirect github.com/lib/pq v1.5.2 ) Loading go-packages/meep-gis-asset-mgr/go.sum +0 −3 Original line number Diff line number Diff line github.com/InterDigitalInc/AdvantEDGE v1.5.0 h1:Gv1wxW7kV31reTqxX5TflvvYEEqnxaUlKWvgoandpfI= github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-postgis v0.0.0-20200703133018-94138d8210a3 h1:O3BYtbMjdX0Qre4kr5vCxbhHZuSPJBEFwIdMOuWS3Dk= github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-postgis v0.0.0-20200703133018-94138d8210a3/go.mod h1:4uz6tZflvTKPcqTf8nu3k2GaotQy4bKsOYj4dw5VTR0= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/lib/pq v1.5.2 h1:yTSXVswvWUOQ3k1sd7vJfDrbSl8lKuscqFJRqjC0ifw= Loading go-packages/meep-gis-cache/gis-cache.go 0 → 100644 +141 −0 Original line number Diff line number Diff line /* * Copyright (c) 2020 InterDigital Communications, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package giscache import ( dkm "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-data-key-mgr" log "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-logger" redis "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-redis" ) const redisTable = 0 // Root key var keyRoot = dkm.GetKeyRootGlobal() + "gis-cache:" type Location struct { Name string } type UeMeasurement struct { Name string } type GisCache struct { rc *redis.Connector } // NewGisCache - Creates and initialize a GIS Cache instance func NewGisCache(redisAddr string) (gc *GisCache, err error) { // Create new GIS Cache instance gc = new(GisCache) // Connect to Redis DB gc.rc, err = redis.NewConnector(redisAddr, redisTable) if err != nil { log.Error("Failed connection to GIS Cache Redis DB. Error: ", err) return nil, err } log.Info("Connected to GIS Cache Redis DB") log.Info("Created GIS Cache") return gc, nil } // // Set - Create or update entry in DB // func (gc *GisCache) Set(name string, location *Location) error { // // Prepare data // fields := make(map[string]interface{}) // fields[fieldSandboxName] = sbox.Name // fields[fieldScenarioName] = sbox.ScenarioName // // Update entry in DB // key := keyRoot + sbox.Name // err := ss.rc.SetEntry(key, fields) // if err != nil { // log.Error("Failed to set entry with error: ", err.Error()) // return err // } // return nil // } // // Get - Return sandbox with provided name // func (gc *GisCache) Get(name string) (*Sandbox, error) { // key := keyRoot + sboxName // // Make sure entry exists // if !ss.rc.EntryExists(key) { // err := errors.New("Entry not found") // log.Error(err.Error()) // return nil, err // } // // Find entry // fields, err := ss.rc.GetEntry(key) // if err != nil { // log.Error("Failed to get entry with error: ", err.Error()) // return nil, err // } // // Prepare sandbox // sbox := new(Sandbox) // sbox.Name = fields[fieldSandboxName] // sbox.ScenarioName = fields[fieldScenarioName] // return sbox, nil // } // // GetAll - Return all sandboxes // func (gc *GisCache) GetAll() (map[string]*Sandbox, error) { // sboxMap := make(map[string]*Sandbox) // keyMatchStr := keyRoot + "*" // // Get all sandbox entry details // err := ss.rc.ForEachEntry(keyMatchStr, getSandbox, &sboxMap) // if err != nil { // log.Error("Failed to get all entries with error: ", err.Error()) // return nil, err // } // return sboxMap, nil // } // // Del - Remove sandbox with provided name // func (gc *GisCache) Del(sboxName string) { // key := keyRoot + sboxName // err := ss.rc.DelEntry(key) // if err != nil { // log.Error("Failed to delete entry for ", sboxName, " with err: ", err.Error()) // } // } // Flush - Remove all sandbox store entries func (gc *GisCache) Flush() { gc.rc.DBFlush(keyRoot) } // func getSandbox(key string, fields map[string]string, userData interface{}) error { // sboxMap := *(userData.(*map[string]*Sandbox)) // // Prepare sandbox // sbox := new(Sandbox) // sbox.Name = fields[fieldSandboxName] // sbox.ScenarioName = fields[fieldScenarioName] // // Add sandbox to // sboxMap[sbox.Name] = sbox // return nil // } Loading
go-apps/meep-gis-engine/server/gis-engine.go +81 −64 Original line number Diff line number Diff line Loading @@ -758,6 +758,7 @@ func setAutomation(automationType string, state bool) (err error) { } func runAutomation() { // Movement if ge.automation[AutoTypeMovement] { log.Debug("Auto Movement: updating UE positions") Loading @@ -776,11 +777,31 @@ func runAutomation() { ge.updateTime = currentTime } // Cache asset snapshot ueMap, err := ge.assetMgr.GetAllUe() if err != nil { log.Error(err.Error()) return } // for _, ue := range ueMap { // ue. // } // poaMap, err := ge.assetMgr.GetAllPoa() // if err != nil { // log.Error(err.Error()) // return // } // computeMap, err := ge.assetMgr.GetAllCompute() // if err != nil { // log.Error(err.Error()) // return // } // Mobility & POA In Range if ge.automation[AutoTypeMobility] || ge.automation[AutoTypePoaInRange] { // Get all UE POA information ueMap, err := ge.assetMgr.GetAllUe() if err == nil { // Loop through UEs for _, ue := range ueMap { // Get stored UE info ueInfo, isNew := getUeInfo(ue.Name) Loading Loading @@ -849,10 +870,6 @@ func runAutomation() { delete(ge.ueInfo, ueName) } } } else { log.Error(err.Error()) } } // Net Char Loading
go-packages/meep-gis-asset-mgr/asset-mgr.go +136 −35 Original line number Diff line number Diff line Loading @@ -296,7 +296,7 @@ func (am *AssetMgr) CreateTables() (err error) { log.Error(err.Error()) return err } log.Info("Created UE Mearuements table: ", UeMeasurementTable) log.Info("Created UE Measurements table: ", UeMeasurementTable) // POA Table _, err = am.db.Exec(`CREATE TABLE ` + PoaTable + ` ( Loading Loading @@ -818,9 +818,11 @@ func (am *AssetMgr) GetUe(name string) (ue *Ue, err error) { rows, err = am.db.Query(` SELECT id, name, ST_AsGeoJSON(position), ST_AsGeoJSON(path), path_mode, path_velocity, path_length, path_increment, path_fraction, poa, poa_distance, poa_in_range, poa_type_prio, connected FROM `+UeTable+` WHERE name = ($1)`, name) poa, poa_distance, poa_in_range, poa_type_prio, connected, meas.poa, meas.type, meas.radius, meas.distance, meas.in_range, meas.rssi, meas.rsrp, meas.rsrq FROM `+UeTable+` AS ue LEFT JOIN `+UeMeasurementTable+` AS meas ON (ue.name = meas.ue) WHERE ue.name = ($1)`, name) if err != nil { log.Error(err.Error()) return nil, err Loading @@ -829,22 +831,35 @@ func (am *AssetMgr) GetUe(name string) (ue *Ue, err error) { // Scan result for rows.Next() { ue = new(Ue) ueEntry := new(Ue) ueMeas := new(UeMeasurement) path := new(string) err = rows.Scan(&ue.Id, &ue.Name, &ue.Position, &path, &ue.PathMode, &ue.PathVelocity, &ue.PathLength, &ue.PathIncrement, &ue.PathFraction, &ue.Poa, &ue.PoaDistance, pq.Array(&ue.PoaInRange), pq.Array(&ue.PoaTypePrio), &ue.Connected) // Fill UE err = rows.Scan(&ueEntry.Id, &ueEntry.Name, &ueEntry.Position, &path, &ueEntry.PathMode, &ueEntry.PathVelocity, &ueEntry.PathLength, &ueEntry.PathIncrement, &ueEntry.PathFraction, &ueEntry.Poa, &ueEntry.PoaDistance, pq.Array(&ueEntry.PoaInRange), pq.Array(&ueEntry.PoaTypePrio), &ueEntry.Connected, &ueMeas.Poa, &ueMeas.SubType, &ueMeas.Radius, &ueMeas.Distance, &ueMeas.InRange, &ueMeas.Rssi, &ueMeas.Rsrp, &ueMeas.Rsrq) if err != nil { log.Error(err.Error()) return nil, err } // Store path // Create new UE if not set if ue == nil { ue = ueEntry ue.Measurements = make(map[string]*UeMeasurement) if path != nil { ue.Path = *path } } // Set UE measurement if in range if ueMeas.InRange { ue.Measurements[ueMeas.Poa] = ueMeas } } err = rows.Err() if err != nil { log.Error(err) Loading Loading @@ -950,10 +965,12 @@ func (am *AssetMgr) GetAllUe() (ueMap map[string]*Ue, err error) { // Get UE entries var rows *sql.Rows rows, err = am.db.Query(` SELECT id, name, ST_AsGeoJSON(position), ST_AsGeoJSON(path), path_mode, path_velocity, path_length, path_increment, path_fraction, poa, poa_distance, poa_in_range, poa_type_prio, connected FROM ` + UeTable) SELECT ue.id, ue.name, ST_AsGeoJSON(ue.position), ST_AsGeoJSON(ue.path), ue.path_mode, ue.path_velocity, ue.path_length, ue.path_increment, ue.path_fraction, ue.poa, ue.poa_distance, ue.poa_in_range, ue.poa_type_prio, ue.connected, meas.poa, meas.type, meas.radius, meas.distance, meas.in_range, meas.rssi, meas.rsrp, meas.rsrq FROM ` + UeTable + ` AS ue LEFT JOIN ` + UeMeasurementTable + ` AS meas ON (ue.name = meas.ue)`) if err != nil { log.Error(err.Error()) return ueMap, err Loading @@ -962,26 +979,37 @@ func (am *AssetMgr) GetAllUe() (ueMap map[string]*Ue, err error) { // Scan results for rows.Next() { ue := new(Ue) ueEntry := new(Ue) ueMeas := new(UeMeasurement) path := new(string) // Fill UE err = rows.Scan(&ue.Id, &ue.Name, &ue.Position, &path, &ue.PathMode, &ue.PathVelocity, &ue.PathLength, &ue.PathIncrement, &ue.PathFraction, &ue.Poa, &ue.PoaDistance, pq.Array(&ue.PoaInRange), pq.Array(&ue.PoaTypePrio), &ue.Connected) err = rows.Scan(&ueEntry.Id, &ueEntry.Name, &ueEntry.Position, &path, &ueEntry.PathMode, &ueEntry.PathVelocity, &ueEntry.PathLength, &ueEntry.PathIncrement, &ueEntry.PathFraction, &ueEntry.Poa, &ueEntry.PoaDistance, pq.Array(&ueEntry.PoaInRange), pq.Array(&ueEntry.PoaTypePrio), &ueEntry.Connected, &ueMeas.Poa, &ueMeas.SubType, &ueMeas.Radius, &ueMeas.Distance, &ueMeas.InRange, &ueMeas.Rssi, &ueMeas.Rsrp, &ueMeas.Rsrq) if err != nil { log.Error(err.Error()) return ueMap, err } // Store path // Get UE entry from UE map (create new entry if not found) ue := ueMap[ueEntry.Name] if ue == nil { ue = ueEntry ue.Measurements = make(map[string]*UeMeasurement) if path != nil { ue.Path = *path } // Add UE to map ueMap[ue.Name] = ue } // Set UE measurement if in range if ueMeas.InRange { ue.Measurements[ueMeas.Poa] = ueMeas } } err = rows.Err() if err != nil { log.Error(err) Loading Loading @@ -1458,6 +1486,8 @@ func (am *AssetMgr) resetUePoaInfo(name string, ueMap map[string]*Ue) (err error // Update all UE Poa Info func (am *AssetMgr) updateUeInfo(ueMap map[string]*Ue) (err error) { // start := time.Now() // Begin Update Transaction tx, err := am.db.Begin() if err != nil { Loading @@ -1481,7 +1511,7 @@ func (am *AssetMgr) updateUeInfo(ueMap map[string]*Ue) (err error) { poa_distance = $3, poa_in_range = $4 WHERE name = ($1)` _, err = am.db.Exec(query, ueName, selectedPoa, distance, pq.Array(ue.PoaInRange)) _, err = tx.Exec(query, ueName, selectedPoa, distance, pq.Array(ue.PoaInRange)) if err != nil { log.Error(err.Error()) return err Loading @@ -1489,19 +1519,17 @@ func (am *AssetMgr) updateUeInfo(ueMap map[string]*Ue) (err error) { // Update UE measurements for poaName, meas := range ue.Measurements { // Calculate power measurements rssi := 1.1 rsrp := 2.2 rsrq := -3.3 rssi, rsrp, rsrq := calculatePower(meas.SubType, meas.Radius, meas.Distance) query := `INSERT INTO ` + UeMeasurementTable + ` (ue, poa, type, radius, distance, in_range, rssi, rsrp, rsrq) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) // Add new entry or update existing one id := ueName + "-" + poaName query := `INSERT INTO ` + UeMeasurementTable + ` (id, ue, poa, type, radius, distance, in_range, rssi, rsrp, rsrq) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) ON CONFLICT (id) DO UPDATE SET radius = $4, distance = $5, in_range = $6, rssi = $7, rsrp = $8, rsrq = $9 WHERE ue = ($1) AND poa = ($2)` log.Error(query) _, err = am.db.Exec(query, ueName, poaName, meas.SubType, meas.Radius, meas.Distance, meas.InRange, rssi, rsrp, rsrq) DO UPDATE SET radius = $5, distance = $6, in_range = $7, rssi = $8, rsrp = $9, rsrq = $10 WHERE ` + UeMeasurementTable + `.ue = ($2) AND ` + UeMeasurementTable + `.poa = ($3)` _, err = tx.Exec(query, id, ueName, poaName, meas.SubType, meas.Radius, meas.Distance, meas.InRange, rssi, rsrp, rsrq) if err != nil { log.Error(err.Error()) return err Loading @@ -1509,6 +1537,9 @@ func (am *AssetMgr) updateUeInfo(ueMap map[string]*Ue) (err error) { } } // finish := time.Now() // log.Error("UPDATE DURATION: ", finish.Sub(start)) return nil } Loading Loading @@ -1589,3 +1620,73 @@ func getPoaTypePriority(poaType string, poaTypePrio []string) int { } return priority } func calculatePower(subtype string, radius float32, distance float32) (rssi float32, rsrp float32, rsrq float32) { switch subtype { case PoaTypeCell4g: rsrp, rsrq = calculateCell4gPower(radius, distance) case PoaTypeCell5g: rsrp, rsrq = calculateCell5gPower(radius, distance) case PoaTypeWifi: rssi = calculateWifiPower(radius, distance) default: } return rssi, rsrp, rsrq } // 4G Cellular signal strength calculator // RSRP power range: -156 dBm to -44 dBm // Equivalent RSRP range: -17 to 97 // RSRQ power range: -34 dBm to 2.5 dBm // Equivalent RSRQ range: -30 to 46 // Algorithm: Linear proportion to distance over radius, if in range const minCell4gRsrp = float32(-17) const maxCell4gRsrp = float32(97) const minCell4gRsrq = float32(-30) const maxCell4gRsrq = float32(46) func calculateCell4gPower(radius float32, distance float32) (rsrp float32, rsrq float32) { rsrp = minCell4gRsrp rsrq = minCell4gRsrq if distance < radius { rsrp = float32(int(minCell4gRsrp + ((maxCell4gRsrp - minCell4gRsrp) * (1 - (distance / radius))))) rsrq = float32(int(minCell4gRsrq + ((maxCell4gRsrq - minCell4gRsrq) * (1 - (distance / radius))))) } return rsrp, rsrq } // 5G Cellular signal strength calculator // RSRP power range: -156 dBm to -31 dBm // Equivalent RSRP range: 0 to 127 // RSRQ power range: -43 dBm to 20 dBm // Equivalent RSRQ range: 0 to 127 // Algorithm: Linear proportion to distance over radius, if in range const minCell5gRsrp = float32(0) const maxCell5gRsrp = float32(127) const minCell5gRsrq = float32(0) const maxCell5gRsrq = float32(127) func calculateCell5gPower(radius float32, distance float32) (rsrp float32, rsrq float32) { rsrp = minCell5gRsrp rsrq = minCell5gRsrq if distance < radius { rsrp = float32(int(minCell5gRsrp + ((maxCell5gRsrp - minCell5gRsrp) * (1 - (distance / radius))))) rsrq = float32(int(minCell5gRsrq + ((maxCell5gRsrq - minCell5gRsrq) * (1 - (distance / radius))))) } return rsrp, rsrq } // WiFi signal strength calculator // Signal power range: -113 dBm to -10 dBm // Equivalent RSSI range: 0 to 100 // Algorithm: Linear proportion to distance over radius, if in range const minWifiRssi = float32(0) const maxWifiRssi = float32(100) func calculateWifiPower(radius float32, distance float32) (rssi float32) { rssi = minWifiRssi if distance < radius { rssi = float32(int(minWifiRssi + ((maxWifiRssi - minWifiRssi) * (1 - (distance / radius))))) } return rssi }
go-packages/meep-gis-asset-mgr/go.mod +0 −1 Original line number Diff line number Diff line Loading @@ -4,7 +4,6 @@ go 1.12 require ( github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-logger v0.0.0 github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-postgis v0.0.0-20200703133018-94138d8210a3 // indirect github.com/lib/pq v1.5.2 ) Loading
go-packages/meep-gis-asset-mgr/go.sum +0 −3 Original line number Diff line number Diff line github.com/InterDigitalInc/AdvantEDGE v1.5.0 h1:Gv1wxW7kV31reTqxX5TflvvYEEqnxaUlKWvgoandpfI= github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-postgis v0.0.0-20200703133018-94138d8210a3 h1:O3BYtbMjdX0Qre4kr5vCxbhHZuSPJBEFwIdMOuWS3Dk= github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-postgis v0.0.0-20200703133018-94138d8210a3/go.mod h1:4uz6tZflvTKPcqTf8nu3k2GaotQy4bKsOYj4dw5VTR0= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/lib/pq v1.5.2 h1:yTSXVswvWUOQ3k1sd7vJfDrbSl8lKuscqFJRqjC0ifw= Loading
go-packages/meep-gis-cache/gis-cache.go 0 → 100644 +141 −0 Original line number Diff line number Diff line /* * Copyright (c) 2020 InterDigital Communications, Inc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package giscache import ( dkm "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-data-key-mgr" log "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-logger" redis "github.com/InterDigitalInc/AdvantEDGE/go-packages/meep-redis" ) const redisTable = 0 // Root key var keyRoot = dkm.GetKeyRootGlobal() + "gis-cache:" type Location struct { Name string } type UeMeasurement struct { Name string } type GisCache struct { rc *redis.Connector } // NewGisCache - Creates and initialize a GIS Cache instance func NewGisCache(redisAddr string) (gc *GisCache, err error) { // Create new GIS Cache instance gc = new(GisCache) // Connect to Redis DB gc.rc, err = redis.NewConnector(redisAddr, redisTable) if err != nil { log.Error("Failed connection to GIS Cache Redis DB. Error: ", err) return nil, err } log.Info("Connected to GIS Cache Redis DB") log.Info("Created GIS Cache") return gc, nil } // // Set - Create or update entry in DB // func (gc *GisCache) Set(name string, location *Location) error { // // Prepare data // fields := make(map[string]interface{}) // fields[fieldSandboxName] = sbox.Name // fields[fieldScenarioName] = sbox.ScenarioName // // Update entry in DB // key := keyRoot + sbox.Name // err := ss.rc.SetEntry(key, fields) // if err != nil { // log.Error("Failed to set entry with error: ", err.Error()) // return err // } // return nil // } // // Get - Return sandbox with provided name // func (gc *GisCache) Get(name string) (*Sandbox, error) { // key := keyRoot + sboxName // // Make sure entry exists // if !ss.rc.EntryExists(key) { // err := errors.New("Entry not found") // log.Error(err.Error()) // return nil, err // } // // Find entry // fields, err := ss.rc.GetEntry(key) // if err != nil { // log.Error("Failed to get entry with error: ", err.Error()) // return nil, err // } // // Prepare sandbox // sbox := new(Sandbox) // sbox.Name = fields[fieldSandboxName] // sbox.ScenarioName = fields[fieldScenarioName] // return sbox, nil // } // // GetAll - Return all sandboxes // func (gc *GisCache) GetAll() (map[string]*Sandbox, error) { // sboxMap := make(map[string]*Sandbox) // keyMatchStr := keyRoot + "*" // // Get all sandbox entry details // err := ss.rc.ForEachEntry(keyMatchStr, getSandbox, &sboxMap) // if err != nil { // log.Error("Failed to get all entries with error: ", err.Error()) // return nil, err // } // return sboxMap, nil // } // // Del - Remove sandbox with provided name // func (gc *GisCache) Del(sboxName string) { // key := keyRoot + sboxName // err := ss.rc.DelEntry(key) // if err != nil { // log.Error("Failed to delete entry for ", sboxName, " with err: ", err.Error()) // } // } // Flush - Remove all sandbox store entries func (gc *GisCache) Flush() { gc.rc.DBFlush(keyRoot) } // func getSandbox(key string, fields map[string]string, userData interface{}) error { // sboxMap := *(userData.(*map[string]*Sandbox)) // // Prepare sandbox // sbox := new(Sandbox) // sbox.Name = fields[fieldSandboxName] // sbox.ScenarioName = fields[fieldScenarioName] // // Add sandbox to // sboxMap[sbox.Name] = sbox // return nil // }