Skip to content

Commit

Permalink
feat(CSerialPort): close #86 support buffer full event by setByteRead…
Browse files Browse the repository at this point in the history
…BufferFullNotify function
  • Loading branch information
itas109 committed Jul 7, 2024
1 parent 463639c commit 2ea9728
Show file tree
Hide file tree
Showing 11 changed files with 98 additions and 30 deletions.
9 changes: 8 additions & 1 deletion include/CSerialPort/SerialPort.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@

namespace itas109
{
template <class T> class ITimer;
template <class T>
class ITimer;
}

class CSerialPortBase;
Expand Down Expand Up @@ -196,6 +197,12 @@ class DLL_EXPORT CSerialPort
*/
void setMinByteReadNotify(unsigned int minByteReadNotify = 2);

/**
* @brief setByteReadBufferFullNotify set byte of read buffer full notify 设置读取通知触发缓冲区字节数
* @param byteReadBufferFullNotify byte of read buffer full notify 读取通知触发缓冲区字节数
*/
virtual void setByteReadBufferFullNotify(unsigned int byteReadBufferFullNotify);

/**
* @brief flush buffers after write 等待发送完成后刷新缓冲区
*
Expand Down
16 changes: 15 additions & 1 deletion include/CSerialPort/SerialPortBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ namespace itas109
{
class IMutex;
class CSerialPortListener;
template <class T> class ITimer;
template <class T>
class ITimer;
} // namespace itas109

/**
Expand Down Expand Up @@ -195,6 +196,18 @@ class CSerialPortBase
*/
virtual unsigned int getMinByteReadNotify();

/**
* @brief setByteReadBufferFullNotify set byte of read buffer full notify 设置读取通知触发缓冲区字节数
* @param byteReadBufferFullNotify byte of read buffer full notify 读取通知触发缓冲区字节数
*/
virtual void setByteReadBufferFullNotify(unsigned int byteReadBufferFullNotify);

/**
* @brief getByteReadBufferFullNotify get byte of read buffer full notify 获取读取通知触发缓冲区字节数
* @return byte of read buffer full notify 读取通知触发缓冲区字节数
*/
virtual unsigned int getByteReadBufferFullNotify();

/**
* @brief flush buffers after write 等待发送完成后刷新缓冲区
*
Expand Down Expand Up @@ -349,6 +362,7 @@ class CSerialPortBase
itas109::OperateMode m_operateMode; ///< operate mode 串口操作类型
unsigned int m_readIntervalTimeoutMS; ///< read time timeout millisecond 读取间隔时间,单位:毫秒
unsigned int m_minByteReadNotify; ///< minimum byte of read notify 读取通知触发最小字节数
unsigned int m_byteReadBufferFullNotify; ///< byte of read buffer full notify 读取通知触发缓冲区字节数
itas109::IMutex *p_mutex; ///< mutex 互斥锁
itas109::CSerialPortListener *p_readEvent; ///< read event 读取事件
itas109::ITimer<itas109::CSerialPortListener> *p_timer; ///< read timer 读取定时器
Expand Down
10 changes: 6 additions & 4 deletions include/CSerialPort/ibuffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,12 @@ namespace itas109
*
* @tparam T
*/
template <typename T> class Buffer
template <typename T>
class Buffer
{
public:
Buffer(){};
virtual ~Buffer(){};
Buffer() {};
virtual ~Buffer() {};

/**
* @brief write data to buffer 向缓冲区写数据
Expand Down Expand Up @@ -105,7 +106,8 @@ template <typename T> class Buffer
*
* @tparam T
*/
template <typename T> class RingBuffer : public Buffer<T>
template <typename T>
class RingBuffer : public Buffer<T>
{
public:
/**
Expand Down
1 change: 1 addition & 0 deletions include/CSerialPort/ilog.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <ctime> // time localtime

#if defined(_WIN32)
#include <windows.h> // FILETIME
#else
#include <sys/time.h> // gettimeofday
#endif
Expand Down
16 changes: 13 additions & 3 deletions include/CSerialPort/itimer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,16 @@
#include "iutils.hpp"
#include "ithread.hpp"

#ifdef CSERIALPORT_DEBUG
#include "ilog.hpp"
#endif

#define PORT_NAME_MAX_LEN 256

namespace itas109
{
template <class T> class ITimer
template <class T>
class ITimer
{
public:
ITimer()
Expand Down Expand Up @@ -58,9 +63,13 @@ template <class T> class ITimer
#ifdef CPP11_TIMER
std::mutex mutex;
std::unique_lock<std::mutex> lock(mutex);
if (!p_base->m_cv.wait_for(lock, std::chrono::milliseconds(p_base->m_timeoutMs), [&] { return p_base->m_tryStop; }))
if (!p_base->m_cv.wait_for(lock, std::chrono::milliseconds(p_base->m_timeoutMs), [&]
{ return p_base->m_tryStop; }))
{
// timeout
#ifdef CSERIALPORT_DEBUG
LOG_INFO("onReadEvent timeout. portName: %s, readLen: %u", p_base->m_portName, p_base->m_readBufferLen);
#endif
((p_base->p_class)->*(p_base->p_memfun))(p_base->m_portName, p_base->m_readBufferLen);
}
#else
Expand Down Expand Up @@ -124,7 +133,8 @@ template <class T> class ITimer

#ifdef CPP11_TIMER
std::unique_lock<std::mutex> lock(m_stopMutex);
m_cvStop.wait(lock, [this] { return m_isRunning == false; });
m_cvStop.wait(lock, [this]
{ return m_isRunning == false; });
#else
IAutoLock lock(&m_stopMutex);
// TODO: fix this error
Expand Down
4 changes: 2 additions & 2 deletions include/CSerialPort/iutils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ namespace itas109
class IUtils
{
public:
IUtils(){};
~IUtils(){};
IUtils() {};
~IUtils() {};

static size_t strlen(const char *str)
{
Expand Down
8 changes: 8 additions & 0 deletions src/SerialPort.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,14 @@ void CSerialPort::setMinByteReadNotify(unsigned int minByteReadNotify)
}
}

void CSerialPort::setByteReadBufferFullNotify(unsigned int byteReadBufferFullNotify)
{
if (p_serialPortBase)
{
p_serialPortBase->setByteReadBufferFullNotify(byteReadBufferFullNotify);
}
}

int itas109::CSerialPort::getLastError() const
{
if (p_serialPortBase)
Expand Down
12 changes: 12 additions & 0 deletions src/SerialPortBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ CSerialPortBase::CSerialPortBase()
, m_operateMode(itas109::AsynchronousOperate)
, m_readIntervalTimeoutMS(50)
, m_minByteReadNotify(1)
, m_byteReadBufferFullNotify(3276) // 4096*0.8
, p_mutex(NULL)
, p_readEvent(NULL)
, p_timer(NULL)
Expand All @@ -20,6 +21,7 @@ CSerialPortBase::CSerialPortBase(const char *portName)
, m_operateMode(itas109::AsynchronousOperate)
, m_readIntervalTimeoutMS(50)
, m_minByteReadNotify(1)
, m_byteReadBufferFullNotify(3276) // 4096*0.8
, p_mutex(NULL)
, p_readEvent(NULL)
, p_timer(NULL)
Expand Down Expand Up @@ -59,6 +61,16 @@ unsigned int CSerialPortBase::getMinByteReadNotify()
return m_minByteReadNotify;
}

void CSerialPortBase::setByteReadBufferFullNotify(unsigned int byteReadBufferFullNotify)
{
m_byteReadBufferFullNotify = byteReadBufferFullNotify;
}

unsigned int CSerialPortBase::getByteReadBufferFullNotify()
{
return m_byteReadBufferFullNotify;
}

int CSerialPortBase::getLastError() const
{
return m_lastError;
Expand Down
2 changes: 1 addition & 1 deletion src/SerialPortInfoBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ HardwareIdDespSingleton::HardwareIdDespSingleton()
HW_MAP_INSERT("058f:9720", "Alcor USB-Serial Adapter");
};

HardwareIdDespSingleton::~HardwareIdDespSingleton(){};
HardwareIdDespSingleton::~HardwareIdDespSingleton() {};

HardwareIdDespSingleton *HardwareIdDespSingleton::getInstance()
{
Expand Down
25 changes: 16 additions & 9 deletions src/SerialPortUnixBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ CSerialPortUnixBase::CSerialPortUnixBase()
, p_buffer(new itas109::RingBuffer<char>(m_readBufferSize))
{
itas109::IUtils::strncpy(m_portName, "", 1);
m_byteReadBufferFullNotify = m_readBufferSize * 0.8;
}

CSerialPortUnixBase::CSerialPortUnixBase(const char *portName)
Expand All @@ -67,6 +68,7 @@ CSerialPortUnixBase::CSerialPortUnixBase(const char *portName)
, p_buffer(new itas109::RingBuffer<char>(m_readBufferSize))
{
itas109::IUtils::strncpy(m_portName, portName, 256);
m_byteReadBufferFullNotify = m_readBufferSize * 0.8;
}

CSerialPortUnixBase::~CSerialPortUnixBase()
Expand All @@ -93,6 +95,7 @@ void CSerialPortUnixBase::init(const char *portName,
m_stopbits = stopbits;
m_flowControl = flowControl;
m_readBufferSize = readBufferSize;
m_byteReadBufferFullNotify = m_readBufferSize * 0.8;

if (p_buffer)
{
Expand Down Expand Up @@ -320,8 +323,7 @@ void *CSerialPortUnixBase::commThreadMonitor(void *pParam)
p_base->p_buffer->write(data, len);
#ifdef CSERIALPORT_DEBUG
char hexStr[201]; // 100*2 + 1
LOG_INFO("write buffer(usedLen %u). len: %d, hex(top100): %s", p_base->p_buffer->getUsedLen(), len,
itas109::IUtils::charToHexStr(hexStr, data, len > 100 ? 100 : len));
LOG_INFO("write buffer(usedLen %u). len: %d, hex(top100): %s", p_base->p_buffer->getUsedLen(), len, itas109::IUtils::charToHexStr(hexStr, data, len > 100 ? 100 : len));
#endif

if (p_base->p_readEvent)
Expand All @@ -336,14 +338,20 @@ void *CSerialPortUnixBase::commThreadMonitor(void *pParam)
p_base->p_timer->stop();
}

LOG_INFO("onReadEvent. portName: %s, readLen: %u", p_base->getPortName(), p_base->p_buffer->getUsedLen());
p_base->p_timer->startOnce(readIntervalTimeoutMS, p_base->p_readEvent, &itas109::CSerialPortListener::onReadEvent, p_base->getPortName(),
p_base->p_buffer->getUsedLen());
if (p_base->p_buffer->isFull() || p_base->p_buffer->getUsedLen() > p_base->getByteReadBufferFullNotify())
{
LOG_INFO("onReadEvent buffer full. portName: %s, readLen: %u", p_base->getPortName(), p_base->p_buffer->getUsedLen());
p_base->p_readEvent->onReadEvent(p_base->getPortName(), p_base->p_buffer->getUsedLen());
}
else
{
p_base->p_timer->startOnce(readIntervalTimeoutMS, p_base->p_readEvent, &itas109::CSerialPortListener::onReadEvent, p_base->getPortName(), p_base->p_buffer->getUsedLen());
}
}
}
else
{
LOG_INFO("onReadEvent. portName: %s, readLen: %u", p_base->getPortName(), p_base->p_buffer->getUsedLen());
LOG_INFO("onReadEvent min read byte. portName: %s, readLen: %u", p_base->getPortName(), p_base->p_buffer->getUsedLen());
p_base->p_readEvent->onReadEvent(p_base->getPortName(), p_base->p_buffer->getUsedLen());
}
}
Expand Down Expand Up @@ -395,9 +403,8 @@ bool CSerialPortUnixBase::openPort()
{
itas109::IAutoLock lock(p_mutex);

LOG_INFO("portName: %s, baudRate: %d, dataBit: %d, parity: %d, stopBit: %d, flowControl: %d, mode: %s, readBufferSize:%u(%u), readIntervalTimeoutMS: %u, minByteReadNotify: %u",
m_portName, m_baudRate, m_dataBits, m_parity, m_stopbits, m_flowControl, m_operateMode == itas109::AsynchronousOperate ? "async" : "sync", m_readBufferSize,
p_buffer->getBufferSize(), m_readIntervalTimeoutMS, m_minByteReadNotify);
LOG_INFO("portName: %s, baudRate: %d, dataBit: %d, parity: %d, stopBit: %d, flowControl: %d, mode: %s, readBufferSize:%u(%u), readIntervalTimeoutMS: %u, minByteReadNotify: %u, byteReadBufferFullNotify: %u",
m_portName, m_baudRate, m_dataBits, m_parity, m_stopbits, m_flowControl, m_operateMode == itas109::AsynchronousOperate ? "async" : "sync", m_readBufferSize, p_buffer->getBufferSize(), m_readIntervalTimeoutMS, m_minByteReadNotify, m_byteReadBufferFullNotify);

bool bRet = false;

Expand Down
25 changes: 16 additions & 9 deletions src/SerialPortWinBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ CSerialPortWinBase::CSerialPortWinBase()
, p_buffer(new itas109::RingBuffer<char>(m_readBufferSize))
{
itas109::IUtils::strncpy(m_portName, "", 1);
m_byteReadBufferFullNotify = m_readBufferSize * 0.8;

overlapMonitor.Internal = 0;
overlapMonitor.InternalHigh = 0;
Expand Down Expand Up @@ -66,6 +67,7 @@ CSerialPortWinBase::CSerialPortWinBase(const char *portName)
, p_buffer(new itas109::RingBuffer<char>(m_readBufferSize))
{
itas109::IUtils::strncpy(m_portName, portName, 256);
m_byteReadBufferFullNotify = m_readBufferSize * 0.8;

overlapMonitor.Internal = 0;
overlapMonitor.InternalHigh = 0;
Expand Down Expand Up @@ -100,6 +102,7 @@ void CSerialPortWinBase::init(const char *portName,
m_stopbits = stopbits;
m_flowControl = flowControl;
m_readBufferSize = readBufferSize;
m_byteReadBufferFullNotify = m_readBufferSize * 0.8;

if (p_buffer)
{
Expand All @@ -113,9 +116,8 @@ bool CSerialPortWinBase::openPort()
{
itas109::IAutoLock lock(p_mutex);

LOG_INFO("portName: %s, baudRate: %d, dataBit: %d, parity: %d, stopBit: %d, flowControl: %d, mode: %s, readBufferSize:%u(%u), readIntervalTimeoutMS: %u, minByteReadNotify: %u",
m_portName, m_baudRate, m_dataBits, m_parity, m_stopbits, m_flowControl, m_operateMode == itas109::AsynchronousOperate ? "async" : "sync", m_readBufferSize,
p_buffer->getBufferSize(), m_readIntervalTimeoutMS, m_minByteReadNotify);
LOG_INFO("portName: %s, baudRate: %d, dataBit: %d, parity: %d, stopBit: %d, flowControl: %d, mode: %s, readBufferSize:%u(%u), readIntervalTimeoutMS: %u, minByteReadNotify: %u, byteReadBufferFullNotify: %u",
m_portName, m_baudRate, m_dataBits, m_parity, m_stopbits, m_flowControl, m_operateMode == itas109::AsynchronousOperate ? "async" : "sync", m_readBufferSize, p_buffer->getBufferSize(), m_readIntervalTimeoutMS, m_minByteReadNotify, m_byteReadBufferFullNotify);

bool bRet = false;

Expand Down Expand Up @@ -348,8 +350,7 @@ unsigned int __stdcall CSerialPortWinBase::commThreadMonitor(LPVOID pParam)
p_base->p_buffer->write(data, len);
#ifdef CSERIALPORT_DEBUG
char hexStr[201]; // 100*2 + 1
LOG_INFO("write buffer(usedLen %u). len: %d, hex(top100): %s", p_base->p_buffer->getUsedLen(), len,
itas109::IUtils::charToHexStr(hexStr, data, len > 100 ? 100 : len));
LOG_INFO("write buffer(usedLen %u). len: %d, hex(top100): %s", p_base->p_buffer->getUsedLen(), len, itas109::IUtils::charToHexStr(hexStr, data, len > 100 ? 100 : len));
#endif

if (p_base->p_readEvent)
Expand All @@ -364,14 +365,20 @@ unsigned int __stdcall CSerialPortWinBase::commThreadMonitor(LPVOID pParam)
p_base->p_timer->stop();
}

LOG_INFO("onReadEvent. portName: %s, readLen: %u", p_base->getPortName(), p_base->p_buffer->getUsedLen());
p_base->p_timer->startOnce(readIntervalTimeoutMS, p_base->p_readEvent, &itas109::CSerialPortListener::onReadEvent, p_base->getPortName(),
p_base->p_buffer->getUsedLen());
if (p_base->p_buffer->isFull() || p_base->p_buffer->getUsedLen() > p_base->getByteReadBufferFullNotify())
{
LOG_INFO("onReadEvent buffer full. portName: %s, readLen: %u", p_base->getPortName(), p_base->p_buffer->getUsedLen());
p_base->p_readEvent->onReadEvent(p_base->getPortName(), p_base->p_buffer->getUsedLen());
}
else
{
p_base->p_timer->startOnce(readIntervalTimeoutMS, p_base->p_readEvent, &itas109::CSerialPortListener::onReadEvent, p_base->getPortName(), p_base->p_buffer->getUsedLen());
}
}
}
else
{
LOG_INFO("onReadEvent. portName: %s, readLen: %u", p_base->getPortName(), p_base->p_buffer->getUsedLen());
LOG_INFO("onReadEvent min read byte. portName: %s, readLen: %u", p_base->getPortName(), p_base->p_buffer->getUsedLen());
p_base->p_readEvent->onReadEvent(p_base->getPortName(), p_base->p_buffer->getUsedLen());
}
}
Expand Down

0 comments on commit 2ea9728

Please sign in to comment.