From 3dcfa14e4f144a1adb4333eeecdce72791a9026e Mon Sep 17 00:00:00 2001 From: Micah Elizabeth Scott Date: Sat, 29 Mar 2014 12:50:12 -0700 Subject: [PATCH] Fixed networking performance in OPC server --- OpenPixelControl.pde | 130 +++++++++++++++++++++++++------------------ 1 file changed, 77 insertions(+), 53 deletions(-) diff --git a/OpenPixelControl.pde b/OpenPixelControl.pde index 830ba6c..0525d90 100644 --- a/OpenPixelControl.pde +++ b/OpenPixelControl.pde @@ -1,78 +1,102 @@ -import processing.net.*; + +import java.io.*; +import java.net.*; // Server for Open Pixel Control patterns (http://openpixelcontrol.org/) -class OpenPixelControl extends SCPattern { +class OpenPixelControl extends SCPattern implements Runnable { int port = 7890; - - Server server; + Thread thread; + ServerSocket server; byte[] buffer; int bufferedByteCount; public OpenPixelControl(LX lx, PApplet parent) { super(lx); - server = new Server(parent, port); - println("Listening for Open Pixel Control data on port " + port); + parent.registerMethod("dispose", this); + + // Save a JSON layout file that some Open Pixel Control clients can use + writeMappingFile("openpixelcontrol-layout.json"); // Buffer space for two frames, worst case buffer = new byte[0x10004 * 2]; bufferedByteCount = 0; - - // Save a JSON layout file that some Open Pixel Control clients can use - writeMappingFile("openpixelcontrol-layout.json"); } - public void run(double deltaMs) { - readFromClient(); + public void dispose() { + thread = null; + if (server != null) { + try { + server.close(); + } catch (IOException e) { + e.printStackTrace(); + } + server = null; + } } - void readFromClient() { - Client client = server.available(); - - if (client == null) { - // No client; flush any stored partial frames - bufferedByteCount = 0; - return; - } + public void run() { + // Thread run function; handle OPC traffic. + while (Thread.currentThread() == thread) { + + try { + Socket cli = server.accept(); + InputStream input = cli.getInputStream(); + bufferedByteCount = 0; + + while (Thread.currentThread() == thread) { + + int r = input.read(buffer, bufferedByteCount, buffer.length - bufferedByteCount); + if (r <= 0) { + break; + } + bufferedByteCount += r; + + // Extract OPC packets from buffer + int offset = 0; + while (bufferedByteCount - offset >= 4) { + int channel = buffer[offset + 0] & 0xFF; + int command = buffer[offset + 1] & 0xFF; + int length = ((buffer[offset + 2] & 0xFF) << 8) | (buffer[offset + 3] & 0xFF); + + if (bufferedByteCount - offset < length + 4) { + // Not enough data for a full packet yet + break; + } + + // Handle the packet in-place + offset += 4; + opcPacket(channel, command, offset, length); + offset += length; + } + + // If we didn't use the whole buffer, save remainder for later + bufferedByteCount -= offset; + arrayCopy(buffer, offset, buffer, 0, bufferedByteCount); + } - while (true) { - int available = client.available(); - if (available <= 0) { - return; - } + cli.close(); - if (bufferedByteCount == 0) { - // Read directly to buffer - bufferedByteCount = client.readBytes(buffer); - } else { - // Append to an earlier partial frame - byte[] additional = new byte[buffer.length - bufferedByteCount]; - int additionalLength = client.readBytes(additional); - arrayCopy(additional, 0, buffer, bufferedByteCount, additionalLength); - bufferedByteCount += additionalLength; + } catch (IOException e) { + e.printStackTrace(); } + } + } - // Extract OPC packets from buffer - int offset = 0; - while (bufferedByteCount - offset >= 4) { - int channel = buffer[offset + 0] & 0xFF; - int command = buffer[offset + 1] & 0xFF; - int length = ((buffer[offset + 2] & 0xFF) << 8) | (buffer[offset + 3] & 0xFF); - - if (bufferedByteCount - offset < length + 4) { - // Not enough data for a full packet yet - break; - } - - // Handle the packet in-place - offset += 4; - opcPacket(channel, command, offset, length); - offset += length; + public void run(double deltaMs) { + // SCPattern run function; nothing to do except start our thread the first time. + + if (server == null) { + try { + server = new ServerSocket(this.port); + thread = new Thread(this); + thread.start(); + println("Listening for Open Pixel Control data on port " + port); + + } catch (IOException e) { + e.printStackTrace(); + thread = null; } - - // If we didn't use the whole buffer, save remainder for later - bufferedByteCount -= offset; - arrayCopy(buffer, offset, buffer, 0, bufferedByteCount); } } -- 2.34.1