OS: macOS Catalina
Software: Xcode 12
IOS minimal version: 12.0
Framework: neurosdk.framework-1.7.6.1
Dependencies: libc++.tbd, CoreBluetooth.framework
Unpack the downloaded zip file with the framework.
Create an empty project “Application”.
Create a frameworks folder in the directory with the project file and put the folder in it neurosdk.framework
Add framework to the project.
To do this, go to Project settings - General - Frameworks, Libraries, and Embedded Content - click on “+”
A window opens in which we click Add Other… - Add Files...
Select the path to neurosdk.framework, click Open
Thus, we have added neurosdk.framework to the project.
Next, add dependencies.
To do this, also go to Project settings - General - Frameworks, Libraries, and Embedded Content - and click on the "+"
In the window that appears, in the search bar, find CoreBluetooth.framework and press the button “Add”
We also add libc ++.tbd
As a result, in the Frameworks, Libraries, and Embedded Content section, we see the following picture:
The required dependencies have been added to the project.
Further, in Info.plist for the correct operation of the SDK, you need to add the NSBluetoothAlwaysUsageDescription key.
First of all to find nearby devices you need to create global variable of NTDeviceEnumerator.
let scanner = NTDeviceEnumerator(deviceType: .TypeBrainbit)
You can specify which type of device you're looking for by deviceType (TypeBrainbit, TypeCallibri,TypeAny). Instance of NTDeviceEnumerator has subscribeFoundDevice event will hit when a new device appears.
Note: Make sure your instance lifetime is enough to find a new device. For example your enumerator variable is a private field of the class.
Warn: Searching for device only when object NTDeviceEnumerator exists in memory.
scanner.subscribeFoundDevice { (deviceInfo) in
self.device = NTDevice(enumerator: self.scanner, deviceInfo: deviceInfo)
}
Here we insert closure and if new device will be detected you received NTDeviceInfo.
Note: Remember to create new NTDevice you new NTDeviceInfo and NTDeviceEnumerator.
Warn: All subscribers are run in separate thread. Be careful when call ui-based code.
To receive data from the device and to send commands to it first you need to connect to it.
device?.connect()
You could read the device state to check whether it is connected or not. You also could subscribe subscribeParameterChanged event to receive notifications when the device goes out of range.
device?.subscribeParameterChanged(subscriber: { (param) in
if(param == .state) {
let state = device.state()
if( state == .connected) {
print("Connected")
} else {
print("Disconnected")
}
}
})
Take EEG channels as an example.
var eegChannels: [String: NTEegChannel?] = [:]
Create channels with their names (T3, T4, O1, O2). To do this, call getChannelInfoArray from NTDeviceTraits to get the channelInfo array, and element-by-element initialize NTEegChannel with device parameters and each channelInfo
do {
try NTDeviceTraits.hasChannels(withType: device, channelType: .signal)
NTDeviceTraits.getChannelInfoArray(withType: device, channelType: .signal, error: nil).forEach {
eegChannels[$0.name] = NTEegChannel(device: device, channelInfo: $0)
}
print("initEegChannels succeeded")
}
catch let err as NSError{
print("initEegChannels failed")
}
First of all, for EEG channels, you need to execute the startSignal command.
self.device?.execute(command: .startSignal)
Then you need to subscribe to each of the four channels (subscribeLengthChanged) and then read the data (readData)
self.eegChannels.forEach { (channelName, channel) in
channel?.subscribeLengthChanged(subscribe: { (length) in
let newdata = channel?.readData(offset: length-1, length: 1).first
})
}
The newdata variables in this example are the desired channel values.
At the end of working with channels, you need to unsubscribe from them (by passing nil to subscribeLengthChanged).
self.eegChannels.forEach{ (_, channel) in
channel?.subscribeLengthChanged(subscribe: nil)
}
And send the stopSignal command to the device.
self.device?.execute(command: .stopSignal)