BlinkenArea - GitList
Repositories
Blog
Wiki
Blinker
Code
Commits
Branches
Tags
Search
Tree:
362c1f4
Branches
Tags
master
Blinker
src
common
Output.cpp
update copyright header
Stefan Schuermans
commited
362c1f4
at 2019-05-04 17:17:10
Output.cpp
Blame
History
Raw
/* Blinker Copyright 2011-2019 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() { // device is not open -> try to (re-)open it if (!m_pDevice) { openDevice(); return; } // buffer not empty -> try to output rest of data if (!m_buffer.empty()) { outputBufferedData(); return; } // (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; } // reset internal status m_buffer.clear(); m_dropped = false; updateTimeCallback(); } /// 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); outputFrameData(data); updateTimeCallback(); } /** * @brief output frame data to device * @param[in] data data of one frame to output to device */ void Output::outputFrameData(const std::string &data) { // add data to buffer (if current buffer contains less than 10 frames) if (m_buffer.size() < data.size() * 10) { m_buffer += data; m_dropped = false; // last frame was not dropped } else { m_dropped = true; // remember that last frame was dropped } outputBufferedData(); } /// write data in output buffer to device void Output::outputBufferedData() { // no device -> forget buffered data, leave if (!m_pDevice) { m_buffer.clear(); return; } // write (at least some) data to device std::string::size_type len; if (!m_pDevice->write(m_buffer, len)) { closeDevice(); // error -> close device return; } // remove written data from buffer m_buffer = m_buffer.substr(len); updateTimeCallback(); } /// update time callback request void Output::updateTimeCallback() { /* no device -> call in 1s for re-opening device buffer empty, last frame not dropped -> call in 1s for re-outputting buffer not empty -> call in 50ms for outputting more data last frame dropped -> call in 50ms for frame update */ Time delay(1); if (m_pDevice && (!m_buffer.empty() || m_dropped)) delay.fromMs(50); m_mgrs.m_callMgr.requestTimeCall(this, Time::now() + delay); } } // namespace Blinker