From db2eb9412ddc4ff687eb4c9b862053f49f9aec7b Mon Sep 17 00:00:00 2001
From: yeg <1347747024@qq.com>
Date: 星期三, 26 八月 2026 13:16:42 +0800
Subject: [PATCH] feat(device): 完善 BTS 只读协议与模拟器

---
 ruoyi-device/src/test/java/com/ruoyi/device/bts/ScriptedBtsTcpSimulator.java |   79 ++++++++++++++++++++++++++++++++-------
 1 files changed, 65 insertions(+), 14 deletions(-)

diff --git a/ruoyi-device/src/test/java/com/ruoyi/device/bts/ScriptedBtsTcpSimulator.java b/ruoyi-device/src/test/java/com/ruoyi/device/bts/ScriptedBtsTcpSimulator.java
index 2e5b46b..5a61ea5 100644
--- a/ruoyi-device/src/test/java/com/ruoyi/device/bts/ScriptedBtsTcpSimulator.java
+++ b/ruoyi-device/src/test/java/com/ruoyi/device/bts/ScriptedBtsTcpSimulator.java
@@ -5,7 +5,9 @@
 import java.io.InputStream;
 import java.net.ServerSocket;
 import java.net.Socket;
+import java.net.SocketException;
 import java.nio.charset.StandardCharsets;
+import java.time.Duration;
 import java.util.List;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.CopyOnWriteArrayList;
@@ -19,24 +21,55 @@
     private static final byte[] FRAME_END = "#\r\n".getBytes(StandardCharsets.UTF_8);
 
     private final ServerSocket serverSocket;
+    private final int port;
     private final ExecutorService executor = Executors.newSingleThreadExecutor();
-    private final BlockingQueue<String> responses = new LinkedBlockingQueue<>();
+    private final BlockingQueue<ScriptedAction> actions = new LinkedBlockingQueue<>();
     private final List<String> requests = new CopyOnWriteArrayList<>();
 
     ScriptedBtsTcpSimulator() throws IOException
     {
+        this(true);
+    }
+
+    private ScriptedBtsTcpSimulator(boolean acceptConnections) throws IOException
+    {
         serverSocket = new ServerSocket(0);
-        executor.submit(this::serve);
+        port = serverSocket.getLocalPort();
+        if (acceptConnections)
+            executor.submit(this::serve);
+        else
+            serverSocket.close();
+    }
+
+    static ScriptedBtsTcpSimulator refusingConnections() throws IOException
+    {
+        return new ScriptedBtsTcpSimulator(false);
     }
 
     int port()
     {
-        return serverSocket.getLocalPort();
+        return port;
     }
 
     void enqueue(String response)
     {
-        responses.add(response);
+        actions.add(new ScriptedAction(Duration.ZERO, response.getBytes(StandardCharsets.UTF_8), false));
+    }
+
+    void enqueueDelayed(Duration delay, String response)
+    {
+        if (delay.isNegative()) throw new IllegalArgumentException("delay must not be negative");
+        actions.add(new ScriptedAction(delay, response.getBytes(StandardCharsets.UTF_8), false));
+    }
+
+    void enqueueRaw(byte[] response)
+    {
+        actions.add(new ScriptedAction(Duration.ZERO, response.clone(), false));
+    }
+
+    void enqueueDisconnect()
+    {
+        actions.add(new ScriptedAction(Duration.ZERO, null, true));
     }
 
     List<String> requests()
@@ -46,21 +79,35 @@
 
     private void serve()
     {
-        try (Socket socket = serverSocket.accept())
+        while (!serverSocket.isClosed())
         {
-            while (!socket.isClosed())
+            try (Socket socket = serverSocket.accept())
             {
-                String request = readFrame(socket.getInputStream());
-                requests.add(request);
-                String response = responses.poll(5, TimeUnit.SECONDS);
-                if (response == null) throw new IOException("No scripted BTS response available");
-                socket.getOutputStream().write(response.getBytes(StandardCharsets.UTF_8));
-                socket.getOutputStream().write(FRAME_END);
-                socket.getOutputStream().flush();
+                serveConnection(socket);
+            }
+            catch (SocketException ex)
+            {
+                if (!serverSocket.isClosed()) throw new IllegalStateException(ex);
+            }
+            catch (Exception ignored)
+            {
             }
         }
-        catch (Exception ignored)
+    }
+
+    private void serveConnection(Socket socket) throws Exception
+    {
+        while (!socket.isClosed())
         {
+            String request = readFrame(socket.getInputStream());
+            requests.add(request);
+            ScriptedAction action = actions.poll(5, TimeUnit.SECONDS);
+            if (action == null) throw new IOException("No scripted BTS action available");
+            TimeUnit.MILLISECONDS.sleep(action.delay().toMillis());
+            if (action.disconnect()) return;
+            socket.getOutputStream().write(action.payload());
+            socket.getOutputStream().write(FRAME_END);
+            socket.getOutputStream().flush();
         }
     }
 
@@ -94,4 +141,8 @@
         executor.shutdownNow();
         executor.awaitTermination(2, TimeUnit.SECONDS);
     }
+
+    private record ScriptedAction(Duration delay, byte[] payload, boolean disconnect)
+    {
+    }
 }

--
Gitblit v1.7.1