# Передача запроса на ровер

В данном документе будет использована версия на языке Python.

## Информация необходимая для понимания

#### Что такое Asyncio?

Asyncio — это библиотека для написания конкурентного кода с использованием синтаксических конструкций async/await.

В частности, этот модуль поддерживает неблокирующую обработку ввода/вывода с использованием подпроцессов (для выполнения команд) и с использованием потоков (для программирования TCP-сокетов).

#### Что такое корутина/сопрограмма?

Корутина — это функция, выполнение которой можно приостановить и возобновить.

{% hint style="info" %}
***Корутина**: корутины — это более общая форма подпрограмм. Подпрограммы имеют одну точку входа и одну точку выхода. А корутины поддерживают множество точек входа, выхода и возобновления их выполнения.*

[*Python glossary*](https://docs.python.org/3/glossary.html#term-coroutine)
{% endhint %}

Более подробно о корутинах можно почитать в разделе [2.1. Изменения, внесённые в Python для добавления в язык поддержки корутин](https://habr.com/ru/companies/wunderfund/articles/700474/).

### Добавление пакета в проект

<pre class="language-sh"><code class="lang-sh"><strong>pip install "python-socketio[asyncio_client]"
</strong>pip install aiohttp
</code></pre>

## Создание экземпляра клиента

```python
import socketio
sio = socketio.AsyncClient()
```

### Подключение к серверу

Основные параметры при подключении:

* url - ip или ссылка на сервер, к которому подключается пользователь для работы с техникой;
* transports - протокол, по которому происходит общение между клиентом и техникой. В нашем случае мы используем `websocket`;
* namespaces - строка или массив строк с названиями "комнат", в которых происходит общение между клиентом и техникой;
* auth - токен для подключения к серверу. Без него никакие запросы на технику выполнить не получится.

```python
import asyncio
# в зависимости от конфигурации сети, может быть разный ip сервера
server = 'http://192.168.0.1:0000'

async def connection():
    await sio.connect(server, wait_timeout = 5 ,transports='websocket', namespaces=['/vehicles'], auth={"token": ''})

asyncio.run(connection())
```

### Отправка запросов на ровер

Основные параметры при создании запроса:

* emit\_name - название запроса, который пользователь отправляет. Список всех возможных запросов находится в другом разделе;
* data - данные, которые передаются без параметра. Необязательный параметр;
* namespace - строка с названиям "комнаты", в которой происходит общение между клиентом и техникой;
* callback - функция, которая обработает возвращенную  информацию.

```python
async def on_message(data):
    print('Получено сообщение:', data)

await sio.emit(`emit_name`, {'data': 'some data'}, namespace=['/vehicles'], callback=on_message)
await sio.emit(`emit_name2`, namespace=['/vehicles'], callback=on_message)
```

### Получение событий

#### Определение событий

Socket.io основан на событиях, поэтому когда сервер хочет связаться с клиентом, он отправляет событие, которое нужно прослушивать. У каждого события есть имя и список аргументов.

* name - название события;
* handler - обработчик вызванного события, в данном примере это `on_message`;&#x20;
* namespace - строка с названиям "комнаты", в которой происходит общение между клиентом и техникой;

```python
async def on_message(data):
    print('Получено сообщение:', data)

sio.on('toClient', on_message, namespace='/vehicles')
```

## Пример команды command на движение

Команда, с громкоговорящим названием `command` , является общей для большинства действий ровера. В данном блоке мы заставим технику сдвинуться с места и через 5 секунд остановиться.

Параметры данного запроса:

* name - название события, строка `command` ;
* data - данные, которые передаются на ровер:

1. id - идентификатор техники;
2. type - тип команды, в данном случае `move` ;
3. value -  данные для команды `move` , которые используются для выполнения команды.

{% hint style="info" %}
Для более подробной информации по value, читайте на [вкладке о командах](https://dh-organization.gitbook.io/droneshub-rover-kontakt/programmirovanie-rovera-kontakt/spisok-dostupnykh-komand)
{% endhint %}

* namespace - строка с названиям "комнаты", в которой происходит общение между клиентом и техникой;
* callback - функция, вызываемая при возвращении результатов выполненя команды.

```python
import socketio
import asyncio
server = 'http://localhost:3006'

# Создаем экземпляр асинхронного клиента Socket.IO
sio = socketio.AsyncClient()

# Определяем обработчик события "connect"
@sio.event
async def connect():
    print('Подключено к серверу Socket.IO')

async def on_move(result):
    print('Command done:', result)
    

async def main():
    # Подключаемся к серверу
    await sio.connect(server, wait_timeout = 20,transports='websocket', namespaces=['/vehicles'], auth={"token": ''})
    await sio.emit('command',{
				'id': 1,
				'type': "move",
				'value': {
					'x': 0,
					'y': 0.5,
					'sensitivity': 1,
				},
			}, namespace='/vehicles', callback=on_move)
    await asyncio.sleep(5)
    await sio.emit('command',{
				'id': 1,
				'type': "move",
				'value': {
					'x': 0,
					'y': 0,
					'sensitivity': 1,
				},
			}, namespace='/vehicles', callback=on_move)
    # Запускаем цикл обработки событий
    await sio.wait()

# Запускаем асинхронный цикл main()
asyncio.run(main())
```
