server & frontend update :: signaling
This commit is contained in:
parent
a3d344ee2f
commit
047a3ffd5c
@ -71,6 +71,10 @@ services:
|
||||
context: ./src/frontend
|
||||
dockerfile: Dockerfile
|
||||
env_file: ".env"
|
||||
volumes:
|
||||
- ./src/frontend:/app
|
||||
working_dir: /app
|
||||
command: ["npm", "start"]
|
||||
ports:
|
||||
- "3000:3000"
|
||||
networks:
|
||||
|
@ -11,7 +11,7 @@ COPY package*.json ./
|
||||
RUN npm install
|
||||
|
||||
# Bundle app source
|
||||
COPY . .
|
||||
# COPY . .
|
||||
|
||||
# Make port 3000 available to the world outside this container
|
||||
EXPOSE 3000
|
||||
|
@ -12,6 +12,7 @@ import Docs from './pages/Docs'; // Импортируем страницу п
|
||||
import './css/bootstrap-5.3.3-dist/css/bootstrap.min.css';
|
||||
import './App.css';
|
||||
import "bootstrap-icons/font/bootstrap-icons.css";
|
||||
import {removeCustomCookie} from './Services/Local'
|
||||
import { BrowserRouter as Router, Routes, Route, Navigate } from 'react-router-dom';
|
||||
|
||||
const App = () => {
|
||||
@ -20,6 +21,7 @@ const App = () => {
|
||||
|
||||
// Функция для выхода из системы
|
||||
const handleLogout = () => {
|
||||
removeCustomCookie("userToken")
|
||||
setIsLoggedIn(false);
|
||||
};
|
||||
|
||||
|
@ -88,8 +88,9 @@ const useWebsocketConnection = (userToken, roomHash) => {
|
||||
};
|
||||
|
||||
// Функция для отправки данных в WebSocket
|
||||
const sendMessage = (message) => {
|
||||
const sendMessage = async (message) => {
|
||||
if (socketRef.current && socketRef.current.readyState === WebSocket.OPEN) {
|
||||
console.log(JSON.stringify(message))
|
||||
socketRef.current.send(JSON.stringify(message));
|
||||
} else {
|
||||
console.error('WebSocket is not open. Unable to send message:', message);
|
||||
@ -99,4 +100,42 @@ const useWebsocketConnection = (userToken, roomHash) => {
|
||||
return { websocketStruct, sendMessage };
|
||||
};
|
||||
|
||||
export const spawnJsonSignal = (signal, name, coords) => {
|
||||
if (![1, 2].includes(signal)) {
|
||||
throw new Error('Invalid signal value. Expected 1 or 2.');
|
||||
}
|
||||
|
||||
if (typeof name !== 'string' || !name.trim()) {
|
||||
throw new Error('Invalid name. Expected a non-empty string.');
|
||||
}
|
||||
|
||||
return {
|
||||
signal,
|
||||
data: {
|
||||
name,
|
||||
params: {
|
||||
coords,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const DeleteSignal = (name) => {
|
||||
const signal = 3;
|
||||
|
||||
if (typeof name !== 'string' || !name.trim()) {
|
||||
throw new Error('Invalid name. Expected a non-empty string.');
|
||||
}
|
||||
|
||||
return {
|
||||
signal,
|
||||
data: {
|
||||
name,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
export default useWebsocketConnection;
|
@ -1,6 +1,6 @@
|
||||
.user-account {
|
||||
padding: 20px;
|
||||
background-color: #f4f4f4;
|
||||
background-color: #3cafb7;
|
||||
border-radius: 10px;
|
||||
max-width: 400px;
|
||||
margin: 0 auto;
|
||||
|
@ -6,25 +6,24 @@ import BaseStation from './model/BaseStation';
|
||||
import HeightPoint from './model/HeightPoint';
|
||||
import { RandomHeightPoint } from './helpers/generateRandomHeightPoints'
|
||||
import ModalWindow from './components/Modal/Modal';
|
||||
import useWebsocketConnection from '../Services/WebsocketHook';
|
||||
import { getCustomCookie } from '../Services/Local';
|
||||
import useWebsocketConnection, { DeleteSignal, spawnJsonSignal } from '../Services/WebsocketHook';
|
||||
import './Dashboard.css';
|
||||
|
||||
|
||||
const Dashboard = () => {
|
||||
const mountRef = useRef(null); // Указатель монтирования
|
||||
const sceneRef = useRef(null); // Указатель на сцену
|
||||
const mouse = new THREE.Vector2(); // Мышка
|
||||
const {websocketStruct, sendMessage} = useWebsocketConnection(1, 1);
|
||||
|
||||
const [heightData, setHeightData] = useState(RandomHeightPoint()); // Высоты
|
||||
const [formData, setFormData] = useState({ x: '', y: '', height: '' }); // Форма для ввода данных карты
|
||||
const [mouseState, setMouseState] = useState({ x: 0, y: 0, z: 0 }); // Форма для ввода данных карты
|
||||
const [drones, setDrones] = useState([]) // Все дроны
|
||||
const [selectedDrone, setSelectedDrone] = useState(null); // Состояние для выбранного дрона
|
||||
const [baseStation, setBaseStation] = useState([]) // Все базовые станции
|
||||
const [selectedBaseStation, setSelectedBaseStation] = useState(null); // Состояние для выбранной базовой станции
|
||||
const [mapSettings, setMapSettings] = useState({maxHeight: 20, coordX: 0, coordY: 0, }); // Настройки карты
|
||||
const [contextMenu, setContextMenu] = useState({ visible: false, x: 0, y: 0 }); // контекстное меню сцены
|
||||
const mountRef = useRef(null); // Указатель монтирования
|
||||
const sceneRef = useRef(null); // Указатель на сцену
|
||||
const {websocketStruct, sendMessage} = useWebsocketConnection(getCustomCookie("userToken"), 1);
|
||||
const [heightData, setHeightData] = useState(RandomHeightPoint()); // Высоты
|
||||
const [formData, setFormData] = useState({ x: '', y: '', height: '' }); // Форма для ввода данных карты
|
||||
const [mouseState, setMouseState] = useState({ x: 0, y: 0, z: 0 }); // Форма для ввода данных карты
|
||||
const [drones, setDrones] = useState([]) // Все дроны
|
||||
const [selectedDrone, setSelectedDrone] = useState(null); // Состояние для выбранного дрона
|
||||
const [baseStation, setBaseStation] = useState([]) // Все базовые станции
|
||||
const [selectedBaseStation, setSelectedBaseStation] = useState(null); // Состояние для выбранной базовой станции
|
||||
const [mapSettings, setMapSettings] = useState({maxHeight: 20, coordX: 0, coordY: 0, }); // Настройки карты
|
||||
const [contextMenu, setContextMenu] = useState({ visible: false, x: 0, y: 0 }); // контекстное меню сцены
|
||||
|
||||
const [objectType, setObjectType] = useState(1); // 1 = Drone, 2 = Base Station
|
||||
const [formObjectData, setFormObjectData] = useState({
|
||||
@ -38,6 +37,45 @@ const Dashboard = () => {
|
||||
baseStationField1: "",
|
||||
baseStationField2: ""
|
||||
});
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const handleSearch = () => {
|
||||
const foundDrone = drones.find(drone => drone.name.toLowerCase() === searchTerm.toLowerCase());
|
||||
const foundBaseStation = baseStation.find(base => base.name.toLowerCase() === searchTerm.toLowerCase());
|
||||
|
||||
if (foundDrone) {
|
||||
// Выделяем найденный дрон
|
||||
if (selectedDrone) {
|
||||
selectedDrone.getObject().traverse((child) => {
|
||||
if (child.isMesh) {
|
||||
child.material.color.set(0xff0000);
|
||||
}
|
||||
});
|
||||
}
|
||||
foundDrone.getObject().traverse((child) => {
|
||||
if (child.isMesh) {
|
||||
child.material.color.set(0x00ff00);
|
||||
}
|
||||
});
|
||||
setSelectedDrone(foundDrone);
|
||||
} else if (foundBaseStation) {
|
||||
// Выделяем найденную базу
|
||||
if (selectedBaseStation) {
|
||||
selectedBaseStation.getObject().traverse((child) => {
|
||||
if (child.isMesh) {
|
||||
child.material.color.set(0x0000ff);
|
||||
}
|
||||
});
|
||||
}
|
||||
foundBaseStation.getObject().traverse((child) => {
|
||||
if (child.isMesh) {
|
||||
child.material.color.set(0x00ff00);
|
||||
}
|
||||
});
|
||||
setSelectedBaseStation(foundBaseStation);
|
||||
} else {
|
||||
alert("Объект с указанным именем не найден");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const handleTypeChange = (type) => {
|
||||
@ -45,14 +83,8 @@ const Dashboard = () => {
|
||||
setFormData({ ...formData, type });
|
||||
};
|
||||
|
||||
const handleSendMessage = () => {
|
||||
const message = {
|
||||
signal: 0,
|
||||
data: {
|
||||
key: 'value'
|
||||
}
|
||||
};
|
||||
sendMessage(message);
|
||||
const handleDeleteSignal = (name) => {
|
||||
sendMessage(DeleteSignal(name));
|
||||
};
|
||||
|
||||
|
||||
@ -82,11 +114,40 @@ const Dashboard = () => {
|
||||
isModalSearchOpen: false,
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (websocketStruct) {
|
||||
console.log('Received WebSocket Data:', websocketStruct);
|
||||
if (websocketStruct && websocketStruct.modulation) {
|
||||
const modulation = websocketStruct.modulation;
|
||||
// Парсинг карты
|
||||
const map = modulation.map;
|
||||
setMapSettings({
|
||||
name: map.name,
|
||||
minBound: map.map.MinBound,
|
||||
maxBound: map.map.MaxBound,
|
||||
heightData: map.map.HeightData,
|
||||
maxHeight: 20,
|
||||
});
|
||||
setHeightData(map.map.HeightData.flatMap((row, x) => row.map((height, y) => new HeightPoint(x, y, height))));
|
||||
|
||||
// Парсинг объектов
|
||||
const parsedDrones = [];
|
||||
const parsedBaseStations = [];
|
||||
modulation.objects.forEach((obj) => {
|
||||
if (obj.type === 1) {
|
||||
const drone = new Drone(obj.name);
|
||||
drone.setPosition(...obj.coords);
|
||||
parsedDrones.push(drone);
|
||||
} else if (obj.type === 2) {
|
||||
const base = new BaseStation(obj.name);
|
||||
base.setPosition(...obj.coords);
|
||||
parsedBaseStations.push(base);
|
||||
}
|
||||
});
|
||||
setDrones(parsedDrones);
|
||||
setBaseStation(parsedBaseStations);
|
||||
}
|
||||
}, [websocketStruct]);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
if (!mountRef.current) return;
|
||||
@ -94,7 +155,7 @@ const Dashboard = () => {
|
||||
let height = mountRef.current.clientHeight;
|
||||
// Создаем объект сцены
|
||||
const scene = new THREE.Scene();
|
||||
|
||||
scene.background = new THREE.Color(0xffffff);
|
||||
// Сохраняем ссылку на сцену
|
||||
sceneRef.current = scene;
|
||||
// Создаем камеру
|
||||
@ -140,7 +201,7 @@ const Dashboard = () => {
|
||||
mesh.rotation.x = -Math.PI / 2;
|
||||
scene.add(mesh);
|
||||
|
||||
const axesHelper = new THREE.AxesHelper(10);
|
||||
const axesHelper = new THREE.AxesHelper(100);
|
||||
scene.add(axesHelper);
|
||||
|
||||
const controls = new OrbitControls(camera, renderer.domElement);
|
||||
@ -149,35 +210,69 @@ const Dashboard = () => {
|
||||
const light = new THREE.DirectionalLight(0xffffff, 1);
|
||||
light.position.set(0, 50, 50).normalize();
|
||||
scene.add(light);
|
||||
// Обработка кликов на сцене
|
||||
const handleClick = (event) => {
|
||||
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
|
||||
mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
|
||||
console.log('Mouse coordinates:', mouse);
|
||||
const raycaster = new THREE.Raycaster();
|
||||
raycaster.setFromCamera(mouse, camera);
|
||||
// Обработка кликов на сцене
|
||||
const handleClick = (event) => {
|
||||
// Рассчитываем координаты мыши в нормализованной системе координат и округляем до целого числа
|
||||
const mouse = new THREE.Vector2();
|
||||
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
|
||||
mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
|
||||
console.log('Mouse coordinates:', mouse);
|
||||
|
||||
const intersects = raycaster.intersectObjects(drones.map(drone => drone.getObject()), true);
|
||||
console.log('Intersections:', intersects)
|
||||
console.log('Drones:', drones.map(drone => [drone.getObject(), drone.getObject().position, drone.name]))
|
||||
if (intersects.length > 0) {
|
||||
const selected = intersects[0].object;
|
||||
console.log('Clicked on:', selected); // Лог для проверки объекта
|
||||
const drone = drones.find(drone => drone.getObject().children[0] === selected);
|
||||
if (drone) {
|
||||
if (selectedDrone) {
|
||||
selectedDrone.getObject().children[0].material.color.set(0xff0000);
|
||||
}
|
||||
drone.getObject().children[0].material.color.set(0xff1111);
|
||||
setSelectedDrone(drone);
|
||||
}
|
||||
} else {
|
||||
if (selectedDrone) {
|
||||
selectedDrone.getObject().children[0].material.color.set(0xff0000);
|
||||
setSelectedDrone(null);
|
||||
}
|
||||
// Создаем объект Raycaster для проверки пересечений
|
||||
const raycaster = new THREE.Raycaster();
|
||||
const rayHelper = new THREE.ArrowHelper(raycaster.ray.direction, raycaster.ray.origin, 100, 0xff4444);
|
||||
scene.add(rayHelper);
|
||||
raycaster.setFromCamera(mouse, camera);
|
||||
|
||||
// Проверяем пересечения с объектами дронов
|
||||
const intersects = raycaster.intersectObjects(drones.map(drone => drone.getObject()), true);
|
||||
console.log('Intersections:', intersects);
|
||||
console.log('Drones:', drones.map(drone => [drone.getObject(), drone.getObject().position, drone.name]));
|
||||
|
||||
if (intersects.length > 0) {
|
||||
const selected = intersects[0].object;
|
||||
console.log('Clicked on:', selected); // Лог для проверки объекта
|
||||
|
||||
// Поиск дрона рекурсивно
|
||||
const drone = drones.find(drone => containsObjectRecursively(drone.getObject(), selected));
|
||||
|
||||
if (drone) {
|
||||
// Сбрасываем цвет предыдущего выбранного дрона
|
||||
if (selectedDrone) {
|
||||
drone.getObject().visible = true;
|
||||
// selectedDrone.getObject().material.color.set(0xff0000);
|
||||
}
|
||||
};
|
||||
// Устанавливаем цвет выбранного дрона
|
||||
// drone.getObject().material.color.set(0xff1111);
|
||||
drone.getObject().visible = false;
|
||||
console.log(drone);
|
||||
setSelectedDrone(drone);
|
||||
}
|
||||
} else {
|
||||
// Сбрасываем выбор, если ни один дрон не был выбран
|
||||
if (selectedDrone) {
|
||||
// selectedDrone.getObject().material.color.set(0xff0000);
|
||||
selectedDrone .getObject().visible = true;
|
||||
|
||||
setSelectedDrone(null);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Рекурсивная функция для поиска объекта среди детей
|
||||
const containsObjectRecursively = (parent, target) => {
|
||||
if (parent === target) {
|
||||
return true;
|
||||
}
|
||||
for (let child of parent.children) {
|
||||
if (containsObjectRecursively(child, target)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
|
||||
const handleMouseMove = (event) => {
|
||||
let x = event.x;
|
||||
@ -226,21 +321,36 @@ const Dashboard = () => {
|
||||
// Создаем новый материал для каждого дрона
|
||||
drone.setPosition(Math.random() * 20 - 10, 20, Math.random() * 20 - 10);
|
||||
setDrones((prevDrones) => [...prevDrones, drone]);
|
||||
console.log(drones.map(drone => drone.getObject().children[0]));
|
||||
console.log(drones.map(drone => drone.getObject()));
|
||||
let json_signal = spawnJsonSignal(1, current / 1000 + "", "" + Math.round(drone.getObject().position.x) + "," + Math.round(drone.getObject().position.y) + "," + Math.round(drone.getObject().position.z) + "");
|
||||
sendMessage(json_signal)
|
||||
sceneRef.current.add(drone.getObject());
|
||||
}
|
||||
};
|
||||
// Добавление дрона в сцену
|
||||
const handleAddBaseStation = () => {
|
||||
if (sceneRef.current) {
|
||||
const current = Date.now();
|
||||
const base = new BaseStation(current / 1000);
|
||||
base.setPosition(Math.random() * 20 - 10, 20, Math.random() * 20 - 10);
|
||||
setBaseStation((prev) => [...prev, base]);
|
||||
console.log(baseStation.map(b => b.getObject().children[0]));
|
||||
sceneRef.current.add(base.getObject());
|
||||
}
|
||||
};
|
||||
// Добавление базовой станции в сцену
|
||||
const handleAddBaseStation = () => {
|
||||
if (sceneRef.current) {
|
||||
const current = Date.now();
|
||||
const base = new BaseStation(current / 1000);
|
||||
|
||||
// Выбираем случайные координаты X и Z
|
||||
const x = Math.random() * 20 - 10;
|
||||
const z = Math.random() * 20 - 10;
|
||||
|
||||
// Находим точку высоты для установки базовой станции на карту
|
||||
const heightPoint = heightData.find(point => point.x === Math.round(x) && point.y === Math.round(z));
|
||||
console.log(heightPoint)
|
||||
const y = heightPoint ? heightPoint.height : 0;
|
||||
|
||||
// Устанавливаем позицию базовой станции на основании высоты карты
|
||||
base.setPosition(x, y, z);
|
||||
|
||||
setBaseStation((prev) => [...prev, base]);
|
||||
console.log(baseStation.map(b => b.getObject().children[0]));
|
||||
sceneRef.current.add(base.getObject());
|
||||
}
|
||||
};
|
||||
|
||||
// Обработчик ввода на форму высот
|
||||
const handleInputChange = (event) => {
|
||||
@ -449,15 +559,20 @@ const Dashboard = () => {
|
||||
|
||||
<ModalWindow isOpen={modals.isModalSearchOpen} onClose={closeAllModals}>
|
||||
<h2>Поиск</h2>
|
||||
<input type="text" placeholder="Введите имя" />
|
||||
<button onClick={() => alert('Добавлено')}>Выбор</button>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Введите имя"
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
/>
|
||||
<button onClick={handleSearch}>Найти</button>
|
||||
</ModalWindow>
|
||||
|
||||
<ModalWindow isOpen={modals.isModalDeleteOpen} onClose={closeAllModals}>
|
||||
<h2>Удаление</h2>
|
||||
<h2>Вы точно хотите удалить объект X?</h2>
|
||||
<button onClick={closeAllModals}>Отмена</button>
|
||||
<button onClick={() => handleSendMessage() }>Удалить</button>
|
||||
<button onClick={() => handleDeleteSignal(1) }>Удалить</button>
|
||||
</ModalWindow>
|
||||
|
||||
<ModalWindow isOpen={modals.isModalOpen} onClose={closeAllModals}>
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { setCustomCookie, getCustomCookie } from '../Services/Local'
|
||||
import { giveMeServerAddress } from '../Services/Server'
|
||||
|
||||
import '../Login.scss';
|
||||
|
||||
@ -13,16 +14,37 @@ const Login = ({ onLogin }) => {
|
||||
onLogin();
|
||||
}
|
||||
}, [])
|
||||
const handleSubmit = (e) => {
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
// Simple login/password check
|
||||
if (username === 'admin' && password === 'admin') {
|
||||
// TODO :: CHANGE
|
||||
setCustomCookie('userToken', '12345', { expires: 7 }); // Куки с истечением через 7 дней
|
||||
onLogin(); // Call function on successful login
|
||||
|
||||
} else {
|
||||
setError('Неверный логин или пароль');
|
||||
|
||||
try {
|
||||
// Отправляем запрос на сервер
|
||||
const response = await fetch(giveMeServerAddress() + "/auth/"+ username +"/" + password, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ username, password })
|
||||
});
|
||||
|
||||
// Проверяем статус ответа
|
||||
if (!response.ok) {
|
||||
// Если статус не 200, ничего не делаем
|
||||
setError('Ошибка авторизации. Пожалуйста, попробуйте снова.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Парсим тело ответа в формате JSON
|
||||
const data = await response.json();
|
||||
|
||||
// Устанавливаем userToken из тела ответа
|
||||
setCustomCookie('userToken', data.userid, { expires: 7 });
|
||||
|
||||
// Вызываем функцию после успешного входа в систему
|
||||
onLogin();
|
||||
} catch (error) {
|
||||
// Обработка ошибок сети
|
||||
setError('Произошла ошибка. Пожалуйста, попробуйте снова позже.');
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -8,7 +8,6 @@ const Main = () => {
|
||||
|
||||
useEffect(() => {
|
||||
getSimulations();
|
||||
setCustomCookie('userToken', '12345', { expires: 7 }); // Куки с истечением через 7 дней
|
||||
|
||||
}, []);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { useState } from 'react';
|
||||
import '../UserAccount.scss';
|
||||
|
||||
import {getCustomCookie} from '../Services/Local';
|
||||
const UserAccount = () => {
|
||||
const [userData, setUserData] = useState({
|
||||
username: 'Никита Николаевич',
|
||||
@ -10,6 +10,15 @@ const UserAccount = () => {
|
||||
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
const [formData, setFormData] = useState(userData);
|
||||
const [debug, setDebug] = useState(false)
|
||||
|
||||
const enableDebug = () => {
|
||||
if (debug){
|
||||
setDebug(false)
|
||||
} else {
|
||||
setDebug(true)
|
||||
}
|
||||
};
|
||||
|
||||
const handleChange = (e) => {
|
||||
const { name, value } = e.target;
|
||||
@ -77,6 +86,18 @@ const UserAccount = () => {
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<button className="btn btn-info" onClick={() => enableDebug()}>
|
||||
Turn Debug Mode
|
||||
</button>
|
||||
|
||||
{debug ? <p>
|
||||
debug:
|
||||
UserToken: {getCustomCookie("userToken")}
|
||||
</p>
|
||||
:
|
||||
<p></p>
|
||||
}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -15,6 +15,12 @@ class Drone {
|
||||
}, undefined, (error) => {
|
||||
console.error("Ошибка загрузки GLTF:", error);
|
||||
});
|
||||
// Создаем красный куб вместо GLB модели
|
||||
// const geometry = new THREE.BoxGeometry(2, 2, 2);
|
||||
// const material = new THREE.MeshBasicMaterial({ color: 0xff0000 });
|
||||
// const cube = new THREE.Mesh(geometry, material);
|
||||
// cube.scale.set(scale, scale, scale);
|
||||
// this.object.add(cube);
|
||||
}
|
||||
|
||||
setPosition(x, y, z) {
|
||||
|
@ -86,6 +86,7 @@ func main() {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
database.Instance = database.NewDbConnection()
|
||||
err = server.SpawnServer()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@ -1,6 +1,7 @@
|
||||
package websocket
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"moxitech/dns/package/math/simulator"
|
||||
"moxitech/dns/package/utils/randomizer"
|
||||
"time"
|
||||
@ -37,8 +38,15 @@ func (o *Modulation) DeleteObjectIfExists(name string) {
|
||||
}
|
||||
}
|
||||
}
|
||||
func (o *Modulation) MirrorPayloadToSimulationStruct() {
|
||||
|
||||
// MirrorPayloadToSimulationStruct - вернет фулл копию симуляции
|
||||
func (o *Modulation) MirrorPayloadToSimulationStruct() Modulation {
|
||||
shadow_sim_copy := Modulation{
|
||||
Map: o.Map,
|
||||
Objects: o.Objects,
|
||||
Ts_update: o.Ts_update,
|
||||
}
|
||||
return shadow_sim_copy
|
||||
}
|
||||
|
||||
func (o *Modulation) RunSimulator() {
|
||||
@ -59,22 +67,24 @@ func (o *Modulation) RunSimulator() {
|
||||
// HeightData: heightData,
|
||||
// }
|
||||
//
|
||||
// ? mapObj := o.Map
|
||||
|
||||
// // Определяем дронов
|
||||
//
|
||||
// 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",
|
||||
// },
|
||||
// },
|
||||
// }
|
||||
// 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",
|
||||
// },
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// // Определяем базовые станции
|
||||
//
|
||||
@ -128,6 +138,7 @@ func (o *Modulation) AddObject(name string, obj_type int, coords [3]int, params
|
||||
// Значит объект не станция или не дрон
|
||||
return
|
||||
}
|
||||
fmt.Println(name, obj_type, coords, params)
|
||||
if o.Objects == nil {
|
||||
o.Objects = make([]*SystemObject, 0)
|
||||
}
|
||||
|
@ -18,12 +18,12 @@ type MongoDbInstance struct {
|
||||
Db *mongo.Database
|
||||
}
|
||||
|
||||
var instance *MongoDbInstance
|
||||
var Instance *MongoDbInstance
|
||||
var once sync.Once
|
||||
|
||||
// giveMeMongoConnectionString возвращает строку подключения к MongoDB
|
||||
func giveMeMongoConnectionString() string {
|
||||
return "mongodb://moxitech:moxitech@localhost:27017/" // Замените строку на свою строку подключения
|
||||
return "mongodb://moxitech:moxitech@mongo:27017/" // Замените строку на свою строку подключения
|
||||
}
|
||||
|
||||
// NewDbConnection создает подключение к базе данных MongoDB и возвращает единственный экземпляр MongoDbInstance
|
||||
@ -49,13 +49,13 @@ func NewDbConnection() *MongoDbInstance {
|
||||
|
||||
log.Println("Успешное подключение к MongoDB")
|
||||
|
||||
instance = &MongoDbInstance{
|
||||
Instance = &MongoDbInstance{
|
||||
Client: client,
|
||||
Db: client.Database(os.Getenv("MONGO_INITDB_DATABASE")),
|
||||
}
|
||||
})
|
||||
|
||||
return instance
|
||||
return Instance
|
||||
}
|
||||
|
||||
// InsertIntoSimulations вставляет данные в коллекцию "simulations"
|
||||
|
@ -5,24 +5,42 @@ import (
|
||||
"moxitech/dns/internal/database"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// GET localhost:8080/auth/username?/password?
|
||||
// POST localhost:8080/auth/username?/password?
|
||||
func AuthUser(c *fiber.Ctx) error {
|
||||
username := c.Params("username")
|
||||
password := c.Params("password")
|
||||
if username == "" || password == "" {
|
||||
return c.Status(501).SendString("username and password has required!")
|
||||
return c.Status(403).JSON(fiber.Map{
|
||||
"error": "username and password are required!",
|
||||
})
|
||||
}
|
||||
|
||||
user, err := database.DbDriver.GetUserByName(username)
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return c.Status(404).JSON(fiber.Map{
|
||||
"error": "User not found",
|
||||
})
|
||||
}
|
||||
if err != nil {
|
||||
return c.Status(501).SendString(err.Error())
|
||||
return c.Status(501).JSON(fiber.Map{
|
||||
"error": err.Error(),
|
||||
})
|
||||
}
|
||||
if user == nil {
|
||||
return c.Status(403).SendString(fmt.Sprintf("User with username: %v not found", username))
|
||||
return c.Status(403).JSON(fiber.Map{
|
||||
"error": fmt.Sprintf("User with username: %v not found", username),
|
||||
})
|
||||
}
|
||||
if user.Password != password {
|
||||
return c.Status(403).SendString("Bad password!")
|
||||
return c.Status(403).JSON(fiber.Map{
|
||||
"error": "Bad password!",
|
||||
})
|
||||
}
|
||||
return c.Status(200).SendString(fmt.Sprintf("Welcome to Drone Network Simulator server-side API! \n UserId: %v ", user.ID))
|
||||
|
||||
return c.Status(200).JSON(fiber.Map{
|
||||
"userid": user.ID,
|
||||
})
|
||||
}
|
||||
|
@ -111,6 +111,7 @@ func (room *WebsocketRoom) InsertObject(message websocket.SignalMessage) error {
|
||||
return fmt.Errorf("[insert] error parsing data: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println("st 1")
|
||||
// Получаем значения name и params
|
||||
name := parsedData.Name
|
||||
params := parsedData.Params
|
||||
@ -119,25 +120,31 @@ func (room *WebsocketRoom) InsertObject(message websocket.SignalMessage) error {
|
||||
if params["coords"] == "" {
|
||||
return fmt.Errorf("[insert] coords is empty")
|
||||
}
|
||||
fmt.Println("st 2")
|
||||
|
||||
// Разделяем строку координат на отдельные элементы
|
||||
coordinateStrings := strings.Split(params["coords"], ",")
|
||||
|
||||
// Инициализируем массив для хранения координат
|
||||
coordinates := make([]int, len(coordinateStrings))
|
||||
fmt.Println("st 3")
|
||||
|
||||
// Преобразуем каждую координату в целое число
|
||||
for i, coord := range coordinateStrings {
|
||||
parsedCoord, err := strconv.Atoi(strings.TrimSpace(coord))
|
||||
if err != nil {
|
||||
fmt.Println(fmt.Errorf("[insert] invalid coordinate: %s", coord))
|
||||
return fmt.Errorf("[insert] invalid coordinate: %s", coord)
|
||||
}
|
||||
coordinates[i] = parsedCoord
|
||||
}
|
||||
fmt.Println("st 4")
|
||||
|
||||
params["coords"] = ""
|
||||
// Добавляем объект в комнату
|
||||
roomsMutex.Lock()
|
||||
defer roomsMutex.Unlock()
|
||||
fmt.Println("st 5")
|
||||
room.Modulation.AddObject(name, type_obj, [3]int{coordinates[0], coordinates[1], coordinates[2]}, params)
|
||||
|
||||
return nil
|
||||
@ -199,6 +206,13 @@ func (room *WebsocketRoom) InsertExampleData() {
|
||||
room.Modulation.SpawnExampleData()
|
||||
}
|
||||
|
||||
// InsertBasicData вставляет базовые случайные данные в симуляцию
|
||||
func (room *WebsocketRoom) StoreMongo() {
|
||||
roomsMutex.Lock()
|
||||
defer roomsMutex.Unlock()
|
||||
room.Modulation.MirrorPayloadToSimulationStruct()
|
||||
}
|
||||
|
||||
// InsertMapFromJson вставляет высоты и прочие данные карты в симуляцию, по шаблону
|
||||
func (room *WebsocketRoom) InsertMapFromJson(template string) {
|
||||
// TODO
|
||||
@ -273,6 +287,8 @@ func (room *WebsocketRoom) WebsocketAction(message []byte) (error, bool) {
|
||||
case 33:
|
||||
// SYNC SIGNAL
|
||||
case 100:
|
||||
case 101:
|
||||
// room.StoreMongo(Signal)
|
||||
|
||||
case 301:
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user