Skip to content

Commit 4ccca00

Browse files
committed
Support Ganglion v3 firmware detection
1 parent b2a8839 commit 4ccca00

10 files changed

Lines changed: 169 additions & 111 deletions

File tree

Lines changed: 67 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,128 +1,128 @@
11
package openbci_gui_helpers;
22

3-
import java.io.BufferedReader;
43
import java.io.File;
54
import java.io.InputStream;
6-
import java.io.InputStreamReader;
7-
import java.lang.reflect.Type;
8-
import java.nio.charset.StandardCharsets;
95
import java.nio.file.Files;
10-
import java.nio.file.Paths;
11-
import java.nio.file.Path;
12-
import java.util.Map;
13-
import java.util.stream.Collectors;
6+
import java.util.ArrayList;
147

158
import org.apache.commons.lang3.SystemUtils;
169

1710
import com.google.gson.Gson;
18-
import com.google.gson.reflect.TypeToken;
1911
import com.sun.jna.Library;
2012
import com.sun.jna.Native;
2113

22-
public class GUIHelper
23-
{
24-
private interface DllInterface extends Library
25-
{
26-
int scan_for_ganglions (String serial_port, int timeout_sec, byte[] output, int[] output_len);
14+
public class GUIHelper {
15+
public class GanglionDevice {
16+
public int firmware_version;
17+
public String identifier;
18+
public String mac_address;
2719
}
2820

29-
private interface DllNativeInterface extends Library
30-
{
31-
int scan_for_ganglions (int timeout_sec, byte[] output, int[] output_len);
21+
private interface DllInterface extends Library {
22+
int scan_for_ganglions(String serial_port, int timeout_sec, byte[] output, int[] output_len);
23+
}
24+
25+
private interface DllNativeInterface extends Library {
26+
int scan_for_ganglions(int timeout_sec, byte[] output, int[] output_len);
3227
}
3328

3429
private static DllInterface instance;
3530
private static DllNativeInterface instance_native;
36-
private static final String VERSION = "2.0.1";
31+
private static final String VERSION = "3.0.0";
3732

38-
static
39-
{
33+
static {
4034
System.out.println("OpenBCI_GUI_Helpers Version: " + VERSION);
4135

4236
String lib_name = "libGanglionScan.so";
4337
String lib_native_name = "libGanglionNativeScan.so";
44-
if (SystemUtils.IS_OS_WINDOWS)
45-
{
38+
if (SystemUtils.IS_OS_WINDOWS) {
4639
lib_name = "GanglionScan.dll";
4740
lib_native_name = "GanglionNativeScan.dll";
4841

49-
} else if (SystemUtils.IS_OS_MAC)
50-
{
42+
} else if (SystemUtils.IS_OS_MAC) {
5143
lib_name = "libGanglionScan.dylib";
5244
lib_native_name = "libGanglionNativeScan.dylib";
5345
}
5446

5547
// need to extract libraries from jar
56-
String lib_path = unpack_from_jar (lib_name);
57-
String lib_native_path = unpack_from_jar (lib_native_name);
48+
String lib_path = unpack_from_jar(lib_name);
49+
String lib_native_path = unpack_from_jar(lib_native_name);
5850

59-
instance = (DllInterface) Native.load (lib_path, DllInterface.class);
60-
instance_native = (DllNativeInterface) Native.load (lib_native_path, DllNativeInterface.class);
51+
instance = (DllInterface) Native.load(lib_path, DllInterface.class);
52+
instance_native = (DllNativeInterface) Native.load(lib_native_path, DllNativeInterface.class);
6153
}
6254

63-
private static String unpack_from_jar (String lib_name)
64-
{
55+
private static String unpack_from_jar(String lib_name) {
6556
File file = null;
6657
InputStream link = null;
67-
try
68-
{
69-
file = new File (lib_name);
70-
if (file.exists ())
71-
file.delete ();
72-
link = (GUIHelper.class.getResourceAsStream (lib_name));
58+
try {
59+
file = new File(lib_name);
60+
if (file.exists())
61+
file.delete();
62+
link = (GUIHelper.class.getResourceAsStream(lib_name));
7363
if (SystemUtils.IS_OS_MAC) {
7464
String jarPath = GUIHelper.class.getProtectionDomain().getCodeSource().getLocation().getPath();
7565
File jarFile = new File(jarPath);
7666
String libPathString = jarFile.getParentFile().getAbsolutePath() + File.separator + lib_name;
7767
return libPathString;
7868
} else {
79-
Files.copy (link, file.getAbsoluteFile ().toPath ());
69+
Files.copy(link, file.getAbsoluteFile().toPath());
8070
}
8171
return file.getAbsolutePath();
82-
} catch (Exception io)
83-
{
84-
io.printStackTrace ();
72+
} catch (Exception io) {
73+
io.printStackTrace();
8574
System.err.println("native library: " + lib_name + " is not found in jar file");
8675
System.err.println("file absolute to path: " + file.getAbsoluteFile().toPath());
8776
System.err.println("file get absolute path: " + file.getAbsolutePath());
8877
return "";
8978
}
9079
}
9180

92-
public static Map<String, String> scan_for_ganglions (String port_name, int timeout_sec) throws GanglionError
93-
{
81+
public static GanglionDevice[] scan_for_ganglions(String port_name, int timeout_sec) throws GanglionError {
9482
int[] len = new int[1];
9583
byte[] output_json = new byte[10240];
96-
int ec = instance.scan_for_ganglions (port_name, timeout_sec, output_json, len);
97-
if (ec != GanglionExitCodes.STATUS_OK.get_code ())
98-
{
99-
throw new GanglionError ("Error in scan for ganglions", ec);
84+
85+
int ec = instance.scan_for_ganglions(port_name, timeout_sec, output_json, len);
86+
if (ec != GanglionExitCodes.STATUS_OK.get_code()) {
87+
throw new GanglionError("Error in scan for ganglions", ec);
10088
}
101-
String json = new String (output_json, 0, len[0]);
102-
Gson gson = new Gson ();
103-
Type type = new TypeToken<Map<String, String>> ()
104-
{
105-
}.getType ();
106-
Map<String, String> map = gson.fromJson (json, type);
107-
return map;
89+
90+
String json = new String(output_json, 0, len[0]);
91+
Gson gson = new Gson();
92+
93+
GanglionDevice[] devices = gson.fromJson(json, GanglionDevice[].class);
94+
95+
ArrayList<GanglionDevice> uniqueDevices = new ArrayList<GanglionDevice>();
96+
for (GanglionDevice device : devices) {
97+
if (!uniqueDevices.stream().anyMatch(entry -> entry.mac_address.equals(device.mac_address))) {
98+
uniqueDevices.add(device);
99+
}
100+
}
101+
102+
return uniqueDevices.toArray(new GanglionDevice[uniqueDevices.size()]);
108103
}
109104

110-
public static Map<String, String> scan_for_ganglions (int timeout_sec) throws GanglionError
111-
{
105+
public static GanglionDevice[] scan_for_ganglions(int timeout_sec) throws GanglionError {
112106
int[] len = new int[1];
113107
byte[] output_json = new byte[10240];
114-
int ec = instance_native.scan_for_ganglions (timeout_sec, output_json, len);
115-
if (ec != GanglionExitCodes.STATUS_OK.get_code ())
116-
{
117-
throw new GanglionError ("Error in scan for ganglions", ec);
108+
109+
int ec = instance_native.scan_for_ganglions(timeout_sec, output_json, len);
110+
if (ec != GanglionExitCodes.STATUS_OK.get_code()) {
111+
throw new GanglionError("Error in scan for ganglions", ec);
118112
}
119-
String json = new String (output_json, 0, len[0]);
120-
Gson gson = new Gson ();
121-
Type type = new TypeToken<Map<String, String>> ()
122-
{
123-
}.getType ();
124-
Map<String, String> map = gson.fromJson (json, type);
125-
return map;
126-
}
127113

114+
String json = new String(output_json, 0, len[0]);
115+
Gson gson = new Gson();
116+
117+
GanglionDevice[] devices = gson.fromJson(json, GanglionDevice[].class);
118+
119+
ArrayList<GanglionDevice> uniqueDevices = new ArrayList<GanglionDevice>();
120+
for (GanglionDevice device : devices) {
121+
if (!uniqueDevices.stream().anyMatch(entry -> entry.mac_address.equals(device.mac_address))) {
122+
uniqueDevices.add(device);
123+
}
124+
}
125+
126+
return uniqueDevices.toArray(new GanglionDevice[uniqueDevices.size()]);
127+
}
128128
}
Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
11
package openbci_gui_helpers.examples;
22

3-
import java.util.Map;
4-
53
import openbci_gui_helpers.GUIHelper;
64
import openbci_gui_helpers.GanglionError;
5+
import openbci_gui_helpers.GUIHelper.GanglionDevice;
76

8-
public class TestDiscovery
9-
{
7+
public class TestDiscovery {
108

11-
public static void main (String[] args) throws GanglionError
12-
{
13-
Map<String, String> map = GUIHelper.scan_for_ganglions (args[0], 3);
14-
for (Map.Entry<String, String> entry : map.entrySet ())
15-
{
16-
System.out.println ("Key = " + entry.getKey () + ", Value = " + entry.getValue ());
9+
public static void main(String[] args) throws GanglionError {
10+
GanglionDevice[] devices = GUIHelper.scan_for_ganglions(args[0], 3);
11+
for (GanglionDevice device : devices) {
12+
System.out.println("Identifier = " + device.identifier + ", Mac Address = " + device.mac_address
13+
+ ", Firmware = " + device.firmware_version);
1714
}
1815
}
1916
}
Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
11
package openbci_gui_helpers.examples;
22

3-
import java.util.Map;
4-
53
import openbci_gui_helpers.GUIHelper;
4+
import openbci_gui_helpers.GUIHelper.GanglionDevice;
65
import openbci_gui_helpers.GanglionError;
76

8-
public class TestNativeDiscovery
9-
{
7+
public class TestNativeDiscovery {
108

11-
public static void main (String[] args) throws GanglionError
12-
{
13-
Map<String, String> map = GUIHelper.scan_for_ganglions (3);
14-
for (Map.Entry<String, String> entry : map.entrySet ())
15-
{
16-
System.out.println ("Key = " + entry.getKey () + ", Value = " + entry.getValue ());
9+
public static void main(String[] args) throws GanglionError {
10+
GanglionDevice[] devices = GUIHelper.scan_for_ganglions(3);
11+
for (GanglionDevice device : devices) {
12+
System.out.println("Identifier = " + device.identifier + ", Mac Address = " + device.mac_address
13+
+ ", Firmware = " + device.firmware_version);
1714
}
18-
System.out.println ("Completed");
15+
System.out.println("Completed");
1916
}
2017
}

modules/bglib/build.cmake

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ SET(GANGLION_LIB "GanglionScan")
22

33
add_library(
44
${GANGLION_LIB} SHARED
5+
modules/common/src/serialization.cpp
56
modules/bglib/src/callbacks.cpp
67
modules/bglib/src/cmd_def.cpp
78
modules/bglib/src/stubs.cpp
@@ -13,6 +14,7 @@ target_include_directories(
1314
${GANGLION_LIB} PUBLIC
1415
3rdparty/json
1516
modules/bglib/include
17+
modules/common/include
1618
)
1719

1820
set_property(TARGET ${GANGLION_LIB} PROPERTY POSITION_INDEPENDENT_CODE ON)

modules/bglib/src/callbacks.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
#include <ctype.h>
22
#include <iomanip>
3-
#include <map>
3+
#include <list>
44
#include <sstream>
55
#include <stdlib.h>
66
#include <string.h>
77
#include <string>
88

9+
910
#include "cmd_def.h"
1011
#include "openbci_gui_helpers.h"
12+
#include "serialization.h"
1113

1214

1315
namespace GanglionDetails
1416
{
1517
extern int exit_code;
16-
extern std::map<std::string, std::string> devices;
18+
extern std::list<GanglionDevice> devices;
1719
}
1820

1921
void ble_evt_gap_scan_response (const struct ble_msg_gap_scan_response_evt_t *msg)
@@ -57,7 +59,15 @@ void ble_evt_gap_scan_response (const struct ble_msg_gap_scan_response_evt_t *ms
5759
mac_addr << ":";
5860
}
5961
}
60-
GanglionDetails::devices[std::string (name)] = mac_addr.str ();
62+
63+
uint8_t firmware = strstr (name, "anglion 1.3") == NULL ? 2 : 3;
64+
65+
GanglionDevice device;
66+
device.identifier = name;
67+
device.mac_address = mac_addr.str ();
68+
device.firmware_version = firmware;
69+
70+
GanglionDetails::devices.push_back (device);
6171
GanglionDetails::exit_code = (int)GanglionDetails::GanglionScanExitCodes::STATUS_OK;
6272
}
6373
}

modules/bglib/src/openbci_gui_helpers.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
#include <chrono>
22
#include <ctype.h>
3-
#include <map>
3+
#include <list>
44
#include <stdlib.h>
55
#include <string.h>
66
#include <string>
77

88
#include "cmd_def.h"
99
#include "openbci_gui_helpers.h"
10+
#include "serialization.h"
1011
#include "uart.h"
1112

1213
#ifdef _WIN32
@@ -15,14 +16,12 @@
1516
#include <unistd.h>
1617
#endif
1718

18-
#include "json.hpp"
19-
2019
using json = nlohmann::json;
2120

2221
namespace GanglionDetails
2322
{
2423
int exit_code = (int)GanglionScanExitCodes::STATUS_OK;
25-
std::map<std::string, std::string> devices;
24+
std::list<GanglionDevice> devices;
2625

2726
void output (uint8 len1, uint8 *data1, uint16 len2, uint8 *data2)
2827
{
@@ -138,7 +137,7 @@ int scan_for_ganglions (char *serial_port, int timeout_sec, char *output_json, i
138137
json result (GanglionDetails::devices);
139138
std::string s = result.dump ();
140139
strcpy (output_json, s.c_str ());
141-
*output_len = s.length ();
140+
*output_len = (int)s.length ();
142141
}
143142
ble_cmd_gap_end_procedure ();
144143
uart_close ();
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#pragma once
2+
3+
#include "json.hpp"
4+
5+
#include <cstdint>
6+
#include <string>
7+
8+
typedef struct GanglionDevice
9+
{
10+
std::string identifier;
11+
std::string mac_address;
12+
uint8_t firmware_version;
13+
} GanglionDevice;
14+
15+
void to_json (nlohmann::json &result, const GanglionDevice &device);
16+
void from_json (const nlohmann::json &string, GanglionDevice &device);
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#include "serialization.h"
2+
3+
void to_json (nlohmann::json &result, const GanglionDevice &device)
4+
{
5+
result = nlohmann::json {{"identifier", device.identifier}, {"mac_address", device.mac_address},
6+
{"firmware_version", std::to_string (device.firmware_version)}};
7+
}
8+
9+
void from_json (const nlohmann::json &string, GanglionDevice &device)
10+
{
11+
string.at ("identifier").get_to (device.identifier);
12+
string.at ("mac_address").get_to (device.mac_address);
13+
string.at ("firmware_version").get_to (device.firmware_version);
14+
}

modules/native-ble/build.cmake

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ SET(OPENBCI_GANGLION_NATIVE_LIB "GanglionNativeScan")
22

33
add_library(
44
${OPENBCI_GANGLION_NATIVE_LIB} SHARED
5+
modules/common/src/serialization.cpp
56
modules/native-ble/src/openbci_gui_native_helpers.cpp
67
)
78

89
target_include_directories(
910
${OPENBCI_GANGLION_NATIVE_LIB} PUBLIC
1011
modules/native-ble/include
12+
modules/common/include
1113
3rdparty/json
1214
3rdparty/SimpleBLE/simpleble/include/simpleble
1315
)

0 commit comments

Comments
 (0)