Commit c778d5ab authored by Kevin Di Lallo's avatar Kevin Di Lallo
Browse files

auto-movement initial implementation

parent 60736254
Loading
Loading
Loading
Loading
+51 −22
Original line number Diff line number Diff line
@@ -428,27 +428,67 @@ func fillGeoDataAsset(geoData *GeoDataAsset, position string, path string, radiu
}

func resetAutomation() {
	ge.automation[AutoTypeMobility] = false
	ge.automation[AutoTypeMovement] = false
	ge.automation[AutoTypeNetChar] = false
	ge.automation[AutoTypePoaInRange] = false
	_ = setAutomation(AutoTypeMovement, false)
	_ = setAutomation(AutoTypeMobility, false)
	_ = setAutomation(AutoTypeNetChar, false)
	_ = setAutomation(AutoTypePoaInRange, false)
}

func startAutomation() {
	log.Debug("Starting automation loop")
	ge.ticker = time.NewTicker(1000 * time.Millisecond)
	ge.updateTime = time.Now()

	go func() {
		for range ge.ticker.C {
			runAutomationLoop()
			runAutomation()
		}
	}()
}

func runAutomationLoop() {
// func stopAutomation() {
// 	log.Debug("Stopping automation loop")
// 	if ge.ticker != nil {
// 		ge.ticker.Stop()
// 		ge.ticker = nil
// 	}
// }

func setAutomation(automationType string, state bool) (err error) {
	// Validate automation type
	if _, found := ge.automation[automationType]; !found {
		return errors.New("Automation type not found")
	}

	// Type-specific configuration
	if automationType == AutoTypeNetChar || automationType == AutoTypePoaInRange {
		return errors.New("Automation type not supported")
	} else if automationType == AutoTypeMovement {
		if state {
			ge.updateTime = time.Now()
		} else {
			ge.updateTime = time.Time{}
		}
	}

	// Update automation state
	ge.automation[automationType] = state

	return nil
}

func runAutomation() {
	// Movement
	if ge.automation[AutoTypeMovement] {
		log.Debug("Auto Movement: updating UE positions")

		// Calculate number of increments (seconds) for position update
		currentTime := time.Now()
		increment := float32(currentTime.Sub(ge.updateTime).Seconds())

		// Update all UE positions with increment
		// ge.pc.Refreash

		// Store new update timestamp
		ge.updateTime = currentTime
	}

	// Mobility & POA In Range
@@ -597,25 +637,14 @@ func geSetAutomationStateByName(w http.ResponseWriter, r *http.Request) {
		log.Debug("Stop automation for type: ", automationType)
	}

	// Validate automation type
	if _, found := ge.automation[automationType]; !found {
		err := errors.New("Automation type not found")
	// Set automation state
	err := setAutomation(automationType, automationState)
	if err != nil {
		log.Error(err.Error())
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	// Filter unsupported automation types
	if automationType == AutoTypeNetChar || automationType == AutoTypePoaInRange {
		err := errors.New("Automation type not supported")
		log.Error(err.Error())
		http.Error(w, err.Error(), http.StatusNotImplemented)
		return
	}

	// Update automation state
	ge.automation[automationType] = automationState

	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	w.WriteHeader(http.StatusOK)
}
+47 −8
Original line number Diff line number Diff line
@@ -854,19 +854,58 @@ func (pc *Connector) DeleteAllCompute() (err error) {
	return nil
}

// AdvanceUePosition - Advance UE along path by provided number of increments
func (pc *Connector) AdvanceUePosition(name string, increment float32) (err error) {
	// Set new position
	// query := `UPDATE ` + UeTable + `
	// SET position = CASE
	// 		WHEN path_mode='` + PathModeLoop + `' THEN ST_LineInterpolatePoint(path, path_fraction + ($2 * path_increment))
	// 		ELSE position
	// 	END,
	// 	path_fraction = CASE
	// 		WHEN path_mode='` + PathModeLoop + `' THEN path_fraction + ($2 * path_increment)
	// 		ELSE path_fraction
	// 	END
	// FROM (
	// 	SELECT
	// 		ST_Length(path::geography) AS path_len, path_velocity
	// 	FROM ` + UeTable + `
	// 	WHERE name = ($1)
	// ) AS selected_ue
	// WHERE name = ($1)`
	query := `UPDATE ` + UeTable + `
		SET position = ST_LineInterpolatePoint(path, (path_fraction + ($2 * path_increment)) % 1),
			path_fraction = (path_fraction + ($2 * path_increment)) % 1
		WHERE name = ($1) AND path_mode='` + PathModeLoop + `'`
	_, err = pc.db.Exec(query, name, increment)
	if err != nil {
		log.Error(err.Error())
		return err
	}

	// Refresh UE POA information
	err = pc.refreshUePoa(name)
	if err != nil {
		log.Error(err.Error())
		return err
	}

	return nil
}

// AdvanceUePosition - Advance all UEs along path by provided number of increments
func (pc *Connector) AdvanceAllUePosition(name string, increment float32) (err error) {
	return nil
}

// ------------------------ Private Methods -----------------------------------

// Recalculate UE path length & increment
func (pc *Connector) refreshUePath(name string) (err error) {
	query := `UPDATE ` + UeTable + `
		SET path_length = selected_ue.path_len,
			path_increment = selected_ue.path_velocity / selected_ue.path_len,
		SET path_length = ST_Length(path::geography),
			path_increment = path_velocity / ST_Length(path::geography),
			path_fraction = 0
		FROM (
			SELECT ST_Length(path::geography) AS path_len, path_velocity
			FROM ` + UeTable + `
			WHERE name = ($1)
		) AS selected_ue
		WHERE name = ($1)`
	_, err = pc.db.Exec(query, name)
	if err != nil {
@@ -885,7 +924,7 @@ func (pc *Connector) refreshUePoa(name string) (err error) {
		SELECT ue.name AS ue, poa.name as poa,
			ST_Distance(ue.position::geography, poa.position::geography) AS dist,
			ST_DWithin(ue.position::geography, poa.position::geography, poa.radius) AS in_range
		FROM `+UeTable+`, `+PoaTable+`
		FROM `+UeTable+` AS ue, `+PoaTable+` AS poa
		WHERE ue.name = ($1)`, name)
	if err != nil {
		log.Error(err.Error())
+96 −28
Original line number Diff line number Diff line
@@ -534,51 +534,119 @@ func TestPostgisConnectorNew(t *testing.T) {
		t.Fatalf("Compute validation failed")
	}

	// Delete all POA & validate updates
	fmt.Println("Delete all POA & validate updates")
	err = pc.DeleteAllPoa()
	// Advance UE1 along path and validate UE
	fmt.Println("Advance UE1 along path and validate UE")

	ueLoc = "{\"type\":\"Point\",\"coordinates\":[7.419547938,43.735155405]}"
	err = pc.AdvanceUePosition(ue1Name, 25.0)
	if err != nil {
		t.Fatalf("Failed to delete all POA")
	}
	poaMap, err = pc.GetAllPoa()
	if err != nil || len(poaMap) != 0 {
		t.Fatalf("POAs should no longer exist")
		t.Fatalf("Failed to create asset")
	}
	ueMap, err = pc.GetAllUe()
	if err != nil || len(ueMap) != 3 {
		t.Fatalf("Failed to get all UE")
	ue, err = pc.GetUe(ue1Name)
	if err != nil || ue == nil {
		t.Fatalf("Failed to get UE")
	}
	if !validateUe(ueMap[ue1Name], ue1Id, ue1Name, ue1Loc, ue1Path, ue1PathMode, ue1Velocity, 1383.59, 0.004, 0.000, "", 0.000, []string{}) {
	if !validateUe(ue, ue1Id, ue1Name, ueLoc, ue1Path, ue1PathMode, ue1Velocity, 1383.59, 0.004, 0.1, poa1Name, 207.738, []string{poa2Name}) {
		t.Fatalf("UE validation failed")
	}
	if !validateUe(ueMap[ue2Name], ue2Id, ue2Name, ue2Loc, ue2Path, ue2PathMode, ue2Velocity, 0.000, 0.000, 0.000, "", 0.000, []string{}) {

	ueLoc = "{\"type\":\"Point\",\"coordinates\":[7.421527545,43.736845475]}"
	err = pc.AdvanceUePosition(ue1Name, 50.0)
	if err != nil {
		t.Fatalf("Failed to create asset")
	}
	ue, err = pc.GetUe(ue1Name)
	if err != nil || ue == nil {
		t.Fatalf("Failed to get UE")
	}
	if !validateUe(ue, ue1Id, ue1Name, ueLoc, ue1Path, ue1PathMode, ue1Velocity, 1383.59, 0.004, 0.3, poa2Name, 17.216, []string{poa2Name}) {
		t.Fatalf("UE validation failed")
	}
	if !validateUe(ueMap[ue3Name], ue3Id, ue3Name, ue3Loc, ue3Path, ue3PathMode, ue3Velocity, 810.678, 0.031, 0.000, "", 0.000, []string{}) {

	ueLoc = "{\"type\":\"Point\",\"coordinates\":[7.422078743,43.73409359]}"
	err = pc.AdvanceUePosition(ue1Name, 50.0)
	if err != nil {
		t.Fatalf("Failed to create asset")
	}
	ue, err = pc.GetUe(ue1Name)
	if err != nil || ue == nil {
		t.Fatalf("Failed to get UE")
	}
	if !validateUe(ue, ue1Id, ue1Name, ueLoc, ue1Path, ue1PathMode, ue1Velocity, 1383.59, 0.004, 0.5, poa3Name, 125.284, []string{poa2Name, poa3Name}) {
		t.Fatalf("UE validation failed")
	}

	// Delete all UE & validate updates
	fmt.Println("Delete all UE & validate updates")
	err = pc.DeleteAllUe()
	err = pc.AdvanceUePosition(ue1Name, 125.0)
	if err != nil {
		t.Fatalf("Failed to delete all UE")
		t.Fatalf("Failed to create asset")
	}
	ueMap, err = pc.GetAllUe()
	if err != nil || len(ueMap) != 0 {
		t.Fatalf("UE should no longer exist")
	ue, err = pc.GetUe(ue1Name)
	if err != nil || ue == nil {
		t.Fatalf("Failed to get UE")
	}
	fmt.Printf("%+v\n", ue)
	if !validateUe(ue, ue1Id, ue1Name, ue1Loc, ue1Path, ue1PathMode, ue1Velocity, 1383.59, 0.004, 0, poa1Name, 83.25, []string{poa1Name}) {
		t.Fatalf("UE validation failed")
	}

	// Delete all Compute & validate updates
	fmt.Println("Delete all Compute & validate updates")
	err = pc.DeleteAllCompute()
	ueLoc = "{\"type\":\"Point\",\"coordinates\":[7.419547938,43.735155405]}"
	err = pc.AdvanceUePosition(ue1Name, 25.0)
	if err != nil {
		t.Fatalf("Failed to delete all Compute")
		t.Fatalf("Failed to create asset")
	}
	computeMap, err = pc.GetAllCompute()
	if err != nil || len(computeMap) != 0 {
		t.Fatalf("Compute should no longer exist")
	ue, err = pc.GetUe(ue1Name)
	if err != nil || ue == nil {
		t.Fatalf("Failed to get UE")
	}
	if !validateUe(ue, ue1Id, ue1Name, ueLoc, ue1Path, ue1PathMode, ue1Velocity, 1383.59, 0.004, 0.1, poa1Name, 207.738, []string{poa2Name}) {
		t.Fatalf("UE validation failed")
	}

	// // Delete all POA & validate updates
	// fmt.Println("Delete all POA & validate updates")
	// err = pc.DeleteAllPoa()
	// if err != nil {
	// 	t.Fatalf("Failed to delete all POA")
	// }
	// poaMap, err = pc.GetAllPoa()
	// if err != nil || len(poaMap) != 0 {
	// 	t.Fatalf("POAs should no longer exist")
	// }
	// ueMap, err = pc.GetAllUe()
	// if err != nil || len(ueMap) != 3 {
	// 	t.Fatalf("Failed to get all UE")
	// }
	// if !validateUe(ueMap[ue1Name], ue1Id, ue1Name, ue1Loc, ue1Path, ue1PathMode, ue1Velocity, 1383.59, 0.004, 0.000, "", 0.000, []string{}) {
	// 	t.Fatalf("UE validation failed")
	// }
	// if !validateUe(ueMap[ue2Name], ue2Id, ue2Name, ue2Loc, ue2Path, ue2PathMode, ue2Velocity, 0.000, 0.000, 0.000, "", 0.000, []string{}) {
	// 	t.Fatalf("UE validation failed")
	// }
	// if !validateUe(ueMap[ue3Name], ue3Id, ue3Name, ue3Loc, ue3Path, ue3PathMode, ue3Velocity, 810.678, 0.031, 0.000, "", 0.000, []string{}) {
	// 	t.Fatalf("UE validation failed")
	// }

	// // Delete all UE & validate updates
	// fmt.Println("Delete all UE & validate updates")
	// err = pc.DeleteAllUe()
	// if err != nil {
	// 	t.Fatalf("Failed to delete all UE")
	// }
	// ueMap, err = pc.GetAllUe()
	// if err != nil || len(ueMap) != 0 {
	// 	t.Fatalf("UE should no longer exist")
	// }

	// // Delete all Compute & validate updates
	// fmt.Println("Delete all Compute & validate updates")
	// err = pc.DeleteAllCompute()
	// if err != nil {
	// 	t.Fatalf("Failed to delete all Compute")
	// }
	// computeMap, err = pc.GetAllCompute()
	// if err != nil || len(computeMap) != 0 {
	// 	t.Fatalf("Compute should no longer exist")
	// }

	// t.Fatalf("DONE")
}