# 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: 1. **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,`) and released (`R,`). - It receives serial messages to set the RGB LED color for each button (`C,,,,`). 2. **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-js` library to simulate keyboard keystrokes or complex keyboard combos (e.g., `LeftControl + G`). - **`cmd`**: Runs arbitrary system commands using Node's `child_process.exec`. - **`mute_app`**: Toggles the mute state of specific applications (like `firefox.exe`) using the included `SoundVolumeView.exe` utility. - **`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 the `systeminformation` library. - It hosts a local REST API and web server on port `3001` to allow configuration changes via a frontend UI. 3. **Web Interface (`ui/` folder)** - A Vite/React-based frontend is bundled into the `ui/dist` folder 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. ## 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 the `http://localhost:3001` configuration 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: ```bash 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): ```bash sudo apt-get update sudo apt-get install libxtst-dev ``` ### 3. Launching Make the script executable and run it: ```bash 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., `F20` or `LeftControl + G`). Used for the `key` action type. - `cmd`: The command to execute or executable to mute. Used for the `cmd` and `mute_app` action types. - `color`: The default RGB LED color when the button is idle. - `pressedColor`: The RGB LED color when the button is actively pressed down.