code style
This commit is contained in:
+32
-17
@@ -92,9 +92,11 @@ bool PollRequest::notify(result_t result, SymbolString& slave) {
|
||||
result = m_message->decodeLastData(output); // decode data
|
||||
}
|
||||
if (result < RESULT_OK) {
|
||||
logError(lf_bus, "poll %s %s failed: %s", m_message->getCircuit().c_str(), m_message->getName().c_str(), getResultCode(result));
|
||||
logError(lf_bus, "poll %s %s failed: %s", m_message->getCircuit().c_str(), m_message->getName().c_str(),
|
||||
getResultCode(result));
|
||||
} else {
|
||||
logNotice(lf_bus, "poll %s %s: %s", m_message->getCircuit().c_str(), m_message->getName().c_str(), output.str().c_str());
|
||||
logNotice(lf_bus, "poll %s %s: %s", m_message->getCircuit().c_str(), m_message->getName().c_str(),
|
||||
output.str().c_str());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -109,7 +111,8 @@ result_t ScanRequest::prepare(unsigned char ownMasterAddress) {
|
||||
m_busHandler->setScanResult(dstAddress, "");
|
||||
}
|
||||
istringstream input;
|
||||
result_t result = m_message->prepareMaster(ownMasterAddress, m_master, input, UI_FIELD_SEPARATOR, dstAddress, m_index);
|
||||
result_t result = m_message->prepareMaster(ownMasterAddress, m_master, input, UI_FIELD_SEPARATOR, dstAddress,
|
||||
m_index);
|
||||
if (result >= RESULT_OK) {
|
||||
logInfo(lf_bus, "scan %2.2x cmd: %s", dstAddress, m_master.getDataStr().c_str());
|
||||
}
|
||||
@@ -473,7 +476,8 @@ result_t BusHandler::handleSymbol() {
|
||||
if (sending && startRequest != NULL && m_nextRequests.remove(startRequest)) {
|
||||
m_currentRequest = startRequest; // force the failed request to be notified
|
||||
}
|
||||
if ((m_generateSynInterval != SYN_TIMEOUT && difftime(now, m_lastReceive) > 1) // at least one full second has passed since last received symbol
|
||||
if ((m_generateSynInterval != SYN_TIMEOUT && difftime(now, m_lastReceive) > 1)
|
||||
// at least one full second has passed since last received symbol
|
||||
|| m_state == bs_noSignal) {
|
||||
return setState(bs_noSignal, result);
|
||||
}
|
||||
@@ -529,14 +533,16 @@ result_t BusHandler::handleSymbol() {
|
||||
|
||||
case bs_recvCmd:
|
||||
headerLen = 4;
|
||||
crcPos = m_command.size() > headerLen ? headerLen + 1 + m_command[headerLen] : 0xff; // header symbols are never escaped
|
||||
// header symbols are never escaped
|
||||
crcPos = m_command.size() > headerLen ? headerLen + 1 + m_command[headerLen] : 0xff;
|
||||
result = m_command.push_back(recvSymbol, true, m_command.size() < crcPos);
|
||||
if (result < RESULT_OK) {
|
||||
return setState(bs_skip, result);
|
||||
}
|
||||
if (result == RESULT_OK && crcPos != 0xff && m_command.size() == crcPos + 1) { // CRC received
|
||||
unsigned char dstAddress = m_command[1];
|
||||
m_commandCrcValid = m_command[headerLen + 1 + m_command[headerLen]] == m_command.getCRC(); // header symbols are never escaped
|
||||
// header symbols are never escaped
|
||||
m_commandCrcValid = m_command[headerLen + 1 + m_command[headerLen]] == m_command.getCRC();
|
||||
if (m_commandCrcValid) {
|
||||
if (dstAddress == BROADCAST) {
|
||||
receiveCompleted();
|
||||
@@ -697,7 +703,8 @@ result_t BusHandler::handleSymbol() {
|
||||
}
|
||||
}
|
||||
if (message == NULL || message->isWrite()) {
|
||||
return setState(bs_skip, RESULT_ERR_INVALID_ARG); // don't know this request or definition has wrong direction, deny
|
||||
// don't know this request or definition has wrong direction, deny
|
||||
return setState(bs_skip, RESULT_ERR_INVALID_ARG);
|
||||
}
|
||||
if (message == m_messages->getScanMessage(m_ownSlaveAddress)) {
|
||||
input.str(SCAN_ANSWER);
|
||||
@@ -748,7 +755,8 @@ result_t BusHandler::setState(BusState state, result_t result, bool firstRepetit
|
||||
addSeenAddress(dstAddress);
|
||||
}
|
||||
bool restart = m_currentRequest->notify(
|
||||
result == RESULT_ERR_SYN && (m_state == bs_recvCmdAck || m_state == bs_recvRes) ? RESULT_ERR_TIMEOUT : result, m_response);
|
||||
result == RESULT_ERR_SYN && (m_state == bs_recvCmdAck || m_state == bs_recvRes)
|
||||
? RESULT_ERR_TIMEOUT : result, m_response);
|
||||
if (restart) {
|
||||
m_currentRequest->m_busLostRetries = 0;
|
||||
m_nextRequests.push(m_currentRequest);
|
||||
@@ -780,7 +788,8 @@ result_t BusHandler::setState(BusState state, result_t result, bool firstRepetit
|
||||
return result;
|
||||
}
|
||||
if (result < RESULT_OK || (result != RESULT_OK && state == bs_skip)) {
|
||||
logDebug(lf_bus, "%s during %s, switching to %s", getResultCode(result), getStateCode(m_state), getStateCode(state));
|
||||
logDebug(lf_bus, "%s during %s, switching to %s", getResultCode(result), getStateCode(m_state),
|
||||
getStateCode(state));
|
||||
} else if (m_currentRequest != NULL || state == bs_sendCmd || state == bs_sendResAck || state == bs_sendSyn) {
|
||||
logDebug(lf_bus, "switching from %s to %s", getStateCode(m_state), getStateCode(state));
|
||||
}
|
||||
@@ -893,7 +902,8 @@ void BusHandler::receiveCompleted() {
|
||||
} else if (master) {
|
||||
logNotice(lf_update, "unknown MM cmd: %s", m_command.getDataStr().c_str());
|
||||
} else {
|
||||
logNotice(lf_update, "unknown MS cmd: %s / %s", m_command.getDataStr().c_str(), m_response.getDataStr().c_str());
|
||||
logNotice(lf_update, "unknown MS cmd: %s / %s", m_command.getDataStr().c_str(),
|
||||
m_response.getDataStr().c_str());
|
||||
}
|
||||
} else {
|
||||
m_messages->invalidateCache(message);
|
||||
@@ -905,14 +915,17 @@ void BusHandler::receiveCompleted() {
|
||||
result = message->decodeLastData(output);
|
||||
}
|
||||
if (result < RESULT_OK) {
|
||||
logError(lf_update, "unable to parse %s %s from %s / %s: %s", circuit.c_str(), name.c_str(), m_command.getDataStr().c_str(), m_response.getDataStr().c_str(), getResultCode(result));
|
||||
logError(lf_update, "unable to parse %s %s from %s / %s: %s", circuit.c_str(), name.c_str(),
|
||||
m_command.getDataStr().c_str(), m_response.getDataStr().c_str(), getResultCode(result));
|
||||
} else {
|
||||
string data = output.str();
|
||||
if (m_answer && dstAddress == (master ? m_ownMasterAddress : m_ownSlaveAddress)) {
|
||||
logNotice(lf_update, "self-update %s %s QQ=%2.2x: %s", circuit.c_str(), name.c_str(), srcAddress, data.c_str()); // TODO store in database of internal variables
|
||||
logNotice(lf_update, "self-update %s %s QQ=%2.2x: %s", circuit.c_str(), name.c_str(), srcAddress,
|
||||
data.c_str()); // TODO store in database of internal variables
|
||||
} else if (message->getDstAddress() == SYN) { // any destination
|
||||
if (message->getSrcAddress() == SYN) { // any destination and any source
|
||||
logNotice(lf_update, "update %s %s QQ=%2.2x ZZ=%2.2x: %s", circuit.c_str(), name.c_str(), srcAddress, dstAddress, data.c_str());
|
||||
logNotice(lf_update, "update %s %s QQ=%2.2x ZZ=%2.2x: %s", circuit.c_str(), name.c_str(), srcAddress,
|
||||
dstAddress, data.c_str());
|
||||
} else {
|
||||
logNotice(lf_update, "update %s %s ZZ=%2.2x: %s", circuit.c_str(), name.c_str(), dstAddress, data.c_str());
|
||||
}
|
||||
@@ -1018,8 +1031,8 @@ void BusHandler::formatScanResult(ostringstream& output) {
|
||||
void BusHandler::formatSeenInfo(ostringstream& output) {
|
||||
unsigned char address = 0;
|
||||
for (int index = 0; index < 256; index++, address++) {
|
||||
if (isValidAddress(address, false)
|
||||
&& ((m_seenAddresses[address]&SEEN) != 0 || (!m_device->isReadOnly() && (address == m_ownMasterAddress || address == m_ownSlaveAddress)))) {
|
||||
if (isValidAddress(address, false) && ((m_seenAddresses[address]&SEEN) != 0
|
||||
|| (!m_device->isReadOnly() && (address == m_ownMasterAddress || address == m_ownSlaveAddress)))) {
|
||||
output << endl << "address " << setfill('0') << setw(2) << hex << static_cast<unsigned>(address);
|
||||
unsigned char master;
|
||||
if (isMaster(address)) {
|
||||
@@ -1081,7 +1094,8 @@ result_t BusHandler::scanAndWait(unsigned char dstAddress, SymbolString& slave)
|
||||
Message* message = m_messages->getScanMessage(dstAddress);
|
||||
if (message != NULL && message != scanMessage) {
|
||||
scanMessage = message;
|
||||
scanMessage->storeLastData(pt_masterData, master, 0); // update the cache, expected to work since this is a clone
|
||||
// update the cache, expected to work since this is a clone
|
||||
scanMessage->storeLastData(pt_masterData, master, 0);
|
||||
}
|
||||
}
|
||||
if (result != RESULT_ERR_NO_SIGNAL) {
|
||||
@@ -1110,7 +1124,8 @@ void BusHandler::formatGrabResult(const bool unknown, ostringstream& output) {
|
||||
output << "grab disabled";
|
||||
} else {
|
||||
bool first = true;
|
||||
for (map<uint64_t, GrabbedMessage>::iterator it = m_grabbedMessages.begin(); it != m_grabbedMessages.end(); it++) {
|
||||
for (map<uint64_t, GrabbedMessage>::iterator it = m_grabbedMessages.begin(); it != m_grabbedMessages.end();
|
||||
it++) {
|
||||
if (it->second.dump(unknown, m_messages, first, output)) {
|
||||
first = false;
|
||||
}
|
||||
|
||||
@@ -192,7 +192,8 @@ class ScanRequest : public BusRequest {
|
||||
* @param busHandler the @a BusHandler instance to notify of final scan result.
|
||||
*/
|
||||
ScanRequest(MessageMap* messageMap, deque<Message*> messages, deque<unsigned char> slaves, BusHandler* busHandler)
|
||||
: BusRequest(m_master, true), m_messageMap(messageMap), m_index(0), m_allMessages(messages), m_messages(messages), m_slaves(slaves), m_busHandler(busHandler) {
|
||||
: BusRequest(m_master, true), m_messageMap(messageMap), m_index(0), m_allMessages(messages), m_messages(messages),
|
||||
m_slaves(slaves), m_busHandler(busHandler) {
|
||||
m_message = m_messages.front();
|
||||
m_messages.pop_front();
|
||||
}
|
||||
@@ -356,7 +357,8 @@ class BusHandler : public WaitThread {
|
||||
m_answer(answer), m_addressConflict(false),
|
||||
m_busLostRetries(busLostRetries), m_failedSendRetries(failedSendRetries),
|
||||
m_transferLatency(transferLatency), m_busAcquireTimeout(busAcquireTimeout), m_slaveRecvTimeout(slaveRecvTimeout),
|
||||
m_masterCount(device->isReadOnly()?0:1), m_autoLockCount(lockCount == 0), m_lockCount(lockCount <= 3 ? 3 : lockCount), m_remainLockCount(m_autoLockCount),
|
||||
m_masterCount(device->isReadOnly()?0:1), m_autoLockCount(lockCount == 0),
|
||||
m_lockCount(lockCount <= 3 ? 3 : lockCount), m_remainLockCount(m_autoLockCount),
|
||||
m_generateSynInterval(generateSyn ? SYN_TIMEOUT*getMasterNumber(ownAddress)+SYMBOL_DURATION : 0),
|
||||
m_pollInterval(pollInterval), m_lastReceive(0), m_lastPoll(0),
|
||||
m_currentRequest(NULL), m_runningScans(0), m_nextSendPos(0),
|
||||
|
||||
+43
-20
@@ -161,7 +161,10 @@ 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', "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 },
|
||||
{"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 },
|
||||
@@ -187,8 +190,10 @@ static const struct argp_option argpoptions[] = {
|
||||
|
||||
{NULL, 0, NULL, 0, "Log options:", 5 },
|
||||
{"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 },
|
||||
{"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 },
|
||||
|
||||
{NULL, 0, NULL, 0, "Raw logging options:", 6 },
|
||||
{"lograwdata", O_RAW, NULL, 0, "Log each received/sent byte on the bus", 0 },
|
||||
@@ -640,7 +645,8 @@ static result_t collectConfigFiles(const string path, const string prefix, const
|
||||
if (hasTemplates) {
|
||||
*hasTemplates = true;
|
||||
}
|
||||
} else if (prefix.length() == 0 || (name.length() >= prefix.length() && name.substr(0, prefix.length()) == prefix)) {
|
||||
} else if (prefix.length() == 0
|
||||
|| (name.length() >= prefix.length() && name.substr(0, prefix.length()) == prefix)) {
|
||||
files.push_back(p);
|
||||
}
|
||||
}
|
||||
@@ -692,7 +698,8 @@ static bool readTemplates(const string path, const string extension, bool availa
|
||||
if (result == RESULT_OK) {
|
||||
logInfo(lf_main, "read templates in %s", path.c_str());
|
||||
} else {
|
||||
logError(lf_main, "error reading templates in %s: %s, last error: %s", path.c_str(), getResultCode(result), templates->getLastError().c_str());
|
||||
logError(lf_main, "error reading templates in %s: %s, last error: %s", path.c_str(), getResultCode(result),
|
||||
templates->getLastError().c_str());
|
||||
}
|
||||
return templates;
|
||||
}
|
||||
@@ -706,7 +713,8 @@ static bool readTemplates(const string path, const string extension, bool availa
|
||||
* @param verbose whether to verbosely log problems.
|
||||
* @return the result code.
|
||||
*/
|
||||
static result_t readConfigFiles(const string path, const string extension, MessageMap* messages, bool recursive, bool verbose) {
|
||||
static result_t readConfigFiles(const string path, const string extension, MessageMap* messages, bool recursive,
|
||||
bool verbose) {
|
||||
vector<string> files, dirs;
|
||||
bool hasTemplates = false;
|
||||
result_t result = collectConfigFiles(path, "", extension, files, &dirs, &hasTemplates);
|
||||
@@ -746,7 +754,8 @@ void readMessage(Message* message) {
|
||||
BusHandler* busHandler = s_mainLoop->getBusHandler();
|
||||
result_t result = busHandler->readFromBus(message, "");
|
||||
if (result != RESULT_OK) {
|
||||
logError(lf_main, "error reading message %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(), getResultCode(result));
|
||||
logError(lf_main, "error reading message %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(),
|
||||
getResultCode(result));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -758,23 +767,27 @@ void readMessage(Message* message) {
|
||||
void executeInstructions(MessageMap* messages, bool verbose) {
|
||||
result_t result = messages->resolveConditions(verbose);
|
||||
if (result != RESULT_OK) {
|
||||
logError(lf_main, "error resolving conditions: %s, last error: %s", getResultCode(result), messages->getLastError().c_str());
|
||||
logError(lf_main, "error resolving conditions: %s, last error: %s", getResultCode(result),
|
||||
messages->getLastError().c_str());
|
||||
}
|
||||
ostringstream log;
|
||||
result = messages->executeInstructions(log, readMessage);
|
||||
if (result != RESULT_OK) {
|
||||
logError(lf_main, "error executing instructions: %s, last error: %s, %s", getResultCode(result), messages->getLastError().c_str(), log.str().c_str());
|
||||
logError(lf_main, "error executing instructions: %s, last error: %s, %s", getResultCode(result),
|
||||
messages->getLastError().c_str(), log.str().c_str());
|
||||
} else if (verbose && log.tellp() > 0) {
|
||||
logInfo(lf_main, log.str().c_str());
|
||||
}
|
||||
logNotice(lf_main, "found messages: %d (%d conditional on %d conditions, %d poll, %d update)", messages->size(), messages->sizeConditional(), messages->sizeConditions(), messages->sizePoll(), messages->sizePassive());
|
||||
logNotice(lf_main, "found messages: %d (%d conditional on %d conditions, %d poll, %d update)", messages->size(),
|
||||
messages->sizeConditional(), messages->sizeConditions(), messages->sizePoll(), messages->sizePassive());
|
||||
}
|
||||
|
||||
result_t loadConfigFiles(MessageMap* messages, bool verbose, bool denyRecursive) {
|
||||
logInfo(lf_main, "loading configuration files from %s", opt.configPath);
|
||||
messages->clear();
|
||||
s_globalTemplates.clear();
|
||||
for (map<string, DataFieldTemplates*>::iterator it = s_templatesByPath.begin(); it != s_templatesByPath.end(); it++) {
|
||||
for (map<string, DataFieldTemplates*>::iterator it = s_templatesByPath.begin(); it != s_templatesByPath.end();
|
||||
it++) {
|
||||
if (it->second != &s_globalTemplates) {
|
||||
delete it->second;
|
||||
}
|
||||
@@ -782,17 +795,20 @@ result_t loadConfigFiles(MessageMap* messages, bool verbose, bool denyRecursive)
|
||||
}
|
||||
s_templatesByPath.clear();
|
||||
|
||||
result_t result = readConfigFiles(string(opt.configPath), ".csv", messages, (!opt.scanConfig || opt.checkConfig) && !denyRecursive, verbose);
|
||||
result_t result = readConfigFiles(string(opt.configPath), ".csv", messages,
|
||||
(!opt.scanConfig || opt.checkConfig) && !denyRecursive, verbose);
|
||||
if (result == RESULT_OK) {
|
||||
logInfo(lf_main, "read config files");
|
||||
} else {
|
||||
logError(lf_main, "error reading config files: %s, last error: %s", getResultCode(result), messages->getLastError().c_str());
|
||||
logError(lf_main, "error reading config files: %s, last error: %s", getResultCode(result),
|
||||
messages->getLastError().c_str());
|
||||
}
|
||||
executeInstructions(messages, verbose);
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
result_t loadScanConfigFile(MessageMap* messages, unsigned char address, SymbolString& data, string& relativeFile, bool verbose) {
|
||||
result_t loadScanConfigFile(MessageMap* messages, unsigned char address, SymbolString& data, string& relativeFile,
|
||||
bool verbose) {
|
||||
PartType partType;
|
||||
if (isMaster(address)) {
|
||||
address = (unsigned char)(data[0]+5); // slave address of sending master
|
||||
@@ -849,14 +865,17 @@ result_t loadScanConfigFile(MessageMap* messages, unsigned char address, SymbolS
|
||||
// find files matching MANUFACTURER/ZZ.*csv in cfgpath
|
||||
result = collectConfigFiles(path, prefix, ".csv", files, NULL, &hasTemplates);
|
||||
if (result != RESULT_OK) {
|
||||
logError(lf_main, "unable to load scan config %2.2x: list files in %s %s", address, path.c_str(), getResultCode(result));
|
||||
logError(lf_main, "unable to load scan config %2.2x: list files in %s %s", address, path.c_str(),
|
||||
getResultCode(result));
|
||||
return result;
|
||||
}
|
||||
if (files.empty()) {
|
||||
logError(lf_main, "unable to load scan config %2.2x: no file from %s with prefix %s found", address, path.c_str(), prefix.c_str());
|
||||
logError(lf_main, "unable to load scan config %2.2x: no file from %s with prefix %s found", address, path.c_str(),
|
||||
prefix.c_str());
|
||||
return RESULT_ERR_NOTFOUND;
|
||||
}
|
||||
logDebug(lf_main, "found %d matching scan config files from %s with prefix %s: %s", files.size(), path.c_str(), prefix.c_str(), getResultCode(result));
|
||||
logDebug(lf_main, "found %d matching scan config files from %s with prefix %s: %s", files.size(), path.c_str(),
|
||||
prefix.c_str(), getResultCode(result));
|
||||
for (string::iterator it = ident.begin(); it != ident.end(); it++) {
|
||||
if (::isspace(*it)) {
|
||||
ident.erase(it--);
|
||||
@@ -872,7 +891,8 @@ result_t loadScanConfigFile(MessageMap* messages, unsigned char address, SymbolS
|
||||
unsigned char checkDest;
|
||||
string checkIdent, useCircuit, useSuffix;
|
||||
unsigned int checkSw, checkHw;
|
||||
if (!FileReader::extractDefaultsFromFilename(name.substr(path.length()+1), checkDest, checkIdent, useCircuit, useSuffix, checkSw, checkHw)) {
|
||||
if (!FileReader::extractDefaultsFromFilename(name.substr(path.length()+1), checkDest, checkIdent, useCircuit,
|
||||
useSuffix, checkSw, checkHw)) {
|
||||
continue;
|
||||
}
|
||||
if (address != checkDest || (checkSw != UINT_MAX && sw != checkSw) || (checkHw != UINT_MAX && hw != checkHw)) {
|
||||
@@ -905,7 +925,9 @@ result_t loadScanConfigFile(MessageMap* messages, unsigned char address, SymbolS
|
||||
}
|
||||
|
||||
if (best.empty()) {
|
||||
logError(lf_main, "unable to load scan config %2.2x: no file from %s with prefix %s matches ID \"%s\", SW%4.4d, HW%4.4d", address, path.c_str(), prefix.c_str(), ident.c_str(), sw, hw);
|
||||
logError(lf_main,
|
||||
"unable to load scan config %2.2x: no file from %s with prefix %s matches ID \"%s\", SW%4.4d, HW%4.4d",
|
||||
address, path.c_str(), prefix.c_str(), ident.c_str(), sw, hw);
|
||||
return RESULT_ERR_NOTFOUND;
|
||||
}
|
||||
|
||||
@@ -934,7 +956,8 @@ result_t loadScanConfigFile(MessageMap* messages, unsigned char address, SymbolS
|
||||
}
|
||||
result = messages->readFromFile(best, opt.checkConfig, "", ident);
|
||||
if (result != RESULT_OK) {
|
||||
logError(lf_main, "error reading scan config file %s for ID \"%s\", SW%4.4d, HW%4.4d: %s", best.c_str(), ident.c_str(), sw, hw, getResultCode(result));
|
||||
logError(lf_main, "error reading scan config file %s for ID \"%s\", SW%4.4d, HW%4.4d: %s", best.c_str(),
|
||||
ident.c_str(), sw, hw, getResultCode(result));
|
||||
return result;
|
||||
}
|
||||
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);
|
||||
|
||||
+7
-3
@@ -39,7 +39,9 @@ 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)
|
||||
/** the initial address to scan for scanconfig
|
||||
* (@a ESC=none, 0xfe=broadcast ident, @a SYN=full scan, else: single slave address). */
|
||||
unsigned char initialScan;
|
||||
int checkConfig; //!< check CSV config files ( != 0) and optionally dump (2), then stop
|
||||
int pollInterval; //!< poll interval in seconds, 0 to disable [5]
|
||||
|
||||
@@ -90,13 +92,15 @@ result_t loadConfigFiles(MessageMap* messages, bool verbose = false, bool denyRe
|
||||
/**
|
||||
* Load the message definitions from a configuration file matching the scan result.
|
||||
* @param messages the @a MessageMap to load the messages into.
|
||||
* @param address the address of the scan participant (either master for broadcast master data or slave for read slave data).
|
||||
* @param address the address of the scan participant
|
||||
* (either master for broadcast master data or slave for read slave data).
|
||||
* @param data the scan @a SymbolString for which to load the configuration file.
|
||||
* @param relativeFile the string in which the name of the configuration file is stored on success.
|
||||
* @param verbose whether to verbosely log problems.
|
||||
* @return the result code.
|
||||
*/
|
||||
result_t loadScanConfigFile(MessageMap* messages, unsigned char address, SymbolString& data, string& relativeFile, bool verbose = false);
|
||||
result_t loadScanConfigFile(MessageMap* messages, unsigned char address, SymbolString& data, string& relativeFile,
|
||||
bool verbose = false);
|
||||
|
||||
} // namespace ebusd
|
||||
|
||||
|
||||
+53
-26
@@ -364,9 +364,11 @@ string MainLoop::decodeMessage(const string& data, const bool isHttp, bool& conn
|
||||
const char* str = args[0].c_str();
|
||||
if (args.size() == 2) {
|
||||
// check for "CMD -h"
|
||||
if (strcasecmp(args[1].c_str(), "-h") == 0 || strcasecmp(args[1].c_str(), "-?") == 0 || strcasecmp(args[1].c_str(), "--help") == 0) {
|
||||
if (strcasecmp(args[1].c_str(), "-h") == 0 || strcasecmp(args[1].c_str(), "-?") == 0 ||
|
||||
strcasecmp(args[1].c_str(), "--help") == 0) {
|
||||
args.clear(); // empty args is used as command help indicator
|
||||
} else if (strcasecmp(args[0].c_str(), "H") == 0 || strcasecmp(args[0].c_str(), "HELP") == 0) { // check for "HELP CMD"
|
||||
} else if (strcasecmp(args[0].c_str(), "H") == 0 || strcasecmp(args[0].c_str(), "HELP") == 0) {
|
||||
// check for "HELP CMD"
|
||||
str = args[1].c_str();
|
||||
args.clear(); // empty args is used as command help indicator
|
||||
}
|
||||
@@ -534,7 +536,8 @@ string MainLoop::executeRead(vector<string> &args) {
|
||||
}
|
||||
argPos++;
|
||||
}
|
||||
if (hex && (dstAddress != SYN || !circuit.empty() || verbosity != 0 || numeric || pollPriority > 0 || args.size() < argPos + 1)) {
|
||||
if (hex && (dstAddress != SYN || !circuit.empty() || verbosity != 0 || numeric || pollPriority > 0
|
||||
|| args.size() < argPos + 1)) {
|
||||
argPos = 0; // print usage
|
||||
}
|
||||
|
||||
@@ -583,17 +586,21 @@ string MainLoop::executeRead(vector<string> &args) {
|
||||
ret = message->decodeLastData(result);
|
||||
}
|
||||
if (ret >= RESULT_OK) {
|
||||
logInfo(lf_main, "read hex %s %s cache update: %s", message->getCircuit().c_str(), message->getName().c_str(), result.str().c_str());
|
||||
logInfo(lf_main, "read hex %s %s cache update: %s", message->getCircuit().c_str(), message->getName().c_str(),
|
||||
result.str().c_str());
|
||||
} else {
|
||||
logError(lf_main, "read hex %s %s cache update: %s", message->getCircuit().c_str(), message->getName().c_str(), getResultCode(ret));
|
||||
logError(lf_main, "read hex %s %s cache update: %s", message->getCircuit().c_str(), message->getName().c_str(),
|
||||
getResultCode(ret));
|
||||
}
|
||||
return slave.getDataStr(true, false);
|
||||
}
|
||||
logError(lf_main, "read hex %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(), getResultCode(ret));
|
||||
logError(lf_main, "read hex %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(),
|
||||
getResultCode(ret));
|
||||
return getResultCode(ret);
|
||||
}
|
||||
if (argPos == 0 || args.size() < argPos + 1 || args.size() > argPos + 2) {
|
||||
return "usage: read [-f] [-m SECONDS] [-c CIRCUIT] [-d ZZ] [-p PRIO] [-v|-V] [-n] [-i VALUE[;VALUE]*] NAME [FIELD[.N]]\n"
|
||||
return "usage: read [-f] [-m SECONDS] [-c CIRCUIT] [-d ZZ] [-p PRIO] [-v|-V] [-n] [-i VALUE[;VALUE]*] NAME "
|
||||
"[FIELD[.N]]\n"
|
||||
" or: read [-f] [-m SECONDS] [-c CIRCUIT] -h ZZPBSBNNDx\n"
|
||||
" Read value(s) or hex message.\n"
|
||||
" -f force reading from the bus (same as '-m 0')\n"
|
||||
@@ -643,18 +650,23 @@ string MainLoop::executeRead(vector<string> &args) {
|
||||
if (!hasCache || (message != NULL && message->getLastUpdateTime() > cacheMessage->getLastUpdateTime())) {
|
||||
cacheMessage = message; // message is newer/better
|
||||
}
|
||||
if (cacheMessage != NULL && (cacheMessage->getLastUpdateTime() + maxAge > now || (cacheMessage->isPassive() && cacheMessage->getLastUpdateTime() != 0))) {
|
||||
if (cacheMessage != NULL
|
||||
&& (cacheMessage->getLastUpdateTime() + maxAge > now
|
||||
|| (cacheMessage->isPassive() && cacheMessage->getLastUpdateTime() != 0))) {
|
||||
if (verbosity & OF_NAMES) {
|
||||
result << cacheMessage->getCircuit() << " " << cacheMessage->getName() << " ";
|
||||
}
|
||||
result_t ret = cacheMessage->decodeLastData(result, verbosity|(numeric?OF_NUMERIC:0), false, fieldIndex == -2 ? NULL : fieldName.c_str(), fieldIndex);
|
||||
result_t ret = cacheMessage->decodeLastData(result, verbosity|(numeric?OF_NUMERIC:0), false,
|
||||
fieldIndex == -2 ? NULL : fieldName.c_str(), fieldIndex);
|
||||
if (ret != RESULT_OK) {
|
||||
if (ret < RESULT_OK) {
|
||||
logError(lf_main, "read %s %s cached: %s", cacheMessage->getCircuit().c_str(), cacheMessage->getName().c_str(), getResultCode(ret));
|
||||
logError(lf_main, "read %s %s cached: %s", cacheMessage->getCircuit().c_str(),
|
||||
cacheMessage->getName().c_str(), getResultCode(ret));
|
||||
}
|
||||
return getResultCode(ret);
|
||||
}
|
||||
logInfo(lf_main, "read %s %s cached: %s", cacheMessage->getCircuit().c_str(), cacheMessage->getName().c_str(), result.str().c_str());
|
||||
logInfo(lf_main, "read %s %s cached: %s", cacheMessage->getCircuit().c_str(), cacheMessage->getName().c_str(),
|
||||
result.str().c_str());
|
||||
return result.str();
|
||||
}
|
||||
|
||||
@@ -677,9 +689,11 @@ string MainLoop::executeRead(vector<string> &args) {
|
||||
if (verbosity & OF_NAMES) {
|
||||
result << message->getCircuit() << " " << message->getName() << " ";
|
||||
}
|
||||
ret = message->decodeLastData(pt_slaveData, result, verbosity|(numeric?OF_NUMERIC:0), false, fieldIndex == -2 ? NULL : fieldName.c_str(), fieldIndex);
|
||||
ret = message->decodeLastData(pt_slaveData, result, verbosity|(numeric?OF_NUMERIC:0), false,
|
||||
fieldIndex == -2 ? NULL : fieldName.c_str(), fieldIndex);
|
||||
if (ret < RESULT_OK) {
|
||||
logError(lf_main, "read %s %s: decode %s", message->getCircuit().c_str(), message->getName().c_str(), getResultCode(ret));
|
||||
logError(lf_main, "read %s %s: decode %s", message->getCircuit().c_str(), message->getName().c_str(),
|
||||
getResultCode(ret));
|
||||
result.str("");
|
||||
result << getResultCode(ret) << " in decode";
|
||||
return result.str();
|
||||
@@ -762,9 +776,11 @@ string MainLoop::executeWrite(vector<string> &args) {
|
||||
ret = message->decodeLastData(result);
|
||||
}
|
||||
if (ret >= RESULT_OK) {
|
||||
logInfo(lf_main, "write hex %s %s cache update: %s", message->getCircuit().c_str(), message->getName().c_str(), result.str().c_str());
|
||||
logInfo(lf_main, "write hex %s %s cache update: %s", message->getCircuit().c_str(),
|
||||
message->getName().c_str(), result.str().c_str());
|
||||
} else {
|
||||
logError(lf_main, "write hex %s %s cache update: %s", message->getCircuit().c_str(), message->getName().c_str(), getResultCode(ret));
|
||||
logError(lf_main, "write hex %s %s cache update: %s", message->getCircuit().c_str(),
|
||||
message->getName().c_str(), getResultCode(ret));
|
||||
}
|
||||
if (master[1] == BROADCAST) {
|
||||
return "done broadcast";
|
||||
@@ -774,7 +790,8 @@ string MainLoop::executeWrite(vector<string> &args) {
|
||||
}
|
||||
return slave.getDataStr(true, false);
|
||||
}
|
||||
logError(lf_main, "write hex %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(), getResultCode(ret));
|
||||
logError(lf_main, "write hex %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(),
|
||||
getResultCode(ret));
|
||||
return getResultCode(ret);
|
||||
}
|
||||
|
||||
@@ -800,15 +817,18 @@ string MainLoop::executeWrite(vector<string> &args) {
|
||||
if (message->getDstAddress() == SYN && dstAddress == SYN) {
|
||||
return getResultCode(RESULT_ERR_INVALID_ADDR);
|
||||
}
|
||||
result_t ret = m_busHandler->readFromBus(message, args.size() == argPos + 1 ? "" : args[argPos + 1], dstAddress); // allow missing values
|
||||
// allow missing values
|
||||
result_t ret = m_busHandler->readFromBus(message, args.size() == argPos + 1 ? "" : args[argPos + 1], dstAddress);
|
||||
if (ret != RESULT_OK) {
|
||||
logError(lf_main, "write %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(), getResultCode(ret));
|
||||
logError(lf_main, "write %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(),
|
||||
getResultCode(ret));
|
||||
return getResultCode(ret);
|
||||
}
|
||||
dstAddress = message->getLastMasterData()[1];
|
||||
ostringstream result;
|
||||
if (dstAddress == BROADCAST || isMaster(dstAddress)) {
|
||||
logNotice(lf_main, "write %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(), getResultCode(ret));
|
||||
logNotice(lf_main, "write %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(),
|
||||
getResultCode(ret));
|
||||
if (dstAddress == BROADCAST) {
|
||||
return "done broadcast";
|
||||
}
|
||||
@@ -817,16 +837,19 @@ string MainLoop::executeWrite(vector<string> &args) {
|
||||
|
||||
ret = message->decodeLastData(pt_slaveData, result); // decode data
|
||||
if (ret >= RESULT_OK && result.str().empty()) {
|
||||
logNotice(lf_main, "write %s %s: decode %s", message->getCircuit().c_str(), message->getName().c_str(), getResultCode(ret));
|
||||
logNotice(lf_main, "write %s %s: decode %s", message->getCircuit().c_str(), message->getName().c_str(),
|
||||
getResultCode(ret));
|
||||
return getResultCode(RESULT_OK);
|
||||
}
|
||||
if (ret != RESULT_OK) {
|
||||
logError(lf_main, "write %s %s: decode %s", message->getCircuit().c_str(), message->getName().c_str(), getResultCode(ret));
|
||||
logError(lf_main, "write %s %s: decode %s", message->getCircuit().c_str(), message->getName().c_str(),
|
||||
getResultCode(ret));
|
||||
result.str("");
|
||||
result << getResultCode(ret) << " in decode";
|
||||
return result.str();
|
||||
}
|
||||
logNotice(lf_main, "write %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(), result.str().c_str());
|
||||
logNotice(lf_main, "write %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(),
|
||||
result.str().c_str());
|
||||
return result.str();
|
||||
}
|
||||
|
||||
@@ -873,7 +896,8 @@ string MainLoop::executeHex(vector<string> &args) {
|
||||
|
||||
string MainLoop::executeFind(vector<string> &args) {
|
||||
size_t argPos = 1;
|
||||
bool configFormat = false, exact = false, withRead = true, withWrite = false, withPassive = true, first = true, onlyWithData = false, hexFormat = false;
|
||||
bool configFormat = false, exact = false, withRead = true, withWrite = false, withPassive = true, first = true,
|
||||
onlyWithData = false, hexFormat = false;
|
||||
OutputFormat verbosity = 0;
|
||||
vector<size_t> columns;
|
||||
string circuit;
|
||||
@@ -1171,7 +1195,8 @@ 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 && dstAddress != BROADCAST
|
||||
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
|
||||
@@ -1291,12 +1316,14 @@ string MainLoop::executeQuit(vector<string> &args, bool& connected) {
|
||||
|
||||
string MainLoop::executeHelp() {
|
||||
return "usage:\n"
|
||||
" read|r Read value(s): read [-f] [-m SECONDS] [-c CIRCUIT] [-d ZZ] [-p PRIO] [-v|-V] [-n] [-i VALUE[;VALUE]*] NAME [FIELD[.N]]\n"
|
||||
" read|r Read value(s): read [-f] [-m SECONDS] [-c CIRCUIT] [-d ZZ] [-p PRIO] [-v|-V] [-n]"
|
||||
" [-i VALUE[;VALUE]*] NAME [FIELD[.N]]\n"
|
||||
" Read hex message: read [-f] [-m SECONDS] [-c CIRCUIT] -h ZZPBSBNNDx\n"
|
||||
" write|w Write value(s): write [-d ZZ] -c CIRCUIT NAME [VALUE[;VALUE]*]\n"
|
||||
" Write hex message: write [-c CIRCUIT] -h ZZPBSBNNDx\n"
|
||||
" hex Send hex data: hex ZZPBSBNNDx\n"
|
||||
" find|f Find message(s): find [-v|-V] [-r] [-w] [-p] [-d] [-h] [-i ID] [-f] [-F COL[,COL]*] [-e] [-c CIRCUIT] [NAME]\n"
|
||||
" find|f Find message(s): find [-v|-V] [-r] [-w] [-p] [-d] [-h] [-i ID] [-f] [-F COL[,COL]*] [-e]"
|
||||
" [-c CIRCUIT] [NAME]\n"
|
||||
" listen|l Listen for updates: listen [stop]\n"
|
||||
" state|s Report bus state\n"
|
||||
" info|i Report information about the daemon, the configuration, and seen devices.\n"
|
||||
|
||||
@@ -230,7 +230,8 @@ class MainLoop : public Thread, DeviceListener {
|
||||
/** 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). */
|
||||
/** 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. */
|
||||
|
||||
@@ -339,7 +339,8 @@ void MqttHandler::notifyTopic(string topic, string data) {
|
||||
if (!message->isPassive()) {
|
||||
result_t result = m_busHandler->readFromBus(message, data);
|
||||
if (result != RESULT_OK) {
|
||||
logOtherError("mqtt", "%s %s %s: %s", isWrite?"write":"read", circuit.c_str(), name.c_str(), getResultCode(result));
|
||||
logOtherError("mqtt", "%s %s %s: %s", isWrite?"write":"read", circuit.c_str(), name.c_str(),
|
||||
getResultCode(result));
|
||||
return;
|
||||
}
|
||||
logOtherNotice("mqtt", "%s %s %s: %s", isWrite?"write":"read", circuit.c_str(), name.c_str(), data.c_str());
|
||||
@@ -436,7 +437,8 @@ string MqttHandler::getTopic(Message* message, signed char fieldIndex) {
|
||||
void MqttHandler::publishMessage(Message* message, ostringstream& updates) {
|
||||
result_t result = message->decodeLastData(updates);
|
||||
if (result != RESULT_OK) {
|
||||
logOtherError("mqtt", "decode %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(), getResultCode(result));
|
||||
logOtherError("mqtt", "decode %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(),
|
||||
getResultCode(result));
|
||||
return;
|
||||
}
|
||||
if (m_publishByField) {
|
||||
@@ -455,7 +457,8 @@ void MqttHandler::publishMessage(Message* message, ostringstream& updates) {
|
||||
|
||||
void MqttHandler::publishTopic(string topic, string data, bool retain) {
|
||||
logOtherDebug("mqtt", "publish %s %s", topic.c_str(), data.c_str());
|
||||
mosquitto_publish(m_mosquitto, NULL, topic.c_str(), (uint32_t)data.size(), reinterpret_cast<const uint8_t*>(data.c_str()), 0, retain);
|
||||
mosquitto_publish(m_mosquitto, NULL, topic.c_str(), (uint32_t)data.size(),
|
||||
reinterpret_cast<const uint8_t*>(data.c_str()), 0, retain);
|
||||
}
|
||||
|
||||
} // namespace ebusd
|
||||
|
||||
@@ -86,7 +86,8 @@ void Connection::run() {
|
||||
if (ret != 0) {
|
||||
#ifdef HAVE_PPOLL
|
||||
// new data from notify
|
||||
if (ret < 0 || (fds[0].revents & (POLLIN | POLLERR | POLLHUP | POLLRDHUP)) || (fds[1].revents & (POLLERR | POLLHUP))) {
|
||||
if (ret < 0 || (fds[0].revents & (POLLIN | POLLERR | POLLHUP | POLLRDHUP))
|
||||
|| (fds[1].revents & (POLLERR | POLLHUP))) {
|
||||
break;
|
||||
}
|
||||
// new data from socket
|
||||
@@ -282,7 +283,8 @@ void Network::run() {
|
||||
}
|
||||
connection->start("connection");
|
||||
m_connections.push_back(connection);
|
||||
logInfo(lf_network, "[%05d] %s connection opened %s", connection->getID(), isHttp ? "HTTP" : "client", socket->getIP().c_str());
|
||||
logInfo(lf_network, "[%05d] %s connection opened %s", connection->getID(), isHttp ? "HTTP" : "client",
|
||||
socket->getIP().c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,7 +108,8 @@ int main() {
|
||||
fields = NULL;
|
||||
}
|
||||
vector<string>::iterator it = entries.begin();
|
||||
result = DataField::create(it, entries.end(), templates, fields, isSet, false, (mstr[1] == BROADCAST || isMaster(mstr[1])));
|
||||
result = DataField::create(it, entries.end(), templates, fields, isSet, false,
|
||||
(mstr[1] == BROADCAST || isMaster(mstr[1])));
|
||||
if (result != RESULT_OK) {
|
||||
cout << "\"" << check[0] << "\": create error: " << getResultCode(result) << endl;
|
||||
error = true;
|
||||
@@ -132,13 +133,15 @@ int main() {
|
||||
SymbolString writeMstr(false);
|
||||
result = writeMstr.parseHex(mstr.getDataStr(true, false).substr(0, 10));
|
||||
if (result != RESULT_OK) {
|
||||
cout << " parse \"" << mstr.getDataStr(true, false).substr(0, 10) << "\" error: " << getResultCode(result) << endl;
|
||||
cout << " parse \"" << mstr.getDataStr(true, false).substr(0, 10) << "\" error: " << getResultCode(result)
|
||||
<< endl;
|
||||
error = true;
|
||||
}
|
||||
SymbolString writeSstr(false);
|
||||
result = writeSstr.parseHex(sstr.getDataStr(true, false).substr(0, 2));
|
||||
if (result != RESULT_OK) {
|
||||
cout << " parse \"" << sstr.getDataStr(true, false).substr(0, 2) << "\" error: " << getResultCode(result) << endl;
|
||||
cout << " parse \"" << sstr.getDataStr(true, false).substr(0, 2) << "\" error: " << getResultCode(result)
|
||||
<< endl;
|
||||
error = true;
|
||||
}
|
||||
result = fields->read(pt_masterData, mstr, 0, output, 0, -1, false);
|
||||
@@ -183,7 +186,8 @@ int main() {
|
||||
error = true;
|
||||
} else {
|
||||
bool match = mstr == writeMstr && sstr == writeSstr;
|
||||
verify(failedWriteMatch, "write", expectStr, match, mstr.getDataStr(true, false) + " " + sstr.getDataStr(true, false), writeMstr.getDataStr(true, false) + " " + writeSstr.getDataStr(true, false));
|
||||
verify(failedWriteMatch, "write", expectStr, match, mstr.getDataStr(true, false) + " "
|
||||
+ sstr.getDataStr(true, false), writeMstr.getDataStr(true, false) + " " + writeSstr.getDataStr(true, false));
|
||||
}
|
||||
delete fields;
|
||||
fields = NULL;
|
||||
|
||||
+18
-10
@@ -206,7 +206,8 @@ result_t DataField::create(vector<string>::iterator& it,
|
||||
}
|
||||
transform(typeName.begin(), typeName.end(), typeName.begin(), ::toupper);
|
||||
SingleDataField* add = NULL;
|
||||
result = SingleDataField::create(typeName, length, firstType ? name : "", firstType ? comment : "", firstType ? unit : "", partType, divisor, values, constantValue, verifyValue, add);
|
||||
result = SingleDataField::create(typeName, length, firstType ? name : "", firstType ? comment : "",
|
||||
firstType ? unit : "", partType, divisor, values, constantValue, verifyValue, add);
|
||||
if (add != NULL) {
|
||||
fields.push_back(add);
|
||||
} else {
|
||||
@@ -226,7 +227,8 @@ result_t DataField::create(vector<string>::iterator& it,
|
||||
} else {
|
||||
fieldName = (firstType && lastType) ? name : "";
|
||||
}
|
||||
result = templ->derive(fieldName, firstType ? comment : "", firstType ? unit : "", partType, divisor, values, fields);
|
||||
result = templ->derive(fieldName, firstType ? comment : "", firstType ? unit : "", partType, divisor, values,
|
||||
fields);
|
||||
if (result != RESULT_OK) {
|
||||
it = typePos; // back to type
|
||||
}
|
||||
@@ -394,7 +396,8 @@ result_t SingleDataField::read(const PartType partType,
|
||||
output << ",";
|
||||
}
|
||||
if (outputIndex >= 0 || m_name.empty() || !(outputFormat & OF_NAMES)) {
|
||||
output << "\n \"" << static_cast<signed int>(outputIndex < 0 ? 0 : outputIndex) << "\": {\"name\": \"" << m_name << "\"" << ", \"value\": ";
|
||||
output << "\n \"" << static_cast<signed int>(outputIndex < 0 ? 0 : outputIndex) << "\": {\"name\": \""
|
||||
<< m_name << "\"" << ", \"value\": ";
|
||||
} else {
|
||||
output << "\n \"" << m_name << "\": {\"value\": ";
|
||||
}
|
||||
@@ -498,7 +501,8 @@ result_t SingleDataField::derive(string name, string comment,
|
||||
if (values.empty()) {
|
||||
fields.push_back(new SingleDataField(name, comment, unit, dataType, partType, m_length));
|
||||
} else if (numeric) {
|
||||
fields.push_back(new ValueListDataField(name, comment, unit, reinterpret_cast<NumberDataType*>(dataType), partType, m_length, values));
|
||||
fields.push_back(new ValueListDataField(name, comment, unit, reinterpret_cast<NumberDataType*>(dataType),
|
||||
partType, m_length, values));
|
||||
} else {
|
||||
return RESULT_ERR_INVALID_ARG;
|
||||
}
|
||||
@@ -562,7 +566,8 @@ result_t ValueListDataField::derive(string name, string comment,
|
||||
} else {
|
||||
values = m_values;
|
||||
}
|
||||
fields.push_back(new ValueListDataField(name, comment, unit, reinterpret_cast<NumberDataType*>(m_dataType), partType, m_length, values));
|
||||
fields.push_back(new ValueListDataField(name, comment, unit, reinterpret_cast<NumberDataType*>(m_dataType),
|
||||
partType, m_length, values));
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
@@ -624,7 +629,8 @@ result_t ValueListDataField::writeSymbols(istringstream& input,
|
||||
SymbolString& output, const bool isMaster, unsigned char* usedLength) {
|
||||
NumberDataType* numType = reinterpret_cast<NumberDataType*>(m_dataType);
|
||||
if (isIgnored()) {
|
||||
return numType->writeRawValue(numType->getReplacement(), offset, m_length, output, usedLength); // replacement value
|
||||
// replacement value
|
||||
return numType->writeRawValue(numType->getReplacement(), offset, m_length, output, usedLength);
|
||||
}
|
||||
const char* str = input.str().c_str();
|
||||
|
||||
@@ -634,7 +640,8 @@ result_t ValueListDataField::writeSymbols(istringstream& input,
|
||||
}
|
||||
}
|
||||
if (strcasecmp(str, NULL_VALUE) == 0) {
|
||||
return numType->writeRawValue(numType->getReplacement(), offset, m_length, output, usedLength); // replacement value
|
||||
// replacement value
|
||||
return numType->writeRawValue(numType->getReplacement(), offset, m_length, output, usedLength);
|
||||
}
|
||||
char* strEnd = NULL; // fall back to raw value in input
|
||||
unsigned int value;
|
||||
@@ -919,7 +926,8 @@ result_t DataFieldSet::read(const PartType partType,
|
||||
if (!previousFullByteOffset && !field->hasFullByteOffset(false)) {
|
||||
offset--;
|
||||
}
|
||||
result_t result = field->read(partType, data, offset, output, outputFormat, outputIndex, leadingSeparator, fieldName, fieldIndex);
|
||||
result_t result = field->read(partType, data, offset, output, outputFormat, outputIndex, leadingSeparator,
|
||||
fieldName, fieldIndex);
|
||||
if (result < RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
@@ -1033,8 +1041,8 @@ result_t DataFieldTemplates::add(DataField* field, string name, bool replace) {
|
||||
}
|
||||
|
||||
result_t DataFieldTemplates::addFromFile(vector<string>::iterator& begin, const vector<string>::iterator end,
|
||||
vector< vector<string> >* defaults, const string& defaultDest, const string& defaultCircuit, const string& defaultSuffix,
|
||||
const string& filename, unsigned int lineNo) {
|
||||
vector< vector<string> >* defaults, const string& defaultDest, const string& defaultCircuit,
|
||||
const string& defaultSuffix, const string& filename, unsigned int lineNo) {
|
||||
vector<string>::iterator restart = begin;
|
||||
DataField* field = NULL;
|
||||
string name;
|
||||
|
||||
+14
-4
@@ -550,14 +550,24 @@ class DataFieldSet : public DataField {
|
||||
* @param index the index of the @a SingleDataField to return.
|
||||
* @return the @a SingleDataField at the specified index, or NULL.
|
||||
*/
|
||||
SingleDataField* operator[](const size_t index) { if (index >= m_fields.size()) { return NULL; } return m_fields[index]; }
|
||||
SingleDataField* operator[](const size_t index) {
|
||||
if (index >= m_fields.size()) {
|
||||
return NULL;
|
||||
}
|
||||
return m_fields[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the @a SingleDataField at the specified index.
|
||||
* @param index the index of the @a SingleDataField to return.
|
||||
* @return the @a SingleDataField at the specified index, or NULL.
|
||||
*/
|
||||
const SingleDataField* operator[](const size_t index) const { if (index >= m_fields.size()) { return NULL; } return m_fields[index]; }
|
||||
const SingleDataField* operator[](const size_t index) const {
|
||||
if (index >= m_fields.size()) {
|
||||
return NULL;
|
||||
}
|
||||
return m_fields[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of @a SingleDataFields instances in this set.
|
||||
@@ -640,8 +650,8 @@ class DataFieldTemplates : public FileReader {
|
||||
|
||||
// @copydoc
|
||||
virtual result_t addFromFile(vector<string>::iterator& begin, const vector<string>::iterator end,
|
||||
vector< vector<string> >* defaults, const string& defaultDest, const string& defaultCircuit, const string& defaultSuffix,
|
||||
const string& filename, unsigned int lineNo);
|
||||
vector< vector<string> >* defaults, const string& defaultDest, const string& defaultCircuit,
|
||||
const string& defaultSuffix, const string& filename, unsigned int lineNo);
|
||||
|
||||
/**
|
||||
* Gets the template @a DataField instance with the specified name.
|
||||
|
||||
+87
-42
@@ -40,7 +40,8 @@ using std::setfill;
|
||||
using std::setprecision;
|
||||
using std::setw;
|
||||
|
||||
unsigned int parseInt(const char* str, int base, const unsigned int minValue, const unsigned int maxValue, result_t& result, unsigned int* length) {
|
||||
unsigned int parseInt(const char* str, int base, const unsigned int minValue, const unsigned int maxValue,
|
||||
result_t& result, unsigned int* length) {
|
||||
char* strEnd = NULL;
|
||||
|
||||
unsigned long ret = strtoul(str, &strEnd, base);
|
||||
@@ -61,7 +62,8 @@ unsigned int parseInt(const char* str, int base, const unsigned int minValue, co
|
||||
return (unsigned int)ret;
|
||||
}
|
||||
|
||||
int parseSignedInt(const char* str, int base, const int minValue, const int maxValue, result_t& result, unsigned int* length) {
|
||||
int parseSignedInt(const char* str, int base, const int minValue, const int maxValue, result_t& result,
|
||||
unsigned int* length) {
|
||||
char* strEnd = NULL;
|
||||
|
||||
long ret = strtol(str, &strEnd, base);
|
||||
@@ -82,11 +84,14 @@ int parseSignedInt(const char* str, int base, const int minValue, const int maxV
|
||||
return static_cast<int>(ret);
|
||||
}
|
||||
|
||||
void printErrorPos(ostream& out, vector<string>::iterator begin, const vector<string>::iterator end, vector<string>::iterator pos, string filename, size_t lineNo, result_t result) {
|
||||
void printErrorPos(ostream& out, vector<string>::iterator begin, const vector<string>::iterator end,
|
||||
vector<string>::iterator pos, string filename, size_t lineNo, result_t result) {
|
||||
if (pos > begin) {
|
||||
pos--;
|
||||
}
|
||||
out << "Error reading \"" << filename << "\" line " << setw(0) << dec << static_cast<unsigned>(lineNo) << " field " << static_cast<unsigned>(1+pos.base()-begin.base()) << " value \"" << *pos << "\": " << getResultCode(result) << endl;
|
||||
out << "Error reading \"" << filename << "\" line " << setw(0) << dec << static_cast<unsigned>(lineNo)
|
||||
<< " field " << static_cast<unsigned>(1+pos.base()-begin.base()) << " value \"" << *pos << "\": "
|
||||
<< getResultCode(result) << endl;
|
||||
out << "Erroneous item is here:" << endl;
|
||||
bool first = true;
|
||||
int cnt = 0;
|
||||
@@ -489,7 +494,8 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
|
||||
if (hasFlag(BCD)) {
|
||||
output[baseOffset + offset - incr] = (unsigned char)((6+daysSinceSunday) % 7); // Sun=0x06
|
||||
} else {
|
||||
output[baseOffset + offset - incr] = (unsigned char)(daysSinceSunday == 0 ? 7 : daysSinceSunday); // Sun=0x07
|
||||
// Sun=0x07
|
||||
output[baseOffset + offset - incr] = (unsigned char)(daysSinceSunday == 0 ? 7 : daysSinceSunday);
|
||||
}
|
||||
}
|
||||
if (value >= 2000) {
|
||||
@@ -969,26 +975,46 @@ bool DataTypeList::s_contrib_initialized = libebus_contrib_register();
|
||||
|
||||
DataTypeList::DataTypeList() {
|
||||
add(new StringDataType("STR", MAX_LEN*8, ADJ, ' ')); // >= 1 byte character string filled up with space
|
||||
add(new NumberDataType("PIN", 16, FIX|BCD|REV, 0xffff, 0, 0x9999, 1)); // unsigned decimal in BCD, 0000 - 9999 (fixed length)
|
||||
// unsigned decimal in BCD, 0000 - 9999 (fixed length)
|
||||
add(new NumberDataType("PIN", 16, FIX|BCD|REV, 0xffff, 0, 0x9999, 1));
|
||||
add(new NumberDataType("UCH", 8, 0, 0xff, 0, 0xfe, 1)); // unsigned integer, 0 - 254
|
||||
add(new StringDataType("IGN", MAX_LEN*8, IGN|ADJ, 0)); // >= 1 byte ignored data
|
||||
add(new StringDataType("NTS", MAX_LEN*8, ADJ, 0)); // >= 1 byte character string filled up with 0x00 (null terminated string)
|
||||
add(new StringDataType("HEX", MAX_LEN*8, ADJ, 0, true)); // >= 1 byte hex digit string, usually separated by space, e.g. 0a 1b 2c 3d
|
||||
add(new DateTimeDataType("BDA", 32, BCD, 0xff, true, false, 0)); // date with weekday in BCD, 01.01.2000 - 31.12.2099 (0x01,0x01,WW,0x00 - 0x31,0x12,WW,0x99, WW is weekday Mon=0x00 - Sun=0x06, replacement 0xff)
|
||||
add(new DateTimeDataType("BDA", 24, BCD, 0xff, true, false, 0)); // date in BCD, 01.01.2000 - 31.12.2099 (0x01,0x01,0x00 - 0x31,0x12,0x99, replacement 0xff)
|
||||
add(new DateTimeDataType("HDA", 32, 0, 0xff, true, false, 0)); // date with weekday, 01.01.2000 - 31.12.2099 (0x01,0x01,WW,0x00 - 0x1f,0x0c,WW,0x63, WW is weekday Mon=0x01 - Sun=0x07, replacement 0xff)
|
||||
add(new DateTimeDataType("HDA", 24, 0, 0xff, true, false, 0)); // date, 01.01.2000 - 31.12.2099 (0x01,0x01,0x00 - 0x1f,0x0c,0x63, replacement 0xff)
|
||||
add(new DateTimeDataType("DAY", 16, 0, 0xff, true, false, 0)); // date, days since 01.01.1900, 01.01.1900 - 06.06.2079 (0x00,0x00 - 0xff,0xff)
|
||||
add(new DateTimeDataType("BTI", 24, BCD|REV, 0xff, false, true, 0)); // time in BCD, 00:00:00 - 23:59:59 (0x00,0x00,0x00 - 0x59,0x59,0x23)
|
||||
add(new DateTimeDataType("HTI", 24, 0, 0xff, false, true, 0)); // time, 00:00:00 - 23:59:59 (0x00,0x00,0x00 - 0x17,0x3b,0x3b)
|
||||
add(new DateTimeDataType("VTI", 24, REV, 0x63, false, true, 0)); // time, 00:00:00 - 23:59:59 (0x00,0x00,0x00 - 0x3b,0x3b,0x17, replacement 0x63) [Vaillant type]
|
||||
add(new DateTimeDataType("BTM", 16, BCD|REV, 0xff, false, true, 0)); // time as hh:mm in BCD, 00:00 - 23:59 (0x00,0x00 - 0x59,0x23, replacement 0xff)
|
||||
add(new DateTimeDataType("HTM", 16, 0, 0xff, false, true, 0)); // time as hh:mm, 00:00 - 23:59 (0x00,0x00 - 0x17,0x3b)
|
||||
add(new DateTimeDataType("VTM", 16, REV, 0xff, false, true, 0)); // time as hh:mm, 00:00 - 23:59 (0x00,0x00 - 0x3b,0x17, replacement 0xff) [Vaillant type]
|
||||
add(new DateTimeDataType("MIN", 16, SPE, 0xff, false, true, 0)); // time, minutes since last midnight, 00:00 - 24:00 (minutes + hour * 60 as integer)
|
||||
add(new DateTimeDataType("TTM", 8, 0, 0x90, false, true, 10)); // truncated time (only multiple of 10 minutes), 00:00 - 24:00 (minutes div 10 + hour * 6 as integer)
|
||||
add(new DateTimeDataType("TTH", 8, 0, 0, false, true, 30)); // truncated time (only multiple of 30 minutes), 00:00 - 24:00 (minutes div 30 + hour * 2 as integer)
|
||||
add(new DateTimeDataType("TTQ", 8, 0, 0, false, true, 15)); // truncated time (only multiple of 15 minutes), 00:00 - 24:00 (minutes div 15 + hour * 4 as integer)
|
||||
// >= 1 byte character string filled up with 0x00 (null terminated string)
|
||||
add(new StringDataType("NTS", MAX_LEN*8, ADJ, 0));
|
||||
// >= 1 byte hex digit string, usually separated by space, e.g. 0a 1b 2c 3d
|
||||
add(new StringDataType("HEX", MAX_LEN*8, ADJ, 0, true));
|
||||
// date with weekday in BCD, 01.01.2000 - 31.12.2099 (0x01,0x01,WW,0x00 - 0x31,0x12,WW,0x99,
|
||||
// WW is weekday Mon=0x00 - Sun=0x06, replacement 0xff)
|
||||
add(new DateTimeDataType("BDA", 32, BCD, 0xff, true, false, 0));
|
||||
// date in BCD, 01.01.2000 - 31.12.2099 (0x01,0x01,0x00 - 0x31,0x12,0x99, replacement 0xff)
|
||||
add(new DateTimeDataType("BDA", 24, BCD, 0xff, true, false, 0));
|
||||
// date with weekday, 01.01.2000 - 31.12.2099 (0x01,0x01,WW,0x00 - 0x1f,0x0c,WW,0x63,
|
||||
// WW is weekday Mon=0x01 - Sun=0x07, replacement 0xff)
|
||||
add(new DateTimeDataType("HDA", 32, 0, 0xff, true, false, 0));
|
||||
// date, 01.01.2000 - 31.12.2099 (0x01,0x01,0x00 - 0x1f,0x0c,0x63, replacement 0xff)
|
||||
add(new DateTimeDataType("HDA", 24, 0, 0xff, true, false, 0));
|
||||
// date, days since 01.01.1900, 01.01.1900 - 06.06.2079 (0x00,0x00 - 0xff,0xff)
|
||||
add(new DateTimeDataType("DAY", 16, 0, 0xff, true, false, 0));
|
||||
// time in BCD, 00:00:00 - 23:59:59 (0x00,0x00,0x00 - 0x59,0x59,0x23)
|
||||
add(new DateTimeDataType("BTI", 24, BCD|REV, 0xff, false, true, 0));
|
||||
// time, 00:00:00 - 23:59:59 (0x00,0x00,0x00 - 0x17,0x3b,0x3b)
|
||||
add(new DateTimeDataType("HTI", 24, 0, 0xff, false, true, 0));
|
||||
// time, 00:00:00 - 23:59:59 (0x00,0x00,0x00 - 0x3b,0x3b,0x17, replacement 0x63) [Vaillant type]
|
||||
add(new DateTimeDataType("VTI", 24, REV, 0x63, false, true, 0));
|
||||
// time as hh:mm in BCD, 00:00 - 23:59 (0x00,0x00 - 0x59,0x23, replacement 0xff)
|
||||
add(new DateTimeDataType("BTM", 16, BCD|REV, 0xff, false, true, 0));
|
||||
// time as hh:mm, 00:00 - 23:59 (0x00,0x00 - 0x17,0x3b)
|
||||
add(new DateTimeDataType("HTM", 16, 0, 0xff, false, true, 0));
|
||||
// time as hh:mm, 00:00 - 23:59 (0x00,0x00 - 0x3b,0x17, replacement 0xff) [Vaillant type]
|
||||
add(new DateTimeDataType("VTM", 16, REV, 0xff, false, true, 0));
|
||||
// time, minutes since last midnight, 00:00 - 24:00 (minutes + hour * 60 as integer)
|
||||
add(new DateTimeDataType("MIN", 16, SPE, 0xff, false, true, 0));
|
||||
// truncated time (only multiple of 10 minutes), 00:00 - 24:00 (minutes div 10 + hour * 6 as integer)
|
||||
add(new DateTimeDataType("TTM", 8, 0, 0x90, false, true, 10));
|
||||
// truncated time (only multiple of 30 minutes), 00:00 - 24:00 (minutes div 30 + hour * 2 as integer)
|
||||
add(new DateTimeDataType("TTH", 8, 0, 0, false, true, 30));
|
||||
// truncated time (only multiple of 15 minutes), 00:00 - 24:00 (minutes div 15 + hour * 4 as integer)
|
||||
add(new DateTimeDataType("TTQ", 8, 0, 0, false, true, 15));
|
||||
add(new NumberDataType("BDY", 8, DAY, 0x07, 0, 6, 1)); // weekday, "Mon" - "Sun" (0x00 - 0x06) [eBUS type]
|
||||
add(new NumberDataType("HDY", 8, DAY, 0x00, 1, 7, 1)); // weekday, "Mon" - "Sun" (0x01 - 0x07) [Vaillant type]
|
||||
add(new NumberDataType("BCD", 8, BCD, 0xff, 0, 99, 1)); // unsigned decimal in BCD, 0 - 99
|
||||
@@ -1001,25 +1027,44 @@ DataTypeList::DataTypeList() {
|
||||
add(new NumberDataType("HCD", 24, HCD|BCD|REQ, 0, 0, 999999, 1)); // unsigned decimal in HCD, 0 - 999999
|
||||
add(new NumberDataType("SCH", 8, SIG, 0x80, 0x81, 0x7f, 1)); // signed integer, -127 - +127
|
||||
add(new NumberDataType("D1B", 8, SIG, 0x80, 0x81, 0x7f, 1)); // signed integer, -127 - +127
|
||||
add(new NumberDataType("D1C", 8, 0, 0xff, 0x00, 0xc8, 2)); // unsigned number (fraction 1/2), 0 - 100 (0x00 - 0xc8, replacement 0xff)
|
||||
add(new NumberDataType("D2B", 16, SIG, 0x8000, 0x8001, 0x7fff, 256)); // signed number (fraction 1/256), -127.99 - +127.99
|
||||
add(new NumberDataType("D2C", 16, SIG, 0x8000, 0x8001, 0x7fff, 16)); // signed number (fraction 1/16), -2047.9 - +2047.9
|
||||
add(new NumberDataType("FLT", 16, SIG, 0x8000, 0x8001, 0x7fff, 1000)); // signed number (fraction 1/1000), -32.767 - +32.767, little endian
|
||||
add(new NumberDataType("FLR", 16, SIG|REV, 0x8000, 0x8001, 0x7fff, 1000)); // signed number (fraction 1/1000), -32.767 - +32.767, big endian
|
||||
add(new NumberDataType("EXP", 32, SIG|EXP, 0x7f800000, 0x00000000, 0xffffffff, 1)); // signed number (IEEE 754 binary32: 1 bit sign, 8 bits exponent, 23 bits significand), little endian
|
||||
add(new NumberDataType("EXR", 32, SIG|EXP|REV, 0x7f800000, 0x00000000, 0xffffffff, 1)); // signed number (IEEE 754 binary32: 1 bit sign, 8 bits exponent, 23 bits significand), big endian
|
||||
add(new NumberDataType("UIN", 16, 0, 0xffff, 0, 0xfffe, 1)); // unsigned integer, 0 - 65534, little endian
|
||||
add(new NumberDataType("UIR", 16, REV, 0xffff, 0, 0xfffe, 1)); // unsigned integer, 0 - 65534, big endian
|
||||
add(new NumberDataType("SIN", 16, SIG, 0x8000, 0x8001, 0x7fff, 1)); // signed integer, -32767 - +32767, little endian
|
||||
add(new NumberDataType("SIR", 16, SIG|REV, 0x8000, 0x8001, 0x7fff, 1)); // signed integer, -32767 - +32767, big endian
|
||||
add(new NumberDataType("U3N", 24, 0, 0xffffff, 0, 0xfffffe, 1)); // unsigned 3 bytes int, 0 - 16777214, little endian
|
||||
add(new NumberDataType("U3R", 24, REV, 0xffffff, 0, 0xfffffe, 1)); // unsigned 3 bytes int, 0 - 16777214, big endian
|
||||
add(new NumberDataType("S3N", 24, SIG, 0x800000, 0x800001, 0xffffff, 1)); // signed 3 bytes int, -8388607 - +8388607, little endian
|
||||
add(new NumberDataType("S3R", 24, SIG|REV, 0x800000, 0x800001, 0xffffff, 1)); // signed 3 bytes int, -8388607 - +8388607, big endian
|
||||
add(new NumberDataType("ULG", 32, 0, 0xffffffff, 0, 0xfffffffe, 1)); // unsigned integer, 0 - 4294967294, little endian
|
||||
add(new NumberDataType("ULR", 32, REV, 0xffffffff, 0, 0xfffffffe, 1)); // unsigned integer, 0 - 4294967294, big endian
|
||||
add(new NumberDataType("SLG", 32, SIG, 0x80000000, 0x80000001, 0xffffffff, 1)); // signed integer, -2147483647 - +2147483647, little endian
|
||||
add(new NumberDataType("SLR", 32, SIG|REV, 0x80000000, 0x80000001, 0xffffffff, 1)); // signed integer, -2147483647 - +2147483647, big endian
|
||||
// unsigned number (fraction 1/2), 0 - 100 (0x00 - 0xc8, replacement 0xff)
|
||||
add(new NumberDataType("D1C", 8, 0, 0xff, 0x00, 0xc8, 2));
|
||||
// signed number (fraction 1/256), -127.99 - +127.99
|
||||
add(new NumberDataType("D2B", 16, SIG, 0x8000, 0x8001, 0x7fff, 256));
|
||||
// signed number (fraction 1/16), -2047.9 - +2047.9
|
||||
add(new NumberDataType("D2C", 16, SIG, 0x8000, 0x8001, 0x7fff, 16));
|
||||
// signed number (fraction 1/1000), -32.767 - +32.767, little endian
|
||||
add(new NumberDataType("FLT", 16, SIG, 0x8000, 0x8001, 0x7fff, 1000));
|
||||
// signed number (fraction 1/1000), -32.767 - +32.767, big endian
|
||||
add(new NumberDataType("FLR", 16, SIG|REV, 0x8000, 0x8001, 0x7fff, 1000));
|
||||
// signed number (IEEE 754 binary32: 1 bit sign, 8 bits exponent, 23 bits significand), little endian
|
||||
add(new NumberDataType("EXP", 32, SIG|EXP, 0x7f800000, 0x00000000, 0xffffffff, 1));
|
||||
// signed number (IEEE 754 binary32: 1 bit sign, 8 bits exponent, 23 bits significand), big endian
|
||||
add(new NumberDataType("EXR", 32, SIG|EXP|REV, 0x7f800000, 0x00000000, 0xffffffff, 1));
|
||||
// unsigned integer, 0 - 65534, little endian
|
||||
add(new NumberDataType("UIN", 16, 0, 0xffff, 0, 0xfffe, 1));
|
||||
// unsigned integer, 0 - 65534, big endian
|
||||
add(new NumberDataType("UIR", 16, REV, 0xffff, 0, 0xfffe, 1));
|
||||
// signed integer, -32767 - +32767, little endian
|
||||
add(new NumberDataType("SIN", 16, SIG, 0x8000, 0x8001, 0x7fff, 1));
|
||||
// signed integer, -32767 - +32767, big endian
|
||||
add(new NumberDataType("SIR", 16, SIG|REV, 0x8000, 0x8001, 0x7fff, 1));
|
||||
// unsigned 3 bytes int, 0 - 16777214, little endian
|
||||
add(new NumberDataType("U3N", 24, 0, 0xffffff, 0, 0xfffffe, 1));
|
||||
// unsigned 3 bytes int, 0 - 16777214, big endian
|
||||
add(new NumberDataType("U3R", 24, REV, 0xffffff, 0, 0xfffffe, 1));
|
||||
// signed 3 bytes int, -8388607 - +8388607, little endian
|
||||
add(new NumberDataType("S3N", 24, SIG, 0x800000, 0x800001, 0xffffff, 1));
|
||||
// signed 3 bytes int, -8388607 - +8388607, big endian
|
||||
add(new NumberDataType("S3R", 24, SIG|REV, 0x800000, 0x800001, 0xffffff, 1));
|
||||
// unsigned integer, 0 - 4294967294, little endian
|
||||
add(new NumberDataType("ULG", 32, 0, 0xffffffff, 0, 0xfffffffe, 1));
|
||||
// unsigned integer, 0 - 4294967294, big endian
|
||||
add(new NumberDataType("ULR", 32, REV, 0xffffffff, 0, 0xfffffffe, 1));
|
||||
// signed integer, -2147483647 - +2147483647, little endian
|
||||
add(new NumberDataType("SLG", 32, SIG, 0x80000000, 0x80000001, 0xffffffff, 1));
|
||||
// signed integer, -2147483647 - +2147483647, big endian
|
||||
add(new NumberDataType("SLR", 32, SIG|REV, 0x80000000, 0x80000001, 0xffffffff, 1));
|
||||
add(new NumberDataType("BI0", 7, ADJ|REQ, 0, 0, 1)); // bit 0 (up to 7 bits until bit 6)
|
||||
add(new NumberDataType("BI1", 7, ADJ|REQ, 0, 1, 1)); // bit 1 (up to 7 bits until bit 7)
|
||||
add(new NumberDataType("BI2", 6, ADJ|REQ, 0, 2, 1)); // bit 2 (up to 6 bits until bit 7)
|
||||
|
||||
+18
-9
@@ -102,7 +102,8 @@ static const unsigned int SIG = 0x08; //!< signed value
|
||||
static const unsigned int IGN = 0x10; //!< ignore value during read and write
|
||||
static const unsigned int FIX = 0x20; //!< fixed width formatting
|
||||
static const unsigned int REQ = 0x40; //!< value may not be NULL
|
||||
static const unsigned int HCD = 0x80; //!< binary representation is hex converted to decimal and interpreted as 2 digits (also requires #BCD)
|
||||
/** binary representation is hex converted to decimal and interpreted as 2 digits (also requires #BCD). */
|
||||
static const unsigned int HCD = 0x80;
|
||||
static const unsigned int EXP = 0x100; //!< exponential numeric representation
|
||||
static const unsigned int DAY = 0x200; //!< forced value list defaulting to week days
|
||||
static const unsigned int NUM = 0x400; //!< numeric type with base class @a NumberDataType
|
||||
@@ -120,7 +121,8 @@ static const unsigned int CON = 0x1000; //!< marker for a constant value
|
||||
* @param length the optional variable in which to store the number of read characters.
|
||||
* @return the parsed value.
|
||||
*/
|
||||
unsigned int parseInt(const char* str, int base, const unsigned int minValue, const unsigned int maxValue, result_t& result, unsigned int* length = NULL);
|
||||
unsigned int parseInt(const char* str, int base, const unsigned int minValue, const unsigned int maxValue,
|
||||
result_t& result, unsigned int* length = NULL);
|
||||
|
||||
/**
|
||||
* Parse a signed int value.
|
||||
@@ -132,7 +134,8 @@ unsigned int parseInt(const char* str, int base, const unsigned int minValue, co
|
||||
* @param length the optional variable in which to store the number of read characters.
|
||||
* @return the parsed value.
|
||||
*/
|
||||
int parseSignedInt(const char* str, int base, const int minValue, const int maxValue, result_t& result, unsigned int* length = NULL);
|
||||
int parseSignedInt(const char* str, int base, const int minValue, const int maxValue, result_t& result,
|
||||
unsigned int* length = NULL);
|
||||
|
||||
/**
|
||||
* Print the error position of the iterator.
|
||||
@@ -144,7 +147,8 @@ int parseSignedInt(const char* str, int base, const int minValue, const int maxV
|
||||
* @param lineNo the current line number in the file being read.
|
||||
* @param result the result code.
|
||||
*/
|
||||
void printErrorPos(ostream& out, vector<string>::iterator begin, const vector<string>::iterator end, vector<string>::iterator pos, string filename, size_t lineNo, result_t result);
|
||||
void printErrorPos(ostream& out, vector<string>::iterator begin, const vector<string>::iterator end,
|
||||
vector<string>::iterator pos, string filename, size_t lineNo, result_t result);
|
||||
|
||||
|
||||
/**
|
||||
@@ -157,7 +161,8 @@ class DataType {
|
||||
* @param id the type identifier.
|
||||
* @param bitCount the number of bits (maximum length if #ADJ flag is set, must be multiple of 8 with flag #BCD).
|
||||
* @param flags the combination of flags (like #BCD).
|
||||
* @param replacement the replacement value (fill-up value for @a StringDataType, no replacement if equal to @a NumberDataType#minValue).
|
||||
* @param replacement the replacement value (fill-up value for @a StringDataType, no replacement if equal to
|
||||
* @a NumberDataType#minValue).
|
||||
*/
|
||||
DataType(const string id, const unsigned char bitCount, const uint16_t flags, const unsigned int replacement)
|
||||
: m_id(id), m_bitCount(bitCount), m_flags(flags), m_replacement(replacement) {}
|
||||
@@ -200,7 +205,8 @@ class DataType {
|
||||
bool isNumeric() const { return hasFlag(NUM); }
|
||||
|
||||
/**
|
||||
* @return the replacement value (fill-up value for @a StringDataType, no replacement if equal to @a NumberDataType#minValue).
|
||||
* @return the replacement value (fill-up value for @a StringDataType, no replacement if equal to
|
||||
* @a NumberDataType#minValue).
|
||||
*/
|
||||
unsigned int getReplacement() const { return m_replacement; }
|
||||
|
||||
@@ -264,7 +270,8 @@ class DataType {
|
||||
/** the combination of flags (like #BCD). */
|
||||
const uint16_t m_flags;
|
||||
|
||||
/** the replacement value (fill-up value for @a StringDataType, no replacement if equal to @a NumberDataType#minValue). */
|
||||
/** the replacement value (fill-up value for @a StringDataType, no replacement if equal to
|
||||
* @a NumberDataType#minValue). */
|
||||
const unsigned int m_replacement;
|
||||
};
|
||||
|
||||
@@ -397,7 +404,8 @@ class NumberDataType : public DataType {
|
||||
*/
|
||||
NumberDataType(const string id, const unsigned char bitCount, const uint16_t flags, const unsigned int replacement,
|
||||
const unsigned int minValue, const unsigned int maxValue, const int divisor)
|
||||
: DataType(id, bitCount, flags|NUM, replacement), m_minValue(minValue), m_maxValue(maxValue), m_divisor(divisor), m_precision(calcPrecision(divisor)), m_firstBit(0), m_baseType(NULL) {}
|
||||
: DataType(id, bitCount, flags|NUM, replacement), m_minValue(minValue), m_maxValue(maxValue), m_divisor(divisor),
|
||||
m_precision(calcPrecision(divisor)), m_firstBit(0), m_baseType(NULL) {}
|
||||
|
||||
/**
|
||||
* Constructs a new instance for less than 8 bits.
|
||||
@@ -410,7 +418,8 @@ class NumberDataType : public DataType {
|
||||
*/
|
||||
NumberDataType(const string id, const unsigned char bitCount, const uint16_t flags, const unsigned int replacement,
|
||||
const int16_t firstBit, const int divisor)
|
||||
: DataType(id, bitCount, flags|NUM, replacement), m_minValue(0), m_maxValue((1 << bitCount)-1), m_divisor(divisor), m_precision(0), m_firstBit(firstBit), m_baseType(NULL) {}
|
||||
: DataType(id, bitCount, flags|NUM, replacement), m_minValue(0), m_maxValue((1 << bitCount)-1), m_divisor(divisor),
|
||||
m_precision(0), m_firstBit(firstBit), m_baseType(NULL) {}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
|
||||
@@ -87,7 +87,8 @@ class Device {
|
||||
* @return the new @a Device, or NULL on error.
|
||||
* Note: the caller needs to free the created instance.
|
||||
*/
|
||||
static Device* create(const char* name, const bool checkDevice = true, const bool readOnly = false, const bool initialSend = false);
|
||||
static Device* create(const char* name, const bool checkDevice = true, const bool readOnly = false,
|
||||
const bool initialSend = false);
|
||||
|
||||
/**
|
||||
* Get the transfer latency of this device.
|
||||
|
||||
@@ -62,9 +62,11 @@ using std::endl;
|
||||
/** the separator character used between multiple values (in CSV only). */
|
||||
#define VALUE_SEPARATOR ';'
|
||||
|
||||
extern void printErrorPos(ostream& out, vector<string>::iterator begin, const vector<string>::iterator end, vector<string>::iterator pos, string filename, size_t lineNo, result_t result);
|
||||
extern void printErrorPos(ostream& out, vector<string>::iterator begin, const vector<string>::iterator end,
|
||||
vector<string>::iterator pos, string filename, size_t lineNo, result_t result);
|
||||
|
||||
extern unsigned int parseInt(const char* str, int base, const unsigned int minValue, const unsigned int maxValue, result_t& result, unsigned int* length);
|
||||
extern unsigned int parseInt(const char* str, int base, const unsigned int minValue, const unsigned int maxValue,
|
||||
result_t& result, unsigned int* length);
|
||||
|
||||
/**
|
||||
* An abstract class that support reading definitions from a file.
|
||||
@@ -106,7 +108,8 @@ class FileReader {
|
||||
unsigned char checkDest;
|
||||
string checkIdent, useCircuit, useSuffix;
|
||||
unsigned int checkSw, checkHw;
|
||||
if (extractDefaultsFromFilename(filename.substr(lastSep+1), checkDest, checkIdent, useCircuit, useSuffix, checkSw, checkHw)) {
|
||||
if (extractDefaultsFromFilename(filename.substr(lastSep+1), checkDest, checkIdent, useCircuit, useSuffix,
|
||||
checkSw, checkHw)) {
|
||||
defaultDest = filename.substr(lastSep+1, 2);
|
||||
if (!useCircuit.empty()) {
|
||||
defaultCircuit = useCircuit;
|
||||
@@ -202,8 +205,8 @@ class FileReader {
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t addFromFile(vector<string>::iterator& begin, const vector<string>::iterator end,
|
||||
vector< vector<string> >* defaults, const string& defaultDest, const string& defaultCircuit, const string& defaultSuffix,
|
||||
const string& filename, unsigned int lineNo) = 0;
|
||||
vector< vector<string> >* defaults, const string& defaultDest, const string& defaultCircuit,
|
||||
const string& defaultSuffix, const string& filename, unsigned int lineNo) = 0;
|
||||
|
||||
/**
|
||||
* Left and right trim the string.
|
||||
@@ -356,7 +359,8 @@ class FileReader {
|
||||
}
|
||||
if (name.length() > 1) {
|
||||
pos = name.find('.', 1); // check for ".IDENT."
|
||||
if (pos != string::npos && pos >= 1 && pos <= 6) { // up to 5 chars between two "."s, immediately after "ZZ.", or ".."
|
||||
if (pos != string::npos && pos >= 1 && pos <= 6) {
|
||||
// up to 5 chars between two "."s, immediately after "ZZ.", or ".."
|
||||
ident = circuit = name.substr(1, pos-1);
|
||||
name.erase(0, pos);
|
||||
pos = name.find('.', 1); // check for ".CIRCUIT."
|
||||
|
||||
+59
-36
@@ -83,13 +83,10 @@ Message::Message(const string circuit, const string name,
|
||||
const bool isWrite, const bool isPassive,
|
||||
const unsigned char pb, const unsigned char sb,
|
||||
DataField* data, const bool deleteData)
|
||||
: m_circuit(circuit), m_name(name), m_isWrite(isWrite),
|
||||
m_isPassive(isPassive), m_comment(),
|
||||
m_srcAddress(SYN), m_dstAddress(SYN),
|
||||
m_data(data), m_deleteData(true),
|
||||
m_pollPriority(0),
|
||||
m_usedByCondition(false), m_isScanMessage(false), m_condition(NULL),
|
||||
m_lastUpdateTime(0), m_lastChangeTime(0), m_pollCount(0), m_lastPollTime(0) {
|
||||
: m_circuit(circuit), m_name(name), m_isWrite(isWrite), m_isPassive(isPassive), m_comment(), m_srcAddress(SYN),
|
||||
m_dstAddress(SYN), m_data(data), m_deleteData(true), m_pollPriority(0), m_usedByCondition(false),
|
||||
m_isScanMessage(false), m_condition(NULL), m_lastUpdateTime(0), m_lastChangeTime(0), m_pollCount(0),
|
||||
m_lastPollTime(0) {
|
||||
m_id.push_back(pb);
|
||||
m_id.push_back(sb);
|
||||
uint64_t key = 0;
|
||||
@@ -116,7 +113,8 @@ Message::Message(const string circuit, const string name,
|
||||
* empty and @p replaceStar is @p true.
|
||||
* @return the default if available and value is empty, or the value.
|
||||
*/
|
||||
string getDefault(const string value, vector<string>* defaults, size_t pos, bool replaceStar = false, bool required = false) {
|
||||
string getDefault(const string value, vector<string>* defaults, size_t pos, bool replaceStar = false,
|
||||
bool required = false) {
|
||||
if (defaults == NULL || pos >= defaults->size()) {
|
||||
return value;
|
||||
}
|
||||
@@ -406,7 +404,8 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
|
||||
}
|
||||
vector<string>::iterator realEnd = end;
|
||||
vector<string> newTypes;
|
||||
if (defaults != NULL && defaults->size() > defaultPos + 2) { // need at least "[name];[part];type" (optional: "[divisor|values][;[unit][;[comment]]]]")
|
||||
if (defaults != NULL && defaults->size() > defaultPos + 2) {
|
||||
// need at least "[name];[part];type" (optional: "[divisor|values][;[unit][;[comment]]]]")
|
||||
while (defaults->size() > defaultPos + 2 && defaults->at(defaultPos + 2).size() > 0) {
|
||||
for (size_t i = 0; i < 6; i++) {
|
||||
if (defaults->size() > defaultPos) {
|
||||
@@ -430,12 +429,14 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
|
||||
vector<SingleDataField*> fields;
|
||||
data = new DataFieldSet("", "", fields);
|
||||
} else {
|
||||
result = DataField::create(it, realEnd, templates, data, isWrite, false, isBroadcastOrMasterDestination, (unsigned char)maxLength);
|
||||
result = DataField::create(it, realEnd, templates, data, isWrite, false, isBroadcastOrMasterDestination,
|
||||
(unsigned char)maxLength);
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if (id.size() + data->getLength(pt_masterData, (unsigned char)maxLength) > 2 + maxLength || data->getLength(pt_slaveData, (unsigned char)maxLength) > maxLength) {
|
||||
if (id.size() + data->getLength(pt_masterData, (unsigned char)maxLength) > 2 + maxLength
|
||||
|| data->getLength(pt_slaveData, (unsigned char)maxLength) > maxLength) {
|
||||
// max NN exceeded
|
||||
delete data;
|
||||
return RESULT_ERR_INVALID_POS;
|
||||
@@ -452,9 +453,11 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
|
||||
}
|
||||
Message* message;
|
||||
if (chainIds.size() > 1) {
|
||||
message = new ChainedMessage(useCircuit, name, isWrite, comment, srcAddress, dstAddress, id, chainIds, chainLengths, data, index == 0, pollPriority, condition);
|
||||
message = new ChainedMessage(useCircuit, name, isWrite, comment, srcAddress, dstAddress, id, chainIds,
|
||||
chainLengths, data, index == 0, pollPriority, condition);
|
||||
} else {
|
||||
message = new Message(useCircuit, name, isWrite, isPassive, comment, srcAddress, dstAddress, id, data, index == 0, pollPriority, condition);
|
||||
message = new Message(useCircuit, name, isWrite, isPassive, comment, srcAddress, dstAddress, id, data,
|
||||
index == 0, pollPriority, condition);
|
||||
}
|
||||
messages.push_back(message);
|
||||
}
|
||||
@@ -687,7 +690,8 @@ result_t Message::decodeLastData(const PartType partType,
|
||||
} else {
|
||||
offset = 0;
|
||||
}
|
||||
result_t result = m_data->read(partType, partType == pt_masterData ? m_lastMasterData : m_lastSlaveData, offset, output, outputFormat, -1, leadingSeparator, fieldName, fieldIndex);
|
||||
result_t result = m_data->read(partType, partType == pt_masterData ? m_lastMasterData : m_lastSlaveData, offset,
|
||||
output, outputFormat, -1, leadingSeparator, fieldName, fieldIndex);
|
||||
if (result < RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
@@ -700,13 +704,15 @@ result_t Message::decodeLastData(const PartType partType,
|
||||
result_t Message::decodeLastData(ostringstream& output, OutputFormat outputFormat,
|
||||
bool leadingSeparator, const char* fieldName, signed char fieldIndex) {
|
||||
size_t startPos = output.str().length();
|
||||
result_t result = m_data->read(pt_masterData, m_lastMasterData, getIdLength(), output, outputFormat, -1, leadingSeparator, fieldName, fieldIndex);
|
||||
result_t result = m_data->read(pt_masterData, m_lastMasterData, getIdLength(), output, outputFormat, -1,
|
||||
leadingSeparator, fieldName, fieldIndex);
|
||||
if (result < RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
bool empty = result == RESULT_EMPTY;
|
||||
leadingSeparator |= output.str().length() > startPos;
|
||||
result = m_data->read(pt_slaveData, m_lastSlaveData, 0, output, outputFormat, -1, leadingSeparator, fieldName, fieldIndex);
|
||||
result = m_data->read(pt_slaveData, m_lastSlaveData, 0, output, outputFormat, -1, leadingSeparator, fieldName,
|
||||
fieldIndex);
|
||||
if (result < RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
@@ -938,7 +944,8 @@ bool ChainedMessage::checkId(Message& other) {
|
||||
return false;
|
||||
}
|
||||
|
||||
result_t ChainedMessage::prepareMasterPart(SymbolString& master, istringstream& input, char separator, unsigned char index) {
|
||||
result_t ChainedMessage::prepareMasterPart(SymbolString& master, istringstream& input, char separator,
|
||||
unsigned char index) {
|
||||
size_t cnt = getCount();
|
||||
if (index >= cnt) {
|
||||
return RESULT_ERR_NOTFOUND;
|
||||
@@ -1166,7 +1173,8 @@ result_t splitValues(string valueList, vector<unsigned int>& valueRanges) {
|
||||
valueRanges.push_back(0);
|
||||
}
|
||||
bool inclusive = str[1] == '=';
|
||||
unsigned int val = parseInt(str.substr(inclusive?2:1).c_str(), 10, inclusive?0:1, inclusive?UINT_MAX:(UINT_MAX-1), result);
|
||||
unsigned int val = parseInt(str.substr(inclusive?2:1).c_str(), 10, inclusive?0:1,
|
||||
inclusive?UINT_MAX:(UINT_MAX-1), result);
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
@@ -1199,7 +1207,8 @@ result_t splitValues(string valueList, vector<unsigned int>& valueRanges) {
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
result_t Condition::create(const string condName, vector<string>::iterator& it, const vector<string>::iterator end, string defaultDest, string defaultCircuit, SimpleCondition*& returnValue) {
|
||||
result_t Condition::create(const string condName, vector<string>::iterator& it, const vector<string>::iterator end,
|
||||
string defaultDest, string defaultCircuit, SimpleCondition*& returnValue) {
|
||||
// name,circuit,messagename,[comment],[fieldname],[ZZ],values (name already skipped by caller)
|
||||
string circuit = it == end ? "" : *(it++); // circuit
|
||||
string name = it == end ? "" : *(it++); // messagename
|
||||
@@ -1304,12 +1313,14 @@ CombinedCondition* SimpleCondition::combineAnd(Condition* other) {
|
||||
return ret->combineAnd(this)->combineAnd(other);
|
||||
}
|
||||
|
||||
result_t SimpleCondition::resolve(MessageMap* messages, ostringstream& errorMessage, void (*readMessageFunc)(Message* message)) {
|
||||
result_t SimpleCondition::resolve(MessageMap* messages, ostringstream& errorMessage,
|
||||
void (*readMessageFunc)(Message* message)) {
|
||||
if (m_message == NULL) {
|
||||
Message* message;
|
||||
if (m_name.length() == 0) {
|
||||
message = messages->getScanMessage(m_dstAddress);
|
||||
errorMessage << "scan condition " << nouppercase << setw(2) << hex << setfill('0') << static_cast<unsigned>(m_dstAddress);
|
||||
errorMessage << "scan condition " << nouppercase << setw(2) << hex << setfill('0')
|
||||
<< static_cast<unsigned>(m_dstAddress);
|
||||
} else {
|
||||
message = messages->find(m_circuit, m_name, false);
|
||||
if (!message) {
|
||||
@@ -1339,7 +1350,8 @@ result_t SimpleCondition::resolve(MessageMap* messages, ostringstream& errorMess
|
||||
} else {
|
||||
Message* first = getFirstAvailable(*derived, message);
|
||||
if (first == NULL) {
|
||||
errorMessage << ": conditional derived message " << message->getCircuit() << "." << message->getName() << " for " << hex << setw(2) << setfill('0') << static_cast<unsigned>(m_dstAddress) << " not found";
|
||||
errorMessage << ": conditional derived message " << message->getCircuit() << "." << message->getName()
|
||||
<< " for " << hex << setw(2) << setfill('0') << static_cast<unsigned>(m_dstAddress) << " not found";
|
||||
return RESULT_ERR_INVALID_ARG;
|
||||
}
|
||||
message = first;
|
||||
@@ -1420,7 +1432,8 @@ void CombinedCondition::dump(ostream& output, bool matched) {
|
||||
}
|
||||
}
|
||||
|
||||
result_t CombinedCondition::resolve(MessageMap* messages, ostringstream& errorMessage, void (*readMessageFunc)(Message* message)) {
|
||||
result_t CombinedCondition::resolve(MessageMap* messages, ostringstream& errorMessage,
|
||||
void (*readMessageFunc)(Message* message)) {
|
||||
for (vector<Condition*>::iterator it = m_conditions.begin(); it != m_conditions.end(); it++) {
|
||||
Condition* condition = *it;
|
||||
ostringstream dummy;
|
||||
@@ -1443,8 +1456,9 @@ bool CombinedCondition::isTrue() {
|
||||
}
|
||||
|
||||
|
||||
result_t Instruction::create(const string contextPath, const string& defaultDest, const string& defaultCircuit, const string& defaultSuffix,
|
||||
Condition* condition, const string type, vector<string>::iterator& it, const vector<string>::iterator end, Instruction*& returnValue) {
|
||||
result_t Instruction::create(const string contextPath, const string& defaultDest, const string& defaultCircuit,
|
||||
const string& defaultSuffix, Condition* condition, const string type, vector<string>::iterator& it,
|
||||
const vector<string>::iterator end, Instruction*& returnValue) {
|
||||
// type[,argument]* (type already skipped by caller)
|
||||
bool singleton = false;
|
||||
if ((singleton=(type == "load")) || type == "include") {
|
||||
@@ -1494,7 +1508,8 @@ result_t LoadInstruction::execute(MessageMap* messages, ostringstream& log, Cond
|
||||
log << ", ";
|
||||
}
|
||||
if (result != RESULT_OK) {
|
||||
log << "error " << (isSingleton() ? "loading \"" : "including \"") << m_filename << "\" for \"" << getDestination() << "\": " << getResultCode(result);
|
||||
log << "error " << (isSingleton() ? "loading \"" : "including \"") << m_filename << "\" for \""
|
||||
<< getDestination() << "\": " << getResultCode(result);
|
||||
return result;
|
||||
}
|
||||
log << (isSingleton() ? "loaded \"" : "included \"") << m_filename << "\" for \"" << getDestination() << "\"";
|
||||
@@ -1562,14 +1577,17 @@ result_t MessageMap::add(Message* message, bool storeByName) {
|
||||
nameKey = string(isPassive ? "-P" : (isWrite ? "-W" : "-R")) + name; // also store without circuit
|
||||
map<string, vector<Message*> >::iterator nameIt = m_messagesByName.find(nameKey);
|
||||
if (nameIt == m_messagesByName.end()) {
|
||||
m_messagesByName[nameKey].push_back(message); // always store first message without circuit (in order of circuit name)
|
||||
// always store first message without circuit (in order of circuit name)
|
||||
m_messagesByName[nameKey].push_back(message);
|
||||
} else {
|
||||
vector<Message*>* messages = &nameIt->second;
|
||||
Message* first = messages->front();
|
||||
if (circuit < first->getCircuit()) {
|
||||
m_messagesByName[nameKey].at(0) = message; // always store first message without circuit (in order of circuit name)
|
||||
// always store first message without circuit (in order of circuit name)
|
||||
m_messagesByName[nameKey].at(0) = message;
|
||||
} else if (m_addAll || (conditional && first->isConditional())) {
|
||||
m_messagesByName[nameKey].push_back(message); // store further messages only if both are conditional or if storing everything
|
||||
// store further messages only if both are conditional or if storing everything
|
||||
m_messagesByName[nameKey].push_back(message);
|
||||
}
|
||||
}
|
||||
m_messageCount++;
|
||||
@@ -1620,20 +1638,24 @@ result_t MessageMap::addDefaultFromFile(vector< vector<string> >& defaults, vect
|
||||
if (row[1].length() == 0) {
|
||||
row[1] = defaultCircuit+defaultSuffix; // set default circuit and suffix: "circuit[.suffix]"
|
||||
} else if (row[1][0] == '#') {
|
||||
row[1] = defaultCircuit+defaultSuffix+row[1]; // move security suffix behind default circuit and suffix: "circuit[.suffix]#security"
|
||||
} else if (defaultSuffix.length() > 0 && row[1].find_last_of('.') == string::npos) { // circuit suffix not yet present
|
||||
// move security suffix behind default circuit and suffix: "circuit[.suffix]#security"
|
||||
row[1] = defaultCircuit+defaultSuffix+row[1];
|
||||
} else if (defaultSuffix.length() > 0 && row[1].find_last_of('.') == string::npos) {
|
||||
// circuit suffix not yet present
|
||||
size_t pos = row[1].find_first_of('#');
|
||||
if (pos == string::npos) {
|
||||
row[1] += defaultSuffix; // append default suffix: "circuit.suffix"
|
||||
} else {
|
||||
row[1] = row[1].substr(0, pos)+defaultSuffix+row[1].substr(pos); // insert default suffix: "circuit.suffix#security"
|
||||
// insert default suffix: "circuit.suffix#security"
|
||||
row[1] = row[1].substr(0, pos)+defaultSuffix+row[1].substr(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (row.size() > 5 && defaultDest.length() > 0 && row[5].length() == 0) {
|
||||
row[5] = defaultDest; // set default destination
|
||||
}
|
||||
return FileReader::addDefaultFromFile(defaults, row, begin, defaultDest, defaultCircuit, defaultSuffix, filename, lineNo);
|
||||
return FileReader::addDefaultFromFile(defaults, row, begin, defaultDest, defaultCircuit, defaultSuffix, filename,
|
||||
lineNo);
|
||||
}
|
||||
|
||||
result_t MessageMap::readConditions(string& types, const string& filename, Condition*& condition) {
|
||||
@@ -1696,8 +1718,8 @@ result_t MessageMap::readConditions(string& types, const string& filename, Condi
|
||||
}
|
||||
|
||||
result_t MessageMap::addFromFile(vector<string>::iterator& begin, const vector<string>::iterator end,
|
||||
vector< vector<string> >* defaults, const string& defaultDest, const string& defaultCircuit, const string& defaultSuffix,
|
||||
const string& filename, unsigned int lineNo) {
|
||||
vector< vector<string> >* defaults, const string& defaultDest, const string& defaultCircuit,
|
||||
const string& defaultSuffix, const string& filename, unsigned int lineNo) {
|
||||
vector<string>::iterator restart = begin;
|
||||
string types = *restart;
|
||||
Condition* condition = NULL;
|
||||
@@ -1709,7 +1731,8 @@ result_t MessageMap::addFromFile(vector<string>::iterator& begin, const vector<s
|
||||
// instruction
|
||||
types = types.substr(1);
|
||||
Instruction* instruction = NULL;
|
||||
result_t result = Instruction::create(filename, defaultDest, defaultCircuit, defaultSuffix, condition, types, ++begin, end, instruction);
|
||||
result_t result = Instruction::create(filename, defaultDest, defaultCircuit, defaultSuffix, condition, types,
|
||||
++begin, end, instruction);
|
||||
if (instruction == NULL || result != RESULT_OK) {
|
||||
m_lastError = "invalid instruction";
|
||||
return result;
|
||||
|
||||
+57
-30
@@ -229,7 +229,8 @@ class Message {
|
||||
* @param circuit the new circuit name, or empty to use the current circuit name.
|
||||
* @return the derived @a Message instance.
|
||||
*/
|
||||
virtual Message* derive(const unsigned char dstAddress, const unsigned char srcAddress = SYN, const string circuit = "");
|
||||
virtual Message* derive(const unsigned char dstAddress, const unsigned char srcAddress = SYN,
|
||||
const string circuit = "");
|
||||
|
||||
/**
|
||||
* Derive a new @a Message from this message.
|
||||
@@ -647,7 +648,8 @@ class ChainedMessage : public Message {
|
||||
virtual ~ChainedMessage();
|
||||
|
||||
// @copydoc
|
||||
virtual Message* derive(const unsigned char dstAddress, const unsigned char srcAddress = SYN, const string circuit = "");
|
||||
virtual Message* derive(const unsigned char dstAddress, const unsigned char srcAddress = SYN,
|
||||
const string circuit = "");
|
||||
|
||||
// @copydoc
|
||||
virtual unsigned char getIdLength() const { return (unsigned char)(m_ids[0].size() - 2); }
|
||||
@@ -766,7 +768,8 @@ class Condition {
|
||||
* @param returnValue the variable in which to store the created instance.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
static result_t create(const string condName, vector<string>::iterator& it, const vector<string>::iterator end, string defaultDest, string defaultCircuit, SimpleCondition*& returnValue);
|
||||
static result_t create(const string condName, vector<string>::iterator& it, const vector<string>::iterator end,
|
||||
string defaultDest, string defaultCircuit, SimpleCondition*& returnValue);
|
||||
|
||||
/**
|
||||
* Derive a new @a SimpleCondition from this condition.
|
||||
@@ -796,7 +799,8 @@ class Condition {
|
||||
* @param readMessageFunc the function to call for immediate reading of a @a Message from the bus, or NULL.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
virtual result_t resolve(MessageMap* messages, ostringstream& errorMessage, void (*readMessageFunc)(Message* message) = NULL) = 0;
|
||||
virtual result_t resolve(MessageMap* messages, ostringstream& errorMessage,
|
||||
void (*readMessageFunc)(Message* message) = NULL) = 0;
|
||||
|
||||
/**
|
||||
* Check and return whether this condition is fulfilled.
|
||||
@@ -825,13 +829,16 @@ class SimpleCondition : public Condition {
|
||||
* @param refName the reference name for dumping.
|
||||
* @param circuit the circuit name.
|
||||
* @param name the message name, or empty for scan message.
|
||||
* @param dstAddress the override destination address, or @a SYN (only for @a Message without specific destination as well as scan message).
|
||||
* @param dstAddress the override destination address, or @a SYN (only for @a Message without specific destination
|
||||
* as well as scan message).
|
||||
* @param field the field name.
|
||||
* @param hasValues whether a value has to be checked against.
|
||||
*/
|
||||
SimpleCondition(const string condName, const string refName, const string circuit, const string name, const unsigned char dstAddress, const string field, const bool hasValues = false)
|
||||
SimpleCondition(const string condName, const string refName, const string circuit, const string name,
|
||||
const unsigned char dstAddress, const string field, const bool hasValues = false)
|
||||
: Condition(),
|
||||
m_condName(condName), m_refName(refName), m_circuit(circuit), m_name(name), m_dstAddress(dstAddress), m_field(field), m_hasValues(hasValues), m_message(NULL) { }
|
||||
m_condName(condName), m_refName(refName), m_circuit(circuit), m_name(name), m_dstAddress(dstAddress),
|
||||
m_field(field), m_hasValues(hasValues), m_message(NULL) { }
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
@@ -848,7 +855,8 @@ class SimpleCondition : public Condition {
|
||||
virtual CombinedCondition* combineAnd(Condition* other);
|
||||
|
||||
// @copydoc
|
||||
virtual result_t resolve(MessageMap* messages, ostringstream& errorMessage, void (*readMessageFunc)(Message* message) = NULL);
|
||||
virtual result_t resolve(MessageMap* messages, ostringstream& errorMessage,
|
||||
void (*readMessageFunc)(Message* message) = NULL);
|
||||
|
||||
// @copydoc
|
||||
virtual bool isTrue();
|
||||
@@ -886,7 +894,8 @@ class SimpleCondition : public Condition {
|
||||
/** the message name, or empty for scan message. */
|
||||
const string m_name;
|
||||
|
||||
/** the override destination address, or @a SYN (only for @a Message without specific destination as well as scan message). */
|
||||
/** the override destination address, or @a SYN (only for @a Message without specific destination as well as scan
|
||||
* message). */
|
||||
const unsigned char m_dstAddress;
|
||||
|
||||
/** the field name, or empty for first field. */
|
||||
@@ -915,7 +924,8 @@ class SimpleNumericCondition : public SimpleCondition {
|
||||
* @param field the field name.
|
||||
* @param valueRanges the valid value ranges (pairs of from/to inclusive), empty for @a m_message seen check.
|
||||
*/
|
||||
SimpleNumericCondition(const string condName, const string refName, const string circuit, const string name, const unsigned char dstAddress, const string field, const vector<unsigned int> valueRanges)
|
||||
SimpleNumericCondition(const string condName, const string refName, const string circuit, const string name,
|
||||
const unsigned char dstAddress, const string field, const vector<unsigned int> valueRanges)
|
||||
: SimpleCondition(condName, refName, circuit, name, dstAddress, field, true),
|
||||
m_valueRanges(valueRanges) { }
|
||||
|
||||
@@ -951,7 +961,8 @@ class SimpleStringCondition : public SimpleCondition {
|
||||
* @param field the field name.
|
||||
* @param values the valid values.
|
||||
*/
|
||||
SimpleStringCondition(const string condName, const string refName, const string circuit, const string name, const unsigned char dstAddress, const string field, const vector<string> values)
|
||||
SimpleStringCondition(const string condName, const string refName, const string circuit, const string name,
|
||||
const unsigned char dstAddress, const string field, const vector<string> values)
|
||||
: SimpleCondition(condName, refName, circuit, name, dstAddress, field, true),
|
||||
m_values(values) { }
|
||||
|
||||
@@ -998,7 +1009,8 @@ class CombinedCondition : public Condition {
|
||||
virtual CombinedCondition* combineAnd(Condition* other) { m_conditions.push_back(other); return this; }
|
||||
|
||||
// @copydoc
|
||||
virtual result_t resolve(MessageMap* messages, ostringstream& errorMessage, void (*readMessageFunc)(Message* message) = NULL);
|
||||
virtual result_t resolve(MessageMap* messages, ostringstream& errorMessage,
|
||||
void (*readMessageFunc)(Message* message) = NULL);
|
||||
|
||||
// @copydoc
|
||||
virtual bool isTrue();
|
||||
@@ -1018,13 +1030,16 @@ class Instruction {
|
||||
/**
|
||||
* Construct a new instance.
|
||||
* @param condition the @a Condition this instruction requires, or null.
|
||||
* @param singleton whether this @a Instruction belongs to a set of instructions of which only the first one may be executed for the same source file.
|
||||
* @param singleton whether this @a Instruction belongs to a set of instructions of which only the first one may be
|
||||
* executed for the same source file.
|
||||
* @param defaultDest the default destination address, or empty.
|
||||
* @param defaultCircuit the default circuit name, or empty.
|
||||
* @param defaultSuffix the default circuit name suffix (starting with a "."), or empty.
|
||||
*/
|
||||
Instruction(Condition* condition, const bool singleton, const string& defaultDest, const string& defaultCircuit, const string& defaultSuffix)
|
||||
: m_condition(condition), m_singleton(singleton), m_defaultDest(defaultDest), m_defaultCircuit(defaultCircuit), m_defaultSuffix(defaultSuffix) { }
|
||||
Instruction(Condition* condition, const bool singleton, const string& defaultDest, const string& defaultCircuit,
|
||||
const string& defaultSuffix)
|
||||
: m_condition(condition), m_singleton(singleton), m_defaultDest(defaultDest), m_defaultCircuit(defaultCircuit),
|
||||
m_defaultSuffix(defaultSuffix) { }
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
@@ -1044,8 +1059,9 @@ class Instruction {
|
||||
* @param returnValue the variable in which to store the created instance.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
static result_t create(const string contextPath, const string& defaultDest, const string& defaultCircuit, const string& defaultSuffix,
|
||||
Condition* condition, const string type, vector<string>::iterator& it, const vector<string>::iterator end, Instruction*& returnValue);
|
||||
static result_t create(const string contextPath, const string& defaultDest, const string& defaultCircuit,
|
||||
const string& defaultSuffix, Condition* condition, const string type, vector<string>::iterator& it,
|
||||
const vector<string>::iterator end, Instruction*& returnValue);
|
||||
|
||||
/**
|
||||
* Return the @a Condition this instruction requires.
|
||||
@@ -1054,8 +1070,10 @@ class Instruction {
|
||||
Condition* getCondition() { return m_condition; }
|
||||
|
||||
/**
|
||||
* Return whether this @a Instruction belongs to a set of instructions of which only the first one may be executed for the same source file.
|
||||
* @return whether this @a Instruction belongs to a set of instructions of which only the first one may be executed for the same source file.
|
||||
* Return whether this @a Instruction belongs to a set of instructions of which only the first one may be executed
|
||||
* for the same source file.
|
||||
* @return whether this @a Instruction belongs to a set of instructions of which only the first one may be executed
|
||||
* for the same source file.
|
||||
*/
|
||||
bool isSingleton() { return m_singleton; }
|
||||
|
||||
@@ -1079,7 +1097,8 @@ class Instruction {
|
||||
/** the @a Condition this instruction requires, or null. */
|
||||
Condition* m_condition;
|
||||
|
||||
/** whether this @a Instruction belongs to a set of instructions of which only the first one may be executed for the same source file. */
|
||||
/** whether this @a Instruction belongs to a set of instructions of which only the first one may be executed for the
|
||||
* same source file. */
|
||||
bool m_singleton;
|
||||
|
||||
|
||||
@@ -1103,13 +1122,16 @@ class LoadInstruction : public Instruction {
|
||||
/**
|
||||
* Construct a new instance.
|
||||
* @param condition the @a Condition this instruction requires, or null.
|
||||
* @param singleton whether this @a Instruction belongs to a set of instructions of which only the first one may be executed for the same source file.
|
||||
* @param singleton whether this @a Instruction belongs to a set of instructions of which only the first one may be
|
||||
* executed for the same source file.
|
||||
* @param defaultDest the default destination address (may be overwritten by file name), or empty.
|
||||
* @param defaultCircuit the default circuit name (may be overwritten by file name), or empty.
|
||||
* @param defaultSuffix the default circuit name suffix (starting with a ".", may be overwritten by file name), or empty.
|
||||
* @param defaultSuffix the default circuit name suffix (starting with a ".", may be overwritten by file name), or
|
||||
* empty.
|
||||
* @param filename the name of the file to load.
|
||||
*/
|
||||
LoadInstruction(Condition* condition, const bool singleton, const string& defaultDest, const string& defaultCircuit, const string& defaultSuffix, const string filename)
|
||||
LoadInstruction(Condition* condition, const bool singleton, const string& defaultDest, const string& defaultCircuit,
|
||||
const string& defaultSuffix, const string filename)
|
||||
: Instruction(condition, singleton, defaultDest, defaultCircuit, defaultSuffix), m_filename(filename) { }
|
||||
|
||||
/**
|
||||
@@ -1174,8 +1196,8 @@ class MessageMap : public FileReader {
|
||||
|
||||
// @copydoc
|
||||
virtual result_t addFromFile(vector<string>::iterator& begin, const vector<string>::iterator end,
|
||||
vector< vector<string> >* defaults, const string& defaultDest, const string& defaultCircuit, const string& defaultSuffix,
|
||||
const string& filename, unsigned int lineNo);
|
||||
vector< vector<string> >* defaults, const string& defaultDest, const string& defaultCircuit,
|
||||
const string& defaultSuffix, const string& filename, unsigned int lineNo);
|
||||
|
||||
/**
|
||||
* Get the scan @a Message instance for the specified address.
|
||||
@@ -1219,7 +1241,8 @@ class MessageMap : public FileReader {
|
||||
/**
|
||||
* Get the loaded files for a participant.
|
||||
* @param address the slave address.
|
||||
* @return the name of the file(s) loaded for the participant (separated by comma and enclosed in double quotes), or empty.
|
||||
* @return the name of the file(s) loaded for the participant (separated by comma and enclosed in double quotes),
|
||||
* or empty.
|
||||
*/
|
||||
string getLoadedFiles(unsigned char address);
|
||||
|
||||
@@ -1246,15 +1269,19 @@ class MessageMap : public FileReader {
|
||||
* Find all active get @a Message instances for the specified circuit and name.
|
||||
* @param circuit the circuit name, or empty for any.
|
||||
* @param name the message name, or empty for any.
|
||||
* @param completeMatch false to also include messages where the circuit and name matches only a part of the given circuit and name (default true).
|
||||
* @param completeMatch false to also include messages where the circuit and name matches only a part of the given
|
||||
* circuit and name (default true).
|
||||
* @param withRead true to include read messages (default true).
|
||||
* @param withWrite true to include write messages (default false).
|
||||
* @param withPassive true to include passive messages (default false).
|
||||
* @return the found @a Message instances.
|
||||
* @param completeMatchIgnoreCircuitSuffix ignore different circuit suffixes (after "#") for completeMatch.
|
||||
* @param onlyAvailable true to include only available messages (default true), false to also include messages that are currently not available (e.g. due to unresolved or false conditions).
|
||||
* @param since the start time from which to add updates (inclusive, also removes messages with unset destination address), or 0 to ignore.
|
||||
* @param until the end time to which to add updates (exclusive, also removes messages with unset destination address), or 0 to ignore.
|
||||
* @param onlyAvailable true to include only available messages (default true), false to also include messages that
|
||||
* are currently not available (e.g. due to unresolved or false conditions).
|
||||
* @param since the start time from which to add updates (inclusive, also removes messages with unset destination
|
||||
* address), or 0 to ignore.
|
||||
* @param until the end time to which to add updates (exclusive, also removes messages with unset destination
|
||||
* address), or 0 to ignore.
|
||||
* Note: the caller may not free the returned instances.
|
||||
*/
|
||||
deque<Message*> findAll(const string& circuit, const string& name, const bool completeMatch = true,
|
||||
|
||||
+24
-10
@@ -68,7 +68,8 @@ namespace ebusd {
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
static const unsigned char ESC = 0xA9; //!< escape symbol, either followed by 0x00 for the value 0xA9, or 0x01 for the value 0xAA
|
||||
/** escape symbol, either followed by 0x00 for the value 0xA9, or 0x01 for the value 0xAA. */
|
||||
static const unsigned char ESC = 0xA9;
|
||||
static const unsigned char SYN = 0xAA; //!< synchronization symbol
|
||||
static const unsigned char ACK = 0x00; //!< positive acknowledge
|
||||
static const unsigned char NAK = 0xFF; //!< negative acknowledge
|
||||
@@ -114,24 +115,35 @@ class SymbolString {
|
||||
* @param index the index of the symbol to return.
|
||||
* @return the reference to the symbol at the specified index.
|
||||
*/
|
||||
unsigned char& operator[](const size_t index) { if (index >= m_data.size()) { m_data.resize(index+1, 0); } return m_data[index]; }
|
||||
unsigned char& operator[](const size_t index) {
|
||||
if (index >= m_data.size()) {
|
||||
m_data.resize(index+1, 0);
|
||||
}
|
||||
return m_data[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this instance is equal to the other instance.
|
||||
* @param other the other instance.
|
||||
* @return true if this instance is equal to the other instance (i.e. both escaped or both unescaped and same symbols).
|
||||
* @return true if this instance is equal to the other instance (i.e. both escaped or both unescaped and same
|
||||
* symbols).
|
||||
*/
|
||||
bool operator == (SymbolString& other) { return m_unescapeState == other.m_unescapeState && m_data == other.m_data; }
|
||||
bool operator == (SymbolString& other) {
|
||||
return m_unescapeState == other.m_unescapeState && m_data == other.m_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this instance is different from the other instance.
|
||||
* @param other the other instance.
|
||||
* @return true if this instance is different from the other instance.
|
||||
*/
|
||||
bool operator != (SymbolString& other) { return m_unescapeState != other.m_unescapeState || m_data != other.m_data; }
|
||||
bool operator != (SymbolString& other) {
|
||||
return m_unescapeState != other.m_unescapeState || m_data != other.m_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this instance to the other instance while treating both as master data (i.e. starting with the master address and ending with the CRC).
|
||||
* Compares this instance to the other instance while treating both as master data (i.e. starting with the master
|
||||
* address and ending with the CRC).
|
||||
* @param other the other instance.
|
||||
* @return 0 if this instance is equal to the other instance (i.e. both escaped or both unescaped and same symbols),
|
||||
* 1 if this instance is completely different to the other instance,
|
||||
@@ -159,8 +171,8 @@ class SymbolString {
|
||||
* @param isEscaped whether the symbol is escaped.
|
||||
* @param updateCRC whether to update the calculated CRC in @a m_crc.
|
||||
* @return RESULT_OK if another symbol was appended,
|
||||
* RESULT_IN_ESC if this is an unescaped instance and the symbol is escaped and the start of the escape sequence was received,
|
||||
* RESULT_ERR_ESC if this is an unescaped instance and an invalid escaped sequence was detected.
|
||||
* RESULT_IN_ESC if this is an unescaped instance and the symbol is escaped and the start of the escape sequence was
|
||||
* received, RESULT_ERR_ESC if this is an unescaped instance and an invalid escaped sequence was detected.
|
||||
*/
|
||||
result_t push_back(const unsigned char value, const bool isEscaped = true, const bool updateCRC = true);
|
||||
|
||||
@@ -234,14 +246,16 @@ bool isSlaveMaster(unsigned char addr);
|
||||
/**
|
||||
* Return the slave address associated with the specified address (master or slave).
|
||||
* @param addr the address to check.
|
||||
* @return the slave address, or SYN if the specified address is neither a master address nor a slave address of a master.
|
||||
* @return the slave address, or SYN if the specified address is neither a master address nor a slave address of a
|
||||
* master.
|
||||
*/
|
||||
unsigned char getSlaveAddress(unsigned char addr);
|
||||
|
||||
/**
|
||||
* Return the master address associated with the specified address (master or slave).
|
||||
* @param addr the address to check.
|
||||
* @return the master address, or SYN if the specified address is neither a master address nor a slave address of a master.
|
||||
* @return the master address, or SYN if the specified address is neither a master address nor a slave address of a
|
||||
* master.
|
||||
*/
|
||||
unsigned char getMasterAddress(unsigned char addr);
|
||||
|
||||
|
||||
@@ -59,7 +59,8 @@ int main() {
|
||||
{"x,,str:10", " ", "10fe07000a20202020202020202020", "00", ""},
|
||||
{"x,,str:10", "", "10fe07000a20202020202020202020", "00", "R"},
|
||||
{"x,,str:11", "", "10fe07000a20202020202020202020", "00", "rW"},
|
||||
{"x,,str:24", "abcdefghijklmnopqrstuvwx", "10fe0700186162636465666768696a6b6c6d6e6f707172737475767778", "00", ""},
|
||||
{"x,,str:24", "abcdefghijklmnopqrstuvwx", "10fe0700186162636465666768696a6b6c6d6e6f707172737475767778",
|
||||
"00", ""},
|
||||
{"x,,str:*", "abcde", "10fe0700056162636465", "00", ""},
|
||||
{"x,,str,2", "", "", "", "c"},
|
||||
{"x,,str:10,=dummy", "", "10fe07000a48616c6c6f2044752120", "00", "W"},
|
||||
@@ -73,7 +74,8 @@ int main() {
|
||||
{"x,,nts:10", "", "10fe07000a00000000000000000000", "00", ""},
|
||||
{"x,,nts:10", "abc", "10fe07000a6162630065666768696a", "00", "W"},
|
||||
{"x,,nts:11", "", "10fe07000a20202020202020202020", "00", "rW"},
|
||||
{"x,,nts:24", "abcdefghijklmnopqrstuvwx", "10fe0700186162636465666768696a6b6c6d6e6f707172737475767778", "00", ""},
|
||||
{"x,,nts:24", "abcdefghijklmnopqrstuvwx", "10fe0700186162636465666768696a6b6c6d6e6f707172737475767778",
|
||||
"00", ""},
|
||||
{"x,,nts:*", "abcde", "10fe0700056162636465", "00", "W"},
|
||||
{"x,,nts:*", "abcde", "10fe070006616263646500", "00", ""},
|
||||
{"x,,nts,2", "", "", "", "c"},
|
||||
@@ -427,12 +429,19 @@ int main() {
|
||||
{"x,,bi3:2,0=off;1=on,ja/nein,Wahrheitswert", "x=on ja/nein [Wahrheitswert]", "10feffff0108", "00", "vvv"},
|
||||
{"x,,bi3:2,0=off;1=on,ja/nein,Wahrheitswert", "x=1 ja/nein [Wahrheitswert]", "10feffff0108", "00", "vvvn"},
|
||||
{"x,,bi3:2,0=off;1=on,ja/nein,Wahrheitswert", "\n \"x\": {\"value\": \"on\"}", "10feffff0108", "00", "vj"},
|
||||
{",,bi3:2,0=off;1=on,ja/nein,Wahrheitswert", "\n \"0\": {\"name\": \"\", \"value\": \"on\"}", "10feffff0108", "00", "vj"},
|
||||
{",,bi3:2,0=off;1=on,ja/nein,Wahrheitswert", "\n \"0\": {\"name\": \"\", \"value\": \"on\"}", "10feffff0108", "00", "j"},
|
||||
{"x,,bi3:2,0=off;1=on,ja/nein,Wahrheitswert", "\n \"x\": {\"value\": \"on\", \"unit\": \"ja/nein\", \"comment\": \"Wahrheitswert\"}", "10feffff0108", "00", "vvvj"},
|
||||
{",,bi3:2,0=off;1=on,ja/nein,Wahrheitswert", "\n \"0\": {\"name\": \"\", \"value\": \"on\"}", "10feffff0108",
|
||||
"00", "vj"},
|
||||
{",,bi3:2,0=off;1=on,ja/nein,Wahrheitswert", "\n \"0\": {\"name\": \"\", \"value\": \"on\"}", "10feffff0108",
|
||||
"00", "j"},
|
||||
{"x,,bi3:2,0=off;1=on,ja/nein,Wahrheitswert",
|
||||
"\n \"x\": {\"value\": \"on\", \"unit\": \"ja/nein\", \"comment\": \"Wahrheitswert\"}", "10feffff0108",
|
||||
"00", "vvvj"},
|
||||
{"x,,bi3:2,0=off;1=on,ja/nein,Wahrheitswert", "\n \"x\": {\"value\": 1}", "10feffff0108", "00", "vnj"},
|
||||
{"x,,bi3:2,0=off;1=on,ja/nein,Wahrheitswert", "\n \"x\": {\"value\": 1, \"unit\": \"ja/nein\", \"comment\": \"Wahrheitswert\"}", "10feffff0108", "00", "vvvnj"},
|
||||
{"x,,bi3:2,0=off;1=on,ja/nein,Wahrheitswert", "\n \"0\": {\"name\": \"x\", \"value\": 1}", "10feffff0108", "00", "nj"},
|
||||
{"x,,bi3:2,0=off;1=on,ja/nein,Wahrheitswert",
|
||||
"\n \"x\": {\"value\": 1, \"unit\": \"ja/nein\", \"comment\": \"Wahrheitswert\"}", "10feffff0108", "00",
|
||||
"vvvnj"},
|
||||
{"x,,bi3:2,0=off;1=on,ja/nein,Wahrheitswert", "\n \"0\": {\"name\": \"x\", \"value\": 1}", "10feffff0108", "00",
|
||||
"nj"},
|
||||
{"x,,uch,1=test;2=high;3=off;0x10=on", "on", "10feffff0110", "00", ""},
|
||||
{"x,s,uch", "3", "1050ffff00", "0103", ""},
|
||||
{"x,,d2b,,°C,Aussentemperatur", "x=18.004 °C [Aussentemperatur]", "10fe0700090112", "00", "vvv"},
|
||||
@@ -455,7 +464,8 @@ int main() {
|
||||
{"x,,temp,,,,y,,d1c", "18.004;9.5", "10fe070003011213", "00", ""}, // reference to template, normal def
|
||||
{"x,,temp;HEX:2", "18.004;13 14", "10fe07000401121314", "00", ""}, // reference to template and base type
|
||||
{"x,,temp;HEX:2", "temp=18.004;=13 14", "10fe07000401121314", "00", "v"}, // reference to template and base type
|
||||
{"x,,temp:degrees;HEX:2", "degrees=18.004;=13 14", "10fe07000401121314", "00", "v"}, // reference to template and base type
|
||||
// reference to template and base type
|
||||
{"x,,temp:degrees;HEX:2", "degrees=18.004;=13 14", "10fe07000401121314", "00", "v"},
|
||||
};
|
||||
DataFieldTemplates* templates = new DataFieldTemplates();
|
||||
DataField* fields = NULL;
|
||||
@@ -510,7 +520,8 @@ int main() {
|
||||
fields = NULL;
|
||||
}
|
||||
vector<string>::iterator it = entries.begin();
|
||||
result = DataField::create(it, entries.end(), templates, fields, isSet, isTemplate, !isTemplate && (mstr[1] == BROADCAST || isMaster(mstr[1])));
|
||||
result = DataField::create(it, entries.end(), templates, fields, isSet, isTemplate,
|
||||
!isTemplate && (mstr[1] == BROADCAST || isMaster(mstr[1])));
|
||||
if (failedCreate) {
|
||||
if (result == RESULT_OK) {
|
||||
cout << "\"" << check[0] << "\": failed create error: unexpectedly succeeded" << endl;
|
||||
@@ -555,18 +566,21 @@ int main() {
|
||||
SymbolString writeMstr(false);
|
||||
result = writeMstr.parseHex(mstr.getDataStr(true, false).substr(0, 10));
|
||||
if (result != RESULT_OK) {
|
||||
cout << " parse \"" << mstr.getDataStr(true, false).substr(0, 10) << "\" error: " << getResultCode(result) << endl;
|
||||
cout << " parse \"" << mstr.getDataStr(true, false).substr(0, 10) << "\" error: " << getResultCode(result)
|
||||
<< endl;
|
||||
error = true;
|
||||
}
|
||||
SymbolString writeSstr(false);
|
||||
result = writeSstr.parseHex(sstr.getDataStr(true, false).substr(0, 2));
|
||||
if (result != RESULT_OK) {
|
||||
cout << " parse \"" << sstr.getDataStr(true, false).substr(0, 2) << "\" error: " << getResultCode(result) << endl;
|
||||
cout << " parse \"" << sstr.getDataStr(true, false).substr(0, 2) << "\" error: " << getResultCode(result)
|
||||
<< endl;
|
||||
error = true;
|
||||
}
|
||||
result = fields->read(pt_masterData, mstr, 0, output, verbosity|(numeric?OF_NUMERIC:0), -1, false);
|
||||
if (result >= RESULT_OK) {
|
||||
result = fields->read(pt_slaveData, sstr, 0, output, verbosity|(numeric?OF_NUMERIC:0), -1, !output.str().empty());
|
||||
result = fields->read(pt_slaveData, sstr, 0, output, verbosity|(numeric?OF_NUMERIC:0), -1,
|
||||
!output.str().empty());
|
||||
}
|
||||
if (failedRead) {
|
||||
if (result >= RESULT_OK) {
|
||||
@@ -607,7 +621,9 @@ int main() {
|
||||
error = true;
|
||||
} else {
|
||||
bool match = mstr == writeMstr && sstr == writeSstr;
|
||||
verify(failedWriteMatch, "write", expectStr, match, mstr.getDataStr(true, false) + " " + sstr.getDataStr(true, false), writeMstr.getDataStr(true, false) + " " + writeSstr.getDataStr(true, false));
|
||||
verify(failedWriteMatch, "write", expectStr, match, mstr.getDataStr(true, false) + " "
|
||||
+ sstr.getDataStr(true, false), writeMstr.getDataStr(true, false) + " "
|
||||
+ writeSstr.getDataStr(true, false));
|
||||
}
|
||||
}
|
||||
delete fields;
|
||||
|
||||
@@ -73,13 +73,23 @@ int main() {
|
||||
{"pumpstate,UCH,0=off;1=on;2=overrun,,Pumpenstatus", "", "", "", "template"},
|
||||
{"tempsensor,temp;sensor,,Temperatursensor", "", "", "", "template"},
|
||||
{"tempsensorc,temp;sensorc,,Temperatursensor", "", "", "", "template"},
|
||||
{"r,,Status01,VL/RL/AussenTemp/VLWW/SpeicherTemp/Status,,08,B511,01,,,temp1;temp1;temp2;temp1;temp1;pumpstate", "28.0;24.0;4.938;35.0;41.0;4", "ff08b5110101", "093830f00446520400ff", "d"},
|
||||
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,tempsensor", "temp=-14.00 Temperatursensor [Temperatur];sensor=ok [Fühlerstatus]", "ff25b509030d2800", "0320ff00", "mD"},
|
||||
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,tempsensor,,field unit,field comment", "temp=-14.00 field unit [field comment];sensor=ok [Fühlerstatus]", "ff25b509030d2800", "0320ff00", "mD"},
|
||||
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,tempsensor,,field unit,field comment", "\n \"temp\": {\"value\": -14.00},\n \"sensor\": {\"value\": \"ok\"}", "ff25b509030d2800", "0320ff00", "mj"},
|
||||
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,tempsensor,,field unit,field comment", "\n \"temp\": {\"value\": -14.00, \"unit\": \"field unit\", \"comment\": \"field comment\"},\n \"sensor\": {\"value\": \"ok\", \"comment\": \"Fühlerstatus\"}", "ff25b509030d2800", "0320ff00", "mJ"},
|
||||
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,temp,,field unit,field comment,,,sensor", "temp=-14.00 field unit [field comment];sensor=ok [Fühlerstatus]", "ff25b509030d2800", "0320ff00", "mD"},
|
||||
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,D2C,,°C,Temperatur,,,sensor", "\n \"0\": {\"name\": \"\", \"value\": -14.00},\n \"1\": {\"name\": \"sensor\", \"value\": \"ok\"}", "ff25b509030d2800", "0320ff00", "mj"},
|
||||
{"r,,Status01,VL/RL/AussenTemp/VLWW/SpeicherTemp/Status,,08,B511,01,,,temp1;temp1;temp2;temp1;temp1;pumpstate",
|
||||
"28.0;24.0;4.938;35.0;41.0;4", "ff08b5110101", "093830f00446520400ff", "d"},
|
||||
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,tempsensor",
|
||||
"temp=-14.00 Temperatursensor [Temperatur];sensor=ok [Fühlerstatus]", "ff25b509030d2800", "0320ff00", "mD"},
|
||||
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,tempsensor,,field unit,field comment",
|
||||
"temp=-14.00 field unit [field comment];sensor=ok [Fühlerstatus]", "ff25b509030d2800", "0320ff00", "mD"},
|
||||
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,tempsensor,,field unit,field comment",
|
||||
"\n \"temp\": {\"value\": -14.00},\n \"sensor\": {\"value\": \"ok\"}", "ff25b509030d2800", "0320ff00",
|
||||
"mj"},
|
||||
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,tempsensor,,field unit,field comment",
|
||||
"\n \"temp\": {\"value\": -14.00, \"unit\": \"field unit\", \"comment\": \"field comment\"},\n"
|
||||
" \"sensor\": {\"value\": \"ok\", \"comment\": \"Fühlerstatus\"}", "ff25b509030d2800", "0320ff00", "mJ"},
|
||||
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,temp,,field unit,field comment,,,sensor",
|
||||
"temp=-14.00 field unit [field comment];sensor=ok [Fühlerstatus]", "ff25b509030d2800", "0320ff00", "mD"},
|
||||
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,D2C,,°C,Temperatur,,,sensor",
|
||||
"\n \"0\": {\"name\": \"\", \"value\": -14.00},\n \"1\": {\"name\": \"sensor\", \"value\": \"ok\"}",
|
||||
"ff25b509030d2800", "0320ff00", "mj"},
|
||||
{"r,,name,,,25,B509,0d2800,,,tempsensorc", "-14.00", "ff25b509030d2800", "0320ff55", "m"},
|
||||
{"r,,name,,,25,B509,0d28,,m,sensorc,,,,,,temp", "-14.00", "ff25b509030d2855", "0220ff", "m"},
|
||||
{"u,,first,,,fe,0700,,x,,bda", "26.10.2014", "fffe07000426100614", "00", "p"},
|
||||
@@ -92,20 +102,27 @@ int main() {
|
||||
{"r,ehp,time,,,08;10,b509,0d2800,,,time", "", "", "", "c"},
|
||||
{"r,ehp,time,,,08;09,b509,0d2800,,,time", "15:00:17", "ff08b509030d2800", "0311000f", "md*"},
|
||||
{"r,ehp,date,,,08,b509,0d2900,,,date", "23.11.2014", "ff08b509030d2900", "03170b0e", "md"},
|
||||
{"r,700,date,,,15,b524,020000003400,,,IGN:4,,,,,,date", "23.11.2015", "ff15b52406020000003400", "0703003400170b0f", "d"},
|
||||
{"r,700,time,,,15,b524,030000003500,,,IGN:4,,,,,,HTI", "12:29:06", "ff15b52406030000003500", "07030035000c1d06", "d"},
|
||||
{"r,700,date,,,15,b524,020000003400,,,IGN:4,,,,,,date", "23.11.2015", "ff15b52406020000003400", "0703003400170b0f",
|
||||
"d"},
|
||||
{"r,700,time,,,15,b524,030000003500,,,IGN:4,,,,,,HTI", "12:29:06", "ff15b52406030000003500", "07030035000c1d06",
|
||||
"d"},
|
||||
{"", "23.11.2015", "ff15b52406020000003400", "0703003400170b0f", "d"},
|
||||
{"", "12:29:06", "ff15b52406030000003500", "07030035000c1d06", "d"},
|
||||
{"w,700,date,,,15,b524,020000003400,,,date", "23.11.2015", "ff15b52409020000003400170b0f", "00", "m"},
|
||||
{"r,ehp,error,,,08,b509,0d2800,index,m,UCH,,,,,,time", "3;15:00:17", "ff08b509040d280003", "0311000f", "mdi"},
|
||||
{"r,ehp,error,,,08,b509,0d2800,index,m,UCH,,,,,,time", "index=3;time=15:00:17", "ff08b509040d280003", "0311000f", "mD"},
|
||||
{"u,ehp,ActualEnvironmentPower,Energiebezug,,08,B509,29BA00,,s,IGN:2,,,,,s,power", "8", "1008b5090329ba00", "03ba0008", "pm"},
|
||||
{"r,ehp,error,,,08,b509,0d2800,index,m,UCH,,,,,,time", "index=3;time=15:00:17", "ff08b509040d280003", "0311000f",
|
||||
"mD"},
|
||||
{"u,ehp,ActualEnvironmentPower,Energiebezug,,08,B509,29BA00,,s,IGN:2,,,,,s,power", "8", "1008b5090329ba00",
|
||||
"03ba0008", "pm"},
|
||||
{"uw,ehp,test,Test,,08,B5de,ab,,,power,,,,,s,hex:1", "8;39", "1008b5de02ab08", "0139", "pm"},
|
||||
{"u,ehp,hwTankTemp,Speichertemperatur IST,,25,B509,290000,,,IGN:2,,,,,,tempsensor", "", "", "", "M"},
|
||||
{"", "55.50;ok", "1025b50903290000", "050000780300", "d"},
|
||||
{"r,ehp,datetime,Datum Uhrzeit,,50,B504,00,,,dcfstate,,,,time,,BTI,,,,date,,BDA,,,,temp,,temp2", "valid;08:24:51;31.12.2014;-0.875", "1050b5040100", "0a035124083112031420ff", "md" },
|
||||
{"r,ehp,bad,invalid pos,,50,B5ff,000102,,m,HEX:8;tempsensor;tempsensor;tempsensor;tempsensor;power;power,,,", "", "", "", "c" },
|
||||
{"r,ehp,bad,invalid pos,,50,B5ff,,,s,HEX:8;tempsensor;tempsensor;tempsensor;tempsensor;tempsensor;power;power,,,", "", "", "", "c" },
|
||||
{"r,ehp,datetime,Datum Uhrzeit,,50,B504,00,,,dcfstate,,,,time,,BTI,,,,date,,BDA,,,,temp,,temp2",
|
||||
"valid;08:24:51;31.12.2014;-0.875", "1050b5040100", "0a035124083112031420ff", "md" },
|
||||
{"r,ehp,bad,invalid pos,,50,B5ff,000102,,m,HEX:8;tempsensor;tempsensor;tempsensor;tempsensor;power;power,,,", "",
|
||||
"", "", "c" },
|
||||
{"r,ehp,bad,invalid pos,,50,B5ff,,,s,HEX:8;tempsensor;tempsensor;tempsensor;tempsensor;tempsensor;power;power,,,",
|
||||
"", "", "", "c" },
|
||||
{"r,ehp,ApplianceCode,,,08,b509,0d4301,,,UCH,", "9", "ff08b509030d4301", "0109", "d" },
|
||||
{"r,ehp,,,,08,b509,0d", "", "", "", "defaults" },
|
||||
{"w,ehp,,,,08,b509,0e", "", "", "", "defaults" },
|
||||
@@ -113,22 +130,39 @@ int main() {
|
||||
{"[airtowater]r,ehp,notavailable,,,,,0100,,,uch", "1", "", "", "c" },
|
||||
{"[brinetowater]r,ehp,available,,,,,0100,,,uch", "1", "ff08b509030d0100", "0101", "d" },
|
||||
{"r,,x,,,,,\"6800\",,,UCH,,,bit0=\"comment, continued comment", "", "", "", "c" },
|
||||
{"r,,x,,,,,\"6800\",,,UCH,,\"\",\"bit0=\"comment, continued comment\"", "=1 [bit0=\"comment, continued comment]", "ff08b509030d6800", "0101", "mD" },
|
||||
{"r,ehp,multi,,,,,0001:5;0002;0003,longname,,STR:15", "ABCDEFGHIJKLMNO", "ff08b509030d0001;ff08b509030d0003;ff08b509030d0002", "054142434445;054b4c4d4e4f;05464748494a", "mdC" },
|
||||
{"r,ehp,multi,,,,,01;02;03,longname,,STR:15", "ABCDEFGHIJKLMNO", "ff08b509020d01;ff08b509020d03;ff08b509020d02", "084142434445464748;054b4c4d4e4f;02494a", "mdC" },
|
||||
{"w,ehp,multi,,,,,01:8;02:2;03,longname,,STR:15", "ABCDEFGHIJKLMNO", "ff08b5090a0e014142434445464748;ff08b509040e02494a;ff08b509070e034b4c4d4e4f", "00;00;00", "mdC" },
|
||||
{"w,ehp,multi,,,,,01:8;02:2;0304,longname,,STR:15", "ABCDEFGHIJKLMNO", "ff08b5090a0e014142434445464748;ff08b509040e02494a;ff08b509070e034b4c4d4e4f", "00;00;00", "cC" },
|
||||
{"r,ehp,scan,chained scan,,08,B509,24:9;25;26;27,,,IGN,,,,id4,,STR:28", "21074500100027790000000000N8", "ff08b5090124;ff08b5090125;ff08b5090126;ff08b5090127", "09003231303734353030;09313030303237373930;09303030303030303030;024E38", "mdC" },
|
||||
{"r,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7:1,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B71;B61", "ff08b509030d6900", "03138040", "md" },
|
||||
{"r,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7:1,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B71;B60", "ff08b509030d6900", "0313ffbf", "md" },
|
||||
{"r,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7:1,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B70;B61", "ff08b509030d6900", "03137fff", "md" },
|
||||
{"r,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7:1,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B70;B60", "ff08b509030d6900", "03137fbf", "md" },
|
||||
{"r,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7:1,0=B70;1=B71", "1.9;B61;B71", "ff08b509030d6900", "0213ff", "md" },
|
||||
{"r,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7:1,0=B70;1=B71", "1.9;B60;B71", "ff08b509030d6900", "0213bf", "md" },
|
||||
{"r,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7:1,0=B70;1=B71", "1.9;B61;B70", "ff08b509030d6900", "02137f", "md" },
|
||||
{"r,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7:1,0=B70;1=B71", "1.9;B60;B70", "ff08b509030d6900", "02133f", "md" },
|
||||
{"r,,x,,,,,\"6800\",,,UCH,,\"\",\"bit0=\"comment, continued comment\"", "=1 [bit0=\"comment, continued comment]",
|
||||
"ff08b509030d6800", "0101", "mD" },
|
||||
{"r,ehp,multi,,,,,0001:5;0002;0003,longname,,STR:15", "ABCDEFGHIJKLMNO",
|
||||
"ff08b509030d0001;ff08b509030d0003;ff08b509030d0002", "054142434445;054b4c4d4e4f;05464748494a", "mdC" },
|
||||
{"r,ehp,multi,,,,,01;02;03,longname,,STR:15", "ABCDEFGHIJKLMNO", "ff08b509020d01;ff08b509020d03;ff08b509020d02",
|
||||
"084142434445464748;054b4c4d4e4f;02494a", "mdC" },
|
||||
{"w,ehp,multi,,,,,01:8;02:2;03,longname,,STR:15", "ABCDEFGHIJKLMNO",
|
||||
"ff08b5090a0e014142434445464748;ff08b509040e02494a;ff08b509070e034b4c4d4e4f", "00;00;00", "mdC" },
|
||||
{"w,ehp,multi,,,,,01:8;02:2;0304,longname,,STR:15", "ABCDEFGHIJKLMNO",
|
||||
"ff08b5090a0e014142434445464748;ff08b509040e02494a;ff08b509070e034b4c4d4e4f", "00;00;00", "cC" },
|
||||
{"r,ehp,scan,chained scan,,08,B509,24:9;25;26;27,,,IGN,,,,id4,,STR:28", "21074500100027790000000000N8",
|
||||
"ff08b5090124;ff08b5090125;ff08b5090126;ff08b5090127",
|
||||
"09003231303734353030;09313030303237373930;09303030303030303030;024E38", "mdC" },
|
||||
{"r,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7:1,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B71;B61",
|
||||
"ff08b509030d6900", "03138040", "md" },
|
||||
{"r,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7:1,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B71;B60",
|
||||
"ff08b509030d6900", "0313ffbf", "md" },
|
||||
{"r,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7:1,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B70;B61",
|
||||
"ff08b509030d6900", "03137fff", "md" },
|
||||
{"r,,x,,,,,6900,,,UCH,10,bar,,Bit7,,BI7:1,0=B70;1=B71,,,Bit6,,BI6:1,0=B60;1=B61", "1.9;B70;B60",
|
||||
"ff08b509030d6900", "03137fbf", "md" },
|
||||
{"r,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7:1,0=B70;1=B71", "1.9;B61;B71",
|
||||
"ff08b509030d6900", "0213ff", "md" },
|
||||
{"r,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7:1,0=B70;1=B71", "1.9;B60;B71",
|
||||
"ff08b509030d6900", "0213bf", "md" },
|
||||
{"r,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7:1,0=B70;1=B71", "1.9;B61;B70",
|
||||
"ff08b509030d6900", "02137f", "md" },
|
||||
{"r,,x,,,,,6a00,,,UCH,10,bar,,Bit6,,BI6:1,0=B60;1=B61,,,Bit7,,BI7:1,0=B70;1=B71", "1.9;B60;B70",
|
||||
"ff08b509030d6900", "02133f", "md" },
|
||||
{"r,cir*cuit#level,na*me,com*ment,ff,75,b509,0d", "", "", "", "defaults" },
|
||||
{"r,CIRCUIT,NAME,COMMENT,,,,0100,field,,UCH", "r,cirCIRCUITcuit#level,naNAMEme,comCOMMENTment,ff,75,b509,0d0100,field,s,UCH,,,: field=42", "ff08b509030d0100", "012a", "mDN"},
|
||||
{"r,CIRCUIT,NAME,COMMENT,,,,0100,field,,UCH",
|
||||
"r,cirCIRCUITcuit#level,naNAMEme,comCOMMENTment,ff,75,b509,0d0100,field,s,UCH,,,: field=42",
|
||||
"ff08b509030d0100", "012a", "mDN"},
|
||||
};
|
||||
templates = new DataFieldTemplates();
|
||||
MessageMap* messages = new MessageMap();
|
||||
@@ -174,7 +208,8 @@ int main() {
|
||||
if (result != RESULT_OK) {
|
||||
cout << "\"" << check[0] << "\": template fields create error: " << getResultCode(result) << endl;
|
||||
} else if (it != entries.end()) {
|
||||
cout << "\"" << check[0] << "\": template fields create error: trailing input " << static_cast<unsigned>(entries.end()-it) << endl;
|
||||
cout << "\"" << check[0] << "\": template fields create error: trailing input "
|
||||
<< static_cast<unsigned>(entries.end()-it) << endl;
|
||||
} else {
|
||||
cout << "\"" << check[0] << "\": create template OK" << endl;
|
||||
result = templates->add(fields, "", true);
|
||||
@@ -195,7 +230,8 @@ int main() {
|
||||
if (result != RESULT_OK) {
|
||||
cout << "\"" << check[0] << "\": defaults read error: " << getResultCode(result) << endl;
|
||||
} else if (it != entries.end()) {
|
||||
cout << "\"" << check[0] << "\": defaults read error: trailing input " << static_cast<unsigned>(entries.end()-it) << endl;
|
||||
cout << "\"" << check[0] << "\": defaults read error: trailing input "
|
||||
<< static_cast<unsigned>(entries.end()-it) << endl;
|
||||
} else {
|
||||
cout << "\"" << check[0] << "\": read defaults OK" << endl;
|
||||
if (isCondition) {
|
||||
@@ -204,7 +240,8 @@ int main() {
|
||||
} else {
|
||||
result = messages->resolveConditions();
|
||||
if (result != RESULT_OK) {
|
||||
cout << " resolve conditions error: " << getResultCode(result) << " " << messages->getLastError() << endl;
|
||||
cout << " resolve conditions error: " << getResultCode(result) << " " << messages->getLastError()
|
||||
<< endl;
|
||||
} else {
|
||||
cout << " resolve conditions OK" << endl;
|
||||
}
|
||||
@@ -314,7 +351,8 @@ int main() {
|
||||
continue;
|
||||
}
|
||||
if (it != entries.end()) {
|
||||
cout << "\"" << check[0] << "\": create error: trailing input " << static_cast<unsigned>(entries.end()-it) << endl;
|
||||
cout << "\"" << check[0] << "\": create error: trailing input " << static_cast<unsigned>(entries.end()-it)
|
||||
<< endl;
|
||||
continue;
|
||||
}
|
||||
if (multi && deleteMessages.size() == 1) {
|
||||
@@ -368,7 +406,8 @@ int main() {
|
||||
message->dump(output, NULL, true);
|
||||
output << ": ";
|
||||
}
|
||||
result = message->decodeLastData(output, (decodeVerbose?OF_NAMES|OF_UNITS|OF_COMMENTS:0)|(decodeJson?OF_NAMES|OF_JSON:0), false);
|
||||
result = message->decodeLastData(output,
|
||||
(decodeVerbose?OF_NAMES|OF_UNITS|OF_COMMENTS:0)|(decodeJson?OF_NAMES|OF_JSON:0), false);
|
||||
if (result != RESULT_OK) {
|
||||
cout << " \"" << check[2] << "\" / \"" << check[3] << "\": decode error: "
|
||||
<< getResultCode(result) << endl;
|
||||
@@ -399,7 +438,8 @@ int main() {
|
||||
cout << " \"" << inputStr << "\": prepare OK" << endl;
|
||||
|
||||
bool match = writeMstr == *mstrs[0];
|
||||
verify(failedPrepareMatch, "prepare", inputStr, match, mstrs[0]->getDataStr(true, false), writeMstr.getDataStr(true, false));
|
||||
verify(failedPrepareMatch, "prepare", inputStr, match, mstrs[0]->getDataStr(true, false),
|
||||
writeMstr.getDataStr(true, false));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,6 @@ bool setLogFacilities(const char* facilities) {
|
||||
newFacilites |= 1 << val;
|
||||
}
|
||||
}
|
||||
//s_lastFacilities = newFacilites;
|
||||
s_logFacilites = newFacilites;
|
||||
free(input);
|
||||
return true;
|
||||
|
||||
+8
-4
@@ -125,15 +125,19 @@ void logWrite(const char* facility, const LogLevel level, const char* message, .
|
||||
#define logDebug(facility, ...) (needsLog(facility, ll_debug) ? logWrite(facility, ll_debug, __VA_ARGS__) : void(0))
|
||||
|
||||
/** A macro for an error message that calls the logging function only if needed. */
|
||||
#define logOtherError(facility, ...) (needsLog(lf_other, ll_error) ? logWrite(facility, ll_error, __VA_ARGS__) : void(0))
|
||||
#define logOtherError(facility, ...) \
|
||||
(needsLog(lf_other, ll_error) ? logWrite(facility, ll_error, __VA_ARGS__) : void(0))
|
||||
|
||||
/** A macro for a notice message that calls the logging function only if needed. */
|
||||
#define logOtherNotice(facility, ...) (needsLog(lf_other, ll_notice) ? logWrite(facility, ll_notice, __VA_ARGS__) : void(0))
|
||||
#define logOtherNotice(facility, ...) \
|
||||
(needsLog(lf_other, ll_notice) ? logWrite(facility, ll_notice, __VA_ARGS__) : void(0))
|
||||
|
||||
/** A macro for an info message that calls the logging function only if needed. */
|
||||
#define logOtherInfo(facility, ...) (needsLog(lf_other, ll_info) ? logWrite(facility, ll_info, __VA_ARGS__) : void(0))
|
||||
#define logOtherInfo(facility, ...) \
|
||||
(needsLog(lf_other, ll_info) ? logWrite(facility, ll_info, __VA_ARGS__) : void(0))
|
||||
|
||||
/** A macro for a debug message that calls the logging function only if needed. */
|
||||
#define logOtherDebug(facility, ...) (needsLog(lf_other, ll_debug) ? logWrite(facility, ll_debug, __VA_ARGS__) : void(0))
|
||||
#define logOtherDebug(facility, ...) \
|
||||
(needsLog(lf_other, ll_debug) ? logWrite(facility, ll_debug, __VA_ARGS__) : void(0))
|
||||
|
||||
#endif // LIB_UTILS_LOG_H_
|
||||
|
||||
Reference in New Issue
Block a user