Skip to content

Commit

Permalink
added --lograwdatafile and --lograwdatasize options similar to --dump…
Browse files Browse the repository at this point in the history
…file/--dumpsize for logging received/sent bytes to a dedicated text file, extracted dump/raw file handling to a separate class, switched to an interface instead of a method for dumping/logging raw data, changed default dump file name to /tmp/ebusd_dump.bin, use "s_" for static variables, formatting
  • Loading branch information
john30 committed Dec 4, 2016
1 parent 14fd6c9 commit cdbcb46
Show file tree
Hide file tree
Showing 9 changed files with 416 additions and 224 deletions.
120 changes: 72 additions & 48 deletions src/ebusd/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "mainloop.h"
#include "bushandler.h"
#include "log.h"
#include "rotatefile.h"
#include <stdlib.h>
#include <argp.h>
#include <csignal>
Expand Down Expand Up @@ -90,8 +91,10 @@ static struct options opt = {
"/var/ebusd/html", // htmlPath
PACKAGE_LOGFILE, // logFile
false, // logRaw
PACKAGE_LOGFILE, // logRawFile
100, // logRawSize
false, // dump
"/tmp/ebus_dump.bin", // dumpFile
"/tmp/" PACKAGE "_dump.bin", // dumpFile
100 // dumpSize
};

Expand Down Expand Up @@ -130,8 +133,10 @@ static const char argpdoc[] =
#define O_HTMLPA (O_HTTPPT+1)
#define O_LOGARE (O_HTMLPA+1)
#define O_LOGLEV (O_LOGARE+1)
#define O_LOGRAW (O_LOGLEV+1)
#define O_DMPFIL (O_LOGRAW+1)
#define O_RAW (O_LOGLEV+1)
#define O_RAWFIL (O_RAW+1)
#define O_RAWSIZ (O_RAWFIL+1)
#define O_DMPFIL (O_RAWSIZ+1)
#define O_DMPSIZ (O_DMPFIL+1)

/** the definition of the known program arguments. */
Expand Down Expand Up @@ -173,24 +178,28 @@ static const struct argp_option argpoptions[] = {
{"logfile", 'l', "FILE", 0, "Write log to FILE (only for daemon) [" PACKAGE_LOGFILE "]", 0 },
{"logareas", O_LOGARE, "AREAS", 0, "Only write log for matching AREA(S): main,network,bus,update,all [all]", 0 },
{"loglevel", O_LOGLEV, "LEVEL", 0, "Only write log below or equal to LEVEL: error/notice/info/debug [notice]", 0 },
{"lograwdata", O_LOGRAW, NULL, 0, "Log each received/sent byte on the bus", 0 },

{NULL, 0, NULL, 0, "Dump options:", 6 },
{"dump", 'D', NULL, 0, "Enable dump of received bytes", 0 },
{"dumpfile", O_DMPFIL, "FILE", 0, "Dump received bytes to FILE [/tmp/ebus_dump.bin]", 0 },
{"dumpsize", O_DMPSIZ, "SIZE", 0, "Make dump files no larger than SIZE kB [100]", 0 },
{NULL, 0, NULL, 0, "Raw logging options:", 6 },
{"lograwdata", O_RAW, NULL, 0, "Log each received/sent byte on the bus", 0 },
{"lograwdatafile", O_RAWFIL, "FILE", 0, "Write raw log to FILE [" PACKAGE_LOGFILE "]", 0 },
{"lograwdatasize", O_RAWSIZ, "SIZE", 0, "Make raw log file no larger than SIZE kB [100]", 0 },

{NULL, 0, NULL, 0, "Binary dump options:", 7 },
{"dump", 'D', NULL, 0, "Enable binary dump of received bytes", 0 },
{"dumpfile", O_DMPFIL, "FILE", 0, "Dump received bytes to FILE [/tmp/" PACKAGE "_dump.bin]", 0 },
{"dumpsize", O_DMPSIZ, "SIZE", 0, "Make dump file no larger than SIZE kB [100]", 0 },

{NULL, 0, NULL, 0, NULL, 0 },
};

/** the global @a DataFieldTemplates. */
static DataFieldTemplates globalTemplates;
static DataFieldTemplates s_globalTemplates;

/**
* the loaded @a DataFieldTemplates by path (may also carry
* @a globalTemplates as replacement for missing file).
*/
static map<string, DataFieldTemplates*> templatesByPath;
static map<string, DataFieldTemplates*> s_templatesByPath;

/**
* The program argument parsing function.
Expand Down Expand Up @@ -404,15 +413,32 @@ error_t parse_opt(int key, char *arg, struct argp_state *state)
return EINVAL;
}
break;
case O_LOGRAW: // --lograwdata

// Raw logging options:
case O_RAW: // --lograwdata
opt->logRaw = true;
break;
case O_RAWFIL: // --lograwdatafile=/var/log/ebusd.log
if (arg == NULL || arg[0] == 0 || strcmp("/", arg) == 0) {
argp_error(state, "invalid dumpfile");
return EINVAL;
}
opt->logRawFile = arg;
break;
case O_RAWSIZ: // --lograwdatasize=100
opt->logRawSize = parseInt(arg, 10, 1, 1000000, result);
if (result != RESULT_OK) {
argp_error(state, "invalid dumpsize");
return EINVAL;
}
break;


// Dump options:
// Binary dump options:
case 'D': // --dump
opt->dump = true;
break;
case O_DMPFIL: // --dumpfile=/tmp/ebus_dump.bin
case O_DMPFIL: // --dumpfile=/tmp/ebusd_dump.bin
if (arg == NULL || arg[0] == 0 || strcmp("/", arg) == 0) {
argp_error(state, "invalid dumpfile");
return EINVAL;
Expand Down Expand Up @@ -521,12 +547,13 @@ void shutdown()
s_messageMap = NULL;
}
// free templates
for (map<string, DataFieldTemplates*>::iterator it = templatesByPath.begin(); it != templatesByPath.end(); it++) {
if (it->second!=&globalTemplates)
for (map<string, DataFieldTemplates*>::iterator it = s_templatesByPath.begin(); it != s_templatesByPath.end(); it++) {
if (it->second!=&s_globalTemplates) {
delete it->second;
}
it->second = NULL;
}
templatesByPath.clear();
s_templatesByPath.clear();

// reset all signal handlers to default
signal(SIGHUP, SIG_DFL);
Expand Down Expand Up @@ -620,13 +647,14 @@ static result_t collectConfigFiles(const string path, const string prefix, const
DataFieldTemplates* getTemplates(const string filename) {
string path;
size_t pos = filename.find_last_of('/');
if (pos!=string::npos)
if (pos!=string::npos) {
path = filename.substr(0, pos);
map<string, DataFieldTemplates*>::iterator it = templatesByPath.find(path);
if (it!=templatesByPath.end()) {
}
map<string, DataFieldTemplates*>::iterator it = s_templatesByPath.find(path);
if (it!=s_templatesByPath.end()) {
return it->second;
}
return &globalTemplates;
return &s_globalTemplates;
}

/**
Expand All @@ -639,17 +667,17 @@ DataFieldTemplates* getTemplates(const string filename) {
* @return the @a DataFieldTemplates.
*/
static bool readTemplates(const string path, const string extension, bool available, bool verbose=false) {
map<string, DataFieldTemplates*>::iterator it = templatesByPath.find(path);
if (it!=templatesByPath.end()) {
map<string, DataFieldTemplates*>::iterator it = s_templatesByPath.find(path);
if (it!=s_templatesByPath.end()) {
return false;
}
DataFieldTemplates* templates;
if (path==opt.configPath || !available) {
templates = &globalTemplates;
templates = &s_globalTemplates;
} else {
templates = new DataFieldTemplates(globalTemplates);
templates = new DataFieldTemplates(s_globalTemplates);
}
templatesByPath[path] = templates;
s_templatesByPath[path] = templates;
if (!available) {
// global templates are stored as replacement in order to determine whether the directory was already loaded
return true;
Expand Down Expand Up @@ -741,14 +769,14 @@ result_t loadConfigFiles(MessageMap* messages, bool verbose, bool denyRecursive)
{
logInfo(lf_main, "loading configuration files from %s", opt.configPath);
messages->clear();
globalTemplates.clear();
for (map<string, DataFieldTemplates*>::iterator it = templatesByPath.begin(); it != templatesByPath.end(); it++) {
if (it->second!=&globalTemplates) {
s_globalTemplates.clear();
for (map<string, DataFieldTemplates*>::iterator it = s_templatesByPath.begin(); it != s_templatesByPath.end(); it++) {
if (it->second!=&s_globalTemplates) {
delete it->second;
}
it->second = NULL;
}
templatesByPath.clear();
s_templatesByPath.clear();

result_t result = readConfigFiles(string(opt.configPath), ".csv", messages, (!opt.scanConfig || opt.checkConfig) && !denyRecursive, verbose);
if (result == RESULT_OK) {
Expand Down Expand Up @@ -908,18 +936,6 @@ result_t loadScanConfigFile(MessageMap* messages, unsigned char address, SymbolS
return RESULT_OK;
}

/**
* Create a log message for a received/sent raw data byte.
* @param byte the raw data byte.
* @param received true if the byte was received, false if it was sent.
*/
static void logRawData(const unsigned char byte, bool received)
{
if (received)
logNotice(lf_bus, "<%02x", byte);
else
logNotice(lf_bus, ">%02x", byte);
}

/**
* Main method.
Expand Down Expand Up @@ -965,10 +981,17 @@ int main(int argc, char* argv[])
continue;
}
unsigned char address = master[1];
string file;
res = loadScanConfigFile(s_messageMap, address, slave, file, true);
if (res==RESULT_OK)
logInfo(lf_main, "scan config %2.2x: file %s loaded", address, file.c_str());
Message* message = s_messageMap->getScanMessage(address);
if (!message) {
logError(lf_main, "invalid scan address %2.2x", address);
} else {
message->storeLastData(master, slave);
string file;
res = loadScanConfigFile(s_messageMap, address, slave, file, true);
if (res==RESULT_OK) {
logInfo(lf_main, "scan config %2.2x: file %s loaded", address, file.c_str());
}
}
}
if (result == RESULT_OK && opt.checkConfig > 1) {
logNotice(lf_main, "configuration dump:");
Expand All @@ -978,8 +1001,9 @@ int main(int argc, char* argv[])
return 0;
}


// open the device
Device *device = Device::create(opt.device, !opt.noDeviceCheck, opt.readOnly, opt.initialSend, &logRawData);
Device *device = Device::create(opt.device, !opt.noDeviceCheck, opt.readOnly, opt.initialSend);
if (device == NULL) {
logError(lf_main, "unable to create device %s", opt.device);
return EINVAL;
Expand All @@ -1003,9 +1027,9 @@ int main(int argc, char* argv[])

// load configuration files
loadConfigFiles(s_messageMap);
if (s_messageMap->sizeConditions()>0 && opt.pollInterval==0)
if (s_messageMap->sizeConditions()>0 && opt.pollInterval==0) {
logError(lf_main, "conditions require a poll interval > 0");

}
// wait for end of MainLoop
s_mainLoop->join();

Expand Down
9 changes: 6 additions & 3 deletions src/ebusd/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,13 @@ struct options
const char* htmlPath; //!< path for HTML files served by the HTTP port [/var/ebusd/html]

const char* logFile; //!< log file name [/var/log/ebusd.log]
bool logRaw; //!< log each received/sent byte on the bus

bool dump; //!< dump received bytes
const char* dumpFile; //!< dump file name [/tmp/ebus_dump.bin]
bool logRaw; //!< raw log each received/sent byte on the bus
const char* logRawFile; //!< name of raw log file [/var/log/ebusd.log]
int logRawSize; //!< maximum size of raw log file in kB [100]

bool dump; //!< binary dump received bytes
const char* dumpFile; //!< name of dump file [/tmp/ebusd_dump.bin]
int dumpSize; //!< maximum size of dump file in kB [100]
};

Expand Down
81 changes: 57 additions & 24 deletions src/ebusd/mainloop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,21 @@ MainLoop::MainLoop(const struct options opt, Device *device, MessageMap* message
m_address(opt.address), m_scanConfig(opt.scanConfig),
m_initialScan(opt.initialScan), m_enableHex(opt.enableHex)
{
// setup Device
m_device->setLogRaw(opt.logRaw);
m_device->setDumpRawFile(opt.dumpFile);
m_device->setDumpRawMaxSize(opt.dumpSize);
m_device->setDumpRaw(opt.dump);

// open Device
result_t result = m_device->open();
if (result != RESULT_OK)
if (result != RESULT_OK) {
logError(lf_bus, "unable to open %s: %s", m_device->getName(), getResultCode(result));
else if (!m_device->isValid())
} else if (!m_device->isValid()) {
logError(lf_bus, "device %s not available", m_device->getName());

}
m_device->setListener(this);
if (opt.dumpFile[0]) {
m_dumpFile = new RotateFile(opt.dumpFile, opt.dumpSize);
}
if (opt.logRawFile[0] && strcmp(opt.logRawFile, opt.logFile)!=0) {
m_logRawFile = new RotateFile(opt.logRawFile, opt.logRawSize, true);
}
m_logRawEnabled = opt.logRaw;
// create BusHandler
unsigned int latency;
if (opt.latency<0) {
Expand All @@ -86,6 +88,14 @@ MainLoop::MainLoop(const struct options opt, Device *device, MessageMap* message
MainLoop::~MainLoop()
{
join();
if (m_dumpFile) {
delete m_dumpFile;
m_dumpFile = NULL;
}
if (m_logRawFile) {
delete m_logRawFile;
m_logRawFile = NULL;
}
if (m_network != NULL) {
delete m_network;
m_network = NULL;
Expand Down Expand Up @@ -233,6 +243,22 @@ void MainLoop::run()
}
}

void MainLoop::notifyDeviceData(const unsigned char byte, bool received)
{
if (received && m_dumpFile) {
m_dumpFile->write((unsigned char*)&byte, 1);
}
if (m_logRawFile) {
m_logRawFile->write((unsigned char*)&byte, 1, received);
} else if (m_logRawEnabled){
if (received) {
logNotice(lf_bus, "<%02x", byte);
} else {
logNotice(lf_bus, ">%02x", byte);
}
}
}

string MainLoop::decodeMessage(const string& data, const bool isHttp, bool& connected, bool& listening, bool& reload)
{
ostringstream result;
Expand Down Expand Up @@ -1105,25 +1131,32 @@ string MainLoop::executeLog(vector<string> &args)

string MainLoop::executeRaw(vector<string> &args)
{
if (args.size() != 1)
if (args.size() != 1) {
return "usage: raw\n"
" Toggle logging raw bytes.";

bool enabled = !m_device->getLogRaw();
m_device->setLogRaw(enabled);

return enabled ? "raw output enabled" : "raw output disabled";
" Toggle logging of each byte.";
}
bool enabled;
if (m_logRawFile) {
enabled = !m_logRawFile->isEnabled();
m_logRawFile->setEnabled(enabled);
} else {
enabled = !m_logRawEnabled;
m_logRawEnabled = enabled;
}
return enabled ? "raw logging enabled" : "raw logging disabled";
}

string MainLoop::executeDump(vector<string> &args)
{
if (args.size() != 1)
if (args.size() != 1) {
return "usage: dump\n"
" Toggle dumping raw bytes.";

bool enabled = !m_device->getDumpRaw();
m_device->setDumpRaw(enabled);

" Toggle binary dump of received bytes.";
}
if (!m_dumpFile) {
return "dump not configured";
}
bool enabled = !m_dumpFile->isEnabled();
m_dumpFile->setEnabled(enabled);
return enabled ? "dump enabled" : "dump disabled";
}

Expand Down Expand Up @@ -1193,8 +1226,8 @@ string MainLoop::executeHelp()
" log Set log area/level: log [AREA[,AREA]*] [LEVEL]\n"
" AREA: main|network|bus|update|all\n"
" LEVEL: error|notice|info|debug\n"
" raw Toggle logging raw bytes\n"
" dump Toggle dumping raw bytes\n"
" raw Toggle logging of each byte\n"
" dump Toggle binary dump of received bytes\n"
" reload Reload CSV config files\n"
" quit|q Close connection\n"
" help|h Print help help [COMMAND]";
Expand Down
Loading

0 comments on commit cdbcb46

Please sign in to comment.