BlinkenArea - GitList
Repositories
Blog
Wiki
Blinker
Code
Commits
Branches
Tags
Search
Tree:
9418df2
Branches
Tags
master
Blinker
src
noarch
Output.cpp
added buffer to serial device output dropping frames on serial output if buffer gets too full (more than 10 frames) added support for high baudrates
Stefan Schuermans
commited
9418df2
at 2011-12-27 08:02:03
Output.cpp
Blame
History
Raw
/* Blinker Copyright 2011 Stefan Schuermans <stefan@blinkenarea.org> Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html a blinkenarea.org project */ #include <string> #include <BlinkenLib/BlinkenFrame.h> #include <BlinkenLib/BlinkenProto.h> #include "Device.h" #include "Directory.h" #include "File.h" #include "InStreamFile.h" #include "Mgrs.h" #include "Module.h" #include "NameFile.h" #include "Output.h" #include "Protocol.h" #include "ProtocolFile.h" #include "SerCfgFile.h" #include "StreamRecv.h" #include "Time.h" #include "TimeCallee.h" namespace Blinker { /** * @brief constructor * @param[in] name module name * @param[in] mgrs managers * @param[in] dirBase base directory */ Output::Output(const std::string &name, Mgrs &mgrs, const Directory &dirBase): Module(name, mgrs, dirBase), m_fileInStream(dirBase.getFile("instream"), mgrs.m_streamMgr), m_fileProtocol(dirBase.getFile("protocol")), m_fileDevice(dirBase.getFile("device")), m_fileSerCfg(dirBase.getFile("ser_cfg")), m_pDevice(NULL) { // set up m_fileInStream.setStreamRecv(this); readProto(); openDevice(); } /// virtual destructor Output::~Output() { // clean up closeDevice(); m_fileInStream.setStreamRecv(NULL); m_mgrs.m_callMgr.cancelTimeCall(this); } /// check for update of configuration void Output::updateConfig() { // input stream name file was modified -> re-get input stream if (m_fileInStream.checkModified()) m_fileInStream.update(); // protocol file was modified -> re-read protocol if (m_fileProtocol.checkModified()) readProto(); // device file or serial settings file was modified -> re-open device if (m_fileDevice.checkModified() || m_fileSerCfg.checkModified()) openDevice(); } /** * @brief set current frame * @param[in] stream stream name * @param[in] pFrame current frame (NULL for none) */ void Output::setFrame(const std::string &stream, stBlinkenFrame *pFrame) { outputFrame(); (void)stream; // unused (void)pFrame; // unused } /// callback when requested time reached void Output::timeCall() { // if device is not open, try to (re-)open it if (!m_pDevice) openDevice(); // re-output current frame outputFrame(); } /// (re-)read protocol void Output::readProto() { // update protocol from file m_fileProtocol.update(); // re-output current frame using new protocol outputFrame(); } /// open device void Output::openDevice() { closeDevice(); // get new device name and new serial config m_fileDevice.update(); m_fileSerCfg.update(); // open device if (m_fileDevice.m_valid) m_pDevice = new Device(m_fileDevice.m_obj.m_str); // serial config available -> configure serial port if (m_pDevice && m_fileSerCfg.m_valid) { if (!m_pDevice->setSerCfg(m_fileSerCfg.m_obj)) closeDevice(); // error -> close device } // output current frame to device outputFrame(); } /// close device void Output::closeDevice() { // close device if (m_pDevice) { delete m_pDevice; m_pDevice = NULL; } // clear buffered data m_buffer.clear(); // request time callback in one second (for trying to re-open device) m_mgrs.m_callMgr.requestTimeCall(this, Time::now() + Time(1)); } /// output current frame to device void Output::outputFrame() { stBlinkenFrame *pFrame; char buf[65536]; int len; std::string data; // no protocol or no device -> leave if (!m_fileProtocol.m_valid || !m_pDevice) return; // get current frame from input stream pFrame = m_fileInStream.getCurFrame(); // convert frame to protocol data if (pFrame) len = BlinkenFrameToNetwork(pFrame, m_fileProtocol.m_obj.m_proto, buf, sizeof(buf)); else len = BlinkenProtoMakePacket(m_fileProtocol.m_obj.m_proto, BlinkenPacketStreamEnd, buf, sizeof(buf)); if (len < 0) len = 0; data.assign(buf, len); // output data to device outputFrameData(data); /* request time callback in one second (for outputting current frame again or reopening device) */ m_mgrs.m_callMgr.requestTimeCall(this, Time::now() + Time(1)); } /** * @brief output frame data to device * @param[in] data data of one frame to output to device */ void Output::outputFrameData(const std::string &data) { // no device -> leave if (!m_pDevice) return; // add data to buffer (if current buffer contains less than 10 frames) if (m_buffer.size() < data.size() * 10) m_buffer += data; // write (at least some) data to device std::string::size_type len; if (!m_pDevice->write(m_buffer, len)) closeDevice(); // error -> close device else m_buffer = m_buffer.substr(len); // done -> remove written data from buffer } } // namespace Blinker