Corsair_Virtuoso_XT_Headset.js hinzugefügt

This commit is contained in:
s-mendyka 2024-07-24 12:41:18 +02:00
parent fd38f7f088
commit 5971386363

View File

@ -0,0 +1,254 @@
export function Name() { return "Corsair Virtuoso XT Headset"; }
export function VendorId() { return 0x1b1c; }
export function ProductId() { return 0x0A64; }
export function Publisher() { return "WhirlwindFX"; }
export function Documentation(){ return "troubleshooting/corsair"; }
export function Size() { return [1, 1]; }
export function DefaultPosition(){return [145, 85];}
export function DefaultScale(){return 10.0;}
/* global
LightingMode:readonly
forcedColor:readonly
idleTimeout:readonly
idleTimeoutLength:readonly
SidetoneAmount:readonly
*/
export function ControllableParameters() {
return [
{"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"},
{"property":"idleTimeout", "group":"", "label":"Enable Device Sleep", "type":"boolean", "default":"true"},
{"property":"idleTimeoutLength", "group":"", "label":"Device Sleep Timeout (Minutes)", "type":"combobox", "values":["1","2","3","4","5","10","15","20","25","30"], "default":"10"},
{"property":"SidetoneAmount", "group":"", "label":"Sidetone", "step":"1", "type":"number", "min":"0", "max":"100", "default":"0"},
];
}
let headsetMode;
let device_status;
let previousBatteryLevel = -1;
let batteryPercentage = -1;
const vLeds = [ 0, 1 ]
const vLedNames = [
"Logo", "Mic"
];
const vLedPositions = [
[0, 0], [0, 1]
];
export function LedNames() {
return vLedNames;
}
export function LedPositions() {
return vLedPositions;
}
export function Initialize() {
// Wired uses 0x08 and wireless device uses 0x09
headsetMode = (ProductId() == 0x0a6b || ProductId() == 0x0a64) ? 0x09 : 0x08;
device.addFeature("battery");
setSoftwareMode();
setMicOn()
setSidetone();
setIdleTimeout(idleTimeoutLength);
}
export function Render() {
readDevice(); // Micstatus why seperate stream?!
sendColors();
}
export function Shutdown(SystemSuspending) {
if(SystemSuspending){
// Go Dark on System Sleep/Shutdown
sendColors("#000000");
}else{
device.write([0x02, headsetMode, 0x01, 0x03, 0x00, 0x01], 64); // Hardware mode
}
}
export function onSidetoneAmountChanged() {
setSidetone();
}
export function onidleTimeoutLengthChanged() {
if (idleTimeout){
console.log ("Set Idle Timeout to: " + idleTimeoutLength + "Minutes")
setIdleTimeout(idleTimeoutLength)
}
}
function sendColors(overrideColor) {
const packet = [];
const RGBData = [];
packet[0] = 0x02;
packet[1] = headsetMode;
packet[2] = 0x06;
packet[4] = 0x09;
for (let idx = 0; idx < vLedPositions.length; idx++) {
const iPxX = vLedPositions[idx][0];
const iPxY = vLedPositions[idx][1];
let color;
if(overrideColor){
color = hexToRgb(overrideColor);
}else if (LightingMode === "Forced") {
color = hexToRgb(forcedColor);
}else{
color = device.color(iPxX, iPxY);
}
RGBData[(vLeds[idx]*3)] = color[0];
RGBData[(vLeds[idx]*3)+1] = color[1];
RGBData[(vLeds[idx]*3)+2] = color[2];
}
device.set_endpoint(3, 0x0001, 0xFF42);
device.write(packet, 64);
}
function setSidetone() {
device.set_endpoint(3, 0x0001, 0xFF42);
const packet = [];
// Header
packet[0] = 0x02;
packet[1] = headsetMode;
packet[2] = 0x01;
packet[3] = 0x47;
let sidetoneValue = Math.round((SidetoneAmount / 100) * 1000);
packet[0x05] = sidetoneValue & 0xFF;
packet[0x06] = (sidetoneValue >> 8) & 0xFF;
device.write(packet, 64);
}
export function onidleTimeoutChanged() {
if (idleTimeout){
device.set_endpoint(3, 0x0001, 0xFF42);
device.write([0x02, headsetMode, 0x01, 0x0d, 0x01], 128);
device.pause(1);
setIdleTimeout(idleTimeoutLength)
}else{
device.set_endpoint(3, 0x0001, 0xFF42);
device.write([0x02, headsetMode, 0x01, 0x0d], 128);
device.log("Set IdleTimeout to: disabled");
}
}
function setSoftwareMode() {
device.set_endpoint(3, 0x0001, 0xFF42);
device.write([0x02, headsetMode, 0x01, 0x03, 0x00, 0x02], 64); // Enable Software Mode
device.write([0x02, headsetMode, 0x0D, 0x00, 0x01], 64); //Open lighting endpoint
device.pause(100);
device.write([0x02, headsetMode, 0x01, 0x02, 0x00, 0xe8, 0x03], 64); //Hardware Brightness 100%
}
function readDevice() {
device.set_endpoint(3, 0x0002, 0xFF42);
const packet = device.read([0x00], 16, 15);
if(packet[0] == 0x03 && packet[1] == 0x01 && packet[2] == 0x01 && packet[3] == 0x10 && packet[4] == 0x00 && packet[5] == 0x02) {
setSoftwareMode();
}
if(packet[0] == 0x03 && packet[2] == 0x01 && packet[3] == 0x46 && packet[4] == 0x00 && packet[5] == 0x00) {
console.log("Microphone: ON")
}
if(packet[0] == 0x03 && packet[2] == 0x01 && packet[3] == 0x46 && packet[4] == 0x00 && packet[5] == 0x01) {
console.log("Microphone: OFF")
}
if(packet[0] == 0x03 && packet[2] == 0x01 && packet[3] == 0x10 && packet[4] == 0x00 && packet[5] == 0x01) {
battery.setBatteryState(2)
console.log("Headset is charging")
}
if(packet[0] == 0x03 && packet[2] == 0x01 && packet[3] == 0x10 && packet[4] == 0x00 && packet[5] == 0x02) {
battery.setBatteryState(1)
console.log("Headset is draining")
}
if (packet[0] == 0x03 && packet[1] == 0x01 && packet[2] == 0x01 && packet[3] == 0x0f && packet[4] == 0x00) {
let batteryValue = (packet[5] & 0xFF) | ((packet[6] & 0xFF) << 8);
let maxBatteryValue = 1023; // 0xff03 in Dezimal
batteryPercentage = Math.round((batteryValue / maxBatteryValue) * 100);
console.log("Battery Level: " + batteryPercentage + "%");
console.log("Battery Level hex: " + packet[5].toString(16) + " " + packet[6].toString(16));
battery.setBatteryLevel(batteryPercentage);
if (typeof previousBatteryLevel !== 'undefined') {
if (batteryPercentage < previousBatteryLevel) {
battery.setBatteryState(1);
} else if (batteryPercentage > previousBatteryLevel) {
battery.setBatteryState(2);
}
}
previousBatteryLevel = batteryPercentage;
}
}
function setMicOn() {
device.set_endpoint(3, 0x0001, 0xFF42);
device.write([0x02, headsetMode, 0x01, 0x8e, 0x00, 0x00], 128); //Mic Status
device.write([0x02, headsetMode, 0x01, 0x46, 0x00, 0x00], 128); //commit
}
function setIdleTimeout(idleTimeoutLength) {
applyPreConfig()
applyIdleTimeout(idleTimeoutLength)
}
function applyIdleTimeout(idleTimeoutLength) {
device.set_endpoint(3, 0x0001, 0xFF42);
const packet = [];
packet[0] = 0x02;
packet[1] = headsetMode;
packet[2] = 0x01;
packet[3] = 0x0e;
const timeoutValue = idleTimeoutLength * 60000;
const hexValue = timeoutValue.toString(16).padStart(6, '0');
const littleEndianHex = hexValue.match(/../g).reverse();
packet[5] = parseInt(littleEndianHex[0], 16);
packet[6] = parseInt(littleEndianHex[1], 16);
packet[7] = parseInt(littleEndianHex[2], 16);
console.log ("Idle Timeout: " + idleTimeoutLength + "Min")
device.write(packet, 128);
}
function applyPreConfig() {
device.set_endpoint(3, 0x0001, 0xFF42);
device.write([0x02, headsetMode, 0x01, 0x0d, 0x00, 0x01], 128);
device.pause(1);
}
function hexToRgb(hex) {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
const 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 === 3 && (endpoint.usage === 0x0001 || endpoint.usage === 0x0002) && endpoint.usage_page === 0xFF42;
}
export function ImageUrl() {
return "https://assets.signalrgb.com/devices/brands/corsair/audio/virtuoso-xt.png";
}