BrainBit foe developers Visit website Subscribe for updates
Home
SDK
Device

Performing device search C/C++

 

In this article, our goal is to provide one with sufficient information about the process of looking for an exact device by serial number and by the DeviceInformation record. The full source code could be found in the Brainbit Example repository.

 

If you have found some erroneous information on this or any other page or you have any questions about the device or SDK, don't hesitate to ask your questions via email or file a bug on our public issue tracker.

Email: support@brainbit.com

Issue tracker link: https://gitlab.com/brainbit-inc/brainbit-sdk/issues

We also have a chant on Gitter.

 

Device identification

Any Brainbit device has a serial number for identification. It could be found on the left-side electronics block of the device under the "BrainBit" line.

This number could be used to select a sensor from a list of available ones. For example, you could scan for all nearby devices once, as described in the Quickstart guide, store the preferred device serial number, and then use it to connect only with the remembered sensor. You may use a whole DeviceInformation record of a device, which could be stored ones and reused later without scanning for devices. Both methods are described in this article.

 

Search by serial number

To perform device search we will make a small console application. Copy and paste the following code to your main.c file.

    
#include "cscanner.h"
#include "cdevice.h"
#include "sdk_error.h"
#include "stdio.h"
#include "windows.h"

int main()
{
	while (true)
	{
		printf("Enter a serial number of a device or \"q\" to exit.\n");

		uint64_t serialNumber;
		if (scanf_s("%llu", &serialNumber, (rsize_t)sizeof(uint64_t)) == 0)
		{
			if (fgetc(stdin) == 'q') 
			{
				while (fgetc(stdin) != '\n') {}
				break;
			}
			else
			{
				while (fgetc(stdin) != '\n'){}
				printf("Invalid command\n");
				continue;
			}
		}
		
		find_by_serial(serialNumber);
	}

	return 0;
}
    

This code does nothing except parsing user input. We have code for parsing the user input, now we need to implement find_by_serial function. Copy and paste the following code to the main.c file.

    
void find_by_serial(uint64_t serial_number)
{
	DeviceEnumerator* enumerator = create_device_enumerator(DeviceTypeBrainbit);
	if (enumerator == NULL)
	{
		char errorMsg[1024];
		sdk_last_error_msg(errorMsg, 1024);
		printf("Device enumerator is null: %s\n", errorMsg);
		return;
	}

	int attempts = 10;
	do
	{
		DeviceInfo deviceInfo;

		if (find_device_info(enumerator, serial_number, &deviceInfo) != 0)
		{
			Sleep(300);
			continue;
		}

		
		char addressString[32];
		if (address_to_string(deviceInfo.Address, addressString, 32) != SDK_NO_ERROR)
		{
			printf("Error converting address to string.\n");
			break;
		}
		
		printf("Device with SN %llu found. Name: %s, Address: %s\n", serial_number, deviceInfo.Name, addressString);
		enumerator_delete(enumerator);
		return;
	}
	while (attempts-- > 0);
	
	enumerator_delete(enumerator);
	printf("Device with SN %llu not found.\n", serial_number);
}
    

Here we create an enumerator and check its device list every 300 ms until we have found a device info structure with the specified serial number or ten attempts have been made. We use a WinAPI function Sleep to pause program between attempts so we have to include the windows.h header file. On each iteration, the device list is filtered by find_device_info function.

    
int find_device_info(DeviceEnumerator* enumerator, uint64_t serial_number, DeviceInfo *out_device_info)
{
	DeviceInfoArray deviceInfoArray;
	const int resultCode = enumerator_get_device_list(enumerator, &deviceInfoArray);
	if (resultCode != SDK_NO_ERROR)
	{
		return -1;
	}
	
	for (size_t i = 0; i < deviceInfoArray.info_count; ++i)
	{
		if (deviceInfoArray.info_array[i].SerialNumber == serial_number)
		{
			*out_device_info = deviceInfoArray.info_array[i];
			free_DeviceInfoArray(deviceInfoArray);
			return 0;
		}
	}

	free_DeviceInfoArray(deviceInfoArray);
	return -1;
}
    

 

Search by DeviceInformation record

As you can see, the whole code is rather complicated, so it would be better not to use it too much and use something else to find or identify the sensor. Another option, as it was mentioned at the beginning of the article, is to use a DeviceInformation record. The search by a record is less complicated, but you need to scan for devices and store that record beforehand. You could perform a search by a serial number once, store the DeviceInformation record and use it to find the sensor down the line. 

    
DeviceInfo deviceInfo;
//load device info from file
Device* device = create_Device(enumerator, deviceInfo);
if (device == NULL)
{
	//device not found
}
    

 

Files content

main.c

    
#include "cscanner.h"
#include "cdevice.h"
#include "sdk_error.h"
#include "stdio.h"
#include "windows.h"

int find_device_info(DeviceEnumerator* enumerator, uint64_t serial_number, DeviceInfo *out_device_info)
{
	DeviceInfoArray deviceInfoArray;
	const int resultCode = enumerator_get_device_list(enumerator, &deviceInfoArray);
	if (resultCode != SDK_NO_ERROR)
	{
		return -1;
	}
	
	for (size_t i = 0; i < deviceInfoArray.info_count; ++i)
	{
		if (deviceInfoArray.info_array[i].SerialNumber == serial_number)
		{
			*out_device_info = deviceInfoArray.info_array[i];
			free_DeviceInfoArray(deviceInfoArray);
			return 0;
		}
	}

	free_DeviceInfoArray(deviceInfoArray);
	return -1;
}

void find_by_serial(uint64_t serial_number)
{
	DeviceEnumerator* enumerator = create_device_enumerator(DeviceTypeBrainbit);
	if (enumerator == NULL)
	{
		char errorMsg[1024];
		sdk_last_error_msg(errorMsg, 1024);
		printf("Device enumerator is null: %s\n", errorMsg);
		return;
	}

	int attempts = 10;
	do
	{
		DeviceInfo deviceInfo;

		if (find_device_info(enumerator, serial_number, &deviceInfo) != 0)
		{
			Sleep(300);
			continue;
		}

		
		char addressString[32];
		if (address_to_string(deviceInfo.Address, addressString, 32) != SDK_NO_ERROR)
		{
			printf("Error converting address to string.\n");
			break;
		}
		
		printf("Device with SN %llu found. Name: %s, Address: %s\n", serial_number, deviceInfo.Name, addressString);
		enumerator_delete(enumerator);
		return;
	}
	while (attempts-- > 0);
	
	enumerator_delete(enumerator);
	printf("Device with SN %llu not found.\n", serial_number);
}

int main()
{
	while (true)
	{
		printf("Enter a serial number of a device or \"q\" to exit.\n");

		uint64_t serialNumber;
		if (scanf_s("%llu", &serialNumber, (rsize_t)sizeof(uint64_t)) == 0)
		{
			if (fgetc(stdin) == 'q') 
			{
				while (fgetc(stdin) != '\n') {}
				break;
			}
			else
			{
				while (fgetc(stdin) != '\n'){}
				printf("Invalid command\n");
				continue;
			}
		}
		
		find_by_serial(serialNumber);
	}

	return 0;
}
    

CMakeLists.txt

    
cmake_minimum_required(VERSION 3.14)

project(BrainbitSearch LANGUAGES C)

add_executable(BrainbitSearch main.c)

target_include_directories(BrainbitSearch PRIVATE include)

find_library(SDK_LIB NAMES neurosdk-x64 PATHS windows)
target_link_libraries(BrainbitSearch PRIVATE ${SDK_LIB})

find_file(SDK_DLL NAMES neurosdk-x64.dll PATHS windows)
add_custom_command(TARGET BrainbitSearch POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${SDK_DLL} $<TARGET_FILE_DIR:BrainbitSearch>)