No description
Find a file
2026-11-05 17:43:01 +08:00
sdk_for_linux Init repo 2026-11-05 17:26:46 +08:00
UnityDemo Init repo 2026-11-05 17:26:46 +08:00
.gitignore upd gitignore 2026-11-05 17:43:01 +08:00
README.md Init repo 2026-11-05 17:26:46 +08:00

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.

  1. Подключите USB-донгл и включите перчатки.
  2. Запустите сервер и проверьте, что устройства появились в окне.
  3. Для нужной руки включите calibration open и нажмите calibrate.
  4. Сохраните профиль через save_calibration_file. Для каждой руки можно выбрать свой профиль.
  5. Оставьте сервер запущенным и подключите клиент.

Скриншоты: инструкция производителя.

Подключение и формат пакета

Пример использует 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

Источники и границы описания

Исходники основной логики сервера в комплекте не представлены. Частота кадров, ограничения числа клиентов, поведение при потере соединения и арбитраж команд нескольких клиентов требуют проверки на сервере с устройствами.