Skip to content

Commit db798cc

Browse files
committed
Merge branch 'master' into DEV-569
2 parents d209b35 + cb73641 commit db798cc

File tree

12 files changed

+322
-86
lines changed

12 files changed

+322
-86
lines changed

ShimmerBluetoothManager/src/main/java/com/shimmerresearch/managers/bluetoothManager/ShimmerBluetoothManager.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838

3939
public abstract class ShimmerBluetoothManager{
4040

41+
protected boolean mVerbose = true;
4142
protected boolean directConnectUnknownShimmer=false;
4243

4344
/** Key is the COM port in PC and BT address for Android*/
@@ -55,7 +56,8 @@ public abstract class ShimmerBluetoothManager{
5556
protected static final boolean USE_INFOMEM_CONFIG_METHOD = true;
5657
public static final long SLEEP_BETWEEN_GROUP_ACTIONS_MS = 50;
5758
public static final String COMPORT_PREFIX = "COM";
58-
public static final String COMPORT_PREFIX_MAC = "/dev/";
59+
// public static final String COMPORT_PREFIX_MAC = "/dev/"; //Commented-out as MacOS is relying on BT device name rather than COM PORT prefix
60+
public static final String COMPORT_PREFIX_MAC = "Shimmer";
5961
protected int mSyncTrainingIntervalInSeconds = 15;
6062
protected int msDelayBetweenSetCommands = 0;
6163
protected BluetoothProgressReportAll mProgressReportAll;
@@ -288,6 +290,10 @@ else if (selectedShimmer instanceof Shimmer4sdk) {
288290
}
289291

290292

293+
public void setVerbose(boolean verbose){
294+
mVerbose = verbose;
295+
}
296+
291297
/** Use setFixedConfigWhenConnecting instead
292298
*
293299
* @param device
@@ -473,6 +479,7 @@ protected void putShimmerBtConnectedMap(ShimmerDevice shimmerDevice){
473479
String connectionHandle = shimmerDevice.getBtConnectionHandle();
474480
ShimmerDevice existingShimmer = getShimmerDeviceBtConnected(connectionHandle);
475481
if (existingShimmer==null){
482+
shimmerDevice.mVerboseMode = this.mVerbose;
476483
System.err.println("Putting Shimmer in BT connected map with connectionHandle:" + (connectionHandle.isEmpty()? "EMPTY":connectionHandle));
477484
mMapOfBtConnectedShimmers.put(connectionHandle, shimmerDevice);
478485
}
@@ -836,7 +843,8 @@ else if(deviceTypeDetected==DEVICE_TYPE.ARDUINO){
836843
if (shimmerDevice!=null && !(shimmerDevice instanceof ShimmerShell)){
837844
printMessage("Connecting to " + shimmerDevice.getClass().getSimpleName() + " with connection handle = " + (connectThroughComPort? comPort:bluetoothAddress));
838845
if(connectThroughComPort){
839-
if (!comPort.contains(COMPORT_PREFIX) && !comPort.contains(COMPORT_PREFIX_MAC)) {
846+
if (!comPort.contains(COMPORT_PREFIX)) {
847+
//Besides Windows, this is used on MacOS to connect Shimmer over BLE, as MacOS does not use BT Classic
840848
connectShimmer3BleGrpc(bluetoothDetails);
841849
}else {
842850
connectExistingShimmer(shimmerDevice, comPort, bluetoothAddress);

ShimmerDriver/build.gradle

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ dependencies {
9595
api group: 'com.google.protobuf', name: 'protobuf-java', version: '3.4.0'
9696

9797
// https://mvnrepository.com/artifact/io.grpc/grpc-all
98-
api group: 'io.grpc', name: 'grpc-all', version: '1.32.1'
98+
api group: 'io.grpc', name: 'grpc-all', version: '1.71.0'
9999

100100
// https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient
101101
api group: 'org.apache.httpcomponents', name: 'httpclient', version: '4.3.6'
@@ -116,7 +116,7 @@ dependencies {
116116

117117
// https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api
118118
api("javax.annotation:javax.annotation-api:1.3.2")
119-
119+
120120
// Declare the dependency for your favourite test framework you want to use in your tests.
121121
// TestNG is also supported by the Gradle Test task. Just change the
122122
// testCompile dependency to testCompile 'org.testng:testng:6.8.1' and add
@@ -130,5 +130,11 @@ dependencies {
130130
testImplementation group: 'junit', name: 'junit', version: '4.+'
131131

132132
api 'com.parse.bolts:bolts-tasks:1.4.0'
133+
134+
// https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk15on
135+
implementation("org.bouncycastle:bcpkix-jdk15on:1.61")
136+
137+
// https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on
138+
implementation("org.bouncycastle:bcprov-jdk15on:1.61")
133139
}
134140

ShimmerDriver/src/main/java/com/shimmerresearch/driverUtilities/BluetoothDeviceDetails.java

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,18 @@ public BluetoothDeviceDetails(String comPort, String macId, String friendlyName)
3333
}
3434

3535
public void setMacId(String mac){
36-
37-
mac = mac.replace("-", "");
38-
39-
if(mac.length()>=12) {
40-
mShimmerMacId = mac.toUpperCase();
41-
mac = mac.replace(":", "").toUpperCase();
42-
mShimmerMacIdParsed = mac.substring(8);
36+
if(mac.startsWith("Shimmer") && mac.contains("-")) {
37+
//If using device name (e.g. Shimmer3-6813), then leave as is
38+
mShimmerMacId = mac;
39+
mShimmerMacId = mac;
40+
} else {
41+
mac = mac.replace("-", "");
42+
43+
if(mac.length()>=12) {
44+
mShimmerMacId = mac.toUpperCase();
45+
mac = mac.replace(":", "").toUpperCase();
46+
mShimmerMacIdParsed = mac.substring(8);
47+
}
4348
}
4449
}
4550

ShimmerDriver/src/main/java/com/shimmerresearch/driverUtilities/HwDriverShimmerDeviceDetails.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,14 +148,27 @@ public static final class MASS_STORAGE_DEVICE {
148148
public static final String[] SHIMMER_3R = new String[] {
149149
"VID_0483&PID_52A4",
150150
};
151+
152+
public static final String[] SHIMMER_3R_USB_DFU = new String[] {
153+
"VID_0483&PID_DF11",
154+
};
155+
151156

152157
public static final String[] SHIMMER = new String[] {
153158
"shimmer",
154159
};
160+
161+
public static final String[] VERISENSE_USB = new String[] {
162+
"VID_1915&PID_520F",
163+
};
164+
165+
public static final String[] VERISENSE = new String[] {
166+
"verisense",
167+
};
155168

156-
public static final String[] SHIMMER3R_COMPOSITE_DEVICE = new String[] { "SHIMMER COMPOSITE DEVICE" };
169+
public static final String[] SHIMMER3R_COMPOSITE_DEVICE = new String[] { "SHIMMER COMPOSITE DEVICE","STM32 COMPOSITE DEVICE"};
157170

158-
public static final String[] SHIMMER3R_MSC_DEVICE = new String[] { "SHIMMER MSC DEVICE" };
171+
public static final String[] SHIMMER3R_MSC_DEVICE = new String[] { "SHIMMER MSC","STM32 MSC DEVICE" };
159172

160173
public static final class SERVICE_DESCRIPTION {
161174
public static final String[] COMPOSITE_DEVICE = new String[]{"USB Composite Device"};

ShimmerDriver/src/main/java/com/shimmerresearch/driverUtilities/UtilShimmer.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,28 @@ public static boolean stringContainsItemFromList(String inputString, String[] it
801801
}
802802
return false;
803803
}
804+
805+
public static boolean stringContainsOnlyWordsItemFromList(String inputString, String[] items) {
806+
807+
boolean allMatched = true;
808+
String target = inputString.toUpperCase();
809+
810+
for (String item : items) {
811+
812+
String[] words = item.toUpperCase().split("\\s+");
813+
for (String w : words) {
814+
if (!target.contains(w)) {
815+
allMatched = false;
816+
}
817+
}
818+
819+
if(allMatched) {
820+
return true;
821+
}
822+
}
823+
824+
return false;
825+
}
804826

805827
public void threadSleep(long millis) {
806828
millisecondDelay(millis);
@@ -1368,5 +1390,10 @@ public static int getTimeZoneOffset(){
13681390
// System.err.println(milliSeconds);
13691391
// System.err.println(UtilShimmer.bytesToHexStringWithSpacesFormatted(convertMilliSecondsToShimmerRtcDataBytesLSB(milliSeconds)));
13701392
// }
1393+
1394+
public static boolean isOsMac() {
1395+
return System.getProperty("os.name").toLowerCase().contains("mac");
1396+
}
1397+
13711398

13721399
}

ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteCommunication.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ public void connect() throws ShimmerException {
135135
@Override
136136
public void onNext(StateStatus value) {
137137
// TODO Auto-generated method stub
138-
System.out.println(value.getMessage() + " " + value.getState().toString());
138+
// System.out.println(value.getMessage() + " " + value.getState().toString());
139139
if (value.getState().equals(BluetoothState.Connected)) {
140140
mConnectTask.setResult(true);
141141

ShimmerDriver/src/main/java/com/shimmerresearch/grpc/GrpcBLERadioByteTools.java

Lines changed: 106 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,47 @@
11
package com.shimmerresearch.grpc;
22

33
import java.io.BufferedReader;
4+
import java.io.File;
45
import java.io.IOException;
56
import java.io.InputStreamReader;
67
import java.net.ServerSocket;
8+
import java.net.URISyntaxException;
9+
import java.net.URL;
10+
import java.nio.file.Path;
11+
import java.nio.file.Paths;
712
import java.util.ArrayList;
813
import java.util.List;
14+
import java.util.concurrent.TimeUnit;
915

1016
import javax.swing.JFrame;
17+
18+
import com.shimmerresearch.driverUtilities.UtilShimmer;
19+
1120
import javax.swing.JButton;
1221
import java.awt.event.ActionListener;
1322
import java.awt.event.ActionEvent;
1423

1524
public class GrpcBLERadioByteTools {
1625

1726
private Process runningProcess;
18-
String mExeName = "ShimmerBLEGrpc.exe";
19-
String mExePath = "C:\\Github\\Shimmer-C-API\\ShimmerAPI\\ShimmerBLEGrpc\\bin\\Debug\\" + mExeName; // Replace with the path to your .exe file
27+
String mExeNameWindows = "ShimmerBLEGrpc.exe";
28+
String mExePathWindows = "C:\\Github\\Shimmer-C-API\\ShimmerAPI\\ShimmerBLEGrpc\\bin\\Debug\\" + mExeNameWindows; // Replace with the path to your .exe file
2029
//String exePath = "C:\\Users\\JC\\Desktop\\testgrpc\\ShimmerBLEGrpc.exe"; // Replace with the path to your .exe file
2130

22-
public GrpcBLERadioByteTools() {
31+
//Below used by Consensys MacOS
32+
String userDir = System.getProperty("user.dir").equals("/") ? (getApplicationPath().toString() + "/libs/") : (System.getProperty("user.dir") + "/libs/");
33+
String mExeNameMac = "ShimmerBLEGrpc";
34+
String mExePathMac = userDir + "ShimmerBLEGrpc/Products/usr/local/bin/" + mExeNameMac;
35+
36+
public GrpcBLERadioByteTools() {
2337

2438
}
2539

2640
public GrpcBLERadioByteTools(String exeName, String exePath) {
27-
mExeName = exeName;
28-
mExePath = exePath;
41+
mExeNameWindows = exeName;
42+
mExeNameMac = exeName;
43+
mExePathWindows = exePath;
44+
mExePathMac = exePath;
2945
}
3046

3147

@@ -67,37 +83,105 @@ public boolean isExeRunning(String exeName) {
6783
return false;
6884
}
6985
}
70-
public int startServer() throws Exception {
86+
87+
public boolean isExeRunningMacOS(String exeName) {
88+
try {
89+
Process process = Runtime.getRuntime().exec(new String[]{"pgrep", "-x", exeName});
90+
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
91+
boolean found = reader.readLine() != null;
92+
93+
if (!process.waitFor(5, TimeUnit.SECONDS)) { // Wait up to 5 seconds
94+
process.destroy(); // Terminate the process if it doesn't exit
95+
System.err.println("pgrep process timed out.");
96+
return false; // Consider it not found or an error
97+
}
7198

99+
return found;
100+
} catch (IOException e) {
101+
System.err.println("Error executing pgrep command: " + e.getMessage());
102+
e.printStackTrace();
103+
return false;
104+
} catch (InterruptedException e) {
105+
System.err.println("Thread interrupted while waiting for pgrep process: " + e.getMessage());
106+
Thread.currentThread().interrupt(); // Restore the interrupted status
107+
return false;
108+
}
109+
}
72110

111+
public boolean isServerRunning() {
112+
if(UtilShimmer.isOsMac()) {
113+
return isExeRunningMacOS(mExeNameMac);
114+
} else {
115+
return isExeRunning(mExeNameWindows);
116+
}
117+
}
118+
119+
public int startServer() throws Exception {
73120
int port = getFreePort();
74121

75122
System.out.println(port + " is free");
76123
List<String> command = new ArrayList<>();
77124

78125
// Add the command itself
79-
command.add(mExePath);
126+
if(UtilShimmer.isOsMac()) {
127+
command.add(mExePathMac);
128+
command.add("--port");
129+
} else {
130+
command.add(mExePathWindows);
131+
}
80132
command.add(Integer.toString(port));
133+
81134
ProcessBuilder processBuilder = new ProcessBuilder(command);
82135
processBuilder.redirectErrorStream(true); // Redirect standard error to the input stream
83136
runningProcess = processBuilder.start();
137+
138+
// Add shutdown hook to ensure server is closed when Java app exits
139+
try {
140+
Runtime.getRuntime().addShutdownHook(shutdownHook);
141+
} catch (IllegalStateException ignored) {
142+
// JVM is already shutting down
143+
}
144+
84145
Thread processThread = new Thread(() -> {
85146
try (BufferedReader reader = new BufferedReader(new InputStreamReader(runningProcess.getInputStream()))) {
86147
String line;
87148
while ((line = reader.readLine()) != null) {
88-
System.out.println(line);
149+
System.out.println("[BLEGrpcServer] " + line);
89150
}
90151
} catch (IOException e) {
91152
// TODO Auto-generated catch block
92153
e.printStackTrace();
93154
}
94155
});
156+
runningProcess.onExit().thenAccept(p -> {
157+
int code = p.exitValue();
158+
System.err.println("[BLEGrpcServer] exited: code=" + code +
159+
(code >= 128 ? " (likely signal " + (code - 128) + ")" : ""));
160+
});
95161

96162
processThread.start();
97163
return port;
98164
// You can continue with other tasks here
99-
100165
}
166+
167+
private final Thread shutdownHook = new Thread(() -> {
168+
Process p = runningProcess;
169+
if (p == null) return;
170+
171+
try {
172+
// Try graceful termination first
173+
p.destroy(); // sends SIGTERM on Unix, WM_CLOSE/CTRL_BREAK semantics vary on Windows
174+
if (!p.waitFor(3, java.util.concurrent.TimeUnit.SECONDS)) {
175+
// Fall back to force kill
176+
p.destroyForcibly();
177+
p.waitFor(2, java.util.concurrent.TimeUnit.SECONDS);
178+
}
179+
} catch (InterruptedException ie) {
180+
Thread.currentThread().interrupt();
181+
} catch (Exception e) {
182+
e.printStackTrace();
183+
}
184+
});
101185

102186
public void stopServer() {
103187
if (runningProcess != null) {
@@ -107,6 +191,18 @@ public void stopServer() {
107191
System.err.println("No external process is currently running.");
108192
}
109193
}
194+
195+
public static Path getApplicationPath() {
196+
try {
197+
URL codeSourceUrl = GrpcBLERadioByteTools.class.getProtectionDomain().getCodeSource().getLocation();
198+
Path codeSourcePath = Paths.get(codeSourceUrl.toURI());
199+
if (codeSourcePath.toFile().isFile())
200+
return codeSourcePath.getParent();
201+
return codeSourcePath;
202+
} catch (URISyntaxException e) {
203+
throw new IllegalStateException("Failed to determine application path due to a URI syntax error.", e);
204+
}
205+
}
110206

111207
public static void main(String[] args) {
112208

@@ -142,7 +238,7 @@ public void actionPerformed(ActionEvent e) {
142238
JButton btnCheck = new JButton("checkServerApp");
143239
btnCheck.addActionListener(new ActionListener() {
144240
public void actionPerformed(ActionEvent e) {
145-
if (grpcTools.isExeRunning(grpcTools.mExeName)) {
241+
if (grpcTools.isExeRunning(grpcTools.mExeNameWindows)) {
146242
System.out.println("EXE RUNNING");
147243
} else {
148244
System.out.println("EXE NOT RUNNING");

ShimmerDriverPC/build.gradle

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,12 @@ dependencies {
9999
// 'test.useTestNG()' to your build script.
100100
testImplementation 'junit:junit:4.12'
101101
implementation 'com.parse.bolts:bolts-tasks:1.4.0'
102+
103+
// https://mvnrepository.com/artifact/org.bouncycastle/bcpkix-jdk15on
104+
implementation("org.bouncycastle:bcpkix-jdk15on:1.61")
105+
106+
// https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on
107+
implementation("org.bouncycastle:bcprov-jdk15on:1.61")
102108
}
103109

104110
// Shadow JAR task to create a runnable JAR with dependencies

0 commit comments

Comments
 (0)