260 lines
10 KiB
JavaScript
260 lines
10 KiB
JavaScript
/*
|
|
QR code server protocol:
|
|
https://macro-deck.app/quick-setup/
|
|
+
|
|
{"instanceName":"DESKTOP-J09EM3G","networkInterfaces":["192.168.1.134"],"port":8191,"ssl":false,"token":"vPl4Vq7v"} in base64
|
|
=
|
|
https://macro-deck.app/quick-setup/eyJpbnN0YW5jZU5hbWUiOiJERVNLVE9QLUowOUVNM0ciLCJuZXR3b3JrSW50ZXJmYWNlcyI6WyIxOTIuMTY4LjEuMTM0Il0sInBvcnQiOjgxOTEsInNzbCI6ZmFsc2UsInRva2VuIjoidlBsNFZxN3YifQ==
|
|
|
|
Device types: Web - Android
|
|
Newer android app (3.3.0) identifies as web (no device settings control)
|
|
Github version (2.4.1-beta) identifies as Android (brightness, auto-connection,keep awake contrll)
|
|
|
|
Start WebSocket server
|
|
Server broadcasts connection data via UDP: {"computer-name": "MDServer","ip-address": "192.168.1.133","port": 8191}
|
|
Client gets
|
|
|
|
Client connects to websocket server
|
|
Client sends: {"Method": "CONNECTED","Client-Id": "CLIENTNAME","API": "20","Device-Type": "Android"}
|
|
Server responds with: {"Method": "GET_CONFIG","Rows": 2,"Columns": 2,"ButtonSpacing": 10,"ButtonRadius": 10,"ButtonBackground": true,"Brightness": 0.3,"AutoConnect": false,"WakeLock": "Connected","SupportButtonReleaseLongPress": true}
|
|
Client sends: {Method: 'GET_BUTTONS'}
|
|
Server responds with: {"Method": "GET_BUTTONS","Buttons": [{"IconBase64": "","Position_X": 0,"Position_Y": 0,"LabelBase64": "","BackgroundColorHex": "#232323"}]}
|
|
Client sends on button press: { "Method": "BUTTON_PRESS", "Message": "0_0" } (X_Y)
|
|
Server can respond with single button updates: {"Method": "UPDATE_BUTTON","Buttons": [{"IconBase64": "","Position_X": 0,"Position_Y": 0,"LabelBase64": "","BackgroundColorHex": "#000000"}]}
|
|
|
|
- Server can resend "GET_BUTTONS" at any moment to update setup
|
|
- Server can resend "GET_CONFIG" at any moment to control client
|
|
- Server can "UPDATE_BUTTON" in any moment
|
|
*/
|
|
|
|
function generateQR(ServerName, ServerIP, token, ServerPort = 8191) {
|
|
const qrcode = require('qrcode-terminal');
|
|
// it generates the exact same link as the official one, but it does not work (?)
|
|
var obj = {
|
|
"instanceName": ServerName,
|
|
"networkInterfaces": ServerIP,
|
|
"port": ServerPort,
|
|
"ssl": false,
|
|
"token": token
|
|
}
|
|
var url = "https://macro-deck.app/quick-setup/" + Buffer.from(JSON.stringify(obj)).toString('base64');
|
|
console.log(url)
|
|
qrcode.generate(url, { small: true }, function (qrcode) {
|
|
console.log(qrcode);
|
|
});
|
|
}
|
|
|
|
var clients = {}
|
|
function broadcastServer(ServerName, ServerIP, BroadcastPort = 8191, BroadcastAddress = '255.255.255.255') {
|
|
const dgram = require('dgram');
|
|
const udpClient = dgram.createSocket('udp4');
|
|
|
|
udpClient.bind(() => {
|
|
udpClient.setBroadcast(true);
|
|
});
|
|
|
|
setInterval(() => {
|
|
try {
|
|
const broadcastObject = {
|
|
"computer-name": ServerName,
|
|
"ip-address": ServerIP,
|
|
"port": BroadcastPort
|
|
};
|
|
|
|
const message = Buffer.from(JSON.stringify(broadcastObject));
|
|
udpClient.send(message, 0, message.length, BroadcastPort, BroadcastAddress, (err) => {
|
|
if (err) console.error(err);
|
|
});
|
|
} catch (error) {
|
|
console.error(error);
|
|
}
|
|
}, 5000);
|
|
}
|
|
|
|
function startWsServer(ServerPort = 8191) {
|
|
const { WebSocketServer } = require("ws");
|
|
const wss = new WebSocketServer({ port: ServerPort })
|
|
wss.on('connection', function connection(ws, req) {
|
|
const ip = req.socket.remoteAddress;
|
|
ws.on('error', console.error)
|
|
ws.on('message', function message(data) {
|
|
data = JSON.parse(data)
|
|
console.log(ip, data);
|
|
switch (data.Method) {
|
|
case "CONNECTED":
|
|
clients[data["Client-Id"]] = ip.replace("::ffff:", "");
|
|
//on "CONNECTED" request, send the grid setup, and client settings
|
|
var obj = JSON.stringify({
|
|
"Method": "GET_CONFIG",
|
|
"Rows": 6,
|
|
"Columns": 8,
|
|
"ButtonSpacing": 2,
|
|
"ButtonRadius": 10,
|
|
"ButtonBackground": true,
|
|
"Brightness": 0.5, // 0.1 -> 1.0
|
|
"AutoConnect": true, // true - false
|
|
"WakeLock": "Connected", //Never - Connected - Always
|
|
"SupportButtonReleaseLongPress": true
|
|
})
|
|
ws.send(obj);
|
|
break;
|
|
|
|
case "GET_BUTTONS":
|
|
//Client will request the buttons content and their position in the setup
|
|
var obj = JSON.stringify({
|
|
"Method": "GET_BUTTONS",
|
|
"Buttons": [
|
|
{
|
|
"IconBase64": "",
|
|
"Position_X": 1,
|
|
"Position_Y": 0,
|
|
"LabelBase64": "",
|
|
"BackgroundColorHex": "#232323"
|
|
},
|
|
{
|
|
"IconBase64": "",
|
|
"Position_X": 0,
|
|
"Position_Y": 0,
|
|
"LabelBase64": "",
|
|
"BackgroundColorHex": "#232323"
|
|
},
|
|
{
|
|
"IconBase64": "",
|
|
"Position_X": 1,
|
|
"Position_Y": 1,
|
|
"LabelBase64": "",
|
|
"BackgroundColorHex": "#232323"
|
|
},
|
|
{
|
|
"IconBase64": "",
|
|
"Position_X": 0,
|
|
"Position_Y": 1,
|
|
"LabelBase64": "",
|
|
"BackgroundColorHex": "#232323"
|
|
}
|
|
]
|
|
})
|
|
ws.send(obj);
|
|
break;
|
|
case "BUTTON_PRESS":
|
|
var obj = JSON.stringify({
|
|
"Method": "UPDATE_BUTTON",
|
|
"Buttons": [
|
|
{
|
|
"IconBase64": "",
|
|
"Position_X": 0,
|
|
"Position_Y": 0,
|
|
"LabelBase64": "",
|
|
"BackgroundColorHex": "#000000"
|
|
}
|
|
]
|
|
})
|
|
// broadcast update to all clients
|
|
wss.clients.forEach(function each(client) {
|
|
if (client.readyState === WebSocket.OPEN) {
|
|
client.send(obj);
|
|
}
|
|
});
|
|
var obj = JSON.stringify({
|
|
"Method": "UPDATE_BUTTON",
|
|
"Buttons": [
|
|
{
|
|
"IconBase64": "",
|
|
"Position_X": 7,
|
|
"Position_Y": 5,
|
|
"LabelBase64": "",
|
|
"BackgroundColorHex": "#000000"
|
|
}
|
|
]
|
|
})
|
|
wss.clients.forEach(function each(client) {
|
|
if (client.readyState === WebSocket.OPEN) {
|
|
client.send(obj);
|
|
}
|
|
});
|
|
|
|
//ws.send(obj)
|
|
console.log(data.Method, data.Message.split('_'))
|
|
break;
|
|
case "BUTTON_RELEASE":
|
|
var obj = JSON.stringify({
|
|
"Method": "UPDATE_BUTTON",
|
|
"Buttons": [
|
|
{
|
|
"IconBase64": "",
|
|
"Position_X": 0,
|
|
"Position_Y": 0,
|
|
"LabelBase64": "",
|
|
"BackgroundColorHex": "#FFFFFF"
|
|
}
|
|
]
|
|
})
|
|
wss.clients.forEach(function each(client) {
|
|
if (client.readyState === WebSocket.OPEN) {
|
|
client.send(obj);
|
|
}
|
|
});
|
|
var obj = JSON.stringify({
|
|
"Method": "UPDATE_BUTTON",
|
|
"Buttons": [
|
|
{
|
|
"IconBase64": "",
|
|
"Position_X": 7,
|
|
"Position_Y": 5,
|
|
"LabelBase64": "",
|
|
"BackgroundColorHex": "#FFFFFF"
|
|
}
|
|
]
|
|
})
|
|
wss.clients.forEach(function each(client) {
|
|
if (client.readyState === WebSocket.OPEN) {
|
|
client.send(obj);
|
|
}
|
|
});
|
|
//ws.send(obj);
|
|
console.log(data.Method, data.Message.split('_'))
|
|
break;
|
|
case "BUTTON_LONG_PRESS":
|
|
console.log(data.Method, data.Message.split('_'))
|
|
break;
|
|
case "BUTTON_LONG_PRESS_RELEASE":
|
|
console.log(data.Method, data.Message.split('_'))
|
|
break;
|
|
default:
|
|
console.log(data);
|
|
break;
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
function startWsClient(ip, port = 8191) {
|
|
const WebSocket = require("ws");
|
|
const fs = require("fs");
|
|
const ws = new WebSocket("ws://" + ip + ":" + port);
|
|
ws.on('error', console.error);
|
|
|
|
ws.on('open', function open() {
|
|
|
|
var obj = JSON.stringify({
|
|
"Method": "CONNECTED",
|
|
"Client-Id": "LinuxClient",
|
|
"API": "20",
|
|
"Device-Type": "Android" //Web - Android
|
|
});
|
|
ws.send(obj);
|
|
});
|
|
var logs = { data: [] }
|
|
ws.on('message', function message(data) {
|
|
console.log('received: %s', data);
|
|
//logs.data.push(JSON.parse(data));
|
|
//fs.writeFileSync("test.json", JSON.stringify(logs), 'utf8', null);
|
|
});
|
|
}
|
|
|
|
//generateQR("DESKTOP-J09EM3G", ["192.168.1.134"], "vPl4Vq7v");
|
|
//startWsClient("192.168.1.134");
|
|
|
|
broadcastServer("DEBIAN-PC", "192.168.1.133");
|
|
|
|
startWsServer(); |