diff --git a/include/timiq/TIMIQLib.h b/include/timiq/TIMIQLib.h index 38fd667e3710beba53914b46edf3c7c6449e2e70..8d76b7fd398c43d35f6179add4f6514393044791 100644 --- a/include/timiq/TIMIQLib.h +++ b/include/timiq/TIMIQLib.h @@ -14,7 +14,7 @@ // ============================================================================ #include <TIMIQException.h> #include <TIMIQCurl.h> - +#include <yat/threading/Task.h> @@ -27,7 +27,53 @@ // =========================================================================== namespace TIMIQLib_ns { - + //------------------------------------------------------------------------ + // Class Description: + // Thread to write the values and commands on the TimIQ equipment + //------------------------------------------------------------------------ + class ThreadedAction : public yat::Thread + { + friend class TIMIQLib; + + protected: + //- ctor --------------------------------- + ThreadedAction ( yat::Thread::IOArg ioa, timIQConfig& cfg); + + //- dtor --------------------------------- + virtual ~ThreadedAction (void); + + //- thread's entry point + virtual yat::Thread::IOArg run_undetached (yat::Thread::IOArg ioa); + + //- asks this ThreadedAction to quit + virtual void exit (void); + + //- Thread state + bool isThreadAlive() + { + return m_goOn; + } + + bool isWriteDone() + { + return m_isActionDone; + } + + private: + + //- thread's ctrl flag + bool m_goOn; + + //- indicates if the threaded action is done + bool m_isActionDone; + + //- indicates if the threaded action has generated an error + bool m_isActionInError; + + //- Thread action configuration member + timIQConfig m_ti_cfg; + }; + //- low layer TimIQ curl class //----------------------------- @@ -40,6 +86,8 @@ namespace TIMIQLib_ns { //------------------------------------------------------------------------ class TIMIQLib { + friend class ThreadedAction; + public: // Contructor TIMIQLib (); @@ -114,9 +162,25 @@ namespace TIMIQLib_ns { //- port number std::string m_numPort; + //- internal timiq state + E_timiq_code_t m_internal_timiq_state; + + + protected: //- internal function //------------------------- // ... + + //- manage command by using task + ThreadedAction * m_timiq_task; + + void ExecuteAction(timIQConfig & cfg); + void iVal_end_task() throw (Exception); + void qVal_end_task() throw (Exception); + void data_end_task() throw (Exception); + void boardT_end_task() throw (Exception); + + }; } // namespace TIMIQLib_ns diff --git a/src/TIMIQLib.cpp b/src/TIMIQLib.cpp index 491fb2c04a171502e1e1d8fc373eaa76618d5819..19604a243efd1f1f5da0e59b6ec17e9600735b8d 100644 --- a/src/TIMIQLib.cpp +++ b/src/TIMIQLib.cpp @@ -33,6 +33,8 @@ TIMIQLib::TIMIQLib () m_timiq_hw = NULL; m_ipAddress = ""; m_numPort = ""; + m_internal_timiq_state = Undefined; + m_timiq_task = NULL; } // ============================================================================ // TIMIQLib::~TIMIQLib() @@ -44,6 +46,13 @@ TIMIQLib::~TIMIQLib() delete m_timiq_hw; m_timiq_hw = NULL; } + + //- + if (m_timiq_task) + { + m_timiq_task->exit(); + m_timiq_task = NULL; + } } // ============================================================================ // TIMIQLib::init @@ -73,21 +82,66 @@ void TIMIQLib::init(const std::string& ip_address, const short& num_port) // ============================================================================ void TIMIQLib::set_data(float data) throw (Exception) -{ - E_timiq_errno_t err; +{ + //- Threading configuration + timIQConfig l_ti_cfg; - CHECK_TIMIQ_HW; + //- set I value config + l_ti_cfg.id = TI_DATA; + l_ti_cfg.value = data; - //- write data value on TIMIQ equipment - err = m_timiq_hw->write_data(data); - if (err != timiq_NO_ERROR) + if ( m_internal_timiq_state != Busy ) { - std::string msg_err = "Set data error -msg: " + m_timiq_hw->get_err_msg(); - throw Exception(static_cast<const char*>("SOFTWARE_FAILURE"), - static_cast<const char*>(msg_err.c_str()), - static_cast<const char*>("TIMIQLib::set_data()")); + //- force timiq state = Busy + m_internal_timiq_state = Busy; + + m_timiq_task = new ThreadedAction(static_cast<yat::Thread::IOArg>(this), l_ti_cfg); + if (m_timiq_task == NULL) + { + std::string msg_err = "Set data error -msg: " + m_timiq_hw->get_err_msg(); + throw Exception(static_cast<const char*>("SOFTWARE_FAILURE"), + static_cast<const char*>(msg_err.c_str()), + static_cast<const char*>("TIMIQLib::set_data")); + } + + //- start the task to write data on TIMIQ equipment + m_timiq_task->start_undetached(); } -} +} + +// ============================================================================ +// TIMIQLib::data_end_task +// ============================================================================ +void TIMIQLib::data_end_task() + throw (Exception) +{ +// std::cout <<"data_end_task ..." <<std::endl; + //- Delete task + if (this->m_timiq_task) + { + if (m_timiq_task->m_ti_cfg.ti_err != timiq_NO_ERROR) + { + //std::cout <<"exit task done ..." <<std::endl; + m_timiq_task->exit(); + m_timiq_task = NULL; + + CHECK_TIMIQ_HW; + + std::string msg_err = "Set data error -msg: " + m_timiq_hw->get_err_msg(); + throw Exception(static_cast<const char*>("SOFTWARE_FAILURE"), + static_cast<const char*>(msg_err.c_str()), + static_cast<const char*>("TIMIQLib::data_end_task")); + } + + //- destroy otherwise + m_timiq_task->exit(); + delete m_timiq_task; + m_timiq_task = NULL; + } + + //- update state of TIMIQ equipment + m_internal_timiq_state = OK; +} // ============================================================================ // TIMIQLib::set_iValue @@ -95,20 +149,64 @@ void TIMIQLib::set_data(float data) void TIMIQLib::set_iValue(float iValue) throw (Exception) { - E_timiq_errno_t err; + //- Threading configuration + timIQConfig l_ti_cfg; - CHECK_TIMIQ_HW; + //- set I value config + l_ti_cfg.id = TI_IVAL; + l_ti_cfg.value = iValue; - //- write "I" tension value on TIMIQ equipment - err = m_timiq_hw->write_iValue(iValue); - if (err != timiq_NO_ERROR) + if ( m_internal_timiq_state != Busy ) { - std::string msg_err = "Set I value error -msg: " + m_timiq_hw->get_err_msg(); - throw Exception(static_cast<const char*>("SOFTWARE_FAILURE"), - static_cast<const char*>(msg_err.c_str()), - static_cast<const char*>("TIMIQLib::set_iValue()")); + //- force timiq state = Busy + m_internal_timiq_state = Busy; + + m_timiq_task = new ThreadedAction(static_cast<yat::Thread::IOArg>(this), l_ti_cfg); + if (m_timiq_task == NULL) + { + std::string msg_err = " Can't instanciate set I value task"; + throw Exception(static_cast<const char*>("SOFTWARE_FAILURE"), + static_cast<const char*>(msg_err.c_str()), + static_cast<const char*>("TIMIQLib::set_iValue")); + } + + //- start the task + m_timiq_task->start_undetached(); + } +} + +// ============================================================================ +// TIMIQLib::iVal_end_task +// ============================================================================ +void TIMIQLib::iVal_end_task() + throw (Exception) +{ +// std::cout <<"iVal_end_task ..." <<std::endl; + //- Delete task + if (this->m_timiq_task) + { + if (m_timiq_task->m_ti_cfg.ti_err != timiq_NO_ERROR) + { + //std::cout <<"exit task done ..." <<std::endl; + m_timiq_task->exit(); + m_timiq_task = NULL; + + CHECK_TIMIQ_HW; + + std::string msg_err = "Set I value error -msg: " + m_timiq_hw->get_err_msg(); + throw Exception(static_cast<const char*>("SOFTWARE_FAILURE"), + static_cast<const char*>(msg_err.c_str()), + static_cast<const char*>("TIMIQLib::set_iValue")); + } + + //- destroy otherwise + m_timiq_task->exit(); + m_timiq_task = NULL; } -} + + //- update state of TIMIQ equipment + m_internal_timiq_state = OK; +} // ============================================================================ // TIMIQLib::set_qValue @@ -116,40 +214,128 @@ void TIMIQLib::set_iValue(float iValue) void TIMIQLib::set_qValue(float qValue) throw (Exception) { - E_timiq_errno_t err; + //- Threading configuration + timIQConfig l_ti_cfg; - CHECK_TIMIQ_HW; + //- set Q value config + l_ti_cfg.id = TI_QVAL; + l_ti_cfg.value = qValue; - //- write "Q" tension value on TIMIQ equipment - err = m_timiq_hw->write_qValue(qValue); - if (err != timiq_NO_ERROR) + if ( m_internal_timiq_state != Busy ) { - std::string msg_err = "Set Q value error -msg: " + m_timiq_hw->get_err_msg(); - throw Exception(static_cast<const char*>("SOFTWARE_FAILURE"), - static_cast<const char*>(msg_err.c_str()), - static_cast<const char*>("TIMIQLib::set_qValue()")); + //- force timiq state = Busy + m_internal_timiq_state = Busy; + + m_timiq_task = new ThreadedAction(static_cast<yat::Thread::IOArg>(this), l_ti_cfg); + if (m_timiq_task == NULL) + { + std::string msg_err = "Set Q value error -msg: " + m_timiq_hw->get_err_msg(); + throw Exception(static_cast<const char*>("SOFTWARE_FAILURE"), + static_cast<const char*>(msg_err.c_str()), + static_cast<const char*>("TIMIQLib::set_qValue")); + } + + //- start the task to write "Q" tension value on TIMIQ equipment + m_timiq_task->start_undetached(); } } +// ============================================================================ +// TIMIQLib::qVal_end_task +// ============================================================================ +void TIMIQLib::qVal_end_task() + throw (Exception) +{ +// std::cout <<"qVal_end_task ..." <<std::endl; + //- Delete task + if (this->m_timiq_task) + { + if (m_timiq_task->m_ti_cfg.ti_err != timiq_NO_ERROR) + { + //std::cout <<"exit task done ..." <<std::endl; + m_timiq_task->exit(); + m_timiq_task = NULL; + + CHECK_TIMIQ_HW; + + std::string msg_err = "Set Q value error -msg: " + m_timiq_hw->get_err_msg(); + throw Exception(static_cast<const char*>("SOFTWARE_FAILURE"), + static_cast<const char*>(msg_err.c_str()), + static_cast<const char*>("TIMIQLib::qVal_end_task")); + } + + //- destroy otherwise + m_timiq_task->exit(); + m_timiq_task = NULL; + } + + //- update state of TIMIQ equipment + m_internal_timiq_state = OK; +} + // ============================================================================ // TIMIQLib::set_boardTemperature // ============================================================================ void TIMIQLib::set_boardTemperature(float boardTemperature) throw (Exception) { - E_timiq_errno_t err; + //- Threading configuration + timIQConfig l_ti_cfg; - CHECK_TIMIQ_HW; + //- set board temperature value config + l_ti_cfg.id = TI_BTEMP; + l_ti_cfg.value = boardTemperature; - //- write board temperature on TIMIQ equipment - err = m_timiq_hw->write_boardTemperature(boardTemperature); - if (err != timiq_NO_ERROR) + if ( m_internal_timiq_state != Busy ) { - std::string msg_err = "Set board Temperature error -msg: " + m_timiq_hw->get_err_msg(); - throw Exception(static_cast<const char*>("SOFTWARE_FAILURE"), - static_cast<const char*>(msg_err.c_str()), - static_cast<const char*>("TIMIQLib::set_boardTemperature()")); + //- force timiq state = Busy + m_internal_timiq_state = Busy; + + m_timiq_task = new ThreadedAction(static_cast<yat::Thread::IOArg>(this), l_ti_cfg); + if (m_timiq_task == NULL) + { + std::string msg_err = "Set board Temperature error -msg: " + m_timiq_hw->get_err_msg(); + throw Exception(static_cast<const char*>("SOFTWARE_FAILURE"), + static_cast<const char*>(msg_err.c_str()), + static_cast<const char*>("TIMIQLib::set_boardTemperature")); + } + + //- start the task to set board temperature on TIMIQ equipment + m_timiq_task->start_undetached(); + } +} + +// ============================================================================ +// TIMIQLib::boardT_end_task +// ============================================================================ +void TIMIQLib::boardT_end_task() + throw (Exception) +{ +// std::cout <<"boardT_end_task ..." <<std::endl; + //- Delete task + if (this->m_timiq_task) + { + if (m_timiq_task->m_ti_cfg.ti_err != timiq_NO_ERROR) + { + //std::cout <<"exit task done ..." <<std::endl; + m_timiq_task->exit(); + m_timiq_task = NULL; + + CHECK_TIMIQ_HW; + + std::string msg_err = "Set board Temperature error -msg: " + m_timiq_hw->get_err_msg(); + throw Exception(static_cast<const char*>("SOFTWARE_FAILURE"), + static_cast<const char*>(msg_err.c_str()), + static_cast<const char*>("TIMIQLib::boardT_end_task")); + } + + //- destroy otherwise + m_timiq_task->exit(); + m_timiq_task = NULL; } + + //- update state of TIMIQ equipment + m_internal_timiq_state = OK; } // ============================================================================ @@ -310,16 +496,129 @@ E_timiq_code_t TIMIQLib::get_state(std::string& status) CHECK_TIMIQ_HW; - //- read status of TIMIQ equipment - err = m_timiq_hw->read_state_and_status(status, retCode); - if (err != timiq_NO_ERROR) - { - std::string msg_err = "Get status error -msg: " + m_timiq_hw->get_err_msg(); - throw Exception(static_cast<const char*>("SOFTWARE_FAILURE"), - static_cast<const char*>(msg_err.c_str()), - static_cast<const char*>("TIMIQLib::get_status()")); + //- get internal timiq state + if (m_internal_timiq_state != Busy) + { + //- read status of TIMIQ equipment + err = m_timiq_hw->read_state_and_status(status, m_internal_timiq_state); + + if (err != timiq_NO_ERROR) + { + m_internal_timiq_state = Undefined; + std::string msg_err = "Get status error -msg: " + m_timiq_hw->get_err_msg(); + throw Exception(static_cast<const char*>("SOFTWARE_FAILURE"), + static_cast<const char*>(msg_err.c_str()), + static_cast<const char*>("TIMIQLib::get_status()")); + } } - return retCode; + + return m_internal_timiq_state; +} + +//***************************************************************************** +//***************************************************************************** +//***************************************************************************** +// Threaded actions for TimIQ equipment +//***************************************************************************** +//***************************************************************************** +//***************************************************************************** +// ============================================================================ +// ThreadedAction::ThreadedAction +// ============================================================================ +ThreadedAction::ThreadedAction ( yat::Thread::IOArg ioa, timIQConfig& cfg) + : yat::Thread(ioa), + m_goOn(true), + m_isActionDone(false), + m_ti_cfg(cfg) +{ + //- noop ctor +} + +// ============================================================================ +// ThreadedAction::~ThreadedAction +// ============================================================================ +ThreadedAction::~ThreadedAction (void) +{ + //- noop dtor +} + +// ============================================================================ +// ThreadedAction::run_undetached +// ============================================================================ +yat::Thread::IOArg ThreadedAction::run_undetached (yat::Thread::IOArg ioa) +{ + //DEBUG_STREAM << "ThreadedAction::run_undetached() entering... " << std::endl; + m_isActionDone = false; + + //- get the reference to parent task + TIMIQLib * l_task = reinterpret_cast<TIMIQLib *>(ioa); + l_task->ExecuteAction(m_ti_cfg); + + //- Action is done + m_isActionDone = true; + + return 0; +} + +// ============================================================================ +// ThreadedAction::exit +// ============================================================================ +void ThreadedAction::exit (void) +{ + this->m_goOn = false; +} + + +// ============================================================================ +// TIMIQLib::ExecuteAction +// ============================================================================ +void TIMIQLib::ExecuteAction(timIQConfig & cfg) +{ + E_timiq_errno_t err; + + CHECK_TIMIQ_HW; + + // E_timiq_code_t l_timiq_state = m_internal_timiq_state; + // if ( l_timiq_state != Busy ) + // { + //- force timiq state = Busy + // m_internal_timiq_state = Busy; + // Actions to be threaded + switch(cfg.id) + { + //- write "I" value + case TI_IVAL: + std::cout<<"Start executeAction - "<< cfg.id<< std::endl; + cfg.ti_err = m_timiq_hw->write_iValue(cfg.value); + std::cout<<"after executeAction - "<< cfg.id<< std::endl; + this->iVal_end_task(); + std::cout<<"End executeAction - "<< cfg.id<< std::endl; + break; + + //- write "Q" value + case TI_QVAL: + cfg.ti_err = m_timiq_hw->write_qValue(cfg.value); + this->qVal_end_task(); + break; + + //- write "DATA" value + case TI_DATA: + cfg.ti_err = m_timiq_hw->write_data(cfg.value); + this->data_end_task(); + break; + + //- write "BOARD Temperature" value + case TI_BTEMP: + cfg.ti_err = m_timiq_hw->write_data(cfg.value); + this->data_end_task(); + break; + default: + break; + } + + //- rollback timiq state to previous state + // m_internal_timiq_state = l_timiq_state; + // } } } // namespace timiqlib