05-03-26

Remote Macro Trigger with WebSocket

This Lua script for Rebind allows you to trigger macros on your PC from external devices using a WebSocket server. Control hardware input with custom actions defined in Lua.

rebindlua scriptmacrowebsocketremote controlhardware inputautomation

Question

Remote macro trigger: press key here, execute there

Rebind AI

Remote Macro Trigger

This script sets up a WebSocket server that listens for macro commands from external tools and executes them on your PC. Perfect for triggering macros from your phone, a stream deck, or another computer.

luau
-- rebind: min_sdk=0.1.0
-- rebind: name=Remote Macro Trigger
-- rebind: permission=net

local cfg = UI.Schema({
    port = UI.Slider(9001, { min = 1024, max = 65535, label = "WebSocket Port" }),
    enabled = UI.Toggle(true, { label = "Server Enabled" }),
})

local server = nil
local macros = {}

-- Define your macros here
function OnStart()
    macros = {
        ["click"] = function()
            HID.Press("Mouse1")
        end,
        ["double_click"] = function()
            Run(function()
                HID.Press("Mouse1", 30)
                Sleep(50)
                HID.Press("Mouse1", 30)
            end)
        end,
        ["copy"] = function()
            Run(function() HID.Press("LCtrl+C") end)
        end,
        ["paste"] = function()
            Run(function() HID.Press("LCtrl+V") end)
        end,
        ["undo"] = function()
            Run(function() HID.Press("LCtrl+Z") end)
        end,
        ["type_hello"] = function()
            Run(function() HID.Type("Hello from Rebind!") end)
        end,
    }

    if cfg.enabled then
        startServer()
    end
end

function startServer()
    server = Net.WSListen(cfg.port, {
        OnConnect = function(client)
            Log.Info("Client " .. client.id .. " connected")
            client:Send(JSON.Stringify({ status = "connected", id = client.id }))
        end,

        OnMessage = function(client, payload, is_binary)
            local req = JSON.Parse(payload)

            if req.action and macros[req.action] then
                Log.Info("Executing macro: " .. req.action)
                macros[req.action]()

                -- echo back confirmation
                client:Send(JSON.Stringify({
                    id = req.id,
                    action = req.action,
                    status = "executed",
                }))
            else
                client:Send(JSON.Stringify({
                    id = req.id,
                    status = "error",
                    message = "Unknown macro: " .. (req.action or "nil"),
                }))
            end
        end,

        OnClose = function(client)
            Log.Info("Client " .. client.id .. " disconnected")
        end,
    })

    Log.Info("Remote macro server listening on ws://0.0.0.0:" .. cfg.port)
    UI.Notify("Server started on port " .. cfg.port, "success")
end

function OnStop()
    if server then
        server:Stop()
        Log.Info("Server stopped")
    end
end

How it works

  1. Server startup: When the script loads, it opens a WebSocket server on the configured port (default 9001).
  2. Macro registry: The macros table maps action names to Lua functions. Each function executes when triggered.
  3. Client connection: External tools (Python, Node.js, mobile apps, stream decks) connect via ws://your-pc-ip:9001.
  4. Message format: Send JSON with an action field:
json
   { "id": 1, "action": "copy"}
   
  1. Response: The server echoes back confirmation:
json
   { "id": 1, "action": "copy", "status": "executed"}
   

Client examples

Python (websocket-client):

python
import json
from websocket import create_connection

ws = create_connection("ws://127.0.0.1:9001")
print(ws.recv())  # "connected"

ws.send(json.dumps({"id": 1, "action": "copy"}))
print(ws.recv())  # "executed"

ws.send(json.dumps({"id": 2, "action": "paste"}))
print(ws.recv())

Node.js (ws):

javascript
const WebSocket = require('ws');

const ws = new WebSocket('ws://127.0.0.1:9001');

ws.on('open', () => {
    ws.send(JSON.stringify({ id: 1, action: 'click' }));
});

ws.on('message', (data) => {
    console.log(JSON.parse(data));
});

JavaScript (browser):

javascript
const ws = new WebSocket('ws://your-pc-ip:9001');

ws.onopen = () => {
    ws.send(JSON.stringify({ id: 1, action: 'type_hello' }));
};

ws.onmessage = (event) => {
    console.log(JSON.parse(event.data));
};

Customization

Add your own macros to the macros table:

luau
macros["my_sequence"] = function()
    Run(function()
        HID.Down("W")
        Sleep(500)
        HID.Up("W")
        Sleep(200)
        HID.Press("Space")
    end)
end

Then trigger it with:

json
{ "action": "my_sequence"}