add mame modem proxy for rockwell -> usrobotics
This commit is contained in:
361
zefie_wtvp_minisrv/modem_proxy.js
Normal file
361
zefie_wtvp_minisrv/modem_proxy.js
Normal file
@@ -0,0 +1,361 @@
|
||||
// Rockwell to USRobotics Modem Proxy for MAME Bitbanger
|
||||
const net = require('net');
|
||||
const { SerialPort } = require('serialport');
|
||||
const { ReadlineParser } = require('@serialport/parser-readline');
|
||||
|
||||
// Configuration
|
||||
const TCP_IP = '127.0.0.1';
|
||||
const TCP_PORT = 57388;
|
||||
const SERIAL_PORT = 'COM3';
|
||||
const SERIAL_BAUDRATE = 115200;
|
||||
|
||||
let NEXT_RECV_IS_LAST_ASCII = false;
|
||||
let DATA_MODE = false;
|
||||
|
||||
const THINGS_TO_STRIP = ["S95=36", "&Q5", "S51=31"];
|
||||
const THINGS_TO_REPLACE = [
|
||||
["M0", "M1"], // M1 = Speaker on
|
||||
["S11=110", "S11=50"], // S11 = Dial speed
|
||||
["S11=200", "S11=50"], // S11 = Dial speed
|
||||
["18004653537", "5736666"],
|
||||
["18006138199", "5736666"]
|
||||
];
|
||||
|
||||
// Global variables
|
||||
let serialPort = null;
|
||||
let server = null;
|
||||
let currentClient = null;
|
||||
|
||||
// Initialize serial port
|
||||
function initSerial() {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
serialPort = new SerialPort({
|
||||
path: SERIAL_PORT,
|
||||
baudRate: SERIAL_BAUDRATE,
|
||||
autoOpen: false,
|
||||
// Disable buffering for immediate data flow
|
||||
highWaterMark: 1,
|
||||
// Set minimal timeouts
|
||||
dataBits: 8,
|
||||
stopBits: 1,
|
||||
parity: 'none',
|
||||
rtscts: false,
|
||||
xon: false,
|
||||
xoff: false,
|
||||
xany: false
|
||||
});
|
||||
|
||||
serialPort.open((err) => {
|
||||
if (err) {
|
||||
console.error('Error opening serial port:', err.message);
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
console.log(`Serial port ${SERIAL_PORT} opened at ${SERIAL_BAUDRATE} baud`);
|
||||
|
||||
// Disable any internal buffering
|
||||
serialPort.set({
|
||||
brk: false,
|
||||
cts: false,
|
||||
dtr: true,
|
||||
rts: true
|
||||
});
|
||||
|
||||
// Add a small delay to ensure port is ready
|
||||
setTimeout(() => {
|
||||
resolve(serialPort);
|
||||
}, 100);
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error initializing serial port:', error);
|
||||
reject(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Reset modem to command mode and hang up
|
||||
function resetModemToCommandMode() {
|
||||
try {
|
||||
// Send escape sequence to exit data mode
|
||||
serialPort.write(Buffer.from('+++', 'ascii'));
|
||||
setTimeout(() => {
|
||||
// Send hang up command
|
||||
serialPort.write(Buffer.from('ATH\r', 'ascii'));
|
||||
console.log("Sent modem reset commands: +++ and ATH");
|
||||
}, 500);
|
||||
} catch (error) {
|
||||
console.error('Error resetting modem:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle data from socket to serial
|
||||
function handleSocketToSerial(socket) {
|
||||
let buffer = Buffer.alloc(0);
|
||||
|
||||
socket.on('data', (data) => {
|
||||
if (!DATA_MODE) {
|
||||
buffer = Buffer.concat([buffer, data]);
|
||||
|
||||
// Process commands only after receiving a complete command ending in '\r'
|
||||
// Use Buffer.indexOf to find CR byte (0x0D) for binary safety
|
||||
const crIndex = buffer.indexOf(0x0D); // '\r' = 0x0D
|
||||
|
||||
if (crIndex === -1) {
|
||||
return; // Wait for complete command
|
||||
}
|
||||
|
||||
// Extract command as buffer first, then convert to string only for processing
|
||||
const commandBuffer = buffer.slice(0, crIndex);
|
||||
let command = commandBuffer.toString('ascii').trim();
|
||||
buffer = buffer.slice(crIndex + 1);
|
||||
|
||||
// Apply string stripping and replacement
|
||||
THINGS_TO_STRIP.forEach(s => {
|
||||
command = command.replace(s, "");
|
||||
});
|
||||
|
||||
THINGS_TO_REPLACE.forEach(([find, replace]) => {
|
||||
command = command.replace(find, replace);
|
||||
});
|
||||
|
||||
const commandBytes = Buffer.from(command + '\r', 'ascii');
|
||||
console.log("WEBTV COMMAND:", commandBytes.toString('ascii').trim());
|
||||
|
||||
if (command + '\r' === 'ATD\r') {
|
||||
NEXT_RECV_IS_LAST_ASCII = true;
|
||||
console.log("ATD detected - next serial response will trigger data mode");
|
||||
}
|
||||
|
||||
try {
|
||||
serialPort.write(commandBytes, (err) => {
|
||||
if (err) {
|
||||
console.error('Error writing command to serial port:', err);
|
||||
} else {
|
||||
// Force immediate transmission of commands too
|
||||
serialPort.drain();
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error writing to serial port:', error);
|
||||
}
|
||||
} else {
|
||||
// In data mode, pass through binary data unchanged with immediate write
|
||||
try {
|
||||
serialPort.write(data, (err) => {
|
||||
if (err) {
|
||||
console.error('Error writing to serial port:', err);
|
||||
} else {
|
||||
// Force immediate transmission
|
||||
serialPort.drain((drainErr) => {
|
||||
if (drainErr) {
|
||||
console.error('Error draining serial port:', drainErr);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error writing to serial port:', error);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('error', (err) => {
|
||||
console.error('Socket error:', err);
|
||||
if (DATA_MODE) {
|
||||
console.log("Exiting data mode due to socket error");
|
||||
DATA_MODE = false;
|
||||
NEXT_RECV_IS_LAST_ASCII = false;
|
||||
resetModemToCommandMode();
|
||||
}
|
||||
});
|
||||
|
||||
socket.on('close', () => {
|
||||
console.log("Socket closed by remote");
|
||||
if (DATA_MODE) {
|
||||
console.log("Exiting data mode due to socket disconnect");
|
||||
DATA_MODE = false;
|
||||
NEXT_RECV_IS_LAST_ASCII = false;
|
||||
resetModemToCommandMode();
|
||||
}
|
||||
currentClient = null;
|
||||
});
|
||||
}
|
||||
|
||||
// Handle data from serial to socket
|
||||
function handleSerialToSocket(socket) {
|
||||
const dataHandler = (data) => {
|
||||
|
||||
// Check if we're switching to data mode
|
||||
if (!DATA_MODE && NEXT_RECV_IS_LAST_ASCII) {
|
||||
DATA_MODE = true;
|
||||
NEXT_RECV_IS_LAST_ASCII = false;
|
||||
// Provide connection result and enable data mode
|
||||
data = Buffer.from('79\r\n67\r\n19\r\n', 'ascii');
|
||||
console.log("MODEM CONNECT RESULT:", data.toString('ascii'));
|
||||
console.log("Data mode enabled");
|
||||
} else if (!DATA_MODE) {
|
||||
console.log("MODEM COMMAND RESPONSE:", data.toString('ascii'));
|
||||
}
|
||||
|
||||
// Check for disabling data mode if unsupported or exit flags are received
|
||||
// Use Buffer.equals for binary-safe comparison
|
||||
const escapeSeq = Buffer.from("+++\r", 'ascii');
|
||||
const exitCode = Buffer.from("3\r", 'ascii');
|
||||
|
||||
if (data.equals(escapeSeq) || data.equals(exitCode)) {
|
||||
console.log("Data mode disabled by serial response");
|
||||
DATA_MODE = false;
|
||||
}
|
||||
|
||||
try {
|
||||
if (socket && !socket.destroyed) {
|
||||
socket.write(data);
|
||||
} else {
|
||||
console.log("[SERIAL->SOCKET] Cannot send - socket destroyed or null");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Send error:', error);
|
||||
if (DATA_MODE) {
|
||||
console.log("Exiting data mode due to send error");
|
||||
DATA_MODE = false;
|
||||
NEXT_RECV_IS_LAST_ASCII = false;
|
||||
resetModemToCommandMode();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const errorHandler = (err) => {
|
||||
console.error('Serial port error:', err);
|
||||
if (DATA_MODE) {
|
||||
console.log("Exiting data mode due to serial error");
|
||||
DATA_MODE = false;
|
||||
NEXT_RECV_IS_LAST_ASCII = false;
|
||||
resetModemToCommandMode();
|
||||
}
|
||||
};
|
||||
|
||||
console.log("[SERIAL] Setting up data and error handlers");
|
||||
serialPort.on('data', dataHandler);
|
||||
serialPort.on('error', errorHandler);
|
||||
|
||||
// Return cleanup function
|
||||
return () => {
|
||||
console.log("[SERIAL] Cleaning up event handlers");
|
||||
serialPort.removeListener('data', dataHandler);
|
||||
serialPort.removeListener('error', errorHandler);
|
||||
};
|
||||
}
|
||||
|
||||
// Handle new client connection
|
||||
function handleClient(socket) {
|
||||
// Reset state for new connection
|
||||
DATA_MODE = false;
|
||||
NEXT_RECV_IS_LAST_ASCII = false;
|
||||
console.log("Reset modem state for new connection");
|
||||
|
||||
// Disable TCP buffering for immediate data flow
|
||||
socket.setNoDelay(true);
|
||||
socket.setTimeout(0);
|
||||
|
||||
currentClient = socket;
|
||||
|
||||
handleSocketToSerial(socket);
|
||||
const cleanupSerial = handleSerialToSocket(socket);
|
||||
|
||||
socket.on('close', () => {
|
||||
// Ensure data mode is reset when client disconnects
|
||||
if (DATA_MODE) {
|
||||
console.log("Client disconnected, exiting data mode");
|
||||
DATA_MODE = false;
|
||||
NEXT_RECV_IS_LAST_ASCII = false;
|
||||
resetModemToCommandMode();
|
||||
}
|
||||
|
||||
// Clean up serial event listeners
|
||||
cleanupSerial();
|
||||
currentClient = null;
|
||||
});
|
||||
|
||||
socket.on('error', (err) => {
|
||||
console.error('Client socket error:', err);
|
||||
cleanupSerial();
|
||||
currentClient = null;
|
||||
});
|
||||
}
|
||||
|
||||
// Clean shutdown procedure
|
||||
function cleanup() {
|
||||
console.log("Cleaning up...");
|
||||
|
||||
// Reset modem if we're in data mode
|
||||
if (DATA_MODE) {
|
||||
console.log("Resetting modem before shutdown");
|
||||
DATA_MODE = false;
|
||||
NEXT_RECV_IS_LAST_ASCII = false;
|
||||
resetModemToCommandMode();
|
||||
}
|
||||
|
||||
if (currentClient) {
|
||||
currentClient.destroy();
|
||||
}
|
||||
|
||||
if (server) {
|
||||
server.close();
|
||||
}
|
||||
|
||||
if (serialPort && serialPort.isOpen) {
|
||||
serialPort.close();
|
||||
}
|
||||
}
|
||||
|
||||
// Signal handlers
|
||||
process.on('SIGINT', () => {
|
||||
console.log('\nReceived interrupt signal, shutting down...');
|
||||
cleanup();
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
process.on('SIGTERM', () => {
|
||||
console.log('\nReceived terminate signal, shutting down...');
|
||||
cleanup();
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
// Main execution
|
||||
async function main() {
|
||||
try {
|
||||
// Initialize serial port and wait for it to be ready
|
||||
await initSerial();
|
||||
|
||||
// Start TCP server
|
||||
server = net.createServer((socket) => {
|
||||
console.log(`Connection from ${socket.remoteAddress}:${socket.remotePort}`);
|
||||
handleClient(socket);
|
||||
});
|
||||
|
||||
server.listen(TCP_PORT, TCP_IP, () => {
|
||||
console.log(`Listening on ${TCP_IP}:${TCP_PORT}...`);
|
||||
});
|
||||
|
||||
server.on('error', (err) => {
|
||||
console.error('Server error:', err);
|
||||
cleanup();
|
||||
process.exit(1);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
// Start the proxy
|
||||
if (require.main === module) {
|
||||
main();
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
main,
|
||||
cleanup
|
||||
};
|
||||
310
zefie_wtvp_minisrv/package-lock.json
generated
310
zefie_wtvp_minisrv/package-lock.json
generated
@@ -1,14 +1,15 @@
|
||||
{
|
||||
"name": "zefie_wtvp_minisrv",
|
||||
"version": "0.9.64-dev",
|
||||
"version": "0.9.66-dev",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "zefie_wtvp_minisrv",
|
||||
"version": "0.9.64-dev",
|
||||
"version": "0.9.66-dev",
|
||||
"license": "GPL3",
|
||||
"dependencies": {
|
||||
"@serialport/parser-readline": "^13.0.0",
|
||||
"adm-zip": "^0.5.12",
|
||||
"cross-env": "^7.0.3",
|
||||
"crypto-js": "^4.2.0",
|
||||
@@ -28,6 +29,7 @@
|
||||
"proxy-agent": "^6.4.0",
|
||||
"rc4-crypto": "^1.5.0",
|
||||
"sanitize-html": "^2.13.0",
|
||||
"serialport": "^13.0.0",
|
||||
"sharp": "^0.34.3",
|
||||
"starttls": "^1.0.1",
|
||||
"strftime": "^0.10.2",
|
||||
@@ -608,6 +610,245 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/@serialport/binding-mock": {
|
||||
"version": "10.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@serialport/binding-mock/-/binding-mock-10.2.2.tgz",
|
||||
"integrity": "sha512-HAFzGhk9OuFMpuor7aT5G1ChPgn5qSsklTFOTUX72Rl6p0xwcSVsRtG/xaGp6bxpN7fI9D/S8THLBWbBgS6ldw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@serialport/bindings-interface": "^1.2.1",
|
||||
"debug": "^4.3.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@serialport/bindings-cpp": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@serialport/bindings-cpp/-/bindings-cpp-13.0.0.tgz",
|
||||
"integrity": "sha512-r25o4Bk/vaO1LyUfY/ulR6hCg/aWiN6Wo2ljVlb4Pj5bqWGcSRC4Vse4a9AcapuAu/FeBzHCbKMvRQeCuKjzIQ==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@serialport/bindings-interface": "1.2.2",
|
||||
"@serialport/parser-readline": "12.0.0",
|
||||
"debug": "4.4.0",
|
||||
"node-addon-api": "8.3.0",
|
||||
"node-gyp-build": "4.8.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/serialport/donate"
|
||||
}
|
||||
},
|
||||
"node_modules/@serialport/bindings-cpp/node_modules/@serialport/parser-delimiter": {
|
||||
"version": "12.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-12.0.0.tgz",
|
||||
"integrity": "sha512-gu26tVt5lQoybhorLTPsH2j2LnX3AOP2x/34+DUSTNaUTzu2fBXw+isVjQJpUBFWu6aeQRZw5bJol5X9Gxjblw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/serialport/donate"
|
||||
}
|
||||
},
|
||||
"node_modules/@serialport/bindings-cpp/node_modules/@serialport/parser-readline": {
|
||||
"version": "12.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-12.0.0.tgz",
|
||||
"integrity": "sha512-O7cywCWC8PiOMvo/gglEBfAkLjp/SENEML46BXDykfKP5mTPM46XMaX1L0waWU6DXJpBgjaL7+yX6VriVPbN4w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@serialport/parser-delimiter": "12.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/serialport/donate"
|
||||
}
|
||||
},
|
||||
"node_modules/@serialport/bindings-cpp/node_modules/debug": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
|
||||
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "^2.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@serialport/bindings-interface": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@serialport/bindings-interface/-/bindings-interface-1.2.2.tgz",
|
||||
"integrity": "sha512-CJaUd5bLvtM9c5dmO9rPBHPXTa9R2UwpkJ0wdh9JCYcbrPWsKz+ErvR0hBLeo7NPeiFdjFO4sonRljiw4d2XiA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^12.22 || ^14.13 || >=16"
|
||||
}
|
||||
},
|
||||
"node_modules/@serialport/parser-byte-length": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@serialport/parser-byte-length/-/parser-byte-length-13.0.0.tgz",
|
||||
"integrity": "sha512-32yvqeTAqJzAEtX5zCrN1Mej56GJ5h/cVFsCDPbF9S1ZSC9FWjOqNAgtByseHfFTSTs/4ZBQZZcZBpolt8sUng==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/serialport/donate"
|
||||
}
|
||||
},
|
||||
"node_modules/@serialport/parser-cctalk": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@serialport/parser-cctalk/-/parser-cctalk-13.0.0.tgz",
|
||||
"integrity": "sha512-RErAe57g9gvnlieVYGIn1xymb1bzNXb2QtUQd14FpmbQQYlcrmuRnJwKa1BgTCujoCkhtaTtgHlbBWOxm8U2uA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/serialport/donate"
|
||||
}
|
||||
},
|
||||
"node_modules/@serialport/parser-delimiter": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@serialport/parser-delimiter/-/parser-delimiter-13.0.0.tgz",
|
||||
"integrity": "sha512-Qqyb0FX1avs3XabQqNaZSivyVbl/yl0jywImp7ePvfZKLwx7jBZjvL+Hawt9wIG6tfq6zbFM24vzCCK7REMUig==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/serialport/donate"
|
||||
}
|
||||
},
|
||||
"node_modules/@serialport/parser-inter-byte-timeout": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@serialport/parser-inter-byte-timeout/-/parser-inter-byte-timeout-13.0.0.tgz",
|
||||
"integrity": "sha512-a0w0WecTW7bD2YHWrpTz1uyiWA2fDNym0kjmPeNSwZ2XCP+JbirZt31l43m2ey6qXItTYVuQBthm75sPVeHnGA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/serialport/donate"
|
||||
}
|
||||
},
|
||||
"node_modules/@serialport/parser-packet-length": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@serialport/parser-packet-length/-/parser-packet-length-13.0.0.tgz",
|
||||
"integrity": "sha512-60ZDDIqYRi0Xs2SPZUo4Jr5LLIjtb+rvzPKMJCohrO6tAqSDponcNpcB1O4W21mKTxYjqInSz+eMrtk0LLfZIg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@serialport/parser-readline": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@serialport/parser-readline/-/parser-readline-13.0.0.tgz",
|
||||
"integrity": "sha512-dov3zYoyf0dt1Sudd1q42VVYQ4WlliF0MYvAMA3MOyiU1IeG4hl0J6buBA2w4gl3DOCC05tGgLDN/3yIL81gsA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@serialport/parser-delimiter": "13.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/serialport/donate"
|
||||
}
|
||||
},
|
||||
"node_modules/@serialport/parser-ready": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@serialport/parser-ready/-/parser-ready-13.0.0.tgz",
|
||||
"integrity": "sha512-JNUQA+y2Rfs4bU+cGYNqOPnNMAcayhhW+XJZihSLQXOHcZsFnOa2F9YtMg9VXRWIcnHldHYtisp62Etjlw24bw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/serialport/donate"
|
||||
}
|
||||
},
|
||||
"node_modules/@serialport/parser-regex": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@serialport/parser-regex/-/parser-regex-13.0.0.tgz",
|
||||
"integrity": "sha512-m7HpIf56G5XcuDdA3DB34Z0pJiwxNRakThEHjSa4mG05OnWYv0IG8l2oUyYfuGMowQWaVnQ+8r+brlPxGVH+eA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/serialport/donate"
|
||||
}
|
||||
},
|
||||
"node_modules/@serialport/parser-slip-encoder": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@serialport/parser-slip-encoder/-/parser-slip-encoder-13.0.0.tgz",
|
||||
"integrity": "sha512-fUHZEExm6izJ7rg0A1yjXwu4sOzeBkPAjDZPfb+XQoqgtKAk+s+HfICiYn7N2QU9gyaeCO8VKgWwi+b/DowYOg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/serialport/donate"
|
||||
}
|
||||
},
|
||||
"node_modules/@serialport/parser-spacepacket": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@serialport/parser-spacepacket/-/parser-spacepacket-13.0.0.tgz",
|
||||
"integrity": "sha512-DoXJ3mFYmyD8X/8931agJvrBPxqTaYDsPoly9/cwQSeh/q4EjQND9ySXBxpWz5WcpyCU4jOuusqCSAPsbB30Eg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/serialport/donate"
|
||||
}
|
||||
},
|
||||
"node_modules/@serialport/stream": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@serialport/stream/-/stream-13.0.0.tgz",
|
||||
"integrity": "sha512-F7xLJKsjGo2WuEWMSEO1SimRcOA+WtWICsY13r0ahx8s2SecPQH06338g28OT7cW7uRXI7oEQAk62qh5gHJW3g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@serialport/bindings-interface": "1.2.2",
|
||||
"debug": "4.4.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/serialport/donate"
|
||||
}
|
||||
},
|
||||
"node_modules/@serialport/stream/node_modules/debug": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
|
||||
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "^2.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@tootallnate/quickjs-emscripten": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz",
|
||||
@@ -2364,6 +2605,26 @@
|
||||
"split2": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/node-addon-api": {
|
||||
"version": "8.3.0",
|
||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.3.0.tgz",
|
||||
"integrity": "sha512-8VOpLHFrOQlAH+qA0ZzuGRlALRA6/LVh8QJldbrC4DY0hXoMP0l4Acq8TzFC018HztWiRqyCEj2aTWY2UvnJUg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^18 || ^20 || >= 21"
|
||||
}
|
||||
},
|
||||
"node_modules/node-gyp-build": {
|
||||
"version": "4.8.4",
|
||||
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
|
||||
"integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"node-gyp-build": "bin.js",
|
||||
"node-gyp-build-optional": "optional.js",
|
||||
"node-gyp-build-test": "build-test.js"
|
||||
}
|
||||
},
|
||||
"node_modules/nunjucks": {
|
||||
"version": "3.2.4",
|
||||
"resolved": "https://registry.npmjs.org/nunjucks/-/nunjucks-3.2.4.tgz",
|
||||
@@ -2945,6 +3206,51 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/serialport": {
|
||||
"version": "13.0.0",
|
||||
"resolved": "https://registry.npmjs.org/serialport/-/serialport-13.0.0.tgz",
|
||||
"integrity": "sha512-PHpnTd8isMGPfFTZNCzOZp9m4mAJSNWle9Jxu6BPTcWq7YXl5qN7tp8Sgn0h+WIGcD6JFz5QDgixC2s4VW7vzg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@serialport/binding-mock": "10.2.2",
|
||||
"@serialport/bindings-cpp": "13.0.0",
|
||||
"@serialport/parser-byte-length": "13.0.0",
|
||||
"@serialport/parser-cctalk": "13.0.0",
|
||||
"@serialport/parser-delimiter": "13.0.0",
|
||||
"@serialport/parser-inter-byte-timeout": "13.0.0",
|
||||
"@serialport/parser-packet-length": "13.0.0",
|
||||
"@serialport/parser-readline": "13.0.0",
|
||||
"@serialport/parser-ready": "13.0.0",
|
||||
"@serialport/parser-regex": "13.0.0",
|
||||
"@serialport/parser-slip-encoder": "13.0.0",
|
||||
"@serialport/parser-spacepacket": "13.0.0",
|
||||
"@serialport/stream": "13.0.0",
|
||||
"debug": "4.4.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/serialport/donate"
|
||||
}
|
||||
},
|
||||
"node_modules/serialport/node_modules/debug": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
|
||||
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "^2.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/serve-static": {
|
||||
"version": "1.16.2",
|
||||
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz",
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
"url": "https://github.com/zefie/zefie_wtvp_minisrv.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"@serialport/parser-readline": "^13.0.0",
|
||||
"adm-zip": "^0.5.12",
|
||||
"cross-env": "^7.0.3",
|
||||
"crypto-js": "^4.2.0",
|
||||
@@ -48,6 +49,7 @@
|
||||
"proxy-agent": "^6.4.0",
|
||||
"rc4-crypto": "^1.5.0",
|
||||
"sanitize-html": "^2.13.0",
|
||||
"serialport": "^13.0.0",
|
||||
"sharp": "^0.34.3",
|
||||
"starttls": "^1.0.1",
|
||||
"strftime": "^0.10.2",
|
||||
|
||||
Reference in New Issue
Block a user