- Python 100%
| sdk_for_linux | ||
| UnityDemo | ||
| .gitignore | ||
| README.md | ||
Dexmo Server 1.1.6
Краткое руководство по Linux-серверу Dexmo и его TCP-протоколу. Сервер получает данные перчаток через USB-донгл и передаёт клиентам положение пальцев. В обратном направлении принимает команды сопротивления и вибрации. Unity для общения с сервером не требуется.
Описание сверено с комплектным README, схемами Protobuf и Python-примером. Запуск сервера с оборудованием, работа на современных дистрибутивах и совместимость Unity на Linux пока не проверены.
Состав папки
| Путь | Назначение |
|---|---|
sdk_for_linux/dexmo_server/ |
Готовый сервер и его библиотеки |
sdk_for_linux/example_client/ |
Пример Python-клиента и схемы сообщений |
sdk_for_linux/readme/ |
Инструкция производителя со скриншотами |
UnityDemo/Docs/ |
Документация Unity SDK |
UnityDemo/Packages/ |
Пакеты для импорта в Unity |
Запуск сервера
Поставляемый сервер — Linux x86_64, для Intel/AMD. Это готовый бинарник: собирать его и устанавливать отдельно Python 3.5 для него не нужно. Рядом поставляются Python 3.5, Qt5, libusb и другие библиотеки; копируйте всю папку сервера.
Инструкция производителя рассчитана на Ubuntu, но точная версия ОС не указана. Сервер имеет графический интерфейс. Нативных версий для macOS и ARM в этом комплекте нет.
На Linux, из папки DexmosIntegration:
cd sdk_for_linux/dexmo_server
chmod +x dexmo_server_1.1.6
sudo ./dexmo_server_1.1.6
Запуск через sudo приведён в инструкции производителя. В текущей копии бинарник не имеет права исполнения, поэтому нужен chmod.
- Подключите USB-донгл и включите перчатки.
- Запустите сервер и проверьте, что устройства появились в окне.
- Для нужной руки включите
calibration openи нажмитеcalibrate. - Сохраните профиль через
save_calibration_file. Для каждой руки можно выбрать свой профиль. - Оставьте сервер запущенным и подключите клиент.
Скриншоты: инструкция производителя.
Подключение и формат пакета
Пример использует TCP (AF_INET, SOCK_STREAM), адрес 127.0.0.1, порт 55555. После подключения клиент сразу читает кадры; отдельного рукопожатия или авторизации в его коде нет. Производитель заявляет поддержку нескольких устройств и клиентов.
Формат в обоих направлениях:
[4 байта длины N, little-endian][N байт сообщения Protobuf]
Длина относится только к сериализованному Protobuf-сообщению. Получатель читает её как little-endian; отправитель использует struct.pack("i", ...), что на целевом x86_64 даёт тот же порядок байтов. В собственном клиенте задавайте порядок явно: struct.pack("<I", len(payload)).
TCP не сохраняет границы сообщений. Один recv(N) может вернуть меньше N байт: заголовок и тело нужно дочитывать в цикле. Пустой результат recv означает закрытие соединения. Комплектный пример этого не учитывает.
Данные от сервера
Схема: message_frame.proto.
Сервер отправляет Frame с полями frameLen и списком frameMessages. Назначение внутреннего frameLen отдельно не описано; для выделения пакета используйте внешний четырёхбайтовый заголовок.
Каждый FrameMessage содержит:
| Поле | Значение |
|---|---|
id |
ID устройства, используемый также в командах |
handMessage |
11 значений положения пальцев |
deviceMessage.isRight |
Правая рука (true) или левая (false) |
deviceMessage.batteryPercent |
Заряд батареи |
Поля пальцев: thumb_rotate, thumb_split, thumb_bend, а также index_split, index_bend, middle_split, middle_bend, ring_split, ring_bend, pinky_split, pinky_bend.
По документации Unity SDK значения нормализованы в диапазоне 0–1. Для сгибания 0 соответствует кулаку, 1 — раскрытой руке. Пространственных координат запястья в этой схеме нет: для них нужен отдельный трекер.
Команды серверу
Схема: ctrl_command.proto.
Корневое сообщение CommandControl содержит id целевого устройства и списки impedance_command, rumble_command, other_messages. ID берите из входящих кадров: число 1344418560 в примере — ID конкретного устройства автора.
| Команда | Поля и назначение |
|---|---|
ImpedanceControl |
Настройки для Thumb, Index, Middle, Ring, Pinky |
ImpedanceControlData.Stiffness |
Жёсткость 0–1; 0 означает отсутствие силы |
ImpedanceControlData.SetPoint |
Заданное положение; комментарий примера указывает модуль 0–1, положительный знак для направления внутрь, отрицательный — наружу |
RumbleControl |
Вибрация пяти пальцев и список UtilRumble |
RumbleControlData |
is_open, repeated_times, volume, wavetype |
OtherControl |
control_type, control_value; значения и назначение не документированы |
У ImpedanceControl и RumbleControl есть флаг has_index. В примере сопротивления он выставлен в true с комментарием «команду нельзя игнорировать». Точная семантика флага, порядок дополнительных вибромоторов и подтверждения выполнения команд не описаны.
Первая проверка клиента: только чтение
В sdk_for_linux/example_client/.venv настроено виртуальное окружение. На macOS проверены Python 3.9.6 и protobuf==3.20.3: импорт модулей клиента и сериализация сообщений в обе стороны работают. Эта версия Protobuf зафиксирована для совместимости со старыми *_pb2.py SDK; подключение к оборудованию пока не проверено.
Активация из папки DexmosIntegration:
cd sdk_for_linux/example_client
source .venv/bin/activate
Для повторного создания окружения на другом компьютере выполните в папке клиента python3 -m venv .venv, затем .venv/bin/python -m pip install -r requirements.txt. Выход из активированного окружения — deactivate.
Проверка импорта в активированном окружении:
python3 -c 'from proto_util import message_frame_pb2, ctrl_command_pb2; print("Protobuf OK")'
Исходный client_connect.py автоматически запускает test_worker, который каждые две секунды отправляет команды сопротивления. Для проверки только чтения используйте следующий фрагмент из папки sdk_for_linux/example_client, когда импорт выше работает:
import socket
import struct
from proto_util import message_frame_pb2
def recv_exact(sock, size):
data = bytearray()
while len(data) < size:
chunk = sock.recv(size - len(data))
if not chunk:
raise EOFError("Сервер закрыл соединение")
data.extend(chunk)
return bytes(data)
with socket.create_connection(("127.0.0.1", 55555), timeout=10) as sock:
while True:
size = struct.unpack("<I", recv_exact(sock, 4))[0]
if not 0 < size <= 16 * 1024 * 1024:
raise ValueError(f"Неожиданная длина кадра: {size}")
frame = message_frame_pb2.Frame()
frame.ParseFromString(recv_exact(sock, size))
print(frame)
Лимит 16 МиБ и тайм-аут 10 секунд — защитные настройки этого примера, а не требования протокола. Пример не отправляет команд устройствам. Остановка — Ctrl+C.
При генерации новых клиентов сначала удалите [default=0] из копии message_frame.proto: явные значения по умолчанию несовместимы с объявленным proto3. Номера и типы полей менять нельзя.
Подключение с Mac и диагностика
На Mac можно реализовать TCP/Protobuf-клиент. Сам сервер должен работать на Linux x86_64 с подключённым донглом. Возможность прямого подключения к серверу с другого компьютера не проверена: адрес прослушивания не описан. Для доступа к его localhost можно использовать SSH-туннель:
ssh -N -L 55555:127.0.0.1:55555 USER@LINUX_HOST
Замените USER и LINUX_HOST на пользователя и адрес Linux-компьютера с настроенным SSH. Затем клиент на Mac подключается к 127.0.0.1:55555.
| Проблема | Что проверить |
|---|---|
Permission denied при запуске |
Выполнен ли chmod +x |
Exec format error |
Запуск на Linux x86_64, а не macOS или ARM |
| Ошибка библиотек или Qt | Скопирована ли вся папка сервера, доступна ли графическая сессия; сохраните точный текст ошибки |
Connection refused |
Работает ли сервер, правильны ли адрес, порт и SSH-туннель |
| Перчатки не видны | Донгл, питание, права доступа к USB, проброс USB при использовании VM |
| Ошибка импорта Protobuf | Совместимость runtime с комплектными *_pb2.py; при необходимости — повторная генерация из исправленных схем |
| Ошибка разбора кадра | Полностью ли прочитаны заголовок и тело, верно ли задан little-endian |
Источники и границы описания
- README производителя.
- Подключение клиента, чтение, отправка, тест сопротивления.
- Схемы Protobuf, приведённые выше, и руководство Unity SDK.
Исходники основной логики сервера в комплекте не представлены. Частота кадров, ограничения числа клиентов, поведение при потере соединения и арбитраж команд нескольких клиентов требуют проверки на сервере с устройствами.