Skip to content
Merged
2 changes: 2 additions & 0 deletions ShimmerBluetoothManager/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
2 changes: 2 additions & 0 deletions ShimmerDriver/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -247,6 +255,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);
// }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4501,6 +4501,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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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){
Expand Down
33 changes: 27 additions & 6 deletions ShimmerDriverPC/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
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.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
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.driver.FormatCluster;
import com.shimmerresearch.driverUtilities.ChannelDetails;
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;
private SensorDataReceived sdr = new SensorDataReceived();
private String[] channelNames;
private final ConcurrentLinkedQueue<String> connectedDevices = new ConcurrentLinkedQueue<>();
private final ConcurrentHashMap<String, Queue<Object[]>> dataQueues = new ConcurrentHashMap<>();
private List<float[]> collectedData = new ArrayList<>();


private boolean mDebug = true;

// private int rowIndex = 0;
Object[] currentData = null;
public static BasicShimmerBluetoothManagerPc mBluetoothManager;

public ShimmerJavaClass() {
mBluetoothManager = new BasicShimmerBluetoothManagerPc(false);
sdr.setWaitForData(mBluetoothManager.callBackObject);
mBluetoothManager.addCallBack(sdr);
if (mDebug) {
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");
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 (hasDataToRead(comPort)) {
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<String, ChannelDetails> mapOfAllChannels = mBluetoothManager.getShimmerDeviceBtConnected(comPort).getMapOfAllChannelsForStoringToDB(COMMUNICATION_TYPE.BLUETOOTH, null, false, false);
List<ChannelDetails> listOfChannelDetails = new ArrayList<ChannelDetails>(mapOfAllChannels.values());

List<String> channelNamesList = new ArrayList<String>();
for (ChannelDetails channel : listOfChannelDetails) {
channelNamesList.add(channel.mObjectClusterName);
}

return channelNamesList.toArray(new String[0]);
}
public boolean hasDataToRead(String comPort) {
Queue<Object[]> 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() {
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<Object[]> queue = dataQueues.get(comPort);
if (queue == null || queue.isEmpty()) return null;

List<float[]> deviceData = new ArrayList<>();
String[] signalNameArray = null, signalFormatArray = null, signalUnitArray = null;

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];
deviceData.add(values);
}

float[][] dataMatrix = deviceData.toArray(new float[0][0]);
return new Object[] { dataMatrix, signalNameArray, signalFormatArray, signalUnitArray };
}


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) {
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();
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);
System.out.flush();

}
} else if (ind == ShimmerPC.MSG_IDENTIFIER_NOTIFICATION_MESSAGE) {

} else if (ind == ShimmerPC.MSG_IDENTIFIER_DATA_PACKET) {
ObjectCluster objc = (ObjectCluster) shimmerMSG.mB;

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++) {
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;
}
}

String comPort = objc.getComPort();
Object[] outputData = { comPort, newData, signalNameArray, signalFormatArray, signalUnitArray };
sendData(comPort, outputData);
}
}
}
}
Loading