From 7885cede659f3255be56f77c1eef2ada7387d6f1 Mon Sep 17 00:00:00 2001
From: chenyc <501753378@qq.com>
Date: 星期日, 22 三月 2026 16:23:21 +0800
Subject: [PATCH] 初始化项目

---
 scripts/stress-50-devices.js |  223 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 223 insertions(+), 0 deletions(-)

diff --git a/scripts/stress-50-devices.js b/scripts/stress-50-devices.js
new file mode 100644
index 0000000..2ccff05
--- /dev/null
+++ b/scripts/stress-50-devices.js
@@ -0,0 +1,223 @@
+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}`
+);

--
Gitblit v1.8.0