diff --git a/README.md b/README.md index d58b7a1..9748f01 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,7 @@ ## Запуск приложения -**Запуск для локальной разработки**: `poetry run uvicorn web_robot_control.main:app --host server_ip - --port port_number` +**Запуск для локальной разработки**: `poetry run start_app` **Todo:** создать Python-функцию для запуска веб-приложения и добавить её в скрипты Poetry diff --git a/pyproject.toml b/pyproject.toml index cc74d7c..c47cfe2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,3 +19,6 @@ packages = [{include = "web_robot_control", from = "src"}] [build-system] requires = ["poetry-core>=2.0.0,<3.0.0"] build-backend = "poetry.core.masonry.api" + +[tool.poetry.scripts] +start_app = "web_robot_control.start:start_app" \ No newline at end of file diff --git a/src/web_robot_control/start.py b/src/web_robot_control/start.py new file mode 100644 index 0000000..20a44a2 --- /dev/null +++ b/src/web_robot_control/start.py @@ -0,0 +1,12 @@ +import uvicorn + + +def start_app(): + """Функция запуска приложения""" + + uvicorn.run( + 'web_robot_control.main:app', + host='127.0.0.1', + port=8000, + reload=True + ) diff --git a/src/web_robot_control/views.py b/src/web_robot_control/views.py index e6023d1..8aeb472 100644 --- a/src/web_robot_control/views.py +++ b/src/web_robot_control/views.py @@ -5,6 +5,7 @@ from fastapi.templating import Jinja2Templates from websockets import exceptions, connect import asyncio import socket +from json import loads, JSONDecodeError from web_robot_control.settings import settings @@ -59,25 +60,37 @@ async def command_to_robot(command: str) -> str: @router.websocket('/ws') async def websocket_endpoint(websocket: WebSocket) -> None: + """Эндпоинт для обработки команд фронтенда""" + # Установка содединения по веб-сокету await websocket.accept() try: + previous_command = None + while True: # Получение команды от клиента (с веб-сокета) command = await websocket.receive_text() - valid_commands = settings.commands_robot.get_list_commands() + + if previous_command != command: + previous_command = command + valid_commands = settings.commands_robot.get_list_commands() + data = loads(command) + name_command = next(iter(data), None) - if command in valid_commands: - # оптравка команды роботу - robot_answer = await command_to_robot(command=command) - - if robot_answer: - # отправка ответа робота на вебсокет фронтенда - await websocket.send_text(f'Получена команда: {command}, ответ робота: {robot_answer}') - print(f'Ответ робота: {robot_answer}') + if name_command in valid_commands: + print(command) + # оптравка команды роботу + robot_answer = await command_to_robot(command=command) + + if robot_answer: + # отправка ответа робота на вебсокет фронтенда + await websocket.send_text(f'Получена команда: {command}, ответ робота: {robot_answer}') + print(f'Ответ робота: {robot_answer}') except WebSocketDisconnect: print('WebSocket отключен') # Todo: для вывода ошибок будет настроен logger # Todo: для каждой ошибки написать своё сообщение except (WebSocketException, exceptions.InvalidMessage) as err: print(f'{err.__class__.__name__}: {err}') + except JSONDecodeError: + print('Ошибка при декодировании JSON') diff --git a/static/command.js b/static/command.js index 1328232..1f04e29 100644 --- a/static/command.js +++ b/static/command.js @@ -39,12 +39,12 @@ document.addEventListener("DOMContentLoaded", () => { // Функция для начала отправки команды с заданным интервалом function startSendingCommand(command) { // Отправляем команду сразу - sendCommand(command); + sendCommand(JSON.stringify(command)); // Запускаем интервал для повторной отправки команды commandInterval = setInterval(() => { - sendCommand(command); // Повторяем отправку команды - }, 10); // Интервал отправки — каждые 10 мс + sendCommand(JSON.stringify(command)); // Повторяем отправку команды + }, 10); // Интервал отправки — каждые 100 мс } // Функция для остановки отправки команд @@ -65,8 +65,13 @@ document.addEventListener("DOMContentLoaded", () => { // Назначение обработчиков событий для кнопки "Вперёд" const forwardButton = document.getElementById("forward-button"); - forwardButton.addEventListener("mousedown", () => startSendingCommand("forward")); // Начало отправки команды - forwardButton.addEventListener("mouseup", stopSendingCommand); // Остановка отправки при отпускании кнопки + const forwardOn = {"forward": true} + forwardButton.addEventListener("mousedown", () => startSendingCommand(forwardOn)); // Начало отправки команды + const forwardOff = {"forward": false} + forwardButton.addEventListener("mouseup", () => { + sendCommand(JSON.stringify(forwardOff)); + stopSendingCommand(); + }); // отправка команды forwardOff и остановка отправки при отпускании кнопки forwardButton.addEventListener("mouseleave", stopSendingCommand); // Остановка отправки, если курсор уходит с кнопки // Назначение обработчиков событий для кнопки "Влево"