Ga naar inhoud

Een plugin maken

Nu we onze RGB-data hebben geïsoleerd, kunnen we beginnen met het maken van onze plugin.

Om een plugin te maken, openen we een teksteditor en plakken we de onderstaande tekst erin.

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 "";
}

De bovenstaande tekst is een basisopzet voor een apparaatplugin.

We beginnen met het invullen van de velden bovenaan de plugin met informatie over ons apparaat.

We kunnen het naamveld invullen met de naam van het apparaat.

Om de leveranciers-ID en product-ID te vinden, moeten we eerst het instellingenmenu van SignalRGB openen via het tandwielpictogram linksonder.

Nu moeten we naar de pagina Apparaatinformatie gaan.

We zoeken naar de VendorID en de ProductID voor het apparaat dat we implementeren. In dit geval is dat de Corsair Scimitar Pro. De leveranciers-ID van de Scimitar is 0x1b1c en de product-ID is 0x1b3e.

Nu we de leveranciers- en product-ID hebben, kunnen we die velden invullen in de plugin.

Voor het veld Publisher kunt u uw eigen naam invullen!

Nu hebben we alle velden ingevuld die we op dit moment kunnen invullen.

Hier is ons voorbeeld voor de Scimitar Pro met de ingevulde velden.

Vervolgens moeten we een functie maken om kleurdata naar ons apparaat te sturen. We beginnen met het maken van een eenvoudige functie zoals de onderstaande:

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

Vervolgens moeten we ons pakket beginnen te vullen met data, wat we doen met behulp van de data uit een van onze gemarkeerde RGB-pakketten.

  • OPMERKING: Dit apparaat is nul-gevuld. Dit betekent dat we alle bytes 1 positie omhoog moeten verschuiven. Lees meer over nulvulling.

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

We beginnen met het invullen van de headerdata voor het pakket zoals hierboven weergegeven. We stoppen bij positie 4, omdat positie 5 onze eerste byte aan RGB-gerelateerde data is.

Vervolgens moeten we ons kleurvulsysteem maken. Er zijn een paar verschillende manieren om dit te doen. De gebruikte methode hangt af van de pakketstructuur van het apparaat. Hier zijn een paar verschillende kleurpakketvoorbeelden:

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);
}

De drie bovenstaande voorbeelden zijn elk geschikt voor een andere pakketstructuur. De functie sendZone is geschikt voor apparaten die een apart pakket gebruiken voor elke LED. De functie sendPacket is beter geschikt voor apparaten die meerdere LED’s achter elkaar in één pakket verzenden. De functie sendColors is geschikt voor apparaten met meerdere LED’s in een pakket, maar niet direct achter elkaar. In ons geval gebruiken we de functie 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);
}

Om de functie sendColors correct in te stellen, moeten we de zone-ID’s van ons apparaat achterhalen. Als we de pakketopname opnieuw bekijken, zien we dat de volgorde van zones 2,4,5,1,3 lijkt te zijn, zoals hieronder weergegeven. Merk op dat we een 5e zone hebben toegevoegd omdat het erop lijkt dat we ook de DPI-LED kunnen aanspreken.

Nu we onze zone-ID’s hebben bepaald, moeten we de offsets voor onze zone_idx achterhalen. Onze eerste zone bevindt zich op packet[4] en onze tweede op packet[8]. Dit betekent dat onze zone_idx elke keer met 4 moet worden vermenigvuldigd om naar een nieuwe LED te gaan. We moeten ook bepalen hoeveel posities we de RGB-data verschuiven. Aangezien onze eerste zone zich op packet[5] bevindt, hoeven we ons pakket slechts met 5 bytes te verschuiven, zoals hieronder te zien is.

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);
}

Nu we alles hebben toegevoegd wat in ons pakket moet, moeten we de pakketlengte bepalen. Om de pakketlengte te vinden, hoeven we alleen te kijken hoe lang onze data uit Wireshark is. In ons voorbeeld zien we dat de data in dit geval 64 bytes lang is.

  • OPMERKING: Dit apparaat is nul-gevuld, wat betekent dat we de schrijflengte één langer moeten maken dan in de Wireshark-opname.

Nu we de lengte van onze data weten, hoeven we alleen de lengte van device.write in te stellen op 65 bytes, zoals hieronder weergegeven.

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);
}

Nu we ons RGB-pakket hebben ingesteld, moeten we onze LED’s instellen en de eindpunten van ons apparaat kiezen.

Om onze LED’s in te stellen, moeten we het juiste aantal LED’s toevoegen aan onze vLedNames en vLedPositions. In ons geval moeten we aan elk vier LED’s toevoegen, zoals hieronder weergegeven.

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

We geven deze vier LED’s voorlopig basistoewijzingen, omdat we nog niet weten waar deze LED’s zich fysiek op het apparaat bevinden ten opzichte van hun toewijzingen in SignalRGB.

Nu we onze LED’s hebben toegewezen, moeten we de grootte van ons apparaat instellen. De grootte van ons apparaat moet in beide richtingen één groter zijn dan onze verste LED. In dit geval moet de grootte [5,1] zijn, omdat onze verste LED zich op [4,0] bevindt.

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]; }

Het volgende wat we moeten achterhalen, is het eindpunt van ons apparaat.