4.2 KiB
sfmacro-client
sfmacro-client is a Node.js server that acts as a bridge between a custom Raspberry Pi Pico-based Macropad and your computer. It listens for physical button presses on the Pico over a USB Serial connection and executes corresponding configurable macros (such as simulating key presses, running commands, or toggling application audio). It also controls the RGB LEDs on the Macropad based on the button state or system metrics (e.g., CPU load).
How It Works
The architecture consists of three main components:
-
Hardware (Raspberry Pi Pico)
- The Pico is connected via USB and communicates over a Serial port.
- It sends serial messages when buttons are pressed (
P,<id>) and released (R,<id>). - It receives serial messages to set the RGB LED color for each button (
C,<id>,<r>,<g>,<b>).
-
Node.js Server (
server.js)- The server auto-detects the connected Pico (by its Vendor ID
2E8A) and maintains the serial connection. - It stores the configuration in
config.json. - When a button press is detected, it triggers the configured action:
key: Uses the@nut-tree-fork/nut-jslibrary to simulate keyboard keystrokes or complex keyboard combos (e.g.,LeftControl + G).cmd: Runs arbitrary system commands using Node'schild_process.exec.mute_app: Toggles the mute state of specific applications (likefirefox.exe) using the includedSoundVolumeView.exeutility.cpu_monitor: Instead of triggering an action, a button assigned this action will constantly have its LED color updated based on the host computer's current CPU utilization (Green -> Yellow -> Orange -> Red) by polling with thesysteminformationlibrary.
- It hosts a local REST API and web server on port
3001to allow configuration changes via a frontend UI.
- The server auto-detects the connected Pico (by its Vendor ID
-
Web Interface (
ui/folder)- A Vite/React-based frontend is bundled into the
ui/distfolder and served by the Node application. - It allows the user to easily configure each of the 16 buttons, setting their action type, command/key, idle LED color, and pressed LED color.
- A Vite/React-based frontend is bundled into the
Starting the Server
There are a few ways to launch the software depending on your needs:
- Interactive Mode (Windows) (
Start-Macropad.bat): Starts the Node.js server, displays the console output, and automatically opens your default web browser to thehttp://localhost:3001configuration page. - Background Mode (Windows) (
Run-Hidden.vbs): Silently launches the Node server in the background without opening a visible command prompt window. This is ideal for adding to your Windows Startup folder for seamless background operation. - Linux Mode (
start-macropad.sh): Starts the Node.js server and automatically opens the configuration page in your default browser.
Linux Installation & Prerequisites
To run the application on Linux (e.g., Ubuntu/Debian), perform the following configuration steps:
1. Serial Port Permissions
By default, Linux limits access to serial devices (like /dev/ttyACM0). Give your user account permission to access the Pico serial port by running:
sudo usermod -a -G dialout $USER
Note: You must log out and log back in (or reboot) for this change to take effect.
2. Keyboard Simulation Dependencies (nut-js)
The keyboard simulation library requires the development header for libXtst and requires an X11 / XWayland environment (native Wayland will block synthetic input):
sudo apt-get update
sudo apt-get install libxtst-dev
3. Launching
Make the script executable and run it:
chmod +x start-macropad.sh
./start-macropad.sh
Configuration
Configuration is saved automatically to config.json when updated via the web interface.
Each of the 16 buttons has the following properties:
actionType: Can be"key","cmd","mute_app","cpu_monitor", or"none".key: The keystroke combination to send (e.g.,F20orLeftControl + G). Used for thekeyaction type.cmd: The command to execute or executable to mute. Used for thecmdandmute_appaction types.color: The default RGB LED color when the button is idle.pressedColor: The RGB LED color when the button is actively pressed down.