Bỏ qua để đến nội dung

Tạo plugin

Bây giờ chúng ta đã phân tích được dữ liệu RGB, chúng ta có thể bắt đầu tạo plugin.

Để tạo plugin, chúng ta mở trình soạn thảo văn bản và dán văn bản sau.

export function Name() { return ""; }
export function VendorId() { return ; }
export function ProductId() { return ; }
export function Publisher() { return ""; }
export function Documentation(){ return "troubleshooting/brand"; }
export function Size() { return [1,1]; }
export function ControllableParameters() {
return [
{"property":"shutdownColor", "group":"lighting", "label":"Shutdown Color", "min":"0", "max":"360", "type":"color", "default":"009bde"},
{"property":"LightingMode", "group":"lighting", "label":"Lighting Mode", "type":"combobox", "values":["Canvas", "Forced"], "default":"Canvas"},
{"property":"forcedColor", "group":"lighting", "label":"Forced Color", "min":"0", "max":"360", "type":"color", "default":"009bde"},
];
}
export function Initialize() {
}
var vLedNames = [ "Led 1" ];
var vLedPositions = [ [0,0] ];
export function LedNames() {
}
export function LedPositions() {
}
export function Render() {
}
export function Shutdown() {
}
function hexToRgb(hex) {
let result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
let colors = [];
colors[0] = parseInt(result[1], 16);
colors[1] = parseInt(result[2], 16);
colors[2] = parseInt(result[3], 16);
return colors;
}
export function Validate(endpoint) {
return endpoint.interface === 0 && endpoint.usage === 0 && endpoint.usage_page === 0;
}
export function ImageUrl() {
return "";
}

Văn bản trên là cấu trúc cơ bản cho plugin thiết bị.

Chúng ta sẽ bắt đầu bằng cách điền vào các trường ở đầu plugin với thông tin về thiết bị của chúng ta.

Trong trường tên, chúng ta có thể nhập tên thiết bị.

Để tìm Vendor ID và Product ID, trước tiên chúng ta cần mở menu cài đặt SignalRGB thông qua biểu tượng bánh răng ở góc dưới bên trái.

Bây giờ chúng ta cần điều hướng đến trang “Thông tin thiết bị”.

Chúng ta đang tìm VendorID và ProductID cho thiết bị chúng ta đang triển khai. Trong trường hợp của tôi, đó là Corsair Scimitar Pro. Vendor ID của Scimitar là 0x1b1c, và Product ID là 0x1b3e.

Bây giờ chúng ta đã có Vendor và Product ID, chúng ta có thể điền vào các trường đó trong plugin.

Bạn có thể điền vào trường Publisher bằng tên của mình!

Với điều này, chúng ta đã điền vào tất cả các trường mà chúng ta có thể điền ngay bây giờ.

Đây là ví dụ của chúng ta cho Scimitar Pro với các trường đã được điền.

Tiếp theo chúng ta cần tạo một hàm để gửi dữ liệu màu đến thiết bị. Chúng ta sẽ bắt đầu bằng cách tạo một hàm đơn giản như sau:

function sendColors(shutdown = false)
{
let packet = [];
}

Sau đó chúng ta cần điền vào packet của mình với dữ liệu. Để làm điều này, chúng ta sử dụng dữ liệu từ một trong các packet RGB đã được đánh dấu của mình.

  • LƯU Ý: Thiết bị này sử dụng zero-padding. Điều đó có nghĩa là chúng ta phải dịch tất cả các byte lên 1 vị trí. Tìm hiểu thêm về zero-padding tại đây.

function sendColors(shutdown = false)
{
let packet = [];
packet[0] = 0x00;
packet[1] = 0x07;
packet[2] = 0x22;
packet[3] = 0x05;
packet[4] = 0x01;
}

Chúng ta bắt đầu bằng cách chèn dữ liệu header của packet như được hiển thị ở trên. Chúng ta dừng ở vị trí 4, vì vị trí 5 là byte dữ liệu RGB đầu tiên của chúng ta.

Tiếp theo chúng ta cần tạo hệ thống điền màu của mình. Có một vài cách khác nhau để làm điều này. Phương pháp được sử dụng phụ thuộc vào cấu trúc packet của thiết bị. Dưới đây là một số ví dụ về các packet màu khác nhau:

function sendZone(zone, shutdown = false)
{
let packet = [];
packet[0] = LongMessage;
packet[1] = ConnectionMode;
packet[2] = RGBFeatureID;
packet[3] = 0x30;
packet[4] = zone;
packet[5] = 0x01;
var iX = vLedPositions[zone][0];
var iY = vLedPositions[zone][1];
var color;
if(shutdown)
{
color = hexToRgb(shutdownColor);
}
else if (LightingMode == "Forced")
{
color = hexToRgb(forcedColor);
}
else
{
color = device.color(iX, iY);
}
packet[6] = color[0];
packet[7] = color[1];
packet[8] = color[2];
packet[9] = 0x02;
device.write(packet, 120);
}
function SendPacket(shutdown = false)
{
let packet = [];
packet[0] = 0x00;
packet[1] = 0x00;
packet[2] = 0x1F;
packet[3] = 0x00;
packet[4] = 0x00;
packet[5] = 0x00;
packet[6] = 0x41;
packet[7] = 0x0F;
packet[8] = 0x03;
packet[13] = 0x13;
for(let iIdx = 0; iIdx < vLedPositions.length; iIdx++)
{
let iPxX = vLedPositions[iIdx][0];
let iPxY = vLedPositions[iIdx][1];
var color;
if(shutdown)
{
color = hexToRgb(shutdownColor);
}
else if (LightingMode === "Forced")
{
color = hexToRgb(forcedColor);
}
else
{
color = device.color(iPxX, iPxY);
}
let iLedIdx = (iIdx*3) + 14;
packet[iLedIdx] = color[0];
packet[iLedIdx+1] = color[1];
packet[iLedIdx+2] = color[2];
}
device.write(packet, 120);
}
function sendColors(shutdown = false){
let packet = [];
packet[0x00] = 0x00;
packet[0x01] = 0x08;
packet[0x02] = 0x12;
packet[0x03] = 0x05;
packet[0x04] = 0x01;
let zoneId = [1, 2, 3, 4, 5];
for(let zone_idx = 0; zone_idx < vLedPositions.length; zone_idx++) {
let iX = vLedPositions[zone_idx][0];
let iY = vLedPositions[zone_idx][1];
var col;
if(shutdown){
col = hexToRgb(shutdownColor);
}else if (LightingMode === "Forced") {
col = hexToRgb(forcedColor);
}else{
col = device.color(iX, iY);
}
packet[(zone_idx * 4) + 2] = zoneId[zone_idx];
packet[(zone_idx * 4) + 3] = col[0];
packet[(zone_idx * 4) + 4] = col[1];
packet[(zone_idx * 4) + 5] = col[2];
}
device.write(packet, 120);
}

Ba ví dụ trên phù hợp với các cấu trúc packet khác nhau. Hàm sendZone phù hợp với các thiết bị sử dụng packet riêng cho mỗi LED. Hàm sendPacket phù hợp hơn với các thiết bị gửi nhiều LED liên tiếp trong một packet. Hàm sendColors phù hợp với các thiết bị có nhiều LED trong một packet nhưng không trực tiếp liên tiếp. Trong trường hợp của chúng ta, chúng ta sẽ sử dụng hàm sendColors.

function sendColors(shutdown = false)
{
let packet = [];
packet[0] = 0x00;
packet[1] = 0x07;
packet[2] = 0x22;
packet[3] = 0x05;
packet[4] = 0x01;
let zoneId = [2, 4, 5, 1, 3];
for(let zone_idx = 0; zone_idx < vLedPositions.length; zone_idx++) {
let iX = vLedPositions[zone_idx][0];
let iY = vLedPositions[zone_idx][1];
var col;
if(shutdown){
col = hexToRgb(shutdownColor);
}else if (LightingMode === "Forced") {
col = hexToRgb(forcedColor);
}else{
col = device.color(iX, iY);
}
packet[(zone_idx * 1) + 2] = zoneId[zone_idx];
packet[(zone_idx * 1) + 3] = col[0];
packet[(zone_idx * 1) + 4] = col[1];
packet[(zone_idx * 1) + 5] = col[2];
}
packet[21] = 0xff;
packet[22] = 0xff;
packet[23] = 0xff;
device.write(packet, 120);
}

Để thiết lập đúng hàm sendColors, chúng ta cần tìm ID vùng của thiết bị. Khi nhìn lại bản ghi packet, chúng ta thấy rằng thứ tự vùng có vẻ là 2, 4, 5, 1, 3 như được hiển thị bên dưới. Lưu ý rằng chúng ta đã thêm vùng thứ 5 vì có vẻ như chúng ta cũng có thể điều khiển LED DPI.

Bây giờ chúng ta đã tìm thấy các ID vùng, chúng ta cần xác định các offset cho zone_idx. Vùng đầu tiên của chúng ta ở packet[4], và vùng thứ hai ở packet[8]. Điều đó có nghĩa là zone_idx phải được nhân với 4 mỗi lần để chuyển sang LED tiếp theo. Chúng ta cũng cần tìm ra bao nhiêu vị trí để dịch dữ liệu RGB. Vì vùng đầu tiên của chúng ta ở packet[5], chúng ta chỉ cần dịch packet của mình đi 5 byte như được thấy bên dưới.

function sendColors(shutdown = false)
{
let packet = [];
packet[0] = 0x00;
packet[1] = 0x07;
packet[2] = 0x22;
packet[3] = 0x05;
packet[4] = 0x01;
let zoneId = [2, 4, 5, 1, 3];
for(let zone_idx = 0; zone_idx < vLedPositions.length; zone_idx++) {
let iX = vLedPositions[zone_idx][0];
let iY = vLedPositions[zone_idx][1];
var col;
if(shutdown){
col = hexToRgb(shutdownColor);
}else if (LightingMode === "Forced") {
col = hexToRgb(forcedColor);
}else{
col = device.color(iX, iY);
}
packet[(zone_idx * 4) + 5] = zoneId[zone_idx];
packet[(zone_idx * 4) + 6] = col[0];
packet[(zone_idx * 4) + 7] = col[1];
packet[(zone_idx * 4) + 8] = col[2];
}
device.write(packet, 120);
}

Bây giờ chúng ta đã thêm tất cả mọi thứ thuộc về packet của mình, chúng ta cần xác định độ dài packet. Để tìm độ dài packet, chúng ta chỉ cần kiểm tra độ dài packet của mình trong Wireshark là bao nhiêu. Trong ví dụ của chúng ta, chúng ta thấy rằng dữ liệu trong trường hợp này dài 64 byte.

  • LƯU Ý: Thiết bị này sử dụng zero-padding, có nghĩa là chúng ta phải đặt độ dài ghi lớn hơn một so với bản ghi Wireshark.

Vì bây giờ chúng ta biết độ dài dữ liệu, chúng ta chỉ cần đặt độ dài device.write thành 65 byte như được hiển thị bên dưới.

function sendColors(shutdown = false)
{
let packet = [];
packet[0] = 0x00;
packet[1] = 0x07;
packet[2] = 0x22;
packet[3] = 0x05;
packet[4] = 0x01;
let zoneId = [2, 4, 5, 1, 3];
for(let zone_idx = 0; zone_idx < vLedPositions.length; zone_idx++) {
let iX = vLedPositions[zone_idx][0];
let iY = vLedPositions[zone_idx][1];
var col;
if(shutdown){
col = hexToRgb(shutdownColor);
}else if (LightingMode === "Forced") {
col = hexToRgb(forcedColor);
}else{
col = device.color(iX, iY);
}
packet[(zone_idx * 4) + 5] = zoneId[zone_idx];
packet[(zone_idx * 4) + 6] = col[0];
packet[(zone_idx * 4) + 7] = col[1];
packet[(zone_idx * 4) + 8] = col[2];
}
device.write(packet, 65);
}

Bây giờ chúng ta đã thiết lập packet RGB, chúng ta cần thiết lập LED và chọn endpoint thiết bị.

Để thiết lập LED, chúng ta cần thêm số lượng LED phù hợp vào vLedNames và vLedPositions. Trong trường hợp của chúng ta, chúng ta cần thêm bốn LED nữa vào cả hai như được hiển thị bên dưới.

var vLedNames = [ "Led 1", "Led 2", "Led 3", "Led 4", "Led 5" ];
var vLedPositions = [ [0,0], [1,0], [2,0], [3,0], [4,0] ];

Chúng ta đặt cho bốn LED này các ánh xạ cơ bản cho bây giờ, vì chúng ta chưa biết các LED này được đặt vật lý ở đâu trên thiết bị so với ánh xạ của chúng trong SignalRGB.

Bây giờ chúng ta đã ánh xạ các LED, chúng ta cần đặt kích thước thiết bị. Kích thước thiết bị phải lớn hơn một so với LED xa nhất của chúng ta theo cả hai hướng. Trong trường hợp của tôi, kích thước phải là [5,1], vì LED xa nhất của tôi là [4,0].

export function Name() { return "Corsair Scimitar Pro"; }
export function VendorId() { return 0x1b1c; }
export function ProductId() { return 0x1B3E; }
export function Publisher() { return "WhirlwindFX"; }
export function Documentation(){ return "troubleshooting/corsair"; }
export function Size() { return [5,1]; }

Tiếp theo chúng ta cần xác định endpoint của thiết bị.