Skip to content
Snippets Groups Projects
Commit f7ffa8f4 authored by Querejeta Lomas, Leire's avatar Querejeta Lomas, Leire
Browse files

Subir nuevo archivo

parent b578b432
No related branches found
No related tags found
No related merge requests found
/**
* @file class_core.hpp
* @author Alfonso Dominguez <alfonso.dominguez@tecnalia.com> and Leire Querejeta Lomas <leire.querejeta@tecnalia.com>
* @date 2020
*
* Copyright 2020 Tecnalia Research & Innovation.
* Distributed under the GNU GPL v3.
* For full terms see https://www.gnu.org/licenses/gpl.txt
*
* @brief Interface to the funccionalities of Class
*/
#ifndef CLASS_CORE_HPP
#define CLASS_CORE_HPP
#include <vector>
#include <string>
#include <memory>
#include <thread>
#include <mutex>
#include <cmath>
#include <iostream>
#include <fstream>
#include <boost/circular_buffer.hpp>
#include <communication/udp_server.hpp>
#include <communication/udp_client.hpp>
#include <logger/logger.hpp>
#include <class/class_structures.hpp>
#include <class/class_error.hpp>
#include <class/class_cb.hpp>
#include <filter/butterworth.hpp>
#include <Python.h>
/**
* @brief Core class
*/
class ClassCore:public UdpServerListener
{
public:
//! Allowed values
int BUZZER_MAX_VALUE = 500;
int BUZZER_MIN_VALUE = 25;
int FREQ_MAX_VALUE = 2000;
int FREQ_MIN_VALUE = 0;
int HV_MAX_VALUE = 200;
int HV_MIN_VALUE = 120;
int INTERVAL_MAX_VALUE = 1000;
int INTERVAL_MIN_VALUE = 250;
//! Structure for electrode
struct Elec
{
int id;
int pads_number;
};
//! Structure for virtual electrode
struct Velec
{
int id;
std::string name;
bool selected;
};
//! basic constructor
ClassCore();
//! basic destructor
~ClassCore();
/*!
\brief Stops acquisition
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error acqOff();
/*!
\brief Starts acquisition
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error acqOn();
/*!
\brief Stops impedance acquisition
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error acqImpedanceOff();
/*!
\brief Starts impedance acquisition
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error acqImpedanceOn();
/*!
\brief Stops acquisition stream
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error acqStreamOff();
/*!
\brief Starts acquisition stream
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error acqStreamOn();
/*!
\brief Sets the config for impedance acquisition
\param positive Indicates whther is positive (true) or negative (false)
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error acqImpedanceConfig(const bool& positive);
/*!
\brief Sets the polarity for impedance acquisition
\param unipolar Indicates whther is unipolar (true) or bipolar (false).
\return Integer indicating the success of the setting process (0-success, <0 error)
*/
ClassError::Error acqImpedancePolarity(const bool& unipolar);
/*!
\brief Sets class acq input to normal (bio signal captured from channels)
\return Integer indicating the success of the setting process (0-success, <0 error)
*/
ClassError::Error acqInputNormal();
/*!
\brief Sets class acq input to test. The class will provide a quadratic signal. It is useful for testing and not getting saturated signal all the time.
\return Integer indicating the success of the setting process (0-success, <0 error)
*/
ClassError::Error acqInputTest();
/*!
\brief Sends the request for battery level
\return Integer indicating the success of the starting process (0-success, <0 error)
*/
ClassError::Error batteryLevel();
/*!
\brief Sets the duration of the buffer (ms*frequency//1000.0)
\param ms Time in ms
\return Integer indicating the success of the setting process (0-success, <0 error)
*/
ClassError::Error bufferDuration(const double& ms);
/*!
\brief Sets buzzer on
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error buzzerPlay();
/*!
\brief Sends the request for buzzer
\return Integer indicating the success of the starting process (0-success, <0 error)
*/
ClassError::Error buzzerStatus();
/*!
\brief Sets ms of buzzer song
\param tempo time in ms
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error buzzerTempo(const std::string& tempo);
/*!
\brief Connect to the CLASS server
\param server_ip IP of the CLASS server
\param server_port of the CLASS server
\param local_ip IP in which the instance is listening for messages coming from CLASS server
\param local_port Port in which the instance is listening for messages coming from CLASS server
\return Integer indicating the success of the connection (0-success, <0 error)
*/
ClassError::Error connect(const std::string & server_ip, const int & server_port, const std::string & local_ip, const int & local_port);
/*!
\brief Sends the request for device name
\return Integer indicating the success of the starting process (0-success, <0 error)
*/
ClassError::Error deviceName();
/*!
\brief Sets name of device
\param devicename Name of the device
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error devName(const std::string& devicename);
/*!
\brief Disconnect from the CLASS server
\return Integer indicating the success of the disconnection (0-success, <0 error)
*/
ClassError::Error disconnect();
/*!
\brief Sets electrode pads number
\param id Electrode number/ID
\param pads_number Number of pads of the electrode
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error elecPads(const int& id, const int& pads_number);
/*!
\brief Sends the request for firmware version
\return Integer indicating the success of the starting process (0-success, <0 error)
*/
ClassError::Error firmwareVersion();
/*!
\brief Sends the request for frequency
\return Integer indicating the success of the starting process (0-success, <0 error)
*/
ClassError::Error frequencyStatus();
/*!
\brief Sets the config for impedance acquisition
\param acq_frames Vector to fill with acqusition frames
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error getAcqFrames(std::vector<AcqFrame>& acq_frames);
/*!
\brief Sends the request for hardware version
\return Integer indicating the success of the starting process (0-success, <0 error)
*/
ClassError::Error hardwareVersion();
/*!
\brief Sets high voltage to off
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error hvOff();
/*!
\brief Sets high voltage to on
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error hvOn();
/*!
\brief Sends the request for high voltage status
\return Integer indicating the success of the starting process (0-success, <0 error)
*/
ClassError::Error hvStatus();
/*!
\brief Sets high voltage value
\param hvvalue value of high voltage
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error hvValue(const std::string& hvvalue);
/*!
\brief Sets the order of the filter used for impedance calculation
\param order Filter order (>0)
\return Integer indicating the success of the setting process (0-success, <0 error)
*/
ClassError::Error impedanceFilterOrder(const int& order);
/*!
\brief Init communication
\param init_mode Initialization mode
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error initCommunication(const std::string& init_mode);
/*!
\brief Sends the request for interval status
\return Integer indicating the success of the starting process (0-success, <0 error)
*/
ClassError::Error intervalStatus();
/*!
\brief Sets stimulation inter pulses interval
\param interval value of stimulation inter pulses
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error intervalValue(const std::string& interval);
/*!
\brief Sets logevents to off
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error logeventsOff();
/*!
\brief Sets logevents to on
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error logeventsOn();
/*!
\brief Sends the request for logevents
\return Integer indicating the success of the starting process (0-success, <0 error)
*/
ClassError::Error logeventsStatus();
/*!
\brief Sets pattern
\param number pattern number
\param pat vector of patterns
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error pattern(const int& number, const std::vector<Pattern>& pat);
/*!
\brief Clear pattern
\param id pattern to delete
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error patternClear(const int& id);
/*!
\brief Sends the request for pattern
\param number pattern
\return Integer indicating the success of the starting process (0-success, <0 error)
*/
ClassError::Error patternStatus(const int& number);
/*!
\brief Sends the request for pattern
\param number pattern
\return Integer indicating the success of the starting process (0-success, <0 error)
*/
ClassError::Error velecStatus(const int& number);
/*!
\brief Sets rtc date
\param rtcdate mm/dd/yyyy format
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error rtcDate(const std::string& rtcdate);
/*!
\brief Sends the request for rtc
\return Integer indicating the success of the starting process (0-success, <0 error)
*/
ClassError::Error rtcStatus();
/*!
\brief Sets rtc time
\param rtctime hh:mm:ss format
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error rtcTime(const std::string& rtctime);
/*!
\brief Sends the request for sd function
\return Integer indicating the success of the starting process (0-success, <0 error)
*/
ClassError::Error sdfunctionStatus();
/*!
\brief Sets name of sdcard folder where the pattern are saved
\param sdfunctionname name of the folder
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error sdFunctionName(const std::string& sdfunctionname);
/*!
\brief Sets name of sdcard folder where the folder containing the patterns is saved
\param sduname name of the folder
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error sdUName(const std::string& sduname);
/*!
\brief Sends the request for sd user name
\return Integer indicating the success of the starting process (0-success, <0 error)
*/
ClassError::Error sdunameStatus();
/*!
\brief Sends custom command to CLASS device
\param cmd Command
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error sendCustomCmd(const std::string& cmd);
/*!
\brief Sets class acq configuration
\param frequency Frequency of acquisition
\param channel_numbers Channel numbers
\param gain Gain of the acquisition
\param input Acq input type, normal or test
\return Integer indicating the success of the setting process (0-success, <0 error)
*/
ClassError::Error setAcqConfig(const double& frequency, const std::vector<int>& channel_numbers, const double& gain, const std::string& input);
/*!
\brief Sets the callback
\param callback Callback
\param language Language which has defined the callback
\return Integer indicating the success of the starting process (0-success, <0 error)
*/
ClassError::Error setCallback(ClassCallback* callback, std::string language);
/*!
\brief Turn off
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error shutdown();
/*!
\brief Sets frequency of the stimulation
\param frequency Frequency of the stimulation
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error stimFreq(const double& frequency);
/*!
\brief Stops stimulation
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error stimOff();
/*!
\brief Starts stimulation
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error stimOn();
/*!
\brief Starts stimulation of the virtual electrode which name is passed as parameter
\param name Name of the virtual electrode
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error stimVelec(const std::string& name);
/*!
\brief Sends the request for tic
\return Integer indicating the success of the starting process (0-success, <0 error)
*/
ClassError::Error tic();
/*!
\brief Handles the reception of an UDP msg from the CLASS server
\param msg Msg
\param ip IP the message comes from
*/
void udpMsgReceived(std::string msg, std::string client_ip);
/*!
\brief Sets virtual electrode
\param number Virtual electrode number/ID
\param name Name of the virtual electrode
\param electrode_id Electrode ID/number
\param cathodes List of integers with the IDs of the pads acting as cathodes
\param anodes List of integers with the IDs of the pads acting as cathodes
\param amp List of doubles with the amplitude (in mA) associated to each of the cathodes. Must have the same length as cathodes
\param width List of integers with the pulse width (in uS) associated to each of the cathodes. Must have the same length as cathodes
\param selected Defines if the velec is selected (‘true’ value) or deselected (‘false’ value). Only selected velecs will be executed with a “stim on” command
\param sync Defines if the velec is synchronous (‘rtue’ value) or asynchronous (‘false’ value).
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error velec(const int& id, const std::string& name, const int& electrode_id, const std::vector<int>& cathodes, const std::vector<int>& anodes, const std::vector<double>& amp, const std::vector<int>& width, const bool& selected, const bool& sync);
/*!
\brief Sets whether the virtual electrode is selected or not
\param id Virtual electrode number/ID
\param selected Defines if the velec is selected (‘true’ value) or deselected (‘false’ value). Only selected velecs will be executed with a “stim on” command.
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error velecSelected(const int& id, const bool& selected);
/*!
\brief Sets whether the virtual electrodes are selected or not
\param id Vector with virtual electrode number/ID.
\param selected Vector of bool values indicating whether the virtual electrode is selected
\return Integer indicating the success of the process (0-success, <0 error)
*/
ClassError::Error velecsSelected(const std::vector<int>& id, const std::vector<bool>& selected);
private:
/*!
\brief Sends msg through serial
\param msg Msg to send.
\return Integer indicating the success of the starting process (0-success, <0 error)
*/
ClassError::Error sendMsg(std::string msg);
/*!
\brief Sends msgs through serial
\param msgs Vector with msgs to send.
\return Integer indicating the success of the starting process (0-success, <0 error)
*/
ClassError::Error sendMsgs(std::vector<std::string> msgs);
/*!
\brief Updates buffer capacity based on acq rate and seconds
\param seconds Buffer duration.
\return Integer indicating the success of the starting process (0-success, <0 error)
*/
ClassError::Error setBufferCapacity(const double& seconds);
/*!
\brief Configures the filter for impedance
\param order Order of the filter
\param low_freq Lower frequency of the band
\param up_freq Upper freqeuncy of the band
\param acq_freq Sampling rate
\return Integer indicating the success of the starting process (0-success, <0 error)
*/
ClassError::Error configureFilter(int order, double low_freq, double up_freq, double acq_freq);
/*!
\brief Sets the number of digits after decimal
\param value Value
\param digits_after_decimal Number of desired digits after decimal
\return Pair with the new_value and a bool indicating whether the operation has enough precision
*/
std::pair< double, bool > trunc_n( double value, std::size_t digits_after_decimal);
/*!
\brief Increases lock error number
*/
void increaseLockError();
//! UDP server where it listens for command coming form the CLASS server
UDPServer *udp_server_;
//! UDP client which sends messages to CLASS server
UDPClient *udp_client_;
//! indicates the IP where the CLASS server is listening
std::string server_ip_;
//! indicates the port where the CLASS server is listening
int server_port_;
//! indicates the local IP where the instance is listening for messages coming from CLASS server
std::string local_ip_;
//! indicates the local port where the instance is listening for messages coming from CLASS server
int local_port_;
//! defined electrodes
std::vector<Elec> electrodes_;
//! defined virual electrodes
std::vector<Velec> virtual_electrodes_;
//! indicates whether it is acquiring frames
bool is_acquiring_frames_;
//! is_acquiring_frames mutex
std::mutex is_acquiring_frames_mutex_;
//! number of channels
int channels_number_;
//! frequency of the acquisition
double acq_frequency_;
//! acquisition time (determinates buffer maximum size)
double acq_seconds_;
//! acquisition time
int acq_buffer_capacity_;
//! acquisition buffer
boost::circular_buffer<AcqFrame> acq_buffer_;
//! acquisition buffer mutex
std::mutex acq_buffer_mutex_;
//! indicates whether it is acquiring impedances
bool is_acquiring_impedances_;
//! is_acquiring_frames mutex
std::mutex is_acquiring_impedances_mutex_;
//! acquisition time
int acq_impedances_buffer_capacity_;
//! acquisition buffer
boost::circular_buffer<AcqFrame> acq_impedances_buffer_;
//! acquisition buffer mutex
std::mutex acq_impedances_buffer_mutex_;
//! butterworth filters, one per channel
Butterworth **butterworth_;
//! order of the filter
int filter_order_;
//! thread for waiting messages
std::thread *waiting_thread_;
//! function for waiting messages
void waitingThreadFunction_();
//! Indicates whether to wait for special messages
bool waiting_;
//! Mutex for waiting
std::mutex waiting_mutex_;
//! indicates whether it is waiting for tic
bool tic_received_;
//! indicates whether tic has been received
bool is_waiting_tic_;
//! mutex for tic
std::mutex tic_mutex_;
//! indicates whether it is waiting for firmware
bool firmware_received_;
//! indicates whether firmware has been received
bool is_waiting_firmware_;
//! mutex for firmware
std::mutex firmware_mutex_;
//! indicates whether it is waiting for device name
bool device_received_;
//! indicates whether device name has been received
bool is_waiting_device_;
//! mutex for firmware
std::mutex device_mutex_;
//! indicates whether it is waiting for hardware
bool hardware_received_;
//! indicates whether hardware has been received
bool is_waiting_hardware_;
//! mutex for hardware
std::mutex hardware_mutex_;
//! indicates whether it is waiting for battery
bool battery_received_;
//! indicates whether battery has been received
bool is_waiting_battery_;
//! mutex for battery
std::mutex battery_mutex_;
//! indicates whether it is waiting for logevents
bool logevents_received_;
//! indicates whether logevents has been received
bool is_waiting_logevents_;
//! mutex for logevents
std::mutex logevents_mutex_;
//! indicates whether it is waiting for high voltage status
bool hvstatus_received_;
//! indicates whether high voltage status has been received
bool is_waiting_hvstatus_;
//! mutex for high voltage status
std::mutex hvstatus_mutex_;
//! indicates whether it is waiting for interval status
bool intervalstatus_received_;
//! indicates whether interval status has been received
bool is_waiting_intervalstatus_;
//! mutex for interval status
std::mutex intervalstatus_mutex_;
//! indicates whether it is waiting for rtc status
bool rtcstatus_received_;
//! indicates whether rtc status has been received
bool is_waiting_rtcstatus_;
//! mutex for rtc status
std::mutex rtcstatus_mutex_;
//! indicates whether it is waiting for buzzer status
bool buzzerstatus_received_;
//! indicates whether buzzer status has been received
bool is_waiting_buzzerstatus_;
//! mutex for buzzer status
std::mutex buzzerstatus_mutex_;
//! indicates whether it is waiting for frequency status
bool frequencystatus_received_;
//! indicates whether frequency status has been received
bool is_waiting_frequencystatus_;
//! mutex for frequency status
std::mutex frequencystatus_mutex_;
//! indicates whether it is waiting for sdfunction
bool sdfunction_received_;
//! indicates whether sdfunction has been received
bool is_waiting_sdfunction_;
//! mutex for sdfunction
std::mutex sdfunction_mutex_;
//! indicates whether it is waiting for sduname
bool sduname_received_;
//! indicates whether sduname has been received
bool is_waiting_sduname_;
//! mutex for sduname
std::mutex sduname_mutex_;
//! indicates whether it is waiting for pattern
bool patternstatus_received_;
//! indicates whether pattern has been received
bool is_waiting_patternstatus_;
//! mutex for logevents
std::mutex patternstatus_mutex_;
//! indicates whether it is waiting for velecstatus
bool velecstatus_received_;
//! indicates whether velecstatus has been received
bool is_waiting_velecstatus_;
//! mutex for velecstatus
std::mutex velecstatus_mutex_;
//! battery level
double battery_;
// tic text
std::string tic_;
// firmware text
std::string firmware_;
// hardware text
std::string hardware_;
// device text
std::string device_;
// logevents text
std::string logevents_;
// high voltage status text
std::string hvstatus_;
// interval status text
std::string intervalstatus_;
// rtc status text
std::string rtcstatus_;
// buzzer status text
std::string buzzerstatus_;
// frequency status text
std::string frequencystatus_;
// sdfunction status text
std::string sdfunctionstatus_;
// sduname status text
std::string sdunamestatus_;
// pattern status text
std::string patternstatus_;
// velecstatus text
std::string velecstatus_;
//! mutex for lock errors
std::mutex lock_error_mutex_;
//! number of lock errors
int lock_error_number_;
//! max number of lock errors before launching error
int lock_error_number_max_;
//! thread for lock errors
std::thread *lock_error_thread_;
//! function for lock error
void lockErrorThreadFunction_();
//! Indicates whether to wait for special messages
bool error_waiting_;
//! callback for battery, turn_off, etc.
ClassCallback* class_cb_;
//! Language which has defined the callback
std::string language_;
//! acq gainb
double gain_;
//! log function
#define log_stream_(x) log_(std::stringstream() << x);
#define log_warn_stream_(x) log_warn_(std::stringstream() << x);
#define log_error_stream_(x) log_err_(std::stringstream() << x);
void log_(const std::string &text);
void log_(const std::stringstream &text);
void log_(std::ostream & text);
void log_err_(const std::string &text);
void log_err_(std::ostream & text);
void log_warn_(const std::string &text);
void log_warn_(std::ostream & text);
};
/**
* @brief Class for locking when accesing callback in Python
*/
class PyThreadStateLock
{
public:
PyThreadStateLock(void)
{
state = PyGILState_Ensure( );
}
~PyThreadStateLock(void)
{
PyGILState_Release( state );
}
private:
PyGILState_STATE state;
};
#endif // CLASS_CORE_HPP
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment