跳到內容

進階通訊

本頁涵蓋進階 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 GET_INPUT_REPORT 控制傳輸。類似於 device.get_report(),但專門請求輸入報告而非功能報告。當 get_report() 返回錯誤資料(因為裝置將輸入和功能報告類型分開)時使用此方法。

參數類型說明範例
DataArray1D 陣列報告請求資料[0x01]
LengthInt預期的報告大小(位元組)64
返回值類型說明
DataArray1D 陣列從裝置接收到的位元組
var inputData = device.input_report([0x01], 64);

對特定 USB 端點執行直接的批量或中斷傳輸。與使用 device.set_endpoint() 所選端點的 device.write()device.read() 不同,此方法允許您通過地址來定向任何端點。

  • 0x80 或更高值結尾的端點地址為 IN(裝置 → 主機,讀取)。
  • 低於 0x80 的端點地址為 OUT(主機 → 裝置,寫入)。
參數類型說明範例
EndpointHexUSB 端點地址0x81
DataArray1D 陣列要發送的資料(OUT),或空陣列(IN)[0x01, 0x02]
LengthInt傳輸大小(位元組)64
TimeoutInt放棄前的毫秒數100
返回值類型說明
DataArray1D 陣列接收到的位元組(IN 傳輸),或空陣列
// 寫入到端點 0x01
device.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);

低階 USB 控制傳輸。用於認證握手、廠商特定協定,以及 HID 方法不足的情況。這是控制傳輸,而非批量傳輸。

參數類型說明範例
RequestTypeHexUSB 請求類型位元組(方向、類型、接收者)0xA1
RequestHex請求代碼(裝置特定)0x01
ValueHex值欄位0x0100
IndexInt介面或端點索引0x00
DataArray1D 陣列要發送的資料(主機到裝置),或空陣列[]
LengthInt預期的響應長度(裝置到主機)192
TimeoutInt放棄前的毫秒數1000
返回值類型說明
DataArray1D 陣列接收到的位元組(裝置到主機傳輸)

常用 RequestType 值:

方向類型接收者使用情況
0x21主機 → 裝置ClassInterfaceHID SET_REPORT
0xA1裝置 → 主機ClassInterfaceHID GET_REPORT
0x80裝置 → 主機StandardDevice描述符讀取
0x00主機 → 裝置StandardDevice標準命令
// 讀取認證令牌(裝置 → 主機,class,interface)
var token = device.control_transfer(
0xA1, // 裝置到主機,class,interface
0x01, // GET_REPORT
0x0100, // 報告類型(Feature)+ 報告 ID
0x00, // 介面 0
[], // 無輸出資料
192, // 預期接收 192 位元組
1000 // 1 秒超時
);
// 發送功能報告(主機 → 裝置)
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, // 預設:115200
parity: "None", // "None", "Even", "Odd", "Space", "Mark"
dataBits: 8, // 5, 6, 7, 或 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 模組並將 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 功能。它使用預共用金鑰(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)發生錯誤時的回呼