mainloop: moved instruction execution to main loop, do not send intial scan when readonly, added "--inject" option, allow --readonly with --scanconfig[=none], store scans initiated by other participants, removed unused code

This commit is contained in:
john30
2017-04-29 15:13:05 +02:00
parent 5938628a3c
commit 33ee8ae0ed
6 changed files with 128 additions and 57 deletions
+23 -13
View File
@@ -384,6 +384,7 @@ void BusHandler::run() {
lastTime += 2; lastTime += 2;
logNotice(lf_bus, "bus started with own address %2.2x/%2.2x%s", m_ownMasterAddress, m_ownSlaveAddress, logNotice(lf_bus, "bus started with own address %2.2x/%2.2x%s", m_ownMasterAddress, m_ownSlaveAddress,
m_answer?" in answer mode":""); m_answer?" in answer mode":"");
do { do {
if (m_device->isValid() && !m_reconnect) { if (m_device->isValid() && !m_reconnect) {
result_t result = handleSymbol(); result_t result = handleSymbol();
@@ -569,7 +570,6 @@ result_t BusHandler::handleSymbol() {
// receive next symbol (optionally check reception of sent symbol) // receive next symbol (optionally check reception of sent symbol)
symbol_t recvSymbol; symbol_t recvSymbol;
result = m_device->recv(timeout+m_transferLatency, recvSymbol); result = m_device->recv(timeout+m_transferLatency, recvSymbol);
if (!sending && result == RESULT_ERR_TIMEOUT && m_generateSynInterval > 0 if (!sending && result == RESULT_ERR_TIMEOUT && m_generateSynInterval > 0
&& timeout >= m_generateSynInterval && (m_state == bs_noSignal || m_state == bs_skip)) { && timeout >= m_generateSynInterval && (m_state == bs_noSignal || m_state == bs_skip)) {
// check if acting as AUTO-SYN generator is required // check if acting as AUTO-SYN generator is required
@@ -1102,6 +1102,21 @@ void BusHandler::receiveCompleted() {
logNotice(lf_update, "unknown MM cmd: %s", m_command.getStr().c_str()); logNotice(lf_update, "unknown MM cmd: %s", m_command.getStr().c_str());
} else { } else {
logNotice(lf_update, "unknown MS cmd: %s / %s", m_command.getStr().c_str(), m_response.getStr().c_str()); logNotice(lf_update, "unknown MS cmd: %s / %s", m_command.getStr().c_str(), m_response.getStr().c_str());
if (m_command.size() >= 5 && m_command[2] == 0x07 && m_command[3] == 0x04) {
Message* message = m_messages->getScanMessage(dstAddress);
if (message && (message->getLastUpdateTime() == 0 || message->getLastSlaveData().getDataSize() < 10)) {
result_t result = message->storeLastData(m_command, m_response);
if (result == RESULT_OK) {
ostringstream output;
result = message->decodeLastData(output, 0, true);
if (result == RESULT_OK) {
string str = output.str();
setScanResult(dstAddress, 0, str);
}
}
logNotice(lf_update, "store %2.2x ident: %s", dstAddress, getResultCode(result));
}
}
} }
} else { } else {
m_messages->invalidateCache(message); m_messages->invalidateCache(message);
@@ -1141,7 +1156,9 @@ result_t BusHandler::prepareScan(symbol_t slave, bool full, string levels, bool&
if (scanMessage == NULL) { if (scanMessage == NULL) {
return RESULT_ERR_NOTFOUND; return RESULT_ERR_NOTFOUND;
} }
if (m_device->isReadOnly()) {
return RESULT_OK;
}
deque<Message*> messages = m_messages->findAll("scan", "", levels, true); deque<Message*> messages = m_messages->findAll("scan", "", levels, true);
auto it = messages.begin(); auto it = messages.begin();
while (it != messages.end()) { while (it != messages.end()) {
@@ -1463,6 +1480,7 @@ result_t BusHandler::scanAndWait(symbol_t dstAddress, bool loadScanConfig, bool
result = loadScanConfigFile(m_messages, dstAddress, file); result = loadScanConfigFile(m_messages, dstAddress, file);
} }
if (result == RESULT_OK) { if (result == RESULT_OK) {
executeInstructions(m_messages);
setScanConfigLoaded(dstAddress, file); setScanConfigLoaded(dstAddress, file);
if (!hasAdditionalScanMessages && m_messages->hasAdditionalScanMessages()) { if (!hasAdditionalScanMessages && m_messages->hasAdditionalScanMessages()) {
// additional scan messages now available // additional scan messages now available
@@ -1499,7 +1517,7 @@ void BusHandler::formatGrabResult(const bool unknown, ostringstream& output, con
} }
} }
symbol_t BusHandler::getNextScanAddress(symbol_t lastAddress, bool onlyScanned) { symbol_t BusHandler::getNextScanAddress(symbol_t lastAddress) {
if (lastAddress == SYN) { if (lastAddress == SYN) {
return SYN; return SYN;
} }
@@ -1507,22 +1525,14 @@ symbol_t BusHandler::getNextScanAddress(symbol_t lastAddress, bool onlyScanned)
if (!isValidAddress(lastAddress, false) || isMaster(lastAddress)) { if (!isValidAddress(lastAddress, false) || isMaster(lastAddress)) {
continue; continue;
} }
if (onlyScanned) { if ((m_seenAddresses[lastAddress]&(SEEN|LOAD_INIT)) == SEEN) {
if ((m_seenAddresses[lastAddress]&(LOAD_INIT|SCAN_DONE)) == SCAN_DONE) {
return lastAddress;
}
} else if ((m_seenAddresses[lastAddress]&(SEEN|LOAD_INIT)) == SEEN) {
return lastAddress; return lastAddress;
} }
symbol_t master = getMasterAddress(lastAddress); symbol_t master = getMasterAddress(lastAddress);
if (master == SYN || (m_seenAddresses[master]&SEEN) == 0) { if (master == SYN || (m_seenAddresses[master]&SEEN) == 0) {
continue; continue;
} }
if (onlyScanned) { if ((m_seenAddresses[lastAddress]&LOAD_INIT) == 0) {
if ((m_seenAddresses[lastAddress]&(LOAD_INIT|SCAN_DONE)) == SCAN_DONE) {
return lastAddress;
}
} else if ((m_seenAddresses[lastAddress]&LOAD_INIT) == 0) {
return lastAddress; return lastAddress;
} }
} }
+15 -3
View File
@@ -413,6 +413,19 @@ class BusHandler : public WaitThread {
*/ */
void clear(); void clear();
/**
* Inject a message from outside and treat it as regularly retrieved from the bus.
* @param master the @a MasterSymbolString with the master data.
* @param slave the @a SlaveSymbolString with the slave data.
*/
void injectMessage(MasterSymbolString& master, SlaveSymbolString& slave) {
m_command = master;
m_response = slave;
m_addressConflict = true; // avoid conflict messages
receiveCompleted();
m_addressConflict = false;
}
/** /**
* Send a message on the bus and wait for the answer. * Send a message on the bus and wait for the answer.
* @param master the @a MasterSymbolString with the master data to send. * @param master the @a MasterSymbolString with the master data to send.
@@ -489,7 +502,7 @@ class BusHandler : public WaitThread {
* Send a scan message on the bus and wait for the answer. * Send a scan message on the bus and wait for the answer.
* @param dstAddress the destination slave address to send to. * @param dstAddress the destination slave address to send to.
* @param loadScanConfig true to immediately load the message definitions matching the scan result. * @param loadScanConfig true to immediately load the message definitions matching the scan result.
* @param reload true to fully reload the scan results. * @param reload true to fully reload the scan results, false when the slave ID was already retrieved.
* @return the result code. * @return the result code.
*/ */
result_t scanAndWait(symbol_t dstAddress, bool loadScanConfig = false, bool reload = false); result_t scanAndWait(symbol_t dstAddress, bool loadScanConfig = false, bool reload = false);
@@ -541,10 +554,9 @@ class BusHandler : public WaitThread {
/** /**
* Get the next slave address that still needs to be scanned or loaded. * Get the next slave address that still needs to be scanned or loaded.
* @param lastAddress the last returned slave address, or 0 for returning the first one. * @param lastAddress the last returned slave address, or 0 for returning the first one.
* @param onlyScanned true to return only already scanned addresses.
* @return the next slave address that still needs to be scanned or loaded, or @a SYN. * @return the next slave address that still needs to be scanned or loaded, or @a SYN.
*/ */
symbol_t getNextScanAddress(symbol_t lastAddress, bool onlyScanned = false); symbol_t getNextScanAddress(symbol_t lastAddress);
/** /**
* Set the state of the participant to configuration @a LOADED. * Set the state of the participant to configuration @a LOADED.
+70 -39
View File
@@ -86,11 +86,12 @@ static struct options opt = {
CONFIG_PATH, // configPath CONFIG_PATH, // configPath
false, // scanConfig false, // scanConfig
BROADCAST, // initialScan 0, // initialScan
getenv("LANG"), // preferLanguage getenv("LANG"), // preferLanguage
false, // checkConfig false, // checkConfig
false, // dumpConfig false, // dumpConfig
5, // pollInterval 5, // pollInterval
false, // injectMessages
0x31, // address 0x31, // address
false, // answer false, // answer
@@ -177,13 +178,16 @@ static const struct argp_option argpoptions[] = {
{"configpath", 'c', "PATH", 0, "Read CSV config files from PATH [" CONFIG_PATH "]", 0 }, {"configpath", 'c', "PATH", 0, "Read CSV config files from PATH [" CONFIG_PATH "]", 0 },
{"scanconfig", 's', "ADDR", OPTION_ARG_OPTIONAL, "Pick CSV config files matching initial scan (ADDR=" {"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, " "\"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 " "default is broadcast ident message). If combined with --checkconfig and --inject, you can add scan message "
"arguments for checking a particular scan configuration, e.g. \"FF08070400/0AB5454850303003277201\".", 0 }, "data as arguments for checking a particular scan configuration, e.g. \"FF08070400/0AB5454850303003277201\".",
0 },
{"configlang", O_CFGLNG, "LANG", 0, {"configlang", O_CFGLNG, "LANG", 0,
"Prefer LANG in multilingual configuration files [system default language]", 0 }, "Prefer LANG in multilingual configuration files [system default language]", 0 },
{"checkconfig", O_CHKCFG, NULL, 0, "Check CSV config files, then stop", 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 }, {"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 }, {"pollinterval", O_POLINT, "SEC", 0, "Poll for data every SEC seconds (0=disable) [5]", 0 },
{"inject", 'i', NULL, 0, "Inject remaining arguments as already seen messages (e.g. "
"\"FF08070400/0AB5454850303003277201\")", 0 },
{NULL, 0, NULL, 0, "eBUS options:", 3 }, {NULL, 0, NULL, 0, "eBUS options:", 3 },
{"address", 'a', "ADDR", 0, "Use ADDR as own bus address [31]", 0 }, {"address", 'a', "ADDR", 0, "Use ADDR as own bus address [31]", 0 },
@@ -261,13 +265,18 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
opt->noDeviceCheck = true; opt->noDeviceCheck = true;
break; break;
case 'r': // --readonly case 'r': // --readonly
if (opt->answer || opt->generateSyn) { if (opt->answer || opt->generateSyn || opt->initialSend
argp_error(state, "cannot combine readonly with answer/generatesyn"); || (opt->scanConfig && opt->initialScan != 0 && opt->initialScan != ESC)) {
argp_error(state, "cannot combine readonly with answer/generatesyn/initsend/scanconfig=*");
return EINVAL; return EINVAL;
} }
opt->readOnly = true; opt->readOnly = true;
break; break;
case O_INISND: // --initsend case O_INISND: // --initsend
if (opt->readOnly) {
argp_error(state, "cannot combine readonly with answer/generatesyn/initsend/scanconfig=*");
return EINVAL;
}
opt->initialSend = true; opt->initialSend = true;
break; break;
case O_DEVLAT: // --latency=10000 case O_DEVLAT: // --latency=10000
@@ -307,6 +316,10 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
opt->initialScan = getSlaveAddress(opt->initialScan); opt->initialScan = getSlaveAddress(opt->initialScan);
} }
} }
if (opt->readOnly && opt->initialScan != ESC) {
argp_error(state, "cannot combine readonly with answer/generatesyn/initsend/scanconfig=*");
return EINVAL;
}
} }
break; break;
case O_CFGLNG: // --configlang=LANG case O_CFGLNG: // --configlang=LANG
@@ -330,6 +343,9 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
return EINVAL; return EINVAL;
} }
break; break;
case 'i': // --inject
opt->injectMessages = true;
break;
// eBUS options: // eBUS options:
case 'a': // --address=31 case 'a': // --address=31
@@ -341,7 +357,7 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
break; break;
case O_ANSWER: // --answer case O_ANSWER: // --answer
if (opt->readOnly) { if (opt->readOnly) {
argp_error(state, "cannot combine readonly with answer/generatesyn"); argp_error(state, "cannot combine readonly with answer/generatesyn/initsend/scanconfig=*");
return EINVAL; return EINVAL;
} }
opt->answer = true; opt->answer = true;
@@ -383,7 +399,7 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
break; break;
case O_GENSYN: // --generatesyn case O_GENSYN: // --generatesyn
if (opt->readOnly) { if (opt->readOnly) {
argp_error(state, "cannot combine readonly with answer/generatesyn"); argp_error(state, "cannot combine readonly with answer/generatesyn/initsend/scanconfig=*");
return EINVAL; return EINVAL;
} }
opt->generateSyn = true; opt->generateSyn = true;
@@ -539,7 +555,7 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) {
break; break;
case ARGP_KEY_ARG: case ARGP_KEY_ARG:
if (!opt->checkConfig) { if (!opt->injectMessages) {
argp_error(state, "invalid arguments starting with \"%s\"", arg); argp_error(state, "invalid arguments starting with \"%s\"", arg);
return EINVAL; return EINVAL;
} }
@@ -830,11 +846,6 @@ void readMessage(Message* message) {
} }
} }
/**
* Helper method for executing all loaded and resolvable instructions.
* @param messages the @a MessageMap instance.
* @param verbose whether to verbosely log all problems.
*/
void executeInstructions(MessageMap* messages, bool verbose) { void executeInstructions(MessageMap* messages, bool verbose) {
string errorDescription; string errorDescription;
result_t result = messages->resolveConditions(errorDescription, verbose); result_t result = messages->resolveConditions(errorDescription, verbose);
@@ -875,13 +886,12 @@ result_t loadConfigFiles(MessageMap* messages, bool verbose, bool denyRecursive)
logError(lf_main, "error reading config files: %s, last error: %s", getResultCode(result), logError(lf_main, "error reading config files: %s, last error: %s", getResultCode(result),
errorDescription.c_str()); errorDescription.c_str());
} }
executeInstructions(messages, verbose);
return RESULT_OK; return RESULT_OK;
} }
result_t loadScanConfigFile(MessageMap* messages, symbol_t address, string& relativeFile, bool verbose) { result_t loadScanConfigFile(MessageMap* messages, symbol_t address, string& relativeFile, bool verbose) {
Message* message = messages->getScanMessage(address); Message* message = messages->getScanMessage(address);
if (!message) { if (!message || message->getLastUpdateTime() == 0) {
return RESULT_ERR_NOTFOUND; return RESULT_ERR_NOTFOUND;
} }
const SlaveSymbolString& data = message->getLastSlaveData(); const SlaveSymbolString& data = message->getLastSlaveData();
@@ -1042,10 +1052,33 @@ result_t loadScanConfigFile(MessageMap* messages, symbol_t address, string& rela
} }
logNotice(lf_main, "read scan config file %s for ID \"%s\", SW%4.4d, HW%4.4d", best.c_str(), ident.c_str(), sw, hw); logNotice(lf_main, "read scan config file %s for ID \"%s\", SW%4.4d, HW%4.4d", best.c_str(), ident.c_str(), sw, hw);
relativeFile = best.substr(strlen(opt.configPath)+1); relativeFile = best.substr(strlen(opt.configPath)+1);
executeInstructions(messages, verbose);
return RESULT_OK; return RESULT_OK;
} }
bool parseMessage(const string& arg, MasterSymbolString& master, SlaveSymbolString& slave, bool onlyMasterSlave) {
size_t pos = arg.find_first_of('/');
if (pos == string::npos) {
logError(lf_main, "invalid message %s: missing \"/\"", arg.c_str());
return false;
}
result_t result = master.parseHex(arg.substr(0, pos));
if (result == RESULT_OK) {
result = slave.parseHex(arg.substr(pos+1));
}
if (result != RESULT_OK) {
logError(lf_main, "invalid message %s: %s", arg.c_str(), getResultCode(result));
return false;
}
if (master.size() < 5) { // skip QQ ZZ PB SB NN
logError(lf_main, "invalid message %s: master part too short", arg.c_str());
return false;
}
if (!isMaster(master[0])) {
logError(lf_main, "invalid message %s: QQ is no master", arg.c_str());
return false;
}
return true;
}
/** /**
* Main function. * Main function.
@@ -1063,6 +1096,9 @@ int main(int argc, char* argv[]) {
return EINVAL; return EINVAL;
} }
if (!opt.readOnly && opt.scanConfig && opt.initialScan == 0) {
opt.initialScan = BROADCAST;
}
if (opt.logAreas != -1 || opt.logLevel != ll_COUNT) { if (opt.logAreas != -1 || opt.logLevel != ll_COUNT) {
setFacilitiesLogLevel(LF_ALL, ll_none); setFacilitiesLogLevel(LF_ALL, ll_none);
setFacilitiesLogLevel(opt.logAreas, opt.logLevel); setFacilitiesLogLevel(opt.logAreas, opt.logLevel);
@@ -1073,27 +1109,12 @@ int main(int argc, char* argv[]) {
logNotice(lf_main, PACKAGE_STRING "." REVISION " performing configuration check..."); logNotice(lf_main, PACKAGE_STRING "." REVISION " performing configuration check...");
result_t result = loadConfigFiles(s_messageMap, true, opt.scanConfig && arg_index < argc); result_t result = loadConfigFiles(s_messageMap, true, opt.scanConfig && arg_index < argc);
executeInstructions(s_messageMap, true);
MasterSymbolString master;
SlaveSymbolString slave;
while (result == RESULT_OK && opt.scanConfig && arg_index < argc) { while (result == RESULT_OK && opt.scanConfig && arg_index < argc) {
// check scan config for each passed ident message // check scan config for each passed ident message
string arg = argv[arg_index++]; if (!parseMessage(argv[arg_index++], master, slave, true)) {
size_t pos = arg.find_first_of('/');
if (pos == string::npos) {
logError(lf_main, "invalid scan message %s: missing \"/\"", arg.c_str());
continue;
}
MasterSymbolString master;
SlaveSymbolString slave;
result_t res = master.parseHex(arg.substr(0, pos));
if (res == RESULT_OK) {
res = slave.parseHex(arg.substr(pos+1));
}
if (res != RESULT_OK) {
logError(lf_main, "invalid scan message %s: %s", arg.c_str(), getResultCode(res));
continue;
}
if (master.size() < 5) { // skip QQ ZZ PB SB NN
logError(lf_main, "invalid scan message %s: master part too short", arg.c_str());
continue; continue;
} }
symbol_t address = master[1]; symbol_t address = master[1];
@@ -1103,7 +1124,8 @@ int main(int argc, char* argv[]) {
} else { } else {
message->storeLastData(master, slave); message->storeLastData(master, slave);
string file; string file;
res = loadScanConfigFile(s_messageMap, address, file, true); result_t res = loadScanConfigFile(s_messageMap, address, file, true);
executeInstructions(s_messageMap, true);
if (res == RESULT_OK) { if (res == RESULT_OK) {
logInfo(lf_main, "scan config %2.2x: file %s loaded", address, file.c_str()); logInfo(lf_main, "scan config %2.2x: file %s loaded", address, file.c_str());
} }
@@ -1139,12 +1161,21 @@ int main(int argc, char* argv[]) {
// load configuration files // load configuration files
loadConfigFiles(s_messageMap); loadConfigFiles(s_messageMap);
if (s_messageMap->sizeConditions() > 0 && opt.pollInterval == 0) {
logError(lf_main, "conditions require a poll interval > 0");
}
// create the MainLoop and start it // create the MainLoop and start it
s_mainLoop = new MainLoop(opt, device, s_messageMap); s_mainLoop = new MainLoop(opt, device, s_messageMap);
if (opt.injectMessages) {
BusHandler* busHandler = s_mainLoop->getBusHandler();
MasterSymbolString master;
SlaveSymbolString slave;
while (arg_index < argc) {
// add each passed message
if (!parseMessage(argv[arg_index++], master, slave, false)) {
continue;
}
busHandler->injectMessage(master, slave);
}
}
s_mainLoop->start("mainloop"); s_mainLoop->start("mainloop");
// wait for end of MainLoop // wait for end of MainLoop
+8
View File
@@ -49,6 +49,7 @@ struct options {
bool checkConfig; //!< check CSV config files, then stop bool checkConfig; //!< check CSV config files, then stop
bool dumpConfig; //!< dump CSV config files, then stop bool dumpConfig; //!< dump CSV config files, then stop
unsigned int pollInterval; //!< poll interval in seconds, 0 to disable [5] unsigned int pollInterval; //!< poll interval in seconds, 0 to disable [5]
bool injectMessages; //!< inject remaining arguments as already seen messages
symbol_t address; //!< own bus address [31] symbol_t address; //!< own bus address [31]
bool answer; //!< answer to requests from other masters bool answer; //!< answer to requests from other masters
@@ -111,6 +112,13 @@ result_t loadConfigFiles(MessageMap* messages, bool verbose = false, bool denyRe
*/ */
result_t loadScanConfigFile(MessageMap* messages, symbol_t address, string& relativeFile, bool verbose = false); result_t loadScanConfigFile(MessageMap* messages, symbol_t address, string& relativeFile, bool verbose = false);
/**
* Helper method for executing all loaded and resolvable instructions.
* @param messages the @a MessageMap instance.
* @param verbose whether to verbosely log all problems.
*/
void executeInstructions(MessageMap* messages, bool verbose = false);
} // namespace ebusd } // namespace ebusd
#endif // EBUSD_MAIN_H_ #endif // EBUSD_MAIN_H_
+9 -2
View File
@@ -99,8 +99,8 @@ result_t UserList::addFromFile(map<string, string>& row, vector< map<string, str
MainLoop::MainLoop(const struct options opt, Device *device, MessageMap* messages) MainLoop::MainLoop(const struct options opt, Device *device, MessageMap* messages)
: Thread(), m_device(device), m_reconnectCount(0), m_userList(opt.accessLevel), m_messages(messages), : Thread(), m_device(device), m_reconnectCount(0), m_userList(opt.accessLevel), m_messages(messages),
m_address(opt.address), m_scanConfig(opt.scanConfig), m_address(opt.address), m_scanConfig(opt.scanConfig), m_initialScan(opt.readOnly ? ESC : opt.initialScan),
m_initialScan(opt.initialScan), m_enableHex(opt.enableHex), m_shutdown(false) { m_polling(opt.pollInterval>0), m_enableHex(opt.enableHex), m_shutdown(false) {
// open Device // open Device
result_t result = m_device->open(); result_t result = m_device->open();
if (result != RESULT_OK) { if (result != RESULT_OK) {
@@ -287,6 +287,13 @@ void MainLoop::run() {
} }
} }
} }
} else if (reload && m_busHandler->hasSignal()) {
reload = false;
// execute initial instructions
executeInstructions(m_messages);
if (m_messages->sizeConditions() > 0 && !m_polling) {
logError(lf_main, "conditions require a poll interval > 0");
}
} }
if (!m_shutdown && now > nextCheckRun) { if (!m_shutdown && now > nextCheckRun) {
TCPClient client; TCPClient client;
+3
View File
@@ -349,6 +349,9 @@ class MainLoop : public Thread, DeviceListener {
* (@a ESC=none, 0xfe=broadcast ident, @a SYN=full scan, else: single slave address). */ * (@a ESC=none, 0xfe=broadcast ident, @a SYN=full scan, else: single slave address). */
const symbol_t m_initialScan; const symbol_t m_initialScan;
/** true when the poll interval is non zero. */
const bool m_polling;
/** whether to enable the hex command. */ /** whether to enable the hex command. */
const bool m_enableHex; const bool m_enableHex;