XNeuroSDK 1.0.4

There is a newer version of this package available.
See the version list below for details.
dotnet add package XNeuroSDK --version 1.0.4
NuGet\Install-Package XNeuroSDK -Version 1.0.4
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="XNeuroSDK" Version="1.0.4" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add XNeuroSDK --version 1.0.4
#r "nuget: XNeuroSDK, 1.0.4"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install XNeuroSDK as a Cake Addin
#addin nuget:?package=XNeuroSDK&version=1.0.4

// Install XNeuroSDK as a Cake Tool
#tool nuget:?package=XNeuroSDK&version=1.0.4

Overview

Neurosdk is a powerful tool for working with neuro-sensors BrainBit, BrainBitBlack, Callibri and Kolibri. All these devices work with BLE 4.2+ technology. Xamarin SDK is designed for Android and iOS platforms. SDK allows you to connect, read the parameters of devices, as well as receive signals of various types from the selected device.

Getting Started

Android:

Because sdk uses the bluetooth api you need to set up the project.

For Android you need to add permissions to use geolocation and bluetooth to the manifest. You can read more about this on AndroidDeveloper.

<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" tools:targetApi="31" android:usesPermissionFlags="neverForLocation" />

Permissions to location and bluetooth requests as:

        private void requestPermissions()
        {
            bool permissionsGranted = Build.VERSION.SdkInt >= BuildVersionCodes.S ?
                (ContextCompat.CheckSelfPermission(Android.App.Application.Context, Manifest.Permission.BluetoothScan) == (int)Permission.Granted &&
                 ContextCompat.CheckSelfPermission(Android.App.Application.Context, Manifest.Permission.BluetoothConnect) == (int)Permission.Granted) :
                (ContextCompat.CheckSelfPermission(Android.App.Application.Context, Manifest.Permission.Bluetooth) == (int)Permission.Granted &&
                 ContextCompat.CheckSelfPermission(Android.App.Application.Context, Manifest.Permission.AccessFineLocation) == (int)Permission.Granted &&
                 ContextCompat.CheckSelfPermission(Android.App.Application.Context, Manifest.Permission.AccessCoarseLocation) == (int)Permission.Granted);

            if (permissionsGranted)
            {
                ...
            }
            else
            {
                String[] permissions = Build.VERSION.SdkInt >= BuildVersionCodes.S ?
                    new String[] { Manifest.Permission.BluetoothScan, Manifest.Permission.BluetoothConnect } :
                    new String[] { Manifest.Permission.Bluetooth, Manifest.Permission.AccessFineLocation, Manifest.Permission.AccessCoarseLocation };
                ActivityCompat.RequestPermissions((Activity)MainActivity.ActivityContext, permissions, REQUEST_PERMISSIONS);
            }
        }

Then, in MainActivity.cs add NeuroSDK.NeuroSDKSetup.Initialize() before LoadApplication :

   protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
			...
            NeuroSDK.NeuroSDKSetup.Initialize();

            LoadApplication(new App());
        }

iOS

For iOS you need to add a key to Info.plist:

<key>NSBluetoothAlwaysUsageDescription</key>
<string>Explanation to using bluetooth</string>

UWP

You need to open package manifest and add enable capability "Bluetooth".

Another way is add this capability manually:

  1. Go into UWP project folder
  2. Open Package.appxmanifest file
  3. Into Capabilities section add: <DeviceCapability Name="bluetooth"/>

Windows DotNet

You don't need to configure anything.

Usage

Scanner

The scanner works like this:

  1. Create scanner. When creating a scanner, you need to specify the type of device to search. It can be either one device or several. Here is example for two type of devices - BrainBit and Callibri.
Scanner scanner = new Scanner(SensorFamily.SensorLECallibri, SensorFamily.SensorLEBrainBit);
  1. During the search, you can get a list of found devices using a callback. To do this, you need to subscribe to receive the event, and unsubscribe after the search is completed:
private void Scanner_Founded(IScanner scanner, IReadOnlyList<SensorInfo> sensors)
{
    foreach(SensorInfo sensorInfo in sensors){
        Console.WriteLine(sensorInfo.Name + ": " + sensorInfo.Address);
    }
}

scanner.EventSensorsChanged += Scanner_Founded;
...
scanner.EventSensorsChanged -= Scanner_Founded;
  1. Start and stop search
scanner.Start();
...
scanner.Stop();
  1. Additionally, a list of found devices can be obtained using a separate method.
IReadOnlyList<SensorInfo> sensors = scanner.Sensors;

SensorInfo contains information about device:

  • Name - the name of device
  • Address - MAC address of device (UUID for iOS/MacOS)
  • Sensor family - type of device
  • Sensor model - numerical value of the device model
  • Pairing requared - whether the device needs to be paired or not
  1. After you finish working with the scanner, you need to clean up the resources used.
scanner.Dispose();

Important! When restarting the search, the callback will only be called when a new device is found. If you need to get all devices found by the current scanner instance, call the appropriate method.

Sensor

You need to create a device using a scanner. All manipulations with the device will be performed without errors only if the device is connected.

Sensor sensor = scanner.CreateSensor(sensorInfo);

Device creation is a blocking method, so it must be called from separate thread.

Manage connectionState

Connection status can be obtained in two ways. The first one is using the sensor property State.

The second way is in real time using a callback:

 private void EventSensorStateChanged(ISensor sensor, SensorState sensorState)
{
    Console.WriteLine(sensorState);
}
...
sensor.EventSensorStateChanged += EventSensorStateChanged;
...
sensor.EventSensorStateChanged -= EventSensorStateChanged;

A connection can be in two states: connected (InRange) and disconnected (OutOfRange).

Important! The state change callback will not come after the device is created, only after disconnecting (device lost from the scope or using a method) and then connected. The device does not automatically reconnect.

You can connect and disconnect from device manually by methods Connect() and Disconnect(). To receive connection state in real time you need to subscribe to stateChanged event. Also you can get connection state by sensor's property.

sensor.Disconnect();
...
sensor.Connect();

Battery

Also, you can get power value from each device by sensor property BattPower or by callback in real time:

private void EventBatteryChanged(ISensor sensor, int battPower)
{
    Console.WriteLine("Power: " + battPower);
}
...
sensor.EventBatteryChanged += EventBatteryChanged;
...
sensor.EventBatteryChanged -= EventBatteryChanged;

Parameters

Each device has its own settings, and some of them can be configured as you need. Not all settings can be changed and not every device supports all settings.

Firstly you need to find out what parameters the device supports and whether they can be changed:

var parameters = sensor.Parameters;

Info about parameter includes two fields:

  • the name of the parameter, represented by an enumeration
  • parameter availability for manipulation. Can be one of three values:
    • read - read-only
    • read and write - parameter can be changed
    • read and notify - parameter is updated over time

You can also check if the parameter is supported, for example Gain:

if(sensor.IsSupportedParameter(SensorParameter.ParameterGain)){
...
}

Each device has a specific set of modules. You can find out which modules the device has using the property Feature:

var features = sensor.Features;

You can also check if the feature is supported, for example Signal:

if(sensor.IsSupportedFeature(SensorFeature.FeatureSignal)){
...
}

The device can execute certain commands. The list of supported commands can be obtained as follows:

var commands = sensor.Commands;

And also check if the device can execute the desired command:

if(sensor.IsSupportedCommand(SensorCommand.StartSignal)){
...
}

BrainBit, BrainBitBlack

The BrainBit and BrainBitBlack is a headband with 4 electrodes and 4 data channels - O1, O2, T3, T4. The device has a frequency of 250 Hz, which means that data on each of the channels will come at a frequency of 250 samples per second. The parameters of this device, such as gain, data offset and the other, cannot be changed, if you try to do this, an exception will appear.

sensor.Gain = SensorGain.SensorGain1; // <- This throw an exeption!

You can distinguish BrainBit device from Flex by the firmware version number: if the SensorVersion.FwMajor is more than 100 - it's Flex, if it's less than BrainBit.

BrainBitBlack, unlike BrainBit, requires pairing with a PC/mobile device. So, before connecting to the BBB, you must put it into pairing mode. SDK starts the pairing process automatically.

To use the BrainBit features, you need to bring the sensor type to a BrainBit or BrainBitBlack device type. The sensor as such does not provide signal or resistance values.

BrainBitSensor sensor = scanner.CreateSensor(info) as BrainBitSensor;
// or
BrainBitBlackSensor sensor = scanner.CreateSensor(info) as BrainBitBlackSensor;
// or
var sensor = = scanner.CreateSensor(info);
// or
Sensor sensor = scanner.CreateSensor(info);
BrainBitSensor BBsensor = sensor as BrainBitSensor;
Receiving signal

To receive signal data, you need to subscribe to the corresponding callback. The values will be received as a packet from four channels at once, which will avoid desynchronization between them. The values come in volts. In order for the device to start transmitting data, you need to start a signal using the execute command. This method is also recommended to be run in an separate thread.

private void onBrainBitSignalDataRecived(ISensor sensor, BrainBitSignalData[] data)
{
    Console.WriteLine("Data: " + data);
}
...
sensor.EventBrainBitSignalDataRecived += onBrainBitSignalDataRecived;
sensor.ExecCommand(SensorCommand.CommandStartSignal);
...
sensor.EventBrainBitSignalDataRecived -= onBrainBitSignalDataRecived;
sensor.ExecCommand(SensorCommand.CommandStopSignal);
Recieving resistance

BrainBit and BrainBitBlack also allow you to get resistance values. With their help, you can determine the quality of the electrodes to the skin.

private void onBrainBitResistDataRecived(ISensor sensor, BrainBitResistData data)
{
    Console.WriteLine("Data: " + data);
}
...
sensor.EventBrainBitResistDataRecived += onBrainBitResistDataRecived;
sensor.ExecCommand(SensorCommand.CommandStartResist);
...
sensor.EventBrainBitResistDataRecived -= onBrainBitResistDataRecived;
sensor.ExecCommand(SensorCommand.CommandStopResist);

Signal Callibri, Kolibri

The Callibri family of devices has a wide range of built-in modules. For each of these modules, the SDK contains its own processing area. It is recommended before using any of the modules to check if the module is supported by the device using one of the methods IsSupportedFeature, IsSupportedCommand or IsSupportedParameter

To use the Callibri features, you need to bring the sensor type to a Callibri device type. The sensor as such does not provide signal or electrodes state values.

CallibriSensor sensor = scanner.CreateSensor(info) as CallibriSensor;
// or
var sensor = = scanner.CreateSensor(info);
// or
Sensor sensor = scanner.CreateSensor(info);
CallibriSensor Сsensor = sensor as CallibriSensor;
Receiving signal

To receive signal data, you need to subscribe to the corresponding callback. The values come in volts. In order for the device to start transmitting data, you need to start a signal using the execute command. This method is also recommended to be run in an separate thread.

The sampling rate can be controlled using the SamplingFrequency property. For example, at a frequency of 1000 Hz, the device will send 1000 samples per second. Supports frequencies 125/250/500/1000/2000/4000/8000 Hz. You can also adjust the signal offset (DataOffset) and signal power (Gain).

private void onCallibriSignalDataRecived(ISensor sensor, CallibriSignalData[] data)
{
    Console.WriteLine("Data: " + data);
}
...
sensor.EventCallibriSignalDataRecived += onCallibriSignalDataRecived;
sensor.ExecCommand(SensorCommand.CommandStartSignal);
...
sensor.EventCallibriSignalDataRecived -= onCallibriSignalDataRecived;
sensor.ExecCommand(SensorCommand.CommandStopSignal);

Callibri can output envelope and respiration data. These channels have a frequency of 20 Hz. Some models support MEMS, its frequency is 100 Hz.

Check electrodes state

Checking the condition of the electrodes is used to determine the quality of the electrodes to the skin. It can be in three states - adjacent (Normal) / not adjacent (Detached) / resistance is too high (HighResistance). To receive data, you need to subscribe to the corresponding callback and start signal pickup.

private void onCallibriElectrodeStateChanged(ISensor sensor, CallibriElectrodeState elState)
{
    Console.WriteLine(elState);
}
...
sensor.EventCallibriElectrodeStateChanged += onCallibriElectrodeStateChanged;
sensor.ExecCommand(SensorCommand.CommandStartSignal);
...
sensor.EventCallibriElectrodeStateChanged -= onCallibriElectrodeStateChanged;
sensor.ExecCommand(SensorCommand.CommandStopSignal);
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed.  monoandroid50 is compatible. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Universal Windows Platform uap was computed.  uap10.0 is compatible. 
Xamarin.iOS xamarinios was computed.  xamarinios10 is compatible. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • No dependencies.
  • MonoAndroid 5.0

    • No dependencies.
  • UAP 10.0

    • No dependencies.
  • Xamarin.iOS 1.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.6.25 109 3/25/2024
1.0.6.16 147 12/18/2023
1.0.4 246 4/20/2023
1.0.3.3 306 12/19/2022
1.0.3.2 273 12/19/2022