const net = require("net");
|
const config = require("../src/config");
|
|
const DEVICE_COUNT = Number(process.env.DEVICE_COUNT || 50);
|
const DURATION_SEC = Number(process.env.DURATION_SEC || 120);
|
const INTERVAL_MS = Number(process.env.INTERVAL_MS || 1000);
|
const ALARM_EVERY = Number(process.env.ALARM_EVERY || 30);
|
const BP_EVERY = Number(process.env.BP_EVERY || 15);
|
|
const HOST = process.env.TCP_HOST || config.tcp.host || "127.0.0.1";
|
const PORT = Number(process.env.TCP_PORT || config.tcp.port || 19000);
|
|
function writeUIntLE(buf, offset, value, bytes) {
|
if (bytes === 1) buf.writeUInt8(value, offset);
|
if (bytes === 2) buf.writeUInt16LE(value, offset);
|
if (bytes === 4) buf.writeUInt32LE(value, offset);
|
}
|
|
function writeInt16LE(buf, offset, value) {
|
buf.writeInt16LE(value, offset);
|
}
|
|
function buildHeader(frameType, machineId) {
|
const header = Buffer.alloc(20);
|
header[0] = 0x55;
|
header[1] = 0x55;
|
header[2] = 0x55;
|
header[3] = 0x55;
|
|
header[4] = 0x31;
|
|
let id = Number(machineId) || 0;
|
for (let i = 0; i < 5; i++) {
|
header[5 + i] = id & 0xff;
|
id = Math.floor(id / 256);
|
}
|
|
header[10] = 0x01;
|
header[11] = frameType;
|
header[12] = 0x6e;
|
return header;
|
}
|
|
function buildRunParamsFrame(machineId, elapsedSec) {
|
const data = Buffer.alloc(200);
|
|
const setTimeSec = 4 * 3600;
|
const doneSec = Math.max(0, elapsedSec);
|
|
writeUIntLE(data, 0, setTimeSec, 4);
|
writeUIntLE(data, 4, doneSec, 4);
|
writeUIntLE(data, 8, 280, 2);
|
writeUIntLE(data, 10, 1, 1);
|
writeUIntLE(data, 11, 1, 1);
|
writeUIntLE(data, 12, 1, 1);
|
writeUIntLE(data, 13, 500, 2);
|
writeUIntLE(data, 15, 20, 2);
|
|
const ufTotalMl = 1800;
|
const ufDoneMl = Math.min(ufTotalMl, Math.floor(doneSec / 10));
|
writeUIntLE(data, 17, ufTotalMl, 4);
|
writeUIntLE(data, 21, ufDoneMl, 4);
|
writeUIntLE(data, 25, 600, 4);
|
|
writeUIntLE(data, 29, 1, 1);
|
writeUIntLE(data, 30, 0, 1);
|
writeUIntLE(data, 31, 500, 2);
|
writeUIntLE(data, 33, 368, 2);
|
writeUIntLE(data, 35, 1450, 2);
|
writeUIntLE(data, 37, 1500, 4);
|
writeUIntLE(data, 41, Math.min(1500, Math.floor(doneSec / 12)), 4);
|
writeUIntLE(data, 45, 0, 1);
|
writeUIntLE(data, 46, 120, 2);
|
writeUIntLE(data, 48, 100, 2);
|
writeUIntLE(data, 50, Math.floor(doneSec / 60), 4);
|
|
writeInt16LE(data, 54, -120);
|
writeInt16LE(data, 56, 130);
|
writeInt16LE(data, 58, 90);
|
writeInt16LE(data, 60, -8);
|
|
writeUIntLE(data, 62, 15, 1);
|
writeUIntLE(data, 64, 3500, 2);
|
writeUIntLE(data, 66, 365, 2);
|
writeUIntLE(data, 68, 366, 2);
|
writeUIntLE(data, 69, 82, 1);
|
|
return Buffer.concat([buildHeader(0x1f, machineId), data]);
|
}
|
|
function buildAlarmFrame(machineId) {
|
const data = Buffer.alloc(130);
|
writeUIntLE(data, 0, 283, 2);
|
writeUIntLE(data, 2, 1, 1);
|
|
const now = new Date();
|
writeUIntLE(data, 3, now.getFullYear(), 2);
|
writeUIntLE(data, 5, now.getMonth() + 1, 1);
|
writeUIntLE(data, 6, now.getDate(), 1);
|
writeUIntLE(data, 7, now.getHours(), 1);
|
writeUIntLE(data, 8, now.getMinutes(), 1);
|
writeUIntLE(data, 9, now.getSeconds(), 1);
|
|
return Buffer.concat([buildHeader(0x26, machineId), data]);
|
}
|
|
function buildBpFrame(machineId) {
|
const data = Buffer.alloc(130);
|
|
writeUIntLE(data, 0, 1, 1);
|
writeUIntLE(data, 1, 1, 1);
|
|
const now = new Date();
|
writeUIntLE(data, 2, now.getFullYear(), 2);
|
writeUIntLE(data, 4, now.getMonth() + 1, 1);
|
writeUIntLE(data, 5, now.getDate(), 1);
|
writeUIntLE(data, 6, now.getHours(), 1);
|
writeUIntLE(data, 7, now.getMinutes(), 1);
|
writeUIntLE(data, 8, now.getSeconds(), 1);
|
|
writeUIntLE(data, 9, 140, 2);
|
writeUIntLE(data, 11, 90, 2);
|
writeUIntLE(data, 13, 80, 2);
|
writeUIntLE(data, 15, 105, 2);
|
|
return Buffer.concat([buildHeader(0x29, machineId), data]);
|
}
|
|
const sockets = [];
|
let sentFrames = 0;
|
let sentBytes = 0;
|
let connectOk = 0;
|
let connectErr = 0;
|
let runtimeSocketErr = 0;
|
let shutdownIgnoredErr = 0;
|
let stopping = false;
|
|
const startTs = Date.now();
|
|
for (let i = 0; i < DEVICE_COUNT; i++) {
|
const machineId = 6220903000 + i;
|
const socket = new net.Socket();
|
sockets.push(socket);
|
|
let tick = 0;
|
let timer = null;
|
|
socket.connect(PORT, HOST, () => {
|
connectOk += 1;
|
timer = setInterval(() => {
|
tick += 1;
|
const elapsedSec = Math.floor((Date.now() - startTs) / 1000);
|
|
const runFrame = buildRunParamsFrame(machineId, elapsedSec);
|
socket.write(runFrame);
|
sentFrames += 1;
|
sentBytes += runFrame.length;
|
|
if (ALARM_EVERY > 0 && tick % ALARM_EVERY === 0) {
|
const alarm = buildAlarmFrame(machineId);
|
socket.write(alarm);
|
sentFrames += 1;
|
sentBytes += alarm.length;
|
}
|
|
if (BP_EVERY > 0 && tick % BP_EVERY === 0) {
|
const bp = buildBpFrame(machineId);
|
socket.write(bp);
|
sentFrames += 1;
|
sentBytes += bp.length;
|
}
|
}, INTERVAL_MS);
|
});
|
|
socket.on("error", (err) => {
|
const msg = (err && (err.message || String(err))) || "";
|
const code = err && err.code;
|
const isExpectedDuringStop =
|
stopping && (code === "ECONNRESET" || code === "EPIPE" || code === "ECONNABORTED");
|
|
if (isExpectedDuringStop) {
|
shutdownIgnoredErr += 1;
|
return;
|
}
|
|
runtimeSocketErr += 1;
|
connectErr += 1;
|
console.error(`[device ${machineId}] socket error:`, code || msg);
|
});
|
|
socket.on("close", () => {
|
if (timer) clearInterval(timer);
|
});
|
}
|
|
setTimeout(() => {
|
stopping = true;
|
|
for (const socket of sockets) {
|
try {
|
socket.end();
|
socket.destroy();
|
} catch (_) {}
|
}
|
|
const duration = Math.max(1, Math.floor((Date.now() - startTs) / 1000));
|
const fps = (sentFrames / duration).toFixed(2);
|
const kbps = ((sentBytes / 1024) / duration).toFixed(2);
|
|
console.log("\n=== Stress Test Summary ===");
|
console.log("host:", HOST, "port:", PORT);
|
console.log("devices:", DEVICE_COUNT, "duration(s):", duration);
|
console.log("connected:", connectOk, "errors:", connectErr);
|
console.log("runtimeSocketErrors:", runtimeSocketErr);
|
console.log("ignoredDuringShutdown:", shutdownIgnoredErr);
|
console.log("sentFrames:", sentFrames, "fps:", fps);
|
console.log("throughput(KB/s):", kbps);
|
process.exit(0);
|
}, DURATION_SEC * 1000);
|
|
console.log(
|
`Starting stress test: devices=${DEVICE_COUNT}, duration=${DURATION_SEC}s, interval=${INTERVAL_MS}ms, target=${HOST}:${PORT}`
|
);
|