From bdcfd722385597b7109161b04a21f4a0f1e3c112 Mon Sep 17 00:00:00 2001 From: JongChern Date: Mon, 21 Oct 2024 15:03:47 +0800 Subject: [PATCH 1/6] Create ShimmerJavaClass.java --- .../tools/matlab/ShimmerJavaClass.java | 183 ++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/matlab/ShimmerJavaClass.java diff --git a/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/matlab/ShimmerJavaClass.java b/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/matlab/ShimmerJavaClass.java new file mode 100644 index 000000000..40a943fbc --- /dev/null +++ b/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/matlab/ShimmerJavaClass.java @@ -0,0 +1,183 @@ +package com.shimmerresearch.tools.matlab; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTextField; + +import com.shimmerresearch.bluetooth.ShimmerBluetooth.BT_STATE; +import com.shimmerresearch.driver.BasicProcessWithCallBack; +import com.shimmerresearch.driver.CallbackObject; +import com.shimmerresearch.driver.ObjectCluster; +import com.shimmerresearch.driver.ShimmerMsg; +import com.shimmerresearch.driver.Configuration.COMMUNICATION_TYPE; +import com.shimmerresearch.driverUtilities.ChannelDetails; +import com.shimmerresearch.exceptions.ShimmerException; +import com.shimmerresearch.pcDriver.ShimmerPC; +import com.shimmerresearch.tools.bluetooth.BasicShimmerBluetoothManagerPc; + +public class ShimmerJavaClass { + private String comPort; + private SensorDataReceived sdr = new SensorDataReceived(); + private String[] channelNames; + private final Queue dataQueue = new ConcurrentLinkedQueue(); + public static BasicShimmerBluetoothManagerPc mBluetoothManager = new BasicShimmerBluetoothManagerPc(); + + public ShimmerJavaClass() { + sdr.setWaitForData(mBluetoothManager.callBackObject); + } + + public static void main(String[] args) { + ShimmerJavaClass example = new ShimmerJavaClass(); + example.createAndShowGUI(); + } + + + + public void createAndShowGUI() { + JFrame frame = new JFrame("Shimmer Device Controller"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setSize(400, 200); + + JPanel panel = new JPanel(); + + JTextField inputComPort = new JTextField("COM3"); + JButton connectButton = new JButton("Connect"); + JButton disconnectButton = new JButton("Disconnect"); + JButton startButton = new JButton("Start Streaming"); + JButton stopButton = new JButton("Stop Streaming"); + + connectButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + comPort = inputComPort.getText(); + mBluetoothManager.connectShimmerThroughCommPort(comPort); + } + }); + + disconnectButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + mBluetoothManager.disconnectShimmer(comPort); + } + }); + + startButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + try { + mBluetoothManager.getShimmerDeviceBtConnected(comPort).startStreaming(); + } catch (ShimmerException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + + while(true) { + if(!dataQueue.isEmpty()) { + readData(); + } + } + } + }); + + stopButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + try { + mBluetoothManager.getShimmerDeviceBtConnected(comPort).stopStreaming(); + } catch (ShimmerException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + } + }); + + panel.add(inputComPort); + panel.add(connectButton); + panel.add(disconnectButton); + panel.add(startButton); + panel.add(stopButton); + frame.add(panel); + + frame.setVisible(true); + } + + public String[] retrieveSensorChannels() { + LinkedHashMap mapOfAllChannels = mBluetoothManager.getShimmerDeviceBtConnected(comPort).getMapOfAllChannelsForStoringToDB(COMMUNICATION_TYPE.BLUETOOTH, null, false, false); + List listOfChannelDetails = new ArrayList(mapOfAllChannels.values()); + + List channelNamesList = new ArrayList(); + for (ChannelDetails channel : listOfChannelDetails) { + channelNamesList.add(channel.mObjectClusterName); + } + + return channelNamesList.toArray(new String[0]); + } + + public float receiveData(String channel) { //Receive data for specific Object Cluster + float[] data = dataQueue.poll(); + for (int i = 0; i < channelNames.length; i++) { + if (channelNames[i].equals(channel)) { + return data[i]; + } + } + return Float.NaN; + } + + public float[] receiveData() { //Receive data for all Object Cluster + float[] data = dataQueue.poll(); + return data; + } + + private void sendData(float[] data) { + dataQueue.add(data); + } + + public void readData() { //Test receive data for all Object Cluster + float[] data = receiveData(); + System.out.println("Timestamp : " + data[4] + "\nAccel_LN_X : " + data[0]); + } + + public class SensorDataReceived extends BasicProcessWithCallBack { + + @Override + protected void processMsgFromCallback(ShimmerMsg shimmerMSG) { + int ind = shimmerMSG.mIdentifier; + Object object = shimmerMSG.mB; + + if (ind == ShimmerPC.MSG_IDENTIFIER_STATE_CHANGE) { + CallbackObject callbackObject = (CallbackObject) object; + + if (callbackObject.mState == BT_STATE.CONNECTING) { + + } else if (callbackObject.mState == BT_STATE.CONNECTED) { + channelNames = retrieveSensorChannels(); + for(String channel : channelNames) { + System.out.println(channel); + } + } else if (callbackObject.mState == BT_STATE.DISCONNECTED || callbackObject.mState == BT_STATE.CONNECTION_LOST) { + + } + } else if (ind == ShimmerPC.MSG_IDENTIFIER_NOTIFICATION_MESSAGE) { + + } else if (ind == ShimmerPC.MSG_IDENTIFIER_DATA_PACKET) { + ObjectCluster objc = (ObjectCluster) shimmerMSG.mB; + + float[] data = new float[channelNames.length]; + for (int i = 0; i < channelNames.length; i++) { + data[i] = (float) objc.getFormatClusterValue(channelNames[i], "CAL"); + } + + sendData(data); + } + } + } +} From 09fb410d1e00fcd0c66284952813018a7de7022b Mon Sep 17 00:00:00 2001 From: Harith Jamadi <114632577+harithjamadi@users.noreply.github.com> Date: Mon, 3 Feb 2025 14:51:32 +0800 Subject: [PATCH 2/6] update on shimmerjavaclass for getformatcluster --- .../shimmerresearch/driver/ObjectCluster.java | 9 ++ .../tools/matlab/ShimmerJavaClass.java | 82 +++++++++++++------ 2 files changed, 67 insertions(+), 24 deletions(-) diff --git a/ShimmerDriver/src/main/java/com/shimmerresearch/driver/ObjectCluster.java b/ShimmerDriver/src/main/java/com/shimmerresearch/driver/ObjectCluster.java index 2b202fae6..4895d7c4c 100644 --- a/ShimmerDriver/src/main/java/com/shimmerresearch/driver/ObjectCluster.java +++ b/ShimmerDriver/src/main/java/com/shimmerresearch/driver/ObjectCluster.java @@ -247,6 +247,15 @@ public double getFormatClusterValue(ChannelDetails channelDetails, CHANNEL_TYPE return getFormatClusterValue(channelDetails.mObjectClusterName, channelType.toString()); } + public FormatCluster getFormatCluster(String channelName, String format) + { + FormatCluster formatCluster = getLastFormatCluster(channelName, format); + if(formatCluster!=null){ + return formatCluster; + } + return null; + } + // public double getFormatClusterValue(ChannelDetails channelDetails, String format){ // return getFormatClusterValue(channelDetails.mObjectClusterName, format); // } diff --git a/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/matlab/ShimmerJavaClass.java b/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/matlab/ShimmerJavaClass.java index 40a943fbc..684a68ea6 100644 --- a/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/matlab/ShimmerJavaClass.java +++ b/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/matlab/ShimmerJavaClass.java @@ -4,6 +4,7 @@ import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.LinkedHashMap; +import java.util.LinkedList; import java.util.List; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; @@ -19,6 +20,7 @@ import com.shimmerresearch.driver.ObjectCluster; import com.shimmerresearch.driver.ShimmerMsg; import com.shimmerresearch.driver.Configuration.COMMUNICATION_TYPE; +import com.shimmerresearch.driver.FormatCluster; import com.shimmerresearch.driverUtilities.ChannelDetails; import com.shimmerresearch.exceptions.ShimmerException; import com.shimmerresearch.pcDriver.ShimmerPC; @@ -28,19 +30,26 @@ public class ShimmerJavaClass { private String comPort; private SensorDataReceived sdr = new SensorDataReceived(); private String[] channelNames; - private final Queue dataQueue = new ConcurrentLinkedQueue(); + private Queue dataQueue = new LinkedList<>(); + private List collectedData = new ArrayList<>(); + private String[] signalNameArray; + private String[] signalFormatArray; + private String[] signalUnitArray; +// private int rowIndex = 0; + Object[] currentData = null; public static BasicShimmerBluetoothManagerPc mBluetoothManager = new BasicShimmerBluetoothManagerPc(); public ShimmerJavaClass() { sdr.setWaitForData(mBluetoothManager.callBackObject); + mBluetoothManager.addCallBack(sdr); + System.out.println("Callback Registered"); + System.out.flush(); } public static void main(String[] args) { ShimmerJavaClass example = new ShimmerJavaClass(); example.createAndShowGUI(); } - - public void createAndShowGUI() { JFrame frame = new JFrame("Shimmer Device Controller"); @@ -122,28 +131,32 @@ public String[] retrieveSensorChannels() { return channelNamesList.toArray(new String[0]); } - public float receiveData(String channel) { //Receive data for specific Object Cluster - float[] data = dataQueue.poll(); - for (int i = 0; i < channelNames.length; i++) { - if (channelNames[i].equals(channel)) { - return data[i]; - } - } - return Float.NaN; - } - - public float[] receiveData() { //Receive data for all Object Cluster - float[] data = dataQueue.poll(); - return data; - } + public Object[] receiveData() { + while (!dataQueue.isEmpty()) { + Object[] currentData = dataQueue.poll(); + + float[] newData = (float[]) currentData[0]; + signalNameArray = (String[]) currentData[1]; + signalFormatArray = (String[]) currentData[2]; + signalUnitArray = (String[]) currentData[3]; - private void sendData(float[] data) { + collectedData.add(newData); + } + + // Convert list to 2D float array (m × n) + float[][] dataMatrix = collectedData.toArray(new float[0][0]); + + return new Object[]{dataMatrix, signalNameArray, signalFormatArray, signalUnitArray}; + } + + private void sendData(Object[] data) { dataQueue.add(data); } public void readData() { //Test receive data for all Object Cluster - float[] data = receiveData(); - System.out.println("Timestamp : " + data[4] + "\nAccel_LN_X : " + data[0]); + Object[] data = receiveData(); + System.out.println("New Data : " + data[0] + "\tChannel Name : " + data[1] + + "\tFormat : " + data[2] + "\tUnit : " + data[3]); } public class SensorDataReceived extends BasicProcessWithCallBack { @@ -157,13 +170,22 @@ protected void processMsgFromCallback(ShimmerMsg shimmerMSG) { CallbackObject callbackObject = (CallbackObject) object; if (callbackObject.mState == BT_STATE.CONNECTING) { + System.out.println("Device State Change: " + callbackObject.mState); + System.out.flush(); } else if (callbackObject.mState == BT_STATE.CONNECTED) { + System.out.println("Device State Change: " + callbackObject.mState); + System.out.flush(); + if (comPort == null) { + comPort = callbackObject.mComPort; + } channelNames = retrieveSensorChannels(); for(String channel : channelNames) { System.out.println(channel); } } else if (callbackObject.mState == BT_STATE.DISCONNECTED || callbackObject.mState == BT_STATE.CONNECTION_LOST) { + System.out.println("Device State Change: " + callbackObject.mState); + System.out.flush(); } } else if (ind == ShimmerPC.MSG_IDENTIFIER_NOTIFICATION_MESSAGE) { @@ -171,13 +193,25 @@ protected void processMsgFromCallback(ShimmerMsg shimmerMSG) { } else if (ind == ShimmerPC.MSG_IDENTIFIER_DATA_PACKET) { ObjectCluster objc = (ObjectCluster) shimmerMSG.mB; - float[] data = new float[channelNames.length]; + float[] newData = new float[channelNames.length]; + String[] signalNameArray = new String[channelNames.length]; + String[] signalFormatArray = new String[channelNames.length]; + String[] signalUnitArray = new String[channelNames.length]; + for (int i = 0; i < channelNames.length; i++) { - data[i] = (float) objc.getFormatClusterValue(channelNames[i], "CAL"); + FormatCluster formatCluster = objc.getFormatCluster(channelNames[i], "CAL"); + if (formatCluster != null) { + newData[i] = (float) formatCluster.mData; + signalNameArray[i] = channelNames[i]; + signalFormatArray[i] = formatCluster.mFormat; + signalUnitArray[i] = formatCluster.mUnits; + } } + + Object[] outputData = { newData, signalNameArray, signalFormatArray, signalUnitArray }; - sendData(data); + sendData(outputData); } } } -} +} \ No newline at end of file From bbbd078b8acac29c81902677cbcd4052d43a3167 Mon Sep 17 00:00:00 2001 From: JongChern Date: Fri, 18 Jul 2025 12:38:14 +0800 Subject: [PATCH 3/6] minor updates --- ShimmerBluetoothManager/build.gradle | 2 ++ ShimmerDriver/build.gradle | 2 ++ ShimmerDriverPC/build.gradle | 33 +++++++++++++++---- .../tools/matlab/ShimmerJavaClass.java | 22 +++++++++---- 4 files changed, 47 insertions(+), 12 deletions(-) diff --git a/ShimmerBluetoothManager/build.gradle b/ShimmerBluetoothManager/build.gradle index 749e52f01..16a3a453e 100644 --- a/ShimmerBluetoothManager/build.gradle +++ b/ShimmerBluetoothManager/build.gradle @@ -12,6 +12,8 @@ Rev0.2 sourceCompatibility = 1.11 targetCompatibility = 1.11 +//sourceCompatibility = '1.8' // Ensure code is compiled with Java 8 when compiling ShimmerJavaClass for Matlab see ShimmerDriverPC (build.gradle) +//targetCompatibility = '1.8' // Ensure bytecode is compatible with Java 8 when compiling ShimmerJavaClass for Matlab see ShimmerDriverPC (build.gradle) repositories { mavenCentral() diff --git a/ShimmerDriver/build.gradle b/ShimmerDriver/build.gradle index 0341173ff..bdf92e022 100644 --- a/ShimmerDriver/build.gradle +++ b/ShimmerDriver/build.gradle @@ -15,6 +15,8 @@ Rev0.2 apply plugin: 'java-library' sourceCompatibility = 1.11 targetCompatibility = 1.11 +//sourceCompatibility = '1.8' // Ensure code is compiled with Java 8 when compiling ShimmerJavaClass for Matlab see ShimmerDriverPC (build.gradle) +//targetCompatibility = '1.8' // Ensure bytecode is compatible with Java 8 when compiling ShimmerJavaClass for Matlab see ShimmerDriverPC (build.gradle) repositories { mavenCentral() diff --git a/ShimmerDriverPC/build.gradle b/ShimmerDriverPC/build.gradle index efe15c385..8ff69f396 100644 --- a/ShimmerDriverPC/build.gradle +++ b/ShimmerDriverPC/build.gradle @@ -8,13 +8,17 @@ */ // Apply the java plugin to add support for Java -apply plugin: 'java' -apply plugin: 'java-library' -apply plugin: 'eclipse' -apply plugin: 'maven-publish' - +plugins { + id 'java' + id 'java-library' + id 'eclipse' + id 'maven-publish' + id 'com.github.johnrengelman.shadow' version '7.0.0' // Apply the Shadow plugin +} sourceCompatibility = 1.11 - +targetCompatibility = 1.11 +//sourceCompatibility = '1.8' // Ensure code is compiled with Java 8 when compiling ShimmerJavaClass for Matlab see ShimmerDriverPC (build.gradle) +//targetCompatibility = '1.8' // Ensure bytecode is compatible with Java 8 when compiling ShimmerJavaClass for Matlab see ShimmerDriverPC (build.gradle) /* Rev0.2 - switch to using jfrog @@ -96,3 +100,20 @@ dependencies { testImplementation 'junit:junit:4.12' implementation 'com.parse.bolts:bolts-tasks:1.4.0' } + +// Shadow JAR task to create a runnable JAR with dependencies +/* +Change to using the following below for ShimmerDriverPC/ShimmerDriver/ShimmerBluetoothManager +sourceCompatibility = '1.8' // Ensure code is compiled with Java 8 +targetCompatibility = '1.8' // Ensure bytecode is compatible with Java 8 +*/ +shadowJar { + archiveBaseName.set('ShimmerJavaClass') // Use archiveBaseName instead of baseName + archiveClassifier.set('') // Remove classifier so it’s named shimmerjavaclass.jar + + manifest { + attributes 'Main-Class': 'com.shimmerresearch.tools.matlab.ShimmerJavaClass' // Specify the main class + } + + mergeServiceFiles() // Merges service files (if any) +} diff --git a/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/matlab/ShimmerJavaClass.java b/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/matlab/ShimmerJavaClass.java index 684a68ea6..61c1bcb7f 100644 --- a/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/matlab/ShimmerJavaClass.java +++ b/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/matlab/ShimmerJavaClass.java @@ -25,6 +25,7 @@ import com.shimmerresearch.exceptions.ShimmerException; import com.shimmerresearch.pcDriver.ShimmerPC; import com.shimmerresearch.tools.bluetooth.BasicShimmerBluetoothManagerPc; +import com.shimmerresearch.algorithms.*; public class ShimmerJavaClass { private String comPort; @@ -35,15 +36,20 @@ public class ShimmerJavaClass { private String[] signalNameArray; private String[] signalFormatArray; private String[] signalUnitArray; + + private boolean mDebug = false; + // private int rowIndex = 0; Object[] currentData = null; - public static BasicShimmerBluetoothManagerPc mBluetoothManager = new BasicShimmerBluetoothManagerPc(); + public static BasicShimmerBluetoothManagerPc mBluetoothManager = new BasicShimmerBluetoothManagerPc(false); public ShimmerJavaClass() { sdr.setWaitForData(mBluetoothManager.callBackObject); mBluetoothManager.addCallBack(sdr); - System.out.println("Callback Registered"); - System.out.flush(); + if (mDebug) { + System.out.println("Callback Registered"); + System.out.flush(); + } } public static void main(String[] args) { @@ -155,8 +161,10 @@ private void sendData(Object[] data) { public void readData() { //Test receive data for all Object Cluster Object[] data = receiveData(); - System.out.println("New Data : " + data[0] + "\tChannel Name : " + data[1] + if (mDebug) { + System.out.println("New Data : " + data[0] + "\tChannel Name : " + data[1] + "\tFormat : " + data[2] + "\tUnit : " + data[3]); + } } public class SensorDataReceived extends BasicProcessWithCallBack { @@ -180,8 +188,10 @@ protected void processMsgFromCallback(ShimmerMsg shimmerMSG) { comPort = callbackObject.mComPort; } channelNames = retrieveSensorChannels(); - for(String channel : channelNames) { - System.out.println(channel); + if (mDebug) { + for(String channel : channelNames) { + System.out.println(channel); + } } } else if (callbackObject.mState == BT_STATE.DISCONNECTED || callbackObject.mState == BT_STATE.CONNECTION_LOST) { System.out.println("Device State Change: " + callbackObject.mState); From 54d40338c6af36ddb2def212788e3a120cb09182 Mon Sep 17 00:00:00 2001 From: JongChern Date: Fri, 18 Jul 2025 13:58:45 +0800 Subject: [PATCH 4/6] Update Configuration.java --- .../src/main/java/com/shimmerresearch/driver/Configuration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ShimmerDriver/src/main/java/com/shimmerresearch/driver/Configuration.java b/ShimmerDriver/src/main/java/com/shimmerresearch/driver/Configuration.java index 834d9669c..8bf461b39 100644 --- a/ShimmerDriver/src/main/java/com/shimmerresearch/driver/Configuration.java +++ b/ShimmerDriver/src/main/java/com/shimmerresearch/driver/Configuration.java @@ -677,7 +677,7 @@ public class SensorBitmap{ * data packets. The firmware also uses the IMU IDs as Sensor IDs in the * IMU/BMP calibration bytes. */ - public class SENSOR_ID{ + public static class SENSOR_ID{ public static final int RESERVED_ANY_SENSOR = -1; public static final int HOST_SHIMMER_STREAMING_PROPERTIES = -100; From 04b43ff0b7073a32e3f7c0d97a41f9fc07931a5e Mon Sep 17 00:00:00 2001 From: JongChern Date: Mon, 21 Jul 2025 13:53:39 +0800 Subject: [PATCH 5/6] update to allow more devices --- .../shimmerresearch/driver/ObjectCluster.java | 8 ++ .../shimmerresearch/driver/ShimmerDevice.java | 7 ++ .../shimmerresearch/driver/ShimmerObject.java | 1 + .../tools/matlab/ShimmerJavaClass.java | 99 ++++++++++++------- 4 files changed, 77 insertions(+), 38 deletions(-) diff --git a/ShimmerDriver/src/main/java/com/shimmerresearch/driver/ObjectCluster.java b/ShimmerDriver/src/main/java/com/shimmerresearch/driver/ObjectCluster.java index 4895d7c4c..29bf516b5 100644 --- a/ShimmerDriver/src/main/java/com/shimmerresearch/driver/ObjectCluster.java +++ b/ShimmerDriver/src/main/java/com/shimmerresearch/driver/ObjectCluster.java @@ -88,6 +88,7 @@ final public class ObjectCluster implements Cloneable,Serializable{ private String mMyName; private String mBluetoothAddress; + private String mComPort; // ------- Old Array approach - Start ----------- public byte[] mRawData; @@ -220,6 +221,13 @@ public void setMacAddress(String macAddress){ mBluetoothAddress = macAddress; } + public void setComPort(String comport) { + mComPort = comport; + } + + public String getComPort() { + return mComPort; + } /** * Takes in a collection of Format Clusters and returns the Format Cluster specified by the string format * @param collectionFormatCluster diff --git a/ShimmerDriver/src/main/java/com/shimmerresearch/driver/ShimmerDevice.java b/ShimmerDriver/src/main/java/com/shimmerresearch/driver/ShimmerDevice.java index 54a55ee54..a7e3089a1 100644 --- a/ShimmerDriver/src/main/java/com/shimmerresearch/driver/ShimmerDevice.java +++ b/ShimmerDriver/src/main/java/com/shimmerresearch/driver/ShimmerDevice.java @@ -4465,6 +4465,13 @@ public String getComPort() { return mComPort; } + /**This method will only return the comport name + * @return + */ + public String getComPortName() { + return mComPort; + } + public boolean isReadyToConnect() { if (mCommsProtocolRadio==null ||mCommsProtocolRadio.mRadioHal==null diff --git a/ShimmerDriver/src/main/java/com/shimmerresearch/driver/ShimmerObject.java b/ShimmerDriver/src/main/java/com/shimmerresearch/driver/ShimmerObject.java index 396c75e68..b54487550 100644 --- a/ShimmerDriver/src/main/java/com/shimmerresearch/driver/ShimmerObject.java +++ b/ShimmerDriver/src/main/java/com/shimmerresearch/driver/ShimmerObject.java @@ -812,6 +812,7 @@ public ObjectCluster buildMsg(byte[] newPacket, COMMUNICATION_TYPE fwType, boole objectCluster.setShimmerName(mShimmerUserAssignedName); objectCluster.setMacAddress(mMyBluetoothAddress); + objectCluster.setComPort(getComPortName()); objectCluster.mRawData = newPacket; if(fwType!=COMMUNICATION_TYPE.BLUETOOTH && fwType!=COMMUNICATION_TYPE.SD){ diff --git a/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/matlab/ShimmerJavaClass.java b/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/matlab/ShimmerJavaClass.java index 61c1bcb7f..04406d3b7 100644 --- a/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/matlab/ShimmerJavaClass.java +++ b/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/matlab/ShimmerJavaClass.java @@ -7,6 +7,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Queue; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import javax.swing.JButton; @@ -31,19 +32,19 @@ public class ShimmerJavaClass { private String comPort; private SensorDataReceived sdr = new SensorDataReceived(); private String[] channelNames; - private Queue dataQueue = new LinkedList<>(); + private final ConcurrentLinkedQueue connectedDevices = new ConcurrentLinkedQueue<>(); + private final ConcurrentHashMap> dataQueues = new ConcurrentHashMap<>(); private List collectedData = new ArrayList<>(); - private String[] signalNameArray; - private String[] signalFormatArray; - private String[] signalUnitArray; + - private boolean mDebug = false; + private boolean mDebug = true; // private int rowIndex = 0; Object[] currentData = null; - public static BasicShimmerBluetoothManagerPc mBluetoothManager = new BasicShimmerBluetoothManagerPc(false); + public static BasicShimmerBluetoothManagerPc mBluetoothManager; public ShimmerJavaClass() { + mBluetoothManager = new BasicShimmerBluetoothManagerPc(false); sdr.setWaitForData(mBluetoothManager.callBackObject); mBluetoothManager.addCallBack(sdr); if (mDebug) { @@ -96,13 +97,16 @@ public void actionPerformed(ActionEvent e) { } while(true) { - if(!dataQueue.isEmpty()) { + if (hasDataToRead(comPort)) { readData(); } + } } }); + + stopButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -136,37 +140,56 @@ public String[] retrieveSensorChannels() { return channelNamesList.toArray(new String[0]); } - - public Object[] receiveData() { - while (!dataQueue.isEmpty()) { - Object[] currentData = dataQueue.poll(); - - float[] newData = (float[]) currentData[0]; - signalNameArray = (String[]) currentData[1]; - signalFormatArray = (String[]) currentData[2]; - signalUnitArray = (String[]) currentData[3]; - - collectedData.add(newData); - } - - // Convert list to 2D float array (m × n) - float[][] dataMatrix = collectedData.toArray(new float[0][0]); - - return new Object[]{dataMatrix, signalNameArray, signalFormatArray, signalUnitArray}; - } - - private void sendData(Object[] data) { - dataQueue.add(data); - } + public boolean hasDataToRead(String comPort) { + Queue queue = dataQueues.get(comPort); + return queue != null && !queue.isEmpty(); + } + private void sendData(String comPort, Object[] data) { + dataQueues.computeIfAbsent(comPort, k -> new LinkedList<>()).add(data); + } - public void readData() { //Test receive data for all Object Cluster - Object[] data = receiveData(); - if (mDebug) { - System.out.println("New Data : " + data[0] + "\tChannel Name : " + data[1] - + "\tFormat : " + data[2] + "\tUnit : " + data[3]); - } + public void readData() { + for (String comPort : dataQueues.keySet()) { + Object[] data = receiveData(comPort); + if (data != null && mDebug) { + float[][] matrix = (float[][]) data[0]; + String[] signalNames = (String[]) data[1]; + String[] formats = (String[]) data[2]; + String[] units = (String[]) data[3]; + + System.out.println("==== Data from device: " + comPort + " ===="); + for (int i = 0; i < matrix.length; i++) { + System.out.print("Row " + i + ": "); + for (int j = 0; j < matrix[i].length; j++) { + System.out.print(matrix[i][j] + " " + units[j] + " [" + signalNames[j] + "] | "); + } + System.out.println(); + } + } + } + } + + public Object[] receiveData(String comPort) { + Queue queue = dataQueues.get(comPort); + if (queue == null || queue.isEmpty()) return null; + + List deviceData = new ArrayList<>(); + String[] signalNameArray = null, signalFormatArray = null, signalUnitArray = null; + + while (!queue.isEmpty()) { + Object[] data = queue.poll(); + float[] values = (float[]) data[1]; + signalNameArray = (String[]) data[2]; + signalFormatArray = (String[]) data[3]; + signalUnitArray = (String[]) data[4]; + deviceData.add(values); + } + + float[][] dataMatrix = deviceData.toArray(new float[0][0]); + return new Object[] { dataMatrix, signalNameArray, signalFormatArray, signalUnitArray }; } + public class SensorDataReceived extends BasicProcessWithCallBack { @Override @@ -218,9 +241,9 @@ protected void processMsgFromCallback(ShimmerMsg shimmerMSG) { } } - Object[] outputData = { newData, signalNameArray, signalFormatArray, signalUnitArray }; - - sendData(outputData); + String comPort = objc.getComPort(); + Object[] outputData = { comPort, newData, signalNameArray, signalFormatArray, signalUnitArray }; + sendData(comPort, outputData); } } } From 94b11021d6e35962fb658adcb903c9e48dd1e901 Mon Sep 17 00:00:00 2001 From: JongChern Date: Tue, 23 Sep 2025 18:34:55 +0800 Subject: [PATCH 6/6] Update ShimmerJavaClass.java --- .../com/shimmerresearch/tools/matlab/ShimmerJavaClass.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/matlab/ShimmerJavaClass.java b/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/matlab/ShimmerJavaClass.java index 04406d3b7..ad56ab320 100644 --- a/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/matlab/ShimmerJavaClass.java +++ b/ShimmerDriverPC/src/main/java/com/shimmerresearch/tools/matlab/ShimmerJavaClass.java @@ -178,7 +178,11 @@ public Object[] receiveData(String comPort) { while (!queue.isEmpty()) { Object[] data = queue.poll(); + if (data == null) continue; // skip this iteration safely + float[] values = (float[]) data[1]; + if (values == null) continue; + signalNameArray = (String[]) data[2]; signalFormatArray = (String[]) data[3]; signalUnitArray = (String[]) data[4];