What I'm trying to do is to create a custom component that act as a non blocking "communication device", wrapping a socket and a serial port and exposing a pair of methods to write and read on whatever device the user choose. I'm starting with the Serial port, right now. I already have my Serial class working (blocking).
This is where i am right now:
CommManager.h
Code: Select all
#ifndef COMMMANAGER_H
#define COMMMANAGER_H
#include <wx/wx.h>
#include <wx/event.h>
#include <string>
#include "Comm/BBBSerial.h"
#define ph_rxBufferSize 2048
#define ph_txBufferSize 512
typedef std::string String;
BEGIN_DECLARE_EVENT_TYPES()
DECLARE_EVENT_TYPE(wxEVT_SERIAL, -1)
END_DECLARE_EVENT_TYPES()
class CommManager : public wxEvtHandler, public wxThreadHelper
{
public:
/** Default constructor */
CommManager();
/** Default destructor */
virtual ~CommManager();
// worker thread entry point
wxThread::ExitCode Entry();
// Seriale
BBBSerial Serial;
bool SendAndWait(const String& tx_Message, String& rx_Answer);
bool SendMessage(const String& tx_Message);
// Buffer TX & RX
char* rxBuffer;
char* txBuffer;
String Answer; // TODO: Make private and expose String GetAnswer() method;
protected:
private:
unsigned int mCounter; //
wxCriticalSection mCS;
void OnSerialRxCompleted(wxCommandEvent& SerialEvent);
};
#endif // COMMMANAGER_H
Code: Select all
#include "CommManager.h"
//---------------------------------------------------------------------------------------------------------------------
DEFINE_EVENT_TYPE(wxEVT_MYTHREAD)
//---------------------------------------------------------------------------------------------------------------------
CommManager::CommManager()
{
rxBuffer = new char[2048];
txBuffer = new char[256];
// Create thread
CreateThread();
Bind(wxEVT_MYTHREAD, &OnSerialRxCompleted, this);
}
//---------------------------------------------------------------------------------------------------------------------
CommManager::~CommManager()
{
}
//---------------------------------------------------------------------------------------------------------------------
bool CommManager::SendAndWait(const String& tx_Message, String& rx_Answer)
{
// Non threaded Serial comunication
unsigned int txlen;
unsigned int rxlen;
bool Result=false;
int Ret;
// String to char array
txlen = tx_Message.length()+1;
strncpy(txBuffer, (const char*)tx_Message.c_str(), txlen);
if (Serial.WriteString(txBuffer)) {
// Send OK, wait for the answer
rxlen = 0;
Ret = Serial.ReadString(rxBuffer);
if (Ret>0) {
rxlen = Ret;
// La serialib termina il buffer con lo 0, quindi non devo farlo io
if (rxlen) {
rx_Answer = rxBuffer;
Result = true;
}
}else if (Ret==0) {
// Timeout
// TODO
}else{
// RX Error
// TODO
}
}else{
// some kind of error
// TODO
}
return Result;
}
//---------------------------------------------------------------------------------------------------------------------
bool CommManager::SendMessage(const String& tx_Message)
{
// Non threaded Serial comunication
unsigned int txlen;
unsigned int rxlen;
bool Result=false;
// String to char array
txlen = tx_Message.length()+1;
strncpy(txBuffer, (const char*)tx_Message.c_str(), txlen);
if (Serial.WriteString(txBuffer)) {
// Send OK, start the thread for the answer
rxlen = 0;
GetThread()->Run();
Result = true;
}else{
// some kind of error
// TODO
}
return Result;
}
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
wxThread::ExitCode CommManager::Entry()
{
int Ret;
wxCommandEvent evt(wxEVT_MYTHREAD);
// loop, so long as we haven't been asked to quit
while ( ! GetThread()->TestDestroy()) {
{
Ret = Serial.ReadString(rxBuffer);
evt.SetInt(Ret);
//evt.SetClientData(rxBuffer);
wxPostEvent(this, evt);
}
//Sleep(100);
}
// we have been asked to stop
return (wxThread::ExitCode)0;
}
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
void CommManager::OnSerialRxCompleted(wxCommandEvent& SerialEvent)
{
int Ret = SerialEvent.GetInt();
unsigned int rxlen;
if (Ret>0) {
rxlen = Ret;
// La serialib termina il buffer con lo 0, quindi non devo farlo io
if (rxlen) {
Answer = rxBuffer;
}
}else if (Ret==0) {
// Timeout
// TODO
}else{
// RX Error
// TODO
}
// Queue the event on the main frame, to let the thread event call finish
GetThread()->Pause();
wxCommandEvent evt(wxEVT_SERIAL);
evt.SetInt(rxlen);
wxTheApp->GetTopWindow()->GetEventHandler()->QueueEvent(&evt);
}
Then i have a lot of doubts:
- should i pause the thread in his own event?
- should i pause it or should i let it run using a flag to avoid to listen to the serial when not needed? my app is "master", the answering machine is "slave" and never send data if not asked for, and my app will COSTANTLY polls the serial device, as fast as it can.
- should i use a wxCriticalSection when copying the data from the buffer to the string?
- should i use a wxThread instead of a wxThreadHelper ?
- EDIT -
If this matters, my app should run on a Beaglebone Black with Debian, even if i'm developing on a Win7 machine.