Created
September 8, 2025 05:33
-
-
Save ecrecover/2be47386240c773a4bba8eedacaa0592 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { SerialPort } from 'serialport' | |
| /** ==== CONFIG ==== */ | |
| const PORT_PATH = '/dev/tty.usbserial-BG00L04S' // ← change to your device if needed | |
| const BAUD_RATE = 9600 | |
| /** ==== OPEN PORT ==== */ | |
| const port = new SerialPort({ | |
| path: PORT_PATH, | |
| baudRate: BAUD_RATE, | |
| dataBits: 8, | |
| stopBits: 1, | |
| parity: 'odd', | |
| }) | |
| /** ==== LED STATE (mirrors 0x94 b0 b1 b2 b3) ==== */ | |
| let ledB0 = 0x00, | |
| ledB1 = 0x00, | |
| ledB2 = 0x00, | |
| ledB3 = 0x00 | |
| function send(bytes) { | |
| const buf = Buffer.from(bytes) | |
| port.write(buf, (err) => { | |
| if (err) console.error('write error:', err.message) | |
| }) | |
| } | |
| function pushLeds() { | |
| send([0x94, ledB0, ledB1, ledB2, ledB3]) | |
| } | |
| export function clearLeds() { | |
| ledB0 = ledB1 = ledB2 = ledB3 = 0x00 | |
| pushLeds() | |
| } | |
| export function setLedBit(k, on = true) { | |
| if (k < 0x00 || k > 0x1f) return | |
| const grp = k >> 3 // 0..3 | |
| const col = k & 7 // 0..7 | |
| const bit = 7 - col // left→right | |
| const mask = 1 << bit | |
| if (grp === 0) ledB0 = on ? ledB0 | mask : ledB0 & ~mask | |
| else if (grp === 1) ledB1 = on ? ledB1 | mask : ledB1 & ~mask | |
| else if (grp === 2) ledB2 = on ? ledB2 | mask : ledB2 & ~mask | |
| else if (grp === 3) ledB3 = on ? ledB3 | mask : ledB3 & ~mask | |
| pushLeds() | |
| } | |
| export function toggleLedBit(k) { | |
| if (k < 0x00 || k > 0x1f) return | |
| const grp = k >> 3, | |
| col = k & 7, | |
| bit = 7 - col, | |
| mask = 1 << bit | |
| if (grp === 0) ledB0 ^= mask | |
| else if (grp === 1) ledB1 ^= mask | |
| else if (grp === 2) ledB2 ^= mask | |
| else if (grp === 3) ledB3 ^= mask | |
| pushLeds() | |
| } | |
| /** ==== LPFK INIT ==== */ | |
| function init() { | |
| send([0x01]) // Reset | |
| setTimeout(() => send([0x08]), 1000) // Enable | |
| } | |
| /** ==== SERIAL EVENTS ==== */ | |
| port.on('open', () => { | |
| console.log('LPFK connected on', PORT_PATH) | |
| init() | |
| }) | |
| port.on('data', (buf) => { | |
| for (const byte of buf) { | |
| if (byte <= 0x1f) { | |
| console.log(`Key code: 0x${byte.toString(16).padStart(2, '0')}`) | |
| if (byte === 0x1c) { | |
| // 特殊动画:左上 → 右下 顺序点亮 | |
| runSweepAnimation() | |
| } else { | |
| // 普通键:toggle 对应 LED | |
| toggleLedBit(byte) | |
| } | |
| } else if (byte === 0x81) { | |
| // ACK | |
| } else if (byte === 0x80) { | |
| console.warn('Retransmit requested (0x80)') | |
| } | |
| } | |
| }) | |
| function runSweepAnimation() { | |
| clearLeds() | |
| const delay = 80 // 每步延迟 ms | |
| for (let k = 0; k < 32; k++) { | |
| setTimeout(() => { | |
| setLedBit(k, true) | |
| }, k * delay) | |
| } | |
| // 结束后清空 | |
| setTimeout(() => { | |
| clearLeds() | |
| }, 32 * delay + 500) | |
| } | |
| port.on('error', (err) => { | |
| console.error('SerialPort error:', err.message) | |
| }) | |
| /** ==== OPTIONAL: simple CLI helpers ==== */ | |
| // Press Ctrl+C to turn all LEDs off before exit. | |
| function gracefulExit() { | |
| try { | |
| clearLeds() | |
| } finally { | |
| process.exit(0) | |
| } | |
| } | |
| process.on('SIGINT', gracefulExit) | |
| process.on('SIGTERM', gracefulExit) | |
| // Export a few helpers for REPL usage if you `node -i -e "import('./lpfk.js')"` | |
| export function enable() { | |
| send([0x08]) | |
| } | |
| export function disable() { | |
| send([0x09]) | |
| } | |
| export function reset() { | |
| send([0x01]) | |
| } | |
| export function readCfg() { | |
| send([0x06]) | |
| } | |
| export function setBitmap(b0, b1, b2, b3) { | |
| ledB0 = b0 & 0xff | |
| ledB1 = b1 & 0xff | |
| ledB2 = b2 & 0xff | |
| ledB3 = b3 & 0xff | |
| pushLeds() | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment