Start start in frontend! Simulation Query
This commit is contained in:
parent
44e28d8e6b
commit
e698c75309
@ -156,6 +156,16 @@ export const DeleteSignal = (name) => {
|
||||
};
|
||||
};
|
||||
|
||||
export const RunSimulatorSignal = (id) => {
|
||||
const signal = 100;
|
||||
|
||||
return {
|
||||
signal,
|
||||
data: {
|
||||
id,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
@ -7,7 +7,7 @@ import HeightPoint from './model/HeightPoint';
|
||||
import { RandomHeightPoint } from './helpers/generateRandomHeightPoints'
|
||||
import ModalWindow from './components/Modal/Modal';
|
||||
import { getCustomCookie } from '../Services/Local';
|
||||
import useWebsocketConnection, { DeleteSignal, spawnJsonSignal } from '../Services/WebsocketHook';
|
||||
import useWebsocketConnection, { DeleteSignal, spawnJsonSignal, RunSimulatorSignal } from '../Services/WebsocketHook';
|
||||
import './Dashboard.css';
|
||||
|
||||
|
||||
@ -781,7 +781,10 @@ const containsObjectRecursively = (parent, target) => {
|
||||
</div>
|
||||
<div class="btn-group me-2" role="group" aria-label="Third group">
|
||||
<button type="button" class="btn btn-info">
|
||||
<i class="bi-play"/>
|
||||
<i class="bi-play" onClick={() => {
|
||||
sendMessage(RunSimulatorSignal(getCustomCookie("userToken")))
|
||||
|
||||
}}/>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
@ -3,7 +3,10 @@ package websocket
|
||||
import (
|
||||
"fmt"
|
||||
"moxitech/dns/package/math/simulator"
|
||||
sim_queue "moxitech/dns/package/simulation"
|
||||
"moxitech/dns/package/utils/randomizer"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -49,75 +52,112 @@ func (o *Modulation) MirrorPayloadToSimulationStruct() Modulation {
|
||||
return shadow_sim_copy
|
||||
}
|
||||
|
||||
func (o *Modulation) RunSimulator() {
|
||||
// // Пример карты высот, замените на настоящие данные
|
||||
// heightData := [][]float64{
|
||||
// {0, 10, 15, 20},
|
||||
// {5, 15, 25, 30},
|
||||
// {10, 20, 35, 40},
|
||||
// {15, 25, 40, 50},
|
||||
// }
|
||||
// StartNewSimulation - инициирует парсинг и добавление в очередь для обработки симуляции
|
||||
func (o *Modulation) StartNewSimulation(timestep int, user_id string) {
|
||||
mapObj := o.Map
|
||||
drones := []*simulator.Drone{}
|
||||
stations := []*simulator.BaseStation{}
|
||||
|
||||
// // Определяем карту высот
|
||||
//
|
||||
// mapObj := &simulator.Map{
|
||||
// Name: "Example Map",
|
||||
// MinBound: [3]float64{-1000, -1000, 0},
|
||||
// MaxBound: [3]float64{1000, 1000, 500},
|
||||
// HeightData: heightData,
|
||||
// }
|
||||
//
|
||||
// ? mapObj := o.Map
|
||||
for i, v := range o.Objects {
|
||||
if v.Params == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// // Определяем дронов
|
||||
//
|
||||
// drones := []*simulator.Drone{
|
||||
// {
|
||||
// ID: 1,
|
||||
// Name: "Drone 1",
|
||||
// Coords: [3]float64{100, 100, 50},
|
||||
// Params: simulator.DroneParams{
|
||||
// AntennaRadius: 500,
|
||||
// AntennaDirection: [3]float64{1, 0, 0},
|
||||
// Waypoints: [][3]float64{{200, 200, 50}},
|
||||
// Speed: 10,
|
||||
// MeshName: "MeshA",
|
||||
// },
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// // Определяем базовые станции
|
||||
//
|
||||
// baseStations := []*simulator.BaseStation{
|
||||
// {
|
||||
// ID: 1,
|
||||
// Name: "BaseStation1",
|
||||
// Coords: [3]float64{0, 0, 0},
|
||||
// Params: simulator.BaseStationParams{
|
||||
// AntennaRadius: 2000,
|
||||
// AntennaDirection: [3]float64{1, 0, 0},
|
||||
// },
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// // Создаем симуляцию
|
||||
//
|
||||
// sim := &simulator.NetworkSimulation{
|
||||
// Map: mapObj,
|
||||
// Drones: drones,
|
||||
// BaseStations: baseStations,
|
||||
// TimeStep: 2,
|
||||
// }
|
||||
//
|
||||
// // Запуск симуляции на 300 секунд
|
||||
// result_sim := sim.Simulate(300)
|
||||
// result := u_sorting.SortMap(result_sim)
|
||||
//
|
||||
// for time, state := range result {
|
||||
// for localstate, f := range state {
|
||||
// fmt.Printf("%v| %v sec :: %v\n", time, localstate, f)
|
||||
// }
|
||||
// }
|
||||
params := *v.Params
|
||||
if v.Type == 1 {
|
||||
// Парсинг параметров для дронов
|
||||
antennaDirection := [3]float64{1, 0, 0} // значение по умолчанию
|
||||
if dir, ok := params["antennaDirections"]; ok && dir != "" {
|
||||
directionValues := strings.Split(dir, ",")
|
||||
if len(directionValues) == 3 {
|
||||
antennaDirection[0], _ = strconv.ParseFloat(directionValues[0], 64)
|
||||
antennaDirection[1], _ = strconv.ParseFloat(directionValues[1], 64)
|
||||
antennaDirection[2], _ = strconv.ParseFloat(directionValues[2], 64)
|
||||
}
|
||||
}
|
||||
|
||||
antennaRadius := 100.0 // значение по умолчанию
|
||||
if radius, ok := params["antennaRadius"]; ok && radius != "" {
|
||||
antennaRadius, _ = strconv.ParseFloat(radius, 64)
|
||||
}
|
||||
|
||||
waypoints := [][3]float64{}
|
||||
if wp, ok := params["wayPoints"]; ok && wp != "" {
|
||||
// Парсинг waypoints, предполагаем, что это строка вида "x1,y1,z1;x2,y2,z2"
|
||||
waypointStrings := strings.Split(wp, ";")
|
||||
for _, waypointStr := range waypointStrings {
|
||||
coords := strings.Split(waypointStr, ",")
|
||||
if len(coords) == 3 {
|
||||
x, _ := strconv.ParseFloat(coords[0], 64)
|
||||
y, _ := strconv.ParseFloat(coords[1], 64)
|
||||
z, _ := strconv.ParseFloat(coords[2], 64)
|
||||
waypoints = append(waypoints, [3]float64{x, y, z})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
speed := 0.0
|
||||
if spd, ok := params["speed"]; ok && spd != "" {
|
||||
speed, _ = strconv.ParseFloat(spd, 64)
|
||||
}
|
||||
|
||||
meshName := ""
|
||||
if mesh, ok := params["meshName"]; ok {
|
||||
meshName = mesh
|
||||
}
|
||||
|
||||
drone := simulator.Drone{
|
||||
ID: i,
|
||||
Name: v.Name,
|
||||
Coords: [3]float64{float64(v.Coords[0]), float64(v.Coords[1]), float64(v.Coords[2])},
|
||||
Params: simulator.DroneParams{
|
||||
AntennaRadius: antennaRadius,
|
||||
AntennaDirection: antennaDirection,
|
||||
Waypoints: waypoints,
|
||||
Speed: speed,
|
||||
MeshName: meshName,
|
||||
},
|
||||
}
|
||||
drones = append(drones, &drone)
|
||||
}
|
||||
|
||||
if v.Type == 2 {
|
||||
// Парсинг параметров для базовых станций
|
||||
antennaDirection := [3]float64{1, 0, 0} // значение по умолчанию
|
||||
if dir, ok := params["antennaDirections"]; ok && dir != "" {
|
||||
directionValues := strings.Split(dir, ",")
|
||||
if len(directionValues) == 3 {
|
||||
antennaDirection[0], _ = strconv.ParseFloat(directionValues[0], 64)
|
||||
antennaDirection[1], _ = strconv.ParseFloat(directionValues[1], 64)
|
||||
antennaDirection[2], _ = strconv.ParseFloat(directionValues[2], 64)
|
||||
}
|
||||
}
|
||||
|
||||
antennaRadius := 200.0 // значение по умолчанию
|
||||
if radius, ok := params["antennaRadius"]; ok && radius != "" {
|
||||
antennaRadius, _ = strconv.ParseFloat(radius, 64)
|
||||
}
|
||||
|
||||
baseStation := simulator.BaseStation{
|
||||
ID: i,
|
||||
Name: v.Name,
|
||||
Coords: [3]float64{float64(v.Coords[0]), float64(v.Coords[1]), float64(v.Coords[2])},
|
||||
Params: simulator.BaseStationParams{
|
||||
AntennaRadius: antennaRadius,
|
||||
AntennaDirection: antennaDirection,
|
||||
},
|
||||
}
|
||||
stations = append(stations, &baseStation)
|
||||
}
|
||||
}
|
||||
|
||||
sim := &simulator.NetworkSimulation{
|
||||
Map: &mapObj.Map,
|
||||
Drones: drones,
|
||||
BaseStations: stations,
|
||||
TimeStep: timestep,
|
||||
}
|
||||
sim_queue.AddSimulationTask(*sim, user_id)
|
||||
}
|
||||
|
||||
// SpawnExampleData создает случайные данные и перезаписывает карту
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"moxitech/dns/entity/dto"
|
||||
"moxitech/dns/internal/server/handlers/authorization"
|
||||
sim_queue "moxitech/dns/package/simulation"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
@ -20,6 +21,8 @@ var (
|
||||
)
|
||||
|
||||
func SpawnServer() error {
|
||||
sim_queue.Start()
|
||||
go sim_queue.InvokeComplete()
|
||||
app := fiber.New()
|
||||
app.Use(cors.New(cors.Config{
|
||||
AllowHeaders: "*",
|
||||
|
@ -230,12 +230,22 @@ func (room *WebsocketRoom) InsertMapFromMongo(name string) {
|
||||
}
|
||||
|
||||
// RunSimulation запускает симуляцию в горутине
|
||||
func (room *WebsocketRoom) RunSimulation(name string) (int, error) {
|
||||
// TODO +NormalizeDataForSimulation()
|
||||
func (room *WebsocketRoom) RunSimulation(message websocket.SignalMessage) (int, error) {
|
||||
var parsedData struct {
|
||||
UserInvoked string `json:"id"`
|
||||
}
|
||||
// Парсим `data` в структуру
|
||||
err := json.Unmarshal(message.Data, &parsedData)
|
||||
if err != nil {
|
||||
return -1, fmt.Errorf("[insert] error parsing data: %v", err)
|
||||
}
|
||||
if parsedData.UserInvoked == "" {
|
||||
return -1, fmt.Errorf("[insert] Error parse userID: %v", err)
|
||||
}
|
||||
roomsMutex.Lock()
|
||||
defer roomsMutex.Unlock()
|
||||
room.Modulation.MirrorPayloadToSimulationStruct()
|
||||
return -1, nil
|
||||
room.Modulation.StartNewSimulation(100, parsedData.UserInvoked)
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// NormalizeDataForSimulation - Преобразование данных для отправки в симуляцию
|
||||
@ -255,6 +265,7 @@ func (room *WebsocketRoom) WebsocketAction(message []byte) (error, bool) {
|
||||
fmt.Printf("[WebsocketAction] %v", err)
|
||||
return fmt.Errorf("error parsing occured: %v \n waiting for signal struct", err), false
|
||||
}
|
||||
fmt.Println("Run collector")
|
||||
room.UpdateGroupUptime()
|
||||
switch Signal.Signal {
|
||||
case 0:
|
||||
@ -264,6 +275,7 @@ func (room *WebsocketRoom) WebsocketAction(message []byte) (error, bool) {
|
||||
room.InsertObject(Signal)
|
||||
return nil, true
|
||||
case 2:
|
||||
fmt.Println("Начата вставка объекта")
|
||||
room.InsertObject(Signal)
|
||||
return nil, true
|
||||
case 3:
|
||||
@ -287,6 +299,8 @@ func (room *WebsocketRoom) WebsocketAction(message []byte) (error, bool) {
|
||||
case 33:
|
||||
// SYNC SIGNAL
|
||||
case 100:
|
||||
fmt.Println("Запуск симуляции : ", Signal)
|
||||
room.RunSimulation(Signal)
|
||||
case 101:
|
||||
// room.StoreMongo(Signal)
|
||||
|
||||
|
60
src/server/package/simulation/sim_queue.go
Normal file
60
src/server/package/simulation/sim_queue.go
Normal file
@ -0,0 +1,60 @@
|
||||
package sim_queue
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"moxitech/dns/package/math/simulator"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
var (
|
||||
AddChannel = make(chan simulator.NetworkSimulation)
|
||||
CompleteChannel = make(chan *simulationResult)
|
||||
)
|
||||
|
||||
type simulationResult struct {
|
||||
Sim *simulator.NetworkSimulation
|
||||
UserID string
|
||||
}
|
||||
|
||||
// AddSimulationTask adds a network simulation to the queue and runs it in a goroutine.
|
||||
func AddSimulationTask(sim simulator.NetworkSimulation, userID string) {
|
||||
AddChannel <- sim
|
||||
CompleteChannel <- &simulationResult{Sim: &sim, UserID: userID}
|
||||
}
|
||||
|
||||
// InvokeComplete listens for completed simulations, serializes them to JSON, and sends to a specified endpoint.
|
||||
func InvokeComplete() {
|
||||
for result := range CompleteChannel {
|
||||
go func(result *simulationResult) {
|
||||
jsonData, err := json.Marshal(result.Sim)
|
||||
if err != nil {
|
||||
fmt.Println("Error serializing simulation result:", err)
|
||||
return
|
||||
}
|
||||
url := fmt.Sprintf("http://socket:9091/storeEvent?client_id=%s&message=%s", result.UserID, string(jsonData))
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
fmt.Println("Error sending simulation result:", err)
|
||||
return
|
||||
}
|
||||
// database.Instance.InsertIntoSimulations(jsonData)
|
||||
defer resp.Body.Close()
|
||||
}(result)
|
||||
}
|
||||
}
|
||||
|
||||
// Start starts listening on the channels to manage simulations.
|
||||
func Start() {
|
||||
go func() {
|
||||
for sim := range AddChannel {
|
||||
go runSimulation(sim)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// runSimulation runs a simulation and then sends it to the CompleteChannel.
|
||||
func runSimulation(sim simulator.NetworkSimulation) {
|
||||
sim.Simulate(sim.TimeStep) // Run the simulation for 300 iterations (as an example)
|
||||
CompleteChannel <- &simulationResult{Sim: &sim}
|
||||
}
|
Loading…
Reference in New Issue
Block a user