From 6554807c83343b2a821d0f2db7343a708e0680a6 Mon Sep 17 00:00:00 2001 From: jyong15 Date: Tue, 15 Apr 2025 15:03:57 +0800 Subject: [PATCH 01/19] DEV-221 Updates for support for gRPC on MacOS --- ShimmerDriver/build.gradle | 2 +- .../BluetoothDeviceDetails.java | 19 ++++++++++++------- .../shimmerresearch/pcDriver/ShimmerGRPC.java | 12 +++--------- .../simpleexamples/SensorMapsExample.java | 11 +++++++---- 4 files changed, 23 insertions(+), 21 deletions(-) diff --git a/ShimmerDriver/build.gradle b/ShimmerDriver/build.gradle index 0245bf4e2..c787a7177 100644 --- a/ShimmerDriver/build.gradle +++ b/ShimmerDriver/build.gradle @@ -93,7 +93,7 @@ dependencies { api group: 'com.google.protobuf', name: 'protobuf-java', version: '3.4.0' // https://mvnrepository.com/artifact/io.grpc/grpc-all - api group: 'io.grpc', name: 'grpc-all', version: '1.32.1' + api group: 'io.grpc', name: 'grpc-all', version: '1.71.0' // https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient api group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.3.6' diff --git a/ShimmerDriver/src/main/java/com/shimmerresearch/driverUtilities/BluetoothDeviceDetails.java b/ShimmerDriver/src/main/java/com/shimmerresearch/driverUtilities/BluetoothDeviceDetails.java index a4c762414..b43598893 100644 --- a/ShimmerDriver/src/main/java/com/shimmerresearch/driverUtilities/BluetoothDeviceDetails.java +++ b/ShimmerDriver/src/main/java/com/shimmerresearch/driverUtilities/BluetoothDeviceDetails.java @@ -33,13 +33,18 @@ public BluetoothDeviceDetails(String comPort, String macId, String friendlyName) } public void setMacId(String mac){ - - mac = mac.replace("-", ""); - - if(mac.length()>=12) { - mShimmerMacId = mac.toUpperCase(); - mac = mac.replace(":", "").toUpperCase(); - mShimmerMacIdParsed = mac.substring(8); + if(mac.startsWith("Shimmer") && mac.contains("-")) { + //If using device name (e.g. Shimmer3-6813), then leave as is + mShimmerMacId = mac; + mShimmerMacId = mac; + } else { + mac = mac.replace("-", ""); + + if(mac.length()>=12) { + mShimmerMacId = mac.toUpperCase(); + mac = mac.replace(":", "").toUpperCase(); + mShimmerMacIdParsed = mac.substring(8); + } } } diff --git a/ShimmerDriverPC/src/main/java/com/shimmerresearch/pcDriver/ShimmerGRPC.java b/ShimmerDriverPC/src/main/java/com/shimmerresearch/pcDriver/ShimmerGRPC.java index 3ff0d57a8..a382d17bf 100644 --- a/ShimmerDriverPC/src/main/java/com/shimmerresearch/pcDriver/ShimmerGRPC.java +++ b/ShimmerDriverPC/src/main/java/com/shimmerresearch/pcDriver/ShimmerGRPC.java @@ -77,18 +77,12 @@ public ShimmerGRPC(String macAddress, String serverHost, int serverPort) { } public void InitializeProcess() { - // Define the server host and port - - // Create a channel to connect to the server - channel = ManagedChannelBuilder.forAddress(mServerHost, mServerPort) + channel = ManagedChannelBuilder.forTarget(mServerHost + ":" + mServerPort) .usePlaintext() // Use plaintext communication (insecure for testing) .build(); + // Create a gRPC client stub blockingStub = ShimmerBLEByteServerGrpc.newBlockingStub(channel); - - - - } @@ -98,7 +92,7 @@ public static void main(String[] args) { JButton btnNewButton = new JButton("Connect"); - final ShimmerGRPC shimmer = new ShimmerGRPC("E8EB1B713E36","localhost",50052); + final ShimmerGRPC shimmer = new ShimmerGRPC("E8EB1B713E36","localhost",50052); //On MacOS, the mac address has to be replaced with device name -> e.g. Shimmer3-6813 SensorDataReceived sdr = shimmer.new SensorDataReceived(); sdr.setWaitForData(shimmer); diff --git a/ShimmerPCBasicExamples/src/main/java/com/shimmerresearch/simpleexamples/SensorMapsExample.java b/ShimmerPCBasicExamples/src/main/java/com/shimmerresearch/simpleexamples/SensorMapsExample.java index c857be85a..81c966404 100644 --- a/ShimmerPCBasicExamples/src/main/java/com/shimmerresearch/simpleexamples/SensorMapsExample.java +++ b/ShimmerPCBasicExamples/src/main/java/com/shimmerresearch/simpleexamples/SensorMapsExample.java @@ -3,6 +3,7 @@ import javax.swing.JFrame; import com.shimmerresearch.bluetooth.ShimmerBluetooth.BT_STATE; +import com.shimmerresearch.comms.radioProtocol.ShimmerLiteProtocolInstructionSet.LiteProtocolInstructionSet.InstructionsGet; import com.shimmerresearch.driver.BasicProcessWithCallBack; import com.shimmerresearch.driver.CallbackObject; import com.shimmerresearch.driver.Configuration; @@ -93,8 +94,9 @@ public void initialize() { frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().setLayout(null); - JLabel lblSetComPort = new JLabel("Set COM Port (e.g. COMX or /dev/rfcommX) or Mac Address (e.g. XX:XX:XX:XX:XX:XX , note this requires grpc and BLE)"); - lblSetComPort.setBounds(10, 25, 1000, 23); + JLabel lblSetComPort = new JLabel("Windows: Set COM Port (e.g. COMX or /dev/rfcommX) or Mac Address (e.g. XX:XX:XX:XX:XX:XX , note this requires grpc and BLE)" + + " | MacOS: Set device name (e.g. Shimmer3-XXXX) - gRPC/BLE"); + lblSetComPort.setBounds(10, 25, 1200, 23); frame.getContentPane().add(lblSetComPort); textField = new JTextField(); @@ -108,7 +110,8 @@ public void initialize() { public void actionPerformed(ActionEvent arg0) { btComport = textField.getText(); - if (btComport.length()==17) { + if (btComport.length()==17 || (btComport.startsWith("Shimmer") && btComport.contains("-"))) { + //Mac address or device name (e.g. Shimmer3-6813) if (comboBox.getSelectedItem().equals("Shimmer3")) { BluetoothDeviceDetails bdd = new BluetoothDeviceDetails("", btComport, "Shimmer3BLE"); btManager.connectShimmer3BleGrpc(bdd); @@ -117,9 +120,9 @@ public void actionPerformed(ActionEvent arg0) { btManager.connectVerisenseDevice(bdd); } } else { + //COM port btManager.connectShimmerThroughCommPort(btComport); } - } }); btnConnect.setToolTipText("attempt connection to Shimmer device"); From 487f27699120c2d1b452fd1e9904f1185adce6fe Mon Sep 17 00:00:00 2001 From: jyong15 Date: Mon, 28 Apr 2025 13:30:08 +0800 Subject: [PATCH 02/19] DEV-221 DEV-232 - Fix Java examples - Updates for Consensys MacOS integration with BLE GRPC server from Shimmer Swift API --- .../ShimmerBluetoothManager.java | 6 ++-- .../driverUtilities/UtilShimmer.java | 5 +++ .../grpc/GrpcBLERadioByteTools.java | 28 +++++++++++---- .../shimmerresearch/pcDriver/ShimmerGRPC.java | 34 ++++++++++++++----- .../BasicShimmerBluetoothManagerPc.java | 10 ++++-- .../simpleexamples/SensorMapsExample.java | 10 ++++-- 6 files changed, 72 insertions(+), 21 deletions(-) diff --git a/ShimmerBluetoothManager/src/main/java/com/shimmerresearch/managers/bluetoothManager/ShimmerBluetoothManager.java b/ShimmerBluetoothManager/src/main/java/com/shimmerresearch/managers/bluetoothManager/ShimmerBluetoothManager.java index 5e9017487..3ebe04b90 100644 --- a/ShimmerBluetoothManager/src/main/java/com/shimmerresearch/managers/bluetoothManager/ShimmerBluetoothManager.java +++ b/ShimmerBluetoothManager/src/main/java/com/shimmerresearch/managers/bluetoothManager/ShimmerBluetoothManager.java @@ -55,7 +55,8 @@ public abstract class ShimmerBluetoothManager{ protected static final boolean USE_INFOMEM_CONFIG_METHOD = true; public static final long SLEEP_BETWEEN_GROUP_ACTIONS_MS = 50; public static final String COMPORT_PREFIX = "COM"; - public static final String COMPORT_PREFIX_MAC = "/dev/"; +// public static final String COMPORT_PREFIX_MAC = "/dev/"; + public static final String COMPORT_PREFIX_MAC = "Shimmer"; protected int mSyncTrainingIntervalInSeconds = 15; protected int msDelayBetweenSetCommands = 0; protected BluetoothProgressReportAll mProgressReportAll; @@ -836,7 +837,8 @@ else if(deviceTypeDetected==DEVICE_TYPE.ARDUINO){ if (shimmerDevice!=null && !(shimmerDevice instanceof ShimmerShell)){ printMessage("Connecting to " + shimmerDevice.getClass().getSimpleName() + " with connection handle = " + (connectThroughComPort? comPort:bluetoothAddress)); if(connectThroughComPort){ - if (!comPort.contains(COMPORT_PREFIX) && !comPort.contains(COMPORT_PREFIX_MAC)) { + if (!comPort.contains(COMPORT_PREFIX)) { + //Besides Windows, this is used on MacOS to connect Shimmer over BLE, as MacOS does not use BT Classic connectShimmer3BleGrpc(bluetoothDetails); }else { connectExistingShimmer(shimmerDevice, comPort, bluetoothAddress); diff --git a/ShimmerDriver/src/main/java/com/shimmerresearch/driverUtilities/UtilShimmer.java b/ShimmerDriver/src/main/java/com/shimmerresearch/driverUtilities/UtilShimmer.java index a988c4c65..b47659d04 100644 --- a/ShimmerDriver/src/main/java/com/shimmerresearch/driverUtilities/UtilShimmer.java +++ b/ShimmerDriver/src/main/java/com/shimmerresearch/driverUtilities/UtilShimmer.java @@ -1365,5 +1365,10 @@ public static int getTimeZoneOffset(){ // System.err.println(milliSeconds); // System.err.println(UtilShimmer.bytesToHexStringWithSpacesFormatted(convertMilliSecondsToShimmerRtcDataBytesLSB(milliSeconds))); // } + + public static boolean isOsMac() { + return System.getProperty("os.name").toLowerCase().contains("mac"); + } + } diff --git a/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java b/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java index 935ed98c3..3694f9b08 100644 --- a/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java +++ b/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java @@ -1,6 +1,7 @@ package com.shimmerresearch.grpc; import java.io.BufferedReader; +import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.net.ServerSocket; @@ -8,6 +9,9 @@ import java.util.List; import javax.swing.JFrame; + +import com.shimmerresearch.driverUtilities.UtilShimmer; + import javax.swing.JButton; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; @@ -15,17 +19,23 @@ public class GrpcBLERadioByteTools { private Process runningProcess; - String mExeName = "ShimmerBLEGrpc.exe"; - String mExePath = "C:\\Github\\Shimmer-C-API\\ShimmerAPI\\ShimmerBLEGrpc\\bin\\Debug\\" + mExeName; // Replace with the path to your .exe file + String mExeNameWindows = "ShimmerBLEGrpc.exe"; + String mExePathWindows = "C:\\Github\\Shimmer-C-API\\ShimmerAPI\\ShimmerBLEGrpc\\bin\\Debug\\" + mExeNameWindows; // Replace with the path to your .exe file //String exePath = "C:\\Users\\JC\\Desktop\\testgrpc\\ShimmerBLEGrpc.exe"; // Replace with the path to your .exe file + //Below used by Consensys MacOS + String mExeNameMac = "ShimmerBLEGrpc"; + String mExePathMac = System.getProperty("user.dir") + "/libs/ShimmerBLEGrpc/Products/usr/local/bin/" + mExeNameMac; + public GrpcBLERadioByteTools() { } public GrpcBLERadioByteTools(String exeName, String exePath) { - mExeName = exeName; - mExePath = exePath; + mExeNameWindows = exeName; + mExeNameMac = exeName; + mExePathWindows = exePath; + mExePathMac = exePath; } @@ -76,8 +86,14 @@ public int startServer() throws Exception { List command = new ArrayList<>(); // Add the command itself - command.add(mExePath); + if(UtilShimmer.isOsMac()) { + command.add(mExePathMac); + command.add("--port"); + } else { + command.add(mExePathWindows); + } command.add(Integer.toString(port)); + ProcessBuilder processBuilder = new ProcessBuilder(command); processBuilder.redirectErrorStream(true); // Redirect standard error to the input stream runningProcess = processBuilder.start(); @@ -142,7 +158,7 @@ public void actionPerformed(ActionEvent e) { JButton btnCheck = new JButton("checkServerApp"); btnCheck.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - if (grpcTools.isExeRunning(grpcTools.mExeName)) { + if (grpcTools.isExeRunning(grpcTools.mExeNameWindows)) { System.out.println("EXE RUNNING"); } else { System.out.println("EXE NOT RUNNING"); diff --git a/ShimmerDriverPC/src/main/java/com/shimmerresearch/pcDriver/ShimmerGRPC.java b/ShimmerDriverPC/src/main/java/com/shimmerresearch/pcDriver/ShimmerGRPC.java index a382d17bf..80e863b29 100644 --- a/ShimmerDriverPC/src/main/java/com/shimmerresearch/pcDriver/ShimmerGRPC.java +++ b/ShimmerDriverPC/src/main/java/com/shimmerresearch/pcDriver/ShimmerGRPC.java @@ -22,6 +22,7 @@ import com.shimmerresearch.driverUtilities.AssembleShimmerConfig; import com.shimmerresearch.driverUtilities.SensorDetails; import com.shimmerresearch.driverUtilities.ShimmerVerDetails.HW_ID; +import com.shimmerresearch.driverUtilities.UtilShimmer; import com.shimmerresearch.driverUtilities.ChannelDetails.CHANNEL_TYPE; import com.shimmerresearch.grpc.ShimmerBLEByteServerGrpc; import com.shimmerresearch.grpc.ShimmerBLEGRPC.BluetoothState; @@ -36,6 +37,7 @@ import io.grpc.ManagedChannel; import io.grpc.ManagedChannelBuilder; +import io.grpc.StatusRuntimeException; import io.grpc.stub.StreamObserver; import com.shimmerresearch.driver.BasicProcessWithCallBack; @@ -74,6 +76,9 @@ public ShimmerGRPC(String macAddress, String serverHost, int serverPort) { if (channel==null) { InitializeProcess(); } + if(UtilShimmer.isOsMac()) { + mComPort = mMacAddress; + } } public void InitializeProcess() { @@ -265,11 +270,18 @@ protected void writeBytes(byte[] data) { // Create a request message WriteBytes request = WriteBytes.newBuilder().setAddress(mMacAddress).setByteToWrite(ByteString.copyFrom(data)).build(); - // Call the remote gRPC service method - Reply response = blockingStub.writeBytesShimmer(request); - - // Process the response - System.out.println("Received: " + response.getMessage()); + try { + // Call the remote gRPC service method + Reply response = blockingStub.writeBytesShimmer(request); + + // Process the response + System.out.println("Received: " + response.getMessage()); + } catch(StatusRuntimeException sre) { + // Remote gRPC service is not available, so disconnect Shimmer device + sre.printStackTrace(); + System.out.println("ERROR: Lost connection to GRPC Server"); + connectionLost(); + } } @Override @@ -504,11 +516,15 @@ public void disconnect() throws ShimmerException { // Create a request message Request request = Request.newBuilder().setName(mMacAddress).build(); - // Call the remote gRPC service method - Reply response = blockingStub.disconnectShimmer(request); + try { + // Call the remote gRPC service method + Reply response = blockingStub.disconnectShimmer(request); + // Process the response + System.out.println("Received: " + response.getMessage()); + } catch(Exception e) { + e.printStackTrace(); + } - // Process the response - System.out.println("Received: " + response.getMessage()); closeConnection(); setBluetoothRadioState(BT_STATE.DISCONNECTED); } diff --git a/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/bluetooth/BasicShimmerBluetoothManagerPc.java b/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/bluetooth/BasicShimmerBluetoothManagerPc.java index b045c75cf..95d93488f 100644 --- a/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/bluetooth/BasicShimmerBluetoothManagerPc.java +++ b/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/bluetooth/BasicShimmerBluetoothManagerPc.java @@ -19,6 +19,7 @@ import com.shimmerresearch.driver.Configuration.COMMUNICATION_TYPE; import com.shimmerresearch.driver.shimmer4sdk.Shimmer4sdk; import com.shimmerresearch.driverUtilities.BluetoothDeviceDetails; +import com.shimmerresearch.driverUtilities.UtilShimmer; import com.shimmerresearch.exceptions.ConnectionExceptionListener; import com.shimmerresearch.exceptions.ShimmerException; import com.shimmerresearch.grpc.GrpcBLERadioByteCommunication; @@ -182,8 +183,12 @@ public void connectShimmer3BleGrpc(BluetoothDeviceDetails bdd) { ShimmerGRPC shimmer; if(!shimmer3BleMacIdList.contains(bdd.mShimmerMacId)) { - - shimmer = new ShimmerGRPC(bdd.mShimmerMacId.replace(":", ""),"localhost",mGRPCPort); + if(UtilShimmer.isOsMac()) { + //Use the mFriendlyName (e.g. Shimmer3-6813), because MacOS doesn't use BT MacID + shimmer = new ShimmerGRPC(bdd.mFriendlyName,"localhost",mGRPCPort); + } else { + shimmer = new ShimmerGRPC(bdd.mShimmerMacId.replace(":", ""),"localhost",mGRPCPort); + } shimmer.setShimmerUserAssignedName(bdd.mFriendlyName); shimmer.setMacIdFromUart(bdd.mShimmerMacId); initializeNewShimmerCommon(shimmer); @@ -193,6 +198,7 @@ public void connectShimmer3BleGrpc(BluetoothDeviceDetails bdd) { } else { shimmer = shimmer3BleDeviceList.get(shimmer3BleMacIdList.indexOf(bdd.mShimmerMacId)); + initializeNewShimmerCommon(shimmer); } try { diff --git a/ShimmerPCBasicExamples/src/main/java/com/shimmerresearch/simpleexamples/SensorMapsExample.java b/ShimmerPCBasicExamples/src/main/java/com/shimmerresearch/simpleexamples/SensorMapsExample.java index 81c966404..3c2c0af5d 100644 --- a/ShimmerPCBasicExamples/src/main/java/com/shimmerresearch/simpleexamples/SensorMapsExample.java +++ b/ShimmerPCBasicExamples/src/main/java/com/shimmerresearch/simpleexamples/SensorMapsExample.java @@ -15,6 +15,7 @@ import com.shimmerresearch.driverUtilities.BluetoothDeviceDetails; import com.shimmerresearch.driverUtilities.SensorDetails; import com.shimmerresearch.driverUtilities.ShimmerVerDetails.HW_ID; +import com.shimmerresearch.driverUtilities.UtilShimmer; import com.shimmerresearch.exceptions.ShimmerException; import com.shimmerresearch.grpc.ShimmerGRPC; import com.shimmerresearch.guiUtilities.configuration.EnableLowPowerModeDialog; @@ -113,8 +114,13 @@ public void actionPerformed(ActionEvent arg0) { if (btComport.length()==17 || (btComport.startsWith("Shimmer") && btComport.contains("-"))) { //Mac address or device name (e.g. Shimmer3-6813) if (comboBox.getSelectedItem().equals("Shimmer3")) { - BluetoothDeviceDetails bdd = new BluetoothDeviceDetails("", btComport, "Shimmer3BLE"); - btManager.connectShimmer3BleGrpc(bdd); + if(UtilShimmer.isOsMac()) { //MacOS uses the device name as both com port and friendly name + BluetoothDeviceDetails bdd = new BluetoothDeviceDetails("", btComport, btComport); + btManager.connectShimmer3BleGrpc(bdd); + } else { + BluetoothDeviceDetails bdd = new BluetoothDeviceDetails("", btComport, "Shimmer3BLE"); + btManager.connectShimmer3BleGrpc(bdd); + } } else if (comboBox.getSelectedItem().equals("Verisense")) { BluetoothDeviceDetails bdd = new BluetoothDeviceDetails(btComport, btComport, "ShimmerGRPC"); btManager.connectVerisenseDevice(bdd); From 04d5d2eb7006e9590685de2efb2b42b1538c1e41 Mon Sep 17 00:00:00 2001 From: jyong15 Date: Mon, 28 Apr 2025 14:13:24 +0800 Subject: [PATCH 03/19] DEV-232 Minor --- .../managers/bluetoothManager/ShimmerBluetoothManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ShimmerBluetoothManager/src/main/java/com/shimmerresearch/managers/bluetoothManager/ShimmerBluetoothManager.java b/ShimmerBluetoothManager/src/main/java/com/shimmerresearch/managers/bluetoothManager/ShimmerBluetoothManager.java index 3ebe04b90..2b379af4b 100644 --- a/ShimmerBluetoothManager/src/main/java/com/shimmerresearch/managers/bluetoothManager/ShimmerBluetoothManager.java +++ b/ShimmerBluetoothManager/src/main/java/com/shimmerresearch/managers/bluetoothManager/ShimmerBluetoothManager.java @@ -55,7 +55,7 @@ public abstract class ShimmerBluetoothManager{ protected static final boolean USE_INFOMEM_CONFIG_METHOD = true; public static final long SLEEP_BETWEEN_GROUP_ACTIONS_MS = 50; public static final String COMPORT_PREFIX = "COM"; -// public static final String COMPORT_PREFIX_MAC = "/dev/"; +// public static final String COMPORT_PREFIX_MAC = "/dev/"; //Commented-out as MacOS is relying on BT device name rather than COM PORT prefix public static final String COMPORT_PREFIX_MAC = "Shimmer"; protected int mSyncTrainingIntervalInSeconds = 15; protected int msDelayBetweenSetCommands = 0; From c953532f0b414cd9089af56b46b6e02520dc5463 Mon Sep 17 00:00:00 2001 From: jyong15 Date: Mon, 28 Apr 2025 16:53:30 +0800 Subject: [PATCH 04/19] DEV-221 DEV-232 Fix imports --- ShimmerDriver/build.gradle | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ShimmerDriver/build.gradle b/ShimmerDriver/build.gradle index 89ae445ed..36f81fa40 100644 --- a/ShimmerDriver/build.gradle +++ b/ShimmerDriver/build.gradle @@ -114,7 +114,7 @@ dependencies { // https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api api("javax.annotation:javax.annotation-api:1.3.2") - + // Declare the dependency for your favourite test framework you want to use in your tests. // TestNG is also supported by the Gradle Test task. Just change the // testCompile dependency to testCompile 'org.testng:testng:6.8.1' and add @@ -128,5 +128,11 @@ dependencies { testImplementation group: 'junit', name: 'junit', version: '4.+' api 'com.parse.bolts:bolts-tasks:1.4.0' + + // https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk15on + implementation("org.bouncycastle:bcpkix-jdk15on:1.61") + + // https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on + implementation("org.bouncycastle:bcprov-jdk15on:1.61") } From 50c722398661c84f9eda82392d9219db165613b2 Mon Sep 17 00:00:00 2001 From: jyong15 Date: Tue, 29 Apr 2025 09:31:09 +0800 Subject: [PATCH 05/19] DEV-221 try fix ShimmerDriverPc build --- ShimmerDriverPC/build.gradle | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ShimmerDriverPC/build.gradle b/ShimmerDriverPC/build.gradle index a556f79ae..f1527470f 100644 --- a/ShimmerDriverPC/build.gradle +++ b/ShimmerDriverPC/build.gradle @@ -95,4 +95,10 @@ dependencies { // 'test.useTestNG()' to your build script. testImplementation 'junit:junit:4.12' implementation 'com.parse.bolts:bolts-tasks:1.4.0' + + // https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk15on + implementation("org.bouncycastle:bcpkix-jdk15on:1.61") + + // https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on + implementation("org.bouncycastle:bcprov-jdk15on:1.61") } From 9d121bed1806303036bd457c500b4e3b0e42df1f Mon Sep 17 00:00:00 2001 From: jyong15 Date: Tue, 29 Apr 2025 13:45:14 +0800 Subject: [PATCH 06/19] DEV-232 DEV-221 remove log print in GrpcBLERadioByteCommunication --- .../com/shimmerresearch/grpc/GrpcBLERadioByteCommunication.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteCommunication.java b/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteCommunication.java index af47b88ab..34b47f75e 100644 --- a/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteCommunication.java +++ b/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteCommunication.java @@ -135,7 +135,7 @@ public void connect() throws ShimmerException { @Override public void onNext(StateStatus value) { // TODO Auto-generated method stub - System.out.println(value.getMessage() + " " + value.getState().toString()); +// System.out.println(value.getMessage() + " " + value.getState().toString()); if (value.getState().equals(BluetoothState.Connected)) { mConnectTask.setResult(true); From d374fc15b06f98e7b417c9a5d42557370fcfcd0f Mon Sep 17 00:00:00 2001 From: jyong15 Date: Fri, 9 May 2025 13:38:29 +0800 Subject: [PATCH 07/19] DEV-232 Update constructors in ShimmerGRPC to fix bugs with mac address --- .../shimmerresearch/pcDriver/ShimmerGRPC.java | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/ShimmerDriverPC/src/main/java/com/shimmerresearch/pcDriver/ShimmerGRPC.java b/ShimmerDriverPC/src/main/java/com/shimmerresearch/pcDriver/ShimmerGRPC.java index 80e863b29..a43b46da7 100644 --- a/ShimmerDriverPC/src/main/java/com/shimmerresearch/pcDriver/ShimmerGRPC.java +++ b/ShimmerDriverPC/src/main/java/com/shimmerresearch/pcDriver/ShimmerGRPC.java @@ -66,21 +66,29 @@ public class ShimmerGRPC extends ShimmerBluetooth implements Serializable{ * */ private static final long serialVersionUID = 5029128107276324956L; - + public ShimmerGRPC(String macAddress, String serverHost, int serverPort) { super(); mServerHost = serverHost; mServerPort = serverPort; mMacAddress = macAddress; + mMyBluetoothAddress = ""; mUseProcessingThread = true; if (channel==null) { InitializeProcess(); } - if(UtilShimmer.isOsMac()) { - mComPort = mMacAddress; - } } - + + /** + * This constructor is used for MacOS for BLE where the mFriendlyName is the BT device name (e.g. Shimmer3-6813). + * BT device name is used in place of COM Port which is Classic BT only + */ + public ShimmerGRPC(String macAddress, String mFriendlyName, String serverHost, int serverPort) { + this(mFriendlyName, serverHost, serverPort); + mMyBluetoothAddress = macAddress; + mComPort = mFriendlyName; + } + public void InitializeProcess() { channel = ManagedChannelBuilder.forTarget(mServerHost + ":" + mServerPort) .usePlaintext() // Use plaintext communication (insecure for testing) @@ -97,8 +105,10 @@ public static void main(String[] args) { JButton btnNewButton = new JButton("Connect"); - final ShimmerGRPC shimmer = new ShimmerGRPC("E8EB1B713E36","localhost",50052); //On MacOS, the mac address has to be replaced with device name -> e.g. Shimmer3-6813 - + final ShimmerGRPC shimmer = new ShimmerGRPC("E8EB1B713E36","localhost",50052); + //Use constructor below instead for MacOS, which uses the BT device name to connect, e.g. Shimmer3-6813 + //final ShimmerGRPC shimmer = new ShimmerGRPC("E8EB1B713E36","Shimmer3-3E36","localhost",50052); + SensorDataReceived sdr = shimmer.new SensorDataReceived(); sdr.setWaitForData(shimmer); From 0f135a72c6cb17a7e4c4560b9a0c5e4cb4c43bd8 Mon Sep 17 00:00:00 2001 From: jyong15 Date: Fri, 9 May 2025 13:40:22 +0800 Subject: [PATCH 08/19] DEV-232 Remove colons from Mac ID when connect Shimmer3BleGrpc --- .../bluetooth/BasicShimmerBluetoothManagerPc.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/bluetooth/BasicShimmerBluetoothManagerPc.java b/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/bluetooth/BasicShimmerBluetoothManagerPc.java index 95d93488f..902aaa2dc 100644 --- a/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/bluetooth/BasicShimmerBluetoothManagerPc.java +++ b/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/bluetooth/BasicShimmerBluetoothManagerPc.java @@ -181,23 +181,24 @@ public void connectVerisenseDevice(BluetoothDeviceDetails bdd) { @Override public void connectShimmer3BleGrpc(BluetoothDeviceDetails bdd) { ShimmerGRPC shimmer; + String macId = bdd.mShimmerMacId.replaceAll(":", ""); - if(!shimmer3BleMacIdList.contains(bdd.mShimmerMacId)) { + if(!shimmer3BleMacIdList.contains(macId)) { if(UtilShimmer.isOsMac()) { //Use the mFriendlyName (e.g. Shimmer3-6813), because MacOS doesn't use BT MacID - shimmer = new ShimmerGRPC(bdd.mFriendlyName,"localhost",mGRPCPort); + shimmer = new ShimmerGRPC(macId, bdd.mFriendlyName, "localhost", mGRPCPort); } else { - shimmer = new ShimmerGRPC(bdd.mShimmerMacId.replace(":", ""),"localhost",mGRPCPort); + shimmer = new ShimmerGRPC(macId, "localhost", mGRPCPort); } shimmer.setShimmerUserAssignedName(bdd.mFriendlyName); - shimmer.setMacIdFromUart(bdd.mShimmerMacId); + shimmer.setMacIdFromUart(macId); initializeNewShimmerCommon(shimmer); shimmer3BleDeviceList.add(shimmer); - shimmer3BleMacIdList.add(bdd.mShimmerMacId); + shimmer3BleMacIdList.add(macId); } else { - shimmer = shimmer3BleDeviceList.get(shimmer3BleMacIdList.indexOf(bdd.mShimmerMacId)); + shimmer = shimmer3BleDeviceList.get(shimmer3BleMacIdList.indexOf(macId)); initializeNewShimmerCommon(shimmer); } @@ -210,6 +211,7 @@ public void connectShimmer3BleGrpc(BluetoothDeviceDetails bdd) { e.printStackTrace(); } } + @Override public void connectShimmerThroughCommPort(String comPort){ directConnectUnknownShimmer=true; From 9b42214c9eb74b135bf74961060a4058d17f7fa4 Mon Sep 17 00:00:00 2001 From: jyong15 Date: Thu, 19 Jun 2025 13:05:58 +0800 Subject: [PATCH 09/19] DEV-221 DEV-270 minor update SensorMapsExample & update log print --- .../java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java | 2 +- .../com/shimmerresearch/simpleexamples/SensorMapsExample.java | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java b/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java index 3694f9b08..7a8721f34 100644 --- a/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java +++ b/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java @@ -101,7 +101,7 @@ public int startServer() throws Exception { try (BufferedReader reader = new BufferedReader(new InputStreamReader(runningProcess.getInputStream()))) { String line; while ((line = reader.readLine()) != null) { - System.out.println(line); + System.out.println("[BLEGrpcServer] " + line); } } catch (IOException e) { // TODO Auto-generated catch block diff --git a/ShimmerPCBasicExamples/src/main/java/com/shimmerresearch/simpleexamples/SensorMapsExample.java b/ShimmerPCBasicExamples/src/main/java/com/shimmerresearch/simpleexamples/SensorMapsExample.java index 3c2c0af5d..c8c949ed7 100644 --- a/ShimmerPCBasicExamples/src/main/java/com/shimmerresearch/simpleexamples/SensorMapsExample.java +++ b/ShimmerPCBasicExamples/src/main/java/com/shimmerresearch/simpleexamples/SensorMapsExample.java @@ -90,6 +90,9 @@ public class SensorMapsExample extends BasicProcessWithCallBack { * @wbp.parser.entryPoint */ public void initialize() { + //Set the default port to 50052, this is used if the software cannot start the gRPC server automatically + BasicShimmerBluetoothManagerPc.mGRPCPort = 50052; + frame = new JFrame("Shimmer SensorMaps Example"); frame.setBounds(100, 100, 1200, 591); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); From 3352eb12aac524bf1c5a278f0211c9ad567465bb Mon Sep 17 00:00:00 2001 From: jyong15 Date: Wed, 25 Jun 2025 13:18:07 +0800 Subject: [PATCH 10/19] DEV-221 DEV-325 refactor boolean for clarity --- .../tools/bluetooth/BasicShimmerBluetoothManagerPc.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/bluetooth/BasicShimmerBluetoothManagerPc.java b/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/bluetooth/BasicShimmerBluetoothManagerPc.java index 64fa28794..07669d4bb 100644 --- a/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/bluetooth/BasicShimmerBluetoothManagerPc.java +++ b/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/bluetooth/BasicShimmerBluetoothManagerPc.java @@ -47,8 +47,8 @@ public BasicShimmerBluetoothManagerPc() { startGrpc(); } - public BasicShimmerBluetoothManagerPc(boolean isInternalUse) { - if(isInternalUse) { + public BasicShimmerBluetoothManagerPc(boolean startGrpc) { + if(startGrpc) { startGrpc(); } } From a78e35fe2b187d72a914f91a3e518b43ba88cfd8 Mon Sep 17 00:00:00 2001 From: jyong15 Date: Wed, 9 Jul 2025 13:59:06 +0800 Subject: [PATCH 11/19] DEV-344 update path location for BLEGrpc for installed MacOS app --- .../grpc/GrpcBLERadioByteTools.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java b/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java index 935ed98c3..c8a989a4f 100644 --- a/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java +++ b/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java @@ -4,6 +4,10 @@ import java.io.IOException; import java.io.InputStreamReader; import java.net.ServerSocket; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; @@ -19,6 +23,11 @@ public class GrpcBLERadioByteTools { String mExePath = "C:\\Github\\Shimmer-C-API\\ShimmerAPI\\ShimmerBLEGrpc\\bin\\Debug\\" + mExeName; // Replace with the path to your .exe file //String exePath = "C:\\Users\\JC\\Desktop\\testgrpc\\ShimmerBLEGrpc.exe"; // Replace with the path to your .exe file + //Below used by Consensys MacOS + String userDir = System.getProperty("user.dir").equals("/") ? (getApplicationPath().toString() + "/libs/") : (System.getProperty("user.dir") + "/libs/"); + String mExeNameMac = "ShimmerBLEGrpc"; + String mExePathMac = userDir + "ShimmerBLEGrpc/Products/usr/local/bin/" + mExeNameMac; + public GrpcBLERadioByteTools() { } @@ -107,6 +116,18 @@ public void stopServer() { System.err.println("No external process is currently running."); } } + + public static Path getApplicationPath() { + try { + URL codeSourceUrl = GrpcBLERadioByteTools.class.getProtectionDomain().getCodeSource().getLocation(); + Path codeSourcePath = Paths.get(codeSourceUrl.toURI()); + if (codeSourcePath.toFile().isFile()) + return codeSourcePath.getParent(); + return codeSourcePath; + } catch (URISyntaxException e) { + throw new IllegalStateException("Failed to determine application path due to a URI syntax error.", e); + } + } public static void main(String[] args) { From 676ca7e97cb9a6090181ba542871070df90a59bb Mon Sep 17 00:00:00 2001 From: jyong15 Date: Tue, 26 Aug 2025 14:45:55 +0800 Subject: [PATCH 12/19] DEV-468 make startGrpc() method accessible --- .../tools/bluetooth/BasicShimmerBluetoothManagerPc.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/bluetooth/BasicShimmerBluetoothManagerPc.java b/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/bluetooth/BasicShimmerBluetoothManagerPc.java index b1edd5413..a955ff277 100644 --- a/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/bluetooth/BasicShimmerBluetoothManagerPc.java +++ b/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/bluetooth/BasicShimmerBluetoothManagerPc.java @@ -61,7 +61,7 @@ protected void startGrpc(String path) { } } - private void startGrpc() { + protected void startGrpc() { try { GrpcBLERadioByteTools grpcTool = new GrpcBLERadioByteTools(); mGRPCPort = grpcTool.startServer(); From e2306115b00d6d18bf6ae45edd8312aa5822952e Mon Sep 17 00:00:00 2001 From: jyong15 Date: Thu, 18 Sep 2025 13:52:10 +0800 Subject: [PATCH 13/19] DEV-448 WIP implementing check for whether BLE gRPC server is running --- .../grpc/GrpcBLERadioByteTools.java | 47 +++++++++++++++++-- .../BasicShimmerBluetoothManagerPc.java | 9 +++- 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java b/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java index e98e2c798..4b11434a2 100644 --- a/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java +++ b/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java @@ -11,6 +11,7 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.TimeUnit; import javax.swing.JFrame; @@ -82,9 +83,50 @@ public boolean isExeRunning(String exeName) { return false; } } + + public boolean isExeRunningMacOS(String exeName) { + try { + // Use 'pgrep -x' for an exact match of the process name. + // 'pgrep' returns the PIDs of matching processes, or nothing if not found. + // The '-x' flag ensures an exact match to the process name. + Process process = Runtime.getRuntime().exec(new String[]{"pgrep", "-x", exeName}); + // Read the output. If any line is read, it means a PID was found. + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + // Check if there's any output. If readLine() returns null, no process was found. + boolean found = reader.readLine() != null; + + // It's good practice to wait for the process to complete to release resources + // and to check its exit value if needed for more robust error handling. + // We'll add a timeout to prevent indefinite blocking. + if (!process.waitFor(5, TimeUnit.SECONDS)) { // Wait up to 5 seconds + process.destroy(); // Terminate the process if it doesn't exit + System.err.println("pgrep process timed out."); + return false; // Consider it not found or an error + } + + // Optionally, you could check the exit code: pgrep returns 0 if matches are found, 1 if none. + // int exitCode = process.exitValue(); + // return exitCode == 0; // This is an alternative way to check if found + + return found; // Return true if any line was read, false otherwise + } catch (IOException e) { + // Handle cases where the command cannot be executed (e.g., pgrep not found in PATH, permissions) + System.err.println("Error executing pgrep command: " + e.getMessage()); + e.printStackTrace(); + return false; + } catch (InterruptedException e) { + // Handle cases where the current thread is interrupted while waiting for the process + System.err.println("Thread interrupted while waiting for pgrep process: " + e.getMessage()); + Thread.currentThread().interrupt(); // Restore the interrupted status + return false; + } + } + + public boolean isServerRunning() { + return false; + } + public int startServer() throws Exception { - - int port = getFreePort(); System.out.println(port + " is free"); @@ -117,7 +159,6 @@ public int startServer() throws Exception { processThread.start(); return port; // You can continue with other tasks here - } public void stopServer() { diff --git a/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/bluetooth/BasicShimmerBluetoothManagerPc.java b/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/bluetooth/BasicShimmerBluetoothManagerPc.java index a955ff277..20f871ae4 100644 --- a/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/bluetooth/BasicShimmerBluetoothManagerPc.java +++ b/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/bluetooth/BasicShimmerBluetoothManagerPc.java @@ -41,6 +41,7 @@ public class BasicShimmerBluetoothManagerPc extends ShimmerBluetoothManager { List verisenseDeviceList = new ArrayList(); List shimmer3BleDeviceList = new ArrayList(); public static int mGRPCPort; + private GrpcBLERadioByteTools grpcTool; public BasicShimmerBluetoothManagerPc() { startGrpc(); @@ -54,7 +55,7 @@ public BasicShimmerBluetoothManagerPc(boolean enableGRPC) { protected void startGrpc(String path) { try { - GrpcBLERadioByteTools grpcTool = new GrpcBLERadioByteTools("ShimmerBLEGrpc.exe",path); + grpcTool = new GrpcBLERadioByteTools("ShimmerBLEGrpc.exe",path); mGRPCPort = grpcTool.startServer(); } catch(Exception e) { e.printStackTrace(); @@ -63,12 +64,16 @@ protected void startGrpc(String path) { protected void startGrpc() { try { - GrpcBLERadioByteTools grpcTool = new GrpcBLERadioByteTools(); + grpcTool = new GrpcBLERadioByteTools(); mGRPCPort = grpcTool.startServer(); } catch(Exception e) { e.printStackTrace(); } } + + public boolean isGrpcServerRunning() { + return grpcTool.isServerRunning(); + } public void setPathToVeriBLEApp(String path) { mPathToVeriBLEApp = path; From 5804f97e79218bde0ee3072c535da9d8267cd074 Mon Sep 17 00:00:00 2001 From: jyong15 Date: Mon, 29 Sep 2025 13:15:38 +0800 Subject: [PATCH 14/19] DEV-448 fix IOThread not stopping --- .../shimmerresearch/pcDriver/ShimmerGRPC.java | 48 ++++++++++--------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/ShimmerDriverPC/src/main/java/com/shimmerresearch/pcDriver/ShimmerGRPC.java b/ShimmerDriverPC/src/main/java/com/shimmerresearch/pcDriver/ShimmerGRPC.java index a43b46da7..901faafb5 100644 --- a/ShimmerDriverPC/src/main/java/com/shimmerresearch/pcDriver/ShimmerGRPC.java +++ b/ShimmerDriverPC/src/main/java/com/shimmerresearch/pcDriver/ShimmerGRPC.java @@ -539,29 +539,31 @@ public void disconnect() throws ShimmerException { setBluetoothRadioState(BT_STATE.DISCONNECTED); } - private void closeConnection(){ - try { - if (mIOThread != null) { - mIOThread.stop = true; - - // Closing serial port before before thread is finished stopping throws an error so waiting here - while(mIOThread != null && mIOThread.isAlive()); - - mIOThread = null; - - if(mUseProcessingThread){ - mPThread.stop = true; - mPThread = null; - } - } - mIsStreaming = false; - mIsInitialised = false; - - setBluetoothRadioState(BT_STATE.DISCONNECTED); - } catch (Exception ex) { - consolePrintException(ex.getMessage(), ex.getStackTrace()); - setBluetoothRadioState(BT_STATE.DISCONNECTED); - } + private void closeConnection() { + try { + if (mIOThread != null) { + mIOThread.stop = true; + + mIOThread.interrupt(); + mIOThread.join(); // Wait until the thread terminates + + mIOThread = null; + + if (mUseProcessingThread) { + mPThread.stop = true; + mIOThread.interrupt(); + mPThread.join(); + mPThread = null; + } + } + mIsStreaming = false; + mIsInitialised = false; + + setBluetoothRadioState(BT_STATE.DISCONNECTED); + } catch (Exception ex) { + consolePrintException(ex.getMessage(), ex.getStackTrace()); + setBluetoothRadioState(BT_STATE.DISCONNECTED); + } } //Need to override here because ShimmerDevice class uses a different map From bb3143e4d1bc9da1123a5a0e249391bafcd0ed1a Mon Sep 17 00:00:00 2001 From: jyong15 Date: Mon, 29 Sep 2025 13:25:39 +0800 Subject: [PATCH 15/19] DEV-448 fix typo --- .../main/java/com/shimmerresearch/pcDriver/ShimmerGRPC.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ShimmerDriverPC/src/main/java/com/shimmerresearch/pcDriver/ShimmerGRPC.java b/ShimmerDriverPC/src/main/java/com/shimmerresearch/pcDriver/ShimmerGRPC.java index 901faafb5..f9dc48001 100644 --- a/ShimmerDriverPC/src/main/java/com/shimmerresearch/pcDriver/ShimmerGRPC.java +++ b/ShimmerDriverPC/src/main/java/com/shimmerresearch/pcDriver/ShimmerGRPC.java @@ -543,15 +543,13 @@ private void closeConnection() { try { if (mIOThread != null) { mIOThread.stop = true; - mIOThread.interrupt(); mIOThread.join(); // Wait until the thread terminates - mIOThread = null; if (mUseProcessingThread) { mPThread.stop = true; - mIOThread.interrupt(); + mPThread.interrupt(); mPThread.join(); mPThread = null; } From 23483169dd70ef7987963cfd2805a8d1e3bb07c2 Mon Sep 17 00:00:00 2001 From: jyong15 Date: Mon, 29 Sep 2025 13:36:10 +0800 Subject: [PATCH 16/19] DEV-448 fix checks for running BLE Server --- .../grpc/GrpcBLERadioByteTools.java | 22 +++++-------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java b/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java index 4b11434a2..64440cb16 100644 --- a/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java +++ b/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java @@ -86,36 +86,22 @@ public boolean isExeRunning(String exeName) { public boolean isExeRunningMacOS(String exeName) { try { - // Use 'pgrep -x' for an exact match of the process name. - // 'pgrep' returns the PIDs of matching processes, or nothing if not found. - // The '-x' flag ensures an exact match to the process name. Process process = Runtime.getRuntime().exec(new String[]{"pgrep", "-x", exeName}); - // Read the output. If any line is read, it means a PID was found. BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); - // Check if there's any output. If readLine() returns null, no process was found. boolean found = reader.readLine() != null; - // It's good practice to wait for the process to complete to release resources - // and to check its exit value if needed for more robust error handling. - // We'll add a timeout to prevent indefinite blocking. if (!process.waitFor(5, TimeUnit.SECONDS)) { // Wait up to 5 seconds process.destroy(); // Terminate the process if it doesn't exit System.err.println("pgrep process timed out."); return false; // Consider it not found or an error } - // Optionally, you could check the exit code: pgrep returns 0 if matches are found, 1 if none. - // int exitCode = process.exitValue(); - // return exitCode == 0; // This is an alternative way to check if found - - return found; // Return true if any line was read, false otherwise + return found; } catch (IOException e) { - // Handle cases where the command cannot be executed (e.g., pgrep not found in PATH, permissions) System.err.println("Error executing pgrep command: " + e.getMessage()); e.printStackTrace(); return false; } catch (InterruptedException e) { - // Handle cases where the current thread is interrupted while waiting for the process System.err.println("Thread interrupted while waiting for pgrep process: " + e.getMessage()); Thread.currentThread().interrupt(); // Restore the interrupted status return false; @@ -123,7 +109,11 @@ public boolean isExeRunningMacOS(String exeName) { } public boolean isServerRunning() { - return false; + if(UtilShimmer.isOsMac()) { + return isExeRunningMacOS(mExeNameMac); + } else { + return isExeRunning(mExeNameWindows); + } } public int startServer() throws Exception { From 9e631a2a0272d3042d5068e6c9b255cfb891ad30 Mon Sep 17 00:00:00 2001 From: JongChern Date: Tue, 30 Sep 2025 14:46:59 +0800 Subject: [PATCH 17/19] Update BasicShimmerBluetoothManagerPc.java --- .../tools/bluetooth/BasicShimmerBluetoothManagerPc.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/bluetooth/BasicShimmerBluetoothManagerPc.java b/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/bluetooth/BasicShimmerBluetoothManagerPc.java index a955ff277..b035bce8b 100644 --- a/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/bluetooth/BasicShimmerBluetoothManagerPc.java +++ b/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/bluetooth/BasicShimmerBluetoothManagerPc.java @@ -37,9 +37,9 @@ public class BasicShimmerBluetoothManagerPc extends ShimmerBluetoothManager { String mPathToVeriBLEApp = "bleconsoleapp\\BLEConsoleApp1.exe"; List verisenseMacIdList = new ArrayList(); - List shimmer3BleMacIdList = new ArrayList(); + protected List shimmer3BleMacIdList = new ArrayList(); List verisenseDeviceList = new ArrayList(); - List shimmer3BleDeviceList = new ArrayList(); + protected List shimmer3BleDeviceList = new ArrayList(); public static int mGRPCPort; public BasicShimmerBluetoothManagerPc() { From 67ed359cfa493841aba39c0419b2ae1f4bb4131d Mon Sep 17 00:00:00 2001 From: jyong15 Date: Wed, 29 Oct 2025 14:02:12 +0800 Subject: [PATCH 18/19] DEV-516 improve logging of BLE Server - add exit code --- .../java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java b/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java index 64440cb16..d172f2dbd 100644 --- a/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java +++ b/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java @@ -145,6 +145,11 @@ public int startServer() throws Exception { e.printStackTrace(); } }); + runningProcess.onExit().thenAccept(p -> { + int code = p.exitValue(); + System.err.println("[BLEGrpcServer] exited: code=" + code + + (code >= 128 ? " (likely signal " + (code - 128) + ")" : "")); + }); processThread.start(); return port; From 6c50e11473fecc2b334a7c4227bbe568c46df954 Mon Sep 17 00:00:00 2001 From: jyong15 Date: Thu, 30 Oct 2025 13:40:42 +0800 Subject: [PATCH 19/19] DEV-516 add shutdown hook to ensure BLE Server closes --- .../grpc/GrpcBLERadioByteTools.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java b/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java index d172f2dbd..254d1ce60 100644 --- a/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java +++ b/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java @@ -134,6 +134,14 @@ public int startServer() throws Exception { ProcessBuilder processBuilder = new ProcessBuilder(command); processBuilder.redirectErrorStream(true); // Redirect standard error to the input stream runningProcess = processBuilder.start(); + + // Add shutdown hook to ensure server is closed when Java app exits + try { + Runtime.getRuntime().addShutdownHook(shutdownHook); + } catch (IllegalStateException ignored) { + // JVM is already shutting down + } + Thread processThread = new Thread(() -> { try (BufferedReader reader = new BufferedReader(new InputStreamReader(runningProcess.getInputStream()))) { String line; @@ -155,6 +163,25 @@ public int startServer() throws Exception { return port; // You can continue with other tasks here } + + private final Thread shutdownHook = new Thread(() -> { + Process p = runningProcess; + if (p == null) return; + + try { + // Try graceful termination first + p.destroy(); // sends SIGTERM on Unix, WM_CLOSE/CTRL_BREAK semantics vary on Windows + if (!p.waitFor(3, java.util.concurrent.TimeUnit.SECONDS)) { + // Fall back to force kill + p.destroyForcibly(); + p.waitFor(2, java.util.concurrent.TimeUnit.SECONDS); + } + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + } catch (Exception e) { + e.printStackTrace(); + } + }); public void stopServer() { if (runningProcess != null) {