154 lines
3.6 KiB
JavaScript
154 lines
3.6 KiB
JavaScript
const path = require("node:path");
|
|
const fs = require("node:fs");
|
|
const http = require("node:http");
|
|
const ws = require("ws");
|
|
|
|
let driver;
|
|
let mappings;
|
|
|
|
const webServer = new http.Server();
|
|
|
|
const socketServer = new ws.WebSocketServer({
|
|
"noServer": true
|
|
});
|
|
|
|
function sendToClients(message) {
|
|
socketServer.clients.forEach(function (client) {
|
|
if (client.readyState === ws.OPEN) {
|
|
client.send(message);
|
|
}
|
|
});
|
|
}
|
|
|
|
webServer.on("request", function (request, response) {
|
|
switch (request.method) {
|
|
case "GET":
|
|
switch (request.url) {
|
|
default:
|
|
var filePath = path.join(__dirname, "view", request.url);
|
|
|
|
if (!fs.existsSync(filePath)) {
|
|
response.writeHead(404);
|
|
return response.end("No entry. ");
|
|
}
|
|
|
|
if (fs.statSync(filePath).isDirectory()) {
|
|
var entryPath = path.join(filePath, "index.html");
|
|
|
|
if (!fs.existsSync(entryPath)) {
|
|
response.writeHead(404);
|
|
return response.end("No entry. ");
|
|
}
|
|
|
|
response.writeHead(200);
|
|
fs.createReadStream(entryPath).pipe(response);
|
|
} else {
|
|
response.writeHead(200);
|
|
fs.createReadStream(filePath).pipe(response);
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
response.writeHead(404);
|
|
return response.end("No entry. ");
|
|
break;
|
|
}
|
|
});
|
|
|
|
webServer.on("upgrade", function (request, socket, head) {
|
|
if (request.url === "/socket") {
|
|
socketServer.handleUpgrade(request, socket, head, function (ws) {
|
|
socketServer.emit("connection", ws, request);
|
|
});
|
|
} else {
|
|
socket.destroy();
|
|
}
|
|
});
|
|
|
|
socketServer.on("connection", function (socket) {
|
|
socket.on("error", console.error);
|
|
|
|
socket.on("message", function (event) {
|
|
var data = JSON.parse(event);
|
|
|
|
switch (data.event) {
|
|
case "load-driver":
|
|
if (driver) {
|
|
driver.close();
|
|
delete driver;
|
|
}
|
|
|
|
var driverPath = path.join(__dirname, "drivers", path.basename(data.data.name) + ".js");
|
|
driver = require(driverPath);
|
|
break;
|
|
case "load-mappings":
|
|
if (mappings) {
|
|
delete mappings;
|
|
}
|
|
|
|
var mappingsPath = path.join(__dirname, "mappings", path.basename(data.data.name) + ".json");
|
|
mappings = JSON.parse(fs.readFileSync(mappingsPath));
|
|
break;
|
|
case "list-devices":
|
|
socket.send(JSON.stringify({
|
|
"event": "device-list",
|
|
"data": {
|
|
"devices": driver.list()
|
|
}
|
|
}));
|
|
break;
|
|
case "open-device":
|
|
driver.open(data.data.name, function (message) {
|
|
var byteArray = new Array(...message);
|
|
var hexStringifiedMessage = byteArray.map(b => b.toString(16)).map(c => ("00".substring(c.length) + c)).join(" ");
|
|
|
|
for (var mappingRegExpString in mappings.inbound) {
|
|
if (mappings.inbound.hasOwnProperty(mappingRegExpString)) {
|
|
var mappingRegExp = new RegExp(mappingRegExpString);
|
|
|
|
var mappingMatches = hexStringifiedMessage.match(mappingRegExp);
|
|
if (!mappingMatches) continue;
|
|
|
|
var mappingName = mappings.inbound[mappingRegExpString];
|
|
|
|
mappingMatches.shift();
|
|
|
|
var value = parseInt(mappingMatches[0], 16);
|
|
|
|
sendToClients(JSON.stringify({
|
|
"event": "signal",
|
|
"data": {
|
|
"name": mappingName,
|
|
"value": value
|
|
}
|
|
}));
|
|
}
|
|
}
|
|
});
|
|
break;
|
|
case "control":
|
|
if (!driver) return;
|
|
if (!mappings.outbound[data.data.name]) return;
|
|
|
|
var message = mappings.outbound[data.data.name].map(function (byte) {
|
|
if (typeof byte != "number") {
|
|
return data.data.value;
|
|
} else {
|
|
return byte;
|
|
}
|
|
});
|
|
|
|
driver.send(message);
|
|
break;
|
|
case "close-device":
|
|
driver.close();
|
|
break;
|
|
default:
|
|
|
|
}
|
|
});
|
|
});
|
|
|
|
webServer.listen(23272);
|