Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,17 @@ public ShimmerDevice getShimmerDeviceBtConnected(String connectionHandle){
return shimmerDevice;
}

public boolean checkIfAlgoEnabledonAnyConnectedDevice(String algoName) {
for (String comPort:mMapOfBtConnectedShimmers.keySet()) {
ShimmerDevice device = getShimmerDeviceBtConnected(comPort);
boolean algoenabled = device.isAlgorithmEnabled(algoName);
if(algoenabled) {
return true;
}
}
return false;
}

public ShimmerDevice getShimmerDeviceBtConnectedFromMac(String macAddress){
Iterator<ShimmerDevice> iterator = mMapOfBtConnectedShimmers.values().iterator();
while(iterator.hasNext()){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

This is a BlackMan-Windowed-Sinc Filter. Algorithm for calculating
filter coefficients from "The Scientist and Engineer's Guide to Digital Signal Processing",
copyright ©1997-1998 by Steven W. Smith.
copyright �1997-1998 by Steven W. Smith.
For more information visit the book's website at: www.DSPguide.com.

* Copyright (c) 2010 - 2014, Shimmer Research, Ltd.
Expand Down Expand Up @@ -64,7 +64,7 @@
*
This is a BlackMan-Windowed-Sinc Filter. Algorithm for calculating
filter coefficients from "The Scientist and Engineer's Guide to Digital Signal Processing",
copyright ©1997-1998 by Steven W. Smith.
copyright ©1997-1998 by Steven W. Smith.
For more information visit the book's website at: www.DSPguide.com.
*
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

/** References
*
*[1] Angkoon Phinyomark, Pornchai Phukpattaranont, Chusak Limsakul (2012) Feature Reduction and Selection for EMG Signal Classification Elsevier, Expert Systems with Applications 39, P74207431
*[1] Angkoon Phinyomark, Pornchai Phukpattaranont, Chusak Limsakul (2012) Feature Reduction and Selection for EMG Signal Classification Elsevier, Expert Systems with Applications 39, P7420 7431
*[2] http://luscinia.sourceforge.net/page26/page35/page35.html
* */

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.util.Map.Entry;
import java.util.Random;
import java.util.TimeZone;
import java.util.regex.Pattern;

import org.apache.commons.lang3.ArrayUtils;

Expand Down Expand Up @@ -938,7 +939,19 @@ public int compare(Entry<Double, Double> o1,
}
return new ArrayList<Double>(sortedMap.keySet());
}

// Regex breakdown:
// ^ : Start of string
// [0-9a-fA-F]{2} : Two hex characters
// ( (:[0-9a-fA-F]{2}){5} | ([0-9a-fA-F]{2}){5} ) : Either 5 groups preceded by colons OR 5 groups with nothing
// $ : End of string
private static final String MAC_REGEX = "^([0-9a-fA-F]{2})((:[0-9a-fA-F]{2}){5}|([0-9a-fA-F]{2}){5})$";
private static final Pattern MAC_PATTERN = Pattern.compile(MAC_REGEX);

public static boolean isValidMacAddress(String mac) {
if (mac == null) return false;
return MAC_PATTERN.matcher(mac).matches();
}

public static boolean isValidMac(String mac) {
if(mac==null){
return false;
Expand All @@ -954,7 +967,7 @@ public static boolean isValidMac(String mac) {

return true;
}

public static String getDayString(int dayIndex) {
switch (dayIndex) {
case Calendar.SUNDAY:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ public double[] calibratePressureSensorData(double UP, double UT){
double adc_T = UT;
double adc_P = UP;

// Returns temperature in DegC, double precision. Output value of 51.23 equals 51.23 DegC.
// Returns temperature in DegC, double precision. Output value of 51.23 equals 51.23 DegC.
// t_fine carries fine temperature as global value
double var1 = ((adc_T)/16384.0 - dig_T1/1024.0) * dig_T2;
double var2 = (((adc_T)/131072.0 - dig_T1/8192.0) * (adc_T/131072.0 - dig_T1/8192.0)) * dig_T3;
Expand All @@ -131,7 +131,7 @@ public double[] calibratePressureSensorData(double UP, double UT){
// double fTemp = T * 1.8 + 32; // Fahrenheit
// T = T/100.0;

// Returns pressure in Pa as double. Output value of 96386.2 equals 96386.2 Pa = 963.862 hPa
// Returns pressure in Pa as double. Output value of 96386.2 equals 96386.2 Pa = 963.862 hPa
var1 = (t_fine/2.0) - 64000.0;
var2 = var1 * var1 * dig_P6 / 32768.0;
var2 = var2 + var1 * dig_P5 * 2.0;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package com.shimmerresearch.tools;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import com.shimmerresearch.driver.Configuration.Shimmer3.DerivedSensorsBitMask;

public class DerivedSensorParser {
private static final Map<Integer, String> SENSOR_MAP = new LinkedHashMap<>();

static {
SENSOR_MAP.put(DerivedSensorsBitMask.RES_AMP, "RES_AMP");
SENSOR_MAP.put(DerivedSensorsBitMask.SKIN_TEMP, "SKIN_TEMP");
SENSOR_MAP.put(DerivedSensorsBitMask.PPG_12_13, "PPG_12_13");
SENSOR_MAP.put(DerivedSensorsBitMask.PPG1_12_13, "PPG1_12_13");
SENSOR_MAP.put(DerivedSensorsBitMask.PPG2_1_14, "PPG2_1_14");
SENSOR_MAP.put(DerivedSensorsBitMask.PPG_TO_HR_12_13, "PPG_TO_HR_12_13");
SENSOR_MAP.put(DerivedSensorsBitMask.PPG_TO_HR1_12_13, "PPG_TO_HR1_12_13");
SENSOR_MAP.put(DerivedSensorsBitMask.PPG_TO_HR2_1_14, "PPG_TO_HR2_1_14");
SENSOR_MAP.put(DerivedSensorsBitMask.ACTIVITY_MODULE, "ACTIVITY_MODULE");
SENSOR_MAP.put(DerivedSensorsBitMask.GSR_METRICS_GENERAL, "GSR_METRICS_GENERAL");
SENSOR_MAP.put(DerivedSensorsBitMask.ECG2HR_HRV_FREQ_DOMAIN, "ECG2HR_HRV_FREQ_DOMAIN");
SENSOR_MAP.put(DerivedSensorsBitMask.ECG2HR_HRV_TIME_DOMAIN, "ECG2HR_HRV_TIME_DOMAIN");
SENSOR_MAP.put(DerivedSensorsBitMask.ECG2HR_CHIP2_CH2, "ECG2HR_CHIP2_CH2");
SENSOR_MAP.put(DerivedSensorsBitMask.ECG2HR_CHIP2_CH1, "ECG2HR_CHIP2_CH1");
SENSOR_MAP.put(DerivedSensorsBitMask.ECG2HR_CHIP1_CH2, "ECG2HR_CHIP1_CH2");
SENSOR_MAP.put(DerivedSensorsBitMask.ECG2HR_CHIP1_CH1, "ECG2HR_CHIP1_CH1");
SENSOR_MAP.put(DerivedSensorsBitMask.ORIENTATION_9DOF_WR_QUAT, "ORIENTATION_9DOF_WR_QUAT");
SENSOR_MAP.put(DerivedSensorsBitMask.ORIENTATION_9DOF_WR_EULER, "ORIENTATION_9DOF_WR_EULER");
SENSOR_MAP.put(DerivedSensorsBitMask.ORIENTATION_6DOF_WR_QUAT, "ORIENTATION_6DOF_WR_QUAT");
SENSOR_MAP.put(DerivedSensorsBitMask.ORIENTATION_6DOF_WR_EULER, "ORIENTATION_6DOF_WR_EULER");
SENSOR_MAP.put(DerivedSensorsBitMask.ORIENTATION_9DOF_LN_QUAT, "ORIENTATION_9DOF_LN_QUAT");
SENSOR_MAP.put(DerivedSensorsBitMask.ORIENTATION_9DOF_LN_EULER, "ORIENTATION_9DOF_LN_EULER");
SENSOR_MAP.put(DerivedSensorsBitMask.ORIENTATION_6DOF_LN_QUAT, "ORIENTATION_6DOF_LN_QUAT");
SENSOR_MAP.put(DerivedSensorsBitMask.ORIENTATION_6DOF_LN_EULER, "ORIENTATION_6DOF_LN_EULER");
SENSOR_MAP.put(DerivedSensorsBitMask.EMG_PROCESSING_CHAN2, "EMG_PROCESSING_CHAN2");
SENSOR_MAP.put(DerivedSensorsBitMask.EMG_PROCESSING_CHAN1, "EMG_PROCESSING_CHAN1");
SENSOR_MAP.put(DerivedSensorsBitMask.GSR_BASELINE, "GSR_BASELINE");
SENSOR_MAP.put(DerivedSensorsBitMask.GSR_METRICS_TREND_PEAK, "GSR_METRICS_TREND_PEAK");
SENSOR_MAP.put(DerivedSensorsBitMask.GAIT_MODULE, "GAIT_MODULE");
SENSOR_MAP.put(DerivedSensorsBitMask.GYRO_ON_THE_FLY_CAL, "GYRO_ON_THE_FLY_CAL");
}

/**
* Parses the hex string and returns a list of enabled sensor names.
* @param hexInput String format "hx:0000000020440000"
*/
public static List<String> parseHex(String hexInput) {
String cleanHex = hexInput.replace("hx:", "");
// Using Long because the input is 64-bit, even though constants are 32-bit
long bitmask = Long.parseUnsignedLong(cleanHex, 16);

List<String> enabledSensors = new ArrayList<>();

for (Map.Entry<Integer, String> entry : SENSOR_MAP.entrySet()) {
// Check if the specific bit is set
if ((bitmask & entry.getKey()) != 0) {
enabledSensors.add(entry.getValue());
}
}
return enabledSensors;
}

public static void main(String[] args) {
// String containing multiple CSV hex values
String csvInput = "hx:0000000000000000,"
+ "hx:0000000000000004,"
+ "hx:0000000020440000,"
+ "hx:0000000020000000,"
+ "hx:0000000020000024,"
+ "hx:0000000000000024,"
+ "hx:000000000000F000,"
+ "hx:0000000000008000,"
+ "hx:0000000020000004,"
+ "hx:0000000008000224,"
+ "hx:0000000001000000,"
+ "hx:0000000020110000";

// Split by comma
String[] hexValues = csvInput.split(",");

System.out.println(String.format("%-25s | %s", "Hex Value", "Enabled Sensors"));
System.out.println("------------------------------------------------------------");

for (String hex : hexValues) {
List<String> results = parseHex(hex);
String sensors = results.isEmpty() ? "None" : String.join(", ", results);

System.out.println(String.format("%-25s | %s", hex.trim(), sensors));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.shimmerresearch.tools;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class EnabledSensorParser {

private static final Map<Integer, String> SENSOR_MAP = new LinkedHashMap<>();

static {
// Motion
SENSOR_MAP.put(0x80, "SENSOR_ACCEL");
SENSOR_MAP.put(0x1000, "SENSOR_DACCEL");
SENSOR_MAP.put(0x40, "SENSOR_GYRO");
SENSOR_MAP.put(0x20, "SENSOR_MAG");
SENSOR_MAP.put(0x400000, "SENSOR_ALT_ACCEL");
SENSOR_MAP.put(0x200000, "SENSOR_ALT_MAG");

// Biopotential / EXG
SENSOR_MAP.put(0x10, "SENSOR_ECG / EXG1_24BIT");
SENSOR_MAP.put(0x08, "SENSOR_EMG / EXG2_24BIT");
SENSOR_MAP.put(0x100000, "SENSOR_EXG1_16BIT");
SENSOR_MAP.put(0x080000, "SENSOR_EXG2_16BIT");

// Analog / ADC
SENSOR_MAP.put(0x02, "SENSOR_EXT_ADC_A7");
SENSOR_MAP.put(0x01, "SENSOR_EXT_ADC_A6");
SENSOR_MAP.put(0x0800, "SENSOR_EXT_ADC_A15");
SENSOR_MAP.put(0x0400, "SENSOR_INT_ADC_A1");
SENSOR_MAP.put(0x0200, "SENSOR_INT_ADC_A12");
SENSOR_MAP.put(0x0100, "SENSOR_INT_ADC_A13");
SENSOR_MAP.put(0x800000, "SENSOR_INT_ADC_A14");

// Other
SENSOR_MAP.put(0x04, "SENSOR_GSR");
SENSOR_MAP.put(0x40000, "SENSOR_BMPX80");
SENSOR_MAP.put(0x8000, "SENSOR_BRIDGE_AMP");
SENSOR_MAP.put(0x4000, "SENSOR_HEART");
SENSOR_MAP.put(0x2000, "SENSOR_BATT");
}

public static List<String> parseHex(String hexInput) {
String cleanHex = hexInput.replace("hx:", "");
long bitmask = Long.parseUnsignedLong(cleanHex, 16);

List<String> enabledSensors = new ArrayList<>();

for (Map.Entry<Integer, String> entry : SENSOR_MAP.entrySet()) {
if ((bitmask & entry.getKey()) != 0) {
enabledSensors.add(entry.getValue());
}
}
return enabledSensors;
}

public static void main(String[] args) {

String csvInput ="hx:0000000000000104,"
+ "hx:0000000000000004,"
+ "hx:00000000000031E4,"
+ "hx:00000000000439E7,"
+ "hx:00000000000010E0,"
+ "hx:0000000000000010,"
+ "hx:0000000000001104,"
+ "hx:0000000000000018,"
+ "hx:0000000000000098,"
+ "hx:00000000000020E0";

String[] hexValues = csvInput.split(",");

System.out.println(String.format("%-25s | %s", "Hex Value", "Enabled Sensors"));
System.out.println("------------------------------------------------------------");

for (String hex : hexValues) {
List<String> results = parseHex(hex);
String sensors = results.isEmpty() ? "None" : String.join(", ", results);
System.out.println(String.format("%-25s | %s", hex.trim(), sensors));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,62 @@

public class API_00007_UtilShimmerTest {

@Test
public void testValidMacWithColons() {
// Upper case
assertTrue("Should be valid: Uppercase with colons",
UtilShimmer.isValidMacAddress("00:1A:2B:3C:4D:5E"));
// Lower case
assertTrue("Should be valid: Lowercase with colons",
UtilShimmer.isValidMacAddress("00:1a:2b:3c:4d:5e"));
}

@Test
public void testValidMacWithoutColons() {
// Pure Hex string
assertTrue("Should be valid: Plain hex string",
UtilShimmer.isValidMacAddress("001A2B3C4D5E"));
assertTrue("Should be valid: Lowercase plain hex",
UtilShimmer.isValidMacAddress("001a2b3c4d5e"));
}

@Test
public void testInvalidCharacters() {
// Contains 'G' (non-hex)
assertFalse("Should be invalid: Contains non-hex character G",
UtilShimmer.isValidMacAddress("00:1A:2B:3C:4D:5G"));
// Contains special characters
assertFalse("Should be invalid: Contains symbols",
UtilShimmer.isValidMacAddress("00:1A:2B:3C:4D:5#"));
}

@Test
public void testInvalidLength() {
// Too short
assertFalse("Should be invalid: Too short",
UtilShimmer.isValidMacAddress("00:1A:2B"));
// Too long
assertFalse("Should be invalid: Too long",
UtilShimmer.isValidMacAddress("00:1A:2B:3C:4D:5E:6F"));
}

@Test
public void testMixedFormats() {
// Cannot mix "no-colon" with "colons" halfway through
assertFalse("Should be invalid: Inconsistent colon usage",
UtilShimmer.isValidMacAddress("001A2B:3C:4D:5E"));
}

@Test
public void testEdgeCases() {
assertFalse("Should be invalid: Null input",
UtilShimmer.isValidMacAddress(null));
assertFalse("Should be invalid: Empty string",
UtilShimmer.isValidMacAddress(""));
assertFalse("Should be invalid: Spaces included",
UtilShimmer.isValidMacAddress("00 1A 2B 3C 4D 5E"));
}

@Test
public void testRoundZeroDecimalPoints() {
assertTrue(UtilShimmer.round(5.567, 0) == 6.0);
Expand Down
1 change: 1 addition & 0 deletions ShimmerDriverPC/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ repositories {
test {
// this test requires a physical Shimmer2r to run
exclude '**/API_00001_ShimmerPC_GeneralBluetoothShimmer2R.class'
exclude '**/API_0000X_ByteCommunicationShimmer3lns0_16_11_w_sd_only.class'
}

publishing {
Expand Down
Loading