Skip to content

Commit 6016d2c

Browse files
authored
Merge pull request #203 from ShimmerEngineering/DEV-135
DEV-135
2 parents faa20d3 + e53478f commit 6016d2c

8 files changed

Lines changed: 311 additions & 7 deletions

File tree

ShimmerBluetoothManager/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ Rev0.2
1212

1313
sourceCompatibility = 1.11
1414
targetCompatibility = 1.11
15+
//sourceCompatibility = '1.8' // Ensure code is compiled with Java 8 when compiling ShimmerJavaClass for Matlab see ShimmerDriverPC (build.gradle)
16+
//targetCompatibility = '1.8' // Ensure bytecode is compatible with Java 8 when compiling ShimmerJavaClass for Matlab see ShimmerDriverPC (build.gradle)
1517

1618
repositories {
1719
mavenCentral()

ShimmerDriver/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ Rev0.2
1515
apply plugin: 'java-library'
1616
sourceCompatibility = 1.11
1717
targetCompatibility = 1.11
18+
//sourceCompatibility = '1.8' // Ensure code is compiled with Java 8 when compiling ShimmerJavaClass for Matlab see ShimmerDriverPC (build.gradle)
19+
//targetCompatibility = '1.8' // Ensure bytecode is compatible with Java 8 when compiling ShimmerJavaClass for Matlab see ShimmerDriverPC (build.gradle)
1820

1921
repositories {
2022
mavenCentral()

ShimmerDriver/src/main/java/com/shimmerresearch/driver/Configuration.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -677,7 +677,7 @@ public class SensorBitmap{
677677
* data packets. The firmware also uses the IMU IDs as Sensor IDs in the
678678
* IMU/BMP calibration bytes.
679679
*/
680-
public class SENSOR_ID{
680+
public static class SENSOR_ID{
681681
public static final int RESERVED_ANY_SENSOR = -1;
682682

683683
public static final int HOST_SHIMMER_STREAMING_PROPERTIES = -100;

ShimmerDriver/src/main/java/com/shimmerresearch/driver/ObjectCluster.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ final public class ObjectCluster implements Cloneable,Serializable{
8888

8989
private String mMyName;
9090
private String mBluetoothAddress;
91+
private String mComPort;
9192

9293
// ------- Old Array approach - Start -----------
9394
public byte[] mRawData;
@@ -220,6 +221,13 @@ public void setMacAddress(String macAddress){
220221
mBluetoothAddress = macAddress;
221222
}
222223

224+
public void setComPort(String comport) {
225+
mComPort = comport;
226+
}
227+
228+
public String getComPort() {
229+
return mComPort;
230+
}
223231
/**
224232
* Takes in a collection of Format Clusters and returns the Format Cluster specified by the string format
225233
* @param collectionFormatCluster
@@ -247,6 +255,15 @@ public double getFormatClusterValue(ChannelDetails channelDetails, CHANNEL_TYPE
247255
return getFormatClusterValue(channelDetails.mObjectClusterName, channelType.toString());
248256
}
249257

258+
public FormatCluster getFormatCluster(String channelName, String format)
259+
{
260+
FormatCluster formatCluster = getLastFormatCluster(channelName, format);
261+
if(formatCluster!=null){
262+
return formatCluster;
263+
}
264+
return null;
265+
}
266+
250267
// public double getFormatClusterValue(ChannelDetails channelDetails, String format){
251268
// return getFormatClusterValue(channelDetails.mObjectClusterName, format);
252269
// }

ShimmerDriver/src/main/java/com/shimmerresearch/driver/ShimmerDevice.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4502,6 +4502,13 @@ public String getComPort() {
45024502
return mComPort;
45034503
}
45044504

4505+
/**This method will only return the comport name
4506+
* @return
4507+
*/
4508+
public String getComPortName() {
4509+
return mComPort;
4510+
}
4511+
45054512
public boolean isReadyToConnect() {
45064513
if (mCommsProtocolRadio==null
45074514
||mCommsProtocolRadio.mRadioHal==null

ShimmerDriver/src/main/java/com/shimmerresearch/driver/ShimmerObject.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -812,6 +812,7 @@ public ObjectCluster buildMsg(byte[] newPacket, COMMUNICATION_TYPE fwType, boole
812812

813813
objectCluster.setShimmerName(mShimmerUserAssignedName);
814814
objectCluster.setMacAddress(mMyBluetoothAddress);
815+
objectCluster.setComPort(getComPortName());
815816
objectCluster.mRawData = newPacket;
816817

817818
if(fwType!=COMMUNICATION_TYPE.BLUETOOTH && fwType!=COMMUNICATION_TYPE.SD){

ShimmerDriverPC/build.gradle

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,17 @@
88
*/
99

1010
// Apply the java plugin to add support for Java
11-
apply plugin: 'java'
12-
apply plugin: 'java-library'
13-
apply plugin: 'eclipse'
14-
apply plugin: 'maven-publish'
15-
11+
plugins {
12+
id 'java'
13+
id 'java-library'
14+
id 'eclipse'
15+
id 'maven-publish'
16+
id 'com.github.johnrengelman.shadow' version '7.0.0' // Apply the Shadow plugin
17+
}
1618
sourceCompatibility = 1.11
17-
19+
targetCompatibility = 1.11
20+
//sourceCompatibility = '1.8' // Ensure code is compiled with Java 8 when compiling ShimmerJavaClass for Matlab see ShimmerDriverPC (build.gradle)
21+
//targetCompatibility = '1.8' // Ensure bytecode is compatible with Java 8 when compiling ShimmerJavaClass for Matlab see ShimmerDriverPC (build.gradle)
1822
/*
1923
Rev0.2
2024
- switch to using jfrog
@@ -96,3 +100,20 @@ dependencies {
96100
testImplementation 'junit:junit:4.12'
97101
implementation 'com.parse.bolts:bolts-tasks:1.4.0'
98102
}
103+
104+
// Shadow JAR task to create a runnable JAR with dependencies
105+
/*
106+
Change to using the following below for ShimmerDriverPC/ShimmerDriver/ShimmerBluetoothManager
107+
sourceCompatibility = '1.8' // Ensure code is compiled with Java 8
108+
targetCompatibility = '1.8' // Ensure bytecode is compatible with Java 8
109+
*/
110+
shadowJar {
111+
archiveBaseName.set('ShimmerJavaClass') // Use archiveBaseName instead of baseName
112+
archiveClassifier.set('') // Remove classifier so it’s named shimmerjavaclass.jar
113+
114+
manifest {
115+
attributes 'Main-Class': 'com.shimmerresearch.tools.matlab.ShimmerJavaClass' // Specify the main class
116+
}
117+
118+
mergeServiceFiles() // Merges service files (if any)
119+
}
Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
package com.shimmerresearch.tools.matlab;
2+
3+
import java.awt.event.ActionEvent;
4+
import java.awt.event.ActionListener;
5+
import java.util.ArrayList;
6+
import java.util.LinkedHashMap;
7+
import java.util.LinkedList;
8+
import java.util.List;
9+
import java.util.Queue;
10+
import java.util.concurrent.ConcurrentHashMap;
11+
import java.util.concurrent.ConcurrentLinkedQueue;
12+
13+
import javax.swing.JButton;
14+
import javax.swing.JFrame;
15+
import javax.swing.JPanel;
16+
import javax.swing.JTextField;
17+
18+
import com.shimmerresearch.bluetooth.ShimmerBluetooth.BT_STATE;
19+
import com.shimmerresearch.driver.BasicProcessWithCallBack;
20+
import com.shimmerresearch.driver.CallbackObject;
21+
import com.shimmerresearch.driver.ObjectCluster;
22+
import com.shimmerresearch.driver.ShimmerMsg;
23+
import com.shimmerresearch.driver.Configuration.COMMUNICATION_TYPE;
24+
import com.shimmerresearch.driver.FormatCluster;
25+
import com.shimmerresearch.driverUtilities.ChannelDetails;
26+
import com.shimmerresearch.exceptions.ShimmerException;
27+
import com.shimmerresearch.pcDriver.ShimmerPC;
28+
import com.shimmerresearch.tools.bluetooth.BasicShimmerBluetoothManagerPc;
29+
import com.shimmerresearch.algorithms.*;
30+
31+
public class ShimmerJavaClass {
32+
private String comPort;
33+
private SensorDataReceived sdr = new SensorDataReceived();
34+
private String[] channelNames;
35+
private final ConcurrentLinkedQueue<String> connectedDevices = new ConcurrentLinkedQueue<>();
36+
private final ConcurrentHashMap<String, Queue<Object[]>> dataQueues = new ConcurrentHashMap<>();
37+
private List<float[]> collectedData = new ArrayList<>();
38+
39+
40+
private boolean mDebug = true;
41+
42+
// private int rowIndex = 0;
43+
Object[] currentData = null;
44+
public static BasicShimmerBluetoothManagerPc mBluetoothManager;
45+
46+
public ShimmerJavaClass() {
47+
mBluetoothManager = new BasicShimmerBluetoothManagerPc(false);
48+
sdr.setWaitForData(mBluetoothManager.callBackObject);
49+
mBluetoothManager.addCallBack(sdr);
50+
if (mDebug) {
51+
System.out.println("Callback Registered");
52+
System.out.flush();
53+
}
54+
}
55+
56+
public static void main(String[] args) {
57+
ShimmerJavaClass example = new ShimmerJavaClass();
58+
example.createAndShowGUI();
59+
}
60+
61+
public void createAndShowGUI() {
62+
JFrame frame = new JFrame("Shimmer Device Controller");
63+
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
64+
frame.setSize(400, 200);
65+
66+
JPanel panel = new JPanel();
67+
68+
JTextField inputComPort = new JTextField("COM3");
69+
JButton connectButton = new JButton("Connect");
70+
JButton disconnectButton = new JButton("Disconnect");
71+
JButton startButton = new JButton("Start Streaming");
72+
JButton stopButton = new JButton("Stop Streaming");
73+
74+
connectButton.addActionListener(new ActionListener() {
75+
@Override
76+
public void actionPerformed(ActionEvent e) {
77+
comPort = inputComPort.getText();
78+
mBluetoothManager.connectShimmerThroughCommPort(comPort);
79+
}
80+
});
81+
82+
disconnectButton.addActionListener(new ActionListener() {
83+
@Override
84+
public void actionPerformed(ActionEvent e) {
85+
mBluetoothManager.disconnectShimmer(comPort);
86+
}
87+
});
88+
89+
startButton.addActionListener(new ActionListener() {
90+
@Override
91+
public void actionPerformed(ActionEvent e) {
92+
try {
93+
mBluetoothManager.getShimmerDeviceBtConnected(comPort).startStreaming();
94+
} catch (ShimmerException e1) {
95+
// TODO Auto-generated catch block
96+
e1.printStackTrace();
97+
}
98+
99+
while(true) {
100+
if (hasDataToRead(comPort)) {
101+
readData();
102+
}
103+
104+
}
105+
}
106+
});
107+
108+
109+
110+
stopButton.addActionListener(new ActionListener() {
111+
@Override
112+
public void actionPerformed(ActionEvent e) {
113+
try {
114+
mBluetoothManager.getShimmerDeviceBtConnected(comPort).stopStreaming();
115+
} catch (ShimmerException e1) {
116+
// TODO Auto-generated catch block
117+
e1.printStackTrace();
118+
}
119+
}
120+
});
121+
122+
panel.add(inputComPort);
123+
panel.add(connectButton);
124+
panel.add(disconnectButton);
125+
panel.add(startButton);
126+
panel.add(stopButton);
127+
frame.add(panel);
128+
129+
frame.setVisible(true);
130+
}
131+
132+
public String[] retrieveSensorChannels() {
133+
LinkedHashMap<String, ChannelDetails> mapOfAllChannels = mBluetoothManager.getShimmerDeviceBtConnected(comPort).getMapOfAllChannelsForStoringToDB(COMMUNICATION_TYPE.BLUETOOTH, null, false, false);
134+
List<ChannelDetails> listOfChannelDetails = new ArrayList<ChannelDetails>(mapOfAllChannels.values());
135+
136+
List<String> channelNamesList = new ArrayList<String>();
137+
for (ChannelDetails channel : listOfChannelDetails) {
138+
channelNamesList.add(channel.mObjectClusterName);
139+
}
140+
141+
return channelNamesList.toArray(new String[0]);
142+
}
143+
public boolean hasDataToRead(String comPort) {
144+
Queue<Object[]> queue = dataQueues.get(comPort);
145+
return queue != null && !queue.isEmpty();
146+
}
147+
private void sendData(String comPort, Object[] data) {
148+
dataQueues.computeIfAbsent(comPort, k -> new LinkedList<>()).add(data);
149+
}
150+
151+
public void readData() {
152+
for (String comPort : dataQueues.keySet()) {
153+
Object[] data = receiveData(comPort);
154+
if (data != null && mDebug) {
155+
float[][] matrix = (float[][]) data[0];
156+
String[] signalNames = (String[]) data[1];
157+
String[] formats = (String[]) data[2];
158+
String[] units = (String[]) data[3];
159+
160+
System.out.println("==== Data from device: " + comPort + " ====");
161+
for (int i = 0; i < matrix.length; i++) {
162+
System.out.print("Row " + i + ": ");
163+
for (int j = 0; j < matrix[i].length; j++) {
164+
System.out.print(matrix[i][j] + " " + units[j] + " [" + signalNames[j] + "] | ");
165+
}
166+
System.out.println();
167+
}
168+
}
169+
}
170+
}
171+
172+
public Object[] receiveData(String comPort) {
173+
Queue<Object[]> queue = dataQueues.get(comPort);
174+
if (queue == null || queue.isEmpty()) return null;
175+
176+
List<float[]> deviceData = new ArrayList<>();
177+
String[] signalNameArray = null, signalFormatArray = null, signalUnitArray = null;
178+
179+
while (!queue.isEmpty()) {
180+
Object[] data = queue.poll();
181+
if (data == null) continue; // skip this iteration safely
182+
183+
float[] values = (float[]) data[1];
184+
if (values == null) continue;
185+
186+
signalNameArray = (String[]) data[2];
187+
signalFormatArray = (String[]) data[3];
188+
signalUnitArray = (String[]) data[4];
189+
deviceData.add(values);
190+
}
191+
192+
float[][] dataMatrix = deviceData.toArray(new float[0][0]);
193+
return new Object[] { dataMatrix, signalNameArray, signalFormatArray, signalUnitArray };
194+
}
195+
196+
197+
public class SensorDataReceived extends BasicProcessWithCallBack {
198+
199+
@Override
200+
protected void processMsgFromCallback(ShimmerMsg shimmerMSG) {
201+
int ind = shimmerMSG.mIdentifier;
202+
Object object = shimmerMSG.mB;
203+
204+
if (ind == ShimmerPC.MSG_IDENTIFIER_STATE_CHANGE) {
205+
CallbackObject callbackObject = (CallbackObject) object;
206+
207+
if (callbackObject.mState == BT_STATE.CONNECTING) {
208+
System.out.println("Device State Change: " + callbackObject.mState);
209+
System.out.flush();
210+
211+
} else if (callbackObject.mState == BT_STATE.CONNECTED) {
212+
System.out.println("Device State Change: " + callbackObject.mState);
213+
System.out.flush();
214+
if (comPort == null) {
215+
comPort = callbackObject.mComPort;
216+
}
217+
channelNames = retrieveSensorChannels();
218+
if (mDebug) {
219+
for(String channel : channelNames) {
220+
System.out.println(channel);
221+
}
222+
}
223+
} else if (callbackObject.mState == BT_STATE.DISCONNECTED || callbackObject.mState == BT_STATE.CONNECTION_LOST) {
224+
System.out.println("Device State Change: " + callbackObject.mState);
225+
System.out.flush();
226+
227+
}
228+
} else if (ind == ShimmerPC.MSG_IDENTIFIER_NOTIFICATION_MESSAGE) {
229+
230+
} else if (ind == ShimmerPC.MSG_IDENTIFIER_DATA_PACKET) {
231+
ObjectCluster objc = (ObjectCluster) shimmerMSG.mB;
232+
233+
float[] newData = new float[channelNames.length];
234+
String[] signalNameArray = new String[channelNames.length];
235+
String[] signalFormatArray = new String[channelNames.length];
236+
String[] signalUnitArray = new String[channelNames.length];
237+
238+
for (int i = 0; i < channelNames.length; i++) {
239+
FormatCluster formatCluster = objc.getFormatCluster(channelNames[i], "CAL");
240+
if (formatCluster != null) {
241+
newData[i] = (float) formatCluster.mData;
242+
signalNameArray[i] = channelNames[i];
243+
signalFormatArray[i] = formatCluster.mFormat;
244+
signalUnitArray[i] = formatCluster.mUnits;
245+
}
246+
}
247+
248+
String comPort = objc.getComPort();
249+
Object[] outputData = { comPort, newData, signalNameArray, signalFormatArray, signalUnitArray };
250+
sendData(comPort, outputData);
251+
}
252+
}
253+
}
254+
}

0 commit comments

Comments
 (0)