高级通信
本页介绍高级 USB 通信方法、串口和网络套接字。有关基本读写操作,请参阅写入和读取。
USB 传输类型
Section titled “USB 传输类型”了解 USB 传输类型之间的差异将帮助您选择正确的方法并调试意外错误。
| 类型 | 方法 | 典型大小 | 使用场景 |
|---|---|---|---|
| 中断 | device.write() / device.read() | 3–64 字节 | RGB 数据、小命令、键盘/鼠标输入 |
| 批量 | device.write() / device.read() | 64–1025 字节 | LCD 图像、固件更新、大型配置块 |
| 控制 | device.send_report() / device.get_report() / device.control_transfer() | 32–192 字节 | 身份验证、HID 功能报告、设备配置 |
相同的 device.write() 和 device.read() 函数用于中断和批量传输——USB 驱动程序根据端点和数据包大小确定传输类型。
HID 报告方法
Section titled “HID 报告方法”device.input_report()
Section titled “device.input_report()”发送 HID GET_INPUT_REPORT 控制传输。类似于 device.get_report(),但专门请求 Input 报告而不是 Feature 报告。当 get_report() 返回错误数据时(因为设备将其 Input 和 Feature 报告类型分开)使用此方法。
| 参数 | 类型 | 描述 | 示例 |
|---|---|---|---|
| DataArray | 1D 数组 | 报告请求数据 | [0x01] |
| Length | Int | 预期报告大小(字节) | 64 |
| 返回值 | 类型 | 描述 |
|---|---|---|
| DataArray | 1D 数组 | 从设备接收的字节 |
var inputData = device.input_report([0x01], 64);原始 USB 方法
Section titled “原始 USB 方法”device.bulk_transfer()
Section titled “device.bulk_transfer()”对特定 USB 端点执行直接批量或中断传输。与使用 device.set_endpoint() 选择端点的 device.write() 和 device.read() 不同,这允许您通过地址定位任何端点。
- 以
0x80或更高值结尾的端点地址是 IN(设备 → 主机,读取)。 - 低于
0x80的端点地址是 OUT(主机 → 设备,写入)。
| 参数 | 类型 | 描述 | 示例 |
|---|---|---|---|
| Endpoint | Hex | USB 端点地址 | 0x81 |
| DataArray | 1D 数组 | 要发送的数据(OUT),或空数组(IN) | [0x01, 0x02] |
| Length | Int | 传输大小(字节) | 64 |
| Timeout | Int | 放弃前的毫秒数 | 100 |
| 返回值 | 类型 | 描述 |
|---|---|---|
| DataArray | 1D 数组 | 接收的字节(IN 传输),或空 |
// 写入端点 0x01device.bulk_transfer(0x01, [0x00, 0x01, 0x02], 3, 100);
// 从端点 0x81 读取var response = device.bulk_transfer(0x81, [], 64, 100);
// 大型批量写入(例如 LCD 图像数据)device.bulk_transfer(0x02, imageData, 1024, 500);device.control_transfer()
Section titled “device.control_transfer()”底层 USB 控制传输。用于身份验证握手、供应商特定协议以及 HID 方法不够用的情况。这是控制传输,而不是批量传输。
| 参数 | 类型 | 描述 | 示例 |
|---|---|---|---|
| RequestType | Hex | USB 请求类型位图(方向、类型、接收方) | 0xA1 |
| Request | Hex | 请求代码(特定于设备) | 0x01 |
| Value | Hex | 值字段 | 0x0100 |
| Index | Int | 接口或端点索引 | 0x00 |
| DataArray | 1D 数组 | 要发送的数据(主机到设备),或空 | [] |
| Length | Int | 预期响应长度(设备到主机) | 192 |
| Timeout | Int | 放弃前的毫秒数 | 1000 |
| 返回值 | 类型 | 描述 |
|---|---|---|
| DataArray | 1D 数组 | 接收的字节(设备到主机传输) |
常用 RequestType 值:
| 值 | 方向 | 类型 | 接收方 | 使用场景 |
|---|---|---|---|---|
0x21 | 主机 → 设备 | 类 | 接口 | HID SET_REPORT |
0xA1 | 设备 → 主机 | 类 | 接口 | HID GET_REPORT |
0x80 | 设备 → 主机 | 标准 | 设备 | 描述符读取 |
0x00 | 主机 → 设备 | 标准 | 设备 | 标准命令 |
// 读取身份验证令牌(设备 → 主机,类,接口)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);
// 发送功能报告(主机 → 设备)device.control_transfer(0x21, 0x09, 0x0300, 0, [0x03, 0x08, 0x32], 0, 500);对于串口/COM 端口设备,导入串口模块并将插件的 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?) | 读取可用字节(默认:全部,1000ms 超时) | 字节数组 |
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)
Section titled “网络通信(TCP / UDP)”对于网络连接的设备,导入 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"
DTLS(加密 UDP)
Section titled “DTLS(加密 UDP)”对于需要加密通信的设备(例如 Philips Hue),请使用 dtls 功能。它使用预共享密钥(PSK)提供 DTLS 加密 UDP。
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 = 小端,1 = 大端) |
dtls.hasEncryptedConnection() | 如果连接已建立则返回 true |
dtls.CloseConnection() | 关闭连接 |
dtls.onConnectionEstablished(cb) | 连接成功时的回调 |
dtls.onConnectionClosed(cb) | 连接关闭时的回调 |
dtls.onConnectionError(cb) | 发生错误时的回调 |