From 88c9908f1cd67c6123be7f86baa8e12fcb38a2b0 Mon Sep 17 00:00:00 2001 From: Luca Warmenhoven Date: Tue, 7 May 2024 16:25:10 +0200 Subject: [PATCH 01/33] Added basic WebSocket functionality (no decoding yet) --- .../fitbot/processing/MotionProcessor.java | 4 - .../{ => util}/processing/MotionData.java | 2 +- .../processing/MotionInputStream.java | 13 ++- .../util/processing/MotionProcessor.java | 4 + .../fitbot/util/server/IWebSocketHandler.java | 15 ++++ .../example/fitbot/util/server/WebSocket.java | 66 ++++++++++++++ .../server/WebSocketConnectionHandler.java | 88 +++++++++++++++++++ 7 files changed, 184 insertions(+), 8 deletions(-) delete mode 100644 code/src/Fitbot/app/src/main/java/com/example/fitbot/processing/MotionProcessor.java rename code/src/Fitbot/app/src/main/java/com/example/fitbot/{ => util}/processing/MotionData.java (97%) rename code/src/Fitbot/app/src/main/java/com/example/fitbot/{ => util}/processing/MotionInputStream.java (68%) create mode 100644 code/src/Fitbot/app/src/main/java/com/example/fitbot/util/processing/MotionProcessor.java create mode 100644 code/src/Fitbot/app/src/main/java/com/example/fitbot/util/server/IWebSocketHandler.java create mode 100644 code/src/Fitbot/app/src/main/java/com/example/fitbot/util/server/WebSocket.java create mode 100644 code/src/Fitbot/app/src/main/java/com/example/fitbot/util/server/WebSocketConnectionHandler.java diff --git a/code/src/Fitbot/app/src/main/java/com/example/fitbot/processing/MotionProcessor.java b/code/src/Fitbot/app/src/main/java/com/example/fitbot/processing/MotionProcessor.java deleted file mode 100644 index 9e0e13e..0000000 --- a/code/src/Fitbot/app/src/main/java/com/example/fitbot/processing/MotionProcessor.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.example.fitbot.processing; - -public class MotionProcessor { -} diff --git a/code/src/Fitbot/app/src/main/java/com/example/fitbot/processing/MotionData.java b/code/src/Fitbot/app/src/main/java/com/example/fitbot/util/processing/MotionData.java similarity index 97% rename from code/src/Fitbot/app/src/main/java/com/example/fitbot/processing/MotionData.java rename to code/src/Fitbot/app/src/main/java/com/example/fitbot/util/processing/MotionData.java index 4cc2abf..42c346c 100644 --- a/code/src/Fitbot/app/src/main/java/com/example/fitbot/processing/MotionData.java +++ b/code/src/Fitbot/app/src/main/java/com/example/fitbot/util/processing/MotionData.java @@ -1,4 +1,4 @@ -package com.example.fitbot.processing; +package com.example.fitbot.util.processing; public class MotionData { diff --git a/code/src/Fitbot/app/src/main/java/com/example/fitbot/processing/MotionInputStream.java b/code/src/Fitbot/app/src/main/java/com/example/fitbot/util/processing/MotionInputStream.java similarity index 68% rename from code/src/Fitbot/app/src/main/java/com/example/fitbot/processing/MotionInputStream.java rename to code/src/Fitbot/app/src/main/java/com/example/fitbot/util/processing/MotionInputStream.java index 1598693..a4db7f6 100644 --- a/code/src/Fitbot/app/src/main/java/com/example/fitbot/processing/MotionInputStream.java +++ b/code/src/Fitbot/app/src/main/java/com/example/fitbot/util/processing/MotionInputStream.java @@ -1,4 +1,6 @@ -package com.example.fitbot.processing; +package com.example.fitbot.util.processing; + +import com.example.fitbot.util.server.WebSocket; import java.io.InputStream; @@ -17,9 +19,14 @@ public class MotionInputStream extends InputStream { */ public static MotionInputStream startListening() { - // Create server - + // Create socket server + WebSocket socket = WebSocket.createServer(80); + // Check if the socket + if ( socket != null ) + { + socket.startListening(); + } return null; } diff --git a/code/src/Fitbot/app/src/main/java/com/example/fitbot/util/processing/MotionProcessor.java b/code/src/Fitbot/app/src/main/java/com/example/fitbot/util/processing/MotionProcessor.java new file mode 100644 index 0000000..6726312 --- /dev/null +++ b/code/src/Fitbot/app/src/main/java/com/example/fitbot/util/processing/MotionProcessor.java @@ -0,0 +1,4 @@ +package com.example.fitbot.util.processing; + +public class MotionProcessor { +} diff --git a/code/src/Fitbot/app/src/main/java/com/example/fitbot/util/server/IWebSocketHandler.java b/code/src/Fitbot/app/src/main/java/com/example/fitbot/util/server/IWebSocketHandler.java new file mode 100644 index 0000000..db4a5f9 --- /dev/null +++ b/code/src/Fitbot/app/src/main/java/com/example/fitbot/util/server/IWebSocketHandler.java @@ -0,0 +1,15 @@ +package com.example.fitbot.util.server; + +import java.net.Socket; + +/** + * Interface for handling WebSocket events. + */ +public interface IWebSocketHandler { + + // Function for handling the connection of the WebSocket. + default void onConnected(Socket socket) {} + default void onDisconnected(Socket socket) {} + default void onMessageReceived(String message) {} + default void onError(Socket socket, String error) {} +} diff --git a/code/src/Fitbot/app/src/main/java/com/example/fitbot/util/server/WebSocket.java b/code/src/Fitbot/app/src/main/java/com/example/fitbot/util/server/WebSocket.java new file mode 100644 index 0000000..f528fab --- /dev/null +++ b/code/src/Fitbot/app/src/main/java/com/example/fitbot/util/server/WebSocket.java @@ -0,0 +1,66 @@ +package com.example.fitbot.util.server; + +import android.support.annotation.Nullable; +import android.util.Log; + +import java.io.IOException; +import java.net.ServerSocket; +import java.net.Socket; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +public class WebSocket { + + private ServerSocket serverSocket; + private WebSocketConnectionHandler connectionHandler; + private final Set clients = Collections.synchronizedSet(new HashSet<>()); + protected IWebSocketHandler eventHandler = new IWebSocketHandler() {}; // NO-OP event handler. + + /** + * Constructor for creating a new WebSocket server. + */ + private WebSocket() {} + + /** + * Function for creating a new WebSocket server given the provided port. + * @param port The port to configure the server to. + * @return A WebSocket connection, or null if something went wrong. + */ + public static @Nullable WebSocket createServer(int port) { + try { + WebSocket socket = new WebSocket(); + socket.serverSocket = new ServerSocket(port); + return socket; + } catch (IOException error) + { + String cause = error.getMessage() == null ? "Unknown reason" : error.getMessage(); + Log.e("WebSocket -- Creating new WebSocket server", cause); + return null; + } + } + + /** + * Method for listening for incoming connections. + */ + public void startListening() { + this.connectionHandler = new WebSocketConnectionHandler(this); + this.connectionHandler.listen(); + } + + /** + * Method for getting the ServerSocket connection + * @return The ServerSocket connection. + */ + public ServerSocket getSocket() { + return this.serverSocket; + } + + /** + * Method for checking whether this WebSocket connection is connected. + * @return The connection status of the WebSocket. + */ + public boolean isConnected() { + return !this.serverSocket.isClosed(); + } +} diff --git a/code/src/Fitbot/app/src/main/java/com/example/fitbot/util/server/WebSocketConnectionHandler.java b/code/src/Fitbot/app/src/main/java/com/example/fitbot/util/server/WebSocketConnectionHandler.java new file mode 100644 index 0000000..4550f31 --- /dev/null +++ b/code/src/Fitbot/app/src/main/java/com/example/fitbot/util/server/WebSocketConnectionHandler.java @@ -0,0 +1,88 @@ +package com.example.fitbot.util.server; + +import android.os.Build; +import android.support.annotation.RequiresApi; +import android.util.Log; + +import java.io.IOException; +import java.net.Socket; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Base64; +import java.util.Scanner; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class WebSocketConnectionHandler implements Runnable { + + private final WebSocket theSocket; + private Thread thread; + + /** + * Constructor for WebSocketConnectionHandler. + * This class handles all new incoming Socket connections. + * @param webSocket The socket to check for new connections. + */ + protected WebSocketConnectionHandler(WebSocket webSocket) { + this.theSocket = webSocket; + } + + @RequiresApi(api = Build.VERSION_CODES.O) + @Override + public void run() { + while (theSocket.isConnected()) { + try { + Socket newSocket = this.theSocket.getSocket().accept(); + this.theSocket.eventHandler.onConnected(newSocket); + + Scanner scanner = new Scanner(newSocket.getInputStream(), "UTF-8"); + String data = scanner.useDelimiter("\\r\\n\\r\\n").next(); + Matcher header = Pattern.compile("^GET").matcher(data); + + // Check if the header contains the GET keyword + // If this is the case, upgrade the HTTP connection to WebSocket. + if (header.find()) { + Matcher match = Pattern.compile("Sec-WebSocket-Key: (.*)").matcher(data); + match.find(); + + String SECAccept = Base64.getEncoder().encodeToString( + MessageDigest.getInstance("SHA-1").digest((match.group(1) + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").getBytes(StandardCharsets.UTF_8))); + + byte[] response = ( + "HTTP/1.1 101 Switching Protocols\r\n" + + "Connection: Upgrade\r\n" + + "Upgrade: websocket\r\n" + + "Sec-WebSocket-Accept: " + + SECAccept + "\r\n\r\n").getBytes(StandardCharsets.UTF_8); + newSocket.getOutputStream().write(response, 0, response.length); + + // TODO: Read data from socket and provide in onMessageReceived. + + } + + } catch (IOException | NoSuchAlgorithmException error) { + String reason = error.getMessage() == null ? "Unknown reason" : error.getMessage(); + Log.e("WebSocketConnectionHandler", "Error listening to Socket connections: " + reason); + break; + } + } + } + + /** + * Method for checking whether the connection handler is actively listening. + * @return Whether or not it's listening. + */ + public boolean isActive() { + return this.thread.isAlive(); + } + + /** + * Method for listening to all new incoming socket connections. + */ + public void listen() { + this.thread = new Thread(this); + this.thread.start(); + Log.i("WebSocketConnectionHandler", "Listening started."); + } +} From 1695f08fb224c32a61a440f1aad5bea0041388fc Mon Sep 17 00:00:00 2001 From: Luca Warmenhoven Date: Wed, 8 May 2024 14:40:14 +0200 Subject: [PATCH 02/33] Added motion processing, fixed WebSocket packet processing, added Vector math to process motion data --- .idea/workspace.xml | 29 +-- .../fitbot/util/processing/MotionData.java | 33 ++-- .../util/processing/MotionInputStream.java | 38 ---- .../util/processing/MotionProcessor.java | 91 ++++++++++ .../fitbot/util/processing/Vector3.java | 165 ++++++++++++++++++ .../fitbot/util/server/IWebSocketHandler.java | 5 +- .../example/fitbot/util/server/WebSocket.java | 70 ++++++++ .../util/server/WebSocketConnection.java | 35 ++++ .../server/WebSocketConnectionHandler.java | 150 +++++++++++++--- .../fitbot/WebSocketMessageParsingTest.java | 37 ++++ .../Luca/literatuuronderzoek/onderzoek.md | 22 +++ 11 files changed, 587 insertions(+), 88 deletions(-) delete mode 100644 code/src/Fitbot/app/src/main/java/com/example/fitbot/util/processing/MotionInputStream.java create mode 100644 code/src/Fitbot/app/src/main/java/com/example/fitbot/util/processing/Vector3.java create mode 100644 code/src/Fitbot/app/src/main/java/com/example/fitbot/util/server/WebSocketConnection.java create mode 100644 code/src/Fitbot/app/src/test/java/com/example/fitbot/WebSocketMessageParsingTest.java diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 22bfcea..fb9da63 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -15,9 +15,14 @@ - - - + + + + + + + +