Skip to content

Commit

Permalink
Changed setMultiColorLed input format to a two-dimensional matrix
Browse files Browse the repository at this point in the history
Updated README
  • Loading branch information
illixion committed May 20, 2020
1 parent 3755a7a commit 01176cc
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 27 deletions.
51 changes: 37 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,44 +4,67 @@ Anne Pro 2 RGB control through Node.js

This npm package allows to control the Anne Pro 2 RGB keyboard keys without ObinsKit. Anne Pro 1 compatibility has not been tested as I don't have that keyboard.

Currently, settings are not saved and custom LED graphics set with this module are lost when the keyboard loses power or when user changes the profile with a keyboard button. This works similarly to the profile preview mode in ObinsKit.

## How to use

1. Install as an npm package
2. `var Annemone = require('annemone')`
3. Annemone is now accessible as a class through a variable
3. `const LEDController = new Annemone()`

## Available methods

### Annemone.setMultiColorLed(arrayOfRgbValues)
### Annemone.LEDController.setMultiColorLed(ledMatrix, fast_mode)

Set per-key RBG value.

Takes a flat array of RBG values for each key, left to right, top to bottom, from the Escape key to right Ctrl.

Example arrayOfRgbValues: `[255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 255, 0, 255, 255, 0, 255, 255, 0, 255, 255, 0, 255, 255, 0, 255, 255, 0, 255, 255, 0, 255, 255, 0, 255, 255, 0, 255, 255, 0, 255, 255, 0, 255, 255, 0, 255, 255, 0, 255, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 0, 0, 0, 255, 255, 0, 0, 0, 0, 255, 255, 0, 255, 255, 0, 255, 255, 0, 255, 255, 0, 255, 255, 0, 255, 255, 0, 255, 255, 0, 255, 255, 0, 255, 255, 0, 255, 255, 0, 255, 255, 0, 0, 0, 255, 0, 255, 0, 0, 0, 255, 0, 255, 255, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 255, 0, 0, 0, 0, 0, 0, 255, 0, 255, 255, 0, 255, 255, 0, 255, 255, 0, 255, 0, 0, 0]`

### Annemone.setSingleColorLed(rgb)
Accepts a two-dimensional matrix with RGB values corresponding to each of the 61 keys as they appear on the keyboard.

There's a 50ms delay between commands, I'm still reverse engineering the music mode.

Example matrix:
```js
[
[255, 0, 0] // esc
[255, 0, 0] // 1
[255, 0, 0] // 2
...
],
[
[255, 0, 0] // tab
[255, 0, 0] // q
[255, 0, 0] // w
...
]
...
```

### Annemone.LEDController.setSingleColorLed(rgb)

Set all keys to one color.

Takes an array with 3 elements: red, green and blue.

Example rgb: `[255, 0, 0]`

### Annemone.generateMultiColor(arrayOfRgbValues, usb_host = 65, command_info = [32, 3, 255, 2])
### Annemone.LEDController.generateMultiColor(arrayOfRgbValues, mcu_address = 65, command_info = [32, 3, 255, 2])

HID packet generator for `setMultiColorLed`.

- arrayOfRgbValues: same as for `setMultiColorLed`
- usb_host: MCU address? Possibly depends on whether this is an Anne Pro or Anne Pro 2, can only be 65 or 49
- command_info: contents unknown, more research needed
- arrayOfRgbValues: 70 sequential rgb values for each key (skip the following keys as they do not exist on the board: *41, 43, 55, 57, 60, 61, 63, 64*)
- mcu_address: not sure what an MCU is internally, possibly depends on whether this is an Anne Pro or Anne Pro 2, code suggests this can only be 65 or 49
- command_info:
- 32: appears to select the destination (32 is LED)
- 3: LED command type selector
- 255: unknown, doesn't do anything
- 2: selects a preset lighting profile (2 is static rainbow for example)

### Annemone.generateOneColor(rbg_color, usb_host = 65)
### Annemone.LEDController.generateOneColor(rbg_color, mcu_address = 65)

HID packet generator for `setSingleColorLed`.

### Annemone.write(message)
### Annemone.LEDController.write(message)

HID message write wrapper with forced delay.
HID write wrapper with a forced delay.

Needed due to Anne Pro 2 ignoring commands when they're sent faster than 50ms apart from each other.
102 changes: 89 additions & 13 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Annemone v0.0.1
// Annemone v0.1.1
//

var HID = require('node-hid');
Expand All @@ -23,19 +23,96 @@ class LEDController {
return new HID.HID(keyboard_info.path);
}
})();
this.AnnePro2Layout = [
{ key: 'esc', matrix_id: 0 },
{ key: '1', matrix_id: 1 },
{ key: '2', matrix_id: 2 },
{ key: '3', matrix_id: 3 },
{ key: '4', matrix_id: 4 },
{ key: '5', matrix_id: 5 },
{ key: '6', matrix_id: 6 },
{ key: '7', matrix_id: 7 },
{ key: '8', matrix_id: 8 },
{ key: '9', matrix_id: 9 },
{ key: '0', matrix_id: 10 },
{ key: 'minus', matrix_id: 11 },
{ key: 'equals', matrix_id: 12 },
{ key: 'backspace', matrix_id: 13 },
{ key: 'tab', matrix_id: 14 },
{ key: 'q', matrix_id: 15 },
{ key: 'w', matrix_id: 16 },
{ key: 'e', matrix_id: 17 },
{ key: 'r', matrix_id: 18 },
{ key: 't', matrix_id: 19 },
{ key: 'y', matrix_id: 20 },
{ key: 'u', matrix_id: 21 },
{ key: 'i', matrix_id: 22 },
{ key: 'o', matrix_id: 23 },
{ key: 'p', matrix_id: 24 },
{ key: 'lbracket', matrix_id: 25 },
{ key: 'rbracket', matrix_id: 26 },
{ key: 'backslash', matrix_id: 27 },
{ key: 'caps', matrix_id: 28 },
{ key: 'a', matrix_id: 29 },
{ key: 's', matrix_id: 30 },
{ key: 'd', matrix_id: 31 },
{ key: 'f', matrix_id: 32 },
{ key: 'g', matrix_id: 33 },
{ key: 'h', matrix_id: 34 },
{ key: 'j', matrix_id: 35 },
{ key: 'k', matrix_id: 36 },
{ key: 'l', matrix_id: 37 },
{ key: 'semicolon', matrix_id: 38 },
{ key: 'apostrophe', matrix_id: 39 },
{ key: 'enter', matrix_id: 40 },
{ key: 'deadkey1', matrix_id: null },
{ key: 'leftshift', matrix_id: 41 },
{ key: 'deadkey2', matrix_id: null },
{ key: 'z', matrix_id: 42 },
{ key: 'x', matrix_id: 43 },
{ key: 'c', matrix_id: 44 },
{ key: 'v', matrix_id: 45 },
{ key: 'b', matrix_id: 46 },
{ key: 'n', matrix_id: 47 },
{ key: 'm', matrix_id: 48 },
{ key: 'comma', matrix_id: 49 },
{ key: 'dot', matrix_id: 50 },
{ key: 'slash', matrix_id: 51 },
{ key: 'rightshift', matrix_id: 52 },
{ key: 'deadkey3', matrix_id: null },
{ key: 'leftctrl', matrix_id: 53 },
{ key: 'deadkey4', matrix_id: null },
{ key: 'leftsuper', matrix_id: 54 },
{ key: 'leftalt', matrix_id: 55 },
{ key: 'deadkey5', matrix_id: null },
{ key: 'daedkey6', matrix_id: null },
{ key: 'space', matrix_id: 56 },
{ key: 'deadkey7', matrix_id: null },
{ key: 'deadkey8', matrix_id: null },
{ key: 'rightalt', matrix_id: 57 },
{ key: 'fn', matrix_id: 58 },
{ key: 'context', matrix_id: 59 },
{ key: 'rightctrl', matrix_id: 60 },
{ key: 'deadkey9', matrix_id: null },
];
}

setMultiColorLed(arrayOfRgbValues) {
const messages = this.generateMultiColor(arrayOfRgbValues);
setMultiColorLed(ledMatrix) {
const ledMatrixFlattened = ledMatrix.flat();
const arrayOfRgbValues = this.AnnePro2Layout.map((key) => {
if (key.matrix_id === null) {
return [0, 0, 0];
} else {
return ledMatrixFlattened[key.matrix_id];
}
});
const messages = this.generateMultiColor(arrayOfRgbValues.flat());

let sentBytes = 0;
for (let i = 0; i < messages.length; i++) {
sentBytes += this.write(messages[i]);
}
return sentBytes;
// for (let i = 0; i < messages.length; i++) {
// this.keyboard.write(messages[i]);
// console.log(messages[i])
// }
}

setSingleColorLed(rgb) {
Expand All @@ -45,11 +122,11 @@ class LEDController {
// Reverse engineered from ObinsKit
generateMultiColor(
arrayOfRgbValues,
usb_host = 65,
mcu_address = 65,
command_info = [32, 3, 255, 2]
) {
const maxMessageLength = 55 - command_info.length,
service_data = [0, 123, 16, usb_host],
service_data = [0, 123, 16, mcu_address],
static_message = [0, 0, 125],
arrayOfRgbValuesCopy = arrayOfRgbValues.slice(0),
messagesToSendAmount = Math.ceil(
Expand All @@ -75,16 +152,15 @@ class LEDController {
return hid_command;
}

generateOneColor(rbg_color, usb_host = 65) {
return [0, 123, 16, usb_host, 16, 7, 0, 0, 125, 32, 3, 255, 1].concat(
generateOneColor(rbg_color, mcu_address = 65) {
return [0, 123, 16, mcu_address, 16, 7, 0, 0, 125, 32, 3, 255, 1].concat(
rbg_color
);
}

// This is required because the keyboard doesn't understand commands sent faster than 50ms apart
write(message) {
const startTime = new Date().getTime();
while (new Date().getTime() < startTime + 50); // TODO: refactor
while (new Date().getTime() < startTime + 50);

return this.keyboard.write(message);
}
Expand Down

0 comments on commit 01176cc

Please sign in to comment.