Arduinum/service orange pi mvp 1 #1
3
.gitignore
vendored
3
.gitignore
vendored
@@ -172,3 +172,6 @@ cython_debug/
|
||||
|
||||
# PyPI configuration file
|
||||
.pypirc
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
3
Makefile
Normal file
3
Makefile
Normal file
@@ -0,0 +1,3 @@
|
||||
run:
|
||||
chmod +x robot_pi_service/robot_pi_service.py
|
||||
python3 robot_pi_service/robot_pi_service.py
|
||||
32
README.md
32
README.md
@@ -1 +1,31 @@
|
||||
# robot-pi-service
|
||||
# Robot-pi-service
|
||||
|
||||
**Robot-pi-service** - сервис для управления роботом на orange pi, работающий на linux Armbian.
|
||||
|
||||
**Запуск сервиса (как проекта python3)** - `make run`
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
<strong>
|
||||
Как оформлять ветки и коммиты
|
||||
</strong>
|
||||
</summary>
|
||||
|
||||
Пример ветки `user_name/name_task`
|
||||
|
||||
- **user_name** (имя пользователя);
|
||||
- **name_task** (название задачи).
|
||||
|
||||
Пример коммита `refactor: renaming a variable`
|
||||
|
||||
- **feat:** (новая функционал кода, БЕЗ учёта функционала для сборок);
|
||||
- **devops:** (функционал для сборки, - добавление, удаление и исправление);
|
||||
- **fix:** (исправление ошибок функционального кода);
|
||||
- **docs:** (изменения в документации);
|
||||
- **style:** (форматирование, отсутствующие точки с запятой и т.п., без изменения производственного кода);
|
||||
- **refactor:** (рефакторинг производственного кода, например, переименование переменной);
|
||||
- **test:** (добавление недостающих тестов, рефакторинг тестов; без изменения производственного кода);
|
||||
- **chore:** (обновление рутинных задач и т. д.; без изменения производственного кода).
|
||||
|
||||
Оформление основано на https://www.conventionalcommits.org/en/v1.0.0/
|
||||
</details>
|
||||
2
requirements.txt
Normal file
2
requirements.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
websockets==15.0.1
|
||||
pydantic-settings==2.9.1
|
||||
0
robot_pi_service/__init__.py
Normal file
0
robot_pi_service/__init__.py
Normal file
68
robot_pi_service/robot_pi_service.py
Executable file
68
robot_pi_service/robot_pi_service.py
Executable file
@@ -0,0 +1,68 @@
|
||||
import asyncio
|
||||
from websockets import serve, exceptions
|
||||
from websockets.legacy.server import WebSocketServerProtocol
|
||||
|
||||
from settings import settings
|
||||
|
||||
|
||||
async def robot_control_gpio(websocket: WebSocketServerProtocol):
|
||||
"""
|
||||
Асинхронная функция для управлением gpio робота (через websocket)
|
||||
"""
|
||||
|
||||
try:
|
||||
while True:
|
||||
try:
|
||||
command = await asyncio.wait_for(websocket.recv(), timeout=30.0)
|
||||
except asyncio.TimeoutError as err:
|
||||
print('Таймаут ожидания команды от клиента')
|
||||
continue # продолжение цикла, чтобы не закрывать соединение
|
||||
|
||||
match command:
|
||||
case settings.commands_robot.forward:
|
||||
action = 'Робот едет вперёд'
|
||||
print(action)
|
||||
await websocket.send(message=action)
|
||||
case settings.commands_robot.backward:
|
||||
action = 'Робот едет назад'
|
||||
print(action)
|
||||
await websocket.send(message=action)
|
||||
case settings.commands_robot.left:
|
||||
action = 'Робот едет налево'
|
||||
print(action)
|
||||
await websocket.send(message=action)
|
||||
case settings.commands_robot.right:
|
||||
action = 'Робот едет направо'
|
||||
print(action)
|
||||
await websocket.send(message=action)
|
||||
except exceptions.ConnectionClosed:
|
||||
pass
|
||||
except (exceptions.ConnectionClosedOK, exceptions.InvalidMessage, exceptions.InvalidState) as err:
|
||||
message_err = f'{err.__class__.__name__}: {err}'
|
||||
print(message_err)
|
||||
await websocket.send(message=message_err)
|
||||
except Exception as err:
|
||||
message_err = f'{err.__class__.__name__}: {err}'
|
||||
print(message_err)
|
||||
await websocket.send(message=message_err)
|
||||
|
||||
|
||||
async def start():
|
||||
"""Асинхронная функция запуска вебсокета и бесконечного цикла"""
|
||||
|
||||
async with serve(handler=robot_control_gpio, host=settings.websocket_host, port=settings.websocket_port):
|
||||
# бесконечный цикл
|
||||
await asyncio.Future()
|
||||
|
||||
|
||||
def run_app():
|
||||
"""Функция старата приложения"""
|
||||
|
||||
try:
|
||||
asyncio.run(start())
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
run_app()
|
||||
31
robot_pi_service/settings.py
Normal file
31
robot_pi_service/settings.py
Normal file
@@ -0,0 +1,31 @@
|
||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||
|
||||
|
||||
class ModelConfig(BaseSettings):
|
||||
"""Модель конфига"""
|
||||
|
||||
model_config = SettingsConfigDict(
|
||||
env_file = '.env',
|
||||
env_file_encoding='utf-8',
|
||||
extra='ignore'
|
||||
)
|
||||
|
||||
|
||||
class CommandsRobot(ModelConfig):
|
||||
"""Класс с командами для робота"""
|
||||
|
||||
forward: str
|
||||
backward: str
|
||||
left: str
|
||||
right: str
|
||||
|
||||
|
||||
class Settings(ModelConfig):
|
||||
"""Класс для данных конфига"""
|
||||
|
||||
websocket_host: str
|
||||
websocket_port: int
|
||||
commands_robot: CommandsRobot = CommandsRobot()
|
||||
|
||||
|
||||
settings = Settings()
|
||||
Reference in New Issue
Block a user