Перейти к содержимому

Расширенная связь

На этой странице описаны расширенные методы USB-связи, последовательные порты и сетевые сокеты. Для базовых операций чтения и записи см. Записи и чтения.

Понимание разницы между типами USB-передач поможет выбрать правильный метод и отладить неожиданные ошибки.

ТипМетодТипичный размерСценарий использования
Interruptdevice.write() / device.read()3–64 байтаДанные RGB, небольшие команды, ввод с клавиатуры/мыши
Bulkdevice.write() / device.read()64–1025 байтИзображения ЖК-дисплея, обновления прошивки, большие блоки конфигурации
Controldevice.send_report() / device.get_report() / device.control_transfer()32–192 байтаАутентификация, HID feature reports, конфигурация устройства

Одни и те же функции device.write() и device.read() используются как для interrupt-, так и для bulk-передач — USB-драйвер определяет тип по конечной точке и размеру пакета.


Отправляет управляющую передачу HID GET_INPUT_REPORT. Аналогична device.get_report(), но специально запрашивает Input report, а не Feature report. Используйте этот метод, когда get_report() возвращает неверные данные, потому что устройство разделяет типы Input и Feature report.

ПараметрТипОписаниеПример
DataArrayОдномерный массивДанные запроса отчёта[0x01]
LengthIntОжидаемый размер отчёта в байтах64
ВозвратТипОписание
DataArrayОдномерный массивБайты, полученные от устройства
var inputData = device.input_report([0x01], 64);

Выполняет прямую bulk- или interrupt-передачу на конкретную конечную точку USB. В отличие от device.write() и device.read(), использующих конечную точку, выбранную device.set_endpoint(), этот метод позволяет адресоваться к любой конечной точке по адресу.

  • Адреса конечных точек, заканчивающиеся на 0x80 и выше — это IN (устройство → хост, чтение).
  • Адреса конечных точек ниже 0x80 — это OUT (хост → устройство, запись).
ПараметрТипОписаниеПример
EndpointHexАдрес конечной точки USB0x81
DataArrayОдномерный массивДанные для отправки (OUT) или пустой массив (IN)[0x01, 0x02]
LengthIntРазмер передачи в байтах64
TimeoutIntМиллисекунды до прерывания операции100
ВозвратТипОписание
DataArrayОдномерный массивПолученные байты (для IN-передач) или пустой массив
// Write to endpoint 0x01
device.bulk_transfer(0x01, [0x00, 0x01, 0x02], 3, 100);
// Read from endpoint 0x81
var response = device.bulk_transfer(0x81, [], 64, 100);
// Large bulk write (e.g. LCD image data)
device.bulk_transfer(0x02, imageData, 1024, 500);

Низкоуровневая управляющая передача USB. Используется для рукопожатий аутентификации, проприетарных протоколов и случаев, когда методов HID недостаточно. Это управляющая передача, а не bulk-передача.

ПараметрТипОписаниеПример
RequestTypeHexБитовая маска типа USB-запроса (направление, тип, получатель)0xA1
RequestHexКод запроса (специфичный для устройства)0x01
ValueHexПоле значения0x0100
IndexIntИндекс интерфейса или конечной точки0x00
DataArrayОдномерный массивДанные для отправки (хост → устройство) или пустой массив[]
LengthIntОжидаемая длина ответа (устройство → хост)192
TimeoutIntМиллисекунды до прерывания операции1000
ВозвратТипОписание
DataArrayОдномерный массивПолученные байты (для передач устройство → хост)

Распространённые значения RequestType:

ЗначениеНаправлениеТипПолучательСценарий использования
0x21Хост → УстройствоClassInterfaceHID SET_REPORT
0xA1Устройство → ХостClassInterfaceHID GET_REPORT
0x80Устройство → ХостStandardDeviceЧтение дескрипторов
0x00Хост → УстройствоStandardDeviceСтандартные команды
// Read authentication token (device → host, class, interface)
var token = device.control_transfer(
0xA1, // Device-to-host, class, interface
0x01, // GET_REPORT
0x0100, // Report type (Feature) + report ID
0x00, // Interface 0
[], // No outbound data
192, // Expect 192 bytes back
1000 // 1 second timeout
);
// Send a feature report (host → device)
device.control_transfer(0x21, 0x09, 0x0300, 0, [0x03, 0x08, 0x32], 0, 500);

Для устройств с последовательным/COM-портом импортируйте модуль serial и установите Type() плагина в "serial".

import { serial } from "@SignalRGB/serial";
export function Type() { return "serial"; }
serial.connect({
baudRate: 115200, // Default: 115200
parity: "None", // "None", "Even", "Odd", "Space", "Mark"
dataBits: 8, // 5, 6, 7, or 8
stopBits: "One" // "One", "OneAndHalf", "Two"
});
МетодОписаниеВозврат
serial.connect(options?)Открыть последовательный портbool
serial.disconnect()Закрыть последовательный портvoid
serial.isConnected()Проверить состояние подключенияbool
serial.write(data)Отправить данныекол-во записанных байт
serial.read(maxBytes?, timeoutMs?)Прочитать доступные байты (по умолчанию: все, таймаут 1000 мс)массив байт
serial.readAll()Немедленно прочитать все доступные байтымассив байт
serial.availablePorts()Получить список доступных COM-портовмассив
serial.getPortName()Имя текущего портаstring
serial.getBaudRate()Текущая скорость передачи данныхnumber
serial.getDeviceInfo()Информация о порте с VID, PID и т. д.object
import { serial } from "@SignalRGB/serial";
export function Type() { return "serial"; }
export function Initialize() {
if (!serial.connect()) {
device.log("Failed to connect to serial port");
return;
}
device.log(`Connected on ${serial.getPortName()} at ${serial.getBaudRate()} baud`);
}
export function Render() {
serial.write([0xFF, ...RGBData]);
}
export function Shutdown() {
serial.disconnect();
}

Для сетевых устройств импортируйте модуль TCP или UDP и установите Type() в "network". Оба модуля используют модель обратных вызовов на основе событий.

import { tcp } from "@SignalRGB/tcp";
import { udp } from "@SignalRGB/udp";
export function Type() { return "network"; }
import { tcp } from "@SignalRGB/tcp";
let socket;
export function Initialize() {
socket = tcp.createSocket();
socket.on("connected", () => {
device.log("Connected");
socket.send([0x01, 0x02, 0x03]);
});
socket.on("message", (data) => {
device.log(`Received: ${data}`);
});
socket.on("error", (err) => {
device.log(`Error: ${err}`);
});
socket.connect("192.168.1.100", 8080);
}
export function Render() {
if (socket.state === socket.ConnectedState) {
socket.send(RGBData);
}
}
export function Shutdown() {
socket.close();
}

Методы TCP:

МетодОписание
tcp.createSocket()Создать новый TCP-сокет
socket.connect(address, port)Подключиться к хосту
socket.send(data)Отправить строку или массив байт
socket.bind(port)Привязать к локальному порту
socket.close()Закрыть сокет
socket.on(event, callback)Зарегистрировать обработчик события

События TCP: "connected", "disconnected", "message", "error"


import { udp } from "@SignalRGB/udp";
let socket;
export function Initialize() {
socket = udp.createSocket();
socket.on("message", (data) => {
device.log(`Received: ${data}`);
});
socket.connect("192.168.1.100", 21324);
}
export function Render() {
socket.send(RGBData);
}
export function Shutdown() {
socket.close();
}

Методы UDP:

МетодОписание
udp.createSocket()Создать новый UDP-сокет
socket.connect(address, port)Задать адрес назначения по умолчанию для отправки
socket.send(data)Отправить на подключённый адрес
socket.write(data, address, port)Отправить на конкретный адрес без предварительного вызова connect()
socket.bind(port)Привязать к локальному порту для приёма данных
socket.close()Закрыть сокет
socket.on(event, callback)Зарегистрировать обработчик события

События UDP: "connected", "disconnected", "message", "error"


Для устройств, требующих зашифрованной связи (например, Philips Hue), используйте функцию dtls. Она обеспечивает DTLS-зашифрованный UDP с использованием Pre-Shared Key (PSK).

export function Initialize() {
device.addFeature("dtls");
dtls.onConnectionEstablished(() => { device.log("DTLS connected"); });
dtls.onConnectionClosed(() => { device.log("DTLS closed"); });
dtls.onConnectionError(() => { device.log("DTLS error"); });
dtls.createConnection("192.168.1.50", 2100, authIdentity, authKey);
}
export function Render() {
if (dtls.hasEncryptedConnection()) {
dtls.send(RGBData);
}
}
export function Shutdown() {
dtls.CloseConnection();
}

Методы DTLS:

МетодОписание
dtls.createConnection(host, port, identity, key)Открыть зашифрованное соединение с использованием PSK
dtls.send(data, endianness?)Отправить зашифрованные данные (0 = little-endian, 1 = big-endian)
dtls.hasEncryptedConnection()Возвращает true, если соединение установлено
dtls.CloseConnection()Закрыть соединение
dtls.onConnectionEstablished(cb)Обратный вызов при успешном подключении
dtls.onConnectionClosed(cb)Обратный вызов при закрытии соединения
dtls.onConnectionError(cb)Обратный вызов при ошибке