Skip to content
Snippets Groups Projects
Commit dcdc3586 authored by Jacques Gouno's avatar Jacques Gouno
Browse files

TANGODEVIC-1636: Remove files src/cry_support/HWProxy.cpp, .h from project

parent dbe5837f
No related branches found
No related tags found
No related merge requests found
//- Project : Cryocooler, ACCEL/CRYOTHERM cryogenic cooler for optics at SOLEIL
//- file : HWProxy.cpp
//- threaded reading of the PLC Data Block
//- Writes on the PLC
//- Local HWProxy (not the 1 in PLCServerProxyHelper!)
#include "HWProxy.h"
#include <DBOffsets.h>
namespace CryoCooler_ns
{
//-----------------------------------------------
//- Ctor ----------------------------------------
HWProxy::HWProxy (size_t _periodic_exec_ms,
Tango::DeviceImpl * _host_device,
std::string _communication_device_name,
short _dbread,
short _dbwrite)
: Tango::LogAdapter (_host_device),
m_com_dev_name (_communication_device_name),
DB_start (0),
DB_end (0),
host_dev (_host_device),
db_read_number (_dbread),
db_write_number (_dbwrite)
{
DEBUG_STREAM << "HWProxy::HWProxy <- " << std::endl;
//-initialise the data buffer
//- TODO does memset initialises correctly the arrays?
::memset(this->plc_buffer, 0, sizeof(this->plc_buffer));
::memset(this->internal_buffer, 0, sizeof(this->internal_buffer));
last_error.resize (256);
//- yat::Task configure optional msg handling
this->enable_timeout_msg(false);
this->enable_periodic_msg(true);
this->set_periodic_msg_period(_periodic_exec_ms);
this->fetch_index = 0;
}
//-----------------------------------------------
//- Dtor ----------------------------------------
HWProxy::~HWProxy (void)
{
DEBUG_STREAM << "HWProxy::~HWProxy <- " << std::endl;
}
//-----------------------------------------------
//- the user core of the Task -------------------
void HWProxy::handle_message (yat::Message& _msg) throw (yat::Exception)
{
//- The DeviceTask's lock_ -------------
DEBUG_STREAM << "HWProxy::handle_message::receiving msg " << _msg.to_string() << std::endl;
//- handle msg
switch (_msg.type())
{
//- THREAD_INIT =======================
case yat::TASK_INIT:
{
DEBUG_STREAM << "HWProxy::handle_message::THREAD_INIT::thread is starting up" << std::endl;
//- "initialization" code goes here
try
{
DEBUG_STREAM << " HWProxy::handle_message handling TASK_INIT try to get device proxy on " << m_com_dev_name << std::endl;
//- this one gets the 50 first WORDS
DB_start = new PLCServerProxy (host_dev,
m_com_dev_name,
host_dev->get_name (),
db_read_number,
0,
50,
0,
0);
//- this one gets the 50 last WORDS (from 100 to 200)
DB_end = new PLCServerProxy (host_dev,
m_com_dev_name,
host_dev->get_name (),
db_read_number,
100,
50,
0,
0);
DB_write = new PLCServerProxy (host_dev,
m_com_dev_name,
host_dev->get_name (),
db_write_number,
0,
0,
0,
100);
this->com_error = 0;
this->consecutive_com_errors = 0;
this->com_success = 0;
this->com_state =HWP_NO_ERROR;
set_com_status ("HWP_NO_ERROR");
}
catch(...)
{
ERROR_STREAM << " HWProxy::handle_message::TASK_INIT exception caugth trying to get/ping device proxy on " << m_com_dev_name << std::endl;
set_last_error (" exception caugth trying to get device proxy on " + m_com_dev_name);
this->com_state =HWP_DEVICE_PROXY_ERROR;
set_com_status ("HWP_DEVICE_PROXY_ERROR");
return;
}
}
break;
//- TASK_EXIT =======================
case yat::TASK_EXIT:
{
DEBUG_STREAM << "HWProxy::handle_message handling TASK_EXIT thread is quitting" << std::endl;
//- "release" code goes here
if (DB_start)
{
delete DB_start;
DB_start = 0;
}
if (DB_end)
{
delete DB_end;
DB_end = 0;
}
if (DB_write)
{
delete DB_write;
DB_write = 0;
}
}
break;
//- TASK_PERIODIC ===================
case yat::TASK_PERIODIC:
{
DEBUG_STREAM << "HWProxy::handle_message handling TASK_PERIODIC msg" << std::endl;
//- code relative to the task's periodic job goes here
{
//- enter critical section
//- yat::AutoMutex<> guard (this->m_lock);
//- get the HW data
this->read_hard();
}
}
break;
//- TASK_TIMEOUT ===================
case yat::TASK_TIMEOUT:
{
//- code relative to the task's tmo handling goes here
DEBUG_STREAM << "HWProxy::handle_message handling TASK_TIMEOUT msg" << std::endl;
}
break;
//- USER_DEFINED_MSG ================
//- WRITE A REAL ----------------
case SET_REAL_MSG:
{
DEBUG_STREAM << "HWProxy::handle_message handling SET_REAL_MSG user msg" << std::endl;
//- get msg data...
struct WReal * wr = 0;
_msg.detach_data(wr);
if (wr)
{
try
{
//- must write the REAL to the PLC thanks to PLCServerProxy
//- the 1rst PLCServerProxy for the beginning of the DB
//- mutex
//- do not need mutex -> write in a different DB
//- yat::AutoMutex<> guard (this->m_lock);
DEBUG_STREAM << "HWProxy::handle_message (1) trying to write REAL value " << wr->value << " at offset " << wr->byte_offset << std::endl;
DB_write->write_float (wr->byte_offset, wr->value);
DB_write->write_bit (ACTION_REQUEST_BYTE_OFFSET, ACTION_REQUEST_BIT_OFFSET, true);
}
catch (...)
{
this->com_state = HWP_COMMUNICATION_ERROR;
set_com_status ("HWP_COMMUNICATION_ERROR");
std::stringstream s;
s << "last error occured trying to write REAL value " << wr->value << " at offset " << wr->byte_offset << std::endl;
set_last_error ( s.str());
delete wr;
break;
}
delete wr;
this->com_state = HWP_NO_ERROR;
set_com_status ("HWP_NO_ERROR");
}
break;
}
//- WRITE AN INT ----------------
case SET_INT_MSG:
{
DEBUG_STREAM << "HWProxy::handle_message handling SET_INT_MSG user msg" << std::endl;
//- get msg data...
struct WInt * wi = 0;
_msg.detach_data(wi);
if (wi)
{
try
{
//- must write the INT to the PLC thanks to PLCServerProxy
//- the 1rst PLCServerProxy for the beginning of the DB
//- mutex
//- do not need mutex -> write in a different DB
//- yat::AutoMutex<> guard (this->m_lock);
DEBUG_STREAM << "HWProxy::handle_message (1) trying to write INT value " << wi->value << " at offset " << wi->byte_offset << std::endl;
DB_write->write_short (wi->byte_offset, wi->value);
DB_write->write_bit (ACTION_REQUEST_BYTE_OFFSET, ACTION_REQUEST_BIT_OFFSET, true);
}
catch (...)
{
this->com_state = HWP_COMMUNICATION_ERROR;
set_com_status ("HWP_COMMUNICATION_ERROR");
std::stringstream s;
s << "last error occured trying to write REAL value " << wi->value << " at offset " << wi->byte_offset << std::endl;
set_last_error (s.str());
delete wi;
break;
}
delete wi;
this->com_state = HWP_NO_ERROR;
set_com_status ("HWP_NO_ERROR");
}
break;
}
//- WRITE A BOOL ----------------
case SET_BOOL_MSG:
{
DEBUG_STREAM << "HWProxy::handle_message handling SET_INT_MSG user msg" << std::endl;
//- get msg data...
struct WBool * wb = 0;
_msg.detach_data(wb);
if (wb)
{
try
{
//- mutex
//- yat::AutoMutex<> guard (this->m_lock);
//- must write the INT to the PLC thanks to PLCServerProxy
//- the 1rst PLCServerProxy for the beginning of the DB
DEBUG_STREAM << "HWProxy::handle_message (1) trying to write BOOL value " << wb->value << " at offset " << wb->byte_offset << "." << wb->bit_offset << std::endl;
DB_write->write_bit (wb->byte_offset, wb->bit_offset, wb->value);
DB_write->write_bit (ACTION_REQUEST_BYTE_OFFSET, ACTION_REQUEST_BIT_OFFSET, true);
}
catch (...)
{
this->com_state = HWP_COMMUNICATION_ERROR;
set_com_status ("HWP_COMMUNICATION_ERROR");
std::stringstream s;
s << "last error occured trying to write BOOL value " << wb->value << " at offset " << wb->byte_offset << "." << wb->bit_offset << std::endl;
set_last_error (s.str());
delete wb;
break;
}
delete wb;
this->com_state = HWP_NO_ERROR;
set_com_status ("HWP_NO_ERROR");
}
break;
}
} //- switch (_msg.type())
} //- HWProxy::handle_message
//-----------------------------------------------
//- Acces to REAL -------------------------------
float HWProxy::get_real (unsigned int byte_offset)
{
DEBUG_STREAM << "HWProxy::get_real get REAL value at offset " << byte_offset << std::endl;
if(consecutive_com_errors > MAX_COM_RETRIES)
{
this->com_state = HWP_COMMUNICATION_ERROR;
set_com_status ("HWP_COMMUNICATION_ERROR");
std::stringstream s;
s << "HWProxy::get_real last error : max consecutive comm errors retries limit reached " << std::endl;
set_last_error (s.str ());
Tango::Except::throw_exception(
static_cast<const char *>("COMMUNICATION_ERROR"),
static_cast<const char *>(s.str().c_str()),
static_cast<const char *>("HWProxy::get_real"));
}
if (byte_offset > 196)
{
this->com_state = HWP_SOFTWARE_ERROR;
set_com_status ("HWP_SOFTWARE_ERROR");
std::stringstream s;
s << "HWProxy::get_real last error occured trying to read a REAL " << " at offset " << byte_offset << std::endl;
set_last_error (s.str ());
Tango::Except::throw_exception(
static_cast<const char *>("OUT_OF_RANGE"),
static_cast<const char *>(s.str().c_str()),
static_cast<const char *>("HWProxy::get_real"));
}
union
{
long l;
float f;
}u;
{ //- critical section
yat::AutoMutex<> guard (this->m_lock);
//- offsets given in byte offsets, data storesd in WORD 16 bits, so
//- divide offsets by 2
u.l = static_cast<long> (plc_buffer[(byte_offset/2)] * 0x10000L);
u.l += (plc_buffer[((byte_offset + 2)/2)] & 0xFFFF);
}
return u.f;
}
//-----------------------------------------------
//- Acces to INT --------------------------------
short HWProxy::get_int (unsigned int byte_offset)
{
DEBUG_STREAM << "HWProxy::get_real get INT value at offset " << byte_offset << std::endl;
if(consecutive_com_errors > MAX_COM_RETRIES)
{
this->com_state = HWP_COMMUNICATION_ERROR;
set_com_status ("HWP_COMMUNICATION_ERROR");
std::stringstream s;
s << "HWProxy::get_int last error : max consecutive comm errors retries limit reached " << std::endl;
set_last_error (s.str ());
Tango::Except::throw_exception(
static_cast<const char *>("COMMUNICATION_ERROR"),
static_cast<const char *>(s.str().c_str()),
static_cast<const char *>("HWProxy::get_int"));
}
if(byte_offset > 198)
{
this->com_state = HWP_SOFTWARE_ERROR;
set_com_status ("HWP_SOFTWARE_ERROR");
std::stringstream s;
s << "HWProxy::get_int last error occured trying to read an INT " << " at offset " << byte_offset << std::endl;
set_last_error (s.str ());
Tango::Except::throw_exception(
static_cast<const char *>("OUT_OF_RANGE"),
static_cast<const char *>(s.str().c_str()),
static_cast<const char *>("HWProxy::get_int"));
}
{ //- critical section
yat::AutoMutex<> guard (this->m_lock);
//- offsets given in byte offsets, data storesd in WORD 16 bits, so
//- divide offsets by 2
return plc_buffer[(byte_offset/2)];
}
}
//-----------------------------------------------
//- Acces to BOOL -------------------------------
bool HWProxy::get_bool (unsigned int bit_offset, unsigned int byte_offset)
{
DEBUG_STREAM << "HWProxy::get_bool trying to get BOOL value at offset " << byte_offset << "." << bit_offset << std::endl;
if(consecutive_com_errors > MAX_COM_RETRIES)
{
this->com_state = HWP_COMMUNICATION_ERROR;
set_com_status ("HWP_COMMUNICATION_ERROR");
std::stringstream s;
s << "HWProxy::get_bool last error : max consecutive comm errors retries limit reached " << std::endl;
set_last_error (s.str ());
Tango::Except::throw_exception(
static_cast<const char *>("COMMUNICATION_ERROR"),
static_cast<const char *>(s.str().c_str()),
static_cast<const char *>("HWProxy::get_bool"));
}
if(byte_offset > 199)
{
this->com_state = HWP_SOFTWARE_ERROR;
set_com_status ("HWP_SOFTWARE_ERROR");
std::stringstream s;
s << "HWProxy::get_bool last error occured trying to read a BOOL " << " at offset " << byte_offset << "." << bit_offset << std::endl;
set_last_error (s.str ());
Tango::Except::throw_exception(
static_cast<const char *>("OUT_OF_RANGE"),
static_cast<const char *>(s.str().c_str()),
static_cast<const char *>("HWProxy::get_bool"));
}
short tmp;
{ //- critical section
yat::AutoMutex<> guard (this->m_lock);
//- offsets given in byte offsets, data storesd in WORD 16 bits, so
//- divide offsets by 2
tmp = plc_buffer[(byte_offset/2)];
}
DB_start->swap_word(tmp);
if(byte_offset % 2 != 0)
bit_offset += 8;
unsigned short mask = 0x0001 << bit_offset;
bool b = ((tmp & mask) != 0) ? true : false;
return b;
}
//-----------------------------------------------
//- Acces to HW -------------------------------
//-----------------------------------------------
void HWProxy::read_hard (void)
{
DEBUG_STREAM << "HWProxy::read_hard trying to read PLC Data " << std::endl;
Tango::DevVarShortArray plc_data(0);
try
{
if(fetch_index == 0)
{
this->DB_start->read_client_inputs(plc_data);
for (size_t i = 0; i < 50; i++)
internal_buffer[i] = plc_data[i];
DEBUG_STREAM << "HWProxy::read_hard got data byte 0 to 100 " << std::endl;
}
else
{
this->DB_end->read_client_inputs(plc_data);
for (size_t i = 0; i < 50; i++)
internal_buffer[i+50] = plc_data[i];
DEBUG_STREAM << "HWProxy::read_hard got data byte 100 to 200 " << std::endl;
}
}
catch(...)
{
this->com_error ++;
this->consecutive_com_errors ++;
this->com_state = HWP_COMMUNICATION_ERROR;
set_com_status ("HWP_COMMUNICATION_ERROR");
set_last_error ("last error : exception occured trying to read PLC");
return;
}
//- copy in client buffer
{ //- critical section
yat::AutoMutex<> guard (this->m_lock);
for (size_t j = 0; j < 100; j++)
{
plc_buffer[j] = internal_buffer[j];
}
}
DEBUG_STREAM << "HWProxy::read_hard com state value = " << com_state << " text = " << hw_state_str [this->com_state] << std::endl;
this->fetch_index = this->fetch_index == 0? 1 : 0;
this->com_state = HWP_NO_ERROR;
set_com_status ("HWP_NO_ERROR");
set_last_error ("communication with PLC is up and running");
this->com_success ++;
this->consecutive_com_errors = 0;
}
} //- namespace
//- Project : Cryocooler, ACCEL/CRYOTHERM cryogenic cooler for optics at SOLEIL
//- file : HWProxy.h
//- threaded reading of the PLC Data Block
//- Writes on the PLC
#ifndef __HW_PROXY_H__
#define __HW_PROXY_H__
#include <tango.h>
#include <yat/threading/Task.h>
#include <yat/time/Timer.h>
#include <helpers/DeviceProxyHelper.h>
#include <PLCServerProxy.h>
namespace CryoCooler_ns
{
// ============================================================================
// some defines enums and constants
// ============================================================================
//- startup and communication errors
const size_t MAX_COM_RETRIES = 20;
typedef enum
{
HWP_UNKNOWN_ERROR = 0,
HWP_INITIALIZATION_ERROR,
HWP_DEVICE_PROXY_ERROR,
HWP_COMMUNICATION_ERROR,
HWP_HARDWARE_ERROR,
HWP_SOFTWARE_ERROR,
HWP_NO_ERROR
} ComState;
const size_t HWP_STATE_MAX_SIZE = 7;
static const std::string hw_state_str[HWP_STATE_MAX_SIZE] =
{
"Unknown Error",
"Initialisation Error",
"Device Proxy Error",
"Communication Error",
"Hardware Error",
"Software Error",
"Communication Running"
};
//
const int DB_SIZE_IN_WORD=100;
//---------------------------------------------------------
//- the YAT user messages
const size_t SET_REAL_MSG = yat::FIRST_USER_MSG + 103;
const size_t SET_INT_MSG = yat::FIRST_USER_MSG + 104;
const size_t SET_BOOL_MSG = yat::FIRST_USER_MSG + 105;
//- structures for use with messages service to write values in the PLC
//- the structure to write a REAL value (a float)
struct WReal
{
unsigned short byte_offset;
float value;
};
//- the structure to write a INT value (a short)
struct WInt
{
unsigned short byte_offset;
short value;
};
//- the structure to write a BOOL value (a bool)
struct WBool
{
unsigned short byte_offset;
unsigned short bit_offset;
bool value;
};
//------------------------------------------------------------------------
//- HWProxy Class
//- read /write in the PLC with the help of PLCServerProxy
//- this class gets the data and puts it in the appropriate structures
//------------------------------------------------------------------------
class HWProxy : public yat::Task, public Tango::LogAdapter
{
public :
//- Constructeur/destructeur
HWProxy (size_t _periodic_exec_ms,
Tango::DeviceImpl * _host_device,
std::string communication_device_name,
short dbread,
short dbwrite
);
virtual ~HWProxy ();
//- retrieve the data from the PLC
//- we write in the PLC thanks to the task message service
float get_real (unsigned int byte_offset);
short get_int (unsigned int byte_offset);
bool get_bool (unsigned int bit_offset, unsigned int byte_offset);
//- the number of communication successfully done
unsigned long get_com_error (void) { return com_error; };
//- the number of communication errors
unsigned long get_com_success (void) { return com_success; };
//- the state and status of communication
ComState get_com_state (void) {return com_state;};
yat::Mutex com_status_mutex, last_error_mutex;
std::string get_last_error (void)
{
yat::AutoMutex <yat::Mutex> lock (last_error_mutex);
return last_error ;
};
void set_last_error (std::string err)
{
yat::AutoMutex <yat::Mutex> lock (last_error_mutex);
last_error = err;
};
std::string get_com_status (void)
{
yat::AutoMutex <yat::Mutex> lock (com_status_mutex);
return com_status ;
};
void set_com_status (std::string err)
{
yat::AutoMutex <yat::Mutex> lock (com_status_mutex);
com_status = err;
};
private :
//- handle_message -----------------------
virtual void handle_message (yat::Message& msg)
throw (yat::Exception);
//- get the HW values
void read_hard (void);
//- Tango communication device stuff
//- need 2 PLCServerProxy helpers as the DB is too large to get it in 1 time
PLCServerProxy * DB_start;
PLCServerProxy * DB_end;
PLCServerProxy * DB_write;
std::string m_com_dev_name;
std::string m_dev_name;
//- the host device
Tango::DeviceImpl * host_dev;
short db_read_number;
short db_write_number;
//- we have to get the whole DB in several parts as it is too big to be fetched in 1 part
//- the fetch index
int fetch_index;
//- here goes the data copied from PLC
unsigned short plc_buffer[100];
unsigned short internal_buffer[100];
unsigned short * plc_vars;
//- the state and status stuff
ComState com_state;
std::string com_status;
std::string last_error;
//- for CryoCooler Com error attribute
unsigned long com_error;
//- for CryoCooler Com OK attribute
unsigned long com_success;
//- internal error counter
unsigned int consecutive_com_errors;
};
}
#endif //- __HW_PROXY_H__
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment