Programming Reference:NatusADC: Difference between revisions

From BCI2000 Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 1: Line 1:
NatusADC module has 3 main classes - NatusPackageInterface, NatusDataServer and NatusClient. The overview of the NatusADC working is shown in the image below.
NatusADC module has 3 main classes - NatusPackageInterface, NatusDataServer and NatusClient. The overview of the NatusADC working is shown in the image below.
[[File:Prog_Ref_NatusADC_NatusWorking.png|center|800px|Overview of NatusADC working]]
[[File:Prog_Ref_NatusADC_NatusWorking.png|center|800px|Overview of NatusADC working]]
NatusDataServer processes and sends signal from the device to the client application. A project named XLDataExportClient reads signals from the device and calls the NatusDataServer's functions to send the signal to the client. NatusClient is the client application within the BCI2000 that receives the signals and does the initial processing. NatusPackageInterface contains the implementation of data transfer protocol between serve/device and client and is used by NatusClient and NatusDataServer to communicate with each other over TCP and UDP. NatusDataServer and NatusPackageInterface are independent of the BCI2000 where as NatusClient relies on BCI2000.


== NatusPackageInterface ==
== NatusPackageInterface ==

Revision as of 19:58, 29 July 2019

NatusADC module has 3 main classes - NatusPackageInterface, NatusDataServer and NatusClient. The overview of the NatusADC working is shown in the image below.

Overview of NatusADC working

NatusDataServer processes and sends signal from the device to the client application. A project named XLDataExportClient reads signals from the device and calls the NatusDataServer's functions to send the signal to the client. NatusClient is the client application within the BCI2000 that receives the signals and does the initial processing. NatusPackageInterface contains the implementation of data transfer protocol between serve/device and client and is used by NatusClient and NatusDataServer to communicate with each other over TCP and UDP. NatusDataServer and NatusPackageInterface are independent of the BCI2000 where as NatusClient relies on BCI2000.

NatusPackageInterface

This class handles the communication between the server/device and the client. It should be included with both - NatusDataServer and NatusClient Class. The class performs the following functions -constructing TCP and UDP packets, calculating the CRC of a packet and checking the CRC on the receiving side, sending the packets over TCP/UDP port, receiving packets over TCP/UDP Port, reconstructing the data from the packets and listening for connections on device/server-side. Note - The file limits the maximum number of channels for a device (stored in MAX_NUM_CHANNELS in NatusPackageInterface.h) to 100.
The format of the packets constructed along with each field size is as follows:

Packet format

TCP Commands

The commands through which the NatusDataServer and NatusClient communicate are as follows:

CMD_Ping
To check if the connection is successful and data can be sent and received.
  • Command Number: 0x01
  • Parameters/Payload: 0xff
  • Return Value: returns payload
CMD_GetInformation
To send the device information such as the number of channels and sampling rate to the client.
  • Command Number: 0x02
  • Parameters/Payload: NULL
  • Return Value: struct NatusDeviceInformation which contains the number of channels, sampling rate, and device identifier.
CMD_GetChannelNames
To send the channel names as set by the device to the client. If no channel names are set, NULL is sent.
  • Command Number: 0x03
  • Parameters/Payload: NULL
  • Return Value: struct NatusChannelInformation which contains all the channels and stream names.
CMD_StartStream
To start sending channel data over UDP port.
  • Command Number: 0x10
  • Parameters/Payload: NULL
  • Return Value: NULL
CMD_StopStream
To stop sending channel data
  • Command Number: 0x1F
  • Parameters/Payload: NULL
  • Return Value: NULL
CMD_SelectChannels
To send data only for the channels numbers mentioned in the payload
  • Command Number: 0x20
  • Parameters/Payload: a list of channel numbers separated by space and stored in a string
  • Return Value: NULL
CMD_SetBlockSize
To set the number of blocks to send per packet.
  • Command Number: 0x21
  • Parameters/Payload: number of blocks to send per packet stored in uint32_t datatype.
  • Return Value: NULL
CMD_GetDecimationFactor
To get the current decimation factor of the device/server.
  • Command Number: 0x22
  • Parameters/Payload: decimation factor stored in uint32_t datatype.
  • Return Value: NULL
CMD_SetDecimationFactor
To set the decimation factor of the device/server.
  • Command Number: 0x23
  • Parameters/Payload: NULL
  • Return Value: decimation factor stored in uint32_t datatype but casted into uint8_t datatype for transmission over TCP.
CMD_ERR
The command is sent if there is any type of error.
  • Command Number: 0xFF
  • Parameters/Payload: command which caused the error and the payload generated by the function handling the command.
  • Return Value: NULL

Note: The packet format for this command is as follows:

Command CMD_ERR packet format.

UDP Commands

CMD_StreamPackage
The command is sent from the server/device to the client when only 1 block per packet is sent.
  • Command Number: 0x11
  • Parameters/Payload: Channel data of 1 block
  • Return Value: NULL
CMD_VariableSizeStreamPackage
The command is sent from the server/device to the client when more than 1 block per packet is sent.
  • Command Number: 0x12
  • Parameters/Payload: Channel data of more than 1 block (number of blocks as set by the CMD_SetBlockSize command)
  • Return Value: NULL

Functions and Variables

The public and protected functions and variables defined in this class are as follows:

  • void Poll () - The function runs on server/device and continuously waits for any command from the NatusClient over the TCP protocol.
  • void send_data (uint8_t cmd, uint8_t* payload, uint32_t len_payload, bool isError=false, PackageType t = Control) - The function creates a packet using cmd (the command) and the payload. The default values for isError is false (i.e., no error) and PackageType is Control (TCP prototcol). The channel data is sent over Stream PackageType (i.e., UDP Protocol).
  • virtual void data_received (CmdStruct * payload) = 0 - The function should be implemented in the child classes to ensure proper processing, in respect ot the child class, of the data recieved via TCP or UDP protocol is done.
  • void printMessage (std::string) - Print the string parameter on the warning window.
  • CmdStruct* getNextPackage () - The function gets a TCP packet (from the server or from the Client, as the case may be) and store in struct CmdStruct. Definietion of CmdStruct can be found in NatusPackageInterface.h file.
  • CmdStruct* getNextUDPPackage () - The function is same as CmdStruct* getNextPackage(), except that it received packet over UDP protocol.
  • void delete_cmdstruct (CmdStruct* ) - The function frees the memory occupied by a CmdStruct pointer.
  • void initWSA () - The function initializes the Winsock.
  • SOCKET connection - It stores the TCP socket connection, i.e, in server/device - the connection to the client and in client - the connection to the server/device.
  • SOCKET udpSocket - It stores the UDP socket connection.
  • sockaddr_in _udpReceiver - It stores the socket address for IPv4.

NatusDataServer

This class handles the server-side processing. It performs the following functions - starts-up the TCP and UDP server, check for new connections, gracefully disconnects from the client, registers various callbacks on client connection and deregister the callbacks when the client disconnects and responds to the commands (described in the NatusPackageInterface section) from the client via TCP protocol.

Functions and Variables

The public and protected functions and variables defined in this class are as follows:

  • void Startup (std::uint16_t port) - The function starts up the server and listens for a TCP connection on the port number specified by port and a UDP connection on the port number port+1.
  • void CheckForConnection () - The function checks for a client connection request and accept it if there is one.
  • void RegisterDataStreamCallback (NatusDataStreamRequest, void*) - The function registers the callbacks to start & stop streams.
  • void RegisterInformationCallback (NatusInformationRequest, void*) - The function registers the callback to get the device information.
  • void RegisterChannelInformationCallback (NatusChannelInfoRequest, void*) - The function registers the callback to get the device's channels' names.
  • void RegisterErrorCallback (NatusResponse, void*) - The function registers the callback to call incase of any error.
  • void UnregisterCallbacks () - The function deregisters all the callbacks. It is called before closing the connection with the client.
  • void SendStreamData (float* data, uint32_t numdata) - The function accepts the channel data and the number of channels numdata and prepares the data by decimating it (if decimation factor is set) and by making packets with required number of blocks which are then sent to the client.
  • void Disconnect () - The function gracefully closes the UDP and TCP connection with the client.
  • bool HasClient () - The function checks if there is a client connected to the server/device.
  • int _channelsToStream[MAX_NUM_CHANNELS] - It stores the channel numbers which are to be streamed. The end of the array is defined by storing the last element as -1.
  • int _numberOfChannelsToStream - It stores the number of channels to stream.
  • void data_received (CmdStruct *payload) - The function checks for the command received from the client and calls the appropriate function to fulfill the client's request.
  • void start_UDP_sever (std::uint16_t port) - The function opens up a UDP connection at the port.

NatusClient

This class handles the client-side processing. It connects with the server/device, gets data from the operator module of the NatusADC and sends it to the server/device. It uses various commands as described in the NatusDataServer to set different parameters. Another important function of this class 'interpolateMissingBlocks' linearly interpolates the missing UDP packets which contain the channel data values. Eg.
Consider the scenario where 1 block is sent per packet and decimation factor is 1. Suppose we received packet 1 and 3, packet 2 was lost. Data for packet 2 is interpolated as follows:
Interpolation formula Interpolated Value = ((Current Packet value – Previous Packet value) / (Current Packet Number – Previous Packet Number)) * (Interpolated Packet Number – Previous Packet Number) + Previous Packet Value

Linear Interpolation example

Functions and Variables

The public and protected functions and variables defined in this class are as follows:

  • NatusDeviceInformation GetInformation () - The function sends a CMD_GetInformation command to the server/device over TCP to query the sampling rate and number of channels of the device. It stores the received information in the NatusDeviceInformation struct type variable.
  • void Connect (std::string server_name, int port) - The function establishes a TCP connection with the server_name server at port number port and calls the init_udp function to establish a UDP connection at port port+1.
  • bool TryConnect (std::string server_name, int port) - The function tries to establish a TCP and UDP connection again with the server_name if the connection is lost and returns true if the connection is successful otherwise false.
  • void Disconnect () - The function gracefully closes the TCP and UDP connection with the server/device.
  • void StartStream () - The function sends the CMD_StartStream command to the server/device to request the channel stream data, which the server/device sends over the UDP.
  • void StopStream () - The function sends the CMD_StopStream command to the server/device.
  • uint8_t Ping (uint8_t ping) - The function sends a CMD_PING command to the sever/device with data stored in ping as payload.
  • NatusSampleBlock* ReadStream () - The function gets channel data blocks from the server/device through a UDP protocol, calls the interpolateMissingBlocks if there is any missing blocks, adds the block to the _receivequeue and returns the first block from the _receivequeue.
  • NatusSampleBlock* create_natus_sampleblock (uint8_t* payload) - The function creates and returns a NatusSampleBlock structure variable from the payload passes. NatusSampleBlock contains block number, number of samples, samples and a boolean specifying whether the block was recieved from the server/device or was interpolated.
  • void DeleteSampleBlock (NatusSampleBlock*) - The function free the space occupied by the NatusSampleBlock variable passed to it.
  • void SetSampleBlockSize (uint32_t blocksize) - The function sends CMD_SetBlockSize command to the server/device to set number of blocks to be sent in a packet as blocksize.
  • void SetDecimationFactor (uint32_t decimationFactor) - The function sends CMD_SetDecimationFactor command to the server/device to set the decimation factor as decimationFactor.
  • NatusChannelInformation GetChannelInfo () - The function sends CMD_GetChannelNames command to the server/device to query the channel and stream names of the device and stores them in a NatusChannelInformation structure.
  • int GetDecimationFactor () - The function queries from the server/device over TCP, the current decimation factor and returns it.
  • int SelectChannelsToStream (std::string channels) - The function sends CMD_SelectChannels command to the server/device along with the channels to stream stored in a space separated channels string.
  • int _channelsToStream[MAX_NUM_CHANNELS] - It stores the channel numbers which are to be streamed.
  • NatusChannelInformation channelInfo - The structure stores the channel and stream names of the device. The NatusChannelInformation structure definition can be found in NatusPackageInterface.h file.
  • void data_received (CmdStruct *payload) - The function checks if the data received from the server/device does not contain a CMD_ERR code.
  • CmdStruct* blockForPackage(uint32_t timeout) - The function waits to receive a TCP packet from server/device for the time specified by the timeout variable.
  • std::queue<NatusSampleBlock*> _receivequeue - The queue stores the blocks received for processing.
  • bool init_udp (int port) - The function creates and binds a UDP socket. If completed successfully, it returns true, otherwise false.
  • NatusSampleBlock _prevblock - It stores the last data block received from the server/device and is used to check if any block is lost in between, when the client receives a new data block.
  • void interpolateMissingBlocks (NatusSampleBlock*) - The function linearly interpolates any number of missing blocks between the current received data block and the last recieved data block.
  • void emptyReceiveQueue () - The function frees the memory occupied by the queue _receivequeue whenever the connection is closed or restarted.

See also

Contributions:NatusADC, User Reference:DataIOFilter, Programming Reference:GenericADC Class