Skip to content
Snippets Groups Projects
TIMIQCurl.cpp 17.5 KiB
Newer Older
ELATTAOUI's avatar
ELATTAOUI committed
//=============================================================================
// TIMIQCurl.cpp
//=============================================================================
// abstraction.......TIMIQCurl Low level access to TIMIQ hardware
// class.............TIMIQCurl 
// original author...J. GOUNO - NEXEYA-FRANCE
//=============================================================================

// ============================================================================
// DEPENDENCIES
// ============================================================================
#include "TIMIQCurl.h"
#include <iostream>
#include <string.h>
#include <yat/utils/StringTokenizer.h>
#include <yat/utils/XString.h>

namespace TIMIQLib_ns {

// ============================================================================
// static variables & functions
// ============================================================================
//- timiq internal web buffer
static std::string m_timiq_internal_buff;	

// ----------------------------------------------------------------------------
// write callback functions
// @param buffer data , size*nmemb buffer size, void userp 
// @return size*nmemb buffer size
// ----------------------------------------------------------------------------
static size_t write_callback( char *buffer, size_t size, size_t nmemb, void* )
{
	// std::cout<<"static size_t write_callback <"<<size<<">  nmemb<"<<nmemb<<">"<<std::endl;
	for (size_t idx = 0; idx < size*nmemb; idx++ )
		m_timiq_internal_buff.push_back(buffer[idx]);
	return size*nmemb;
}

ELATTAOUI's avatar
ELATTAOUI committed
// ============================================================================
// TIMIQCurl::TIMIQCurl
// ============================================================================
TIMIQCurl::TIMIQCurl(const std::string& ip_address, const std::string& num_port)
{
	//std::cout << "TIMIQCurl constructor" << std::endl;
	m_base_addr = kHTTP_WEB_PROTOCOL + ip_address + ":"+ num_port;
ELATTAOUI's avatar
ELATTAOUI committed
	
	m_error_string = "";
ELATTAOUI's avatar
ELATTAOUI committed
	m_hw_curl = NULL; 
}

// ============================================================================
// TIMIQCurl::~TIMIQCurl
// ============================================================================
TIMIQCurl::~TIMIQCurl ()
{
	m_hw_curl = NULL; 
}

// ============================================================================
// TIMIQCurl::write_data
// ============================================================================
E_timiq_errno_t  TIMIQCurl::write_data(float& data)
{
	E_timiq_errno_t  err_num = timiq_internal_ERROR;
		
	char buff[kMAX_DATA_SIZE];
    memset(buff, 0, sizeof(buff));
	sprintf(buff, "%s=%2.3f", (char*)kTIMIQ_DATA_KEY.c_str(), data);
	std::string strbuff(buff);

	//- request to the web page
	//  http://address/set_data
	std::string str_url = m_base_addr + kTIMIQ_DATA_PAGE+ "?" + strbuff;
	
	if (this->write_i(str_url, strbuff))
		err_num = timiq_NO_ERROR;
		
	return err_num;
}

// ============================================================================
// TIMIQCurl::write_iValue
// ============================================================================
E_timiq_errno_t  TIMIQCurl::write_iValue(float& iValue)
{
	E_timiq_errno_t  err_num = timiq_internal_ERROR;
		 
	char buff[kMAX_DATA_SIZE];
    memset(buff, 0, sizeof(buff));
	sprintf(buff, "%s=%1.6f",  kTIMIQ_IVALUE_KEY.c_str() , iValue);
	std::string strbuff(buff);

	//- request to the web page 
	//  http://address/set_iValue
	std::string str_url = m_base_addr + kTIMIQ_IVALUE_PAGE + "?" + strbuff;

	if (this->write_i(str_url, strbuff))
		err_num = timiq_NO_ERROR;
	
	return err_num;
}
			
// ============================================================================
// TIMIQCurl::write_qValue
// ============================================================================
E_timiq_errno_t  TIMIQCurl::write_qValue(float& qValue)
{
	E_timiq_errno_t  err_num = timiq_internal_ERROR;
	
	char buff[kMAX_DATA_SIZE];
    memset(buff, 0, sizeof (buff));
	sprintf(buff, "%s=%1.6f", kTIMIQ_QVALUE_KEY.c_str(), qValue);
	std::string strbuff(buff);
	
	//- request to the web page
	//  http://address/set_qValue
	std::string str_url = m_base_addr + kTIMIQ_QVALUE_PAGE + "?" + strbuff;

	if (this->write_i(str_url, strbuff))
		err_num = timiq_NO_ERROR;
	
	return err_num;
}
			
// ============================================================================
// TIMIQCurl::write_boardTemperature
// ============================================================================
E_timiq_errno_t  TIMIQCurl::write_boardTemperature(float& boardTemperature)
{
	E_timiq_errno_t  err_num = timiq_internal_ERROR;
	
	char buff[kMAX_DATA_SIZE];
    memset(buff, 0, sizeof (buff));
	sprintf(buff, "%s=%2.3f", kTIMIQ_BOARD_TEMPERATURE_KEY.c_str(),  boardTemperature);
	std::string strbuff(buff);

	//- request to the web page  
	//  http://address/set_boardTemperature.wsgi
	std::string str_url = m_base_addr + kTIMIQ_BOARD_TEMPERATURE_PAGE + "?" + strbuff;

	if (this->write_i(str_url, strbuff))
		err_num = timiq_NO_ERROR;
	
	return err_num;
}
			
// ============================================================================
// TIMIQCurl::write_command
// ============================================================================
E_timiq_errno_t  TIMIQCurl::write_command(E_timiq_cmd_t& cmd)
{
	E_timiq_errno_t  err_num = timiq_internal_ERROR;
	
	char buff[kMAX_DATA_SIZE];
    memset(buff, 0, sizeof(buff));
	sprintf(buff, "%s=%d", kTIMIQ_COMMAND_KEY.c_str(), (unsigned short)cmd);
	std::string strbuff(buff);
	
	//- request to the web page  
	//  http://address/set_command
	std::string str_url = m_base_addr + kTIMIQ_COMMAND_PAGE + "?" + strbuff;

	if (this->write_i(str_url, strbuff))
		err_num = timiq_NO_ERROR;
	
	return err_num;
}
		
// ============================================================================
// TIMIQCurl::read_data
// ============================================================================
E_timiq_errno_t  TIMIQCurl::read_data(float& data)
{
	E_timiq_errno_t  err_num = timiq_internal_ERROR;
	
	//- request to the web page  
	//  http://address/get_data.wsgi
	std::string str_url = m_base_addr + kTIMIQ_DATA_PAGE;
	
	if (this->read_float_i(str_url, kTIMIQ_DATA_KEY, data))
		err_num = timiq_NO_ERROR;

	return err_num;
}
	
// ============================================================================
// TIMIQCurl::read_iValue
// ============================================================================
E_timiq_errno_t  TIMIQCurl::read_iValue(float& iValue)
{
	E_timiq_errno_t  err_num = timiq_internal_ERROR;
	
	//- request to the web page  
	//  http://address/get_feedback.wsgi
	std::string str_url = m_base_addr + kTIMIQ_FEEDBACK_PAGE;

	if (this->read_float_i(str_url, kTIMIQ_IVALUE_KEY, iValue))
		err_num = timiq_NO_ERROR;
	
	return err_num;
}

// ============================================================================
// TIMIQCurl::read_qValue
// ============================================================================
E_timiq_errno_t  TIMIQCurl::read_qValue(float& qValue)
{
	E_timiq_errno_t  err_num = timiq_internal_ERROR;
	
	//- request to the web page  
	//  http://address/get_feedback.wsgi
	std::string str_url = m_base_addr + kTIMIQ_FEEDBACK_PAGE;
	
	if (this->read_float_i(str_url, kTIMIQ_QVALUE_KEY, qValue))
		err_num = timiq_NO_ERROR;
	
	return err_num;
}
		
// ============================================================================
// TIMIQCurl::read_mixerCosOutput
// ============================================================================
E_timiq_errno_t  TIMIQCurl::read_mixerCosOutput(float& mixerCosOutput)
{
	E_timiq_errno_t  err_num = timiq_internal_ERROR;
	
	//- request to the web page  
	//- http://address/get_feedback.wsgi
	std::string str_url = m_base_addr + kTIMIQ_FEEDBACK_PAGE;
	
	if (this->read_float_i(str_url, kTIMIQ_MIXER_COS_OUTPUT_KEY, mixerCosOutput))
		err_num = timiq_NO_ERROR;
		
	return err_num;
}
		
// ============================================================================
// TIMIQCurl::read_mixerSinOutput
// ============================================================================
E_timiq_errno_t  TIMIQCurl::read_mixerSinOutput(float& mixerSinOutput)
{
	E_timiq_errno_t  err_num = timiq_internal_ERROR;
	
	//- request to the web page  
	//- http://address/get_feedback.wsgi
	std::string str_url = m_base_addr + kTIMIQ_FEEDBACK_PAGE;

	if (this->read_float_i(str_url, kTIMIQ_MIXER_SIN_OUTPUT_KEY, mixerSinOutput))
		err_num = timiq_NO_ERROR;
	
	return err_num;
}
		
// ============================================================================
// TIMIQCurl::read_boardTemperature
// ============================================================================
E_timiq_errno_t  TIMIQCurl::read_boardTemperature(float& boardTemperature)
{
	E_timiq_errno_t  err_num = timiq_internal_ERROR;
	
	//- request to the web page  
	//- http://address/get_feedback.wsgi
	std::string str_url = m_base_addr + kTIMIQ_FEEDBACK_PAGE;

	if (this->read_float_i(str_url, kTIMIQ_BOARD_TEMPERATURE_KEY, boardTemperature))
		err_num = timiq_NO_ERROR;
	
	return err_num;
}

// ============================================================================
// TIMIQCurl::read_state_and_status
// ============================================================================
E_timiq_errno_t  TIMIQCurl::read_state_and_status(std::string& status, E_timiq_code_t& codeRet)
{
	E_timiq_errno_t  err_num = timiq_internal_ERROR;
	
	//- request to the web page  
	//- http://address/get_state.wsgi
	std::string str_url = m_base_addr + kTIMIQ_STATE_PAGE;

	if (this->read_state_and_status_i(str_url, status, codeRet))
		err_num = timiq_NO_ERROR;
	
	return err_num;
}

// ============================================================================
// TIMIQCurl::connect_i
// ============================================================================
E_timiq_errno_t TIMIQCurl::connect_i()
{
	E_timiq_errno_t  err_num = timiq_internal_ERROR;
	m_error_string = "";
	
	try
	{
		if (!m_hw_curl)
ELATTAOUI's avatar
ELATTAOUI committed
		{
			m_hw_curl = curl_easy_init();
				
			if (m_hw_curl) 
			{
				err_num = timiq_NO_ERROR;
			}
			else
			{ 
				m_error_string = "INTERNAL_ERROR\n"; 
				m_error_string += "TIMIQ WebServer access is not available, null pointer detected!\n"; 
				m_error_string += "TIMIQCurl::connect()"; 
			}
ELATTAOUI's avatar
ELATTAOUI committed
		}
		else
		{ 
			m_error_string = "TIMIQ WebServer access allows only single session!\n"; 
ELATTAOUI's avatar
ELATTAOUI committed
			m_error_string += "TIMIQCurl::connect()"; 
ELATTAOUI's avatar
ELATTAOUI committed
	}
	catch (...)
	{
		m_error_string = "TIMIQCurl::connect: exception while initialize Webserver...";
		m_hw_curl = NULL;
	}
	return err_num;
}

// ============================================================================
// TIMIQCurl::write_i
// ============================================================================
bool TIMIQCurl::write_i(std::string& url, std::string& strData)
{
	//- CURL easy return code
	CURLcode result;
	
	m_error_string = "";

#if !defined (_SIMULATION_)	
	//- no connection is possible
	if (this->connect_i() != timiq_NO_ERROR)
		return false;
	
	try
	{
		result = send_to_webserver_i(url);
ELATTAOUI's avatar
ELATTAOUI committed
	}	
	catch (...)
	{
		m_error_string = "TIMIQCurl::write_i: exception while writing data on" + url;
		return false;
	}
	
	//- check the result
	//----------------------------
	if (result != CURLE_OK)
	{
		//- HTTP error 
		m_error_string = m_timiq_internal_buff;
		return false;		
	}
	else
	//- check the data returned
	{
#else	
	m_timiq_internal_buff = "\ncommand=1\n";
	m_timiq_internal_buff += "command=2\n";
	m_timiq_internal_buff += "command=3\n";
ELATTAOUI's avatar
ELATTAOUI committed
	m_timiq_internal_buff += "iValue=-0.000001\n";
	m_timiq_internal_buff += "qValue=-0.000002";
	
#endif
		std::size_t found = m_timiq_internal_buff.find(strData);	
		if (found != std::string::npos)
		{
			m_error_string = "OK";
			return true;
		}
		else
		{
			//- otherwise error
			m_error_string = m_timiq_internal_buff;	
		}
#if !defined (_SIMULATION_)	
	}
#endif	
	return false;
}

// ============================================================================
// TIMIQCurl::read_float_i
// ============================================================================
bool TIMIQCurl::read_float_i(const std::string& url, const std::string& strData, float& value )
{
	// std::cout <<"TIMIQCurl::read_float_i"<<std::endl;
	//- CURL easy return code
	CURLcode result;
	
	m_error_string = "";

#if !defined (_SIMULATION_)	
	//- no connection is possible
	if (this->connect_i() != timiq_NO_ERROR)
		return false;
ELATTAOUI's avatar
ELATTAOUI committed
	try
	{
		result = send_to_webserver_i(url);
ELATTAOUI's avatar
ELATTAOUI committed
	}	
	catch (...)
	{
		m_error_string = "TIMIQCurl::read_float_i: exception while reading data on " + url;
		return false;
	}
	
	//- check the result
	//----------------------------
	if (result != CURLE_OK)
	{
		//- HTTP error 
		char buff[kMAX_DATA_SIZE];
		memset(buff, 0, sizeof(buff));
		sprintf (buff, "TIMIQCurl::read_float_i - CURL code error <%d>",result);
		m_error_string = buff;	
ELATTAOUI's avatar
ELATTAOUI committed
		return false;		
	}
	else
	//- check the data returned	
	{
#else
	m_timiq_internal_buff = "\niValue=-0.000001\n";
	m_timiq_internal_buff += "qValue=0.000002\n";
	m_timiq_internal_buff += "mixerSinOutput=3.100000\n";
	m_timiq_internal_buff += "mixerCosOutput=0.154600\n";
	m_timiq_internal_buff += "boardTemperature=20.154";
#endif	
		
		std::size_t index = m_timiq_internal_buff.find(strData);	
		if (index != std::string::npos)
		{
			//- extract substring from index 
			std::string l_subStr = m_timiq_internal_buff.substr(index);
			
			//- parse "="
			yat::StringTokenizer tokfloatStr (l_subStr, "=");
			try
			{
				//- field  
				std::string fieldStr = tokfloatStr.next_token();

				//- value
				std::string floatStr =  tokfloatStr.next_token();
				
				//- convert data to float 
ELATTAOUI's avatar
ELATTAOUI committed
				value = (float)yat::XString<float>::to_num(floatStr);						
			}
			catch(...)
			{
				m_error_string = "TIMIQCurl::read_float_i: exception while converting data from " + url;
				m_error_string += m_timiq_internal_buff;
				return false;
			}
			
			//- success
			m_error_string = "OK";
			return true;
		}
		
		//- otherwise error
		m_error_string = m_timiq_internal_buff;
#if !defined (_SIMULATION_)			
	}
#endif
	return false;
}

// ============================================================================
// TIMIQCurl::read_state_and_status_i
// ============================================================================
bool TIMIQCurl::read_state_and_status_i(const std::string& url, std::string& status, E_timiq_code_t& codeRet )
{
	//- CURL easy return code
	CURLcode result;
	
	m_error_string = "";

#if !defined (_SIMULATION_)		
	//- no connection is possible
	if (this->connect_i() != timiq_NO_ERROR)
		return false;

	try
	{
		result = send_to_webserver_i(url);
ELATTAOUI's avatar
ELATTAOUI committed
	}	
	catch (...)
	{
		m_error_string = "TIMIQCurl::read_status_i: exception while reading TimIQ status on " + url;
		return false;
	}
	
	//- check the result
	//----------------------------
	if (result != CURLE_OK)
	{
		//- HTTP error
		char buff[kMAX_DATA_SIZE];
		memset(buff, 0, sizeof(buff));
		sprintf (buff, "TIMIQCurl::read_state_and_status_i - CURL code error <%d>",result);
		m_error_string = buff;	
ELATTAOUI's avatar
ELATTAOUI committed
		return false;		
	}
	else
	//- check the data returned
	{
#else
	m_timiq_internal_buff="message=System up and running\n";
	m_timiq_internal_buff+="state=OK\n";
	m_timiq_internal_buff+="code=1\n";
#endif
		bool b_found = true;
		
		//- key word: message
		std::size_t found = m_timiq_internal_buff.find(kTIMIQ_MESSAGE_KEY);	
		b_found = (found != std::string::npos);
			
		//- key word: state
		found = m_timiq_internal_buff.find(kTIMIQ_STATE_KEY);	
		b_found &=(found != std::string::npos);
			
		//- key word: code
		found = m_timiq_internal_buff.find(kTIMIQ_CODE_KEY);	
		b_found &=(found != std::string::npos);
			
		if (b_found)
		{
			//- extract the code value
			std::string strCode = m_timiq_internal_buff.substr(found);
			
			//- parse "="
			yat::StringTokenizer tokKeyword (strCode, "=");
			try
			{
				//- field
				std::string fieldStr = tokKeyword.next_token();
				
				//- value
				codeRet = (E_timiq_code_t) tokKeyword.next_int_token();	
			}
			catch(...)
			{
				m_error_string = "TIMIQCurl::read_state_and_status_i: exception while converting code from " + url;
				m_error_string += m_timiq_internal_buff;
				return false;
			}
		
			status = m_timiq_internal_buff;
			m_error_string = "OK";
			return true;
		}
		
		//- otherwise error
		m_error_string = m_timiq_internal_buff;
		
#if !defined (_SIMULATION_)	
	}
#endif
	return false;
}

// ============================================================================
// TIMIQCurl::send_to_webserver_i
// ============================================================================
CURLcode TIMIQCurl:: send_to_webserver_i(const std::string& url)
{
	
	CURLcode result;
	
	//- clean the timiq buffer data before perform
	m_timiq_internal_buff.clear();
	
	/* ask libcurl to set options */
	curl_easy_setopt(m_hw_curl, CURLOPT_URL, url.c_str());
	curl_easy_setopt(m_hw_curl, CURLOPT_PROXY, "");
	curl_easy_setopt(m_hw_curl, CURLOPT_WRITEFUNCTION, &write_callback);
	
	/* complete within 1500 ms */
	curl_easy_setopt(m_hw_curl,  CURLOPT_TIMEOUT_MS, 1500L);

	/* ask libcurl to show us the verbose output */
	// curl_easy_setopt(m_hw_curl, CURLOPT_VERBOSE, 1L);
	
	//- perform the query
	result = curl_easy_perform(m_hw_curl);
	//- clean up
	curl_easy_cleanup(m_hw_curl);
	m_hw_curl = NULL;
ELATTAOUI's avatar
ELATTAOUI committed
}