تخطَّ إلى المحتوى

الاتصال المتقدم

تتناول هذه الصفحة طرق اتصال USB المتقدمة والمنافذ التسلسلية ومقابس الشبكة. للاطلاع على عمليات القراءة والكتابة الأساسية، راجع الكتابة والقراءة.

سيساعدك فهم الفرق بين أنواع نقل USB على اختيار الطريقة المناسبة وتصحيح الأخطاء غير المتوقعة.

النوعالطريقةالحجم المعتادحالة الاستخدام
المقاطعة (Interrupt)device.write() / device.read()3–64 بايتبيانات RGB، الأوامر الصغيرة، إدخال لوحة المفاتيح/الماوس
الجملة (Bulk)device.write() / device.read()64–1025 بايتصور LCD، تحديثات البرامج الثابتة، كتل الإعدادات الكبيرة
التحكم (Control)device.send_report() / device.get_report() / device.control_transfer()32–192 بايتالمصادقة، تقارير ميزات HID، تهيئة الجهاز

تُستخدم الدالتان device.write() وdevice.read() نفسهما لكل من نقل المقاطعة ونقل الجملة — إذ يحدد برنامج تشغيل USB النوع بناءً على نقطة النهاية وحجم الحزمة.


ترسل عملية نقل تحكم HID من نوع GET_INPUT_REPORT. تشبه device.get_report() لكنها تطلب تحديدًا تقرير إدخال (Input) بدلًا من تقرير ميزة (Feature). استخدمها عندما تُرجع get_report() بيانات خاطئة لأن الجهاز يفصل بين نوعي تقارير الإدخال والميزات.

المعاملالنوعالوصفمثال
DataArrayمصفوفة أحادية البعدبيانات طلب التقرير[0x01]
LengthIntحجم التقرير المتوقع بالبايت64
القيمة المُرجعةالنوعالوصف
DataArrayمصفوفة أحادية البعدالبايتات المستلمة من الجهاز
var inputData = device.input_report([0x01], 64);

تُجري عملية نقل جملة أو مقاطعة مباشرة إلى نقطة نهاية 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. هذه عملية نقل تحكم، وليست نقل جملة.

المعاملالنوعالوصفمثال
RequestTypeHexخريطة بتات نوع طلب USB (الاتجاه، النوع، المستلم)0xA1
RequestHexرمز الطلب (خاص بالجهاز)0x01
ValueHexحقل القيمة0x0100
IndexIntفهرس الواجهة أو نقطة النهاية0x00
DataArrayمصفوفة أحادية البعدالبيانات المراد إرسالها (من المضيف إلى الجهاز)، أو فارغة[]
LengthIntطول الاستجابة المتوقع (من الجهاز إلى المضيف)192
TimeoutIntعدد المللي ثانية قبل التوقف عن المحاولة1000
القيمة المُرجعةالنوعالوصف
DataArrayمصفوفة أحادية البعدالبايتات المستلمة (في عمليات النقل من الجهاز إلى المضيف)

قيم RequestType الشائعة:

القيمةالاتجاهالنوعالمستلمحالة الاستخدام
0x21المضيف ← الجهازالفئة (Class)الواجهةHID SET_REPORT
0xA1الجهاز ← المضيفالفئة (Class)الواجهةHID GET_REPORT
0x80الجهاز ← المضيفقياسيالجهازقراءة الواصفات
0x00المضيف ← الجهازقياسيالجهازالأوامر القياسية
// 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?)قراءة البايتات المتاحة (الافتراضي: الكل، مهلة 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". تستخدم كلتا الوحدتين نموذج استدعاء (callback) قائمًا على الأحداث.

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. فهي توفر UDP مشفّرًا بتقنية DTLS باستخدام مفتاح مُشترك مسبقًا (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)استدعاء عند حدوث خطأ