added optional initial active scan address to --scanconfig option (including full scan) and set default to sending broadcast ident message, check address argument for validity in scan command

This commit is contained in:
john30
2016-09-18 12:13:43 +02:00
parent 50b74b491b
commit ff0b3636c5
4 changed files with 64 additions and 12 deletions
+23 -5
View File
@@ -70,6 +70,7 @@ static struct options opt = {
-1, // latency
CONFIG_PATH, // configPath
false, // scanConfig
BROADCAST, // initialScan
0, // checkConfig
5, // pollInterval
0x31, // address
@@ -144,7 +145,7 @@ static const struct argp_option argpoptions[] = {
{NULL, 0, NULL, 0, "Message configuration options:", 2 },
{"configpath", 'c', "PATH", 0, "Read CSV config files from PATH [" CONFIG_PATH "]", 0 },
{"scanconfig", 's', NULL, 0, "Pick CSV config files matching initial scan. If combined with --checkconfig, you can add scan message data as arguments for checking a particular scan configuration, e.g. \"FF08070400/0AB5454850303003277201\".", 0 },
{"scanconfig", 's', "ADDR", OPTION_ARG_OPTIONAL, "Pick CSV config files matching initial scan (ADDR=\"none\" or empty for no initial scan message, \"full\" for full scan, or a single hex address to scan, default is broadcast ident message). If combined with --checkconfig, you can add scan message data as arguments for checking a particular scan configuration, e.g. \"FF08070400/0AB5454850303003277201\".", 0 },
{"checkconfig", O_CHKCFG, NULL, 0, "Check CSV config files, then stop", 0 },
{"dumpconfig", O_DMPCFG, NULL, 0, "Check and dump CSV config files, then stop", 0 },
{"pollinterval", O_POLINT, "SEC", 0, "Poll for data every SEC seconds (0=disable) [5]", 0 },
@@ -224,7 +225,7 @@ error_t parse_opt(int key, char *arg, struct argp_state *state)
case O_INISND: // --initsend
opt->initialSend = true;
break;
case O_DEVLAT: // --latency
case O_DEVLAT: // --latency=10000
opt->latency = parseInt(arg, 10, 0, 200000, result);
if (result != RESULT_OK) {
argp_error(state, "invalid latency");
@@ -240,12 +241,28 @@ error_t parse_opt(int key, char *arg, struct argp_state *state)
}
opt->configPath = arg;
break;
case 's': // --scanconfig
case 's': // --scanconfig[=ADDR] (ADDR=<empty>|full|<hexaddr>)
opt->scanConfig = true;
if (opt->readOnly) {
argp_error(state, "cannot combine readonly with scanconfig/answer/generatesyn");
return EINVAL;
}
if (arg != NULL) {
if (arg[0] == 0 || strcmp("none", arg) == 0) {
opt->initialScan = ESC;
} else if (strcmp("full", arg) == 0) {
opt->initialScan = SYN;
} else {
opt->initialScan = (unsigned char)parseInt(arg, 16, 0x00, 0xff, result);
if (!isValidAddress(opt->initialScan)) {
argp_error(state, "invalid initial scan address");
return EINVAL;
}
if (isMaster(opt->initialScan)) {
opt->initialScan = (unsigned char)(opt->initialScan+5);
}
}
}
break;
case O_CHKCFG: // --checkconfig
if (opt->checkConfig==0)
@@ -344,7 +361,7 @@ error_t parse_opt(int key, char *arg, struct argp_state *state)
case O_LOCAL: // --localhost
opt->localOnly = true;
break;
case O_HTTPPT: // --httpport
case O_HTTPPT: // --httpport=0
opt->httpPort = (uint16_t)parseInt(arg, 10, 1, 65535, result);
if (result != RESULT_OK) {
argp_error(state, "invalid port");
@@ -897,8 +914,9 @@ int main(int argc, char* argv[])
struct argp argp = { argpoptions, parse_opt, NULL, argpdoc, NULL, NULL, NULL };
int arg_index = -1;
setenv("ARGP_HELP_FMT", "no-dup-args-note", 0);
if (argp_parse(&argp, argc, argv, ARGP_IN_ORDER, &arg_index, &opt) != 0)
if (argp_parse(&argp, argc, argv, ARGP_IN_ORDER, &arg_index, &opt) != 0) {
return EINVAL;
}
s_messageMap = new MessageMap(opt.checkConfig && opt.scanConfig && arg_index >= argc);
if (opt.checkConfig) {
+1
View File
@@ -37,6 +37,7 @@ struct options
const char* configPath; //!< path to CSV configuration files [/etc/ebusd]
bool scanConfig; //!< pick configuration files matching initial scan
unsigned char initialScan; //!< the initial address to scan for scanconfig (@a ESC=none, 0xfe=broadcast ident, @a SYN=full scan, else: single slave address)
int checkConfig; //!< check CSV config files (!=0) and optionally dump (2), then stop
int pollInterval; //!< poll interval in seconds, 0 to disable [5]
+35 -6
View File
@@ -42,7 +42,7 @@ static const char* columnNames[] = {
static const size_t columnCount = sizeof(columnNames) / sizeof(char*);
MainLoop::MainLoop(const struct options opt, Device *device, MessageMap* messages)
: m_device(device), m_messages(messages), m_address(opt.address), m_scanConfig(opt.scanConfig), m_enableHex(opt.enableHex)
: m_device(device), m_messages(messages), m_address(opt.address), m_scanConfig(opt.scanConfig), m_initialScan(opt.initialScan), m_enableHex(opt.enableHex)
{
// setup Device
m_device->setLogRaw(opt.logRaw);
@@ -96,7 +96,7 @@ MainLoop::~MainLoop()
void MainLoop::run()
{
bool running = true;
bool running = true, reload = true;
time_t lastTaskRun, now;
int taskDelay = 5;
unsigned char lastScanAddress = 0; // 0 is known to be a master
@@ -115,6 +115,31 @@ void MainLoop::run()
} else if (now > lastTaskRun+taskDelay) {
logDebug(lf_main, "performing regular tasks");
if (m_scanConfig) {
if (m_initialScan != ESC && reload && m_busHandler->hasSignal()) {
result_t result = RESULT_ERR_NO_SIGNAL;
if (m_initialScan == SYN) {
logNotice(lf_main, "initiating full scan");
result = m_busHandler->startScan(true);
} else {
logNotice(lf_main, "starting initial scan for %2.2x", m_initialScan);
SymbolString slave(false);
result = m_busHandler->scanAndWait(m_initialScan, slave);
Message* message = m_messages->getScanMessage(m_initialScan);
if (result == RESULT_OK && message != NULL) {
ostringstream ret;
result = message->decodeLastData(ret, 0, true); // decode data
if (result == RESULT_OK) {
logNotice(lf_main, "initial scan result: %2.2x%s", m_initialScan, ret.str().c_str());
}
}
}
if (result != RESULT_OK) {
logError(lf_main, "initial scan failed: %s", getResultCode(result));
}
if (result != RESULT_ERR_NO_SIGNAL) {
reload = false;
}
}
bool scanned = false;
lastScanAddress = m_busHandler->getNextScanAddress(lastScanAddress, scanned);
if (lastScanAddress==SYN) {
@@ -164,7 +189,7 @@ void MainLoop::run()
bool connected = true;
if (request.length() > 0) {
logDebug(lf_main, ">>> %s", request.c_str());
result = decodeMessage(request, message->isHttp(), connected, listening, running);
result = decodeMessage(request, message->isHttp(), connected, listening, running, reload);
if (result.length() == 0 && !message->isHttp())
result = getResultCode(RESULT_EMPTY);
@@ -188,7 +213,7 @@ void MainLoop::run()
}
}
string MainLoop::decodeMessage(const string& data, const bool isHttp, bool& connected, bool& listening, bool& running)
string MainLoop::decodeMessage(const string& data, const bool isHttp, bool& connected, bool& listening, bool& running, bool& reload)
{
ostringstream result;
@@ -272,8 +297,10 @@ string MainLoop::decodeMessage(const string& data, const bool isHttp, bool& conn
return executeRaw(args);
if (strcasecmp(str, "DUMP") == 0)
return executeDump(args);
if (strcasecmp(str, "RELOAD") == 0)
if (strcasecmp(str, "RELOAD") == 0) {
reload = true;
return executeReload(args);
}
if (strcasecmp(str, "STOP") == 0)
return executeStop(args, running);
if (strcasecmp(str, "Q") == 0 || strcasecmp(str, "QUIT") == 0)
@@ -993,6 +1020,8 @@ string MainLoop::executeScan(vector<string> &args)
result_t result;
unsigned char dstAddress = (unsigned char)parseInt(args[1].c_str(), 16, 0, 0xff, result);
if (result == RESULT_OK && !isValidAddress(dstAddress, false))
result = RESULT_ERR_INVALID_ADDR;
if (result != RESULT_OK)
return getResultCode(result);
@@ -1001,7 +1030,7 @@ string MainLoop::executeScan(vector<string> &args)
if (result != RESULT_OK)
return getResultCode(result);
Message* message = m_messages->getScanMessage(dstAddress); // never NULL due to scanAndWait() == RESULT_OK
Message* message = m_messages->getScanMessage(dstAddress); // never NULL due to scanAndWait() == RESULT_OK && dstAddress != BROADCAST
ostringstream ret;
ret << hex << setw(2) << setfill('0') << static_cast<unsigned>(dstAddress);
result = message->decodeLastData(ret, 0, true); // decode data
+5 -1
View File
@@ -72,6 +72,9 @@ private:
/** whether to pick configuration files matching initial scan. */
const bool m_scanConfig;
/** the initial address to scan for @a m_scanConfig (@a ESC=none, 0xfe=broadcast ident, @a SYN=full scan, else: single slave address). */
const unsigned char m_initialScan;
/** whether to enable the hex command. */
const bool m_enableHex;
@@ -94,9 +97,10 @@ private:
* @param isHttp true for HTTP message.
* @param listening set to true when the client is in listening mode.
* @param running set to false when the server shall be stopped.
* @param reload set to true when the configuration files were reloaded.
* @return result string to send back to the client.
*/
string decodeMessage(const string& data, const bool isHttp, bool& connected, bool& listening, bool& running);
string decodeMessage(const string& data, const bool isHttp, bool& connected, bool& listening, bool& running, bool& reload);
/**
* Parse the hex master message from the remaining arguments.