new file: .gitignore
new file: main.js new file: package-lock.json new file: package.json
This commit is contained in:
136
.gitignore
vendored
Normal file
136
.gitignore
vendored
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
.pnpm-debug.log*
|
||||||
|
|
||||||
|
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||||
|
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||||
|
|
||||||
|
# Runtime data
|
||||||
|
pids
|
||||||
|
*.pid
|
||||||
|
*.seed
|
||||||
|
*.pid.lock
|
||||||
|
|
||||||
|
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||||
|
lib-cov
|
||||||
|
|
||||||
|
# Coverage directory used by tools like istanbul
|
||||||
|
coverage
|
||||||
|
*.lcov
|
||||||
|
|
||||||
|
# nyc test coverage
|
||||||
|
.nyc_output
|
||||||
|
|
||||||
|
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||||
|
.grunt
|
||||||
|
|
||||||
|
# Bower dependency directory (https://bower.io/)
|
||||||
|
bower_components
|
||||||
|
|
||||||
|
# node-waf configuration
|
||||||
|
.lock-wscript
|
||||||
|
|
||||||
|
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||||
|
build/Release
|
||||||
|
|
||||||
|
# Dependency directories
|
||||||
|
node_modules/
|
||||||
|
jspm_packages/
|
||||||
|
|
||||||
|
# Snowpack dependency directory (https://snowpack.dev/)
|
||||||
|
web_modules/
|
||||||
|
|
||||||
|
# TypeScript cache
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# Optional npm cache directory
|
||||||
|
.npm
|
||||||
|
|
||||||
|
# Optional eslint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Optional stylelint cache
|
||||||
|
.stylelintcache
|
||||||
|
|
||||||
|
# Microbundle cache
|
||||||
|
.rpt2_cache/
|
||||||
|
.rts2_cache_cjs/
|
||||||
|
.rts2_cache_es/
|
||||||
|
.rts2_cache_umd/
|
||||||
|
|
||||||
|
# Optional REPL history
|
||||||
|
.node_repl_history
|
||||||
|
|
||||||
|
# Output of 'npm pack'
|
||||||
|
*.tgz
|
||||||
|
|
||||||
|
# Yarn Integrity file
|
||||||
|
.yarn-integrity
|
||||||
|
|
||||||
|
# dotenv environment variable files
|
||||||
|
.env
|
||||||
|
.env.development.local
|
||||||
|
.env.test.local
|
||||||
|
.env.production.local
|
||||||
|
.env.local
|
||||||
|
|
||||||
|
# parcel-bundler cache (https://parceljs.org/)
|
||||||
|
.cache
|
||||||
|
.parcel-cache
|
||||||
|
|
||||||
|
# Next.js build output
|
||||||
|
.next
|
||||||
|
out
|
||||||
|
|
||||||
|
# Nuxt.js build / generate output
|
||||||
|
.nuxt
|
||||||
|
dist
|
||||||
|
|
||||||
|
# Gatsby files
|
||||||
|
.cache/
|
||||||
|
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||||
|
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||||
|
# public
|
||||||
|
|
||||||
|
# vuepress build output
|
||||||
|
.vuepress/dist
|
||||||
|
|
||||||
|
# vuepress v2.x temp and cache directory
|
||||||
|
.temp
|
||||||
|
.cache
|
||||||
|
|
||||||
|
# vitepress build output
|
||||||
|
**/.vitepress/dist
|
||||||
|
|
||||||
|
# vitepress cache directory
|
||||||
|
**/.vitepress/cache
|
||||||
|
|
||||||
|
# Docusaurus cache and generated files
|
||||||
|
.docusaurus
|
||||||
|
|
||||||
|
# Serverless directories
|
||||||
|
.serverless/
|
||||||
|
|
||||||
|
# FuseBox cache
|
||||||
|
.fusebox/
|
||||||
|
|
||||||
|
# DynamoDB Local files
|
||||||
|
.dynamodb/
|
||||||
|
|
||||||
|
# TernJS port file
|
||||||
|
.tern-port
|
||||||
|
|
||||||
|
# Stores VSCode versions used for testing VSCode extensions
|
||||||
|
.vscode-test
|
||||||
|
|
||||||
|
# yarn v2
|
||||||
|
.yarn/cache
|
||||||
|
.yarn/unplugged
|
||||||
|
.yarn/build-state.yml
|
||||||
|
.yarn/install-state.gz
|
||||||
|
.pnp.*
|
||||||
261
main.js
Normal file
261
main.js
Normal file
@@ -0,0 +1,261 @@
|
|||||||
|
/*
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
|
||||||
|
var clients = {}
|
||||||
|
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
46
package-lock.json
generated
Normal file
46
package-lock.json
generated
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"name": "macrodeckreimp",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "macrodeckreimp",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"qrcode-terminal": "^0.12.0",
|
||||||
|
"ws": "^8.18.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/qrcode-terminal": {
|
||||||
|
"version": "0.12.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz",
|
||||||
|
"integrity": "sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ==",
|
||||||
|
"bin": {
|
||||||
|
"qrcode-terminal": "bin/qrcode-terminal.js"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ws": {
|
||||||
|
"version": "8.18.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
|
||||||
|
"integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"bufferutil": "^4.0.1",
|
||||||
|
"utf-8-validate": ">=5.0.2"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"bufferutil": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"utf-8-validate": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
15
package.json
Normal file
15
package.json
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"name": "macrodeckreimp",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"description": "",
|
||||||
|
"dependencies": {
|
||||||
|
"qrcode-terminal": "^0.12.0",
|
||||||
|
"ws": "^8.18.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user