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 a68b024ec..0aff19939 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/"; //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; 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/build.gradle b/ShimmerDriver/build.gradle index 8189c8c9c..f0cdc3b62 100644 --- a/ShimmerDriver/build.gradle +++ b/ShimmerDriver/build.gradle @@ -95,7 +95,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' @@ -116,7 +116,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 @@ -130,5 +130,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") } 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/ShimmerDriver/src/main/java/com/shimmerresearch/driverUtilities/UtilShimmer.java b/ShimmerDriver/src/main/java/com/shimmerresearch/driverUtilities/UtilShimmer.java index c34293add..024b1ba44 100644 --- a/ShimmerDriver/src/main/java/com/shimmerresearch/driverUtilities/UtilShimmer.java +++ b/ShimmerDriver/src/main/java/com/shimmerresearch/driverUtilities/UtilShimmer.java @@ -1368,5 +1368,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/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); diff --git a/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java b/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java index 935ed98c3..254d1ce60 100644 --- a/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java +++ b/ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java @@ -1,13 +1,22 @@ package com.shimmerresearch.grpc; import java.io.BufferedReader; +import java.io.File; 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; +import java.util.concurrent.TimeUnit; 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 +24,24 @@ 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 - public GrpcBLERadioByteTools() { + //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() { } public GrpcBLERadioByteTools(String exeName, String exePath) { - mExeName = exeName; - mExePath = exePath; + mExeNameWindows = exeName; + mExeNameMac = exeName; + mExePathWindows = exePath; + mExePathMac = exePath; } @@ -67,37 +83,105 @@ public boolean isExeRunning(String exeName) { return false; } } - public int startServer() throws Exception { + + public boolean isExeRunningMacOS(String exeName) { + try { + Process process = Runtime.getRuntime().exec(new String[]{"pgrep", "-x", exeName}); + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + boolean found = reader.readLine() != null; + + 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 + } + return found; + } catch (IOException e) { + System.err.println("Error executing pgrep command: " + e.getMessage()); + e.printStackTrace(); + return false; + } catch (InterruptedException e) { + System.err.println("Thread interrupted while waiting for pgrep process: " + e.getMessage()); + Thread.currentThread().interrupt(); // Restore the interrupted status + return false; + } + } + public boolean isServerRunning() { + if(UtilShimmer.isOsMac()) { + return isExeRunningMacOS(mExeNameMac); + } else { + return isExeRunning(mExeNameWindows); + } + } + + public int startServer() throws Exception { int port = getFreePort(); System.out.println(port + " is free"); 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(); + + // 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; while ((line = reader.readLine()) != null) { - System.out.println(line); + System.out.println("[BLEGrpcServer] " + line); } } catch (IOException e) { // TODO Auto-generated catch block 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; // 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) { @@ -107,6 +191,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) { @@ -142,7 +238,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/build.gradle b/ShimmerDriverPC/build.gradle index b6d05e7ab..edd3dd083 100644 --- a/ShimmerDriverPC/build.gradle +++ b/ShimmerDriverPC/build.gradle @@ -99,6 +99,12 @@ 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") } // Shadow JAR task to create a runnable JAR with dependencies diff --git a/ShimmerDriverPC/src/main/java/com/shimmerresearch/pcDriver/ShimmerGRPC.java b/ShimmerDriverPC/src/main/java/com/shimmerresearch/pcDriver/ShimmerGRPC.java index 3ff0d57a8..f9dc48001 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; @@ -64,31 +66,36 @@ 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(); } } - + + /** + * 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() { - // 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,8 +105,10 @@ 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); + //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); @@ -271,11 +280,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 @@ -510,38 +526,42 @@ 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); } - 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; + mPThread.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 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 50d5ec42c..7bab26eb4 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; @@ -36,10 +37,11 @@ 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; + private GrpcBLERadioByteTools grpcTool; public BasicShimmerBluetoothManagerPc() { startGrpc(); @@ -53,21 +55,25 @@ 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(); } } - private void startGrpc() { + 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; @@ -199,19 +205,25 @@ public void connectVerisenseDevice(BluetoothDeviceDetails bdd) { @Override public void connectShimmer3BleGrpc(BluetoothDeviceDetails bdd) { ShimmerGRPC shimmer; + String macId = bdd.mShimmerMacId.replaceAll(":", ""); - if(!shimmer3BleMacIdList.contains(bdd.mShimmerMacId)) { - - shimmer = new ShimmerGRPC(bdd.mShimmerMacId.replace(":", ""),"localhost",mGRPCPort); + if(!shimmer3BleMacIdList.contains(macId)) { + if(UtilShimmer.isOsMac()) { + //Use the mFriendlyName (e.g. Shimmer3-6813), because MacOS doesn't use BT MacID + shimmer = new ShimmerGRPC(macId, bdd.mFriendlyName, "localhost", mGRPCPort); + } else { + 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); } try { @@ -223,6 +235,7 @@ public void connectShimmer3BleGrpc(BluetoothDeviceDetails bdd) { e.printStackTrace(); } } + @Override public void connectShimmerThroughCommPort(String comPort){ directConnectUnknownShimmer=true; diff --git a/ShimmerPCBasicExamples/src/main/java/com/shimmerresearch/simpleexamples/SensorMapsExample.java b/ShimmerPCBasicExamples/src/main/java/com/shimmerresearch/simpleexamples/SensorMapsExample.java index 49d95fd17..4a45d850d 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; @@ -14,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; @@ -88,13 +90,17 @@ 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); 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,18 +114,24 @@ 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); + 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); } } else { + //COM port btManager.connectShimmerThroughCommPort(btComport); } - } }); btnConnect.setToolTipText("attempt connection to Shimmer device");