diff --git a/src/ebusd/mainloop.cpp b/src/ebusd/mainloop.cpp index 710acc6f..ce809683 100644 --- a/src/ebusd/mainloop.cpp +++ b/src/ebusd/mainloop.cpp @@ -120,6 +120,9 @@ MainLoop::MainLoop(const struct options opt, Device *device, MessageMap* message m_logRawFile = NULL; } m_logRawEnabled = opt.logRaw; + m_logRawBytes = false; + m_logRawLastReceived = true; + m_logRawLastSymbol = SYN; if (opt.aclFile[0]) { string errorDescription; result_t result = m_userList.readFromFile(opt.aclFile, errorDescription); @@ -152,6 +155,7 @@ MainLoop::MainLoop(const struct options opt, Device *device, MessageMap* message } MainLoop::~MainLoop() { + m_shutdown = true; join(); for (list::iterator it = m_dataHandlers.begin(); it != m_dataHandlers.end(); it++) { @@ -208,7 +212,7 @@ void MainLoop::run() { } (*it)->start(); } - while (true) { + while (!m_shutdown) { // pick the next message to handle NetMessage* netMessage = m_netQueue.pop(taskDelay); time(&now); @@ -437,14 +441,40 @@ void MainLoop::notifyDeviceData(const symbol_t symbol, bool received) { if (received && m_dumpFile) { m_dumpFile->write((unsigned char*)&symbol, 1); } - if (m_logRawFile) { - m_logRawFile->write((unsigned char*)&symbol, 1, received); - } else if (m_logRawEnabled) { - if (received) { - logNotice(lf_bus, "<%02x", symbol); - } else { - logNotice(lf_bus, ">%02x", symbol); + if (!m_logRawFile && !m_logRawEnabled) { + return; + } + if (m_logRawBytes) { + if (m_logRawFile) { + m_logRawFile->write((unsigned char*)&symbol, 1, received); + } else if (m_logRawEnabled) { + if (received) { + logNotice(lf_bus, "<%02x", symbol); + } else { + logNotice(lf_bus, ">%02x", symbol); + } } + return; + } + if (symbol != SYN) { + if (received && !m_logRawLastReceived && symbol == m_logRawLastSymbol) { + return; // skip received echo of previously sent symbol + } + if (m_logRawBuffer.tellp() == 0 || received != m_logRawLastReceived) { + m_logRawLastReceived = received; + m_logRawBuffer << (received ? "<" : ">"); + } + m_logRawBuffer << setw(2) << setfill('0') << hex << static_cast(symbol); + m_logRawLastSymbol = symbol; + } + if (symbol == SYN && m_logRawBuffer.tellp() > 0) { // flush + if (m_logRawFile) { + const char* str = m_logRawBuffer.str().c_str(); + m_logRawFile->write((const unsigned char*)str, strlen(str), received, false); + } else { + logNotice(lf_bus, m_logRawBuffer.str().c_str()); + } + m_logRawBuffer.str(""); } } @@ -1431,11 +1461,13 @@ string MainLoop::executeLog(vector &args) { } string MainLoop::executeRaw(vector &args) { - if (args.size() != 1) { - return "usage: raw\n" - " Toggle logging of each byte."; + bool bytes = args.size() == 2 && args[1] == "bytes"; + if (args.size() != 1 && !bytes) { + return "usage: raw [bytes]\n" + " Toggle logging of messages or each byte."; } bool enabled; + m_logRawBytes = bytes; if (m_logRawFile) { enabled = !m_logRawFile->isEnabled(); m_logRawFile->setEnabled(enabled); @@ -1531,7 +1563,7 @@ string MainLoop::executeHelp() { " scan Scan slaves: scan [full|ZZ]\n" " Report scan result: scan result\n" " log Set log area level: log [AREA[,AREA]* LEVEL]\n" - " raw Toggle logging of each byte\n" + " raw Toggle logging of messages or each byte.\n" " dump Toggle binary dump of received bytes\n" " reload Reload CSV config files\n" " quit|q Close connection\n" diff --git a/src/ebusd/mainloop.h b/src/ebusd/mainloop.h index db3b4f1d..f0c3c23d 100644 --- a/src/ebusd/mainloop.h +++ b/src/ebusd/mainloop.h @@ -313,6 +313,18 @@ class MainLoop : public Thread, DeviceListener { /** whether raw logging to @p logNotice is enabled (only relevant if m_logRawFile is NULL). */ bool m_logRawEnabled; + /** whether to log raw bytes instead of messages with @a m_logRawEnabled. */ + bool m_logRawBytes; + + /** the buffer for building log raw message. */ + ostringstream m_logRawBuffer; + + /** true when the last byte in @a m_logRawBuffer was receive, false if it was sent. */ + bool m_logRawLastReceived; + + /** the last sent/received symbol.*/ + symbol_t m_logRawLastSymbol; + /** the @a RotateFile for dumping received data, or NULL. */ RotateFile* m_dumpFile; @@ -335,6 +347,9 @@ class MainLoop : public Thread, DeviceListener { /** whether to enable the hex command. */ const bool m_enableHex; + /** set to true to shutdown. */ + bool m_shutdown; + /** the created @a BusHandler instance. */ BusHandler* m_busHandler; diff --git a/src/lib/utils/rotatefile.cpp b/src/lib/utils/rotatefile.cpp index 57f58882..0133b61f 100644 --- a/src/lib/utils/rotatefile.cpp +++ b/src/lib/utils/rotatefile.cpp @@ -54,7 +54,7 @@ bool RotateFile::setEnabled(bool enabled) { return true; } -void RotateFile::write(unsigned char* value, unsigned int size, bool received) { +void RotateFile::write(const unsigned char* value, const size_t size, const bool received, const bool bytes) { if (!m_enabled || !m_stream) { return; } @@ -63,12 +63,16 @@ void RotateFile::write(unsigned char* value, unsigned int size, bool received) { struct tm td; clockGettime(&ts); localtime_r(&ts.tv_sec, &td); - fprintf(m_stream, "%04d-%02d-%02d %02d:%02d:%02d.%03ld %c", + fprintf(m_stream, "%04d-%02d-%02d %02d:%02d:%02d.%03ld ", td.tm_year+1900, td.tm_mon+1, td.tm_mday, - td.tm_hour, td.tm_min, td.tm_sec, ts.tv_nsec/1000000, - received ? '<' : '>'); - for (unsigned int pos = 0; pos < size; pos++) { - fprintf(m_stream, "%2.2x ", value[pos]); + td.tm_hour, td.tm_min, td.tm_sec, ts.tv_nsec/1000000); + if (bytes) { + fprintf(m_stream, received ? "<" : ">"); + for (unsigned int pos = 0; pos < size; pos++) { + fprintf(m_stream, "%2.2x ", value[pos]); + } + } else { + fwrite(value, 1, size, m_stream); } fprintf(m_stream, "\n"); m_fileSize += 25+3*size+1; diff --git a/src/lib/utils/rotatefile.h b/src/lib/utils/rotatefile.h index 57236f6c..ee111bf6 100644 --- a/src/lib/utils/rotatefile.h +++ b/src/lib/utils/rotatefile.h @@ -57,7 +57,7 @@ class RotateFile { * @param enabled @p true to enable writing to the file, @p false to disable it. * @return @p true when the state was changed, @p false otherwise. */ - bool setEnabled(bool enabled = true); + bool setEnabled(bool enabled); /** * Return whether writing to the file is enabled. @@ -70,8 +70,10 @@ class RotateFile { * @param value the pointer to the bytes to write. * @param size the number of bytes to write. * @param received @a true on reception, @a false on sending (only relevant in text mode). + * @param bytes whether to log single bytes (only relevant in text mode). */ - void write(unsigned char* value, unsigned int size, bool received = true); + void write(const unsigned char* value, const size_t size, const bool received = true, + const bool bytes = true); private: