diff --git a/.gitignore b/.gitignore
index 937f8525..475319fc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,100 @@
ShimmerAndroidInstrumentDriver/build/generated/mockable-android-19.jar
ShimmerAndroidInstrumentDriver/build/generated/mockable-android-21.jar
ShimmerAndroidInstrumentDriver/gradle.properties
+
+# Built application files
+*.apk
+*.aar
+*.ap_
+*.aab
+
+# Files for the ART/Dalvik VM
+*.dex
+
+# Java class files
+*.class
+
+# Generated files
+bin/
+gen/
+out/
+# Uncomment the following line in case you need and you don't have the release build type files in your app
+# release/
+
+# Gradle files
+.gradle/
+build/
+
+# Local configuration file (sdk path, etc)
+local.properties
+
+# Proguard folder generated by Eclipse
+proguard/
+
+# Log Files
+*.log
+
+# Android Studio Navigation editor temp files
+.navigation/
+
+# Android Studio captures folder
+captures/
+
+# IntelliJ
+*.iml
+.idea/
+misc.xml
+deploymentTargetDropDown.xml
+render.experimental.xml
+.idea/workspace.xml
+.idea/tasks.xml
+.idea/gradle.xml
+.idea/assetWizardSettings.xml
+.idea/dictionaries
+.idea/libraries
+.idea/jarRepositories.xml
+# Android Studio 3 in .gitignore file.
+.idea/caches
+.idea/modules.xml
+# Comment next line if keeping position of elements in Navigation Editor is relevant for you
+.idea/navEditor.xml
+
+# Keystore files
+# Uncomment the following lines if you do not want to check your keystore files in.
+#*.jks
+#*.keystore
+
+# External native build folder generated in Android Studio 2.2 and later
+.externalNativeBuild
+.cxx/
+
+# Google Services (e.g. APIs or Firebase)
+# google-services.json
+
+# Freeline
+freeline.py
+freeline/
+freeline_project_description.json
+
+# fastlane
+fastlane/report.xml
+fastlane/Preview.html
+fastlane/screenshots
+fastlane/test_output
+fastlane/readme.md
+
+# Version control
+vcs.xml
+
+# lint
+lint/intermediates/
+lint/generated/
+lint/outputs/
+lint/tmp/
+# lint/reports/
+
+# Android Profiling
+*.hprof
gradle.properties
+ShimmerAndroidInstrumentDriver/.idea/jarRepositories.xml
+ShimmerAndroidInstrumentDriver/.idea/gradle.xml
diff --git a/ShimmerAndroidInstrumentDriver/.gitignore b/ShimmerAndroidInstrumentDriver/.gitignore
index ecc2fdb4..cecbba34 100644
--- a/ShimmerAndroidInstrumentDriver/.gitignore
+++ b/ShimmerAndroidInstrumentDriver/.gitignore
@@ -1,38 +1,93 @@
# Built application files
-/**/build/
+*.apk
+*.aar
+*.ap_
+*.aab
-# Crashlytics configuations
-com_crashlytics_export_strings.xml
+# Files for the ART/Dalvik VM
+*.dex
+
+# Java class files
+*.class
+
+# Generated files
+bin/
+gen/
+out/
+# Uncomment the following line in case you need and you don't have the release build type files in your app
+# release/
+
+# Gradle files
+.gradle/
+build/
# Local configuration file (sdk path, etc)
local.properties
-# Gradle generated files
-.gradle/
+# Proguard folder generated by Eclipse
+proguard/
+
+# Log Files
+*.log
-# Signing files
-.signing/
+# Android Studio Navigation editor temp files
+.navigation/
-# User-specific configurations
-.idea/libraries/
+# Android Studio captures folder
+captures/
+
+# IntelliJ
+*.iml
+.idea/
+misc.xml
+deploymentTargetDropDown.xml
+render.experimental.xml
.idea/workspace.xml
.idea/tasks.xml
-.idea/.name
-.idea/compiler.xml
-.idea/copyright/profiles_settings.xml
-.idea/encodings.xml
-.idea/misc.xml
+.idea/gradle.xml
+.idea/assetWizardSettings.xml
+.idea/dictionaries
+.idea/libraries
+.idea/jarRepositories.xml
+# Android Studio 3 in .gitignore file.
+.idea/caches
.idea/modules.xml
-.idea/scopes/scope_settings.xml
-.idea/vcs.xml
-*.iml
+# Comment next line if keeping position of elements in Navigation Editor is relevant for you
+.idea/navEditor.xml
+
+# Keystore files
+# Uncomment the following lines if you do not want to check your keystore files in.
+#*.jks
+#*.keystore
+
+# External native build folder generated in Android Studio 2.2 and later
+.externalNativeBuild
+.cxx/
+
+# Google Services (e.g. APIs or Firebase)
+# google-services.json
+
+# Freeline
+freeline.py
+freeline/
+freeline_project_description.json
+
+# fastlane
+fastlane/report.xml
+fastlane/Preview.html
+fastlane/screenshots
+fastlane/test_output
+fastlane/readme.md
+
+# Version control
+vcs.xml
+
+# lint
+lint/intermediates/
+lint/generated/
+lint/outputs/
+lint/tmp/
+# lint/reports/
-# OS-specific files
-.DS_Store
-.DS_Store?
-._*
-.Spotlight-V100
-.Trashes
-ehthumbs.db
-Thumbs.db
-/ShimmerAndroidInstrumentDriver/gradle.properties
+# Android Profiling
+*.hprof
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/.idea/codeStyles/Project.xml b/ShimmerAndroidInstrumentDriver/.idea/codeStyles/Project.xml
deleted file mode 100644
index 30aa626c..00000000
--- a/ShimmerAndroidInstrumentDriver/.idea/codeStyles/Project.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/.idea/gradle.xml b/ShimmerAndroidInstrumentDriver/.idea/gradle.xml
deleted file mode 100644
index 327e3464..00000000
--- a/ShimmerAndroidInstrumentDriver/.idea/gradle.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/.idea/runConfigurations.xml b/ShimmerAndroidInstrumentDriver/.idea/runConfigurations.xml
deleted file mode 100644
index 7f68460d..00000000
--- a/ShimmerAndroidInstrumentDriver/.idea/runConfigurations.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/.gitignore b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/.gitignore
index a307a61d..c2f04fbc 100644
--- a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/.gitignore
+++ b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/.gitignore
@@ -1,37 +1,90 @@
# Built application files
-/*/build/
+*.apk
+*.aar
+*.ap_
+*.aab
-# Crashlytics configuations
-com_crashlytics_export_strings.xml
+# Files for the ART/Dalvik VM
+*.dex
+
+# Java class files
+*.class
+
+# Generated files
+bin/
+gen/
+out/
+# Uncomment the following line in case you need and you don't have the release build type files in your app
+# release/
+
+# Gradle files
+.gradle/
+build/
# Local configuration file (sdk path, etc)
local.properties
-# Gradle generated files
-.gradle/
+# Proguard folder generated by Eclipse
+proguard/
+
+# Log Files
+*.log
-# Signing files
-.signing/
+# Android Studio Navigation editor temp files
+.navigation/
-# User-specific configurations
-.idea/libraries/
+# Android Studio captures folder
+captures/
+
+# IntelliJ
+*.iml
.idea/workspace.xml
.idea/tasks.xml
-.idea/.name
-.idea/compiler.xml
-.idea/copyright/profiles_settings.xml
-.idea/encodings.xml
-.idea/misc.xml
+.idea/gradle.xml
+.idea/assetWizardSettings.xml
+.idea/dictionaries
+.idea/libraries
+.idea/jarRepositories.xml
+# Android Studio 3 in .gitignore file.
+.idea/caches
.idea/modules.xml
-.idea/scopes/scope_settings.xml
-.idea/vcs.xml
-*.iml
+# Comment next line if keeping position of elements in Navigation Editor is relevant for you
+.idea/navEditor.xml
+
+# Keystore files
+# Uncomment the following lines if you do not want to check your keystore files in.
+#*.jks
+#*.keystore
+
+# External native build folder generated in Android Studio 2.2 and later
+.externalNativeBuild
+.cxx/
+
+# Google Services (e.g. APIs or Firebase)
+# google-services.json
+
+# Freeline
+freeline.py
+freeline/
+freeline_project_description.json
+
+# fastlane
+fastlane/report.xml
+fastlane/Preview.html
+fastlane/screenshots
+fastlane/test_output
+fastlane/readme.md
+
+# Version control
+vcs.xml
+
+# lint
+lint/intermediates/
+lint/generated/
+lint/outputs/
+lint/tmp/
+# lint/reports/
-# OS-specific files
-.DS_Store
-.DS_Store?
-._*
-.Spotlight-V100
-.Trashes
-ehthumbs.db
-Thumbs.db
\ No newline at end of file
+# Android Profiling
+*.hprof
+/gradle.properties
diff --git a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/build.gradle b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/build.gradle
index b70f3425..f3dcbd5e 100644
--- a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/build.gradle
+++ b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/build.gradle
@@ -2,13 +2,10 @@
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
-//apply plugin: 'com.jfrog.artifactory'
apply plugin: 'maven-publish'
-version = '3.0.73Beta'
-
android {
- compileSdkVersion 25
+ compileSdkVersion 33
lintOptions {
abortOnError false
@@ -18,7 +15,7 @@ android {
// Enabling multidex support.
multiDexEnabled true
minSdkVersion 14
- targetSdkVersion 14
+ targetSdkVersion 33
}
buildTypes {
@@ -75,12 +72,13 @@ publishing {
def getArtificatId = { ->
return "ShimmerAndroidInstrumentDriver" // Replace with library name ID
}
+/*
publishing {
publications {
bar(MavenPublication) {
groupId = 'com.shimmerresearch' // Replace with your package's group/organization name
artifactId = 'shimmerandroidinstrumentdriver' // Replace with the name of your package
- version = '3.1.0_alpha' // Replace with your package version
+ version = '3.0.83_beta' // Replace with your package version
artifact("$buildDir/outputs/aar/${getArtificatId()}-release.aar")
}
}
@@ -90,31 +88,20 @@ publishing {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/ShimmerEngineering/ShimmerAndroidAPI")
credentials {
- /**Create github.properties in root project folder file with gpra.usr=GITHUB_USER_ID & gpra.key=PERSONAL_ACCESS_TOKEN**/
- username = githubProperties['gpra.usr'] ?: System.getenv("GPRA_USER")
- password = githubProperties['gpra.key'] ?: System.getenv("GPRA_API_KEY")
+ //Create github.properties in root project folder file with gpra.usr=GITHUB_USER_ID & gpra.key=PERSONAL_ACCESS_TOKEN
+ username = project.findProperty('gpra.usr')
+ password = project.findProperty('gpra.key')
}
}
}
}
-
+*/
dependencies {
compile 'com.google.guava:guava:20.0'
compile 'java3d:vecmath:1.3.1'
compile files('libs/ShimmerBiophysicalProcessingLibrary_Rev_0_11.jar')
compile files('libs/AndroidBluetoothLibrary.jar')
compile files('libs/androidplot-core-0.5.0-release.jar')
- implementation (group: 'com.shimmerresearch', name: 'shimmerbluetoothmanager', version:'0.10.0_alpha'){
- // excluding org.json which is provided by Android
- exclude group: 'io.netty'
- exclude group: 'com.google.protobuf'
- exclude group: 'org.apache.commons.math'
- }
- implementation (group: 'com.shimmerresearch', name: 'shimmerdriver', version:'0.10.0_alpha'){
- // excluding org.json which is provided by Android
- exclude group: 'io.netty'
- exclude group: 'com.google.protobuf'
- exclude group: 'org.apache.commons.math'
- }
- compile 'com.android.support:appcompat-v7:25.3.1'
+ compile 'com.android.support:appcompat-v7:26.1.0'
+ compile 'com.clj.fastble:FastBleLib:2.3.4'
}
diff --git a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/Shimmer.java b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/Shimmer.java
index 7d8c3e68..e883ffe0 100644
--- a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/Shimmer.java
+++ b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/Shimmer.java
@@ -132,15 +132,22 @@
package com.shimmerresearch.android;
+import static android.content.Context.BLUETOOTH_SERVICE;
+
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothSocket;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
+import com.shimmerresearch.androidinstrumentdriver.R;
import com.shimmerresearch.bluetooth.BluetoothProgressReportPerCmd;
import com.shimmerresearch.bluetooth.ShimmerBluetooth;
import com.shimmerresearch.driver.CallbackObject;
@@ -151,9 +158,14 @@
import com.shimmerresearch.driver.ShimmerMsg;
import com.shimmerresearch.driver.shimmer2r3.ConfigByteLayoutShimmer3;
import com.shimmerresearch.driver.shimmer4sdk.Shimmer4sdk;
+import com.shimmerresearch.driverUtilities.ShimmerBattStatusDetails;
import com.shimmerresearch.driverUtilities.ShimmerVerDetails;
+import com.shimmerresearch.driverUtilities.UtilShimmer;
+import com.shimmerresearch.exceptions.ShimmerException;
import com.shimmerresearch.exgConfig.ExGConfigOptionDetails;
+import org.apache.commons.lang3.ArrayUtils;
+
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
@@ -221,6 +233,7 @@ public class Shimmer extends ShimmerBluetooth{
public static final int MSG_STATE_STREAMING = 4;
public static final int MSG_STATE_STOP_STREAMING = 5;
+ transient private Context mContext;
protected String mClassName="Shimmer";
private int mBluetoothLib=0; // 0 = default lib, 1 = arduino lib
@@ -236,11 +249,37 @@ public class Shimmer extends ShimmerBluetooth{
setUseInfoMemConfigMethod(true);
}
+ protected void unregisterDisconnectListener(){
+ if(mContext!=null) {
+ try {
+ mContext.unregisterReceiver(mReceiver);
+ } catch (Exception ex){
+ System.out.println(ex);
+ }
+ }
+ }
+
+ protected void registerDisconnectListener(){
+ if(mContext!=null) {
+ System.out.println("initialize process 0) register disconnect listener");
+ BluetoothAdapter bluetoothAdapter = null;
+ if (android.os.Build.VERSION.SDK_INT >= 18) {
+ BluetoothManager bluetoothManager = (BluetoothManager) mContext.getSystemService(BLUETOOTH_SERVICE);
+ bluetoothAdapter = bluetoothManager.getAdapter();
+ } else bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+
+ IntentFilter filter = new IntentFilter(bluetoothAdapter.ACTION_STATE_CHANGED);
+ filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
+ filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
+ mContext.registerReceiver(mReceiver, filter);
+ }
+ }
+
/**
* This constructor is for applications that only require one Handler.
* @param handler add handler to receive msgs from the shimmer class
*/
- public Shimmer(Handler handler) {
+ public Shimmer(Handler handler, Context context) {
super();
mAdapter = BluetoothAdapter.getDefaultAdapter();
mBluetoothRadioState = BT_STATE.DISCONNECTED;
@@ -248,20 +287,40 @@ public Shimmer(Handler handler) {
// mContinousSync=continousSync;
mSetupDeviceWhileConnecting=false;
mUseProcessingThread = true;
+ mContext = context;
}
+ // The BroadcastReceiver that listens for discovered devices and
+ // changes the title when discovery is finished
+ transient private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ // When discovery finds a device
+ if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
+ BluetoothDevice device = intent
+ .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+
+ String macAdd = device.getAddress();
+ if (macAdd.equals(mMyBluetoothAddress)){
+ connectionLost();
+ }
+ }
+ }
+ };
/**
* This constructor is for applications requiring more than one Handler so as to receive the msg
* in multiple threads.
* @param handlerList this is an ArrayList containing multiple Handlers
*/
- public Shimmer(ArrayList handlerList) {
+ public Shimmer(ArrayList handlerList, Context context) {
super();
mAdapter = BluetoothAdapter.getDefaultAdapter();
mBluetoothRadioState = BT_STATE.DISCONNECTED;
mHandlerList = handlerList;
mSetupDeviceWhileConnecting = false;
mUseProcessingThread = true;
+ mContext = context;
}
/**
@@ -436,14 +495,16 @@ public Shimmer(Context context, Handler handler, String myName, double samplingR
* @param magRange
* @param orientation
* @param pressureResolution
+ * @param context
*/
- public Shimmer(Handler handler, String userAssignedName, double samplingRate, int accelRange, int gsrRange, Integer[] sensorIdsToEnable, int gyroRange, int magRange, int orientation, int pressureResolution){
+ public Shimmer(Handler handler, String userAssignedName, double samplingRate, int accelRange, int gsrRange, Integer[] sensorIdsToEnable, int gyroRange, int magRange, int orientation, int pressureResolution, Context context){
super(userAssignedName, samplingRate, sensorIdsToEnable, accelRange, gsrRange, gyroRange, magRange, pressureResolution);
mAdapter = BluetoothAdapter.getDefaultAdapter();
mBluetoothRadioState = BT_STATE.DISCONNECTED;
mHandlerList.add(handler);
setupOrientation(orientation, samplingRate);
mUseProcessingThread = true;
+ mContext = context;
}
/** Shimmer2R Constructor
@@ -455,7 +516,7 @@ public Shimmer(Handler handler, String userAssignedName, double samplingRate, in
* @param magGain
* @param orientation
*/
- public Shimmer(Handler handler, String myName, double samplingRate, int accelRange, int gsrRange, int setEnabledSensors, int magGain, int orientation) {
+ public Shimmer(Handler handler, String myName, double samplingRate, int accelRange, int gsrRange, int setEnabledSensors, int magGain, int orientation, Context context) {
super(myName,samplingRate, setEnabledSensors, accelRange, gsrRange, magGain);
setupOrientation(orientation, samplingRate);
mAdapter = BluetoothAdapter.getDefaultAdapter();
@@ -463,6 +524,7 @@ public Shimmer(Handler handler, String myName, double samplingRate, int accelRan
mHandlerList.add(handler);
setupOrientation(orientation, samplingRate);
mUseProcessingThread = true;
+ mContext = context;
}
/**
@@ -479,7 +541,7 @@ public Shimmer(Handler handler, String myName, double samplingRate, int accelRan
* @param pressureResolution
* @param enableCalibration
*/
- public Shimmer(Handler handler, String userAssignedName, double samplingRate, int accelRange, int gsrRange, Integer[] sensorIdsToEnable, int gyroRange, int magRange, int orientation, int pressureResolution, boolean enableCalibration){
+ public Shimmer(Handler handler, String userAssignedName, double samplingRate, int accelRange, int gsrRange, Integer[] sensorIdsToEnable, int gyroRange, int magRange, int orientation, int pressureResolution, boolean enableCalibration, Context context){
super(userAssignedName, samplingRate, sensorIdsToEnable, accelRange, gsrRange, gyroRange, magRange, pressureResolution);
mAdapter = BluetoothAdapter.getDefaultAdapter();
mBluetoothRadioState = BT_STATE.DISCONNECTED;
@@ -487,6 +549,7 @@ public Shimmer(Handler handler, String userAssignedName, double samplingRate, in
setupOrientation(orientation, samplingRate);
setEnableCalibration(enableCalibration);
mUseProcessingThread = true;
+ mContext = context;
}
/**
@@ -501,7 +564,7 @@ public Shimmer(Handler handler, String userAssignedName, double samplingRate, in
* @param orientation
* @param enableCalibration
*/
- public Shimmer(Handler handler, String myName, double samplingRate, int accelRange, int gsrRange, int setEnabledSensors, int magGain, int orientation, boolean enableCalibration) {
+ public Shimmer(Handler handler, String myName, double samplingRate, int accelRange, int gsrRange, int setEnabledSensors, int magGain, int orientation, boolean enableCalibration, Context context) {
super(myName,samplingRate, setEnabledSensors, accelRange, gsrRange, magGain);
setupOrientation(orientation, samplingRate);
mAdapter = BluetoothAdapter.getDefaultAdapter();
@@ -510,9 +573,9 @@ public Shimmer(Handler handler, String myName, double samplingRate, int accelRan
setupOrientation(orientation, samplingRate);
setEnableCalibration(enableCalibration);
mUseProcessingThread = true;
+ mContext = context;
}
-
/**
* Set the current state of the chat connection
* @param state An integer defining the current connection state
@@ -535,11 +598,11 @@ public Shimmer(Handler handler, String myName, double samplingRate, int accelRan
* @param bluetoothLibrary Supported libraries are 'default' and 'gerdavax'
*/
public synchronized void connect(final String address, String bluetoothLibrary) {
+ registerDisconnectListener();
mIamAlive = false;
getListofInstructions().clear();
mFirstTime=true;
-
if (bluetoothLibrary=="default"){
mMyBluetoothAddress=address;
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
@@ -592,6 +655,7 @@ public synchronized void ready() {
* @param socket The BluetoothSocket on which the connection was made
*/
public synchronized void connected(BluetoothSocket socket) {
+ System.out.println("initialize process 2) connected and start initialize");
// Cancel the thread that completed the connection
if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}
// Cancel any thread currently running a connection
@@ -599,9 +663,11 @@ public synchronized void connected(BluetoothSocket socket) {
// Start the thread to manage the connection and perform transmissions
mConnectedThread = new ConnectedThread(socket);
mIOThread = new IOThread();
+ mIOThread.setName("IO Thread " + socket.getRemoteDevice().getAddress());
mIOThread.start();
if (mUseProcessingThread){
mPThread = new ProcessingThread();
+ mPThread.setName("P Thread " + socket.getRemoteDevice().getAddress());
mPThread.start();
}
@@ -618,7 +684,7 @@ public synchronized void connected(BluetoothSocket socket) {
/**
* Stop all threads
*/
- public synchronized void stop() {
+ public void stop() {
if (mTimerReadStatus!=null) {
mTimerReadStatus.cancel();
mTimerReadStatus.purge();
@@ -651,15 +717,267 @@ public synchronized void stop() {
mConnectThread = null;
}
if (mConnectedThread != null) {
+ mConnectedThread.cancel();
+ mConnectedThread = null;
+ }
+
+ }
+
+ @Override
+ protected void clearSingleDataPacketFromBuffers(byte[] bufferTemp, int packetSize) {
+ byte[] fullBuffer = mByteArrayOutputStream.toByteArray();
+ byte[] keepBuffer = new byte[fullBuffer.length-packetSize];
+ System.arraycopy(fullBuffer,packetSize,keepBuffer,0,keepBuffer.length);
+ this.mByteArrayOutputStream.reset();
+ try {
+ this.mByteArrayOutputStream.write(keepBuffer);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ if (this.mEnablePCTimeStamps) {
+ for(int i = 0; i < packetSize; ++i) {
+ try {
+ this.mListofPCTimeStamps.remove(0);
+ } catch (Exception var5) {
+ this.consolePrintException(var5.getMessage(), var5.getStackTrace());
+ }
+ }
+ }
+
+ }
+
+ @Override
+ protected void processPacket() {
+ setIamAlive(true);
+ byte[] allBytes = mByteArrayOutputStream.toByteArray();
+ byte[] bufferTemp = new byte[getPacketSizeWithCrc()+2];
+ System.arraycopy(allBytes,0,bufferTemp,0,bufferTemp.length);
+ //Data packet followed by another data packet
+ if(bufferTemp[0]==DATA_PACKET
+ && bufferTemp[getPacketSizeWithCrc()+1]==DATA_PACKET){
+
+ if (mBtCommsCrcModeCurrent != BT_CRC_MODE.OFF && !checkCrc(bufferTemp, getPacketSize() + 1)) {
+ discardFirstBufferByte();
+ return;
+ }
+
+ //Handle the data packet
+ processDataPacket(bufferTemp);
+ clearSingleDataPacketFromBuffers(bufferTemp, getPacketSizeWithCrc()+1);
+ }
+
+ //Data packet followed by an ACK (suggesting an ACK in response to a SET BT command or else a BT response command)
+ else if(bufferTemp[0]==DATA_PACKET
+ && bufferTemp[getPacketSizeWithCrc()+1]==ACK_COMMAND_PROCESSED){
+
+ if(mByteArrayOutputStream.size()>getPacketSizeWithCrc()+2){
+ allBytes = mByteArrayOutputStream.toByteArray();
+ bufferTemp = new byte[getPacketSizeWithCrc()+3]; //check if the next byte is data packet
+ System.arraycopy(allBytes,0,bufferTemp,0,bufferTemp.length);
+ if(bufferTemp[getPacketSizeWithCrc()+2]==DATA_PACKET){
+ //Firstly handle the data packet
+ processDataPacket(bufferTemp);
+ clearSingleDataPacketFromBuffers(bufferTemp, getPacketSizeWithCrc()+2); //clear an extra byte which is the ack
+
+ //Then handle the ACK from the last SET command
+ if(isKnownSetCommand(mCurrentCommand)){
+ stopTimerCheckForAckOrResp(); //cancel the ack timer
+ mWaitForAck=false;
+
+ processAckFromSetCommand(mCurrentCommand);
+
+ mTransactionCompleted = true;
+ setInstructionStackLock(false);
+ }
+ printLogDataForDebugging("Ack Received for Command: \t\t\t" + btCommandToString(mCurrentCommand));
+ }
+
+ //this is for LogAndStream support, command is transmitted and ack received
+ else if(isSupportedInStreamCmds() && bufferTemp[getPacketSizeWithCrc()+2]==INSTREAM_CMD_RESPONSE){
+ printLogDataForDebugging("COMMAND TXed and ACK RECEIVED IN STREAM");
+ printLogDataForDebugging("INS CMD RESP");
+
+ //Firstly handle the in-stream response
+ stopTimerCheckForAckOrResp(); //cancel the ack timer
+ mWaitForResponse=false;
+ mWaitForAck=false;
+
+ processInstreamResponse();
+
+ // Need to remove here because it is an
+ // in-stream response while streaming so not
+ // handled elsewhere
+ if(getListofInstructions().size()>0){
+ removeInstruction(0);
+ }
+
+ mTransactionCompleted=true;
+ setInstructionStackLock(false);
+
+ //Then process the Data packet
+ //processDataPacket(bufferTemp);
+ //clearBuffers();
+ }
+ else {
+ printLogDataForDebugging("Unknown parsing error while streaming");
+ discardFirstBufferByte(); //throw the first byte away
+ }
+ }
+ /*
+ if(mByteArrayOutputStream.size()>getPacketSizeWithCrc()+2){
+ printLogDataForDebugging("Unknown packet error (check with JC):\tExpected: " + (getPacketSizeWithCrc()+2) + "bytes but buffer contains " + mByteArrayOutputStream.size() + "bytes");
+ discardFirstBufferByte(); //throw the first byte away
+ }
+ */
+
+ }
+ //TODO: ACK in bufferTemp[0] not handled
+ //else if
+ else {
+ printLogDataForDebugging("Packet syncing problem:\tExpected: " + (getPacketSizeWithCrc()+2) + "bytes. Buffer contains " + mByteArrayOutputStream.size() + "bytes"
+ + "\nBuffer = " + UtilShimmer.bytesToHexStringWithSpacesFormatted(mByteArrayOutputStream.toByteArray()));
+ discardFirstBufferByte(); //throw the first byte away
+ }
+ }
+
+ protected byte[] getDataFromArrayOutputStream(int extraBytesLength){
+ if (mByteArrayOutputStream.size() >= getPacketSizeWithCrc() + extraBytesLength) {
+ byte[] allBytes = mByteArrayOutputStream.toByteArray();
+ byte[] bufferTemp = new byte[getPacketSizeWithCrc() + extraBytesLength]; //check if the next byte is data packet
+ System.arraycopy(allBytes, 0, bufferTemp, 0, bufferTemp.length);
+ return bufferTemp;
+ }
+ return null;
+ }
+
+ /** process responses to in-stream response */
+ @Override
+ protected void processInstreamResponse() {
+
+ if (mBluetoothRadioState.equals(BT_STATE.CONNECTED)){
+ super.processInstreamResponse();
+ } else if (mBluetoothRadioState.equals(BT_STATE.STREAMING)){
+ //byte[] inStreamResponseCommandBuffer = readBytes(1, INSTREAM_CMD_RESPONSE);
+ byte[] bufferTemp = getDataFromArrayOutputStream(4);
+ if (bufferTemp != null) {
+ byte inStreamResponseCommand = bufferTemp[bufferTemp.length - 1];
+ consolePrintLn("In-stream received = " + btCommandToString(inStreamResponseCommand));
+
+ if (inStreamResponseCommand == DIR_RESPONSE) {
+ //byte[] responseData = readBytes(1, inStreamResponseCommand);
+ bufferTemp = getDataFromArrayOutputStream(5);
+ if (bufferTemp != null) {
+ int directoryNameLength = bufferTemp[bufferTemp.length - 1];
+ byte[] bufferDirectoryName = new byte[directoryNameLength];
+ bufferTemp = getDataFromArrayOutputStream(5 + directoryNameLength);
+ System.arraycopy(bufferTemp, bufferTemp.length - bufferDirectoryName.length, bufferDirectoryName, 0, bufferDirectoryName.length);
+ if (bufferDirectoryName != null) {
+ String tempDirectory = new String(bufferDirectoryName);
+ mDirectoryName = tempDirectory;
+ printLogDataForDebugging("Directory Name = " + mDirectoryName);
+ }
+ processDataPacket(bufferTemp);
+ clearSingleDataPacketFromBuffers(bufferTemp, bufferTemp.length + mBtCommsCrcModeCurrent.getNumCrcBytes());
+ }
+ } else if (inStreamResponseCommand == STATUS_RESPONSE) {
+ bufferTemp = getDataFromArrayOutputStream(5);
+ if (bufferTemp != null) {
+ byte[] responseData = new byte[1];
+ System.arraycopy(bufferTemp, bufferTemp.length - responseData.length, responseData, 0, responseData.length);
+ if (responseData != null) {
+ parseStatusByte(responseData[0]);
+
+ if (!isSupportedRtcStateInStatus()) {
+ if (!mIsSensing && !isInitialised()) {
+ writeRealTimeClock();
+ }
+ } else {
+ //New case to make sure RTC is set if it hasn't been already
+ if (!isSDLogging() && (!isInitialised() || !mIsRtcSet)) {
+ writeRealTimeClock();
+ }
+ }
+ eventLogAndStreamStatusChanged(mCurrentCommand);
+ processDataPacket(bufferTemp);
+ clearSingleDataPacketFromBuffers(bufferTemp, bufferTemp.length + mBtCommsCrcModeCurrent.getNumCrcBytes());
+ }
+ }
+ } else if (inStreamResponseCommand == VBATT_RESPONSE) {
+ bufferTemp = getDataFromArrayOutputStream(7);
+ if (bufferTemp != null) {
+ byte[] responseData = new byte[3];
+ System.arraycopy(bufferTemp, bufferTemp.length - responseData.length, responseData, 0, responseData.length);
+ if (responseData != null) {
+ ShimmerBattStatusDetails battStatusDetails = new ShimmerBattStatusDetails(((responseData[1] & 0xFF) << 8) + (responseData[0] & 0xFF), responseData[2]);
+ setBattStatusDetails(battStatusDetails);
+ printLogDataForDebugging("Battery Status:"
+ + "\tVoltage=" + battStatusDetails.getBattVoltageParsed()
+ + "\tCharging status=" + battStatusDetails.getChargingStatusParsed()
+ + "\tBatt %=" + battStatusDetails.getEstimatedChargePercentageParsed());
+ }
+ processDataPacket(bufferTemp);
+ clearSingleDataPacketFromBuffers(bufferTemp, bufferTemp.length + mBtCommsCrcModeCurrent.getNumCrcBytes());
+ }
+
+ } else {
+ discardFirstBufferByte();
+ }
+ }
+ }
+ }
+
+
+ @Override
+ protected void processWhileStreaming() {
+ byte[] byteBuffer = readBytes(availableBytes());
+ if(byteBuffer!=null){
try {
- wait(200);
- } catch (InterruptedException e) {
- e.printStackTrace();
+ mByteArrayOutputStream.write(byteBuffer);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
}
- mConnectedThread.cancel();
- mConnectedThread = null;
+ //Everytime a byte is received the timestamp is taken
+ if(mEnablePCTimeStamps) {
+ for (int index:byteBuffer) {
+ mListofPCTimeStamps.add(System.currentTimeMillis());
+ }
+ }
+ }
+ else {
+ printLogDataForDebugging("readbyte null");
}
+ //If there is a full packet and the subsequent sequence number of following packet
+ if(mByteArrayOutputStream.size()>=getPacketSizeWithCrc()+2){ // +2 because there are two acks
+ processPacket();
+ }
+ }
+
+ /**this is to clear the buffer
+ *
+ */
+ @Override
+ protected void clearSerialBuffer() {
+ startTimerCheckForSerialPortClear();
+ byte[] buffer = new byte[0];
+ while (availableBytes() != 0) {
+// int available = availableBytes();
+ if (bytesAvailableToBeRead()) {
+ //AA-283 : the clearing of the serial bytes , is too slow when streaming 1024Hz (e.g. exg test)
+ buffer = readBytes(availableBytes());
+
+ if (mSerialPortReadTimeout) {
+ break;
+ }
+ }
+ }
+
+ if (buffer.length > 0) {
+ String msg = "Clearing Buffer:\t\t" + UtilShimmer.bytesToHexStringWithSpacesFormatted(buffer);
+ printLogDataForDebugging(msg);
+ }
+
+ stopTimerCheckForSerialPortClear();
}
/**
@@ -668,6 +986,7 @@ public synchronized void stop() {
* @see ConnectedThread write(byte[])
*/
public void write(byte[] out) {
+ /*
// Create temporary object
ConnectedThread r;
// Synchronize a copy of the ConnectedThread
@@ -678,6 +997,8 @@ public void write(byte[] out) {
}
// Perform the write unsynchronized
r.write(out);
+ */
+ mConnectedThread.write(out);
}
/**
@@ -746,6 +1067,7 @@ public ConnectThread(BluetoothDevice device) {
}
public void run() {
+ System.out.println("initialize process 1) start connecting thread");
setName("ConnectThread");
// Always cancel discovery because it will slow down a connection
@@ -989,7 +1311,7 @@ public void cancel() {
-
+ @Override
protected void inquiryDone() {
//TODO: Delete this...
// Message msg = mHandler.obtainMessage(MESSAGE_TOAST);
@@ -1001,6 +1323,7 @@ protected void inquiryDone() {
isReadyForStreaming();
}
+ @Override
protected void isReadyForStreaming(){
//TODO: Delete this...
// Message msg = mHandler.obtainMessage(MESSAGE_TOAST);
@@ -1030,7 +1353,12 @@ protected void isReadyForStreaming(){
//mHandler.obtainMessage(ShimmerBluetooth.MSG_IDENTIFIER_STATE_CHANGE, -1, -1, new ObjectCluster(mShimmerUserAssignedName,getBluetoothAddress(),mBluetoothRadioState)).sendToTarget();
Log.d(mClassName,"Shimmer " + mMyBluetoothAddress +" Initialization completed and is ready for Streaming");
if(mAutoStartStreaming){
- startStreaming();
+ try {
+ startStreaming();
+ } catch (ShimmerException e) {
+ connectionLost();
+ e.printStackTrace();
+ }
}
}
@@ -1345,6 +1673,7 @@ else if((mBluetoothRadioState==BT_STATE.DISCONNECTED)
mIsConnected = false;
mIsStreaming = false;
mIsInitialised = false;
+ unregisterDisconnectListener();
}
// Give the new state to the Handler so the UI Activity can update
@@ -1478,16 +1807,14 @@ public Set getSensorIdsSet() {
// }
// }
public void setRadio(BluetoothSocket socket){
-
+ System.out.println("initialize process set radio");
+ registerDisconnectListener();
if (socket.isConnected()){
setBluetoothRadioState(BT_STATE.CONNECTING);
mMyBluetoothAddress = socket.getRemoteDevice().getAddress();
connected(socket);
}
-
-
-
-}
+ }
private void sendMsgToHandlerList(int obtainMessage) {
for(Handler handler : mHandlerList) {
diff --git a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/VerisenseDeviceAndroid.java b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/VerisenseDeviceAndroid.java
new file mode 100644
index 00000000..69b5f64a
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/VerisenseDeviceAndroid.java
@@ -0,0 +1,56 @@
+package com.shimmerresearch.android;
+
+import android.bluetooth.BluetoothAdapter;
+import android.os.Handler;
+
+import com.shimmerresearch.bluetooth.ShimmerBluetooth;
+import com.shimmerresearch.driver.CallbackObject;
+import com.shimmerresearch.driver.ObjectCluster;
+import com.shimmerresearch.driver.ShimmerMsg;
+import com.shimmerresearch.verisense.VerisenseDevice;
+import com.shimmerresearch.verisense.communication.SyncProgressDetails;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class VerisenseDeviceAndroid extends VerisenseDevice {
+ transient List mHandlerList = new ArrayList();
+
+ public VerisenseDeviceAndroid(Handler handler) {
+ super();
+ mHandlerList.add(0, handler);
+ }
+
+ private void sendMsgToHandlerListTarget(int what, int arg1, int arg2, Object object) {
+ for(Handler handler : mHandlerList) {
+ if (handler!=null) {
+ handler.obtainMessage(what, arg1, arg2, object).sendToTarget();
+ }
+ }
+ }
+
+ @Override
+ protected void dataHandler(ObjectCluster ojc){
+ sendMsgToHandlerListTarget(ShimmerBluetooth.MSG_IDENTIFIER_DATA_PACKET, ojc);
+ }
+
+ private void sendMsgToHandlerListTarget(int what, Object object) {
+ for(Handler handler : mHandlerList) {
+ if (handler!=null) {
+ handler.obtainMessage(what, object).sendToTarget();
+ }
+ }
+ }
+
+ @Override
+ public void sendCallBackMsg(int i, Object ojc){
+ super.sendCallBackMsg(i, ojc);
+ if(i == ShimmerBluetooth.MSG_IDENTIFIER_STATE_CHANGE){
+ sendMsgToHandlerListTarget(i, -1, -1,
+ new ObjectCluster(mShimmerUserAssignedName, getMacId(), ((CallbackObject)ojc).mState));
+ }
+ else{
+ sendMsgToHandlerListTarget(i, -1, -1, ojc);
+ }
+ }
+}
diff --git a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/DeviceConfigFragment.java b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/DeviceConfigFragment.java
index 7716d2d9..f0984723 100644
--- a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/DeviceConfigFragment.java
+++ b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/DeviceConfigFragment.java
@@ -4,7 +4,6 @@
import android.app.Fragment;
import android.content.Context;
import android.os.Bundle;
-import android.support.annotation.Nullable;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
@@ -16,6 +15,8 @@
import android.widget.LinearLayout;
import android.widget.Toast;
+import androidx.annotation.Nullable;
+
import com.shimmerresearch.android.Shimmer;
import com.shimmerresearch.android.manager.ShimmerBluetoothManagerAndroid;
import com.shimmerresearch.androidinstrumentdriver.R;
diff --git a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/DeviceSensorConfigFragment.java b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/DeviceSensorConfigFragment.java
index c75be7c1..35eb97ad 100644
--- a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/DeviceSensorConfigFragment.java
+++ b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/DeviceSensorConfigFragment.java
@@ -4,7 +4,6 @@
import android.app.Fragment;
import android.content.Context;
import android.os.Bundle;
-import android.support.annotation.Nullable;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
@@ -16,6 +15,8 @@
import android.widget.LinearLayout;
import android.widget.Toast;
+import androidx.annotation.Nullable;
+
import com.shimmerresearch.android.Shimmer;
import com.shimmerresearch.android.manager.ShimmerBluetoothManagerAndroid;
import com.shimmerresearch.androidinstrumentdriver.R;
diff --git a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/FileListActivity.java b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/FileListActivity.java
index 9981904c..1b386080 100644
--- a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/FileListActivity.java
+++ b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/FileListActivity.java
@@ -4,8 +4,7 @@
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
-import android.support.annotation.Nullable;
-import android.support.v4.content.FileProvider;
+
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
@@ -14,6 +13,8 @@
import android.widget.Toast;
+import androidx.core.content.FileProvider;
+
import com.shimmerresearch.androidinstrumentdriver.R;
import org.apache.commons.lang3.StringUtils;
@@ -21,6 +22,8 @@
import java.io.File;
import java.util.ArrayList;
+import javax.annotation.Nullable;
+
/**
* Opens a list of files from a selected folder. Files in the list can be clicked to open an app selector.
* A file provider that is defined in the Android manifest is needed in order to provide read access to files which are clicked.
diff --git a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/PlotFragment.java b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/PlotFragment.java
index ac3a965d..e6d291cb 100644
--- a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/PlotFragment.java
+++ b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/PlotFragment.java
@@ -8,7 +8,6 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
-import android.support.annotation.Nullable;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
@@ -40,6 +39,8 @@
import java.util.HashMap;
import java.util.List;
+import javax.annotation.Nullable;
+
import pl.flex_it.androidplot.XYSeriesShimmer;
/**
diff --git a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/SensorsEnabledFragment.java b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/SensorsEnabledFragment.java
index 87789a54..06ef3e3b 100644
--- a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/SensorsEnabledFragment.java
+++ b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/SensorsEnabledFragment.java
@@ -24,6 +24,7 @@
import com.shimmerresearch.driverUtilities.SensorDetails;
import com.shimmerresearch.driverUtilities.SensorGroupingDetails;
import com.shimmerresearch.driverUtilities.ShimmerVerObject;
+import com.shimmerresearch.verisense.VerisenseDevice;
import java.util.ArrayList;
import java.util.List;
@@ -157,7 +158,7 @@ public void onClick(View v) {
AssembleShimmerConfig.generateSingleShimmerConfig(shimmerDeviceClone, Configuration.COMMUNICATION_TYPE.BLUETOOTH);
- if (shimmerDevice instanceof Shimmer) {
+ if (shimmerDevice instanceof Shimmer || shimmerDevice instanceof VerisenseDevice) {
bluetoothManager.configureShimmer(shimmerDeviceClone);
mCallback.onSensorsSelected();
diff --git a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/ShimmerBluetoothDialog.java b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/ShimmerBluetoothDialog.java
index 90413522..5564d42e 100644
--- a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/ShimmerBluetoothDialog.java
+++ b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/ShimmerBluetoothDialog.java
@@ -16,6 +16,7 @@
*/
+import android.Manifest;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
@@ -23,6 +24,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
@@ -38,6 +40,8 @@
import android.widget.Toast;
+import androidx.core.app.ActivityCompat;
+
import com.shimmerresearch.androidinstrumentdriver.R;
import java.util.Set;
@@ -47,7 +51,7 @@
* devices detected in the area after discovery. When a device is chosen
* by the user, the MAC address of the device is sent back to the parent
* Activity in the result Intent.
- *
+ *
*/
public class ShimmerBluetoothDialog extends Activity {
// Debugging
@@ -57,6 +61,7 @@ public class ShimmerBluetoothDialog extends Activity {
// Return Intent extra
public static String EXTRA_DEVICE_ADDRESS = "device_address";
+ public static String EXTRA_DEVICE_NAME = "device_name";
// Member fields
@@ -65,10 +70,11 @@ public class ShimmerBluetoothDialog extends Activity {
private ArrayAdapter mNewDevicesArrayAdapter;
//private String[] deviceAddresses={"","","","","","",""};
private Button scanButton;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
//Set Material Design if the device's OS is Android Lollipop or higher
- if(Build.VERSION.SDK_INT >= 21) {
+ if (Build.VERSION.SDK_INT >= 21) {
setTheme(android.R.style.Theme_Material_Light_Dialog);
} else {
setTheme(android.R.style.Theme_Holo_Light_Dialog);
@@ -84,7 +90,7 @@ protected void onCreate(Bundle savedInstanceState) {
// Initialize the button to perform device discovery
scanButton = (Button) findViewById(R.id.button_scan);
-
+
scanButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
doDiscovery();
@@ -111,7 +117,8 @@ public void onClick(View v) {
// Register for broadcasts when a device is discovered
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
this.registerReceiver(mReceiver, filter);
-
+ filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
+ this.registerReceiver(mReceiver, filter);
// Register for broadcasts when discovery has finished
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
this.registerReceiver(mReceiver, filter);
@@ -164,6 +171,19 @@ private void doDiscovery() {
findViewById(R.id.layoutNewDevices).setVisibility(View.VISIBLE);
// If we're already discovering, stop it
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) {
+ // TODO: Consider calling
+ // ActivityCompat#requestPermissions
+ // here to request the missing permissions, and then overriding
+ // public void onRequestPermissionsResult(int requestCode, String[] permissions,
+ // int[] grantResults)
+ // to handle the case where the user grants the permission. See the documentation
+ // for ActivityCompat#requestPermissions for more details.
+ return;
+ }
+ }
+
if (mBtAdapter.isDiscovering()) {
mBtAdapter.cancelDiscovery();
}
@@ -181,10 +201,11 @@ public void onItemClick(AdapterView> av, View v, int arg2, long arg3) {
// Get the device MAC address, which is the last 17 chars in the View
String info = ((TextView) v).getText().toString();
String address = info.substring(info.length() - 17);
-
+ String devicename = info.split("\n")[0];
// Create the result Intent and include the MAC address
Intent intent = new Intent();
intent.putExtra(EXTRA_DEVICE_ADDRESS, address);
+ intent.putExtra(EXTRA_DEVICE_NAME, devicename);
Toast.makeText(getApplicationContext(),"Device Selected " + "-> "+ address, Toast.LENGTH_SHORT).show();
setResult(Activity.RESULT_OK, intent); // Set result and finish this Activity
diff --git a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/ShimmerDialogConfigurations.java b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/ShimmerDialogConfigurations.java
index aa61f796..8fd3a567 100644
--- a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/ShimmerDialogConfigurations.java
+++ b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/ShimmerDialogConfigurations.java
@@ -6,7 +6,6 @@
import android.content.DialogInterface;
import android.hardware.Sensor;
import android.os.Build;
-import android.support.v4.content.ContextCompat;
import android.text.InputType;
import android.util.Log;
import android.view.Gravity;
@@ -29,6 +28,7 @@
import com.shimmerresearch.android.manager.ShimmerBluetoothManagerAndroid;
import com.shimmerresearch.android.shimmerService.ShimmerService;
import com.shimmerresearch.androidinstrumentdriver.R;
+import com.shimmerresearch.androidradiodriver.Shimmer3BLEAndroid;
import com.shimmerresearch.bluetooth.ShimmerBluetooth;
import com.shimmerresearch.driver.Configuration;
import com.shimmerresearch.driver.ShimmerDevice;
@@ -224,6 +224,8 @@ public void onClick(DialogInterface dialog, int id) {
if (shimmerDeviceClone instanceof Shimmer) {
bluetoothManager.configureShimmer(shimmerDeviceClone);
+ }else if(shimmerDeviceClone instanceof Shimmer3BLEAndroid) {
+ bluetoothManager.configureShimmer(shimmerDeviceClone);
}
}
})
@@ -329,6 +331,8 @@ public void onClick(DialogInterface dialog, int which) {
((Shimmer)shimmerDevice).writeConfigBytes(shimmerDeviceClone.getShimmerConfigBytes());
} else if (shimmerDevice instanceof Shimmer4Android){
((Shimmer4Android)shimmerDevice).writeConfigBytes(shimmerDeviceClone.getShimmerConfigBytes());
+ }else if(shimmerDeviceClone instanceof Shimmer3BLEAndroid) {
+ ((Shimmer3BLEAndroid)shimmerDevice).writeBytes(shimmerDeviceClone.getShimmerConfigBytes());
}
}
});
@@ -363,6 +367,8 @@ public void onClick(DialogInterface dialog, int which) {
((Shimmer)shimmerDevice).writeConfigBytes(shimmerDeviceClone.getShimmerConfigBytes());
} else if (shimmerDevice instanceof Shimmer4Android){
((Shimmer4Android)shimmerDevice).writeConfigBytes(shimmerDeviceClone.getShimmerConfigBytes());
+ }else if(shimmerDeviceClone instanceof Shimmer3BLEAndroid) {
+ ((Shimmer3BLEAndroid)shimmerDevice).writeBytes(shimmerDeviceClone.getShimmerConfigBytes());
}
}
});
@@ -415,6 +421,8 @@ public void onClick(DialogInterface dialog, int which) {
//((Shimmer)shimmerDevice).configureShimmer(shimmerDeviceClone);
} else if (shimmerDevice instanceof Shimmer4Android){
bluetoothManager.configureShimmer(shimmerDeviceClone);
+ }else if(shimmerDevice instanceof Shimmer3BLEAndroid) {
+ bluetoothManager.configureShimmer(shimmerDeviceClone);
}
}
});
@@ -532,6 +540,8 @@ public void writeConfigToShimmer(ShimmerDevice clone, ShimmerBluetoothManagerAnd
bluetoothManager.configureShimmer(clone);
} else if (clone instanceof Shimmer4Android){
bluetoothManager.configureShimmer(clone);
+ } else if (clone instanceof Shimmer3BLEAndroid){
+ bluetoothManager.configureShimmer(clone);
}
}
diff --git a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/SignalsToPlotFragment.java b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/SignalsToPlotFragment.java
index 7a946ef5..60532332 100644
--- a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/SignalsToPlotFragment.java
+++ b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/SignalsToPlotFragment.java
@@ -3,7 +3,6 @@
import android.content.Context;
import android.os.Bundle;
-import android.support.annotation.Nullable;
import android.app.Fragment;
import android.app.ListFragment;
import android.util.Log;
@@ -12,6 +11,8 @@
import android.widget.ArrayAdapter;
import android.widget.ListView;
+import androidx.annotation.Nullable;
+
import com.androidplot.xy.XYPlot;
import com.shimmerresearch.android.manager.ShimmerBluetoothManagerAndroid;
import com.shimmerresearch.android.shimmerService.ShimmerService;
diff --git a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/supportfragments/ConnectedShimmersListFragment.java b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/supportfragments/ConnectedShimmersListFragment.java
index 86430c6d..8d80d647 100644
--- a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/supportfragments/ConnectedShimmersListFragment.java
+++ b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/supportfragments/ConnectedShimmersListFragment.java
@@ -4,8 +4,8 @@
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.ListFragment;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.ListFragment;
import android.util.Log;
import android.view.View;
import android.widget.AbsListView;
@@ -26,24 +26,22 @@
*/
public class ConnectedShimmersListFragment extends ListFragment {
- OnShimmerDeviceSelectedListener mCallBack;
- String selectedDeviceAddress, selectedDeviceName;
final static String LOG_TAG = "SHIMMER";
+ OnShimmerDeviceSelectedListener mCallBack;
+ String selectedDeviceAddress;
ListView savedListView = null;
ArrayAdapter savedListAdapter = null;
- int selectedItemPos = -1;
List shimmerDeviceList;
Context context;
int selectedDevicePos = -1;
-
public ConnectedShimmersListFragment() {
// Required empty public constructor
}
//Container Activity must implement this interface
public interface OnShimmerDeviceSelectedListener {
- public void onShimmerDeviceSelected(String macAddress, String deviceName);
+ public void onShimmerDeviceSelected(String macAddress, String deviceName, Boolean selected);
}
@Override
@@ -66,72 +64,71 @@ public static ConnectedShimmersListFragment newInstance() {
public void buildShimmersConnectedListView(final List deviceList, final Context context) {
if(isVisible()){
- shimmerDeviceList = deviceList;
- this.context = context;
- if(deviceList == null) {
- //String[] displayList = {"Service not yet initialised"};
- String[] displayList = {"No devices connected"};
- ArrayAdapter listAdapter = new ArrayAdapter(context, android.R.layout.simple_list_item_1, displayList);
- setListAdapter(listAdapter);
- }
- else {
- final String[] nameList = new String[deviceList.size()];
- final String[] macList = new String[deviceList.size()];
- final String[] displayList = new String[deviceList.size()];
-
- for (int i = 0; i < nameList.length; i++) {
- nameList[i] = deviceList.get(i).getShimmerUserAssignedName();
- macList[i] = deviceList.get(i).getMacId();
- displayList[i] = nameList[i] + "\n" + macList[i];
+ shimmerDeviceList = deviceList;
+ this.context = context;
+ if(deviceList == null) {
+ //String[] displayList = {"Service not yet initialised"};
+ String[] displayList = {"No devices connected"};
+ ArrayAdapter listAdapter = new ArrayAdapter(context, android.R.layout.simple_list_item_1, displayList);
+ setListAdapter(listAdapter);
}
+ else {
+ final String[] nameList = new String[deviceList.size()];
+ final String[] macList = new String[deviceList.size()];
+ final String[] displayList = new String[deviceList.size()];
+
+ for (int i = 0; i < nameList.length; i++) {
+ nameList[i] = deviceList.get(i).getShimmerUserAssignedName();
+ macList[i] = deviceList.get(i).getMacId();
+ displayList[i] = nameList[i] + "\n" + macList[i];
+ }
- ArrayAdapter listAdapter = new ArrayAdapter(context, R.layout.simple_list_item_multiple_choice_force_black_text, displayList);
-
- //Set the list of devices to be displayed in the Fragment
- setListAdapter(listAdapter);
+ ArrayAdapter listAdapter = new ArrayAdapter(context, R.layout.simple_list_item_multiple_choice_force_black_text, displayList);
- final ListView listView = getListView();
- listView.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
- listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView> parent, View view, int position, long id) {
- selectedItemPos = position;
+ //Set the list of devices to be displayed in the Fragment
+ setListAdapter(listAdapter);
- selectedDeviceAddress = macList[position];
- selectedDeviceName = nameList[position];
- selectedDevicePos = position;
+ final ListView listView = getListView();
+ listView.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
+ listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
+ if(selectedDeviceAddress != null && selectedDeviceAddress == macList[position]){
+ selectedDeviceAddress = null;
+ selectedDevicePos = -1;
+ }
+ else{
+ selectedDeviceAddress = macList[position];
+ selectedDevicePos = position;
+ }
- try {
- mCallBack.onShimmerDeviceSelected(macList[position], nameList[position]);
- } catch (ClassCastException cce) {
+ try {
+ mCallBack.onShimmerDeviceSelected(macList[position], nameList[position], selectedDevicePos == -1 ? false : true);
+ } catch (ClassCastException cce) {
+ }
}
- }
- });
+ });
- //Save the listView so that it can be restored in onCreateView when returning to the Fragment.
- savedListView = listView;
- savedListAdapter = listAdapter;
+ //Save the listView so that it can be restored in onCreateView when returning to the Fragment.
+ savedListView = listView;
+ savedListAdapter = listAdapter;
- //Ensure that the selected item's checkbox is checked
- if (selectedDeviceAddress != null) {
+ //Ensure that the selected item's checkbox is checked
for (int i = 0; i < listView.getAdapter().getCount(); i++) {
-
View view = getViewByPosition(i, listView);
CheckedTextView checkedTextView = (CheckedTextView) view.findViewById(android.R.id.text1);
if (checkedTextView != null) {
String text = checkedTextView.getText().toString();
- if (text.contains(selectedDeviceAddress)) {
- listView.setItemChecked(i, true);
- } else {
+ if (selectedDeviceAddress == null || !text.contains(selectedDeviceAddress)) {
listView.setItemChecked(i, false);
}
+ else {
+ listView.setItemChecked(i, true);
+ }
}
-
}
}
-
- }
}
}
@@ -157,6 +154,11 @@ public View getViewByPosition(int pos, ListView listView) {
}
}
+ public void removeSelectedDevice(){
+ selectedDeviceAddress = null;
+ selectedDevicePos = -1;
+ }
+
public int getNumShimmersConnected() {
if(shimmerDeviceList != null) {
return shimmerDeviceList.size();
diff --git a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/supportfragments/DataSyncFragment.java b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/supportfragments/DataSyncFragment.java
new file mode 100644
index 00000000..be172081
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/supportfragments/DataSyncFragment.java
@@ -0,0 +1,55 @@
+package com.shimmerresearch.android.guiUtilities.supportfragments;
+
+import android.content.Context;
+import android.os.Bundle;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.EditText;
+import com.shimmerresearch.androidinstrumentdriver.R;
+
+
+public class DataSyncFragment extends Fragment {
+
+ Context context;
+ public EditText editTextParticipantName;
+ public EditText editTextTrialName;
+ public TextView TextViewPayloadIndex;
+ public TextView TextViewSpeed;
+ public TextView TextViewDirectory;
+ public Button ButtonDataSync;
+
+ public DataSyncFragment() {
+ // Required empty public constructor
+ }
+
+ public static DataSyncFragment newInstance() {
+ DataSyncFragment fragment = new DataSyncFragment();
+ Bundle args = new Bundle();
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ context = getActivity();
+ // Inflate the layout for this fragment
+ return inflater.inflate(R.layout.data_sync, container, false);
+ }
+
+ @Override
+ public void onActivityCreated(@Nullable Bundle savedInstanceState) {
+ ButtonDataSync = (Button) getView().findViewById(R.id.dataSyncButton);
+ editTextParticipantName = (EditText) getView().findViewById(R.id.participantName);
+ editTextTrialName = (EditText) getView().findViewById(R.id.trialName);
+ TextViewPayloadIndex = (TextView) getView().findViewById(R.id.payloadIndex);
+ TextViewSpeed = (TextView) getView().findViewById(R.id.speed);
+ TextViewDirectory = (TextView) getView().findViewById(R.id.directory);
+ super.onActivityCreated(savedInstanceState);
+ }
+}
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/supportfragments/DeviceConfigFragment.java b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/supportfragments/DeviceConfigFragment.java
index 191d47be..d5bcafcb 100644
--- a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/supportfragments/DeviceConfigFragment.java
+++ b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/supportfragments/DeviceConfigFragment.java
@@ -3,8 +3,9 @@
import android.content.Context;
import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.v4.app.Fragment;
+
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -22,8 +23,10 @@
import com.shimmerresearch.driverUtilities.AssembleShimmerConfig;
import com.shimmerresearch.driverUtilities.ConfigOptionDetailsSensor;
import com.shimmerresearch.driverUtilities.SensorDetails;
+import com.shimmerresearch.verisense.VerisenseDevice;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -48,10 +51,14 @@ public void buildDeviceConfigList(final ShimmerDevice shimmerDevice, final Conte
final Map configOptionsMap = shimmerDevice.getConfigOptionsMap();
shimmerDeviceClone = shimmerDevice.deepClone();
Map sensorMap = shimmerDevice.getSensorMap();
- List listOfKeys = new ArrayList();
+ final List listOfKeys = new ArrayList();
for (SensorDetails sd:sensorMap.values()) {
if (sd.mSensorDetailsRef.mListOfConfigOptionKeysAssociated!=null && sd.isEnabled()) {
- listOfKeys.addAll(sd.mSensorDetailsRef.mListOfConfigOptionKeysAssociated);
+ for(String configOptionKey:sd.mSensorDetailsRef.mListOfConfigOptionKeysAssociated){
+ if(!listOfKeys.contains(configOptionKey)){
+ listOfKeys.add(configOptionKey);
+ }
+ }
}
}
@@ -135,7 +142,7 @@ public boolean onChildClick(ExpandableListView parent, View v, int groupPosition
if(expandListView.getFooterViewsCount() == 0) {
LinearLayout buttonLayout = new LinearLayout(context);
buttonLayout.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
- buttonLayout.setOrientation(LinearLayout.HORIZONTAL);
+ buttonLayout.setOrientation(LinearLayout.VERTICAL);
Button writeConfigButton = new Button(context);
Button resetListButton = new Button(context);
writeConfigButton.setOnClickListener(new View.OnClickListener() {
@@ -146,9 +153,9 @@ public void onClick(View v) {
cloneList.add(0, shimmerDeviceClone);
AssembleShimmerConfig.generateMultipleShimmerConfig(cloneList, Configuration.COMMUNICATION_TYPE.BLUETOOTH);
- if(shimmerDeviceClone instanceof Shimmer) {
+ //if(shimmerDeviceClone instanceof Shimmer) {
bluetoothManager.configureShimmer(shimmerDeviceClone);
- }
+ //}
}
});
@@ -163,6 +170,39 @@ public void onClick(View v) {
});
writeConfigButton.setText("Write config to Shimmer");
resetListButton.setText("Reset settings");
+
+ if(shimmerDevice instanceof VerisenseDevice){
+ Button setDefaultConfigButton = new Button(context);
+ setDefaultConfigButton.setText("Set default config");
+ setDefaultConfigButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ final Map defaultConfigMap = new HashMap();
+ defaultConfigMap.put("Accel_Range", 3);
+ defaultConfigMap.put("Gyro_Range", 3);
+ defaultConfigMap.put("Accel_Rate", 2);
+ defaultConfigMap.put("Mode", 1);
+ defaultConfigMap.put("Accel_Gyro_Rate", 6);
+ defaultConfigMap.put("LP Mode", 1);
+ defaultConfigMap.put("Range", 3);
+ defaultConfigMap.put("PPG Rate", 3);
+
+ shimmerDeviceClone = shimmerDevice.deepClone();
+ for(String key : listOfKeys) {
+ if(defaultConfigMap.containsKey(key)){
+ final ConfigOptionDetailsSensor cods = configOptionsMap.get(key);
+ if(cods != null){
+ shimmerDeviceClone.setConfigValueUsingConfigLabel(key, cods.mConfigValues[defaultConfigMap.get(key)]);
+ }
+ }
+ }
+ expandListAdapter.updateCloneDevice(shimmerDeviceClone);
+ expandListAdapter.notifyDataSetChanged();
+ Toast.makeText(context, "Settings have been set to default", Toast.LENGTH_SHORT).show();
+ }
+ });
+ buttonLayout.addView(setDefaultConfigButton);
+ }
buttonLayout.addView(resetListButton);
buttonLayout.addView(writeConfigButton);
expandListView.addFooterView(buttonLayout);
diff --git a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/supportfragments/PlotFragment.java b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/supportfragments/PlotFragment.java
index 60cdf71b..b26f12e2 100644
--- a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/supportfragments/PlotFragment.java
+++ b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/supportfragments/PlotFragment.java
@@ -6,9 +6,11 @@
import android.graphics.Point;
import android.os.Bundle;
import android.os.Handler;
+import android.os.Looper;
import android.os.Message;
-import android.support.annotation.Nullable;
-import android.support.v4.app.Fragment;
+
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
@@ -39,6 +41,8 @@
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
import pl.flex_it.androidplot.XYSeriesShimmer;
@@ -50,6 +54,8 @@ public class PlotFragment extends Fragment {
static String deviceState = "";
static TextView textViewDeviceName;
static TextView textViewDeviceState;
+ static TextView textViewPRR;
+ static String selectedDeviceAddress;
private static String LOG_TAG = "PlotFragment";
Button signalsToPlotButton;
@@ -91,7 +97,7 @@ public void onActivityCreated(@Nullable Bundle savedInstanceState) {
initPlot();
textViewDeviceName = (TextView) getView().findViewById(R.id.textViewDeviceName);
textViewDeviceState = (TextView) getView().findViewById(R.id.textViewDeviceState);
-
+ textViewPRR = (TextView) getView().findViewById(R.id.textViewPRR);
super.onActivityCreated(savedInstanceState);
}
@@ -176,8 +182,25 @@ public void setShimmerService(ShimmerService service) {
}
shimmerService.mPlotManager.updateDynamicPlot(dynamicPlot);
}
-
-
+ static Timer timer = null;
+ static class PRRTask extends TimerTask {
+ @Override
+ public void run() {
+ if (shimmerService.getShimmer(mBluetoothAddress)!=null) {
+ double value = shimmerService.getShimmer(mBluetoothAddress).getPacketReceptionRateOverall();
+ final String formattedValue = String.format("%.2f", value);
+
+ Handler mainHandler = new Handler(Looper.getMainLooper());
+ mainHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ // Update UI elements here
+ textViewPRR.setText(formattedValue);
+ }
+ });
+ }
+ }
+ }
private static Handler graphHandler = new Handler() {
@@ -198,11 +221,18 @@ public void handleMessage(Message msg) {
}
switch (state) {
case CONNECTED:
+ if (timer!=null){
+ timer.cancel();
+ timer = new Timer();
+ }
Log.d(LOG_TAG,"Message Fully Initialized Received from Shimmer driver");
shimmerService.enableGraphingHandler(true);
deviceState = "Connected";
- textViewDeviceName.setText(mBluetoothAddress);
- textViewDeviceState.setText(deviceState);
+ if(selectedDeviceAddress.equals(mBluetoothAddress)){
+ textViewDeviceName.setText(mBluetoothAddress);
+ textViewDeviceState.setText(deviceState);
+ }
+
break;
case SDLOGGING:
Log.d(LOG_TAG,"Message Fully Initialized Received from Shimmer driver");
@@ -214,10 +244,23 @@ public void handleMessage(Message msg) {
case CONNECTING:
Log.d(LOG_TAG,"Driver is attempting to establish connection with Shimmer device");
deviceState = "Connecting";
- textViewDeviceName.setText(mBluetoothAddress);
- textViewDeviceState.setText(deviceState);
+ if(selectedDeviceAddress.equals(mBluetoothAddress)){
+ textViewDeviceName.setText(mBluetoothAddress);
+ textViewDeviceState.setText(deviceState);
+ }
break;
case STREAMING:
+
+ if (timer!=null){
+ timer.cancel();
+ timer = new Timer();
+ } else {
+ timer = new Timer();
+ }
+ // Schedule a task to be executed after a delay of 2 seconds
+ timer.schedule(new PRRTask(), 0 , 2000);
+
+
deviceState="Streaming";
textViewDeviceName.setText(mBluetoothAddress);
textViewDeviceState.setText(deviceState);
@@ -279,12 +322,27 @@ else if(shimmerService.isEXGUsingTestSignal16Configuration(mBluetoothAddress))
textViewDeviceState.setText(deviceState);
//TODO: set the enable logging regarding the user selection
break;
+ case STREAMING_LOGGED_DATA:
+ deviceState="Data Sync";
+ textViewDeviceName.setText(mBluetoothAddress);
+ textViewDeviceState.setText(deviceState);
+ break;
case DISCONNECTED:
Log.d(LOG_TAG,"Shimmer No State");
mBluetoothAddress=null;
deviceState = "Disconnected";
textViewDeviceName.setText("Unknown");
textViewDeviceState.setText(deviceState);
+ if (timer!=null) {
+ timer.cancel();
+ timer = null;
+ }
+ break;
+ case CONFIGURING:
+ break;
+ case CONNECTION_LOST:
+ break;
+ case CONNECTION_FAILED:
break;
}
@@ -324,4 +382,11 @@ public void clearPlot() {
mPlotDataMap.clear();
dynamicPlot.clear();
}
+
+ public void setSelectedDeviceAddress(String address){
+ selectedDeviceAddress = address;
+ textViewDeviceName.setText(address);
+ textViewDeviceState.setText("Connected");
+ }
+
}
diff --git a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/supportfragments/SensorsEnabledFragment.java b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/supportfragments/SensorsEnabledFragment.java
index 49757cd8..c6739ffc 100644
--- a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/supportfragments/SensorsEnabledFragment.java
+++ b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/supportfragments/SensorsEnabledFragment.java
@@ -3,7 +3,7 @@
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
-import android.support.v4.app.ListFragment;
+import androidx.fragment.app.ListFragment;
import android.util.Log;
import android.view.View;
import android.widget.AbsListView;
@@ -18,12 +18,14 @@
import com.shimmerresearch.android.Shimmer4Android;
import com.shimmerresearch.android.manager.ShimmerBluetoothManagerAndroid;
import com.shimmerresearch.android.shimmerService.ShimmerService;
+import com.shimmerresearch.androidradiodriver.Shimmer3BLEAndroid;
import com.shimmerresearch.driver.Configuration;
import com.shimmerresearch.driver.ShimmerDevice;
import com.shimmerresearch.driverUtilities.AssembleShimmerConfig;
import com.shimmerresearch.driverUtilities.SensorDetails;
import com.shimmerresearch.driverUtilities.SensorGroupingDetails;
import com.shimmerresearch.driverUtilities.ShimmerVerObject;
+import com.shimmerresearch.verisense.VerisenseDevice;
import java.util.ArrayList;
import java.util.List;
@@ -164,7 +166,7 @@ public void onClick(View v) {
//TODO: Change this when AssembleShimmerConfig has been updated:
AssembleShimmerConfig.generateMultipleShimmerConfig(cloneList, Configuration.COMMUNICATION_TYPE.BLUETOOTH);
- if (shimmerDevice instanceof Shimmer) {
+ if (shimmerDevice instanceof Shimmer || shimmerDevice instanceof VerisenseDevice || shimmerDevice instanceof Shimmer3BLEAndroid) {
//((Shimmer)device).writeConfigBytes(shimmerDeviceClone.getShimmerInfoMemBytes());
/*try {
Thread.sleep(1000);
diff --git a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/supportfragments/SignalsToPlotFragment.java b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/supportfragments/SignalsToPlotFragment.java
index 77f12060..5df6cc19 100644
--- a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/supportfragments/SignalsToPlotFragment.java
+++ b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/guiUtilities/supportfragments/SignalsToPlotFragment.java
@@ -3,10 +3,12 @@
import android.content.Context;
import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.ListFragment;
+
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.ListFragment;
import android.util.Log;
+import android.util.SparseBooleanArray;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
@@ -141,6 +143,23 @@ public void buildSignalsToPlotList(Context context, final ShimmerService service
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
updateCheckboxes();
+ shimmerService.mPlotManager.removeAllSignals();
+
+ SparseBooleanArray pos = listView.getCheckedItemPositions();
+ for (int i = 0; i < listView.getCount(); i++) {
+ if (pos.get(i)) {
+ try {
+ if(dynamicPlot == null) {
+ Log.e(LOG_TAG, "dynamicPlot is null!");
+ }
+ shimmerService.mPlotManager.addSignal(mList.get(i), dynamicPlot);
+ } catch (Exception e) {
+ Log.e(LOG_TAG, "Error! Could not add signal: " + e);
+ e.printStackTrace();
+ }
+ }
+ }
+
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
@@ -196,9 +215,8 @@ public static String joinStrings(String[] a){
public void setDeviceNotStreamingView() {
String[] notStreamingMsg = new String[]{"Device not streaming", "Signals to plot can only be displayed when device is streaming"};
- ArrayAdapter adapter = new ArrayAdapter(context, android.R.layout.simple_list_item_1, notStreamingMsg);
+ ArrayAdapter adapter = new ArrayAdapter(getActivity(), android.R.layout.simple_list_item_1, notStreamingMsg);
setListAdapter(adapter);
}
-
}
diff --git a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/manager/ShimmerBluetoothManagerAndroid.java b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/manager/ShimmerBluetoothManagerAndroid.java
index 71131238..35630142 100644
--- a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/manager/ShimmerBluetoothManagerAndroid.java
+++ b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/manager/ShimmerBluetoothManagerAndroid.java
@@ -4,6 +4,11 @@
import android.app.ProgressDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.le.BluetoothLeScanner;
+import android.bluetooth.le.ScanCallback;
+import android.bluetooth.le.ScanFilter;
+import android.bluetooth.le.ScanResult;
+import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.os.Handler;
import android.util.Log;
@@ -11,6 +16,10 @@
import com.shimmerresearch.android.Shimmer;
import com.shimmerresearch.android.Shimmer4Android;
+import com.shimmerresearch.android.VerisenseDeviceAndroid;
+import com.shimmerresearch.android.protocol.VerisenseProtocolByteCommunicationAndroid;
+import com.shimmerresearch.androidradiodriver.VerisenseBleAndroidRadioByteCommunication;
+import com.shimmerresearch.androidradiodriver.Shimmer3BLEAndroid;
import com.shimmerresearch.androidradiodriver.ShimmerRadioInitializerAndroid;
import com.shimmerresearch.androidradiodriver.ShimmerSerialPortAndroid;
import com.shimmerresearch.bluetooth.ShimmerBluetooth;
@@ -35,8 +44,10 @@
import com.shimmerresearch.exceptions.ConnectionExceptionListener;
import com.shimmerresearch.exceptions.ShimmerException;
import com.shimmerresearch.managers.bluetoothManager.ShimmerBluetoothManager;
+import com.shimmerresearch.verisense.communication.VerisenseProtocolByteCommunication;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
@@ -53,11 +64,19 @@ public class ShimmerBluetoothManagerAndroid extends ShimmerBluetoothManager {
private static final String TAG = ShimmerBluetoothManagerAndroid.class.getSimpleName();
private static final String DEFAULT_SHIMMER_NAME = "ShimmerDevice";
+ static final String VERISENSE_NAME_NO_PAIRING_REQUIRED = "Verisense-00";
+
+
BluetoothAdapter mBluetoothAdapter;
Context mContext;
protected Handler mHandler;
private boolean AllowAutoPairing = true;
+ public enum BT_TYPE{
+ BT_CLASSIC,
+ BLE
+ }
+
public ShimmerBluetoothManagerAndroid(Context context, Handler handler) throws Exception {
super();
ShimmerRadioInitializer.useLegacyDelayBeforeBtRead(true);
@@ -92,6 +111,13 @@ public void enablePairingOnConnect(boolean enable){
AllowAutoPairing = enable;
}
+ public boolean checkIfDeviceRequiresPairing(String deviceName){
+ if(deviceName.contains(VERISENSE_NAME_NO_PAIRING_REQUIRED)){
+ return false;
+ }
+ return true;
+ }
+
/**
* See also {@link #connectShimmerThroughBTAddress(String)}.
* @param bluetoothAddress in the form of XX:XX:XX:XX:XX:XX
@@ -99,10 +125,10 @@ public void enablePairingOnConnect(boolean enable){
* @exception IllegalArgumentException if bluetoothAddress is invalid, note this will only occur when {@link #enablePairingOnConnect(boolean)} is enabled
* @exception DeviceNotPairedException if the device is not paired
*/
- public void connectShimmerThroughBTAddress(final String bluetoothAddress,Context context) {
+ public void connectShimmerThroughBTAddress(final String bluetoothAddress, final String deviceName, Context context) {
if(isDevicePaired(bluetoothAddress) || AllowAutoPairing) {
- if (!isDevicePaired(bluetoothAddress)){
+ if (!isDevicePaired(bluetoothAddress) && checkIfDeviceRequiresPairing(deviceName)){
if (context!=null) {
//Toast.makeText(mContext, "Attempting to pair device, please wait...", Toast.LENGTH_LONG).show();
final ProgressDialog progress = new ProgressDialog(context);
@@ -116,7 +142,9 @@ public void connectShimmerThroughBTAddress(final String bluetoothAddress,Context
}
}
addDiscoveredDevice(bluetoothAddress);
- super.connectShimmerThroughBTAddress(bluetoothAddress);
+ //super.connectShimmerThroughBTAddress(bluetoothAddress);
+ BluetoothDeviceDetails bdd = new BluetoothDeviceDetails("",bluetoothAddress,deviceName);
+ super.connectShimmerThroughBTAddress(bdd);
super.setConnectionExceptionListener(new ConnectionExceptionListener() {
@Override
public void onConnectionStart(String connectionHandle) {
@@ -157,8 +185,126 @@ public void onConnectStartException(String connectionHandle) {
* @exception DeviceNotPairedException if the device is not paired
*/
@Override
+ public void connectVerisenseDevice(BluetoothDeviceDetails bdd) {
+ VerisenseBleAndroidRadioByteCommunication radio1 = new VerisenseBleAndroidRadioByteCommunication(bdd.mShimmerMacId);
+ VerisenseProtocolByteCommunicationAndroid protocol1 = new VerisenseProtocolByteCommunicationAndroid(radio1);
+ final VerisenseDeviceAndroid verisenseDevice = new VerisenseDeviceAndroid(mHandler);
+ verisenseDevice.setMacIdFromUart(bdd.mShimmerMacId);
+ verisenseDevice.setProtocol(Configuration.COMMUNICATION_TYPE.BLUETOOTH, protocol1);
+ initializeNewShimmerCommon(verisenseDevice);
+ Thread thread = new Thread(){
+ public void run(){
+
+ try {
+ verisenseDevice.connect();
+ } catch (ShimmerException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ };
+ thread.start();
+ }
+
+ public void connectShimmerThroughBTAddress(final String bluetoothAddress, BT_TYPE btType) {
+ if(btType.equals(BT_TYPE.BT_CLASSIC)){
+ connectShimmerThroughBTAddress(bluetoothAddress);
+ }else{
+ connectShimmer3BLEThroughBTAddress(bluetoothAddress,"",null);
+ }
+ }
+ @Override
public void connectShimmerThroughBTAddress(final String bluetoothAddress) {
- connectShimmerThroughBTAddress(bluetoothAddress,null);
+
+ //scanLeDevice(bluetoothAddress);
+ //doDiscovery();
+ connectShimmerThroughBTAddress(bluetoothAddress,"",null);
+ }
+
+ public void connectShimmer3BLEThroughBTAddress(final String bluetoothAddress, final String deviceName, Context context){
+ final Shimmer3BLEAndroid shimmer3BLE = new Shimmer3BLEAndroid(bluetoothAddress, mHandler);
+ shimmer3BLE.setMacIdFromUart(bluetoothAddress);
+ initializeNewShimmerCommon(shimmer3BLE);
+ Thread thread = new Thread(){
+ public void run(){
+ shimmer3BLE.connect(bluetoothAddress, "default");
+ }
+ };
+ thread.start();
+ }
+
+ //BT Classic Scan
+ private void doDiscovery() {
+
+ // If we're already discovering, stop it
+ if (mBluetoothAdapter.isDiscovering()) {
+ mBluetoothAdapter.cancelDiscovery();
+ }
+
+ // Request discover from BluetoothAdapter
+ mBluetoothAdapter.startDiscovery();
+ }
+
+ private BluetoothLeScanner bluetoothLeScanner;
+ private boolean scanning;
+ private Handler handler = new Handler();
+ // Stops scanning after 10 seconds.
+ private static final long SCAN_PERIOD = 10000;
+ List listScanBleDevice = new ArrayList();
+
+ //BLE Scan
+ private void scanLeDevice(String deviceMacAddress) {
+ getScannedBleDevices();
+ bluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();
+ if (!scanning) {
+ // Stops scanning after a predefined scan period.
+ handler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ scanning = false;
+ bluetoothLeScanner.stopScan(leScanCallback);
+ }
+ }, SCAN_PERIOD);
+
+ scanning = true;
+ scanForAllBleDevices();
+ //scanForSpecificBleDevices(deviceMacAddress);
+
+ } else {
+ scanning = false;
+ bluetoothLeScanner.stopScan(leScanCallback);
+ }
+ }
+ private void scanForAllBleDevices() {
+ bluetoothLeScanner.startScan(leScanCallback);
+ }
+ private void scanForSpecificBleDevices(String deviceMacAddress) {
+ List scanFilters = new ArrayList<>();
+ ScanFilter filter = new ScanFilter.Builder().setDeviceAddress(deviceMacAddress).build();
+ scanFilters.add(filter);
+ ScanSettings scanSettings = new ScanSettings.Builder().build();
+ bluetoothLeScanner.startScan(scanFilters, scanSettings, leScanCallback);
+ }
+
+ // Device scan callback.
+ private ScanCallback leScanCallback =
+ new ScanCallback() {
+ @Override
+ public void onScanResult(int callbackType, ScanResult result) {
+ super.onScanResult(callbackType, result);
+ BluetoothDevice bledevice = result.getDevice();
+ if(!listScanBleDevice.contains(result.getDevice())){
+ listScanBleDevice.add(result.getDevice());
+ }
+ }
+ };
+
+ private void getScannedBleDevices(){
+ for(BluetoothDevice dev : listScanBleDevice)
+ {
+ System.out.println(dev.getAddress());
+ }
+
}
/**
@@ -245,7 +391,7 @@ protected ShimmerDevice createNewShimmer3(ShimmerRadioInitializer shimmerRadioIn
mProgressDialog.dismiss();
}
ShimmerSerialPortAndroid serialPort = (ShimmerSerialPortAndroid) shimmerRadioInitializer.getSerialCommPort();
- Shimmer shimmer = new Shimmer(mHandler);
+ Shimmer shimmer = new Shimmer(mHandler, mContext);
shimmer.setDelayForBtRespone(true);
mMapOfBtConnectedShimmers.put(bluetoothAddress, shimmer);
try {
@@ -276,6 +422,18 @@ protected ShimmerDevice initializeShimmer3(AbstractSerialPortHal abstractSerialP
return shimmerDevice;
}
+ @Override
+ public void configureShimmer(final ShimmerDevice shimmerClone) {
+ Thread thread = new Thread(){
+ public void run(){
+ configureShimmers(Arrays.asList(shimmerClone));
+ }
+ };
+
+ thread.start();
+
+ }
+
@Override
protected Shimmer4sdk createNewShimmer4(String comport, String bluetoothAddress) {
if(mProgressDialog!=null){
@@ -317,7 +475,10 @@ private void connectExistingShimmer4(Shimmer4Android shimmer4, String btAddress)
}
}
-
+ @Override
+ protected BluetoothDeviceDetails getBluetoothDeviceDetails(String connectionHandle) {
+ return (BluetoothDeviceDetails)this.mMapOfParsedBtComPorts.get(connectionHandle);
+ }
private void addDiscoveredDevice(String bluetoothAddress){
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(bluetoothAddress);
diff --git a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/protocol/VerisenseProtocolByteCommunicationAndroid.java b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/protocol/VerisenseProtocolByteCommunicationAndroid.java
new file mode 100644
index 00000000..c0dafd97
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/protocol/VerisenseProtocolByteCommunicationAndroid.java
@@ -0,0 +1,142 @@
+package com.shimmerresearch.android.protocol;
+
+import android.content.Context;
+import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+
+import androidx.documentfile.provider.DocumentFile;
+
+import com.shimmerresearch.exceptions.ShimmerException;
+import com.shimmerresearch.tools.FileUtils;
+import com.shimmerresearch.verisense.communication.AbstractByteCommunication;
+import com.shimmerresearch.verisense.communication.VerisenseMessage;
+import com.shimmerresearch.verisense.communication.VerisenseProtocolByteCommunication;
+
+import java.io.BufferedWriter;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class VerisenseProtocolByteCommunicationAndroid extends VerisenseProtocolByteCommunication {
+
+ protected Context mContext;
+ protected Uri mTreeURI;
+
+ public VerisenseProtocolByteCommunicationAndroid(AbstractByteCommunication byteComm) {
+ super(byteComm);
+ }
+
+ public void enableWriteToBinFile(Context context, Uri treeUri){
+ mContext = context;
+ mTreeURI = treeUri;
+ }
+
+ @Override
+ protected void createBinFile(VerisenseMessage verisenseMessage, boolean crcError) {
+ System.out.println();
+ try {
+
+ String pIndex = String.format("%05d", verisenseMessage.payloadIndex);
+ if (crcError) {
+ dataFileName = String.format("%s_%s_%s.bin", new SimpleDateFormat("yyMMdd_HHmmss").format(new Date()), pIndex, BadCRC);
+ } else {
+ dataFileName = String.format("%s_%s.bin", new SimpleDateFormat("yyMMdd_HHmmss").format(new Date()), pIndex);
+ }
+
+ // AdvanceLog(LogObject, "BinFileCreated", dataFilePath, ASMName);
+ } catch (Exception ex) {
+ // AdvanceLog(LogObject, "BinFileCreatedException", ex, ASMName);
+ }
+
+ }
+
+ @Override
+ public void readLoggedData() throws ShimmerException {
+ if (mContext==null || mTreeURI ==null){
+ throw new ShimmerException("Context and Uri needs to be set");
+ }
+ super.readLoggedData();
+ }
+
+ protected void WritePayloadToBinFile(VerisenseMessage verisenseMessage) {
+
+ if (PreviouslyWrittenPayloadIndex != verisenseMessage.payloadIndex) {
+ try {
+ DocumentFile pickedDir = DocumentFile.fromTreeUri(mContext, mTreeURI);
+ DocumentFile[] arrDF = pickedDir.listFiles();
+ for (DocumentFile file:arrDF) {
+ System.out.println(file.getName());
+ }
+ //trial name
+ DocumentFile dfT = pickedDir.findFile(getTrialName());
+ if (dfT==null){
+ dfT = pickedDir.createDirectory(getTrialName());
+ }
+
+ //participant name
+ DocumentFile dfP = dfT.findFile(getParticipantID());
+ if(dfP==null) {
+ dfP = dfT.createDirectory(getParticipantID());
+ }
+
+ //uuid
+ DocumentFile dfUUID = dfP.findFile(mByteCommunication.getUuid());
+ if(dfUUID==null) {
+ dfUUID = dfP.createDirectory(mByteCommunication.getUuid());
+ }
+
+ //BinaryFiles
+ DocumentFile dfBF = dfUUID.findFile("BinaryFiles");
+ if(dfBF==null) {
+ dfBF = dfUUID.createDirectory("BinaryFiles");
+ }
+
+ DocumentFile newFile = dfBF.findFile(dataFileName);
+ if (newFile == null) {
+ newFile = dfBF.createFile("application/bin", dataFileName);
+ dataFilePath = new FileUtils(mContext).getPath(newFile.getUri(), FileUtils.UriType.FILE);
+ }
+ if (newFile != null) {
+ ParcelFileDescriptor pfd = mContext.getContentResolver().openFileDescriptor(newFile.getUri(), "wa"); // "w" for write, "a" for append
+ FileOutputStream fos = new FileOutputStream(pfd.getFileDescriptor());
+ fos.write(verisenseMessage.payloadBytes);
+ fos.flush();
+ fos.close();
+ }
+
+ /*
+ // System.Console.WriteLine("Write Payload To Bin File!");
+ File f = new File(dataFilePath);
+ if (!f.exists()) {
+ f.createNewFile();
+ }
+ Files.write(Paths.get(dataFilePath), verisenseMessage.payloadBytes, StandardOpenOption.APPEND);
+ */
+ if (verisenseMessage.mCRCErrorPayload) {
+ //SaveBinFileToDB();
+ } else {
+ // only assume non crc error payload index is valid
+ PreviouslyWrittenPayloadIndex = verisenseMessage.payloadIndex;
+ }
+ // DataBufferToBeSaved = null;
+ // RealmService.UpdateSensorDataSyncDate(Asm_uuid.ToString());
+ // UpdateSensorDataSyncDate();
+
+
+ } catch (Exception ex) {
+ // AdvanceLog(LogObject, "FileAppendException", ex, ASMName);
+ // throw ex;
+ System.out.println(ex.toString());
+ }
+ } else {
+ // AdvanceLog(LogObject, "WritePayloadToBinFile", "Same Payload Index = " +
+ // PayloadIndex.ToString(), ASMName);
+ }
+
+ }
+
+
+}
diff --git a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/shimmerService/ShimmerService.java b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/shimmerService/ShimmerService.java
index 3992a6df..0984e512 100644
--- a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/shimmerService/ShimmerService.java
+++ b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/android/shimmerService/ShimmerService.java
@@ -41,9 +41,11 @@
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.media.MediaScannerConnection;
+import android.net.Uri;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
@@ -63,10 +65,14 @@
import com.shimmerresearch.driver.FormatCluster;
import com.shimmerresearch.driver.ObjectCluster;
import com.shimmerresearch.driver.ShimmerDevice;
+import com.shimmerresearch.driverUtilities.BluetoothDeviceDetails;
import com.shimmerresearch.driverUtilities.ChannelDetails.CHANNEL_TYPE;
+import com.shimmerresearch.exceptions.ShimmerException;
import com.shimmerresearch.tools.Logging;
import com.shimmerresearch.tools.PlotManagerAndroid;
+import com.shimmerresearch.verisense.VerisenseDevice;
+import java.net.URI;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
@@ -90,6 +96,10 @@ public class ShimmerService extends Service {
protected Handler mHandlerGraph=null;
private boolean mGraphing=false;
public String mLogFileName="Default";
+
+ public Uri mFileURI= null;
+ public ContentResolver mResolver = null;
+ public Context mContext = null;
Filter mFilter;
Filter mLPFilterECG;
Filter mHPFilterECG;
@@ -245,7 +255,29 @@ public boolean isECGtoHREnabled(){
}
public void connectShimmer(final String bluetoothAddress,Context context){
- btManager.connectShimmerThroughBTAddress(bluetoothAddress,context);
+ btManager.connectShimmerThroughBTAddress(bluetoothAddress,"",context);
+ }
+
+ public void connectShimmer(final String bluetoothAddress,final String deviceName, Context context){
+ btManager.connectShimmerThroughBTAddress(bluetoothAddress,deviceName,context);
+ }
+
+ public void connectShimmer(final String bluetoothAddress,final String deviceName, ShimmerBluetoothManagerAndroid.BT_TYPE preferredBtType, Context context){
+ boolean isVerisense = false;
+ if (deviceName!=null){
+ if (deviceName.contains(VerisenseDevice.VERISENSE_PREFIX)) {
+ isVerisense = true;
+ }
+ }
+
+ if (isVerisense){
+ btManager.connectVerisenseDevice(new BluetoothDeviceDetails("",bluetoothAddress,deviceName));
+ } else {
+ btManager.connectShimmerThroughBTAddress(bluetoothAddress, preferredBtType); //Connect to the selected device
+ }
+
+
+
}
public void connectShimmer(final String bluetoothAddress){
@@ -427,9 +459,17 @@ public void handleMsgDataPacket(Message msg) {
char[] bA=objectCluster.getMacAddress().toCharArray();
Logging shimmerLog;
if (mLogFileName.equals("Default")){
- shimmerLog=new Logging(fromMilisecToDate(System.currentTimeMillis()) + " Device" + bA[12] + bA[13] + bA[15] + bA[16],"\t", mLogFolderName, mLoggingFileType);
+ if(mFileURI==null) {
+ shimmerLog = new Logging(fromMilisecToDate(System.currentTimeMillis()) + " Device" + bA[12] + bA[13] + bA[15] + bA[16], "\t", mLogFolderName, mLoggingFileType);
+ } else {
+ shimmerLog = new Logging(mFileURI,mContext,fromMilisecToDate(System.currentTimeMillis()) + " Device" + bA[12] + bA[13] + bA[15] + bA[16], "\t", mLogFolderName, mLoggingFileType);
+ }
} else {
- shimmerLog=new Logging(fromMilisecToDate(System.currentTimeMillis()) + mLogFileName,"\t", mLogFolderName, mLoggingFileType);
+ if(mFileURI==null) {
+ shimmerLog = new Logging(fromMilisecToDate(System.currentTimeMillis()) + mLogFileName, "\t", mLogFolderName, mLoggingFileType);
+ }else {
+ shimmerLog = new Logging(mFileURI,mContext,fromMilisecToDate(System.currentTimeMillis()) + mLogFileName, "\t", mLogFolderName, mLoggingFileType);
+ }
}
mLogShimmer.remove(objectCluster.getMacAddress());
if (mLogShimmer.get(objectCluster.getMacAddress())==null){
@@ -513,6 +553,7 @@ public void handleMsgStateChange(Message msg) {
sendBroadcast(intent);
break;
case DISCONNECTED:
+ btManager.removeShimmerDeviceBtConnected(macAddress);
intent.putExtra("ShimmerBluetoothAddress", macAddress );
intent.putExtra("ShimmerDeviceName", shimmerName );
intent.putExtra("ShimmerState",BT_STATE.DISCONNECTED);
@@ -915,8 +956,8 @@ public void startStreaming(String bluetoothAddress) {
}
*/
- public void startStreaming(String bluetoothAddress) {
- btManager.startStreaming(bluetoothAddress);
+ public void startStreaming(String bluetoothAddress) throws Exception{
+ btManager.startStreaming(bluetoothAddress);
}
/**
@@ -1008,8 +1049,8 @@ public void stopStreaming(String bluetoothAddress) {
}
*/
- public void stopStreaming(String bluetoothAddress) {
- btManager.stopStreaming(bluetoothAddress);
+ public void stopStreaming(String bluetoothAddress) throws Exception{
+ btManager.stopStreaming(bluetoothAddress);
}
/**
@@ -1130,7 +1171,12 @@ public void setLoggingName(String name){
public void closeAndRemoveFile(String bluetoothAddress){
if (mLogShimmer.get(bluetoothAddress)!=null){
mLogShimmer.get(bluetoothAddress).closeFile();
- MediaScannerConnection.scanFile(this, new String[] { mLogShimmer.get(bluetoothAddress).getAbsoluteName() }, null, null);
+
+ try {
+ MediaScannerConnection.scanFile(this, new String[] { mLogShimmer.get(bluetoothAddress).getAbsoluteName() }, null, null);
+ } catch (Exception e) {
+ System.out.println(e);
+ }
mLogShimmer.remove(bluetoothAddress);
}
diff --git a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/androidradiodriver/Shimmer3BLEAndroid.java b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/androidradiodriver/Shimmer3BLEAndroid.java
new file mode 100644
index 00000000..2785d85d
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/androidradiodriver/Shimmer3BLEAndroid.java
@@ -0,0 +1,602 @@
+package com.shimmerresearch.androidradiodriver;
+
+import static com.shimmerresearch.android.Shimmer.MESSAGE_TOAST;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothGatt;
+import android.bluetooth.BluetoothGattCharacteristic;
+import android.bluetooth.BluetoothGattService;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+
+import com.clj.fastble.BleManager;
+import com.clj.fastble.callback.BleGattCallback;
+import com.clj.fastble.callback.BleMtuChangedCallback;
+import com.clj.fastble.callback.BleNotifyCallback;
+import com.clj.fastble.callback.BleWriteCallback;
+import com.clj.fastble.data.BleDevice;
+import com.clj.fastble.exception.BleException;
+import com.shimmerresearch.android.Shimmer;
+import com.shimmerresearch.bluetooth.BluetoothProgressReportPerCmd;
+import com.shimmerresearch.bluetooth.ShimmerBluetooth;
+import com.shimmerresearch.driver.BasicProcessWithCallBack;
+import com.shimmerresearch.driver.CallbackObject;
+import com.shimmerresearch.driver.Configuration;
+import com.shimmerresearch.driver.FormatCluster;
+import com.shimmerresearch.driver.ObjectCluster;
+import com.shimmerresearch.driver.ShimmerDevice;
+import com.shimmerresearch.driver.ShimmerDeviceCallbackAdapter;
+import com.shimmerresearch.driver.ShimmerMsg;
+import com.shimmerresearch.driver.ThreadSafeByteFifoBuffer;
+import com.shimmerresearch.driver.shimmer2r3.ConfigByteLayoutShimmer3;
+import com.shimmerresearch.driverUtilities.ChannelDetails;
+import com.shimmerresearch.driverUtilities.SensorDetails;
+import com.shimmerresearch.driverUtilities.UtilShimmer;
+import com.shimmerresearch.exceptions.ShimmerException;
+import com.shimmerresearch.sensors.kionix.SensorKionixAccel;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+import bolts.TaskCompletionSource;
+
+public class Shimmer3BLEAndroid extends ShimmerBluetooth implements Serializable {
+ transient BleDevice mBleDevice;
+ String TxID = "49535343-8841-43f4-a8d4-ecbe34729bb3";
+ String RxID = "49535343-1e4d-4bd9-ba61-23c647249616";
+ String ServiceID = "49535343-fe7d-4ae5-8fa9-9fafd205e455";
+ UUID sid = UUID.fromString(ServiceID);
+ UUID txid = UUID.fromString(TxID);
+ UUID rxid = UUID.fromString(RxID);
+ String mMac;
+ String uuid;
+ transient ThreadSafeByteFifoBuffer mBuffer;
+ protected transient ShimmerDeviceCallbackAdapter mDeviceCallbackAdapter = new ShimmerDeviceCallbackAdapter(this);
+ transient public final Handler mHandler;
+ public static final String TOAST = "toast";
+
+ //"DA:A6:19:F0:4A:D7"
+ //"E7:45:2C:6D:6F:14"
+
+ /**
+ * Initialize a ble radio
+ *
+ * @param mac mac address of the Shimmer3 BLE device e.g. d0:2b:46:3d:a2:bb
+ */
+ public Shimmer3BLEAndroid(String mac) {
+ mMac = mac;
+ mHandler = null;
+ }
+
+ public Shimmer3BLEAndroid(String mac, Handler handler){
+ mMac = mac;
+ mHandler = handler;
+ }
+ transient TaskCompletionSource mTaskConnect = new TaskCompletionSource<>();
+ transient TaskCompletionSource mTaskMTU = new TaskCompletionSource<>();
+
+ @Override
+ public void sendCallBackMsg(int msgid,Object obj){
+ if (mHandler != null) {
+ mHandler.obtainMessage(msgid, obj).sendToTarget();
+ }
+ }
+ /**
+ * Connect to the Shimmer3 BLE device
+ */
+ @Override
+ public void connect(String s, String s1) {
+ mTaskConnect = new TaskCompletionSource<>();
+ BleManager.getInstance().connect(mMac, new BleGattCallback() {
+ @Override
+ public void onStartConnect() {
+ System.out.println("Connecting");
+ }
+
+ @Override
+ public void onConnectFail(BleDevice bleDevice, BleException exception) {
+
+ }
+
+ @Override
+ public void onConnectSuccess(BleDevice bleDevice, BluetoothGatt gatt, int status) {
+ mBuffer = new ThreadSafeByteFifoBuffer(1000000);
+ mTaskMTU = new TaskCompletionSource<>();
+ BleManager.getInstance().setMtu(bleDevice, 251, new BleMtuChangedCallback() {
+ @Override
+ public void onSetMTUFailure(BleException exception) {
+ System.out.println("MTU Failure");
+
+ }
+
+ @Override
+ public void onMtuChanged(int mtu) {
+ System.out.println("MTU Changed: " + mtu);
+ mTaskMTU.setResult("MTU Changed: " + mtu);
+ }
+ });
+
+ try {
+ boolean result = mTaskMTU.getTask().waitForCompletion(3, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ gatt.requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_HIGH);
+ }
+
+ mBleDevice = bleDevice;
+ startServiceS(bleDevice);
+ System.out.println(bleDevice.getMac() + " Connected");
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ gatt.setPreferredPhy(BluetoothDevice.PHY_LE_2M_MASK, BluetoothDevice.PHY_LE_2M_MASK, BluetoothDevice.PHY_OPTION_NO_PREFERRED);
+ }
+ mTaskConnect.setResult("Connected");
+ //mHandler.obtainMessage(ShimmerBluetooth.MSG_IDENTIFIER_STATE_CHANGE, -1, -1,
+ //new ObjectCluster("", bleDevice.getMac(), BT_STATE.CONNECTED)).sendToTarget();
+ sendCallBackMsg(ShimmerBluetooth.MSG_IDENTIFIER_STATE_CHANGE, new ObjectCluster("", bleDevice.getMac(), BT_STATE.CONNECTED));
+ Bundle bundle = new Bundle();
+ bundle.putString(TOAST, "Device connection established");
+ sendMsgToHandlerList(MESSAGE_TOAST, bundle);
+
+ mIOThread = new IOThread();
+ mIOThread.start();
+ if (mUseProcessingThread){
+ mPThread = new ProcessingThread();
+ mPThread.start();
+ }
+
+ initialize();
+ }
+
+ @Override
+ public void onDisConnected(boolean isActiveDisConnected, BleDevice bleDevice, BluetoothGatt gatt, int status) {
+ //mHandler.obtainMessage(ShimmerBluetooth.MSG_IDENTIFIER_STATE_CHANGE, -1, -1,
+ //new ObjectCluster("", bleDevice.getMac(), BT_STATE.DISCONNECTED)).sendToTarget();
+ sendCallBackMsg(ShimmerBluetooth.MSG_IDENTIFIER_STATE_CHANGE, new ObjectCluster("", bleDevice.getMac(), BT_STATE.DISCONNECTED));
+
+ Bundle bundle = new Bundle();
+ bundle.putString(TOAST, "Device connection was lost");
+ sendMsgToHandlerList(MESSAGE_TOAST, bundle);
+ System.out.println();
+ }
+ });
+
+
+ try {
+ boolean result = mTaskConnect.getTask().waitForCompletion(10, TimeUnit.SECONDS);
+ Thread.sleep(200);
+ if (!result) {
+ System.out.println("Connect fail");
+ }
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void startServiceS(BleDevice bleDevice) {
+ List services = BleManager.getInstance().getBluetoothGattServices(bleDevice);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+
+
+ for (BluetoothGattService service : services) {
+ System.out.println(service.getUuid());
+ if (service.getUuid().compareTo(sid) == 0) {
+ for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()) {
+ if (characteristic.getUuid().compareTo(txid) == 0) {
+ //newConnectedBLEDevice(bleDevice,characteristic);
+ CharSequence text = "TXID!";
+ } else if (characteristic.getUuid().compareTo(rxid) == 0) {
+ newConnectedBLEDevice(bleDevice, characteristic);
+ CharSequence text = "RxID!";
+ }
+ }
+ }
+ }
+
+
+ }
+ }
+
+ /**
+ * Start notify for characteristics changed
+ *
+ * @param bleDevice BLE device
+ * @param characteristic
+ */
+ public void newConnectedBLEDevice(final BleDevice bleDevice, final BluetoothGattCharacteristic characteristic) {
+ int count = 1;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ BleManager.getInstance().notify(
+ bleDevice,
+ characteristic.getService().getUuid().toString(),
+ characteristic.getUuid().toString(),
+ new BleNotifyCallback() {
+
+
+ @Override
+ public void onNotifySuccess() {
+
+ }
+
+ @Override
+ public void onNotifyFailure(BleException exception) {
+
+ }
+
+ @Override
+ public void onCharacteristicChanged(byte[] data) {
+ try {
+ mBuffer.write(data);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ });
+ }
+ }
+
+ @Override
+ protected boolean bytesAvailableToBeRead() {
+ if (mBuffer.size()>0) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ protected int availableBytes() {
+ return mBuffer.size();
+ }
+
+ @Override
+ public void writeBytes(byte[] bytes) {
+ BleManager.getInstance().write(mBleDevice, sid.toString(), txid.toString(), bytes, false, new BleWriteCallback() {
+ @Override
+ public void onWriteSuccess(int current, int total, byte[] justWrite) {
+ System.out.println("Write Success " + UtilShimmer.bytesToHexStringWithSpacesFormatted(justWrite));
+ }
+
+ @Override
+ public void onWriteFailure(BleException exception) {
+ System.out.println("Write Fail");
+ }
+ });
+ }
+
+ @Override
+ protected void stop() {
+ try {
+ disconnect();
+ } catch (ShimmerException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ protected void sendProgressReport(BluetoothProgressReportPerCmd bluetoothProgressReportPerCmd) {
+ mDeviceCallbackAdapter.sendProgressReport(bluetoothProgressReportPerCmd);
+ }
+
+ @Override
+ protected void isReadyForStreaming() {
+ mDeviceCallbackAdapter.isReadyForStreaming();
+ restartTimersIfNull();
+ }
+
+ @Override
+ protected void isNowStreaming() {
+ mDeviceCallbackAdapter.isNowStreaming();
+ }
+
+ @Override
+ protected void hasStopStreaming() {
+ mDeviceCallbackAdapter.hasStopStreaming();
+ }
+
+ @Override
+ protected void sendStatusMsgPacketLossDetected() {
+
+ }
+
+ @Override
+ protected void inquiryDone() {
+ mDeviceCallbackAdapter.inquiryDone();
+ isReadyForStreaming();
+ }
+
+ @Override
+ protected void sendStatusMSGtoUI(String s) {
+
+ }
+
+ @Override
+ protected void printLogDataForDebugging(String s) {
+ consolePrintLn(s);
+ }
+
+ @Override
+ protected void connectionLost() {
+ try {
+ disconnect();
+ } catch (ShimmerException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ setBluetoothRadioState(BT_STATE.CONNECTION_LOST);
+ }
+
+ @Override
+ public boolean setBluetoothRadioState(BT_STATE state) {
+ boolean isChanged = super.setBluetoothRadioState(state);
+ mDeviceCallbackAdapter.setBluetoothRadioState(state, isChanged);
+ return isChanged;
+ }
+
+ @Override
+ protected void startOperation(BT_STATE bt_state) {
+ this.startOperation(bt_state, 1);
+ consolePrintLn(bt_state + " START");
+ }
+
+ @Override
+ protected void finishOperation(BT_STATE bt_state) {
+ mDeviceCallbackAdapter.finishOperation(bt_state);
+ }
+
+ @Override
+ protected void startOperation(BT_STATE bt_state, int i) {
+ mDeviceCallbackAdapter.startOperation(bt_state, i);
+ }
+
+ @Override
+ protected void eventLogAndStreamStatusChanged(byte currentCommand) {
+ if (currentCommand == STOP_LOGGING_ONLY_COMMAND) {
+ //TODO need to query the Bluetooth connection here!
+ if (mIsStreaming) {
+ setBluetoothRadioState(BT_STATE.STREAMING);
+ } else if (isConnected()) {
+ setBluetoothRadioState(BT_STATE.CONNECTED);
+ } else {
+ setBluetoothRadioState(BT_STATE.DISCONNECTED);
+ }
+ } else {
+ if (mIsStreaming && isSDLogging()) {
+ setBluetoothRadioState(BT_STATE.STREAMING_AND_SDLOGGING);
+ } else if (mIsStreaming) {
+ setBluetoothRadioState(BT_STATE.STREAMING);
+ } else if (isSDLogging()) {
+ setBluetoothRadioState(BT_STATE.SDLOGGING);
+ } else {
+ // if(!isStreaming() && !isSDLogging() && isConnected()){
+ if (!mIsStreaming && !isSDLogging() && isConnected() && mBluetoothRadioState != BT_STATE.CONNECTED) {
+ setBluetoothRadioState(BT_STATE.CONNECTED);
+ }
+ // if(getBTState() == BT_STATE.INITIALISED){
+ //
+ // }
+ // else if(getBTState() != BT_STATE.CONNECTED){
+ // setState(BT_STATE.CONNECTED);
+ // }
+
+ CallbackObject callBackObject = new CallbackObject(NOTIFICATION_SHIMMER_STATE_CHANGE, mBluetoothRadioState, getMacId(), getComPort());
+ sendCallBackMsg(MSG_IDENTIFIER_STATE_CHANGE, callBackObject);
+ }
+ }
+ }
+
+ @Override
+ protected void batteryStatusChanged() {
+ mDeviceCallbackAdapter.batteryStatusChanged();
+ }
+
+ @Override
+ protected byte[] readBytes(int numberofBytes) {
+ try {
+ return mBuffer.read(numberofBytes);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ @Override
+ protected byte readByte() {
+ try {
+ return mBuffer.read();
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return -1;
+ }
+
+ @Override
+ protected void dockedStateChange() {
+ mDeviceCallbackAdapter.dockedStateChange();
+ }
+
+ @Override
+ public ShimmerDevice deepClone() {
+ try {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ oos.writeObject(this);
+
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ObjectInputStream ois = new ObjectInputStream(bais);
+ Object readdd = ois.readObject();
+ return (ShimmerDevice) readdd;
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ @Override
+ protected void interpretDataPacketFormat(Object o, Configuration.COMMUNICATION_TYPE communication_type) {
+
+ }
+
+ @Override
+ public void createConfigBytesLayout() {
+ mConfigByteLayout = new ConfigByteLayoutShimmer3(getFirmwareIdentifier(), getFirmwareVersionMajor(), getFirmwareVersionMinor(), getFirmwareVersionInternal());
+ }
+
+ @Override
+ protected void dataHandler(ObjectCluster objectCluster) {
+ mDeviceCallbackAdapter.dataHandler(objectCluster);
+ }
+
+ @Override
+ protected void processMsgFromCallback(ShimmerMsg shimmerMsg) {
+ System.out.println(shimmerMsg.mIdentifier);
+ }
+
+ @Override
+ public void disconnect() throws ShimmerException {
+ // super.disconnect();
+ stopAllTimers();
+ BleManager.getInstance().disconnect(mBleDevice);
+ closeConnection();
+ setBluetoothRadioState(BT_STATE.DISCONNECTED);
+ Bundle bundle = new Bundle();
+ bundle.putString(TOAST, "Device connection was lost");
+ sendMsgToHandlerList(MESSAGE_TOAST, bundle);
+ }
+ private void sendMsgToHandlerList(int obtainMessage, Bundle bundle) {
+ if (mHandler != null) {
+ Message msg = mHandler.obtainMessage(obtainMessage);
+ msg.setData(bundle);
+ mHandler.sendMessage(msg);
+ }
+
+ }
+ 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);
+ }
+ }
+
+ //Need to override here because ShimmerDevice class uses a different map
+ @Override
+ public String getSensorLabel(int sensorKey) {
+ //TODO 2017-08-03 MN: super does this but in a different way, don't know is either is better
+ super.getSensorLabel(sensorKey);
+ SensorDetails sensor = mSensorMap.get(sensorKey);
+ if (sensor != null) {
+ return sensor.mSensorDetailsRef.mGuiFriendlyLabel;
+ }
+ return null;
+ }
+
+ public class SensorDataReceived extends BasicProcessWithCallBack {
+
+ @Override
+ protected void processMsgFromCallback(ShimmerMsg shimmerMSG) {
+ // TODO Auto-generated method stub
+ System.out.println(shimmerMSG.mIdentifier);
+
+
+ // TODO Auto-generated method stub
+
+ // TODO Auto-generated method stub
+ int ind = shimmerMSG.mIdentifier;
+
+ Object object = (Object) shimmerMSG.mB;
+
+ if (ind == Shimmer.MSG_IDENTIFIER_STATE_CHANGE) {
+ CallbackObject callbackObject = (CallbackObject) object;
+
+ if (callbackObject.mState == BT_STATE.CONNECTING) {
+ } else if (callbackObject.mState == BT_STATE.CONNECTED) {
+ } else if (callbackObject.mState == BT_STATE.DISCONNECTED
+ // || callbackObject.mState == BT_STATE.NONE
+ || callbackObject.mState == BT_STATE.CONNECTION_LOST) {
+
+ }
+ } else if (ind == Shimmer.MSG_IDENTIFIER_NOTIFICATION_MESSAGE) {
+ CallbackObject callbackObject = (CallbackObject) object;
+ int msg = callbackObject.mIndicator;
+ if (msg == Shimmer.NOTIFICATION_SHIMMER_FULLY_INITIALIZED) {
+ }
+ if (msg == Shimmer.NOTIFICATION_SHIMMER_STOP_STREAMING) {
+
+ } else if (msg == Shimmer.NOTIFICATION_SHIMMER_START_STREAMING) {
+
+ } else {
+ }
+ } else if (ind == Shimmer.MSG_IDENTIFIER_DATA_PACKET) {
+
+ double accelX = 0;
+ double accelY = 0;
+ double accelZ = 0;
+ FormatCluster formatx;
+ FormatCluster formaty;
+ FormatCluster formatz;
+
+ int INVALID_RESULT = -1;
+
+ ObjectCluster objc = (ObjectCluster) shimmerMSG.mB;
+
+ Collection adcFormats = objc.getCollectionOfFormatClusters(SensorKionixAccel.ObjectClusterSensorName.ACCEL_LN_X);
+ formatx = ((FormatCluster) ObjectCluster.returnFormatCluster(adcFormats, ChannelDetails.CHANNEL_TYPE.CAL.toString())); // retrieve the calibrated data
+
+ adcFormats = objc.getCollectionOfFormatClusters(SensorKionixAccel.ObjectClusterSensorName.ACCEL_LN_Y);
+ formaty = ((FormatCluster) ObjectCluster.returnFormatCluster(adcFormats, ChannelDetails.CHANNEL_TYPE.CAL.toString())); // retrieve the calibrated data
+
+ adcFormats = objc.getCollectionOfFormatClusters(SensorKionixAccel.ObjectClusterSensorName.ACCEL_LN_Z);
+ formatz = ((FormatCluster) ObjectCluster.returnFormatCluster(adcFormats, ChannelDetails.CHANNEL_TYPE.CAL.toString())); // retrieve the calibrated data
+
+ if (formatx != null) {
+ System.out.println("X:" + formatx.mData + " Y:" + formaty.mData + " Z:" + formatz.mData);
+
+ } else {
+ System.out.println("ERROR! FormatCluster is Null!");
+ }
+
+ } else if (ind == Shimmer.MSG_IDENTIFIER_PACKET_RECEPTION_RATE_OVERALL) {
+
+ }
+
+
+ }
+
+ }
+}
diff --git a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/androidradiodriver/Shimmer3BleAndroidRadioByteCommunication.java b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/androidradiodriver/Shimmer3BleAndroidRadioByteCommunication.java
new file mode 100644
index 00000000..7e5c5772
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/androidradiodriver/Shimmer3BleAndroidRadioByteCommunication.java
@@ -0,0 +1,23 @@
+package com.shimmerresearch.androidradiodriver;
+
+import java.util.UUID;
+
+public class Shimmer3BleAndroidRadioByteCommunication extends VerisenseBleAndroidRadioByteCommunication{
+
+
+
+ /**
+ * Initialize a ble radio
+ *
+ * @param mac mac address of the verisense device e.g. d0:2b:46:3d:a2:bb
+ */
+ public Shimmer3BleAndroidRadioByteCommunication(String mac) {
+ super(mac);
+ TxID = "49535343-8841-43f4-a8d4-ecbe34729bb3";
+ RxID = "49535343-1e4d-4bd9-ba61-23c647249616";
+ ServiceID = "49535343-fe7d-4ae5-8fa9-9fafd205e455";
+ sid = UUID.fromString(ServiceID);
+ txid = UUID.fromString(TxID);
+ rxid = UUID.fromString(RxID);
+ }
+}
diff --git a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/androidradiodriver/Shimmer3RAndroidRadioByteCommunication.java b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/androidradiodriver/Shimmer3RAndroidRadioByteCommunication.java
new file mode 100644
index 00000000..a48a7e44
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/androidradiodriver/Shimmer3RAndroidRadioByteCommunication.java
@@ -0,0 +1,23 @@
+package com.shimmerresearch.androidradiodriver;
+
+import java.util.UUID;
+
+public class Shimmer3RAndroidRadioByteCommunication extends VerisenseBleAndroidRadioByteCommunication{
+
+
+
+ /**
+ * Initialize a ble radio
+ *
+ * @param mac mac address of the verisense device e.g. d0:2b:46:3d:a2:bb
+ */
+ public Shimmer3RAndroidRadioByteCommunication(String mac) {
+ super(mac);
+ TxID = "65333333-A115-11E2-9E9A-0800200CA102";
+ RxID = "65333333-A115-11E2-9E9A-0800200CA101";
+ ServiceID = "65333333-A115-11E2-9E9A-0800200CA100";
+ sid = UUID.fromString(ServiceID);
+ txid = UUID.fromString(TxID);
+ rxid = UUID.fromString(RxID);
+ }
+}
diff --git a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/androidradiodriver/ShimmerSerialPortAndroid.java b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/androidradiodriver/ShimmerSerialPortAndroid.java
index 13f4a883..0721081b 100644
--- a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/androidradiodriver/ShimmerSerialPortAndroid.java
+++ b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/androidradiodriver/ShimmerSerialPortAndroid.java
@@ -35,16 +35,23 @@ public class ShimmerSerialPortAndroid extends AbstractSerialPortHal {
transient private BluetoothSocket mBluetoothSocket;
transient private DataInputStream mInStream;
transient private OutputStream mOutStream;
+ private transient SerialPortListener mShimmerSerialEventCallback;
+ private boolean mUseListenerThread;
public ShimmerSerialPortAndroid(String bluetoothAddress){
mBluetoothAddress = bluetoothAddress;
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
}
+ public ShimmerSerialPortAndroid(String bluetoothAddress, boolean useListenerThread){
+ mBluetoothAddress = bluetoothAddress;
+ mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+ mUseListenerThread = useListenerThread;
+ }
@Override
public void connect(){
-
+ System.out.println("initialize process shimmer serial port android");
if (mState == ShimmerBluetooth.BT_STATE.DISCONNECTED) {
createBluetoothSocket();
@@ -95,6 +102,9 @@ private boolean getIOStreams(){
InputStream tmpIn = mBluetoothSocket.getInputStream();
mInStream = new DataInputStream(tmpIn);
mOutStream = mBluetoothSocket.getOutputStream();
+ if(mUseListenerThread) {
+ startListening();
+ }
} catch (IOException e) {
catchException(e, ErrorCodesSerialPort.SHIMMERUART_COMM_ERR_PORT_EXCEPTON_OPENING);
return false;
@@ -257,7 +267,7 @@ public boolean isDisonnected() {
@Override
public void registerSerialPortRxEventCallback(SerialPortListener serialPortListener) {
-
+ mShimmerSerialEventCallback = serialPortListener;
}
private void catchException(Exception e, int errorCode) {
@@ -267,7 +277,39 @@ private void catchException(Exception e, int errorCode) {
}
+ public void startListening() {
+ Thread thread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ while (true) {
+ // Read data from the input stream
+
+ int availableBytes = mInStream.available();
+ if (availableBytes < 1) {
+ // End of stream
+
+ } else {
+ // Notify listeners with the read data
+ mShimmerSerialEventCallback.serialPortRxEvent(availableBytes);
+ }
+
+
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ mInStream.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ });
+ thread.start();
+ }
public BluetoothSocket getBluetoothSocket(){
return mBluetoothSocket;
diff --git a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/androidradiodriver/VerisenseBleAndroidRadioByteCommunication.java b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/androidradiodriver/VerisenseBleAndroidRadioByteCommunication.java
new file mode 100644
index 00000000..33a89603
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/androidradiodriver/VerisenseBleAndroidRadioByteCommunication.java
@@ -0,0 +1,254 @@
+package com.shimmerresearch.androidradiodriver;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothGatt;
+import android.bluetooth.BluetoothGattCharacteristic;
+import android.bluetooth.BluetoothGattService;
+import android.content.Context;
+import android.os.Build;
+import android.widget.Toast;
+
+import com.clj.fastble.callback.BleMtuChangedCallback;
+import com.shimmerresearch.driverUtilities.UtilShimmer;
+import com.shimmerresearch.verisense.communication.AbstractByteCommunication;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+import com.clj.fastble.BleManager;
+import com.clj.fastble.callback.BleGattCallback;
+import com.clj.fastble.callback.BleNotifyCallback;
+import com.clj.fastble.callback.BleWriteCallback;
+import com.clj.fastble.data.BleDevice;
+import com.clj.fastble.exception.BleException;
+
+import org.apache.commons.codec.binary.Hex;
+
+import bolts.TaskCompletionSource;
+
+/**
+ * Each instance of this class represents a ble radio that is used to communicate with a verisense device
+ */
+public class VerisenseBleAndroidRadioByteCommunication extends AbstractByteCommunication {
+ BleDevice mBleDevice;
+ protected String TxID = "6E400002-B5A3-F393-E0A9-E50E24DCCA9E";
+ protected String RxID = "6E400003-B5A3-F393-E0A9-E50E24DCCA9E";
+ protected String ServiceID = "6E400001-B5A3-F393-E0A9-E50E24DCCA9E";
+ protected UUID sid;
+ protected UUID txid;
+ protected UUID rxid;
+ String mMac;
+ String uuid;
+
+ //"DA:A6:19:F0:4A:D7"
+ //"E7:45:2C:6D:6F:14"
+ /**
+ * Initialize a ble radio
+ * @param mac mac address of the verisense device e.g. d0:2b:46:3d:a2:bb
+ */
+ public VerisenseBleAndroidRadioByteCommunication(String mac) {
+ mMac = mac;
+ sid = UUID.fromString(ServiceID);
+ txid = UUID.fromString(TxID);
+ rxid = UUID.fromString(RxID);
+
+ }
+ TaskCompletionSource mTaskConnect = new TaskCompletionSource<>();
+ TaskCompletionSource mTaskMTU = new TaskCompletionSource<>();
+
+ /**
+ * Connect to the verisense device
+ */
+ @Override
+ public void connect() {
+ mTaskConnect = new TaskCompletionSource<>();
+ BleManager.getInstance().connect(mMac, new BleGattCallback() {
+ @Override
+ public void onStartConnect() {
+ System.out.println("Connecting");
+ }
+
+ @Override
+ public void onConnectFail(BleDevice bleDevice, BleException exception) {
+ if (mByteCommunicationListener != null) {
+ mByteCommunicationListener.eventDisconnected();
+ }
+ }
+
+ @Override
+ public void onConnectSuccess(BleDevice bleDevice, BluetoothGatt gatt, int status) {
+ mTaskMTU= new TaskCompletionSource<>();
+ BleManager.getInstance().setMtu(bleDevice, 251, new BleMtuChangedCallback() {
+ @Override
+ public void onSetMTUFailure(BleException exception) {
+ System.out.println("MTU Failure");
+
+ }
+
+ @Override
+ public void onMtuChanged(int mtu) {
+ System.out.println("MTU Changed: " + mtu);
+ mTaskMTU.setResult("MTU Changed: " + mtu);
+ }
+ });
+
+ try {
+ boolean result = mTaskMTU.getTask().waitForCompletion(3, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ gatt.requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_HIGH);
+ }
+
+ if (mByteCommunicationListener != null) {
+ mByteCommunicationListener.eventConnected();
+ }
+ mBleDevice = bleDevice;
+ startServiceS(bleDevice);
+ System.out.println(bleDevice.getMac() + " Connected");
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ gatt.setPreferredPhy(BluetoothDevice.PHY_LE_2M_MASK, BluetoothDevice.PHY_LE_2M_MASK, BluetoothDevice.PHY_OPTION_NO_PREFERRED);
+ }
+ mTaskConnect.setResult("Connected");
+ }
+
+ @Override
+ public void onDisConnected(boolean isActiveDisConnected, BleDevice bleDevice, BluetoothGatt gatt, int status) {
+ System.out.println();
+ }
+ });
+
+
+ try {
+ boolean result = mTaskConnect.getTask().waitForCompletion(5, TimeUnit.SECONDS);
+ Thread.sleep(200);
+ if (!result) {
+ System.out.println("Connect fail");
+ }
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Get services and start notify for characteristics changed
+ * @param bleDevice BLE device
+ */
+ public void startServiceS(BleDevice bleDevice){
+ List services = BleManager.getInstance().getBluetoothGattServices(bleDevice);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+
+
+ for (BluetoothGattService service:services) {
+ System.out.println(service.getUuid());
+ if (service.getUuid().compareTo(sid)==0){
+ for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()) {
+ if (characteristic.getUuid().compareTo(txid)==0){
+ //newConnectedBLEDevice(bleDevice,characteristic);
+ CharSequence text = "TXID!";
+ }
+ else if (characteristic.getUuid().compareTo(rxid)==0){
+ newConnectedBLEDevice(bleDevice,characteristic);
+ CharSequence text = "RxID!";
+ }
+ }
+ }
+ }
+
+
+ }
+ }
+
+ /**
+ * Start notify for characteristics changed
+ * @param bleDevice BLE device
+ * @param characteristic
+ */
+ public void newConnectedBLEDevice(final BleDevice bleDevice, final BluetoothGattCharacteristic characteristic) {
+
+
+ int count = 1;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ BleManager.getInstance().notify(
+ bleDevice,
+ characteristic.getService().getUuid().toString(),
+ characteristic.getUuid().toString(),
+ new BleNotifyCallback() {
+
+
+ @Override
+ public void onNotifySuccess() {
+
+ }
+
+ @Override
+ public void onNotifyFailure(BleException exception) {
+
+ }
+
+ @Override
+ public void onCharacteristicChanged(byte[] data) {
+ if (mByteCommunicationListener != null) {
+ try{
+ mByteCommunicationListener.eventNewBytesReceived(data);
+ }catch (Exception e){
+ e.printStackTrace();
+ }
+ }
+ }
+ });
+ }
+ }
+
+ /**
+ * Disconnect from the verisense device
+ */
+ @Override
+ public void disconnect() {
+ BleManager.getInstance().disconnect(mBleDevice);
+ }
+
+ /**
+ * Write bytes to the verisense device
+ * @param bytes byte array to be written
+ */
+ @Override
+ public void writeBytes(byte[] bytes) {
+ BleManager.getInstance().write(mBleDevice, sid.toString(), txid.toString(), bytes, false, new BleWriteCallback() {
+ @Override
+ public void onWriteSuccess(int current, int total, byte[] justWrite) {
+ System.out.println("Write Success " + UtilShimmer.bytesToHexStringWithSpacesFormatted(justWrite));
+ }
+
+ @Override
+ public void onWriteFailure(BleException exception) {
+ System.out.println("Write Fail");
+ }
+ });
+ }
+
+ @Override
+ public void stop() {
+
+ }
+
+ /**
+ * Convert mac address to uuid
+ * @param MacID e.g. d0:2b:46:3d:a2:bb
+ * @return uuid e.g. 00000000-0000-0000-0000-d02b463da2bb
+ */
+ public String convertMacIDtoUUID(String MacID) {
+ String uuid = "00000000-0000-0000-0000-";
+ return uuid + MacID.replace(":", "");
+ }
+
+ /**
+ * @return uuid e.g. 00000000-0000-0000-0000-d02b463da2bb
+ */
+ public String getUuid() {
+ return convertMacIDtoUUID(this.mMac);
+ }
+}
diff --git a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/tools/FileUtils.java b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/tools/FileUtils.java
new file mode 100644
index 00000000..92035b8f
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/tools/FileUtils.java
@@ -0,0 +1,421 @@
+package com.shimmerresearch.tools;
+
+import android.annotation.SuppressLint;
+import android.content.ContentUris;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Environment;
+import android.provider.DocumentsContract;
+import android.provider.MediaStore;
+import android.provider.OpenableColumns;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.util.UUID;
+
+public class FileUtils {
+ public static String FALLBACK_COPY_FOLDER = "upload_part";
+
+ private static String TAG = "FileUtils";
+
+ private static Uri contentUri = null;
+
+ Context context;
+
+ public FileUtils(Context context) {
+ this.context = context;
+ }
+ public enum UriType {
+ FILE, FOLDER; // These are the constants of the enum
+ }
+ @SuppressLint("NewApi")
+ public String getPath(final Uri uri, UriType uritype) {
+ // check here to KITKAT or new version
+ final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
+ String selection = null;
+ String[] selectionArgs = null;
+ // DocumentProvider
+
+ if (isKitKat) {
+ // ExternalStorageProvider
+
+ if (isExternalStorageDocument(uri)) {
+ String docId = "";
+ if(uritype.equals(UriType.FOLDER)) {
+ docId = DocumentsContract.getTreeDocumentId(uri);
+ } else if(uritype.equals(UriType.FILE)) {
+ docId = DocumentsContract.getDocumentId(uri);
+ }
+
+ final String[] split = docId.split(":");
+ final String type = split[0];
+
+ String fullPath = getPathFromExtSD(split);
+
+ if (fullPath == null || !fileExists(fullPath)) {
+ Log.d(TAG, "Copy files as a fallback");
+ fullPath = copyFileToInternalStorage(uri, FALLBACK_COPY_FOLDER);
+ }
+
+ if (fullPath != "") {
+ return fullPath;
+ } else {
+ return null;
+ }
+ }
+
+
+ // DownloadsProvider
+
+ if (isDownloadsDocument(uri)) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ final String id;
+ Cursor cursor = null;
+ try {
+ cursor = context.getContentResolver().query(uri, new String[] {
+ MediaStore.MediaColumns.DISPLAY_NAME
+ }, null, null, null);
+ if (cursor != null && cursor.moveToFirst()) {
+ String fileName = cursor.getString(0);
+ String path = Environment.getExternalStorageDirectory().toString() + "/Download/" + fileName;
+ if (!TextUtils.isEmpty(path)) {
+ return path;
+ }
+ }
+ } finally {
+ if (cursor != null)
+ cursor.close();
+ }
+ id = DocumentsContract.getDocumentId(uri);
+
+ if (!TextUtils.isEmpty(id)) {
+ if (id.startsWith("raw:")) {
+ return id.replaceFirst("raw:", "");
+ }
+ String[] contentUriPrefixesToTry = new String[] {
+ "content://downloads/public_downloads",
+ "content://downloads/my_downloads"
+ };
+
+ for (String contentUriPrefix: contentUriPrefixesToTry) {
+ try {
+ final Uri contentUri = ContentUris.withAppendedId(Uri.parse(contentUriPrefix), Long.valueOf(id));
+
+ return getDataColumn(context, contentUri, null, null);
+ } catch (NumberFormatException e) {
+ //In Android 8 and Android P the id is not a number
+ return uri.getPath().replaceFirst("^/document/raw:", "").replaceFirst("^raw:", "");
+ }
+ }
+ }
+ } else {
+ final String id = DocumentsContract.getDocumentId(uri);
+
+ if (id.startsWith("raw:")) {
+ return id.replaceFirst("raw:", "");
+ }
+ try {
+ contentUri = ContentUris.withAppendedId(
+ Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
+ } catch (NumberFormatException e) {
+ e.printStackTrace();
+ }
+
+ if (contentUri != null)
+ return getDataColumn(context, contentUri, null, null);
+ }
+ }
+
+
+ // MediaProvider
+ if (isMediaDocument(uri)) {
+ final String docId = DocumentsContract.getDocumentId(uri);
+ final String[] split = docId.split(":");
+ final String type = split[0];
+
+ Log.d(TAG, "MEDIA DOCUMENT TYPE: " + type);
+
+ Uri contentUri = null;
+
+ if ("image".equals(type)) {
+ contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
+ } else if ("video".equals(type)) {
+ contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
+ } else if ("audio".equals(type)) {
+ contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
+ } else if ("document".equals(type)) {
+ contentUri = MediaStore.Files.getContentUri(MediaStore.getVolumeName(uri));
+ }
+
+ selection = "_id=?";
+ selectionArgs = new String[] {
+ split[1]
+ };
+
+
+ return getDataColumn(context, contentUri, selection, selectionArgs);
+ }
+
+ if (isGoogleDriveUri(uri)) {
+ return getDriveFilePath(uri);
+ }
+
+ if (isWhatsAppFile(uri)) {
+ return getFilePathForWhatsApp(uri);
+ }
+
+ if ("content".equalsIgnoreCase(uri.getScheme())) {
+ if (isGooglePhotosUri(uri)) {
+ return uri.getLastPathSegment();
+ }
+
+ if (isGoogleDriveUri(uri)) {
+ return getDriveFilePath(uri);
+ }
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+ // return getFilePathFromURI(context,uri);
+ return copyFileToInternalStorage(uri, FALLBACK_COPY_FOLDER);
+ // return getRealPathFromURI(context,uri);
+ } else {
+ return getDataColumn(context, uri, null, null);
+ }
+
+ }
+
+ if ("file".equalsIgnoreCase(uri.getScheme())) {
+ return uri.getPath();
+ }
+ } else {
+ if (isWhatsAppFile(uri)) {
+ return getFilePathForWhatsApp(uri);
+ }
+
+ if ("content".equalsIgnoreCase(uri.getScheme())) {
+ String[] projection = {
+ MediaStore.Images.Media.DATA
+ };
+ Cursor cursor = null;
+
+ try {
+ cursor = context.getContentResolver()
+ .query(uri, projection, selection, selectionArgs, null);
+ int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
+
+ if (cursor.moveToFirst()) {
+ return cursor.getString(column_index);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ return copyFileToInternalStorage(uri, FALLBACK_COPY_FOLDER);
+ }
+
+ private static boolean fileExists(String filePath) {
+ File file = new File(filePath);
+
+ return file.exists();
+ }
+
+ private static String getPathFromExtSD(String[] pathData) {
+ final String type = pathData[0];
+ final String relativePath = File.separator + pathData[1];
+ String fullPath = "";
+
+
+ Log.d(TAG, "MEDIA EXTSD TYPE: " + type);
+ Log.d(TAG, "Relative path: " + relativePath);
+ // on my Sony devices (4.4.4 & 5.1.1), `type` is a dynamic string
+ // something like "71F8-2C0A", some kind of unique id per storage
+ // don't know any API that can get the root path of that storage based on its id.
+ //
+ // so no "primary" type, but let the check here for other devices
+ if ("primary".equalsIgnoreCase(type)) {
+ fullPath = Environment.getExternalStorageDirectory() + relativePath;
+ if (fileExists(fullPath)) {
+ return fullPath;
+ }
+ }
+
+ if ("home".equalsIgnoreCase(type)) {
+ fullPath = "/storage/emulated/0/Documents" + relativePath;
+ if (fileExists(fullPath)) {
+ return fullPath;
+ }
+ }
+
+ // Environment.isExternalStorageRemovable() is `true` for external and internal storage
+ // so we cannot relay on it.
+ //
+ // instead, for each possible path, check if file exists
+ // we'll start with secondary storage as this could be our (physically) removable sd card
+ fullPath = System.getenv("SECONDARY_STORAGE") + relativePath;
+ if (fileExists(fullPath)) {
+ return fullPath;
+ }
+
+ fullPath = System.getenv("EXTERNAL_STORAGE") + relativePath;
+ if (fileExists(fullPath)) {
+ return fullPath;
+ }
+
+ return null;
+ }
+
+ private String getDriveFilePath(Uri uri) {
+ Uri returnUri = uri;
+ Cursor returnCursor = context.getContentResolver().query(returnUri, null, null, null, null);
+ /*
+ * Get the column indexes of the data in the Cursor,
+ * * move to the first row in the Cursor, get the data,
+ * * and display it.
+ * */
+ int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
+ int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
+ returnCursor.moveToFirst();
+ String name = (returnCursor.getString(nameIndex));
+ String size = (Long.toString(returnCursor.getLong(sizeIndex)));
+ File file = new File(context.getCacheDir(), name);
+ try {
+ InputStream inputStream = context.getContentResolver().openInputStream(uri);
+ FileOutputStream outputStream = new FileOutputStream(file);
+ int read = 0;
+ int maxBufferSize = 1 * 1024 * 1024;
+ int bytesAvailable = inputStream.available();
+
+ //int bufferSize = 1024;
+ int bufferSize = Math.min(bytesAvailable, maxBufferSize);
+
+ final byte[] buffers = new byte[bufferSize];
+ while ((read = inputStream.read(buffers)) != -1) {
+ outputStream.write(buffers, 0, read);
+ }
+ Log.e(TAG, "Size " + file.length());
+ inputStream.close();
+ outputStream.close();
+ Log.e(TAG, "Path " + file.getPath());
+ Log.e(TAG, "Size " + file.length());
+ } catch (Exception e) {
+ Log.e(TAG, e.getMessage());
+ }
+
+ return file.getPath();
+ }
+
+ /***
+ * Used for Android Q+
+ * @param uri
+ * @param newDirName if you want to create a directory, you can set this variable
+ * @return
+ */
+ private String copyFileToInternalStorage(Uri uri, String newDirName) {
+ Uri returnUri = uri;
+
+ Cursor returnCursor = context.getContentResolver().query(returnUri, new String[] {
+ OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE
+ }, null, null, null);
+
+
+ /*
+ * Get the column indexes of the data in the Cursor,
+ * * move to the first row in the Cursor, get the data,
+ * * and display it.
+ * */
+ int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
+ int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
+ returnCursor.moveToFirst();
+ String name = (returnCursor.getString(nameIndex));
+ String size = (Long.toString(returnCursor.getLong(sizeIndex)));
+
+ File output;
+ if (!newDirName.equals("")) {
+ String random_collision_avoidance = UUID.randomUUID().toString();
+
+ File dir = new File(context.getFilesDir() + File.separator + newDirName + File.separator + random_collision_avoidance);
+ if (!dir.exists()) {
+ dir.mkdirs();
+ }
+ output = new File(context.getFilesDir() + File.separator + newDirName + File.separator + random_collision_avoidance + File.separator + name);
+ } else {
+ output = new File(context.getFilesDir() + File.separator + name);
+ }
+
+ try {
+ InputStream inputStream = context.getContentResolver().openInputStream(uri);
+ FileOutputStream outputStream = new FileOutputStream(output);
+ int read = 0;
+ int bufferSize = 1024;
+ final byte[] buffers = new byte[bufferSize];
+
+ while ((read = inputStream.read(buffers)) != -1) {
+ outputStream.write(buffers, 0, read);
+ }
+
+ inputStream.close();
+ outputStream.close();
+ } catch (Exception e) {
+ Log.e(TAG, e.getMessage());
+ }
+
+ return output.getPath();
+ }
+
+ private String getFilePathForWhatsApp(Uri uri) {
+ return copyFileToInternalStorage(uri, "whatsapp");
+ }
+
+ private String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
+ Cursor cursor = null;
+ final String column = "_data";
+ final String[] projection = {
+ column
+ };
+
+ try {
+ cursor = context.getContentResolver().query(uri, projection,
+ selection, selectionArgs, null);
+
+ if (cursor != null && cursor.moveToFirst()) {
+ final int index = cursor.getColumnIndexOrThrow(column);
+ return cursor.getString(index);
+ }
+ } finally {
+ if (cursor != null)
+ cursor.close();
+ }
+
+ return null;
+ }
+
+ private static boolean isExternalStorageDocument(Uri uri) {
+ return "com.android.externalstorage.documents".equals(uri.getAuthority());
+ }
+
+ private static boolean isDownloadsDocument(Uri uri) {
+ return "com.android.providers.downloads.documents".equals(uri.getAuthority());
+ }
+
+ private boolean isMediaDocument(Uri uri) {
+ return "com.android.providers.media.documents".equals(uri.getAuthority());
+ }
+
+ private boolean isGooglePhotosUri(Uri uri) {
+ return "com.google.android.apps.photos.content".equals(uri.getAuthority());
+ }
+
+ public boolean isWhatsAppFile(Uri uri) {
+ return "com.whatsapp.provider.media".equals(uri.getAuthority());
+ }
+
+ private boolean isGoogleDriveUri(Uri uri) {
+ return "com.google.android.apps.docs.storage".equals(uri.getAuthority()) || "com.google.android.apps.docs.storage.legacy".equals(uri.getAuthority());
+ }
+}
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/tools/Logging.java b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/tools/Logging.java
index c608326e..9a4825bb 100644
--- a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/tools/Logging.java
+++ b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/java/com/shimmerresearch/tools/Logging.java
@@ -43,12 +43,18 @@
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
import java.util.Collection;
import java.util.Iterator;
+import android.content.Context;
+import android.net.Uri;
import android.os.Environment;
import android.util.Log;
+import androidx.documentfile.provider.DocumentFile;
+
import com.google.common.collect.Multimap;
import com.shimmerresearch.android.shimmerService.ShimmerService;
import com.shimmerresearch.driver.FormatCluster;
@@ -64,7 +70,8 @@ public class Logging {
BufferedWriter writer=null;
File outputFile;
String mDelimiter=","; //default is comma
-
+
+ @Deprecated
/**
* @param myName is the file name which will be used
*/
@@ -74,7 +81,8 @@ public Logging(String myName){
Log.d("AbsolutePath", root.getAbsolutePath());
outputFile = new File(root, mFileName+".dat");
}
-
+
+ @Deprecated
public Logging(String myName, String delimiter){
mFileName=myName;
mDelimiter=delimiter;
@@ -82,7 +90,8 @@ public Logging(String myName, String delimiter){
Log.d("AbsolutePath", root.getAbsolutePath());
outputFile = new File(root, mFileName+".dat");
}
-
+
+ @Deprecated
/**
* Constructor with default file output type (.dat)
* @param myName
@@ -99,6 +108,7 @@ public Logging(String myName,String delimiter, String folderName){
outputFile = new File(root, mFileName+ "." + ShimmerService.FILE_TYPE.DAT.getName());
}
+ @Deprecated
/**
* Constructor to select output file type
* @param myName
@@ -109,13 +119,44 @@ public Logging(String myName,String delimiter, String folderName){
public Logging(String myName, String delimiter, String folderName, ShimmerService.FILE_TYPE fileType) {
mFileName=myName;
mDelimiter=delimiter;
- File root = new File(Environment.getExternalStorageDirectory() + "/"+folderName);
+ File root;
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
+ root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS+ "/"+folderName);
+ } else {
+ root = new File(Environment.getExternalStorageDirectory() + "/"+folderName); //android 13 no longer allows this
+ }
+
if(!root.exists()) {
- if(root.mkdir()); //directory is created;
+ if(root.mkdir()){
+ System.out.println();//directory is created;
+ } else {
+
+ }
}
outputFile = new File(root, mFileName + "." + fileType.getName());
}
-
+ DocumentFile mNewFile = null;
+ Context mContext = null;
+ public Logging(Uri treeURI, Context context, String myName, String delimiter, String folderName, ShimmerService.FILE_TYPE fileType) {
+ mFileName=myName;
+ mDelimiter=delimiter;
+
+ File root;
+
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
+
+ DocumentFile pickedDir = DocumentFile.fromTreeUri(context, treeURI);
+ if (fileType.equals(ShimmerService.FILE_TYPE.CSV)) {
+ mNewFile = pickedDir.createFile("text/comma-separated-values", myName);
+ } else if (fileType.equals(ShimmerService.FILE_TYPE.DAT)) {
+ mNewFile = pickedDir.createFile("application/dat", myName+"."+ShimmerService.FILE_TYPE.DAT.toString().toLowerCase());
+ }
+ mContext = context;
+ }
+
+
+ }
+
/**
* This function takes an object cluster and logs all the data within it. User should note that the function will write over prior files with the same name.
@@ -126,8 +167,12 @@ public void logData(ObjectCluster objectCluster){
try {
if (mFirstWrite==true) {
- writer = new BufferedWriter(new FileWriter(outputFile,true));
-
+ if (mNewFile != null){
+ OutputStream outputStream = mContext.getContentResolver().openOutputStream(mNewFile.getUri());
+ writer = new BufferedWriter(new OutputStreamWriter(outputStream));
+ } else {
+ writer = new BufferedWriter(new FileWriter(outputFile, true));
+ }
//First retrieve all the unique keys from the objectClusterLog
Multimap m = objectClusterLog.getPropertyCluster();
@@ -154,7 +199,7 @@ public void logData(ObjectCluster objectCluster){
}
// write header to a file
- writer = new BufferedWriter(new FileWriter(outputFile,false));
+ //writer = new BufferedWriter(new FileWriter(outputFile,false));
for (int k=0;k
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/res/layouts/fragments/layout/fragment_plot.xml b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/res/layouts/fragments/layout/fragment_plot.xml
index 1037cf63..8faef336 100644
--- a/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/res/layouts/fragments/layout/fragment_plot.xml
+++ b/ShimmerAndroidInstrumentDriver/ShimmerAndroidInstrumentDriver/src/main/res/layouts/fragments/layout/fragment_plot.xml
@@ -46,6 +46,31 @@
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
-
+ android:supportsRtl="true" android:theme="@style/AppTheme">
+
diff --git a/ShimmerAndroidInstrumentDriver/bluetoothManagerExample/src/main/java/com/shimmerresearch/bluetoothmanagerexample/MainActivity.java b/ShimmerAndroidInstrumentDriver/bluetoothManagerExample/src/main/java/com/shimmerresearch/bluetoothmanagerexample/MainActivity.java
index ce3867f8..0c232055 100644
--- a/ShimmerAndroidInstrumentDriver/bluetoothManagerExample/src/main/java/com/shimmerresearch/bluetoothmanagerexample/MainActivity.java
+++ b/ShimmerAndroidInstrumentDriver/bluetoothManagerExample/src/main/java/com/shimmerresearch/bluetoothmanagerexample/MainActivity.java
@@ -1,16 +1,30 @@
package com.shimmerresearch.bluetoothmanagerexample;
+import android.Manifest;
import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.os.Build;
import android.os.Handler;
+import android.os.Looper;
import android.os.Message;
-import android.support.v7.app.AppCompatActivity;
+import androidx.core.app.ActivityCompat;
+import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
+import com.clj.fastble.BleManager;
import com.shimmerresearch.android.Shimmer;
import com.shimmerresearch.android.guiUtilities.ShimmerBluetoothDialog;
import com.shimmerresearch.android.guiUtilities.ShimmerDialogConfigurations;
@@ -21,6 +35,7 @@
import com.shimmerresearch.driver.FormatCluster;
import com.shimmerresearch.driver.ObjectCluster;
import com.shimmerresearch.driver.ShimmerDevice;
+import com.shimmerresearch.exceptions.ShimmerException;
import java.io.IOException;
import java.util.Collection;
@@ -40,8 +55,9 @@ public class MainActivity extends AppCompatActivity {
ShimmerBluetoothManagerAndroid btManager;
ShimmerDevice shimmerDevice;
- String shimmerBtAdd = "00:00:00:00:00:00"; //Put the address of the Shimmer device you want to connect here
+ String shimmerBtAdd;
+ ShimmerBluetoothManagerAndroid.BT_TYPE preferredBtType;
final static String LOG_TAG = "BluetoothManagerExample";
TextView textView;
@@ -49,17 +65,80 @@ public class MainActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ requestPermissions(new String[]{
+ Manifest.permission.BLUETOOTH_ADVERTISE,
+ Manifest.permission.BLUETOOTH_CONNECT,
+ Manifest.permission.BLUETOOTH_SCAN,
+ Manifest.permission.ACCESS_FINE_LOCATION},
+ 0);
+ }else{
+ requestPermissions(new String[]{
+ Manifest.permission.ACCESS_FINE_LOCATION},
+ 0);
+ }
+ }
- try {
- btManager = new ShimmerBluetoothManagerAndroid(this, mHandler);
- } catch (Exception e) {
- Log.e(LOG_TAG, "Couldn't create ShimmerBluetoothManagerAndroid. Error: " + e);
+// Register for broadcasts when a device is discovered.
+ IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
+ registerReceiver(receiver, filter);
+ }
+
+ // Create a BroadcastReceiver for ACTION_FOUND.
+ private final BroadcastReceiver receiver = new BroadcastReceiver() {
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (BluetoothDevice.ACTION_FOUND.equals(action)) {
+ // Discovery has found a device. Get the BluetoothDevice
+ // object and its info from the Intent.
+ BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ if (checkSelfPermission(Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
+ return;
+ }
+ }
+ String deviceName = device.getName();
+ String deviceHardwareAddress = device.getAddress(); // MAC address
+ }
}
+ };
+ @Override
+ public void onRequestPermissionsResult(int requestCode,
+ String permissions[], int[] grantResults) {
+ boolean allPermissionsGranted = true;
+ for (int result : grantResults){
+ if(result != 0){
+ allPermissionsGranted = false;
+ }
+ }
+ if(!allPermissionsGranted){
+ Toast.makeText(this, "Please allow all requested permissions", Toast.LENGTH_SHORT).show();
+ }else{
+ BleManager.getInstance().init(getApplication());
+ try {
+ btManager = new ShimmerBluetoothManagerAndroid(this, mHandler);
+ } catch (Exception e) {
+ Log.e(LOG_TAG, "Couldn't create ShimmerBluetoothManagerAndroid. Error: " + e);
+ Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
+ if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
+ return;
+ }
+ startActivityForResult(enableBtIntent, 1);
+ }
+ }
+ }
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ // Don't forget to unregister the ACTION_FOUND receiver.
+ unregisterReceiver(receiver);
}
@Override
protected void onStart() {
+ /*
//Connect the Shimmer using its Bluetooth Address
try {
btManager.connectShimmerThroughBTAddress(shimmerBtAdd);
@@ -67,7 +146,7 @@ protected void onStart() {
Log.e(LOG_TAG, "Error. Shimmer device not paired or Bluetooth is not enabled");
Toast.makeText(this, "Error. Shimmer device not paired or Bluetooth is not enabled. " +
"Please close the app and pair or enable Bluetooth", Toast.LENGTH_LONG).show();
- }
+ }*/
textView = (TextView) findViewById(R.id.textView);
super.onStart();
}
@@ -81,7 +160,11 @@ protected void onStop() {
Log.d(LOG_TAG, "Stopped Shimmer Logging");
}
else if(shimmerDevice.isStreaming()) {
- shimmerDevice.stopStreaming();
+ try {
+ shimmerDevice.stopStreaming();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
Log.d(LOG_TAG, "Stopped Shimmer Streaming");
}
else {
@@ -165,6 +248,7 @@ public void handleMessage(Message msg) {
break;
case DISCONNECTED:
Log.i(LOG_TAG, "Shimmer [" + macAddress + "] has been DISCONNECTED");
+ shimmerDevice = null;
break;
}
break;
@@ -175,11 +259,19 @@ public void handleMessage(Message msg) {
};
public void stopStreaming(View v){
- shimmerDevice.stopStreaming();
+ try {
+ shimmerDevice.stopStreaming();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
}
public void startStreaming(View v){
- shimmerDevice.startStreaming();
+ try {
+ shimmerDevice.startStreaming();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
}
/**
@@ -234,6 +326,18 @@ public void connectDevice(View v) {
startActivityForResult(intent, ShimmerBluetoothDialog.REQUEST_CONNECT_SHIMMER);
}
+ /**
+ * Called when the disconnect button is clicked
+ * @param v
+ */
+ public void disconnectDevice(View v) {
+ try {
+ ((ShimmerBluetooth)shimmerDevice).disconnect();
+ } catch (ShimmerException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
public void startSDLogging(View v) {
((ShimmerBluetooth)shimmerDevice).writeConfigTime(System.currentTimeMillis());
shimmerDevice.startSDLogging();
@@ -254,15 +358,45 @@ public void stopSDLogging(View v) {
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == 2) {
if (resultCode == Activity.RESULT_OK) {
+ if(btManager==null){
+ try {
+ btManager = new ShimmerBluetoothManagerAndroid(this, mHandler);
+ } catch (Exception e) {
+ Log.e(LOG_TAG, "Couldn't create ShimmerBluetoothManagerAndroid. Error: " + e);
+ }
+ }
btManager.disconnectAllDevices(); //Disconnect all devices first
shimmerDevice = null;
+ showBtTypeConnectionOption();
//Get the Bluetooth mac address of the selected device:
String macAdd = data.getStringExtra(EXTRA_DEVICE_ADDRESS);
- btManager.connectShimmerThroughBTAddress(macAdd); //Connect to the selected device
+ btManager.connectShimmerThroughBTAddress(macAdd, preferredBtType); //Connect to the selected device
shimmerBtAdd = macAdd;
}
}
super.onActivityResult(requestCode, resultCode, data);
}
+ Looper looper = Looper.myLooper();
+
+ public void showBtTypeConnectionOption(){
+ AlertDialog alertDialog = new AlertDialog.Builder(this).create();
+ alertDialog.setCancelable(false);
+ alertDialog.setMessage("Choose preferred Bluetooth type");
+ alertDialog.setButton( Dialog.BUTTON_POSITIVE, "BT CLASSIC", new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ preferredBtType = ShimmerBluetoothManagerAndroid.BT_TYPE.BT_CLASSIC;
+ looper.quit();
+ };
+ });
+ alertDialog.setButton( Dialog.BUTTON_NEGATIVE, "BLE", new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ preferredBtType = ShimmerBluetoothManagerAndroid.BT_TYPE.BLE;
+ looper.quit();
+ };
+ });
+ alertDialog.show();
+ try{ looper.loop(); }
+ catch(RuntimeException e){}
+ }
}
diff --git a/ShimmerAndroidInstrumentDriver/bluetoothManagerExample/src/main/res/layout/activity_main.xml b/ShimmerAndroidInstrumentDriver/bluetoothManagerExample/src/main/res/layout/activity_main.xml
index fe632e6f..59496eaa 100644
--- a/ShimmerAndroidInstrumentDriver/bluetoothManagerExample/src/main/res/layout/activity_main.xml
+++ b/ShimmerAndroidInstrumentDriver/bluetoothManagerExample/src/main/res/layout/activity_main.xml
@@ -86,5 +86,11 @@
android:layout_height="wrap_content"
android:onClick="connectDevice"
android:text="Connect" />
+
diff --git a/ShimmerAndroidInstrumentDriver/build.gradle b/ShimmerAndroidInstrumentDriver/build.gradle
index d8e5724c..8ab97522 100644
--- a/ShimmerAndroidInstrumentDriver/build.gradle
+++ b/ShimmerAndroidInstrumentDriver/build.gradle
@@ -36,7 +36,7 @@ allprojects {
gpr.usr=GITHUB_USER_ID
gpr.key=PERSONAL_ACCESS_TOKEN
*/
- username = project.findProperty("gpr.user") ?: System.getenv("USERNAME")
+ username = project.findProperty("gpr.usr") ?: System.getenv("USERNAME")
password = project.findProperty("gpr.key") ?: System.getenv("TOKEN")
/* should the above not work key in your username and password directly e.g.
username = "username"
@@ -56,7 +56,7 @@ allprojects {
gpr.usr=GITHUB_USER_ID
gpr.key=PERSONAL_ACCESS_TOKEN
*/
- username = project.findProperty("gpr.user") ?: System.getenv("USERNAME")
+ username = project.findProperty("gpr.usr") ?: System.getenv("USERNAME")
password = project.findProperty("gpr.key") ?: System.getenv("TOKEN")
/* should the above not work key in your username and password directly e.g.
username = "username"
@@ -67,7 +67,33 @@ allprojects {
}
mavenCentral()
mavenLocal()
+ jcenter()
}
+ subprojects {
+ afterEvaluate {
+ dependencies {
+ implementation 'com.google.guava:guava:20.0'
+ implementation 'java3d:vecmath:1.3.1'
+ implementation 'com.android.support:appcompat-v7:26.1.0'
+ implementation 'com.clj.fastble:FastBleLib:2.3.4'
+ implementation (group: 'com.shimmerresearch', name: 'shimmerbluetoothmanager', version:'0.10.18_alpha'){
+
+ // excluding org.json which is provided by Android
+ exclude group: 'io.netty'
+ exclude group: 'com.google.protobuf'
+ exclude group: 'org.apache.commons.math'
+ }
+
+ implementation (group: 'com.shimmerresearch', name: 'shimmerdriver', version:'0.10.18_alpha'){
+
+ // excluding org.json which is provided by Android
+ exclude group: 'io.netty'
+ exclude group: 'com.google.protobuf'
+ }
+ }
+ }
+ }
+
// artifactory {
// contextUrl = "${artifactory_contextUrl}"
// publish {
diff --git a/ShimmerAndroidInstrumentDriver/efficientDataArrayExample/build.gradle b/ShimmerAndroidInstrumentDriver/efficientDataArrayExample/build.gradle
index 8acd8a36..303c1c49 100644
--- a/ShimmerAndroidInstrumentDriver/efficientDataArrayExample/build.gradle
+++ b/ShimmerAndroidInstrumentDriver/efficientDataArrayExample/build.gradle
@@ -1,14 +1,14 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 26
+ compileSdkVersion 33
defaultConfig {
applicationId "com.shimmerresearch.efficientdataarrayexample"
minSdkVersion 14
- targetSdkVersion 26
+ targetSdkVersion 33
versionCode 1
versionName "1.0"
multiDexEnabled true
@@ -39,27 +39,19 @@ android {
exclude 'META-INF/ASL2.0'
}
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
- androidTestCompile 'com.android.support:support-annotations:25.3.1'
+ androidTestImplementation 'com.android.support:support-annotations:25.3.1'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
- compile project(path: ':ShimmerAndroidInstrumentDriver')
- implementation (group: 'com.shimmersensing', name: 'ShimmerBluetoothManager', version:'0.9.42beta'){
- // excluding org.json which is provided by Android
- exclude group: 'io.netty'
- exclude group: 'com.google.protobuf'
- exclude group: 'org.apache.commons.math'
- }
- implementation (group: 'com.shimmersensing', name: 'ShimmerDriver', version:'0.9.138beta'){
- // excluding org.json which is provided by Android
- exclude group: 'io.netty'
- exclude group: 'com.google.protobuf'
- exclude group: 'org.apache.commons.math'
- }
+ implementation project(path: ':ShimmerAndroidInstrumentDriver')
}
diff --git a/ShimmerAndroidInstrumentDriver/efficientDataArrayExample/src/main/AndroidManifest.xml b/ShimmerAndroidInstrumentDriver/efficientDataArrayExample/src/main/AndroidManifest.xml
index 1bf7d1ce..9c387a16 100644
--- a/ShimmerAndroidInstrumentDriver/efficientDataArrayExample/src/main/AndroidManifest.xml
+++ b/ShimmerAndroidInstrumentDriver/efficientDataArrayExample/src/main/AndroidManifest.xml
@@ -1,6 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+ android:theme="@style/AppTheme"
+ tools:remove="android:appComponentFactory"
+ tools:targetApi="p">
+
@@ -24,7 +44,7 @@
android:theme="@android:style/Theme.DeviceDefault.Light.Dialog">
@@ -33,5 +53,4 @@
android:resource="@xml/file_paths"/>
-
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/efficientDataArrayExample/src/main/java/com/shimmerresearch/efficientdataarrayexample/MainActivity.java b/ShimmerAndroidInstrumentDriver/efficientDataArrayExample/src/main/java/com/shimmerresearch/efficientdataarrayexample/MainActivity.java
index 0ecd02df..fdf55ffc 100644
--- a/ShimmerAndroidInstrumentDriver/efficientDataArrayExample/src/main/java/com/shimmerresearch/efficientdataarrayexample/MainActivity.java
+++ b/ShimmerAndroidInstrumentDriver/efficientDataArrayExample/src/main/java/com/shimmerresearch/efficientdataarrayexample/MainActivity.java
@@ -4,6 +4,7 @@
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
@@ -21,18 +22,29 @@
import com.shimmerresearch.driver.Configuration;
import com.shimmerresearch.driver.ObjectCluster;
import com.shimmerresearch.driverUtilities.ChannelDetails;
+import com.shimmerresearch.exceptions.ShimmerException;
+import com.shimmerresearch.tools.FileUtils;
+import com.shimmerresearch.verisense.VerisenseDevice;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import static com.shimmerresearch.android.guiUtilities.ShimmerBluetoothDialog.EXTRA_DEVICE_ADDRESS;
import static com.shimmerresearch.android.guiUtilities.ShimmerBluetoothDialog.REQUEST_CONNECT_SHIMMER;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+import androidx.documentfile.provider.DocumentFile;
+
/**
* This example demonstrates the use of the arrays data structure, {@link ObjectCluster#sensorDataArray}, in the following scenarios:
*
@@ -44,42 +56,78 @@
* Switching to using the arrays can improve packet reception rate on slower Android devices.
*/
public class MainActivity extends Activity {
-
+ private static final int PERMISSION_FILE_REQUEST_SHIMMER = 99;
ShimmerBluetoothManagerAndroid btManager;
private String bluetoothAdd = "";
private final static String LOG_TAG = "ArraysExample";
private final static String CSV_FILE_NAME_PREFIX = "Data";
private final static String APP_FOLDER_NAME = "ShimmerArraysExample";
- private final static String APP_DIR_PATH = android.os.Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + APP_FOLDER_NAME + File.separator;
+ private String APP_DIR_PATH = android.os.Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + APP_FOLDER_NAME + File.separator;
/** This can be found in the Manifest */
private final static String APP_FILE_PROVIDER_AUTHORITY = "com.shimmerresearch.efficientdataarrayexample.fileprovider";
private final static int PERMISSIONS_REQUEST_WRITE_STORAGE = 5;
//Write to CSV variables
- private FileWriter fw;
+ //private FileWriter fw;
private BufferedWriter bw;
private File file;
boolean firstTimeWrite = true;
-
+ Uri mTreeUri;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
+ boolean permissionGranted = true;
+ int permissionCheck = 0;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT);
- try {
- btManager = new ShimmerBluetoothManagerAndroid(this, mHandler);
- } catch (Exception e) {
- e.printStackTrace();
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ } else {
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ }
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
}
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+
- //Check if permission to write to external storage has been granted
- if (Build.VERSION.SDK_INT >= 23) {
- if(checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE )!= PackageManager.PERMISSION_GRANTED) {
- requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
- PERMISSIONS_REQUEST_WRITE_STORAGE);
+ if (!permissionGranted) {
+ // Should we show an explanation?
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, 110);
+ } else {
+ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION}, 110);
}
- }
+ } else {
+
+ Intent intent =new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
+
+ startActivityForResult(intent, PERMISSION_FILE_REQUEST_SHIMMER);
+
+
+ try {
+ btManager = new ShimmerBluetoothManagerAndroid(this, mHandler);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ }
}
public void connectDevice(View v) {
@@ -95,7 +143,11 @@ public void startStreaming(View v) {
shimmer.enablePCTimeStamps(false);
//Enable the arrays data structure. Note that enabling this will disable the Multimap/FormatCluster data structure
shimmer.enableArraysDataStructure(true);
- btManager.startStreaming(bluetoothAdd);
+ try {
+ btManager.startStreaming(bluetoothAdd);
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
} else {
Toast.makeText(this, "Can't start streaming\nShimmer device is not connected", Toast.LENGTH_SHORT).show();
}
@@ -103,16 +155,12 @@ public void startStreaming(View v) {
public void stopStreaming(View v) {
if(btManager.getShimmer(bluetoothAdd) != null) {
- try { //Stop CSV writing
- bw.flush();
- bw.close();
- fw.close();
- firstTimeWrite = true;
- } catch (IOException e) {
+ try {
+ Shimmer shimmer = (Shimmer) btManager.getShimmer(bluetoothAdd);
+ btManager.stopStreaming(bluetoothAdd);
+ } catch (ShimmerException e) {
e.printStackTrace();
}
-
- btManager.stopStreaming(bluetoothAdd);
} else {
Toast.makeText(this, "Can't stop streaming\nShimmer device is not connected", Toast.LENGTH_SHORT).show();
}
@@ -126,6 +174,8 @@ public void stopStreaming(View v) {
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+
+
if(requestCode == 2) {
if (resultCode == Activity.RESULT_OK) {
//Get the Bluetooth mac address of the selected device:
@@ -134,9 +184,82 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
}
}
+ if (resultCode == RESULT_OK && requestCode == PERMISSION_FILE_REQUEST_SHIMMER) {
+ if (data != null) {
+ mTreeUri = data.getData();
+ FileUtils futils = new FileUtils(MainActivity.this);
+ File file = new File(futils.getPath(mTreeUri, FileUtils.UriType.FOLDER));
+ APP_DIR_PATH = file.getAbsolutePath();
+ }
+ }
+
super.onActivityResult(requestCode, resultCode, data);
}
+ private final ExecutorService executor = Executors.newSingleThreadExecutor();
+
+ private int countNonNulls(String[] dataArray){
+ int count =0;
+ for (String data:dataArray){
+ if (data!=null){
+ count++;
+ }
+ }
+ return count;
+ }
+
+ int numberOfChannels = 0;
+ private void writeDataToFile(ObjectCluster objc) {
+ if (firstTimeWrite) {
+ //Write headers on first-time
+ numberOfChannels = countNonNulls(objc.sensorDataArray.mSensorNames);
+ int count = 1;
+ for (String channelName : objc.sensorDataArray.mSensorNames) {
+ try {
+ if(channelName!=null) {
+ if (count < numberOfChannels) {
+ bw.write(channelName + ",");
+ } else {
+ bw.write(channelName);
+ }
+ }
+ count++;
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ try {
+ bw.write("\n");
+ } catch (IOException e2) {
+ e2.printStackTrace();
+ }
+ firstTimeWrite = false;
+ }
+ int count = 1;
+ for (double calData : objc.sensorDataArray.mCalData) {
+
+ String dataString = String.valueOf(calData);
+ try {
+ if(objc.sensorDataArray.mSensorNames[count-1]!=null) {
+ if (count < numberOfChannels) {
+ bw.write(dataString + ",");
+ } else {
+ bw.write(dataString);
+ }
+ }
+ count++;
+ } catch (IOException e3) {
+ e3.printStackTrace();
+ }
+ }
+ try {
+ bw.write("\n");
+ } catch (IOException e2) {
+ e2.printStackTrace();
+ }
+ }
+
+
Handler mHandler = new Handler() {
@Override
@@ -145,69 +268,88 @@ public void handleMessage(Message msg) {
switch (msg.what) {
case ShimmerBluetooth.MSG_IDENTIFIER_DATA_PACKET:
if ((msg.obj instanceof ObjectCluster)) {
- ObjectCluster objc = (ObjectCluster) msg.obj;
-
- /**
- * ---------- Printing a channel to Logcat ----------
- */
- //Method 1 - retrieve data from the ObjectCluster using get method
- double data = objc.getFormatClusterValue(Configuration.Shimmer3.ObjectClusterSensorName.ACCEL_WR_X, ChannelDetails.CHANNEL_TYPE.CAL.toString());
- Log.i(LOG_TAG, Configuration.Shimmer3.ObjectClusterSensorName.ACCEL_WR_X + " data: " + data);
-
- //Method 2a - retrieve data from the ObjectCluster by manually parsing the arrays
- int index = -1;
- for(int i=0; i
+ android:visibility="invisible" />
diff --git a/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/.gitignore b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/.gitignore
new file mode 100644
index 00000000..42afabfd
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/build.gradle b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/build.gradle
new file mode 100644
index 00000000..65ebc636
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/build.gradle
@@ -0,0 +1,63 @@
+plugins {
+ id 'com.android.application'
+}
+
+android {
+ //buildToolsVersion '23.0.1'
+ compileSdkVersion 33
+
+ defaultConfig {
+ applicationId "shimmerresearch.com.multiverisenseblebasicexample"
+ minSdkVersion 14
+ targetSdkVersion 33
+ versionCode 1
+ versionName "1.0"
+ multiDexEnabled true
+
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ packagingOptions {
+ exclude 'META-INF/DEPENDENCIES'
+ exclude 'META-INF/LICENSE'
+ exclude 'META-INF/LICENSE.txt'
+ exclude 'META-INF/license.txt'
+ exclude 'META-INF/NOTICE'
+ exclude 'META-INF/NOTICE.txt'
+ exclude 'META-INF/notice.txt'
+ exclude 'META-INF/ASL2.0'
+ }
+ configurations.all {
+ resolutionStrategy.force 'com.android.support:support-annotations:25.3.1'
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation project(path: ':ShimmerAndroidInstrumentDriver')
+
+ androidTestImplementation 'com.android.support:support-annotations:25.3.1'
+ //compile(group: 'com.shimmersensing', name: 'ShimmerAndroidInstrumentDriver', version: '3.0.71Beta', ext: 'aar')
+ implementation 'com.android.support.constraint:constraint-layout:1.0.2'
+ testImplementation 'junit:junit:4.12'
+ androidTestImplementation 'com.android.support.test:runner:1.0.1'
+ androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ implementation 'com.android.support.constraint:constraint-layout:1.0.2'
+ testImplementation 'junit:junit:4.12'
+ implementation 'com.android.support:multidex:1.0.3'
+}
+repositories {
+ mavenCentral()
+}
diff --git a/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/proguard-rules.pro b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/proguard-rules.pro
new file mode 100644
index 00000000..481bb434
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/androidTest/java/shimmerresearch/com/multiverisenseblebasicexample/ExampleInstrumentedTest.java b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/androidTest/java/shimmerresearch/com/multiverisenseblebasicexample/ExampleInstrumentedTest.java
new file mode 100644
index 00000000..2294203e
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/androidTest/java/shimmerresearch/com/multiverisenseblebasicexample/ExampleInstrumentedTest.java
@@ -0,0 +1,25 @@
+package shimmerresearch.com.multiverisenseblebasicexample;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ assertEquals("shimmerresearch.com.multiverisenseblebasicexample", appContext.getPackageName());
+ }
+}
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/AndroidManifest.xml b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..b66c24f4
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/AndroidManifest.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/java/shimmerresearch/com/multiverisenseblebasicexample/MainActivity.java b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/java/shimmerresearch/com/multiverisenseblebasicexample/MainActivity.java
new file mode 100644
index 00000000..8f54feee
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/java/shimmerresearch/com/multiverisenseblebasicexample/MainActivity.java
@@ -0,0 +1,562 @@
+package shimmerresearch.com.multiverisenseblebasicexample;
+
+import static com.shimmerresearch.android.guiUtilities.ShimmerBluetoothDialog.EXTRA_DEVICE_ADDRESS;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Handler;
+import android.os.Message;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.clj.fastble.BleManager;
+import com.shimmerresearch.android.Shimmer;
+import com.shimmerresearch.android.VerisenseDeviceAndroid;
+import com.shimmerresearch.android.manager.ShimmerBluetoothManagerAndroid;
+import com.shimmerresearch.androidradiodriver.VerisenseBleAndroidRadioByteCommunication;
+import com.shimmerresearch.bluetooth.ShimmerBluetooth;
+import com.shimmerresearch.driver.CallbackObject;
+import com.shimmerresearch.driver.Configuration;
+import com.shimmerresearch.driver.FormatCluster;
+import com.shimmerresearch.driver.ObjectCluster;
+import com.shimmerresearch.exceptions.ShimmerException;
+import com.shimmerresearch.verisense.communication.VerisenseProtocolByteCommunication;
+import com.shimmerresearch.verisense.sensors.SensorLIS2DW12;
+
+import java.io.IOException;
+import java.util.Collection;
+
+public class MainActivity extends AppCompatActivity {
+
+ private final static String LOG_TAG = "MultiVeriBLEExample";
+ VerisenseBleAndroidRadioByteCommunication radio1 = new VerisenseBleAndroidRadioByteCommunication("DA:A6:19:F0:4A:D7");
+ VerisenseProtocolByteCommunication protocol1 = new VerisenseProtocolByteCommunication(radio1);
+ VerisenseDeviceAndroid device1;
+
+ VerisenseBleAndroidRadioByteCommunication radio2 = new VerisenseBleAndroidRadioByteCommunication("C9:61:17:53:74:02");
+ VerisenseProtocolByteCommunication protocol2 = new VerisenseProtocolByteCommunication(radio2);
+ VerisenseDeviceAndroid device2;
+//BTHLE\Dev_f2527c20d97e
+ VerisenseBleAndroidRadioByteCommunication radio3 = new VerisenseBleAndroidRadioByteCommunication("F2:52:7C:20:D9:7E");
+ VerisenseProtocolByteCommunication protocol3 = new VerisenseProtocolByteCommunication(radio3);
+ VerisenseDeviceAndroid device3;
+ TextView txtViewThroughput1;
+ TextView txtViewThroughput2;
+ TextView txtViewThroughput3;
+ boolean isSpeedTestSensor1 = false;
+ boolean isSpeedTestSensor2 = false;
+ boolean isSpeedTestSensor3 = false;
+ private Thread t1 = null;
+ private Thread t2 = null;
+ private Thread t3 = null;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ boolean permissionGranted = true;
+ int permissionCheck = 0;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT);
+
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ } else {
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ }
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+
+
+ if (!permissionGranted) {
+ // Should we show an explanation?
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, 110);
+ } else {
+ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION}, 110);
+ }
+ } else {
+ BleManager.getInstance().init(getApplication());
+ device1 = new VerisenseDeviceAndroid(mHandler);
+ device2 = new VerisenseDeviceAndroid(mHandler);
+ device3 = new VerisenseDeviceAndroid(mHandler);
+ }
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
+ if (requestCode == 110){
+ BleManager.getInstance().init(getApplication());
+ device1 = new VerisenseDeviceAndroid(mHandler);
+ device2 = new VerisenseDeviceAndroid(mHandler);
+ device3 = new VerisenseDeviceAndroid(mHandler);
+ }
+ }
+
+ //Sensor 1
+ public void connectDevice1(View v) {
+
+ Thread thread = new Thread(){
+ public void run(){
+
+ device1.setProtocol(Configuration.COMMUNICATION_TYPE.BLUETOOTH, protocol1);
+ try {
+ device1.connect();
+ } catch (ShimmerException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ }
+
+ }
+ };
+
+ thread.start();
+ }
+
+ public void disconnectDevice1(View v) {
+ Thread thread = new Thread(){
+ public void run(){
+ try {
+ isSpeedTestSensor1 = false;
+ device1.disconnect();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+ thread.start();
+ }
+
+ public void readOpConfig1(View v) {
+ Thread thread = new Thread(){
+ public void run(){
+ try {
+ protocol1.readOperationalConfig();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+ thread.start();
+ }
+
+ public void readProdConfig1(View v) {
+ Thread thread = new Thread(){
+ public void run(){
+ try {
+ protocol1.readProductionConfig();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+ thread.start();
+ }
+
+ public void startStreaming1(View v) throws InterruptedException, IOException, ShimmerException {
+ Thread thread = new Thread(){
+ public void run(){
+ try {
+ protocol1.startStreaming();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+ thread.start();
+ }
+
+ public void stopStreaming1(View v) throws IOException, ShimmerException {
+ Thread thread = new Thread(){
+ public void run(){
+ try {
+ protocol1.stopStreaming();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+ thread.start();
+ }
+ public void startSpeedTest1(View v) throws IOException, ShimmerException {
+ Thread thread = new Thread(){
+ public void run(){
+ try {
+ protocol1.startSpeedTest();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+ thread.start();
+ }
+ public void stopSpeedTest1(View v) throws IOException, ShimmerException {
+ Thread thread = new Thread(){
+ public void run(){
+ try {
+ protocol1.stopSpeedTest();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+ thread.start();
+ }
+
+ //Sensor 2
+ public void connectDevice2(View v) {
+
+ Thread thread = new Thread(){
+ public void run(){
+
+ device2.setProtocol(Configuration.COMMUNICATION_TYPE.BLUETOOTH, protocol2);
+ try {
+ device2.connect();
+ } catch (ShimmerException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ }
+
+ }
+ };
+
+ thread.start();
+ }
+
+ public void disconnectDevice2(View v) {
+ Thread thread = new Thread(){
+ public void run(){
+ try {
+ isSpeedTestSensor2 = false;
+ device2.disconnect();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+ thread.start();
+ }
+
+ public void readOpConfig2(View v) {
+ Thread thread = new Thread(){
+ public void run(){
+ try {
+ protocol2.readOperationalConfig();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+ thread.start();
+ }
+
+ public void readProdConfig2(View v) {
+ Thread thread = new Thread(){
+ public void run(){
+ try {
+ protocol2.readProductionConfig();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+ thread.start();
+ }
+
+ public void startStreaming2(View v) throws InterruptedException, IOException, ShimmerException {
+ Thread thread = new Thread(){
+ public void run(){
+ try {
+ protocol2.startStreaming();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+ thread.start();
+ }
+
+ public void stopStreaming2(View v) throws IOException, ShimmerException {
+ Thread thread = new Thread(){
+ public void run(){
+ try {
+ protocol2.stopStreaming();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+ thread.start();
+ }
+ public void startSpeedTest1And2(View v) throws IOException, ShimmerException {
+ t1 = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ protocol1.startSpeedTest();
+ protocol2.startSpeedTest();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ t1.start();
+ }
+ public void stopSpeedTest1And2(View v) throws IOException, ShimmerException {
+ Thread thread = new Thread(){
+ public void run(){
+ try {
+ protocol1.stopSpeedTest();
+ protocol2.stopSpeedTest();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+
+ thread.start();
+ }
+ //Sensor 3
+ public void connectDevice3(View v) {
+
+ Thread thread = new Thread(){
+ public void run(){
+
+ device3.setProtocol(Configuration.COMMUNICATION_TYPE.BLUETOOTH, protocol3);
+ try {
+ device3.connect();
+ } catch (ShimmerException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ }
+
+ }
+ };
+
+ thread.start();
+ }
+
+ public void disconnectDevice3(View v) {
+ Thread thread = new Thread(){
+ public void run(){
+ try {
+ isSpeedTestSensor3 = false;
+ device3.disconnect();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+ thread.start();
+ }
+
+ public void readOpConfig3(View v) {
+ Thread thread = new Thread(){
+ public void run(){
+ try {
+ protocol3.readOperationalConfig();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+ thread.start();
+ }
+
+ public void readProdConfig3(View v) {
+ Thread thread = new Thread(){
+ public void run(){
+ try {
+ protocol3.readProductionConfig();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+ thread.start();
+ }
+
+ public void startStreaming3(View v) throws InterruptedException, IOException, ShimmerException {
+ Thread thread = new Thread(){
+ public void run(){
+ try {
+ protocol3.startStreaming();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+ thread.start();
+ }
+
+ public void stopStreaming3(View v) throws IOException, ShimmerException {
+ Thread thread = new Thread(){
+ public void run(){
+ try {
+ protocol3.stopStreaming();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+ thread.start();
+ }
+
+ public void startAllSpeedTest(View v) throws IOException, ShimmerException {
+
+ t1 = new Thread(new Runnable() {
+
+ @Override
+ public void run() {
+ try {
+ protocol1.startSpeedTest();
+ protocol2.startSpeedTest();
+ protocol3.startSpeedTest();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ t1.start();
+ }
+ public void stopAllSpeedTest(View v) throws IOException, ShimmerException {
+ Thread thread = new Thread(){
+ public void run(){
+ try {
+ protocol1.stopSpeedTest();
+ protocol2.stopSpeedTest();
+ protocol3.stopSpeedTest();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+
+ thread.start();
+ }
+ /**
+ * Sensor 1
+ * Messages from the Shimmer device including sensor data are received here
+ */
+ Handler mHandler = new Handler() {
+
+ @Override
+ public void handleMessage(Message msg) {
+
+ switch (msg.what) {
+ case ShimmerBluetooth.MSG_IDENTIFIER_DATA_PACKET:
+ if ((msg.obj instanceof ObjectCluster)) {
+
+ //Print data to Logcat
+ ObjectCluster objectCluster = (ObjectCluster) msg.obj;
+
+ //Retrieve all possible formats for the current sensor device:
+ Collection allFormats = objectCluster.getCollectionOfFormatClusters(Configuration.Shimmer3.ObjectClusterSensorName.TIMESTAMP);
+ FormatCluster timeStampCluster = ((FormatCluster)ObjectCluster.returnFormatCluster(allFormats,"CAL"));
+ double timeStampData = timeStampCluster.mData;
+ Log.i(LOG_TAG, "Time Stamp: " + timeStampData);
+ allFormats = objectCluster.getCollectionOfFormatClusters(SensorLIS2DW12.ObjectClusterSensorName.LIS2DW12_ACC_X);
+ FormatCluster accelXCluster = ((FormatCluster)ObjectCluster.returnFormatCluster(allFormats,"CAL"));
+ if (accelXCluster!=null) {
+ double accelXData = accelXCluster.mData;
+ Log.i(LOG_TAG, "Accel X: " + accelXData);
+ }
+ allFormats = objectCluster.getCollectionOfFormatClusters(SensorLIS2DW12.ObjectClusterSensorName.LIS2DW12_ACC_Y);
+ FormatCluster accelYCluster = ((FormatCluster)ObjectCluster.returnFormatCluster(allFormats,"CAL"));
+ if (accelXCluster!=null) {
+ double accelYData = accelYCluster.mData;
+ Log.i(LOG_TAG, "Accel Y: " + accelYData);
+ }
+ allFormats = objectCluster.getCollectionOfFormatClusters(SensorLIS2DW12.ObjectClusterSensorName.LIS2DW12_ACC_Z);
+ FormatCluster accelZCluster = ((FormatCluster)ObjectCluster.returnFormatCluster(allFormats,"CAL"));
+ if (accelZCluster!=null) {
+ double accelZData = accelZCluster.mData;
+ Log.i(LOG_TAG, "Accel Z: " + accelZData);
+ }
+
+ }
+ break;
+ case Shimmer.MESSAGE_TOAST:
+ /** Toast messages sent from {@link Shimmer} are received here. E.g. device xxxx now streaming.
+ * Note that display of these Toast messages is done automatically in the Handler in {@link com.shimmerresearch.android.shimmerService.ShimmerService} */
+ Toast.makeText(getApplicationContext(), msg.getData().getString(Shimmer.TOAST), Toast.LENGTH_SHORT).show();
+ break;
+ case ShimmerBluetooth.MSG_IDENTIFIER_STATE_CHANGE:
+ ShimmerBluetooth.BT_STATE state = null;
+ String macAddress = "";
+
+ if (msg.obj instanceof ObjectCluster) {
+ state = ((ObjectCluster) msg.obj).mState;
+ macAddress = ((ObjectCluster) msg.obj).getMacAddress();
+ } else if (msg.obj instanceof CallbackObject) {
+ state = ((CallbackObject) msg.obj).mState;
+ macAddress = ((CallbackObject) msg.obj).mBluetoothAddress;
+ }
+
+ switch (state) {
+ case CONNECTED:
+ break;
+ case CONNECTING:
+ break;
+ case STREAMING:
+ break;
+ case STREAMING_AND_SDLOGGING:
+ break;
+ case SDLOGGING:
+ break;
+ case DISCONNECTED:
+ isSpeedTestSensor1 = false;
+ isSpeedTestSensor2 = false;
+ isSpeedTestSensor3 = false;
+ break;
+ }
+ break;
+ }
+ super.handleMessage(msg);
+ }
+ };
+ /**
+ * Get the result from the paired devices dialog
+ * @param requestCode
+ * @param resultCode
+ * @param data
+ */
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if(requestCode == 2) {
+ if (resultCode == Activity.RESULT_OK) {
+ //Get the Bluetooth mac address of the selected device:
+ String macAdd = data.getStringExtra(EXTRA_DEVICE_ADDRESS);
+
+ }
+
+ }
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+
+
+}
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/drawable-v24/ic_launcher_foreground.xml b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 00000000..2b068d11
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/drawable/ic_launcher_background.xml b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 00000000..07d5da9c
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/layout/activity_main.xml b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/layout/activity_main.xml
new file mode 100644
index 00000000..8922b026
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/layout/activity_main.xml
@@ -0,0 +1,253 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 00000000..eca70cfe
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 00000000..eca70cfe
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-hdpi/ic_launcher.webp b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-hdpi/ic_launcher.webp
new file mode 100644
index 00000000..c209e78e
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-hdpi/ic_launcher.webp differ
diff --git a/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-hdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..b2dfe3d1
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ
diff --git a/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-mdpi/ic_launcher.webp b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-mdpi/ic_launcher.webp
new file mode 100644
index 00000000..4f0f1d64
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-mdpi/ic_launcher.webp differ
diff --git a/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-mdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..62b611da
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ
diff --git a/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-xhdpi/ic_launcher.webp b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-xhdpi/ic_launcher.webp
new file mode 100644
index 00000000..948a3070
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-xhdpi/ic_launcher.webp differ
diff --git a/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..1b9a6956
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ
diff --git a/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-xxhdpi/ic_launcher.webp
new file mode 100644
index 00000000..28d4b77f
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ
diff --git a/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..9287f508
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ
diff --git a/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
new file mode 100644
index 00000000..aa7d6427
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ
diff --git a/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..9126ae37
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ
diff --git a/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/values-night/themes.xml b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/values-night/themes.xml
new file mode 100644
index 00000000..05bee0b0
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/values-night/themes.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/values/colors.xml b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/values/colors.xml
new file mode 100644
index 00000000..f8c6127d
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+
+
+ #FFBB86FC
+ #FF6200EE
+ #FF3700B3
+ #FF03DAC5
+ #FF018786
+ #FF000000
+ #FFFFFFFF
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/values/strings.xml b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/values/strings.xml
new file mode 100644
index 00000000..0b1f542e
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ MultiVerisenseBLEBasicExample
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/values/themes.xml b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/values/themes.xml
new file mode 100644
index 00000000..53be00a2
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/main/res/values/themes.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/test/java/shimmerresearch/com/multiverisenseblebasicexample/ExampleUnitTest.java b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/test/java/shimmerresearch/com/multiverisenseblebasicexample/ExampleUnitTest.java
new file mode 100644
index 00000000..3df98489
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/multiverisenseblebasicexample/src/test/java/shimmerresearch/com/multiverisenseblebasicexample/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package shimmerresearch.com.multiverisenseblebasicexample;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/settings.gradle b/ShimmerAndroidInstrumentDriver/settings.gradle
index 5d51416d..e523ef6f 100644
--- a/ShimmerAndroidInstrumentDriver/settings.gradle
+++ b/ShimmerAndroidInstrumentDriver/settings.gradle
@@ -1,5 +1,7 @@
-include ':ShimmerAndroidInstrumentDriver', ':bluetoothManagerExample', ':shimmerServiceExample', ':shimmerLegacyExample', ':shimmerBasicExample', ':efficientDataArrayExample'
+include ':ShimmerAndroidInstrumentDriver', ':bluetoothManagerExample', ':shimmerServiceExample', ':shimmerLegacyExample', ':shimmerBasicExample', ':verisenseBLEBasicExample', ':efficientDataArrayExample'
include ':shimmer3DOrientationExample', ':shimmerConnectionTest'
//Don't need shimmeradvancelibrary is just an example on how to import projects from different folders
//include ':ShimmerAdvanceLibrary'
//project (":ShimmerAdvanceLibrary").projectDir = new File("../../ShimmerAdvanceAPI/ShimmerAdvanceLibrary")
+include ':multiverisenseblebasicexample' , ':shimmer3BLEBasicExample'
+include ':shimmerspeedtest'
diff --git a/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/.gitignore b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/.gitignore
new file mode 100644
index 00000000..42afabfd
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/README.md b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/README.md
new file mode 100644
index 00000000..1fe2173a
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/README.md
@@ -0,0 +1,12 @@
+# Shimmer3 BLE Basic Example
+This example is only applicable for Shimmer3 with BLE support onwards
+
+- Set Shimmer3 macAddress to be used in MainActivity
+- Run the example to Connect(pairing is not required), Disconnect, Start and Stop Streaming with the device
+- Enable LN Accel in order to see the data when streaming, otherwise only Timestamp will be printed out
+- You will require using a firmware that supports BLE (e.g. https://github.com/ShimmerResearch/shimmer3/releases/tag/LogAndStream_Shimmer3_BLE_v0.16.002) note this firwmare is a PRERELEASE, and is only to allow you to try the BLE radio on the Shimmer3. We recommend checking the releases to make sure you have the latest supported FW.
+- Note that not all Shimmer3 radios support this you can check whether your Shimmer3 radios supports this by using Consensys and check that it is using BT:RN6478 rather than BT:RN42
+
+
+
+
diff --git a/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/build.gradle b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/build.gradle
new file mode 100644
index 00000000..09e75a6a
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/build.gradle
@@ -0,0 +1,54 @@
+plugins {
+ id 'com.android.application'
+}
+
+android {
+ compileSdkVersion 33
+
+ defaultConfig {
+ applicationId "shimmerresearch.com.shimmer3blebasicexample"
+ minSdkVersion 17
+ targetSdkVersion 33
+ versionCode 1
+ versionName "1.0"
+ multiDexEnabled true
+
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ packagingOptions {
+ exclude 'META-INF/DEPENDENCIES'
+ exclude 'META-INF/LICENSE'
+ exclude 'META-INF/LICENSE.txt'
+ exclude 'META-INF/license.txt'
+ exclude 'META-INF/NOTICE'
+ exclude 'META-INF/NOTICE.txt'
+ exclude 'META-INF/notice.txt'
+ exclude 'META-INF/ASL2.0'
+ }
+ configurations.all {
+ resolutionStrategy.force 'com.android.support:support-annotations:25.3.1'
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+}
+
+dependencies {
+ implementation project(path: ':ShimmerAndroidInstrumentDriver')
+
+ implementation 'com.android.support:support-annotations:25.3.1'
+ implementation 'com.android.support.constraint:constraint-layout:2.0.4'
+ testImplementation 'junit:junit:4.13.2'
+ androidTestImplementation 'com.android.support.test:runner:1.0.2'
+ androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
+}
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/proguard-rules.pro b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/proguard-rules.pro
new file mode 100644
index 00000000..481bb434
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/androidTest/java/shimmerresearch/com/shimmer3blebasicexample/ExampleInstrumentedTest.java b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/androidTest/java/shimmerresearch/com/shimmer3blebasicexample/ExampleInstrumentedTest.java
new file mode 100644
index 00000000..a91b781a
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/androidTest/java/shimmerresearch/com/shimmer3blebasicexample/ExampleInstrumentedTest.java
@@ -0,0 +1,25 @@
+package shimmerresearch.com.shimmer3blebasicexample;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ assertEquals("shimmerresearch.com.shimmer3blebasicexample", appContext.getPackageName());
+ }
+}
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/AndroidManifest.xml b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..b07bb6ab
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/AndroidManifest.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/java/shimmerresearch/com/shimmer3blebasicexample/MainActivity.java b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/java/shimmerresearch/com/shimmer3blebasicexample/MainActivity.java
new file mode 100644
index 00000000..c049f742
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/java/shimmerresearch/com/shimmer3blebasicexample/MainActivity.java
@@ -0,0 +1,332 @@
+package shimmerresearch.com.shimmer3blebasicexample;
+
+import static com.shimmerresearch.android.guiUtilities.ShimmerBluetoothDialog.EXTRA_DEVICE_ADDRESS;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Handler;
+import android.os.Message;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.Toast;
+
+import com.clj.fastble.BleManager;
+import com.shimmerresearch.android.Shimmer;
+import com.shimmerresearch.android.guiUtilities.ShimmerBluetoothDialog;
+import com.shimmerresearch.androidradiodriver.Shimmer3BLEAndroid;
+import com.shimmerresearch.bluetooth.ShimmerBluetooth;
+import com.shimmerresearch.driver.BasicProcessWithCallBack;
+import com.shimmerresearch.driver.CallbackObject;
+import com.shimmerresearch.driver.Configuration;
+import com.shimmerresearch.driver.FormatCluster;
+import com.shimmerresearch.driver.ObjectCluster;
+import com.shimmerresearch.driver.ShimmerMsg;
+import com.shimmerresearch.driverUtilities.ChannelDetails;
+import com.shimmerresearch.exceptions.ShimmerException;
+import com.shimmerresearch.sensors.kionix.SensorKionixAccel;
+
+import java.io.IOException;
+import java.util.Collection;
+
+public class MainActivity extends AppCompatActivity {
+ final static int REQUEST_CONNECT_SHIMMER = 2;
+ protected Handler mHandler;
+ private final static String LOG_TAG = "Shimmer3BLEBasicExample";
+ Shimmer3BLEAndroid shimmer1;
+ String macAddress = "E8:EB:1B:97:67:FC";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT);
+ boolean permissionGranted = true;
+ {
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ }
+ if (!permissionGranted) {
+ // Should we show an explanation?
+ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH_CONNECT,Manifest.permission.BLUETOOTH_SCAN,Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_FINE_LOCATION}, 110);
+
+ }
+
+
+ setContentView(R.layout.activity_main);
+ BleManager.getInstance().init(getApplication());
+
+ this.mHandler = handler;
+
+
+ }
+
+ public void connectDevice(View v) {
+ Intent pairedDevicesIntent = new Intent(getApplicationContext(), ShimmerBluetoothDialog.class);
+ startActivityForResult(pairedDevicesIntent, REQUEST_CONNECT_SHIMMER);
+ //device1.setProtocol(Configuration.COMMUNICATION_TYPE.BLUETOOTH, protocol1);
+ //shimmer1.connect("E8:EB:1B:97:67:FC", "default");
+ }
+
+ public void disconnectDevice(View v) {
+ Thread thread = new Thread(){
+ public void run(){
+ try {
+ shimmer1.disconnect();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+
+ thread.start();
+
+
+ }
+
+ public void startStreaming(View v) throws InterruptedException, IOException, ShimmerException {
+ Thread thread = new Thread(){
+ public void run(){
+ try {
+ shimmer1.startStreaming();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+
+ thread.start();
+ }
+
+ public void stopStreaming(View v) throws IOException, ShimmerException {
+ Thread thread = new Thread(){
+ public void run(){
+ shimmer1.stopStreaming();
+ }
+ };
+
+ thread.start();
+
+ }
+ public void startSpeedTest(View v) throws IOException, ShimmerException {
+ Thread thread = new Thread(){
+ public void run(){
+ //shimmer1.startSpeedTest();
+ }
+ };
+
+ thread.start();
+
+ }
+ public void stopSpeedTest(View v) throws IOException, ShimmerException {
+ Thread thread = new Thread(){
+ public void run(){
+ //shimmer1.stopSpeedTest();
+ }
+ };
+
+ thread.start();
+
+ }
+
+
+ /**
+ * Messages from the Shimmer device including sensor data are received here
+ */
+ Handler handler = new Handler() {
+
+ @Override
+ public void handleMessage(Message msg) {
+
+ switch (msg.what) {
+ case ShimmerBluetooth.MSG_IDENTIFIER_DATA_PACKET:
+ if ((msg.obj instanceof ObjectCluster)) {
+
+ //Print data to Logcat
+ ObjectCluster objectCluster = (ObjectCluster) msg.obj;
+
+ //Retrieve all possible formats for the current sensor device:
+ Collection allFormats = objectCluster.getCollectionOfFormatClusters(Configuration.Shimmer3.ObjectClusterSensorName.TIMESTAMP);
+ FormatCluster timeStampCluster = ((FormatCluster)ObjectCluster.returnFormatCluster(allFormats,"CAL"));
+ double timeStampData = timeStampCluster.mData;
+ Log.i(LOG_TAG, "Time Stamp: " + timeStampData);
+ allFormats = objectCluster.getCollectionOfFormatClusters(Configuration.Shimmer3.ObjectClusterSensorName.ACCEL_LN_X);
+ FormatCluster accelXCluster = ((FormatCluster)ObjectCluster.returnFormatCluster(allFormats,"CAL"));
+ if (accelXCluster!=null) {
+ double accelXData = accelXCluster.mData;
+ Log.i(LOG_TAG, "Accel LN X: " + accelXData);
+ }
+ allFormats = objectCluster.getCollectionOfFormatClusters(Configuration.Shimmer3.ObjectClusterSensorName.ACCEL_LN_X);
+ FormatCluster accelYCluster = ((FormatCluster)ObjectCluster.returnFormatCluster(allFormats,"CAL"));
+ if (accelYCluster!=null) {
+ double accelYData = accelYCluster.mData;
+ Log.i(LOG_TAG, "Accel LN Y: " + accelYData);
+ }
+ allFormats = objectCluster.getCollectionOfFormatClusters(Configuration.Shimmer3.ObjectClusterSensorName.ACCEL_LN_X);
+ FormatCluster accelZCluster = ((FormatCluster)ObjectCluster.returnFormatCluster(allFormats,"CAL"));
+ if (accelZCluster!=null) {
+ double accelZData = accelZCluster.mData;
+ Log.i(LOG_TAG, "Accel LN Z: " + accelZData);
+ }
+
+ }
+ break;
+ case Shimmer.MESSAGE_TOAST:
+ /** Toast messages sent from {@link Shimmer} are received here. E.g. device xxxx now streaming.
+ * Note that display of these Toast messages is done automatically in the Handler in {@link com.shimmerresearch.android.shimmerService.ShimmerService} */
+ Toast.makeText(getApplicationContext(), msg.getData().getString(Shimmer.TOAST), Toast.LENGTH_SHORT).show();
+ break;
+ case ShimmerBluetooth.MSG_IDENTIFIER_STATE_CHANGE:
+ ShimmerBluetooth.BT_STATE state = null;
+ String macAddress = "";
+
+ if (msg.obj instanceof ObjectCluster) {
+ state = ((ObjectCluster) msg.obj).mState;
+ macAddress = ((ObjectCluster) msg.obj).getMacAddress();
+ } else if (msg.obj instanceof CallbackObject) {
+ state = ((CallbackObject) msg.obj).mState;
+ macAddress = ((CallbackObject) msg.obj).mBluetoothAddress;
+ }
+
+ switch (state) {
+ case CONNECTED:
+ break;
+ case CONNECTING:
+ break;
+ case STREAMING:
+ break;
+ case STREAMING_AND_SDLOGGING:
+ break;
+ case SDLOGGING:
+ break;
+ case DISCONNECTED:
+ break;
+ }
+ break;
+ }
+ super.handleMessage(msg);
+ }
+ };
+
+ /**
+ * Get the result from the paired devices dialog
+ * @param requestCode
+ * @param resultCode
+ * @param data
+ */
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if(requestCode == REQUEST_CONNECT_SHIMMER) {
+ if (resultCode == Activity.RESULT_OK) {
+ //Get the Bluetooth mac address of the selected device:
+ String macAdd = data.getStringExtra(EXTRA_DEVICE_ADDRESS);
+ shimmer1 = new Shimmer3BLEAndroid(macAdd, this.mHandler);
+ SensorDataReceived sdr = this.new SensorDataReceived();
+ sdr.setWaitForData(shimmer1);
+
+ Thread thread = new Thread(){
+ public void run(){
+ shimmer1.connect(macAdd, "default");
+ }
+ };
+
+ thread.start();
+ }
+
+ }
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+ public class SensorDataReceived extends BasicProcessWithCallBack {
+
+ @Override
+ protected void processMsgFromCallback(ShimmerMsg shimmerMSG) {
+ // TODO Auto-generated method stub
+ System.out.println(shimmerMSG.mIdentifier);
+
+
+ // TODO Auto-generated method stub
+
+ // TODO Auto-generated method stub
+ int ind = shimmerMSG.mIdentifier;
+
+ Object object = (Object) shimmerMSG.mB;
+
+ if (ind == Shimmer.MSG_IDENTIFIER_STATE_CHANGE) {
+ CallbackObject callbackObject = (CallbackObject)object;
+
+ if (callbackObject.mState == ShimmerBluetooth.BT_STATE.CONNECTING) {
+ } else if (callbackObject.mState == ShimmerBluetooth.BT_STATE.CONNECTED) {} else if (callbackObject.mState == ShimmerBluetooth.BT_STATE.DISCONNECTED
+// || callbackObject.mState == BT_STATE.NONE
+ || callbackObject.mState == ShimmerBluetooth.BT_STATE.CONNECTION_LOST){
+
+ }
+ } else if (ind == Shimmer.MSG_IDENTIFIER_NOTIFICATION_MESSAGE) {
+ CallbackObject callbackObject = (CallbackObject)object;
+ int msg = callbackObject.mIndicator;
+ if (msg== Shimmer.NOTIFICATION_SHIMMER_FULLY_INITIALIZED){}
+ if (msg == Shimmer.NOTIFICATION_SHIMMER_STOP_STREAMING) {
+
+ } else if (msg == Shimmer.NOTIFICATION_SHIMMER_START_STREAMING) {
+
+ } else {}
+ } else if (ind == Shimmer.MSG_IDENTIFIER_DATA_PACKET) {
+
+ double accelX = 0;
+ double accelY = 0;
+ double accelZ = 0;
+ FormatCluster formatx;
+ FormatCluster formaty;
+ FormatCluster formatz;
+
+ int INVALID_RESULT = -1;
+
+ ObjectCluster objc = (ObjectCluster) shimmerMSG.mB;
+
+ Collection adcFormats = objc.getCollectionOfFormatClusters(SensorKionixAccel.ObjectClusterSensorName.ACCEL_LN_X);
+ formatx = ((FormatCluster)ObjectCluster.returnFormatCluster(adcFormats, ChannelDetails.CHANNEL_TYPE.CAL.toString())); // retrieve the calibrated data
+
+ adcFormats = objc.getCollectionOfFormatClusters(SensorKionixAccel.ObjectClusterSensorName.ACCEL_LN_Y);
+ formaty = ((FormatCluster)ObjectCluster.returnFormatCluster(adcFormats, ChannelDetails.CHANNEL_TYPE.CAL.toString())); // retrieve the calibrated data
+
+ adcFormats = objc.getCollectionOfFormatClusters(SensorKionixAccel.ObjectClusterSensorName.ACCEL_LN_Z);
+ formatz = ((FormatCluster)ObjectCluster.returnFormatCluster(adcFormats, ChannelDetails.CHANNEL_TYPE.CAL.toString())); // retrieve the calibrated data
+
+ if(formatx != null) {
+ System.out.println("X:"+formatx.mData +" Y:"+formaty.mData+" Z:"+formatz.mData);
+
+ }
+ else {
+ System.out.println("ERROR! FormatCluster is Null!");
+ }
+
+ } else if (ind == Shimmer.MSG_IDENTIFIER_PACKET_RECEPTION_RATE_OVERALL) {
+
+ }
+
+
+
+
+
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/drawable-v24/ic_launcher_foreground.xml b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 00000000..2b068d11
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/drawable/ic_launcher_background.xml b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 00000000..07d5da9c
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/layout/activity_main.xml b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/layout/activity_main.xml
new file mode 100644
index 00000000..20c0845e
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/layout/activity_main.xml
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 00000000..eca70cfe
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 00000000..eca70cfe
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-hdpi/ic_launcher.webp b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-hdpi/ic_launcher.webp
new file mode 100644
index 00000000..c209e78e
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-hdpi/ic_launcher.webp differ
diff --git a/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-hdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..b2dfe3d1
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ
diff --git a/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-mdpi/ic_launcher.webp b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-mdpi/ic_launcher.webp
new file mode 100644
index 00000000..4f0f1d64
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-mdpi/ic_launcher.webp differ
diff --git a/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-mdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..62b611da
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ
diff --git a/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-xhdpi/ic_launcher.webp b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-xhdpi/ic_launcher.webp
new file mode 100644
index 00000000..948a3070
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-xhdpi/ic_launcher.webp differ
diff --git a/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..1b9a6956
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ
diff --git a/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-xxhdpi/ic_launcher.webp
new file mode 100644
index 00000000..28d4b77f
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ
diff --git a/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..9287f508
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ
diff --git a/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
new file mode 100644
index 00000000..aa7d6427
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ
diff --git a/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..9126ae37
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ
diff --git a/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/values-night/themes.xml b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/values-night/themes.xml
new file mode 100644
index 00000000..05bee0b0
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/values-night/themes.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/values/colors.xml b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/values/colors.xml
new file mode 100644
index 00000000..f8c6127d
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+
+
+ #FFBB86FC
+ #FF6200EE
+ #FF3700B3
+ #FF03DAC5
+ #FF018786
+ #FF000000
+ #FFFFFFFF
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/values/strings.xml b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/values/strings.xml
new file mode 100644
index 00000000..c7794910
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ Shimmer3BLEBasicExample
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/values/themes.xml b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/values/themes.xml
new file mode 100644
index 00000000..53be00a2
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/main/res/values/themes.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/test/java/shimmerresearch/com/shimmer3blebasicexample/ExampleUnitTest.java b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/test/java/shimmerresearch/com/shimmer3blebasicexample/ExampleUnitTest.java
new file mode 100644
index 00000000..6bbe9523
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmer3BLEBasicExample/src/test/java/shimmerresearch/com/shimmer3blebasicexample/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package shimmerresearch.com.shimmer3blebasicexample;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmer3DOrientationExample/build.gradle b/ShimmerAndroidInstrumentDriver/shimmer3DOrientationExample/build.gradle
index b3883d96..c8148e05 100644
--- a/ShimmerAndroidInstrumentDriver/shimmer3DOrientationExample/build.gradle
+++ b/ShimmerAndroidInstrumentDriver/shimmer3DOrientationExample/build.gradle
@@ -2,12 +2,12 @@ apply plugin: 'com.android.application'
android {
// compileSdkVersion 23
- compileSdkVersion 25
+ compileSdkVersion 33
defaultConfig {
applicationId "com.shimmerresearch.shimmer3dexample"
minSdkVersion 14
- targetSdkVersion 25
+ targetSdkVersion 33
multiDexEnabled true
}
@@ -27,22 +27,15 @@ android {
exclude 'META-INF/notice.txt'
exclude 'META-INF/ASL2.0'
}
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
}
dependencies {
compile project(':ShimmerAndroidInstrumentDriver')
- implementation (group: 'com.shimmersensing', name: 'ShimmerBluetoothManager', version:'0.9.42beta'){
- // excluding org.json which is provided by Android
- exclude group: 'io.netty'
- exclude group: 'com.google.protobuf'
- exclude group: 'org.apache.commons.math'
- }
- implementation (group: 'com.shimmersensing', name: 'ShimmerDriver', version:'0.9.138beta'){
- // excluding org.json which is provided by Android
- exclude group: 'io.netty'
- exclude group: 'com.google.protobuf'
- exclude group: 'org.apache.commons.math'
- }
compile 'org.apache.commons:commons-math:2.2'
compile 'org.apache.commons:commons-lang3:3.4'
provided files('../ShimmerAndroidInstrumentDriver/libs/ShimmerBiophysicalProcessingLibrary_Rev_0_11.jar')
diff --git a/ShimmerAndroidInstrumentDriver/shimmer3DOrientationExample/src/main/AndroidManifest.xml b/ShimmerAndroidInstrumentDriver/shimmer3DOrientationExample/src/main/AndroidManifest.xml
index 705ded24..571b7637 100644
--- a/ShimmerAndroidInstrumentDriver/shimmer3DOrientationExample/src/main/AndroidManifest.xml
+++ b/ShimmerAndroidInstrumentDriver/shimmer3DOrientationExample/src/main/AndroidManifest.xml
@@ -3,17 +3,27 @@
package="com.shimmerresearch.shimmer3dexample"
android:versionCode="1"
android:versionName="1.0">
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+ android:exported="true">
diff --git a/ShimmerAndroidInstrumentDriver/shimmer3DOrientationExample/src/main/java/com/shimmerresearch/orientationexample/Shimmer3DOrientationExample.java b/ShimmerAndroidInstrumentDriver/shimmer3DOrientationExample/src/main/java/com/shimmerresearch/orientationexample/Shimmer3DOrientationExample.java
index 50c2737d..2b67428b 100644
--- a/ShimmerAndroidInstrumentDriver/shimmer3DOrientationExample/src/main/java/com/shimmerresearch/orientationexample/Shimmer3DOrientationExample.java
+++ b/ShimmerAndroidInstrumentDriver/shimmer3DOrientationExample/src/main/java/com/shimmerresearch/orientationexample/Shimmer3DOrientationExample.java
@@ -12,9 +12,12 @@
import javax.vecmath.Matrix3d;
import javax.vecmath.Quat4d;
+import android.Manifest;
import android.app.Activity;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.opengl.GLSurfaceView;
+import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -27,12 +30,17 @@
import android.widget.TextView;
import android.widget.Toast;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+
import com.shimmerresearch.android.Shimmer;
+import com.shimmerresearch.android.manager.ShimmerBluetoothManagerAndroid;
import com.shimmerresearch.bluetooth.ShimmerBluetooth;
import com.shimmerresearch.driver.Configuration;
import com.shimmerresearch.driver.FormatCluster;
import com.shimmerresearch.driver.ObjectCluster;
import com.shimmerresearch.driver.ShimmerObject;
+import com.shimmerresearch.exceptions.ShimmerException;
import com.shimmerresearch.shimmer3dexample.R;
/**
* The initial Android Activity, setting and initiating
@@ -63,12 +71,8 @@ public class Shimmer3DOrientationExample extends Activity {
private Shimmer mShimmerDevice1 = null;
static final int REQUEST_CONNECT_SHIMMER = 2;
static final int REQUEST_CONFIGURE_SHIMMER = 3;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.exercise);
+ protected void setup(){
t= new MyGLSurfaceView(this);
//Create an Instance with this Activity
glSurface = (GLSurfaceView)findViewById(R.id.graphics_glsurfaceview1);
@@ -82,16 +86,14 @@ protected void onCreate(Bundle savedInstanceState) {
fm3d = new Matrix3d();
m3d = new Matrix3d();
invm3d.setIdentity();
- Integer[] arraySensorID ={Configuration.Shimmer3.SENSOR_ID.SHIMMER_ANALOG_ACCEL,Configuration.Shimmer3.SENSOR_ID.SHIMMER_MPU9X50_GYRO,Configuration.Shimmer3.SENSOR_ID.SHIMMER_LSM303_MAG};
// TODO Auto-generated method stub
- mShimmerDevice1 = new Shimmer(mHandler,"test",51.2,1, 4, arraySensorID, 1, 0, 1, 0);
buttonReset.setOnClickListener(new OnClickListener(){
public void onClick(View arg0) {
invm3d.setIdentity();
}
-
- });
+
+ });
buttonSet.setOnClickListener(new OnClickListener(){
@@ -100,16 +102,70 @@ public void onClick(View arg0) {
invm3d.set(m3d);
invm3d.invert();
}
-
- });
-
- mTVQ1 = (TextView)findViewById(R.id.textViewQ1);
- mTVQ2 = (TextView)findViewById(R.id.textViewQ2);
- mTVQ3 = (TextView)findViewById(R.id.textViewQ3);
- mTVQ4 = (TextView)findViewById(R.id.textViewQ4);
-
+
+ });
+
+ mTVQ1 = (TextView)findViewById(R.id.textViewQ1);
+ mTVQ2 = (TextView)findViewById(R.id.textViewQ2);
+ mTVQ3 = (TextView)findViewById(R.id.textViewQ3);
+ mTVQ4 = (TextView)findViewById(R.id.textViewQ4);
+
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.exercise);
+ boolean permissionGranted = true;
+ int permissionCheck = 0;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT);
+
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ } else {
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ }
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+
+
+ if (!permissionGranted) {
+ // Should we show an explanation?
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, 110);
+ } else {
+ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION}, 110);
+ }
+ } else {
+
+ Integer[] arraySensorID ={Configuration.Shimmer3.SENSOR_ID.SHIMMER_ANALOG_ACCEL,Configuration.Shimmer3.SENSOR_ID.SHIMMER_MPU9X50_GYRO,Configuration.Shimmer3.SENSOR_ID.SHIMMER_LSM303_MAG};
+ mShimmerDevice1 = new Shimmer(mHandler,"test",51.2,1, 4, arraySensorID, 1, 0, 1, 0, Shimmer3DOrientationExample.this);
+ }
+ setup();
}
+ @Override
+ public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
+ if (requestCode == 110){
+ Integer[] arraySensorID ={Configuration.Shimmer3.SENSOR_ID.SHIMMER_ANALOG_ACCEL,Configuration.Shimmer3.SENSOR_ID.SHIMMER_MPU9X50_GYRO,Configuration.Shimmer3.SENSOR_ID.SHIMMER_LSM303_MAG};
+ mShimmerDevice1 = new Shimmer(mHandler,"test",51.2,1, 4, arraySensorID, 1, 0, 1, 0,Shimmer3DOrientationExample.this);
+ }
+ }
/**
* Remember to resume the glSurface
*/
@@ -191,8 +247,12 @@ public void handleMessage(Message msg) {
Log.d("ConnectionStatus","Successful");
//because the default mag range for Shimmer2 and 3 are 0 and 1 respectively, please be aware of what range you use when calibrating using Shimmer 9DOF Cal App, and use the same range here
mShimmerDevice1.enableOnTheFlyGyroCal(true, 102, 1.2);
- mShimmerDevice1.startStreaming();
- break;
+ try {
+ mShimmerDevice1.startStreaming();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ break;
/* case INITIALISED:
@@ -279,8 +339,12 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (mShimmerDevice1.getStreamingStatus()){
mShimmerDevice1.stopStreaming();
mShimmerDevice1.enableLowPowerMag(data.getExtras().getBoolean("Enable"));
- mShimmerDevice1.startStreaming();
- } else {
+ try {
+ mShimmerDevice1.startStreaming();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ } else {
mShimmerDevice1.enableLowPowerMag(data.getExtras().getBoolean("Enable"));
}
} else if (data.getExtras().getString("Command").equals("Gyro")) {
diff --git a/ShimmerAndroidInstrumentDriver/shimmerBasicExample/.gitignore b/ShimmerAndroidInstrumentDriver/shimmerBasicExample/.gitignore
index 796b96d1..0b7b04c2 100644
--- a/ShimmerAndroidInstrumentDriver/shimmerBasicExample/.gitignore
+++ b/ShimmerAndroidInstrumentDriver/shimmerBasicExample/.gitignore
@@ -1 +1,89 @@
-/build
+# Built application files
+*.apk
+*.aar
+*.ap_
+*.aab
+
+# Files for the ART/Dalvik VM
+*.dex
+
+# Java class files
+*.class
+
+# Generated files
+bin/
+gen/
+out/
+# Uncomment the following line in case you need and you don't have the release build type files in your app
+# release/
+
+# Gradle files
+.gradle/
+build/
+
+# Local configuration file (sdk path, etc)
+local.properties
+
+# Proguard folder generated by Eclipse
+proguard/
+
+# Log Files
+*.log
+
+# Android Studio Navigation editor temp files
+.navigation/
+
+# Android Studio captures folder
+captures/
+
+# IntelliJ
+*.iml
+.idea/workspace.xml
+.idea/tasks.xml
+.idea/gradle.xml
+.idea/assetWizardSettings.xml
+.idea/dictionaries
+.idea/libraries
+.idea/jarRepositories.xml
+# Android Studio 3 in .gitignore file.
+.idea/caches
+.idea/modules.xml
+# Comment next line if keeping position of elements in Navigation Editor is relevant for you
+.idea/navEditor.xml
+
+# Keystore files
+# Uncomment the following lines if you do not want to check your keystore files in.
+#*.jks
+#*.keystore
+
+# External native build folder generated in Android Studio 2.2 and later
+.externalNativeBuild
+.cxx/
+
+# Google Services (e.g. APIs or Firebase)
+# google-services.json
+
+# Freeline
+freeline.py
+freeline/
+freeline_project_description.json
+
+# fastlane
+fastlane/report.xml
+fastlane/Preview.html
+fastlane/screenshots
+fastlane/test_output
+fastlane/readme.md
+
+# Version control
+vcs.xml
+
+# lint
+lint/intermediates/
+lint/generated/
+lint/outputs/
+lint/tmp/
+# lint/reports/
+
+# Android Profiling
+*.hprof
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmerBasicExample/build.gradle b/ShimmerAndroidInstrumentDriver/shimmerBasicExample/build.gradle
index ff935146..667eec37 100644
--- a/ShimmerAndroidInstrumentDriver/shimmerBasicExample/build.gradle
+++ b/ShimmerAndroidInstrumentDriver/shimmerBasicExample/build.gradle
@@ -1,14 +1,14 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 26
+ compileSdkVersion 33
defaultConfig {
applicationId "shimmerresearch.com.shimmerbasicexample"
minSdkVersion 17
- targetSdkVersion 26
+ targetSdkVersion 33
versionCode 1
versionName "1.0"
multiDexEnabled true
@@ -39,47 +39,18 @@ android {
resolutionStrategy.force 'com.android.support:support-annotations:25.3.1'
}
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
-
- androidTestCompile 'com.android.support:support-annotations:25.3.1'
- compile(group: 'com.shimmerresearch', name: 'shimmerandroidinstrumentdriver', version: '3.1.0_alpha', ext: 'aar')
-
- implementation (group: 'com.shimmerresearch', name: 'shimmerbluetoothmanager', version:'0.10.0_alpha'){
- // excluding org.json which is provided by Android
- exclude group: 'io.netty'
- exclude group: 'com.google.protobuf'
- exclude group: 'org.apache.commons.math'
- }
- implementation (group: 'com.shimmerresearch', name: 'shimmerdriver', version:'0.10.0_alpha'){
- // excluding org.json which is provided by Android
- exclude group: 'io.netty'
- exclude group: 'com.google.protobuf'
- exclude group: 'org.apache.commons.math'
- }
-// implementation (group: 'com.shimmersensing', name: 'ShimmerBluetoothManager', version:'0.9.42beta'){
-// // excluding org.json which is provided by Android
-// exclude group: 'io.netty'
-// exclude group: 'com.google.protobuf'
-// exclude group: 'org.apache.commons.math'
-// }
-// implementation (group: 'com.shimmersensing', name: 'ShimmerDriver', version:'0.9.138beta'){
-// // excluding org.json which is provided by Android
-// exclude group: 'io.netty'
-// exclude group: 'com.google.protobuf'
-// exclude group: 'org.apache.commons.math'
-// }
-/*
- implementation (group: 'com.shimmersensing', name: 'ShimmerDriverDev', version:'JA-79 v0.1'){
- // excluding org.json which is provided by Android
- exclude group: 'io.netty'
- exclude group: 'com.google.protobuf'
- exclude group: 'org.apache.commons.math'
- }
-
- */
+ implementation 'com.android.support:support-v4:+'
+ androidTestImplementation 'com.android.support:support-annotations:25.3.1'
+ compile(group: 'com.shimmerresearch', name: 'shimmerandroidinstrumentdriver', version: '3.0.83_beta', ext: 'aar')
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
diff --git a/ShimmerAndroidInstrumentDriver/shimmerBasicExample/src/main/AndroidManifest.xml b/ShimmerAndroidInstrumentDriver/shimmerBasicExample/src/main/AndroidManifest.xml
index b6a7d2db..17fdce53 100644
--- a/ShimmerAndroidInstrumentDriver/shimmerBasicExample/src/main/AndroidManifest.xml
+++ b/ShimmerAndroidInstrumentDriver/shimmerBasicExample/src/main/AndroidManifest.xml
@@ -1,7 +1,20 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -21,9 +35,6 @@
-
-
-
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmerBasicExample/src/main/java/shimmerresearch/com/shimmerbasicexample/MainActivity.java b/ShimmerAndroidInstrumentDriver/shimmerBasicExample/src/main/java/shimmerresearch/com/shimmerbasicexample/MainActivity.java
index ed71da4d..a88499ad 100644
--- a/ShimmerAndroidInstrumentDriver/shimmerBasicExample/src/main/java/shimmerresearch/com/shimmerbasicexample/MainActivity.java
+++ b/ShimmerAndroidInstrumentDriver/shimmerBasicExample/src/main/java/shimmerresearch/com/shimmerbasicexample/MainActivity.java
@@ -3,10 +3,14 @@
import android.Manifest;
import android.app.Activity;
import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
-import android.support.v4.app.ActivityCompat;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
@@ -14,6 +18,7 @@
import android.widget.Spinner;
import android.widget.Toast;
+import com.clj.fastble.BleManager;
import com.shimmerresearch.android.Shimmer;
import com.shimmerresearch.android.guiUtilities.ShimmerBluetoothDialog;
import com.shimmerresearch.bluetooth.ShimmerBluetooth;
@@ -21,6 +26,7 @@
import com.shimmerresearch.driver.Configuration;
import com.shimmerresearch.driver.FormatCluster;
import com.shimmerresearch.driver.ObjectCluster;
+import com.shimmerresearch.exceptions.ShimmerException;
import java.io.BufferedWriter;
import java.io.File;
@@ -42,10 +48,45 @@ public class MainActivity extends Activity implements AdapterView.OnItemSelected
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
- ActivityCompat.requestPermissions(this,
- new String[]{Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION},
- 0);
- shimmer = new Shimmer(mHandler);
+ boolean permissionGranted = true;
+ int permissionCheck = 0;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT);
+
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ } else {
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_BACKGROUND_LOCATION);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ }
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+
+
+ if (!permissionGranted) {
+ // Should we show an explanation?
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}, 110);
+ } else {
+ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_BACKGROUND_LOCATION}, 110);
+ }
+ } else {
+
+ }
+ shimmer = new Shimmer(mHandler,MainActivity.this);
spinner = (Spinner) findViewById(R.id.crcSpinner);
spinner.setEnabled(false);
// Spinner click listener
@@ -95,7 +136,11 @@ public void disconnectDevice(View v) {
}
public void startStreaming(View v) throws InterruptedException, IOException{
- shimmer.startStreaming();
+ try {
+ shimmer.startStreaming();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
}
public void stopStreaming(View v) throws IOException{
@@ -129,6 +174,12 @@ public void handleMessage(Message msg) {
double accelXData = accelXCluster.mData;
Log.i(LOG_TAG, "Accel LN X: " + accelXData);
}
+
+ Collection allFormatsPRR = objectCluster.getCollectionOfFormatClusters(Configuration.Shimmer3.ObjectClusterSensorName.PACKET_RECEPTION_RATE_OVERALL);
+ FormatCluster prrCluster = ((FormatCluster)ObjectCluster.returnFormatCluster(allFormatsPRR,"CAL"));
+ double PRR = prrCluster.mData;
+ Log.i(LOG_TAG, "Packet Reception Rate: " + PRR);
+
}
break;
case Shimmer.MESSAGE_TOAST:
@@ -200,7 +251,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
//Get the Bluetooth mac address of the selected device:
String macAdd = data.getStringExtra(EXTRA_DEVICE_ADDRESS);
- shimmer = new Shimmer(mHandler);
+ shimmer = new Shimmer(mHandler,MainActivity.this);
shimmer.connect(macAdd, "default"); //Connect to the selected device
}
diff --git a/ShimmerAndroidInstrumentDriver/shimmerConnectionTest/build.gradle b/ShimmerAndroidInstrumentDriver/shimmerConnectionTest/build.gradle
index eb1e9767..4ca18823 100644
--- a/ShimmerAndroidInstrumentDriver/shimmerConnectionTest/build.gradle
+++ b/ShimmerAndroidInstrumentDriver/shimmerConnectionTest/build.gradle
@@ -1,14 +1,14 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 26
+ compileSdkVersion 33
defaultConfig {
applicationId "shimmerresearch.com.shimmerconnectiontest"
minSdkVersion 17
- targetSdkVersion 26
+ targetSdkVersion 33
versionCode 1
versionName "1.0"
multiDexEnabled true
@@ -39,26 +39,18 @@ android {
resolutionStrategy.force 'com.android.support:support-annotations:25.3.1'
}
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
- androidTestCompile 'com.android.support:support-annotations:25.3.1'
+ androidTestImplementation 'com.android.support:support-annotations:25.3.1'
//compile(group: 'com.shimmersensing', name: 'ShimmerAndroidInstrumentDriver', version: '3.0.71Beta', ext: 'aar')
- compile project(':ShimmerAndroidInstrumentDriver')
- implementation (group: 'com.shimmersensing', name: 'ShimmerBluetoothManager', version:'0.9.42beta'){
- // excluding org.json which is provided by Android
- exclude group: 'io.netty'
- exclude group: 'com.google.protobuf'
- exclude group: 'org.apache.commons.math'
- }
- implementation (group: 'com.shimmersensing', name: 'ShimmerDriver', version:'0.9.138beta'){
- // excluding org.json which is provided by Android
- exclude group: 'io.netty'
- exclude group: 'com.google.protobuf'
- exclude group: 'org.apache.commons.math'
- }
+ implementation project(':ShimmerAndroidInstrumentDriver')
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
diff --git a/ShimmerAndroidInstrumentDriver/shimmerConnectionTest/src/main/AndroidManifest.xml b/ShimmerAndroidInstrumentDriver/shimmerConnectionTest/src/main/AndroidManifest.xml
index 647a3145..39085398 100644
--- a/ShimmerAndroidInstrumentDriver/shimmerConnectionTest/src/main/AndroidManifest.xml
+++ b/ShimmerAndroidInstrumentDriver/shimmerConnectionTest/src/main/AndroidManifest.xml
@@ -1,7 +1,20 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
-
+
diff --git a/ShimmerAndroidInstrumentDriver/shimmerConnectionTest/src/main/java/shimmerresearch/com/shimmerconnectiontest/MainActivity.java b/ShimmerAndroidInstrumentDriver/shimmerConnectionTest/src/main/java/shimmerresearch/com/shimmerconnectiontest/MainActivity.java
index 0b022aa9..dc07a6e2 100644
--- a/ShimmerAndroidInstrumentDriver/shimmerConnectionTest/src/main/java/shimmerresearch/com/shimmerconnectiontest/MainActivity.java
+++ b/ShimmerAndroidInstrumentDriver/shimmerConnectionTest/src/main/java/shimmerresearch/com/shimmerconnectiontest/MainActivity.java
@@ -1,7 +1,9 @@
package shimmerresearch.com.shimmerconnectiontest;
+import android.Manifest;
import android.app.Activity;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
@@ -30,6 +32,9 @@
import static com.shimmerresearch.android.guiUtilities.ShimmerBluetoothDialog.EXTRA_DEVICE_ADDRESS;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+
public class MainActivity extends Activity {
private final static String LOG_TAG = "ShimmerConnectionTest";
@@ -84,6 +89,34 @@ protected void onCreate(Bundle savedInstanceState) {
editTextRetryCountLimit.setText(Integer.toString(retryCountLimit));
editTextTotalIteration.setText(Integer.toString(totalIterationLimit));
editTextInterval.setText(Integer.toString(durationBetweenTest));
+
+ int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT);
+ boolean permissionGranted = true;
+ {
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ }
+ if (!permissionGranted) {
+ // Should we show an explanation?
+ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH_CONNECT,Manifest.permission.BLUETOOTH_SCAN,Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_FINE_LOCATION}, 110);
+
+ } else {
+ //startServiceandBTManager();
+ }
+
}
public void startTest(View v){
@@ -218,7 +251,7 @@ public void run() {
//shimmer.connect(macAdd, "default");
Log.i(LOG_TAG, "Connect Called, retry count: " + Integer.toString(retryCount) + "; Total number of retries:" + totalRetries);
btManager.removeShimmerDeviceBtConnected(macAdd);
- btManager.putShimmerGlobalMap(macAdd,new Shimmer(mHandler));
+ btManager.putShimmerGlobalMap(macAdd,new Shimmer(mHandler,MainActivity.this));
btManager.connectShimmerThroughBTAddress(macAdd);
try {
Thread.sleep(500);
@@ -324,7 +357,7 @@ public void run() {
//shimmer = new Shimmer(mHandler);
//shimmer.connect(macAdd, "default");
Log.i(LOG_TAG, "Connect Called, retry count: " + Integer.toString(retryCount) + "; Total number of retries:" + totalRetries);
- Shimmer shimmer = new Shimmer(mHandler);
+ Shimmer shimmer = new Shimmer(mHandler, MainActivity.this);
shimmer.setMacIdFromUart(macAdd);
btManager.removeShimmerDeviceBtConnected(macAdd);
btManager.putShimmerGlobalMap(macAdd, shimmer);
diff --git a/ShimmerAndroidInstrumentDriver/shimmerLegacyExample/build.gradle b/ShimmerAndroidInstrumentDriver/shimmerLegacyExample/build.gradle
index ea45fb45..f82eac11 100644
--- a/ShimmerAndroidInstrumentDriver/shimmerLegacyExample/build.gradle
+++ b/ShimmerAndroidInstrumentDriver/shimmerLegacyExample/build.gradle
@@ -1,13 +1,13 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 25
+ compileSdkVersion 33
buildToolsVersion '26.0.2'
defaultConfig {
applicationId "com.shimmerresearch.shimmerlegacyexample"
minSdkVersion 14
- targetSdkVersion 25
+ targetSdkVersion 33
versionCode 1
versionName "1.0"
multiDexEnabled true
@@ -38,27 +38,19 @@ android {
exclude 'META-INF/notice.txt'
exclude 'META-INF/ASL2.0'
}
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
}
dependencies {
- compile project(':ShimmerAndroidInstrumentDriver')
- implementation (group: 'com.shimmersensing', name: 'ShimmerBluetoothManager', version:'0.9.42beta'){
- // excluding org.json which is provided by Android
- exclude group: 'io.netty'
- exclude group: 'com.google.protobuf'
- exclude group: 'org.apache.commons.math'
- }
- implementation (group: 'com.shimmersensing', name: 'ShimmerDriver', version:'0.9.138beta'){
- // excluding org.json which is provided by Android
- exclude group: 'io.netty'
- exclude group: 'com.google.protobuf'
- exclude group: 'org.apache.commons.math'
- }
- compile fileTree(dir: 'libs', include: ['*.jar'])
+ implementation project(':ShimmerAndroidInstrumentDriver')
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
- compile 'com.android.support:appcompat-v7:25.3.1'
- compile 'com.android.support.constraint:constraint-layout:1.0.2'
- testCompile 'junit:junit:4.12'
+ implementation 'com.android.support.constraint:constraint-layout:1.0.2'
+ testImplementation 'junit:junit:4.12'
}
diff --git a/ShimmerAndroidInstrumentDriver/shimmerLegacyExample/src/main/java/com/shimmerresearch/shimmerlegacyexample/MainActivity.java b/ShimmerAndroidInstrumentDriver/shimmerLegacyExample/src/main/java/com/shimmerresearch/shimmerlegacyexample/MainActivity.java
index 02ad1d25..47c523d5 100644
--- a/ShimmerAndroidInstrumentDriver/shimmerLegacyExample/src/main/java/com/shimmerresearch/shimmerlegacyexample/MainActivity.java
+++ b/ShimmerAndroidInstrumentDriver/shimmerLegacyExample/src/main/java/com/shimmerresearch/shimmerlegacyexample/MainActivity.java
@@ -4,7 +4,7 @@
import android.content.Intent;
import android.os.Handler;
import android.os.Message;
-import android.support.v7.app.AppCompatActivity;
+import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
@@ -21,6 +21,7 @@
import com.shimmerresearch.driver.FormatCluster;
import com.shimmerresearch.driver.ObjectCluster;
import com.shimmerresearch.driver.ShimmerDevice;
+import com.shimmerresearch.exceptions.ShimmerException;
import java.util.Collection;
import java.util.HashMap;
@@ -141,11 +142,19 @@ public void selectDevice(View v) {
}
public void startStreaming(View v) {
- btManager.startStreaming(shimmerBtAdd);
+ try {
+ btManager.startStreaming(shimmerBtAdd);
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
}
public void stopStreaming(View v) {
- btManager.stopStreaming(shimmerBtAdd);
+ try {
+ btManager.stopStreaming(shimmerBtAdd);
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
}
public void disconnectDevice(View v){
diff --git a/ShimmerAndroidInstrumentDriver/shimmerServiceExample/README.md b/ShimmerAndroidInstrumentDriver/shimmerServiceExample/README.md
index 69fb46bc..f1f7532c 100644
--- a/ShimmerAndroidInstrumentDriver/shimmerServiceExample/README.md
+++ b/ShimmerAndroidInstrumentDriver/shimmerServiceExample/README.md
@@ -1,5 +1,13 @@
# ShimmerServiceExample
-This example is only applicable for the use with Shimmer3 devices onwards
+This example is only applicable for the use with Verisense devices and Shimmer3 devices onwards
-To get started click on the menu and connect to a device. To configure select the device in the Connected Device Fragment, and swipe right. To plot data, start streaming via the menu, and sipe to the Signals to Plot fragment
+To get started click on the menu and connect to a device. To configure select the device in the Connected Device Fragment, and swipe right. To plot data, start streaming via the menu, and swipe to the Signals to Plot fragment
+
+This ShimmerSeriviceExample allows user to
+- Connect to Shimmer3/Verisense device
+- Configure the device
+- Stream and plot the data
+- Erase data in Verisense device
+- Disable logging in Verisense device
+- Data sync Verisense device
diff --git a/ShimmerAndroidInstrumentDriver/shimmerServiceExample/build.gradle b/ShimmerAndroidInstrumentDriver/shimmerServiceExample/build.gradle
index 810db5bb..613b5414 100644
--- a/ShimmerAndroidInstrumentDriver/shimmerServiceExample/build.gradle
+++ b/ShimmerAndroidInstrumentDriver/shimmerServiceExample/build.gradle
@@ -1,12 +1,12 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 25
+ compileSdkVersion 33
defaultConfig {
applicationId "com.shimmerresearch.shimmerserviceexample"
minSdkVersion 14
- targetSdkVersion 25
+ targetSdkVersion 33
versionCode 1
versionName "1.0"
multiDexEnabled true
@@ -37,30 +37,21 @@ android {
exclude 'META-INF/notice.txt'
exclude 'META-INF/ASL2.0'
}
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
}
dependencies {
- compile project(':ShimmerAndroidInstrumentDriver')
- implementation (group: 'com.shimmerresearch', name: 'shimmerbluetoothmanager', version:'0.10.0_alpha'){
- // excluding org.json which is provided by Android
- exclude group: 'io.netty'
- exclude group: 'com.google.protobuf'
- exclude group: 'org.apache.commons.math'
- }
- implementation (group: 'com.shimmerresearch', name: 'shimmerdriver', version:'0.10.0_alpha'){
- // excluding org.json which is provided by Android
- exclude group: 'io.netty'
- exclude group: 'com.google.protobuf'
- exclude group: 'org.apache.commons.math'
- }
- compile fileTree(dir: 'libs', include: ['*.jar'])
+ implementation project(':ShimmerAndroidInstrumentDriver')
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
- compile 'com.android.support:appcompat-v7:25.3.1'
- compile 'com.android.support.constraint:constraint-layout:1.0.2'
- compile 'com.android.support:support-v4:25.3.1'
- compile 'com.android.support:recyclerview-v7:25.3.1'
- testCompile 'junit:junit:4.12'
- compile 'com.android.support:multidex:1.0.3'
+ implementation 'com.android.support.constraint:constraint-layout:1.0.2'
+ testImplementation 'junit:junit:4.12'
+ implementation 'com.android.support:multidex:1.0.3'
}
diff --git a/ShimmerAndroidInstrumentDriver/shimmerServiceExample/src/main/AndroidManifest.xml b/ShimmerAndroidInstrumentDriver/shimmerServiceExample/src/main/AndroidManifest.xml
index c0475a67..1e2a222d 100644
--- a/ShimmerAndroidInstrumentDriver/shimmerServiceExample/src/main/AndroidManifest.xml
+++ b/ShimmerAndroidInstrumentDriver/shimmerServiceExample/src/main/AndroidManifest.xml
@@ -1,14 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ tools:remove="android:appComponentFactory"
+ tools:targetApi="p">
+ android:screenOrientation="portrait"
+ android:exported="true">
@@ -20,4 +37,5 @@
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmerServiceExample/src/main/java/com/shimmerresearch/shimmerserviceexample/MainActivity.java b/ShimmerAndroidInstrumentDriver/shimmerServiceExample/src/main/java/com/shimmerresearch/shimmerserviceexample/MainActivity.java
index 174364cf..43c8e04f 100644
--- a/ShimmerAndroidInstrumentDriver/shimmerServiceExample/src/main/java/com/shimmerresearch/shimmerserviceexample/MainActivity.java
+++ b/ShimmerAndroidInstrumentDriver/shimmerServiceExample/src/main/java/com/shimmerresearch/shimmerserviceexample/MainActivity.java
@@ -1,9 +1,23 @@
package com.shimmerresearch.shimmerserviceexample;
+import android.Manifest;
+
import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.ProgressDialog;
+import android.content.DialogInterface;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.Looper;
import android.os.Message;
-import android.support.v4.app.FragmentManager;
-import android.support.v4.app.FragmentPagerAdapter;
+
+import androidx.annotation.NonNull;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+import androidx.fragment.app.FragmentManager;
+
+
import android.bluetooth.BluetoothAdapter;
import android.content.ComponentName;
import android.content.Context;
@@ -11,35 +25,63 @@
import android.content.ServiceConnection;
import android.os.Handler;
import android.os.IBinder;
-import android.support.v4.app.Fragment;
-import android.support.v4.view.ViewPager;
-import android.support.v7.app.AppCompatActivity;
+import androidx.fragment.app.Fragment;
+
+import androidx.fragment.app.FragmentStatePagerAdapter;
+import androidx.viewpager.widget.PagerAdapter;
+import androidx.viewpager.widget.ViewPager;
+import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
+import android.view.View;
+import android.widget.EditText;
import android.widget.Toast;
-
import com.androidplot.xy.XYPlot;
+import com.clj.fastble.BleManager;
import com.shimmerresearch.android.Shimmer;
import com.shimmerresearch.android.guiUtilities.supportfragments.ConnectedShimmersListFragment;
import com.shimmerresearch.android.guiUtilities.supportfragments.DeviceConfigFragment;
import com.shimmerresearch.android.guiUtilities.supportfragments.PlotFragment;
import com.shimmerresearch.android.guiUtilities.supportfragments.SensorsEnabledFragment;
+import com.shimmerresearch.android.guiUtilities.supportfragments.DataSyncFragment;
import com.shimmerresearch.android.guiUtilities.ShimmerBluetoothDialog;
import com.shimmerresearch.android.guiUtilities.ShimmerDialogConfigurations;
import com.shimmerresearch.android.guiUtilities.supportfragments.SignalsToPlotFragment;
+import com.shimmerresearch.android.manager.ShimmerBluetoothManagerAndroid;
+import com.shimmerresearch.android.protocol.VerisenseProtocolByteCommunicationAndroid;
import com.shimmerresearch.android.shimmerService.ShimmerService;
+import com.shimmerresearch.androidradiodriver.Shimmer3BLEAndroid;
import com.shimmerresearch.bluetooth.ShimmerBluetooth;
import com.shimmerresearch.driver.CallbackObject;
import com.shimmerresearch.driver.ObjectCluster;
import com.shimmerresearch.driver.ShimmerDevice;
+import com.shimmerresearch.driverUtilities.AssembleShimmerConfig;
+import com.shimmerresearch.exceptions.ShimmerException;
+
+import com.shimmerresearch.driver.Configuration.COMMUNICATION_TYPE;
+import com.shimmerresearch.tools.FileUtils;
+import com.shimmerresearch.verisense.VerisenseDevice;
+import com.shimmerresearch.verisense.communication.SyncProgressDetails;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.concurrent.TimeUnit;
-import java.util.List;
+import static com.shimmerresearch.android.guiUtilities.ShimmerBluetoothDialog.EXTRA_DEVICE_ADDRESS;
+import static com.shimmerresearch.android.guiUtilities.ShimmerBluetoothDialog.EXTRA_DEVICE_NAME;
public class MainActivity extends AppCompatActivity implements ConnectedShimmersListFragment.OnShimmerDeviceSelectedListener, SensorsEnabledFragment.OnSensorsSelectedListener {
+ private static final int PERMISSION_FILE_REQUEST_SHIMMER = 99;
+ private static final int PERMISSION_FILE_REQUEST_VERISENSE = 100;
+
+ final static String LOG_TAG = "Shimmer";
+ final static String SERVICE_TAG = "ShimmerService";
+ final static int REQUEST_CONNECT_SHIMMER = 2;
+
ShimmerDialogConfigurations dialog;
BluetoothAdapter btAdapter;
ShimmerService mService;
@@ -48,20 +90,11 @@ public class MainActivity extends AppCompatActivity implements ConnectedShimmers
DeviceConfigFragment deviceConfigFragment;
PlotFragment plotFragment;
SignalsToPlotFragment signalsToPlotFragment;
+ DataSyncFragment dataSyncFragment;
public String selectedDeviceAddress, selectedDeviceName;
- boolean mServiceFirstTime;
-
XYPlot dynamicPlot;
+ boolean isServiceStarted = false;
-
- /**
- * The {@link android.support.v4.view.PagerAdapter} that will provide
- * fragments for each of the sections. We use a
- * {@link FragmentPagerAdapter} derivative, which will keep every
- * loaded fragment in memory. If this becomes too memory intensive, it
- * may be best to switch to a
- * {@link android.support.v4.app.FragmentStatePagerAdapter}.
- */
private SectionsPagerAdapter1 mSectionsPagerAdapter1;
/**
@@ -69,54 +102,64 @@ public class MainActivity extends AppCompatActivity implements ConnectedShimmers
*/
private ViewPager mViewPager;
-
- //Extra for intent from ShimmerBluetoothDialog
- public static final String EXTRA_DEVICE_ADDRESS = "device_address";
-
- boolean isServiceStarted = false;
-
- final static String LOG_TAG = "Shimmer";
- final static String SERVICE_TAG = "ShimmerService";
- final static int REQUEST_CONNECT_SHIMMER = 2;
-
-
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
+ int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT);
+ boolean permissionGranted = true;
+ {
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ }
+ if (!permissionGranted) {
+ // Should we show an explanation?
+ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH_CONNECT,Manifest.permission.BLUETOOTH_SCAN,Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_FINE_LOCATION}, 110);
+
+ } else {
+ startServiceandBTManager();
+ }
+
+ setContentView(R.layout.activity_main);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter1 = new SectionsPagerAdapter1(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter1);
- mViewPager.setOffscreenPageLimit(4); //Ensure none of the fragments has their view destroyed when off-screen
-
+ mViewPager.setOffscreenPageLimit(5); //Ensure none of the fragments has their view destroyed when off-screen
btAdapter = BluetoothAdapter.getDefaultAdapter();
dialog = new ShimmerDialogConfigurations();
- sensorsEnabledFragment = SensorsEnabledFragment.newInstance(null, null);
- connectedShimmersListFragment = ConnectedShimmersListFragment.newInstance();
- deviceConfigFragment = DeviceConfigFragment.newInstance();
- plotFragment = PlotFragment.newInstance();
- signalsToPlotFragment = SignalsToPlotFragment.newInstance();
-
//Check if Bluetooth is enabled
- if (!btAdapter.isEnabled()) {
+ /*if (!btAdapter.isEnabled()) {
int REQUEST_ENABLE_BT = 1;
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
- else {
- Intent intent = new Intent(this, ShimmerService.class);
- startService(intent);
- getApplicationContext().bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
- Log.d(LOG_TAG, "Shimmer Service started");
- Toast.makeText(this, "Shimmer Service started", Toast.LENGTH_SHORT).show();
- }
+ else {*/
+
+ //}
+/*
+ if(checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE )!= PackageManager.PERMISSION_GRANTED) {
+ requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
+ PERMISSIONS_REQUEST_WRITE_STORAGE);
+ }*/
}
@Override
@@ -126,9 +169,66 @@ public boolean onCreateOptionsMenu(Menu menu) {
return true;
}
+ @Override
+ public void onRequestPermissionsResult(
+ int requestCode,
+ @NonNull String[] permissions,
+ @NonNull int[] grantResults
+ ){
+ int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ startServiceandBTManager();
+ }
+ }
+
+ protected void startServiceandBTManager(){
+ BleManager.getInstance().init(getApplication());
+ Intent intent = new Intent(this, ShimmerService.class);
+ startService(intent);
+ getApplicationContext().bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
+ Log.d(LOG_TAG, "Shimmer Service started");
+ Toast.makeText(this, "Shimmer Service started", Toast.LENGTH_SHORT).show();
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ MenuItem item1 = menu.findItem(R.id.data_sync);
+ MenuItem item2 = menu.findItem(R.id.disable_logging);
+ MenuItem item3 = menu.findItem(R.id.erase_data);
+ MenuItem item4 = menu.findItem(R.id.set_sampling_rate);
+ MenuItem item5 = menu.findItem(R.id.enable_write_to_csv);
+ MenuItem item6 = menu.findItem(R.id.disable_write_to_csv);
+ if(selectedDeviceAddress != null){
+ ShimmerDevice device = mService.getShimmer(selectedDeviceAddress);
+ if(device instanceof VerisenseDevice) {
+ item1.setVisible(true);
+ item2.setVisible(true);
+ item3.setVisible(true);
+ item4.setVisible(false);
+ item5.setVisible(false);
+ item6.setVisible(false);
+ if (((VerisenseDevice)device).isRecordingEnabled()){
+ item2.setTitle("Disable Logging");
+ return true;
+ }
+ item2.setTitle("Enable Logging");
+ return true;
+ } else {
+ item4.setVisible(true);
+ item5.setVisible(true);
+ item6.setVisible(true);
+ }
+ }
+ item1.setVisible(false);
+ item2.setVisible(false);
+ item3.setVisible(false);
+ return true;
+ }
+
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
+ final Toast otherTaskOngoingToast = Toast.makeText(this, "Please wait until current task is finished", Toast.LENGTH_LONG);
switch (item.getItemId()) {
case R.id.connect_device:
Intent pairedDevicesIntent = new Intent(getApplicationContext(), ShimmerBluetoothDialog.class);
@@ -136,22 +236,141 @@ public boolean onOptionsItemSelected(MenuItem item) {
return true;
case R.id.start_streaming:
if(selectedDeviceAddress != null) {
- ShimmerDevice mDevice1 = mService.getShimmer(selectedDeviceAddress);
- mDevice1.startStreaming();
+
+ ShimmerDevice mDevice = mService.getShimmer(selectedDeviceAddress);
+ try {
+ mDevice.startStreaming();
+ mViewPager.setCurrentItem(mDevice instanceof VerisenseDevice ? 5 : 4);
+ } catch (ShimmerException e) {
+ if(e.getMessage() == "A task is still ongoing"){
+ otherTaskOngoingToast.show();
+ }
+
+ e.printStackTrace();
+ }
signalsToPlotFragment.buildSignalsToPlotList(this, mService, selectedDeviceAddress, dynamicPlot);
}
return true;
case R.id.stop_streaming:
if(selectedDeviceAddress != null) {
- ShimmerDevice mDevice2 = mService.getShimmer(selectedDeviceAddress);
- mDevice2.stopStreaming();
- sensorsEnabledFragment.buildSensorsList(mDevice2, this, mService.getBluetoothManager());
- deviceConfigFragment.buildDeviceConfigList(mDevice2, this, mService.getBluetoothManager());
+ ShimmerDevice mDevice = mService.getShimmer(selectedDeviceAddress);
+ try {
+ mDevice.stopStreaming();
+ } catch (ShimmerException e) {
+ if(e.getMessage() == "A task is still ongoing"){
+ otherTaskOngoingToast.show();
+ }
+ e.printStackTrace();
+ }
+ }
+ return true;
+ case R.id.data_sync:
+ if(selectedDeviceAddress != null) {
+ mViewPager.setCurrentItem(5);
+ }
+ return true;
+ case R.id.disable_logging:
+ if(selectedDeviceAddress != null) {
+ VerisenseDevice mDevice = (VerisenseDevice)mService.getShimmer(selectedDeviceAddress);
+ VerisenseDevice mDeviceClone = mDevice.deepClone();
+ boolean logging = !mDevice.isRecordingEnabled();
+ mDeviceClone.setRecordingEnabled(logging);
+ byte[] opConfig = mDeviceClone.configBytesGenerate(true, COMMUNICATION_TYPE.BLUETOOTH);
+ try {
+ mDevice.getMapOfVerisenseProtocolByteCommunication().get(COMMUNICATION_TYPE.BLUETOOTH).writeAndReadOperationalConfig(opConfig);
+ Toast.makeText(this, logging?"Logging Enabled":"Logging Disabled", Toast.LENGTH_SHORT).show();
+ } catch (ShimmerException e) {
+ if(e.getMessage() == "A task is still ongoing"){
+ otherTaskOngoingToast.show();
+ }
+ e.printStackTrace();
+ }
+ }
+ return true;
+ case R.id.erase_data:
+ if(selectedDeviceAddress != null) {
+ final VerisenseDevice mDevice = (VerisenseDevice)mService.getShimmer(selectedDeviceAddress);
+ final ProgressDialog progress = new ProgressDialog(this);
+ progress.setTitle("Erasing data");
+ progress.setMessage("Please wait for the operation to complete...");
+ progress.setCancelable(false); // disable dismiss by tapping outside of the dialog
+ progress.show();
+ new Thread(){
+ public void run(){
+ try {
+ mDevice.getMapOfVerisenseProtocolByteCommunication().get(COMMUNICATION_TYPE.BLUETOOTH).eraseDataTask().waitForCompletion(60, TimeUnit.SECONDS);
+ progress.dismiss();
+ } catch (ShimmerException | InterruptedException e) {
+ progress.dismiss();
+ if(e.getMessage() == "A task is still ongoing"){
+ otherTaskOngoingToast.show();
+ }
+ e.printStackTrace();
+ }
+ }
+ }.start();
}
return true;
case R.id.disconnect_all_devices:
mService.disconnectAllDevices();
connectedShimmersListFragment.buildShimmersConnectedListView(null, getApplicationContext());
+ mViewPager.setCurrentItem(0);
+ selectedDeviceAddress = null;
+ selectedDeviceName = null;
+ connectedShimmersListFragment.removeSelectedDevice();
+ return true;
+ case R.id.enable_write_to_csv:
+ Intent intent =new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
+
+ startActivityForResult(intent, PERMISSION_FILE_REQUEST_SHIMMER);
+
+ mService.setEnableLogging(true);
+ return true;
+ case R.id.disable_write_to_csv:
+ mService.setEnableLogging(false);
+ return true;
+ case R.id.set_sampling_rate:
+
+ // Create an AlertDialog Builder
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle("Enter Sampling Rate");
+
+ // Inflate the dialog layout
+ final EditText editTextSamplingRate = new EditText(this);
+ if (selectedDeviceAddress.isEmpty()){
+ return true;
+ }
+ ShimmerBluetooth device = (ShimmerBluetooth) mService.getShimmer(selectedDeviceAddress);
+ editTextSamplingRate.setText(Double.toString(device.getSamplingRateShimmer()));
+ builder.setView(editTextSamplingRate);
+ // Add OK button
+ builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ String samplingRateStr = editTextSamplingRate.getText().toString();
+ // Convert the input to integer
+ double samplingRate = Double.parseDouble(samplingRateStr);
+
+ // Call a method to write sampling rate or do whatever you need
+ ShimmerDevice clone = device.deepClone();
+ clone.setSamplingRateShimmer(samplingRate);
+ AssembleShimmerConfig.generateSingleShimmerConfig(clone, COMMUNICATION_TYPE.BLUETOOTH);
+ mService.configureShimmer(clone);
+ //device.writeShimmerAndSensorsSamplingRate(samplingRate);
+
+ }
+ });
+
+ // Add Cancel button
+ builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ }
+ });
+
+
+ builder.show();
return true;
default:
return super.onOptionsItemSelected(item);
@@ -163,7 +382,6 @@ protected void onStart() {
super.onStart();
}
-
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
// This is called when the connection with the service has been
@@ -195,6 +413,55 @@ public void onServiceDisconnected(ComponentName className) {
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+
+ if (resultCode == RESULT_OK && requestCode == PERMISSION_FILE_REQUEST_VERISENSE) {
+ if (data != null) {
+ Uri treeUri = data.getData();
+ VerisenseDevice mDevice = (VerisenseDevice) mService.getShimmer(selectedDeviceAddress);
+ mDevice.setTrialName(dataSyncFragment.editTextTrialName.getText().toString());
+ mDevice.setParticipantID(dataSyncFragment.editTextParticipantName.getText().toString());
+ FileUtils futils = new FileUtils(MainActivity.this);
+ File file = new File(futils.getPath(treeUri, FileUtils.UriType.FOLDER));
+ ((VerisenseProtocolByteCommunicationAndroid)mDevice.getMapOfVerisenseProtocolByteCommunication().get(COMMUNICATION_TYPE.BLUETOOTH)).enableWriteToBinFile(MainActivity.this,treeUri);
+
+ try {
+ mDevice.getMapOfVerisenseProtocolByteCommunication().get(COMMUNICATION_TYPE.BLUETOOTH).readLoggedData();
+ } catch (Exception e) {
+ if (e.getMessage() == "A task is still ongoing") {
+ //otherTaskOngoingToast.show();
+ }
+ e.printStackTrace();
+ }
+ }
+ }
+
+ if (resultCode == RESULT_OK && requestCode == PERMISSION_FILE_REQUEST_SHIMMER) {
+ if (data != null) {
+ Uri treeUri = data.getData();
+ mService.mFileURI = treeUri;
+ mService.mResolver = getContentResolver();
+ mService.mContext = this;
+
+
+
+
+
+ /*
+ DocumentFile pickedDir = DocumentFile.fromTreeUri(this, treeUri);
+ DocumentFile newF = pickedDir.createFile("text/comma-separated-values", "newshimmer.csv");
+ try {
+ OutputStream outputStream = getContentResolver().openOutputStream(newF.getUri());
+ BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));
+ writer.write("test");
+ writer.close();
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException(e);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ */
+ }
+ }
if (requestCode == 1) { //The system Bluetooth enable dialog has returned a result
if (resultCode == RESULT_OK) {
Intent intent = new Intent(this, ShimmerService.class);
@@ -214,61 +481,131 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
//Get the Bluetooth mac address of the selected device:
String macAdd = data.getStringExtra(EXTRA_DEVICE_ADDRESS);
- mService.connectShimmer(macAdd,this); //Connect to the selected device, and set context to show progress dialog when pairing
+ String deviceName = data.getStringExtra(EXTRA_DEVICE_NAME);
+ if (deviceName.contains(VerisenseDevice.VERISENSE_PREFIX)){
+
+ } else {
+ showBtTypeConnectionOption();
+
+ }
+ mService.connectShimmer(macAdd,deviceName,preferredBtType,this); //Connect to the selected device, and set context to show progress dialog when pairing
+ //mService.connectShimmer(macAdd,this); //Connect to the selected device, and set context to show progress dialog when pairing
+
+
}
}
}
- public class SectionsPagerAdapter1 extends FragmentPagerAdapter {
+ public class SectionsPagerAdapter1 extends FragmentStatePagerAdapter {
+
+ final static int VERISENSE_PAGE_COUNT = 6;
+ final static int SHIMMER3_PAGE_COUNT = 5;
+ ArrayList fragmentArrayList = new ArrayList();
+ ArrayList fragmentTitle = new ArrayList();
public SectionsPagerAdapter1(FragmentManager fm) {
super(fm);
+ dataSyncFragment = DataSyncFragment.newInstance();
+ connectedShimmersListFragment = ConnectedShimmersListFragment.newInstance();
+ sensorsEnabledFragment = SensorsEnabledFragment.newInstance(null, null);
+ deviceConfigFragment = DeviceConfigFragment.newInstance();
+ plotFragment = PlotFragment.newInstance();
+ signalsToPlotFragment = SignalsToPlotFragment.newInstance();
+
+ add(connectedShimmersListFragment, "Connected Devices");
+ add(sensorsEnabledFragment, "Enable Sensors");
+ add(deviceConfigFragment, "Device Configuration");
+ add(plotFragment, "Plot");
+ add(signalsToPlotFragment, "Signals to Plot");
+ add(dataSyncFragment, "Verisense Sync");
}
@Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
- if(position == 0) {
+ if(position < fragmentArrayList.size()){
+ if(position == 0){
connectedShimmersListFragment.buildShimmersConnectedListView(null, getApplicationContext());
- return connectedShimmersListFragment;
- }
- else if(position == 1) {
- return sensorsEnabledFragment;
- }
- else if (position == 2) {
- return deviceConfigFragment;
- }
- else if (position == 3) {
- return plotFragment;
- }
- else if (position == 4) {
- return signalsToPlotFragment;
- }
- else {
- return null;
}
+ return fragmentArrayList.get(position);
+ }
+ else{
+ return null;
+ }
}
@Override
public int getCount() {
- // Show 5 total pages.
- return 5;
+ // Show 5 total pages (Show 6 when a verisense device is selected)
+ return fragmentArrayList.size();
}
@Override
public CharSequence getPageTitle(int position) {
- switch (position) {
- case 0: return "Connected Devices";
- case 1: return "Enable Sensors";
- case 2: return "Device Configuration";
- case 3: return "Plot";
- case 4: return "Signals to Plot";
- default: return "";
+ if(position < fragmentTitle.size()){
+ return fragmentTitle.get(position);
+ }
+ return "";
+ }
+
+ public void add(Fragment fragment, String title, int index)
+ {
+ fragmentArrayList.add(index, fragment);
+ fragmentTitle.add(index, title);
+ }
+
+ public void add(Fragment fragment, String title)
+ {
+ fragmentArrayList.add(fragment);
+ fragmentTitle.add(title);
+ }
+
+ public void remove(int index)
+ {
+ if(fragmentArrayList.size() > 1 && fragmentTitle.size() > 1){
+ fragmentArrayList.remove(index);
+ fragmentTitle.remove(index);
}
}
+ @Override
+ public int getItemPosition(Object object) {
+ // refresh all fragments when data set changed
+ return PagerAdapter.POSITION_NONE;
+ }
+ }
+ ShimmerBluetoothManagerAndroid.BT_TYPE preferredBtType;
+ Looper looper = Looper.myLooper();
+
+ public void showBtTypeConnectionOption(){
+ AlertDialog alertDialog = new AlertDialog.Builder(this).create();
+ alertDialog.setCancelable(false);
+ alertDialog.setMessage("Choose preferred Bluetooth type");
+ alertDialog.setButton( Dialog.BUTTON_POSITIVE, "BT CLASSIC", new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ preferredBtType = ShimmerBluetoothManagerAndroid.BT_TYPE.BT_CLASSIC;
+ looper.quit();
+ };
+ });
+ alertDialog.setButton( Dialog.BUTTON_NEGATIVE, "BLE", new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ preferredBtType = ShimmerBluetoothManagerAndroid.BT_TYPE.BLE;
+ looper.quit();
+ };
+ });
+ alertDialog.show();
+ try{ looper.loop(); }
+ catch(RuntimeException e){}
}
+ int mNumberOfCurrentlyConnectedDevices=0;
+ public boolean isNumberOfConnectedDevicesChanged(){
+ if(mService.getListOfConnectedDevices().size()!=mNumberOfCurrentlyConnectedDevices){
+ mNumberOfCurrentlyConnectedDevices = mService.getListOfConnectedDevices().size();
+ return true;
+ }
+ return false;
+ }
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
if(msg.what == ShimmerBluetooth.MSG_IDENTIFIER_STATE_CHANGE) {
@@ -286,7 +623,22 @@ public void handleMessage(Message msg) {
}
switch (state) {
case CONNECTED:
- connectedShimmersListFragment.buildShimmersConnectedListView(mService.getListOfConnectedDevices(), getApplicationContext());
+ if(isNumberOfConnectedDevicesChanged()) {
+ connectedShimmersListFragment.buildShimmersConnectedListView(mService.getListOfConnectedDevices(), getApplicationContext());
+ if (selectedDeviceAddress != null) {
+ ShimmerDevice mDevice = mService.getShimmer(selectedDeviceAddress);
+ if (mDevice!=null) {
+ deviceConfigFragment.buildDeviceConfigList(mDevice, getApplicationContext(), mService.getBluetoothManager());
+ }
+ }
+ }
+ if(dataSyncFragment != null){
+ dataSyncFragment.TextViewPayloadIndex.setText("");
+ dataSyncFragment.TextViewSpeed.setText("");
+ dataSyncFragment.editTextTrialName.setEnabled(true);
+ dataSyncFragment.editTextParticipantName.setEnabled(true);
+ }
+
break;
case CONNECTING:
break;
@@ -305,20 +657,33 @@ public void handleMessage(Message msg) {
case SDLOGGING:
connectedShimmersListFragment.buildShimmersConnectedListView(mService.getListOfConnectedDevices(), getApplicationContext());
break;
+ case STREAMING_LOGGED_DATA:
+ Toast.makeText(getApplicationContext(), "Data Sync: " + shimmerName + " " + macAddress, Toast.LENGTH_SHORT).show();
+ dataSyncFragment.editTextTrialName.setEnabled(false);
+ dataSyncFragment.editTextParticipantName.setEnabled(false);
+ break;
case DISCONNECTED:
+ isNumberOfConnectedDevicesChanged();
Toast.makeText(getApplicationContext(), "Device disconnected: " + shimmerName + " " + macAddress, Toast.LENGTH_SHORT).show();
connectedShimmersListFragment.buildShimmersConnectedListView(mService.getListOfConnectedDevices(), getApplicationContext()); //to be safe lets rebuild this
break;
}
-
+ }
+ else if(msg.what == Shimmer.MSG_IDENTIFIER_SYNC_PROGRESS){
+ SyncProgressDetails mDetails = (SyncProgressDetails)((CallbackObject)msg.obj).mMyObject;
+ dataSyncFragment.TextViewPayloadIndex.setText("Current Payload Index : " + Integer.toString(mDetails.mPayloadIndex));
+ dataSyncFragment.TextViewSpeed.setText("Speed(KBps) : " + String.format("%.2f", mDetails.mTransferRateBytes/1024));
+ dataSyncFragment.TextViewDirectory.setText("Bin file path : " + mDetails.mBinFilePath);
+ }
+ else if(msg.what == Shimmer.MSG_IDENTIFIER_NOTIFICATION_MESSAGE){
+ if(((CallbackObject)msg.obj).mIndicator == Shimmer.NOTIFICATION_SHIMMER_FULLY_INITIALIZED){
+ Toast.makeText(getApplicationContext(), "Device fully initialized: ", Toast.LENGTH_SHORT).show();
+ }
}
if(msg.arg1 == Shimmer.MSG_STATE_STOP_STREAMING) {
signalsToPlotFragment.setDeviceNotStreamingView();
}
-
-
-
}
};
@@ -327,24 +692,74 @@ public void handleMessage(Message msg) {
* @param macAddress
*/
@Override
- public void onShimmerDeviceSelected(String macAddress, String deviceName) {
- Toast.makeText(this, "Selected Device: " + deviceName + "\n" + macAddress, Toast.LENGTH_SHORT).show();
- selectedDeviceAddress = macAddress;
- selectedDeviceName = deviceName;
+ public void onShimmerDeviceSelected(String macAddress, String deviceName, Boolean selected) {
+ if(selected){
+ Toast.makeText(this, "Selected Device: " + deviceName + "\n" + macAddress, Toast.LENGTH_SHORT).show();
+ selectedDeviceAddress = macAddress;
+ selectedDeviceName = deviceName;
+
+ //Pass the selected device to the fragments
+ ShimmerDevice device = mService.getShimmer(selectedDeviceAddress);
+ if (device instanceof Shimmer3BLEAndroid) { //Due to BLE using the main thread the timer needs to be stopped otherwise no response will be received due to the main thread executing the following code below to generate the fragments
+ ((ShimmerBluetooth) device).stopTimerReadStatus();
+ }
+ //add and remove DataSyncFragment based on the type of device
+ /*
+ if(device instanceof VerisenseDeviceAndroid) {
+ if(mSectionsPagerAdapter1.getCount() == mSectionsPagerAdapter1.SHIMMER3_PAGE_COUNT)
+ {
+ dataSyncFragment = DataSyncFragment.newInstance();
+ mSectionsPagerAdapter1.add(dataSyncFragment, "Data Sync", 3);
+ }
+ }
+ else{
+ if(mSectionsPagerAdapter1.getCount() == mSectionsPagerAdapter1.VERISENSE_PAGE_COUNT)
+ {
+ mSectionsPagerAdapter1.remove(3);
+ }
+ }*/
- //Pass the selected device to the fragments
- ShimmerDevice device = mService.getShimmer(selectedDeviceAddress);
+ mSectionsPagerAdapter1.notifyDataSetChanged();
- sensorsEnabledFragment.setShimmerService(mService);
- sensorsEnabledFragment.buildSensorsList(device, this, mService.getBluetoothManager());
+ sensorsEnabledFragment.setShimmerService(mService);
+ sensorsEnabledFragment.buildSensorsList(device, this, mService.getBluetoothManager());
- deviceConfigFragment.buildDeviceConfigList(device, this, mService.getBluetoothManager());
+ deviceConfigFragment.buildDeviceConfigList(device, this, mService.getBluetoothManager());
+
+ plotFragment.setShimmerService(mService);
+ plotFragment.clearPlot();
+ plotFragment.setSelectedDeviceAddress(selectedDeviceAddress);
+ dynamicPlot = plotFragment.getDynamicPlot();
+
+ mService.stopStreamingAllDevices();
+ signalsToPlotFragment.setDeviceNotStreamingView();
+
+ if (device instanceof VerisenseDevice) {
+ if (dataSyncFragment.editTextParticipantName.getText().toString().isEmpty()) {
+ dataSyncFragment.editTextParticipantName.setText("Default Participant");
+ }
+ if (dataSyncFragment.editTextTrialName.getText().toString().isEmpty()) {
+ dataSyncFragment.editTextTrialName.setText("Default trial");
+ }
- plotFragment.setShimmerService(mService);
- plotFragment.clearPlot();
- dynamicPlot = plotFragment.getDynamicPlot();
+ dataSyncFragment.ButtonDataSync.setVisibility(View.VISIBLE);
+ dataSyncFragment.ButtonDataSync.setOnClickListener(new View.OnClickListener() {
+ public void onClick(View v) {
+ Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
- mService.stopStreamingAllDevices();
+ startActivityForResult(intent, PERMISSION_FILE_REQUEST_VERISENSE);
+ }
+ });
+ }
+ if (device instanceof Shimmer3BLEAndroid) { //Due to BLE using the main thread the timer needs to be stopped otherwise no response will be received due to the main thread executing the following code below to generate the fragments
+ ((ShimmerBluetooth) device).startTimerReadStatus(); // restart the timer
+ }
+
+ }
+ else{
+ selectedDeviceAddress = null;
+ mSectionsPagerAdapter1.notifyDataSetChanged();
+ }
}
@Override
@@ -356,8 +771,11 @@ public void onSensorsSelected() {
@Override
protected void onResume() {
super.onResume();
- Intent intent=new Intent(this, ShimmerService.class);
- getApplicationContext().bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
+ int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT);
+ if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
+ Intent intent = new Intent(this, ShimmerService.class);
+ getApplicationContext().bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
+ }
}
}
diff --git a/ShimmerAndroidInstrumentDriver/shimmerServiceExample/src/main/res/layout/activity_main.xml b/ShimmerAndroidInstrumentDriver/shimmerServiceExample/src/main/res/layout/activity_main.xml
index 9ad62946..134845a1 100644
--- a/ShimmerAndroidInstrumentDriver/shimmerServiceExample/src/main/res/layout/activity_main.xml
+++ b/ShimmerAndroidInstrumentDriver/shimmerServiceExample/src/main/res/layout/activity_main.xml
@@ -1,5 +1,5 @@
-
<-->
-
-
-
+
-
+
diff --git a/ShimmerAndroidInstrumentDriver/shimmerServiceExample/src/main/res/menu/menu.xml b/ShimmerAndroidInstrumentDriver/shimmerServiceExample/src/main/res/menu/menu.xml
index b6e858aa..f288b40f 100644
--- a/ShimmerAndroidInstrumentDriver/shimmerServiceExample/src/main/res/menu/menu.xml
+++ b/ShimmerAndroidInstrumentDriver/shimmerServiceExample/src/main/res/menu/menu.xml
@@ -22,6 +22,19 @@
android:id="@+id/start_streaming">
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/.gitignore b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/.gitignore
new file mode 100644
index 00000000..42afabfd
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/build.gradle b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/build.gradle
new file mode 100644
index 00000000..bd96a0ca
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/build.gradle
@@ -0,0 +1,52 @@
+plugins {
+ id 'com.android.application'
+}
+
+android {
+ compileSdkVersion 33
+
+ defaultConfig {
+ applicationId "com.shimmerresearch.shimmerspeedtest"
+ minSdkVersion 14
+ targetSdkVersion 33
+ versionCode 1
+ versionName "1.0"
+ multiDexEnabled true
+
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ packagingOptions {
+ exclude 'META-INF/DEPENDENCIES'
+ exclude 'META-INF/LICENSE'
+ exclude 'META-INF/LICENSE.txt'
+ exclude 'META-INF/license.txt'
+ exclude 'META-INF/NOTICE'
+ exclude 'META-INF/NOTICE.txt'
+ exclude 'META-INF/notice.txt'
+ exclude 'META-INF/ASL2.0'
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+}
+
+dependencies {
+ implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
+ implementation project(':ShimmerAndroidInstrumentDriver')
+ implementation 'com.android.support.constraint:constraint-layout:2.0.4'
+ implementation 'android.arch.navigation:navigation-fragment:1.0.0'
+ implementation 'android.arch.navigation:navigation-ui:1.0.0'
+ testImplementation 'junit:junit:4.13.2'
+ androidTestImplementation 'com.android.support.test:runner:1.0.2'
+ androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
+}
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/proguard-rules.pro b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/proguard-rules.pro
new file mode 100644
index 00000000..481bb434
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/androidTest/java/com/shimmerresearch/shimmerspeedtest/ExampleInstrumentedTest.java b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/androidTest/java/com/shimmerresearch/shimmerspeedtest/ExampleInstrumentedTest.java
new file mode 100644
index 00000000..7e9e81e8
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/androidTest/java/com/shimmerresearch/shimmerspeedtest/ExampleInstrumentedTest.java
@@ -0,0 +1,25 @@
+package com.shimmerresearch.shimmerspeedtest;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ assertEquals("com.shimmerresearch.shimmerspeedtest", appContext.getPackageName());
+ }
+}
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/AndroidManifest.xml b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..c62b5d26
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/AndroidManifest.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/java/com/shimmerresearch/shimmerspeedtest/FirstFragment.java b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/java/com/shimmerresearch/shimmerspeedtest/FirstFragment.java
new file mode 100644
index 00000000..e91ad441
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/java/com/shimmerresearch/shimmerspeedtest/FirstFragment.java
@@ -0,0 +1,199 @@
+package com.shimmerresearch.shimmerspeedtest;
+
+import static com.shimmerresearch.android.guiUtilities.ShimmerBluetoothDialog.EXTRA_DEVICE_ADDRESS;
+import static com.shimmerresearch.android.guiUtilities.ShimmerBluetoothDialog.EXTRA_DEVICE_NAME;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import androidx.annotation.Nullable;
+import android.os.Handler;
+import android.os.Message;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import androidx.navigation.fragment.NavHostFragment;
+
+import com.shimmerresearch.android.Shimmer;
+import com.shimmerresearch.android.guiUtilities.ShimmerBluetoothDialog;
+import com.shimmerresearch.androidradiodriver.Shimmer3BleAndroidRadioByteCommunication;
+import com.shimmerresearch.androidradiodriver.Shimmer3RAndroidRadioByteCommunication;
+import com.shimmerresearch.androidradiodriver.VerisenseBleAndroidRadioByteCommunication;
+import com.shimmerresearch.bluetooth.ShimmerBluetooth;
+import com.shimmerresearch.driver.CallbackObject;
+import com.shimmerresearch.driver.ObjectCluster;
+import com.shimmerresearch.exceptions.ShimmerException;
+import com.shimmerresearch.shimmer3.communication.SpeedTestProtocol;
+import com.shimmerresearch.verisense.communication.ByteCommunicationListener;
+
+public class FirstFragment extends Fragment {
+ SpeedTestProtocol protocol;
+ Shimmer shimmer;
+ TextView tv;
+ final static int REQUEST_CONNECT_SHIMMER = 2;
+ @Override
+ public View onCreateView(
+ LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState
+ ) {
+ return inflater.inflate(R.layout.fragment_first, container, false);
+ }
+
+ long time = System.currentTimeMillis();
+
+ public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+
+ view.findViewById(R.id.button_first).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Intent pairedDevicesIntent = new Intent(getActivity().getApplicationContext(), ShimmerBluetoothDialog.class);
+ startActivityForResult(pairedDevicesIntent, REQUEST_CONNECT_SHIMMER);
+ }
+ });
+
+ view.findViewById(R.id.button_start).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+
+ protocol.startSpeedTest();
+ }
+ });
+
+ view.findViewById(R.id.button_stop).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+
+ protocol.stopSpeedTest();
+ }
+ });
+
+ view.findViewById(R.id.button_dc).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Thread thread = new Thread(){
+ public void run(){
+
+ if (protocol!=null){
+ try {
+ protocol.disconnect();
+ shimmer.disconnect();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ };
+
+ thread.start();
+ }
+ });
+
+ tv = view.findViewById(R.id.textView);
+ }
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ if (requestCode == 2) { //The devices paired list has returned a result
+ if (resultCode == Activity.RESULT_OK) {
+ //Get the Bluetooth mac address of the selected device:
+ String macAdd = data.getStringExtra(EXTRA_DEVICE_ADDRESS);
+ String deviceName = data.getStringExtra(EXTRA_DEVICE_NAME);
+ shimmer = new Shimmer(mHandler,getActivity().getApplicationContext());
+ VerisenseBleAndroidRadioByteCommunication port = null;
+ if (deviceName.toUpperCase().contains("SHIMMER3-")) {
+ port = new Shimmer3BleAndroidRadioByteCommunication(macAdd);
+ } else if (deviceName.toUpperCase().contains("SHIMMER3R-")){
+ port = new Shimmer3RAndroidRadioByteCommunication(macAdd);
+ } else {
+ port = new VerisenseBleAndroidRadioByteCommunication(macAdd);
+ }
+
+ protocol = new SpeedTestProtocol(port);
+
+ protocol.setListener(new SpeedTestProtocol.SpeedTestResult() {
+ @Override
+ public void onNewResult(String s) {
+ getActivity().runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ if ((System.currentTimeMillis()-time)>1000) {
+ time = System.currentTimeMillis();
+ tv.setText(s);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onConnected() {
+ Toast.makeText(getActivity().getApplicationContext(), "Device Connected", Toast.LENGTH_LONG).show();
+ tv.setText("Device Connected");
+ }
+
+ @Override
+ public void onDisconnected() {
+ Toast.makeText(getActivity().getApplicationContext(), "Device Disconnected", Toast.LENGTH_LONG).show();
+ tv.setText("Device Disconnected");
+ }
+ });
+
+ try {
+
+ protocol.connect();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+
+ /**
+ * Messages from the Shimmer device including sensor data are received here
+ */
+ Handler mHandler = new Handler() {
+
+ @Override
+ public void handleMessage(Message msg) {
+
+ switch (msg.what) {
+ case ShimmerBluetooth.MSG_IDENTIFIER_DATA_PACKET:
+ if ((msg.obj instanceof ObjectCluster)) {
+ }
+ break;
+ case Shimmer.MESSAGE_TOAST:
+ case ShimmerBluetooth.MSG_IDENTIFIER_STATE_CHANGE:
+ ShimmerBluetooth.BT_STATE state = null;
+ if (msg.obj instanceof ObjectCluster) {
+ state = ((ObjectCluster) msg.obj).mState;
+ } else if (msg.obj instanceof CallbackObject) {
+ state = ((CallbackObject) msg.obj).mState;
+ }
+
+ switch (state) {
+ case CONNECTED:
+ break;
+ case CONNECTING:
+ break;
+ case STREAMING:
+ case STREAMING_AND_SDLOGGING:
+ break;
+ case SDLOGGING:
+ break;
+ case DISCONNECTED:
+ Toast.makeText(getActivity().getApplicationContext(), "Device Disconnected", Toast.LENGTH_LONG).show();
+ tv.setText("Device Disconnected");
+ break;
+ }
+ break;
+ }
+ super.handleMessage(msg);
+ }
+ };
+}
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/java/com/shimmerresearch/shimmerspeedtest/MainActivity.java b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/java/com/shimmerresearch/shimmerspeedtest/MainActivity.java
new file mode 100644
index 00000000..ea886a07
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/java/com/shimmerresearch/shimmerspeedtest/MainActivity.java
@@ -0,0 +1,149 @@
+package com.shimmerresearch.shimmerspeedtest;
+
+import android.Manifest;
+import android.annotation.TargetApi;
+import android.content.DialogInterface;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Bundle;
+import com.google.android.material.snackbar.Snackbar;
+
+import androidx.appcompat.app.AlertDialog;
+import androidx.appcompat.app.AppCompatActivity;
+import android.view.View;
+
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+import androidx.navigation.NavController;
+import androidx.navigation.Navigation;
+import androidx.navigation.fragment.NavHostFragment;
+import androidx.navigation.ui.AppBarConfiguration;
+import androidx.navigation.ui.NavigationUI;
+
+import android.view.Menu;
+import android.view.MenuItem;
+
+import com.clj.fastble.BleManager;
+import com.shimmerresearch.androidradiodriver.Shimmer3BleAndroidRadioByteCommunication;
+import com.shimmerresearch.androidradiodriver.Shimmer3RAndroidRadioByteCommunication;
+import com.shimmerresearch.androidradiodriver.ShimmerSerialPortAndroid;
+import com.shimmerresearch.androidradiodriver.VerisenseBleAndroidRadioByteCommunication;
+import com.shimmerresearch.comms.SerialPortByteCommunication;
+import com.shimmerresearch.comms.TestRadioSerialPort;
+import com.shimmerresearch.exceptions.ShimmerException;
+import com.shimmerresearch.shimmer3.communication.SpeedTestProtocol;
+
+public class MainActivity extends AppCompatActivity {
+
+ private AppBarConfiguration appBarConfiguration;
+ private static final int PERMISSION_REQUEST_BACKGROUND_LOCATION = 1;
+ private static final int PERMISSION_REQUEST_FINE_LOCATION = 2;
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_DENIED
+ ||ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.BLUETOOTH_SCAN) == PackageManager.PERMISSION_DENIED)
+ {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
+ {
+ ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.BLUETOOTH_CONNECT,Manifest.permission.BLUETOOTH_SCAN}, 2);
+ } else if(Build.VERSION.SDK_INT >=Build.VERSION_CODES.M){
+ if (this.checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION)
+ == PackageManager.PERMISSION_GRANTED) {
+ if (this.checkSelfPermission(Manifest.permission.ACCESS_BACKGROUND_LOCATION)
+ != PackageManager.PERMISSION_GRANTED) {
+ if (this.shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_BACKGROUND_LOCATION)) {
+ final AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle("This app needs background location access");
+ builder.setMessage("Please grant location access so this app can detect beacons in the background.");
+ builder.setPositiveButton(android.R.string.ok, null);
+ builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
+ @TargetApi(23)
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ requestPermissions(new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION},
+ PERMISSION_REQUEST_BACKGROUND_LOCATION);
+ }
+
+ });
+ builder.show();
+ }
+ else {
+ final AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle("Functionality limited");
+ builder.setMessage("Since background location access has not been granted, this app will not be able to discover beacons in the background. Please go to Settings -> Applications -> Permissions and grant background location access to this app.");
+ builder.setPositiveButton(android.R.string.ok, null);
+ builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
+
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ }
+
+ });
+ builder.show();
+ }
+
+ }
+ }else {
+ if (!this.shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)) {
+ requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION,
+ Manifest.permission.ACCESS_BACKGROUND_LOCATION},
+ PERMISSION_REQUEST_FINE_LOCATION);
+ }
+ }
+
+ }
+
+ }
+
+
+ BleManager.getInstance().init(getApplication());
+ setContentView(R.layout.activity_main);
+ setSupportActionBar(findViewById(R.id.toolbar));
+
+ NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
+ appBarConfiguration = new AppBarConfiguration.Builder(navController.getGraph()).build();
+ NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
+
+ findViewById(R.id.fab).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
+ .setAction("Action", null).show();
+ }
+ });
+
+
+
+
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.menu_main, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // Handle action bar item clicks here. The action bar will
+ // automatically handle clicks on the Home/Up button, so long
+ // as you specify a parent activity in AndroidManifest.xml.
+ int id = item.getItemId();
+ //noinspection SimplifiableIfStatement
+ if (id == R.id.action_settings) {
+ return true;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ public boolean onSupportNavigateUp() {
+ NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
+ return NavigationUI.navigateUp(navController, appBarConfiguration)
+ || super.onSupportNavigateUp();
+ }
+}
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/java/com/shimmerresearch/shimmerspeedtest/SecondFragment.java b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/java/com/shimmerresearch/shimmerspeedtest/SecondFragment.java
new file mode 100644
index 00000000..d3237bd6
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/java/com/shimmerresearch/shimmerspeedtest/SecondFragment.java
@@ -0,0 +1,34 @@
+package com.shimmerresearch.shimmerspeedtest;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.fragment.app.Fragment;
+
+import androidx.navigation.fragment.NavHostFragment;
+
+public class SecondFragment extends Fragment {
+
+ @Override
+ public View onCreateView(
+ LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState
+ ) {
+ return inflater.inflate(R.layout.fragment_second, container, false);
+ }
+
+ public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+
+ view.findViewById(R.id.button_second).setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+
+ }
+ });
+ }
+
+}
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/drawable-v24/ic_launcher_foreground.xml b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 00000000..2b068d11
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/drawable/ic_launcher_background.xml b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 00000000..07d5da9c
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/layout/activity_main.xml b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/layout/activity_main.xml
new file mode 100644
index 00000000..a404c907
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/layout/activity_main.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/layout/content_main.xml b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/layout/content_main.xml
new file mode 100644
index 00000000..e416e1c1
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/layout/content_main.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/layout/fragment_first.xml b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/layout/fragment_first.xml
new file mode 100644
index 00000000..af496e69
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/layout/fragment_first.xml
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/layout/fragment_second.xml b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/layout/fragment_second.xml
new file mode 100644
index 00000000..bd905242
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/layout/fragment_second.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/menu/menu_main.xml b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/menu/menu_main.xml
new file mode 100644
index 00000000..40431a0f
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/menu/menu_main.xml
@@ -0,0 +1,10 @@
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 00000000..eca70cfe
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 00000000..eca70cfe
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-hdpi/ic_launcher.webp b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-hdpi/ic_launcher.webp
new file mode 100644
index 00000000..c209e78e
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-hdpi/ic_launcher.webp differ
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-hdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..b2dfe3d1
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-mdpi/ic_launcher.webp b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-mdpi/ic_launcher.webp
new file mode 100644
index 00000000..4f0f1d64
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-mdpi/ic_launcher.webp differ
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-mdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..62b611da
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-xhdpi/ic_launcher.webp b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-xhdpi/ic_launcher.webp
new file mode 100644
index 00000000..948a3070
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-xhdpi/ic_launcher.webp differ
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..1b9a6956
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-xxhdpi/ic_launcher.webp
new file mode 100644
index 00000000..28d4b77f
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..9287f508
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
new file mode 100644
index 00000000..aa7d6427
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..9126ae37
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/navigation/nav_graph.xml b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/navigation/nav_graph.xml
new file mode 100644
index 00000000..75604683
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/navigation/nav_graph.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/values-land/dimens.xml b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/values-land/dimens.xml
new file mode 100644
index 00000000..22d7f004
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/values-land/dimens.xml
@@ -0,0 +1,3 @@
+
+ 48dp
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/values-night/themes.xml b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/values-night/themes.xml
new file mode 100644
index 00000000..05bee0b0
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/values-night/themes.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/values-w1240dp/dimens.xml b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/values-w1240dp/dimens.xml
new file mode 100644
index 00000000..d73f4a35
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/values-w1240dp/dimens.xml
@@ -0,0 +1,3 @@
+
+ 200dp
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/values-w600dp/dimens.xml b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/values-w600dp/dimens.xml
new file mode 100644
index 00000000..22d7f004
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/values-w600dp/dimens.xml
@@ -0,0 +1,3 @@
+
+ 48dp
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/values/colors.xml b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/values/colors.xml
new file mode 100644
index 00000000..f8c6127d
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+
+
+ #FFBB86FC
+ #FF6200EE
+ #FF3700B3
+ #FF03DAC5
+ #FF018786
+ #FF000000
+ #FFFFFFFF
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/values/dimens.xml b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/values/dimens.xml
new file mode 100644
index 00000000..125df871
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/values/dimens.xml
@@ -0,0 +1,3 @@
+
+ 16dp
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/values/strings.xml b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/values/strings.xml
new file mode 100644
index 00000000..0cc28f9d
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/values/strings.xml
@@ -0,0 +1,12 @@
+
+ shimmerSpeedTest
+ Settings
+
+ First Fragment
+ Second Fragment
+ Next
+ Previous
+
+ Hello first fragment
+ Hello second fragment. Arg: %1$s
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/values/themes.xml b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/values/themes.xml
new file mode 100644
index 00000000..eaa3df2c
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/main/res/values/themes.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/test/java/com/shimmerresearch/shimmerspeedtest/ExampleUnitTest.java b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/test/java/com/shimmerresearch/shimmerspeedtest/ExampleUnitTest.java
new file mode 100644
index 00000000..2d39a837
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/shimmerspeedtest/src/test/java/com/shimmerresearch/shimmerspeedtest/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package com.shimmerresearch.shimmerspeedtest;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/.gitignore b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/.gitignore
new file mode 100644
index 00000000..0b7b04c2
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/.gitignore
@@ -0,0 +1,89 @@
+# Built application files
+*.apk
+*.aar
+*.ap_
+*.aab
+
+# Files for the ART/Dalvik VM
+*.dex
+
+# Java class files
+*.class
+
+# Generated files
+bin/
+gen/
+out/
+# Uncomment the following line in case you need and you don't have the release build type files in your app
+# release/
+
+# Gradle files
+.gradle/
+build/
+
+# Local configuration file (sdk path, etc)
+local.properties
+
+# Proguard folder generated by Eclipse
+proguard/
+
+# Log Files
+*.log
+
+# Android Studio Navigation editor temp files
+.navigation/
+
+# Android Studio captures folder
+captures/
+
+# IntelliJ
+*.iml
+.idea/workspace.xml
+.idea/tasks.xml
+.idea/gradle.xml
+.idea/assetWizardSettings.xml
+.idea/dictionaries
+.idea/libraries
+.idea/jarRepositories.xml
+# Android Studio 3 in .gitignore file.
+.idea/caches
+.idea/modules.xml
+# Comment next line if keeping position of elements in Navigation Editor is relevant for you
+.idea/navEditor.xml
+
+# Keystore files
+# Uncomment the following lines if you do not want to check your keystore files in.
+#*.jks
+#*.keystore
+
+# External native build folder generated in Android Studio 2.2 and later
+.externalNativeBuild
+.cxx/
+
+# Google Services (e.g. APIs or Firebase)
+# google-services.json
+
+# Freeline
+freeline.py
+freeline/
+freeline_project_description.json
+
+# fastlane
+fastlane/report.xml
+fastlane/Preview.html
+fastlane/screenshots
+fastlane/test_output
+fastlane/readme.md
+
+# Version control
+vcs.xml
+
+# lint
+lint/intermediates/
+lint/generated/
+lint/outputs/
+lint/tmp/
+# lint/reports/
+
+# Android Profiling
+*.hprof
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/README.md b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/README.md
new file mode 100644
index 00000000..89ae1fce
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/README.md
@@ -0,0 +1,6 @@
+# Verisense BLE Basic Example
+This example is only applicable for Verisense devices
+
+- Set Verisense macAddress to be used in MainActivity
+- Pair to the Verisense device in Android Bluetooth settings
+- Run the example to Connect, Disconnect, Read Prod and Op Config, Start and Stop Streaming with the device as well as to run data transfer speed test
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/build.gradle b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/build.gradle
new file mode 100644
index 00000000..60e1c7be
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/build.gradle
@@ -0,0 +1,66 @@
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 33
+
+
+
+ defaultConfig {
+ applicationId "shimmerresearch.com.verisenseblebasicexample"
+ minSdkVersion 17
+ targetSdkVersion 33
+ versionCode 1
+ versionName "1.0"
+ multiDexEnabled true
+
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ packagingOptions {
+ exclude 'META-INF/DEPENDENCIES'
+ exclude 'META-INF/LICENSE'
+ exclude 'META-INF/LICENSE.txt'
+ exclude 'META-INF/license.txt'
+ exclude 'META-INF/NOTICE'
+ exclude 'META-INF/NOTICE.txt'
+ exclude 'META-INF/notice.txt'
+ exclude 'META-INF/ASL2.0'
+ }
+
+ configurations.all {
+ resolutionStrategy.force 'com.android.support:support-annotations:25.3.1'
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation project(path: ':ShimmerAndroidInstrumentDriver')
+
+ androidTestImplementation 'com.android.support:support-annotations:25.3.1'
+ //compile(group: 'com.shimmersensing', name: 'ShimmerAndroidInstrumentDriver', version: '3.0.71Beta', ext: 'aar')
+
+ implementation 'com.android.support.constraint:constraint-layout:1.0.2'
+ testImplementation 'junit:junit:4.12'
+ androidTestImplementation 'com.android.support.test:runner:1.0.1'
+ androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
+ implementation 'com.android.support.constraint:constraint-layout:1.0.2'
+ testImplementation 'junit:junit:4.12'
+ implementation 'com.android.support:multidex:1.0.3'
+}
+repositories {
+ mavenCentral()
+}
diff --git a/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/proguard-rules.pro b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/proguard-rules.pro
new file mode 100644
index 00000000..f1b42451
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/androidTest/java/shimmerresearch/com/verisenseblebasicexample/ExampleInstrumentedTest.java b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/androidTest/java/shimmerresearch/com/verisenseblebasicexample/ExampleInstrumentedTest.java
new file mode 100644
index 00000000..6a9b6128
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/androidTest/java/shimmerresearch/com/verisenseblebasicexample/ExampleInstrumentedTest.java
@@ -0,0 +1,26 @@
+package shimmerresearch.com.verisenseblebasicexample;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() throws Exception {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getTargetContext();
+
+ assertEquals("shimmerresearch.com.shimmerbasicexample", appContext.getPackageName());
+ }
+}
diff --git a/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/AndroidManifest.xml b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..d4db9a8e
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/AndroidManifest.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/java/shimmerresearch/com/verisenseblebasicexample/MainActivity.java b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/java/shimmerresearch/com/verisenseblebasicexample/MainActivity.java
new file mode 100644
index 00000000..e727a057
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/java/shimmerresearch/com/verisenseblebasicexample/MainActivity.java
@@ -0,0 +1,310 @@
+package shimmerresearch.com.verisenseblebasicexample;
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.view.View;
+import android.widget.Toast;
+
+import com.shimmerresearch.android.Shimmer;
+import com.shimmerresearch.android.VerisenseDeviceAndroid;
+import com.shimmerresearch.android.guiUtilities.ShimmerBluetoothDialog;
+import com.shimmerresearch.androidradiodriver.VerisenseBleAndroidRadioByteCommunication;
+import com.shimmerresearch.bluetooth.ShimmerBluetooth;
+import com.shimmerresearch.driver.CallbackObject;
+import com.shimmerresearch.driver.Configuration;
+import com.shimmerresearch.driver.FormatCluster;
+import com.shimmerresearch.driver.ObjectCluster;
+import com.shimmerresearch.exceptions.ShimmerException;
+
+import com.shimmerresearch.verisense.communication.VerisenseProtocolByteCommunication;
+import com.clj.fastble.BleManager;
+import com.shimmerresearch.verisense.sensors.SensorLIS2DW12;
+
+import java.io.IOException;
+import java.util.Collection;
+
+import static com.shimmerresearch.android.guiUtilities.ShimmerBluetoothDialog.EXTRA_DEVICE_ADDRESS;
+import static com.shimmerresearch.android.guiUtilities.ShimmerBluetoothDialog.REQUEST_CONNECT_SHIMMER;
+
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.ContextCompat;
+
+public class MainActivity extends Activity {
+
+ private final static String LOG_TAG = "VeriBLEBasicExample";
+ String macAddress = "C0:04:19:85:9A:D5";
+
+ VerisenseBleAndroidRadioByteCommunication radio1 = new VerisenseBleAndroidRadioByteCommunication(macAddress);
+ //AndroidBleRadioByteCommunication radio1 = new AndroidBleRadioByteCommunication("C9:61:17:53:74:02");
+ VerisenseProtocolByteCommunication protocol1 = new VerisenseProtocolByteCommunication(radio1);
+ VerisenseDeviceAndroid device1;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ int permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_CONNECT);
+ boolean permissionGranted = true;
+ {
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH_SCAN);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ permissionCheck = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
+ if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
+ permissionGranted = false;
+ }
+ }
+ if (!permissionGranted) {
+ // Should we show an explanation?
+ ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.BLUETOOTH_CONNECT,Manifest.permission.BLUETOOTH_SCAN,Manifest.permission.ACCESS_COARSE_LOCATION,Manifest.permission.ACCESS_FINE_LOCATION}, 110);
+
+ }
+
+ }
+
+ public void connectDevice(View v) {
+
+ Intent pairedDevicesIntent = new Intent(this.getApplicationContext(), ShimmerBluetoothDialog.class);
+ startActivityForResult(pairedDevicesIntent, REQUEST_CONNECT_SHIMMER);
+
+ }
+
+ public void disconnectDevice(View v) {
+ Thread thread = new Thread(){
+ public void run(){
+ try {
+ device1.disconnect();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+
+ thread.start();
+
+
+ }
+
+ public void readOpConfig(View v) {
+ Thread thread = new Thread(){
+ public void run(){
+ try {
+ protocol1.readOperationalConfig();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+
+ thread.start();
+
+
+
+
+ }
+
+ public void readProdConfig(View v) {
+ Thread thread = new Thread(){
+ public void run(){
+ try {
+ protocol1.readProductionConfig();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+
+ thread.start();
+
+ }
+
+ public void startStreaming(View v) throws InterruptedException, IOException, ShimmerException {
+ Thread thread = new Thread(){
+ public void run(){
+ try {
+ protocol1.startStreaming();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+
+ thread.start();
+ }
+
+ public void stopStreaming(View v) throws IOException, ShimmerException {
+ Thread thread = new Thread(){
+ public void run(){
+ try {
+ protocol1.stopStreaming();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+
+ thread.start();
+
+ }
+ public void startSpeedTest(View v) throws IOException, ShimmerException {
+ Thread thread = new Thread(){
+ public void run(){
+ try {
+ protocol1.startSpeedTest();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+
+ thread.start();
+
+ }
+ public void stopSpeedTest(View v) throws IOException, ShimmerException {
+ Thread thread = new Thread(){
+ public void run(){
+ try {
+ protocol1.stopSpeedTest();
+ } catch (ShimmerException e) {
+ e.printStackTrace();
+ }
+ }
+ };
+
+ thread.start();
+
+ }
+
+
+ /**
+ * Messages from the Shimmer device including sensor data are received here
+ */
+ Handler mHandler = new Handler() {
+
+ @Override
+ public void handleMessage(Message msg) {
+
+ switch (msg.what) {
+ case ShimmerBluetooth.MSG_IDENTIFIER_DATA_PACKET:
+ if ((msg.obj instanceof ObjectCluster)) {
+
+ //Print data to Logcat
+ ObjectCluster objectCluster = (ObjectCluster) msg.obj;
+
+ //Retrieve all possible formats for the current sensor device:
+ Collection allFormats = objectCluster.getCollectionOfFormatClusters(Configuration.Shimmer3.ObjectClusterSensorName.TIMESTAMP);
+ FormatCluster timeStampCluster = ((FormatCluster)ObjectCluster.returnFormatCluster(allFormats,"CAL"));
+ double timeStampData = timeStampCluster.mData;
+ Log.i(LOG_TAG, "Time Stamp: " + timeStampData);
+ allFormats = objectCluster.getCollectionOfFormatClusters(SensorLIS2DW12.ObjectClusterSensorName.LIS2DW12_ACC_X);
+ FormatCluster accelXCluster = ((FormatCluster)ObjectCluster.returnFormatCluster(allFormats,"CAL"));
+ if (accelXCluster!=null) {
+ double accelXData = accelXCluster.mData;
+ Log.i(LOG_TAG, "Accel X: " + accelXData);
+ }
+ allFormats = objectCluster.getCollectionOfFormatClusters(SensorLIS2DW12.ObjectClusterSensorName.LIS2DW12_ACC_Y);
+ FormatCluster accelYCluster = ((FormatCluster)ObjectCluster.returnFormatCluster(allFormats,"CAL"));
+ if (accelXCluster!=null) {
+ double accelYData = accelYCluster.mData;
+ Log.i(LOG_TAG, "Accel Y: " + accelYData);
+ }
+ allFormats = objectCluster.getCollectionOfFormatClusters(SensorLIS2DW12.ObjectClusterSensorName.LIS2DW12_ACC_Z);
+ FormatCluster accelZCluster = ((FormatCluster)ObjectCluster.returnFormatCluster(allFormats,"CAL"));
+ if (accelZCluster!=null) {
+ double accelZData = accelZCluster.mData;
+ Log.i(LOG_TAG, "Accel Z: " + accelZData);
+ }
+
+ }
+ break;
+ case Shimmer.MESSAGE_TOAST:
+ /** Toast messages sent from {@link Shimmer} are received here. E.g. device xxxx now streaming.
+ * Note that display of these Toast messages is done automatically in the Handler in {@link com.shimmerresearch.android.shimmerService.ShimmerService} */
+ Toast.makeText(getApplicationContext(), msg.getData().getString(Shimmer.TOAST), Toast.LENGTH_SHORT).show();
+ break;
+ case ShimmerBluetooth.MSG_IDENTIFIER_STATE_CHANGE:
+ ShimmerBluetooth.BT_STATE state = null;
+ String macAddress = "";
+
+ if (msg.obj instanceof ObjectCluster) {
+ state = ((ObjectCluster) msg.obj).mState;
+ macAddress = ((ObjectCluster) msg.obj).getMacAddress();
+ } else if (msg.obj instanceof CallbackObject) {
+ state = ((CallbackObject) msg.obj).mState;
+ macAddress = ((CallbackObject) msg.obj).mBluetoothAddress;
+ }
+
+ switch (state) {
+ case CONNECTED:
+ break;
+ case CONNECTING:
+ break;
+ case STREAMING:
+ break;
+ case STREAMING_AND_SDLOGGING:
+ break;
+ case SDLOGGING:
+ break;
+ case DISCONNECTED:
+ break;
+ }
+ break;
+ }
+ super.handleMessage(msg);
+ }
+ };
+
+ /**
+ * Get the result from the paired devices dialog
+ * @param requestCode
+ * @param resultCode
+ * @param data
+ */
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if(requestCode == REQUEST_CONNECT_SHIMMER) {
+ if (resultCode == Activity.RESULT_OK) {
+ BleManager.getInstance().init(getApplication());
+ device1 = new VerisenseDeviceAndroid(mHandler);
+ //Get the Bluetooth mac address of the selected device:
+ String macAdd = data.getStringExtra(EXTRA_DEVICE_ADDRESS);
+ radio1 = new VerisenseBleAndroidRadioByteCommunication(macAdd);
+ protocol1 = new VerisenseProtocolByteCommunication(radio1);
+
+ Thread thread = new Thread(){
+ public void run(){
+
+ device1.setProtocol(Configuration.COMMUNICATION_TYPE.BLUETOOTH, protocol1);
+ try {
+ device1.connect();
+ } catch (ShimmerException e1) {
+ // TODO Auto-generated catch block
+ e1.printStackTrace();
+ }
+
+ }
+ };
+
+ thread.start();
+ }
+
+ }
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+
+
+}
diff --git a/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/drawable-v24/ic_launcher_foreground.xml b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 00000000..c7bd21db
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/drawable/ic_launcher_background.xml b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 00000000..d5fccc53
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/layout/activity_main.xml b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/layout/activity_main.xml
new file mode 100644
index 00000000..b56c99e0
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/layout/activity_main.xml
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 00000000..eca70cfe
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 00000000..eca70cfe
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-hdpi/ic_launcher.png b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 00000000..a2f59082
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-hdpi/ic_launcher_round.png b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 00000000..1b523998
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-mdpi/ic_launcher.png b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 00000000..ff10afd6
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-mdpi/ic_launcher_round.png b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 00000000..115a4c76
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-xhdpi/ic_launcher.png b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 00000000..dcd3cd80
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 00000000..459ca609
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-xxhdpi/ic_launcher.png b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 00000000..8ca12fe0
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 00000000..8e19b410
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 00000000..b824ebdd
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 00000000..4c19a13c
Binary files /dev/null and b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/values/colors.xml b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/values/colors.xml
new file mode 100644
index 00000000..3ab3e9cb
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/values/colors.xml
@@ -0,0 +1,6 @@
+
+
+ #3F51B5
+ #303F9F
+ #FF4081
+
diff --git a/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/values/strings.xml b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/values/strings.xml
new file mode 100644
index 00000000..39930f75
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ Verisense BLE Basic Example
+
diff --git a/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/values/styles.xml b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/values/styles.xml
new file mode 100644
index 00000000..ff6c9d2c
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/main/res/values/styles.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
diff --git a/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/test/java/com/shimmerresearch/verisenseblebasicexample/ExampleUnitTest.java b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/test/java/com/shimmerresearch/verisenseblebasicexample/ExampleUnitTest.java
new file mode 100644
index 00000000..9ddf89d1
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/test/java/com/shimmerresearch/verisenseblebasicexample/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package com.shimmerresearch.verisenseblebasicexample;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() throws Exception {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/test/java/shimmerresearch/com/verisenseblebasicexample/ExampleUnitTest.java b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/test/java/shimmerresearch/com/verisenseblebasicexample/ExampleUnitTest.java
new file mode 100644
index 00000000..ffd038c0
--- /dev/null
+++ b/ShimmerAndroidInstrumentDriver/verisenseBLEBasicExample/src/test/java/shimmerresearch/com/verisenseblebasicexample/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package shimmerresearch.com.verisenseblebasicexample;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() throws Exception {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file