Merge pull request #1 from Arduinum/arduinum/service-orange-pi-mvp-1

Arduinum/service orange pi mvp 1
This commit was merged in pull request #1.
This commit is contained in:
Eugene
2025-07-18 16:53:15 +03:00
committed by GitHub
7 changed files with 138 additions and 1 deletions

3
.gitignore vendored
View File

@@ -172,3 +172,6 @@ cython_debug/
# PyPI configuration file # PyPI configuration file
.pypirc .pypirc
# IDE
.vscode/

3
Makefile Normal file
View File

@@ -0,0 +1,3 @@
run:
chmod +x robot_pi_service/robot_pi_service.py
python3 robot_pi_service/robot_pi_service.py

View File

@@ -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
View File

@@ -0,0 +1,2 @@
websockets==15.0.1
pydantic-settings==2.9.1

View File

View 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()

View 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()