-
-
Save Overemployed/3595853329092ccff5fa2990c5dbde20 to your computer and use it in GitHub Desktop.
// assumes your mouse is in relative mode https://docs.pikvm.org/mouse/?h=relative#relative-mouse-on-v2-platform-otg-hid | |
// You may want to set your pikvm to support dual mode, so you can switch between absolute and relative | |
const { PIKVM_HOST, PIKVM_USER, PIKVM_PASSWORD, MOUSE_MODE = 'normal' } = process.env | |
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0; | |
import fetch from 'node-fetch'; | |
import { path } from "ghost-cursor"; | |
import websocket from 'websocket'; | |
const WebSocketClient = websocket.client | |
let connection; | |
let previous = { | |
x: 0, | |
y: 0 | |
} | |
let begin = true; | |
async function tracePath(vectors) { | |
const isPixelMode = MOUSE_MODE === 'pixel' | |
if (isPixelMode) { | |
const randomDirection = randomValue(1, 4) | |
let x = 0; | |
let y = 0; | |
switch (randomDirection) { | |
case 1: | |
x = 1 | |
y = 0 | |
break; | |
case 2: | |
x = -1 | |
y = 0 | |
break; | |
case 3: | |
x = 0 | |
y = 1 | |
break; | |
case 4: | |
default: | |
x = 0 | |
y = -1 | |
break; | |
} | |
await sendMouse({ x, y }); | |
await wait(randomValue(600, 5000)); | |
return | |
} | |
for (const v of vectors) { | |
const x = Math.floor(previous.x - v.x) | |
const y = Math.floor(previous.y - v.y) | |
try { | |
await sendMouse({ x, y }); | |
await wait(randomValue(10, 30)); | |
previous = v; | |
} catch (error) { | |
console.log(error.message); | |
} | |
} | |
} | |
async function sendMouse({ x, y }) { | |
console.log(x, y) | |
connection.send(`{ | |
"event_type":"mouse_relative", | |
"event":{ | |
"delta":[ | |
{"x":${x},"y":${y}} | |
], | |
"squash":true | |
} | |
}`) | |
} | |
async function connectTo() { | |
const client = new WebSocketClient(); | |
client.on('connectFailed', function(error) { | |
console.log('Connect Error: ' + error.toString()); | |
connectTo() | |
}); | |
client.on('connect', async function(conn) { | |
connection = conn | |
console.log(`Connected`); | |
connection.on('error', function(error) { | |
console.log(`Connection Error: ` + error.toString()); | |
connectTo() | |
}); | |
connection.on('close', function() { | |
console.log(`echo-protocol Connection Closed`); | |
connectTo() | |
}); | |
if (connection.connected) { | |
await updateMouseMode(true) | |
while (true) { | |
try { | |
const from = begin ? getRandomPoint() : previous | |
begin = false | |
await wait(randomValue(20, 5000)); | |
const to = getRandomPoint(); | |
const pathV = path(from, to); | |
await tracePath(pathV, connection); | |
} catch (e) { | |
console.log('Warning: stopping random mouse movements', e); | |
} | |
} | |
} | |
}) | |
await wait(1000) | |
console.log(`connectiong to ${PIKVM_HOST}, ${PIKVM_USER}, ${PIKVM_PASSWORD}`) | |
client.connect(`wss://${PIKVM_HOST}/api/ws?stream=0`, '', '', { | |
'X-KVMD-User': PIKVM_USER, | |
'X-KVMD-Passwd': PIKVM_PASSWORD | |
}) | |
} | |
function randomValue(min, max) { | |
min = Math.ceil(min); | |
max = ~~max; | |
return ~~(Math.random() * (max - min)) + min; | |
} | |
async function updateMouseMode(on) { | |
await fetch( | |
`https://${PIKVM_HOST}/api/hid/set_params?mouse_output=${on ? 'usb_rel' : 'usb'}` | |
, { | |
"headers": { | |
'X-KVMD-User': PIKVM_USER, | |
'X-KVMD-Passwd': PIKVM_PASSWORD | |
}, | |
"method": "POST" | |
}); | |
} | |
function getRandomPoint(){ | |
const height = 1920 | |
const width = 1080 | |
let paddingPercentage = 1 | |
const paddingWidth = (width * paddingPercentage) / 100; | |
const paddingHeight = (height * paddingPercentage) / 100; | |
const x = 0+ paddingWidth / 2 + Math.random() * (width - paddingWidth) | |
const y = 0+ paddingHeight / 2 + Math.random() * (height - paddingHeight) | |
return { | |
x: Math.floor(x), | |
y: Math.floor(y) | |
}; | |
} | |
function wait(time){ | |
return new Promise((resolve)=>{ | |
setTimeout(resolve, time) | |
}) | |
} | |
connectTo() |
{ | |
"name": "jiggler", | |
"version": "1.0.0", | |
"description": "", | |
"main": "jiggler.mjs", | |
"scripts": { | |
"test": "echo \"Error: no test specified\" && exit 1" | |
}, | |
"author": "", | |
"license": "ISC", | |
"dependencies": { | |
"ghost-cursor": "^1.1.15", | |
"node-fetch": "^3.2.10", | |
"websocket": "^1.0.34" | |
} | |
} |
This does NOT work on PiKVM, do not install it and expect it to work. Unknown why this does not work.
Windows does not work, at least not in the same way.
Spinning up an Ubuntu VM might be the best to use in this case. But it does work.
This is working for me with 2 PiKVM's
I am using a Mac Studio (M1 Max, 32GB)
Steps to take before running the script
- You need to set your PiKVM to be dual mode (reference the PiKVM docs which are linked above)
- You need to have Node & npm installed on your system (the one thats connecting to the pikvms)
- create a folder and put the two provided files inside
- run
npm i
to get the dependencies - run
node jiggler.mjs
to run the script
I would recommend when running jiggler.mjs you follow the above example where you provide the host, user & password.
Note: I've only tested/used MOUSE_MODE=normal.
I've also written a quick little script that puts my mouse mode back to absolute which can be done with pretty much the existing code in the jiggler.mjs script.
@overemployedswe Can you provide this script and how its used?
@arch1mede to set the mouse mode back to absolute I'm using this script here which was pretty much taken from the main jiggle script but I stripped everything jiggle related out:
const { PIKVM_HOST, PIKVM_USER, PIKVM_PASSWORD } = process.env;
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0;
import fetch from "node-fetch";
async function updateMouseMode() {
try {
await fetch(`https://${PIKVM_HOST}/api/hid/set_params?mouse_output=usb`, {
headers: {
"X-KVMD-User": PIKVM_USER,
"X-KVMD-Passwd": PIKVM_PASSWORD,
},
method: "POST",
});
} catch (e) {
console.log("ERROR: ", e);
}
}
updateMouseMode();
You call this script the exact same way you call the jiggler script by passing in the env variables nessecary, then when you run the script it makes an api call to the pikvm to set the mouse mode to absolute so its back to normal.
I don't have it yet but I plan to build an orchestration api to start & stop mouse jigglers via an api call so that I can utilize macropads to handle these scripts rather than needing to actually run a script in my terminal.
Installation
Tested using NodeJS 16 and on my personal Macbook Pro. Some have reported they could not get this working on the PiKVM so I recommend you to install this script on your personal computer.
NodeJS version 16 or greater is required
After downloading both jiggler.mjs and package.json to a folder, run
npm install
to install the dependencies.Notes
Currently this script will attempt to set the mouse mode to relative before running, however the mouse will not move unless you configure your pikvm to use relative mode. This script expects your PIKVM to be in dual mode which allows you to switch between relative and absolute mose modes. Read more here
When the script runs it will try to switch to relative mode for you but only after you have changed your PIKVM config to dual mode.
How to run
In the terminal you'll run the following
Explanation of the environment variables
PIKVM_HOST
is the domain you use to access the pikvm. This can also be an ip address.PIKVM_USER
is the user for the pikvm.PIVKM_PASSWORD
is the password for the pikvm.MOUSE_MODE
can beMOUSE_MODE=normal
orMOUSE_MODE=pixel
. Use pixel mode if you want the mouse to move 1 pixel every few seconds.