code style

This commit is contained in:
john30
2017-01-14 19:00:47 +01:00
parent ebcb260d5f
commit 5bf2f124b3
42 changed files with 1347 additions and 1066 deletions
+32 -17
View File
@@ -92,9 +92,11 @@ bool PollRequest::notify(result_t result, SymbolString& slave) {
result = m_message->decodeLastData(output); // decode data result = m_message->decodeLastData(output); // decode data
} }
if (result < RESULT_OK) { 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 { } 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; return false;
} }
@@ -109,7 +111,8 @@ result_t ScanRequest::prepare(unsigned char ownMasterAddress) {
m_busHandler->setScanResult(dstAddress, ""); m_busHandler->setScanResult(dstAddress, "");
} }
istringstream input; 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) { if (result >= RESULT_OK) {
logInfo(lf_bus, "scan %2.2x cmd: %s", dstAddress, m_master.getDataStr().c_str()); 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)) { if (sending && startRequest != NULL && m_nextRequests.remove(startRequest)) {
m_currentRequest = startRequest; // force the failed request to be notified 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) { || m_state == bs_noSignal) {
return setState(bs_noSignal, result); return setState(bs_noSignal, result);
} }
@@ -529,14 +533,16 @@ result_t BusHandler::handleSymbol() {
case bs_recvCmd: case bs_recvCmd:
headerLen = 4; 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); result = m_command.push_back(recvSymbol, true, m_command.size() < crcPos);
if (result < RESULT_OK) { if (result < RESULT_OK) {
return setState(bs_skip, result); return setState(bs_skip, result);
} }
if (result == RESULT_OK && crcPos != 0xff && m_command.size() == crcPos + 1) { // CRC received if (result == RESULT_OK && crcPos != 0xff && m_command.size() == crcPos + 1) { // CRC received
unsigned char dstAddress = m_command[1]; 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 (m_commandCrcValid) {
if (dstAddress == BROADCAST) { if (dstAddress == BROADCAST) {
receiveCompleted(); receiveCompleted();
@@ -697,7 +703,8 @@ result_t BusHandler::handleSymbol() {
} }
} }
if (message == NULL || message->isWrite()) { 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)) { if (message == m_messages->getScanMessage(m_ownSlaveAddress)) {
input.str(SCAN_ANSWER); input.str(SCAN_ANSWER);
@@ -748,7 +755,8 @@ result_t BusHandler::setState(BusState state, result_t result, bool firstRepetit
addSeenAddress(dstAddress); addSeenAddress(dstAddress);
} }
bool restart = m_currentRequest->notify( 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) { if (restart) {
m_currentRequest->m_busLostRetries = 0; m_currentRequest->m_busLostRetries = 0;
m_nextRequests.push(m_currentRequest); m_nextRequests.push(m_currentRequest);
@@ -780,7 +788,8 @@ result_t BusHandler::setState(BusState state, result_t result, bool firstRepetit
return result; return result;
} }
if (result < RESULT_OK || (result != RESULT_OK && state == bs_skip)) { 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) { } 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)); logDebug(lf_bus, "switching from %s to %s", getStateCode(m_state), getStateCode(state));
} }
@@ -893,7 +902,8 @@ void BusHandler::receiveCompleted() {
} else if (master) { } else if (master) {
logNotice(lf_update, "unknown MM cmd: %s", m_command.getDataStr().c_str()); logNotice(lf_update, "unknown MM cmd: %s", m_command.getDataStr().c_str());
} else { } 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 { } else {
m_messages->invalidateCache(message); m_messages->invalidateCache(message);
@@ -905,14 +915,17 @@ void BusHandler::receiveCompleted() {
result = message->decodeLastData(output); result = message->decodeLastData(output);
} }
if (result < RESULT_OK) { 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 { } else {
string data = output.str(); string data = output.str();
if (m_answer && dstAddress == (master ? m_ownMasterAddress : m_ownSlaveAddress)) { 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 } else if (message->getDstAddress() == SYN) { // any destination
if (message->getSrcAddress() == SYN) { // any destination and any source 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 { } else {
logNotice(lf_update, "update %s %s ZZ=%2.2x: %s", circuit.c_str(), name.c_str(), dstAddress, data.c_str()); 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) { void BusHandler::formatSeenInfo(ostringstream& output) {
unsigned char address = 0; unsigned char address = 0;
for (int index = 0; index < 256; index++, address++) { for (int index = 0; index < 256; index++, address++) {
if (isValidAddress(address, false) if (isValidAddress(address, false) && ((m_seenAddresses[address]&SEEN) != 0
&& ((m_seenAddresses[address]&SEEN) != 0 || (!m_device->isReadOnly() && (address == m_ownMasterAddress || address == m_ownSlaveAddress)))) { || (!m_device->isReadOnly() && (address == m_ownMasterAddress || address == m_ownSlaveAddress)))) {
output << endl << "address " << setfill('0') << setw(2) << hex << static_cast<unsigned>(address); output << endl << "address " << setfill('0') << setw(2) << hex << static_cast<unsigned>(address);
unsigned char master; unsigned char master;
if (isMaster(address)) { if (isMaster(address)) {
@@ -1081,7 +1094,8 @@ result_t BusHandler::scanAndWait(unsigned char dstAddress, SymbolString& slave)
Message* message = m_messages->getScanMessage(dstAddress); Message* message = m_messages->getScanMessage(dstAddress);
if (message != NULL && message != scanMessage) { if (message != NULL && message != scanMessage) {
scanMessage = message; 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) { if (result != RESULT_ERR_NO_SIGNAL) {
@@ -1110,7 +1124,8 @@ void BusHandler::formatGrabResult(const bool unknown, ostringstream& output) {
output << "grab disabled"; output << "grab disabled";
} else { } else {
bool first = true; 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)) { if (it->second.dump(unknown, m_messages, first, output)) {
first = false; first = false;
} }
+4 -2
View File
@@ -192,7 +192,8 @@ class ScanRequest : public BusRequest {
* @param busHandler the @a BusHandler instance to notify of final scan result. * @param busHandler the @a BusHandler instance to notify of final scan result.
*/ */
ScanRequest(MessageMap* messageMap, deque<Message*> messages, deque<unsigned char> slaves, BusHandler* busHandler) 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_message = m_messages.front();
m_messages.pop_front(); m_messages.pop_front();
} }
@@ -356,7 +357,8 @@ class BusHandler : public WaitThread {
m_answer(answer), m_addressConflict(false), m_answer(answer), m_addressConflict(false),
m_busLostRetries(busLostRetries), m_failedSendRetries(failedSendRetries), m_busLostRetries(busLostRetries), m_failedSendRetries(failedSendRetries),
m_transferLatency(transferLatency), m_busAcquireTimeout(busAcquireTimeout), m_slaveRecvTimeout(slaveRecvTimeout), 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_generateSynInterval(generateSyn ? SYN_TIMEOUT*getMasterNumber(ownAddress)+SYMBOL_DURATION : 0),
m_pollInterval(pollInterval), m_lastReceive(0), m_lastPoll(0), m_pollInterval(pollInterval), m_lastReceive(0), m_lastPoll(0),
m_currentRequest(NULL), m_runningScans(0), m_nextSendPos(0), m_currentRequest(NULL), m_runningScans(0), m_nextSendPos(0),
+43 -20
View File
@@ -161,7 +161,10 @@ static const struct argp_option argpoptions[] = {
{NULL, 0, NULL, 0, "Message configuration options:", 2 }, {NULL, 0, NULL, 0, "Message configuration options:", 2 },
{"configpath", 'c', "PATH", 0, "Read CSV config files from PATH [" CONFIG_PATH "]", 0 }, {"configpath", 'c', "PATH", 0, "Read CSV config files from PATH [" CONFIG_PATH "]", 0 },
{"scanconfig", 's', "ADDR", OPTION_ARG_OPTIONAL, "Pick CSV config files matching initial scan (ADDR=\"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 }, {"checkconfig", O_CHKCFG, NULL, 0, "Check CSV config files, then stop", 0 },
{"dumpconfig", O_DMPCFG, NULL, 0, "Check and dump CSV config files, then stop", 0 }, {"dumpconfig", O_DMPCFG, NULL, 0, "Check and dump CSV config files, then stop", 0 },
{"pollinterval", O_POLINT, "SEC", 0, "Poll for data every SEC seconds (0=disable) [5]", 0 }, {"pollinterval", O_POLINT, "SEC", 0, "Poll for data every SEC seconds (0=disable) [5]", 0 },
@@ -187,8 +190,10 @@ static const struct argp_option argpoptions[] = {
{NULL, 0, NULL, 0, "Log options:", 5 }, {NULL, 0, NULL, 0, "Log options:", 5 },
{"logfile", 'l', "FILE", 0, "Write log to FILE (only for daemon) [" PACKAGE_LOGFILE "]", 0 }, {"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 }, {"logareas", O_LOGARE, "AREAS", 0, "Only write log for matching AREA(S): main,network,bus,update,all "
{"loglevel", O_LOGLEV, "LEVEL", 0, "Only write log below or equal to LEVEL: error/notice/info/debug [notice]", 0 }, "[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 }, {NULL, 0, NULL, 0, "Raw logging options:", 6 },
{"lograwdata", O_RAW, NULL, 0, "Log each received/sent byte on the bus", 0 }, {"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) { if (hasTemplates) {
*hasTemplates = true; *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); files.push_back(p);
} }
} }
@@ -692,7 +698,8 @@ static bool readTemplates(const string path, const string extension, bool availa
if (result == RESULT_OK) { if (result == RESULT_OK) {
logInfo(lf_main, "read templates in %s", path.c_str()); logInfo(lf_main, "read templates in %s", path.c_str());
} else { } 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; return templates;
} }
@@ -706,7 +713,8 @@ static bool readTemplates(const string path, const string extension, bool availa
* @param verbose whether to verbosely log problems. * @param verbose whether to verbosely log problems.
* @return the result code. * @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; vector<string> files, dirs;
bool hasTemplates = false; bool hasTemplates = false;
result_t result = collectConfigFiles(path, "", extension, files, &dirs, &hasTemplates); result_t result = collectConfigFiles(path, "", extension, files, &dirs, &hasTemplates);
@@ -746,7 +754,8 @@ void readMessage(Message* message) {
BusHandler* busHandler = s_mainLoop->getBusHandler(); BusHandler* busHandler = s_mainLoop->getBusHandler();
result_t result = busHandler->readFromBus(message, ""); result_t result = busHandler->readFromBus(message, "");
if (result != RESULT_OK) { 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) { void executeInstructions(MessageMap* messages, bool verbose) {
result_t result = messages->resolveConditions(verbose); result_t result = messages->resolveConditions(verbose);
if (result != RESULT_OK) { 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; ostringstream log;
result = messages->executeInstructions(log, readMessage); result = messages->executeInstructions(log, readMessage);
if (result != RESULT_OK) { 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) { } else if (verbose && log.tellp() > 0) {
logInfo(lf_main, log.str().c_str()); 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) { result_t loadConfigFiles(MessageMap* messages, bool verbose, bool denyRecursive) {
logInfo(lf_main, "loading configuration files from %s", opt.configPath); logInfo(lf_main, "loading configuration files from %s", opt.configPath);
messages->clear(); messages->clear();
s_globalTemplates.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) { if (it->second != &s_globalTemplates) {
delete it->second; delete it->second;
} }
@@ -782,17 +795,20 @@ result_t loadConfigFiles(MessageMap* messages, bool verbose, bool denyRecursive)
} }
s_templatesByPath.clear(); 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) { if (result == RESULT_OK) {
logInfo(lf_main, "read config files"); logInfo(lf_main, "read config files");
} else { } 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); executeInstructions(messages, verbose);
return RESULT_OK; 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; PartType partType;
if (isMaster(address)) { if (isMaster(address)) {
address = (unsigned char)(data[0]+5); // slave address of sending master 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 // find files matching MANUFACTURER/ZZ.*csv in cfgpath
result = collectConfigFiles(path, prefix, ".csv", files, NULL, &hasTemplates); result = collectConfigFiles(path, prefix, ".csv", files, NULL, &hasTemplates);
if (result != RESULT_OK) { 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; return result;
} }
if (files.empty()) { 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; 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++) { for (string::iterator it = ident.begin(); it != ident.end(); it++) {
if (::isspace(*it)) { if (::isspace(*it)) {
ident.erase(it--); ident.erase(it--);
@@ -872,7 +891,8 @@ result_t loadScanConfigFile(MessageMap* messages, unsigned char address, SymbolS
unsigned char checkDest; unsigned char checkDest;
string checkIdent, useCircuit, useSuffix; string checkIdent, useCircuit, useSuffix;
unsigned int checkSw, checkHw; 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; continue;
} }
if (address != checkDest || (checkSw != UINT_MAX && sw != checkSw) || (checkHw != UINT_MAX && hw != checkHw)) { 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()) { 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; return RESULT_ERR_NOTFOUND;
} }
@@ -934,7 +956,8 @@ result_t loadScanConfigFile(MessageMap* messages, unsigned char address, SymbolS
} }
result = messages->readFromFile(best, opt.checkConfig, "", ident); result = messages->readFromFile(best, opt.checkConfig, "", ident);
if (result != RESULT_OK) { 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; 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); 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
View File
@@ -39,7 +39,9 @@ struct options {
const char* configPath; //!< path to CSV configuration files [/etc/ebusd] const char* configPath; //!< path to CSV configuration files [/etc/ebusd]
bool scanConfig; //!< pick configuration files matching initial scan 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 checkConfig; //!< check CSV config files ( != 0) and optionally dump (2), then stop
int pollInterval; //!< poll interval in seconds, 0 to disable [5] 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. * Load the message definitions from a configuration file matching the scan result.
* @param messages the @a MessageMap to load the messages into. * @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 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 relativeFile the string in which the name of the configuration file is stored on success.
* @param verbose whether to verbosely log problems. * @param verbose whether to verbosely log problems.
* @return the result code. * @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 } // namespace ebusd
+53 -26
View File
@@ -364,9 +364,11 @@ string MainLoop::decodeMessage(const string& data, const bool isHttp, bool& conn
const char* str = args[0].c_str(); const char* str = args[0].c_str();
if (args.size() == 2) { if (args.size() == 2) {
// check for "CMD -h" // 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 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(); str = args[1].c_str();
args.clear(); // empty args is used as command help indicator args.clear(); // empty args is used as command help indicator
} }
@@ -534,7 +536,8 @@ string MainLoop::executeRead(vector<string> &args) {
} }
argPos++; 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 argPos = 0; // print usage
} }
@@ -583,17 +586,21 @@ string MainLoop::executeRead(vector<string> &args) {
ret = message->decodeLastData(result); ret = message->decodeLastData(result);
} }
if (ret >= RESULT_OK) { 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 { } 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); 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); return getResultCode(ret);
} }
if (argPos == 0 || args.size() < argPos + 1 || args.size() > argPos + 2) { 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" " or: read [-f] [-m SECONDS] [-c CIRCUIT] -h ZZPBSBNNDx\n"
" Read value(s) or hex message.\n" " Read value(s) or hex message.\n"
" -f force reading from the bus (same as '-m 0')\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())) { if (!hasCache || (message != NULL && message->getLastUpdateTime() > cacheMessage->getLastUpdateTime())) {
cacheMessage = message; // message is newer/better 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) { if (verbosity & OF_NAMES) {
result << cacheMessage->getCircuit() << " " << cacheMessage->getName() << " "; 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) {
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); 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(); return result.str();
} }
@@ -677,9 +689,11 @@ string MainLoop::executeRead(vector<string> &args) {
if (verbosity & OF_NAMES) { if (verbosity & OF_NAMES) {
result << message->getCircuit() << " " << message->getName() << " "; 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) { 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.str("");
result << getResultCode(ret) << " in decode"; result << getResultCode(ret) << " in decode";
return result.str(); return result.str();
@@ -762,9 +776,11 @@ string MainLoop::executeWrite(vector<string> &args) {
ret = message->decodeLastData(result); ret = message->decodeLastData(result);
} }
if (ret >= RESULT_OK) { 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 { } 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) { if (master[1] == BROADCAST) {
return "done broadcast"; return "done broadcast";
@@ -774,7 +790,8 @@ string MainLoop::executeWrite(vector<string> &args) {
} }
return slave.getDataStr(true, false); 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); return getResultCode(ret);
} }
@@ -800,15 +817,18 @@ string MainLoop::executeWrite(vector<string> &args) {
if (message->getDstAddress() == SYN && dstAddress == SYN) { if (message->getDstAddress() == SYN && dstAddress == SYN) {
return getResultCode(RESULT_ERR_INVALID_ADDR); 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) { 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); return getResultCode(ret);
} }
dstAddress = message->getLastMasterData()[1]; dstAddress = message->getLastMasterData()[1];
ostringstream result; ostringstream result;
if (dstAddress == BROADCAST || isMaster(dstAddress)) { 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) { if (dstAddress == BROADCAST) {
return "done broadcast"; return "done broadcast";
} }
@@ -817,16 +837,19 @@ string MainLoop::executeWrite(vector<string> &args) {
ret = message->decodeLastData(pt_slaveData, result); // decode data ret = message->decodeLastData(pt_slaveData, result); // decode data
if (ret >= RESULT_OK && result.str().empty()) { 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); return getResultCode(RESULT_OK);
} }
if (ret != 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.str("");
result << getResultCode(ret) << " in decode"; result << getResultCode(ret) << " in decode";
return result.str(); 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(); return result.str();
} }
@@ -873,7 +896,8 @@ string MainLoop::executeHex(vector<string> &args) {
string MainLoop::executeFind(vector<string> &args) { string MainLoop::executeFind(vector<string> &args) {
size_t argPos = 1; 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; OutputFormat verbosity = 0;
vector<size_t> columns; vector<size_t> columns;
string circuit; string circuit;
@@ -1171,7 +1195,8 @@ string MainLoop::executeScan(vector<string> &args) {
if (result != RESULT_OK) { if (result != RESULT_OK) {
return getResultCode(result); 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; ostringstream ret;
ret << hex << setw(2) << setfill('0') << static_cast<unsigned>(dstAddress); ret << hex << setw(2) << setfill('0') << static_cast<unsigned>(dstAddress);
result = message->decodeLastData(ret, 0, true); // decode data result = message->decodeLastData(ret, 0, true); // decode data
@@ -1291,12 +1316,14 @@ string MainLoop::executeQuit(vector<string> &args, bool& connected) {
string MainLoop::executeHelp() { string MainLoop::executeHelp() {
return "usage:\n" 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" " 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|w Write value(s): write [-d ZZ] -c CIRCUIT NAME [VALUE[;VALUE]*]\n"
" Write hex message: write [-c CIRCUIT] -h ZZPBSBNNDx\n" " Write hex message: write [-c CIRCUIT] -h ZZPBSBNNDx\n"
" hex Send hex data: hex 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" " listen|l Listen for updates: listen [stop]\n"
" state|s Report bus state\n" " state|s Report bus state\n"
" info|i Report information about the daemon, the configuration, and seen devices.\n" " info|i Report information about the daemon, the configuration, and seen devices.\n"
+2 -1
View File
@@ -230,7 +230,8 @@ class MainLoop : public Thread, DeviceListener {
/** whether to pick configuration files matching initial scan. */ /** whether to pick configuration files matching initial scan. */
const bool m_scanConfig; 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; const unsigned char m_initialScan;
/** whether to enable the hex command. */ /** whether to enable the hex command. */
+6 -3
View File
@@ -339,7 +339,8 @@ void MqttHandler::notifyTopic(string topic, string data) {
if (!message->isPassive()) { if (!message->isPassive()) {
result_t result = m_busHandler->readFromBus(message, data); result_t result = m_busHandler->readFromBus(message, data);
if (result != RESULT_OK) { 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; return;
} }
logOtherNotice("mqtt", "%s %s %s: %s", isWrite?"write":"read", circuit.c_str(), name.c_str(), data.c_str()); 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) { void MqttHandler::publishMessage(Message* message, ostringstream& updates) {
result_t result = message->decodeLastData(updates); result_t result = message->decodeLastData(updates);
if (result != RESULT_OK) { 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; return;
} }
if (m_publishByField) { if (m_publishByField) {
@@ -455,7 +457,8 @@ void MqttHandler::publishMessage(Message* message, ostringstream& updates) {
void MqttHandler::publishTopic(string topic, string data, bool retain) { void MqttHandler::publishTopic(string topic, string data, bool retain) {
logOtherDebug("mqtt", "publish %s %s", topic.c_str(), data.c_str()); 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 } // namespace ebusd
+4 -2
View File
@@ -86,7 +86,8 @@ void Connection::run() {
if (ret != 0) { if (ret != 0) {
#ifdef HAVE_PPOLL #ifdef HAVE_PPOLL
// new data from notify // 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; break;
} }
// new data from socket // new data from socket
@@ -282,7 +283,8 @@ void Network::run() {
} }
connection->start("connection"); connection->start("connection");
m_connections.push_back(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());
} }
} }
} }
+8 -4
View File
@@ -108,7 +108,8 @@ int main() {
fields = NULL; fields = NULL;
} }
vector<string>::iterator it = entries.begin(); 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) { if (result != RESULT_OK) {
cout << "\"" << check[0] << "\": create error: " << getResultCode(result) << endl; cout << "\"" << check[0] << "\": create error: " << getResultCode(result) << endl;
error = true; error = true;
@@ -132,13 +133,15 @@ int main() {
SymbolString writeMstr(false); SymbolString writeMstr(false);
result = writeMstr.parseHex(mstr.getDataStr(true, false).substr(0, 10)); result = writeMstr.parseHex(mstr.getDataStr(true, false).substr(0, 10));
if (result != RESULT_OK) { 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; error = true;
} }
SymbolString writeSstr(false); SymbolString writeSstr(false);
result = writeSstr.parseHex(sstr.getDataStr(true, false).substr(0, 2)); result = writeSstr.parseHex(sstr.getDataStr(true, false).substr(0, 2));
if (result != RESULT_OK) { 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; error = true;
} }
result = fields->read(pt_masterData, mstr, 0, output, 0, -1, false); result = fields->read(pt_masterData, mstr, 0, output, 0, -1, false);
@@ -183,7 +186,8 @@ int main() {
error = true; error = true;
} else { } else {
bool match = mstr == writeMstr && sstr == writeSstr; 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; delete fields;
fields = NULL; fields = NULL;
+18 -10
View File
@@ -206,7 +206,8 @@ result_t DataField::create(vector<string>::iterator& it,
} }
transform(typeName.begin(), typeName.end(), typeName.begin(), ::toupper); transform(typeName.begin(), typeName.end(), typeName.begin(), ::toupper);
SingleDataField* add = NULL; 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) { if (add != NULL) {
fields.push_back(add); fields.push_back(add);
} else { } else {
@@ -226,7 +227,8 @@ result_t DataField::create(vector<string>::iterator& it,
} else { } else {
fieldName = (firstType && lastType) ? name : ""; 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) { if (result != RESULT_OK) {
it = typePos; // back to type it = typePos; // back to type
} }
@@ -394,7 +396,8 @@ result_t SingleDataField::read(const PartType partType,
output << ","; output << ",";
} }
if (outputIndex >= 0 || m_name.empty() || !(outputFormat & OF_NAMES)) { 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 { } else {
output << "\n \"" << m_name << "\": {\"value\": "; output << "\n \"" << m_name << "\": {\"value\": ";
} }
@@ -498,7 +501,8 @@ result_t SingleDataField::derive(string name, string comment,
if (values.empty()) { if (values.empty()) {
fields.push_back(new SingleDataField(name, comment, unit, dataType, partType, m_length)); fields.push_back(new SingleDataField(name, comment, unit, dataType, partType, m_length));
} else if (numeric) { } 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 { } else {
return RESULT_ERR_INVALID_ARG; return RESULT_ERR_INVALID_ARG;
} }
@@ -562,7 +566,8 @@ result_t ValueListDataField::derive(string name, string comment,
} else { } else {
values = m_values; 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; return RESULT_OK;
} }
@@ -624,7 +629,8 @@ result_t ValueListDataField::writeSymbols(istringstream& input,
SymbolString& output, const bool isMaster, unsigned char* usedLength) { SymbolString& output, const bool isMaster, unsigned char* usedLength) {
NumberDataType* numType = reinterpret_cast<NumberDataType*>(m_dataType); NumberDataType* numType = reinterpret_cast<NumberDataType*>(m_dataType);
if (isIgnored()) { 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(); const char* str = input.str().c_str();
@@ -634,7 +640,8 @@ result_t ValueListDataField::writeSymbols(istringstream& input,
} }
} }
if (strcasecmp(str, NULL_VALUE) == 0) { 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 char* strEnd = NULL; // fall back to raw value in input
unsigned int value; unsigned int value;
@@ -919,7 +926,8 @@ result_t DataFieldSet::read(const PartType partType,
if (!previousFullByteOffset && !field->hasFullByteOffset(false)) { if (!previousFullByteOffset && !field->hasFullByteOffset(false)) {
offset--; 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) { if (result < RESULT_OK) {
return result; 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, 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, vector< vector<string> >* defaults, const string& defaultDest, const string& defaultCircuit,
const string& filename, unsigned int lineNo) { const string& defaultSuffix, const string& filename, unsigned int lineNo) {
vector<string>::iterator restart = begin; vector<string>::iterator restart = begin;
DataField* field = NULL; DataField* field = NULL;
string name; string name;
+14 -4
View File
@@ -550,14 +550,24 @@ class DataFieldSet : public DataField {
* @param index the index of the @a SingleDataField to return. * @param index the index of the @a SingleDataField to return.
* @return the @a SingleDataField at the specified index, or NULL. * @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. * Returns the @a SingleDataField at the specified index.
* @param index the index of the @a SingleDataField to return. * @param index the index of the @a SingleDataField to return.
* @return the @a SingleDataField at the specified index, or NULL. * @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. * Returns the number of @a SingleDataFields instances in this set.
@@ -640,8 +650,8 @@ class DataFieldTemplates : public FileReader {
// @copydoc // @copydoc
virtual result_t addFromFile(vector<string>::iterator& begin, const vector<string>::iterator end, 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, vector< vector<string> >* defaults, const string& defaultDest, const string& defaultCircuit,
const string& filename, unsigned int lineNo); const string& defaultSuffix, const string& filename, unsigned int lineNo);
/** /**
* Gets the template @a DataField instance with the specified name. * Gets the template @a DataField instance with the specified name.
+87 -42
View File
@@ -40,7 +40,8 @@ using std::setfill;
using std::setprecision; using std::setprecision;
using std::setw; 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; char* strEnd = NULL;
unsigned long ret = strtoul(str, &strEnd, base); 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; 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; char* strEnd = NULL;
long ret = strtol(str, &strEnd, base); 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); 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) { if (pos > begin) {
pos--; 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; out << "Erroneous item is here:" << endl;
bool first = true; bool first = true;
int cnt = 0; int cnt = 0;
@@ -489,7 +494,8 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
if (hasFlag(BCD)) { if (hasFlag(BCD)) {
output[baseOffset + offset - incr] = (unsigned char)((6+daysSinceSunday) % 7); // Sun=0x06 output[baseOffset + offset - incr] = (unsigned char)((6+daysSinceSunday) % 7); // Sun=0x06
} else { } 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) { if (value >= 2000) {
@@ -969,26 +975,46 @@ bool DataTypeList::s_contrib_initialized = libebus_contrib_register();
DataTypeList::DataTypeList() { DataTypeList::DataTypeList() {
add(new StringDataType("STR", MAX_LEN*8, ADJ, ' ')); // >= 1 byte character string filled up with space 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 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("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) // >= 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 StringDataType("NTS", MAX_LEN*8, ADJ, 0));
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) // >= 1 byte hex digit string, usually separated by space, e.g. 0a 1b 2c 3d
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 StringDataType("HEX", MAX_LEN*8, ADJ, 0, true));
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) // date with weekday in BCD, 01.01.2000 - 31.12.2099 (0x01,0x01,WW,0x00 - 0x31,0x12,WW,0x99,
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) // WW is weekday Mon=0x00 - Sun=0x06, 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("BDA", 32, BCD, 0xff, true, false, 0));
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) // date in BCD, 01.01.2000 - 31.12.2099 (0x01,0x01,0x00 - 0x31,0x12,0x99, replacement 0xff)
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("BDA", 24, BCD, 0xff, true, false, 0));
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] // date with weekday, 01.01.2000 - 31.12.2099 (0x01,0x01,WW,0x00 - 0x1f,0x0c,WW,0x63,
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) // WW is weekday Mon=0x01 - Sun=0x07, 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("HDA", 32, 0, 0xff, true, false, 0));
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] // date, 01.01.2000 - 31.12.2099 (0x01,0x01,0x00 - 0x1f,0x0c,0x63, replacement 0xff)
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("HDA", 24, 0, 0xff, true, false, 0));
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) // date, days since 01.01.1900, 01.01.1900 - 06.06.2079 (0x00,0x00 - 0xff,0xff)
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("DAY", 16, 0, 0xff, true, false, 0));
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) // 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("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("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 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("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("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("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) // 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("D1C", 8, 0, 0xff, 0x00, 0xc8, 2));
add(new NumberDataType("D2C", 16, SIG, 0x8000, 0x8001, 0x7fff, 16)); // signed number (fraction 1/16), -2047.9 - +2047.9 // signed number (fraction 1/256), -127.99 - +127.99
add(new NumberDataType("FLT", 16, SIG, 0x8000, 0x8001, 0x7fff, 1000)); // signed number (fraction 1/1000), -32.767 - +32.767, little endian add(new NumberDataType("D2B", 16, SIG, 0x8000, 0x8001, 0x7fff, 256));
add(new NumberDataType("FLR", 16, SIG|REV, 0x8000, 0x8001, 0x7fff, 1000)); // signed number (fraction 1/1000), -32.767 - +32.767, big endian // signed number (fraction 1/16), -2047.9 - +2047.9
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("D2C", 16, SIG, 0x8000, 0x8001, 0x7fff, 16));
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 // signed number (fraction 1/1000), -32.767 - +32.767, little endian
add(new NumberDataType("UIN", 16, 0, 0xffff, 0, 0xfffe, 1)); // unsigned integer, 0 - 65534, little endian add(new NumberDataType("FLT", 16, SIG, 0x8000, 0x8001, 0x7fff, 1000));
add(new NumberDataType("UIR", 16, REV, 0xffff, 0, 0xfffe, 1)); // unsigned integer, 0 - 65534, big endian // signed number (fraction 1/1000), -32.767 - +32.767, big endian
add(new NumberDataType("SIN", 16, SIG, 0x8000, 0x8001, 0x7fff, 1)); // signed integer, -32767 - +32767, little endian add(new NumberDataType("FLR", 16, SIG|REV, 0x8000, 0x8001, 0x7fff, 1000));
add(new NumberDataType("SIR", 16, SIG|REV, 0x8000, 0x8001, 0x7fff, 1)); // signed integer, -32767 - +32767, big endian // signed number (IEEE 754 binary32: 1 bit sign, 8 bits exponent, 23 bits significand), little endian
add(new NumberDataType("U3N", 24, 0, 0xffffff, 0, 0xfffffe, 1)); // unsigned 3 bytes int, 0 - 16777214, little endian add(new NumberDataType("EXP", 32, SIG|EXP, 0x7f800000, 0x00000000, 0xffffffff, 1));
add(new NumberDataType("U3R", 24, REV, 0xffffff, 0, 0xfffffe, 1)); // unsigned 3 bytes int, 0 - 16777214, big endian // signed number (IEEE 754 binary32: 1 bit sign, 8 bits exponent, 23 bits significand), big endian
add(new NumberDataType("S3N", 24, SIG, 0x800000, 0x800001, 0xffffff, 1)); // signed 3 bytes int, -8388607 - +8388607, little endian add(new NumberDataType("EXR", 32, SIG|EXP|REV, 0x7f800000, 0x00000000, 0xffffffff, 1));
add(new NumberDataType("S3R", 24, SIG|REV, 0x800000, 0x800001, 0xffffff, 1)); // signed 3 bytes int, -8388607 - +8388607, big endian // unsigned integer, 0 - 65534, little endian
add(new NumberDataType("ULG", 32, 0, 0xffffffff, 0, 0xfffffffe, 1)); // unsigned integer, 0 - 4294967294, little endian add(new NumberDataType("UIN", 16, 0, 0xffff, 0, 0xfffe, 1));
add(new NumberDataType("ULR", 32, REV, 0xffffffff, 0, 0xfffffffe, 1)); // unsigned integer, 0 - 4294967294, big endian // unsigned integer, 0 - 65534, big endian
add(new NumberDataType("SLG", 32, SIG, 0x80000000, 0x80000001, 0xffffffff, 1)); // signed integer, -2147483647 - +2147483647, little endian add(new NumberDataType("UIR", 16, REV, 0xffff, 0, 0xfffe, 1));
add(new NumberDataType("SLR", 32, SIG|REV, 0x80000000, 0x80000001, 0xffffffff, 1)); // signed integer, -2147483647 - +2147483647, big endian // 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("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("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) add(new NumberDataType("BI2", 6, ADJ|REQ, 0, 2, 1)); // bit 2 (up to 6 bits until bit 7)
+18 -9
View File
@@ -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 IGN = 0x10; //!< ignore value during read and write
static const unsigned int FIX = 0x20; //!< fixed width formatting static const unsigned int FIX = 0x20; //!< fixed width formatting
static const unsigned int REQ = 0x40; //!< value may not be NULL 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 EXP = 0x100; //!< exponential numeric representation
static const unsigned int DAY = 0x200; //!< forced value list defaulting to week days 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 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. * @param length the optional variable in which to store the number of read characters.
* @return the parsed value. * @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. * 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. * @param length the optional variable in which to store the number of read characters.
* @return the parsed value. * @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. * 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 lineNo the current line number in the file being read.
* @param result the result code. * @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 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 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 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) 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) {} : m_id(id), m_bitCount(bitCount), m_flags(flags), m_replacement(replacement) {}
@@ -200,7 +205,8 @@ class DataType {
bool isNumeric() const { return hasFlag(NUM); } 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; } unsigned int getReplacement() const { return m_replacement; }
@@ -264,7 +270,8 @@ class DataType {
/** the combination of flags (like #BCD). */ /** the combination of flags (like #BCD). */
const uint16_t m_flags; 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; 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, 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) 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. * 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, NumberDataType(const string id, const unsigned char bitCount, const uint16_t flags, const unsigned int replacement,
const int16_t firstBit, const int divisor) 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. * Destructor.
+2 -1
View File
@@ -87,7 +87,8 @@ class Device {
* @return the new @a Device, or NULL on error. * @return the new @a Device, or NULL on error.
* Note: the caller needs to free the created instance. * 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. * Get the transfer latency of this device.
+10 -6
View File
@@ -62,9 +62,11 @@ using std::endl;
/** the separator character used between multiple values (in CSV only). */ /** the separator character used between multiple values (in CSV only). */
#define VALUE_SEPARATOR ';' #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. * An abstract class that support reading definitions from a file.
@@ -106,7 +108,8 @@ class FileReader {
unsigned char checkDest; unsigned char checkDest;
string checkIdent, useCircuit, useSuffix; string checkIdent, useCircuit, useSuffix;
unsigned int checkSw, checkHw; 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); defaultDest = filename.substr(lastSep+1, 2);
if (!useCircuit.empty()) { if (!useCircuit.empty()) {
defaultCircuit = useCircuit; defaultCircuit = useCircuit;
@@ -202,8 +205,8 @@ class FileReader {
* @return @a RESULT_OK on success, or an error code. * @return @a RESULT_OK on success, or an error code.
*/ */
virtual result_t addFromFile(vector<string>::iterator& begin, const vector<string>::iterator end, 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, vector< vector<string> >* defaults, const string& defaultDest, const string& defaultCircuit,
const string& filename, unsigned int lineNo) = 0; const string& defaultSuffix, const string& filename, unsigned int lineNo) = 0;
/** /**
* Left and right trim the string. * Left and right trim the string.
@@ -356,7 +359,8 @@ class FileReader {
} }
if (name.length() > 1) { if (name.length() > 1) {
pos = name.find('.', 1); // check for ".IDENT." 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); ident = circuit = name.substr(1, pos-1);
name.erase(0, pos); name.erase(0, pos);
pos = name.find('.', 1); // check for ".CIRCUIT." pos = name.find('.', 1); // check for ".CIRCUIT."
+60 -37
View File
@@ -83,13 +83,10 @@ Message::Message(const string circuit, const string name,
const bool isWrite, const bool isPassive, const bool isWrite, const bool isPassive,
const unsigned char pb, const unsigned char sb, const unsigned char pb, const unsigned char sb,
DataField* data, const bool deleteData) DataField* data, const bool deleteData)
: m_circuit(circuit), m_name(name), m_isWrite(isWrite), : m_circuit(circuit), m_name(name), m_isWrite(isWrite), m_isPassive(isPassive), m_comment(), m_srcAddress(SYN),
m_isPassive(isPassive), m_comment(), m_dstAddress(SYN), m_data(data), m_deleteData(true), m_pollPriority(0), m_usedByCondition(false),
m_srcAddress(SYN), m_dstAddress(SYN), m_isScanMessage(false), m_condition(NULL), m_lastUpdateTime(0), m_lastChangeTime(0), m_pollCount(0),
m_data(data), m_deleteData(true), m_lastPollTime(0) {
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(pb);
m_id.push_back(sb); m_id.push_back(sb);
uint64_t key = 0; uint64_t key = 0;
@@ -116,7 +113,8 @@ Message::Message(const string circuit, const string name,
* empty and @p replaceStar is @p true. * empty and @p replaceStar is @p true.
* @return the default if available and value is empty, or the value. * @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()) { if (defaults == NULL || pos >= defaults->size()) {
return value; return value;
} }
@@ -336,7 +334,7 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
if (it == end) { if (it == end) {
token = ""; token = "";
} else { } else {
token = *it++;// [ID] (optional master data) token = *it++; // [ID] (optional master data)
} }
string defaultIdPrefix; string defaultIdPrefix;
if (useDefaults) { if (useDefaults) {
@@ -406,7 +404,8 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
} }
vector<string>::iterator realEnd = end; vector<string>::iterator realEnd = end;
vector<string> newTypes; 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) { while (defaults->size() > defaultPos + 2 && defaults->at(defaultPos + 2).size() > 0) {
for (size_t i = 0; i < 6; i++) { for (size_t i = 0; i < 6; i++) {
if (defaults->size() > defaultPos) { if (defaults->size() > defaultPos) {
@@ -430,12 +429,14 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
vector<SingleDataField*> fields; vector<SingleDataField*> fields;
data = new DataFieldSet("", "", fields); data = new DataFieldSet("", "", fields);
} else { } 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) { if (result != RESULT_OK) {
return result; 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 // max NN exceeded
delete data; delete data;
return RESULT_ERR_INVALID_POS; return RESULT_ERR_INVALID_POS;
@@ -452,9 +453,11 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
} }
Message* message; Message* message;
if (chainIds.size() > 1) { 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 { } 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); messages.push_back(message);
} }
@@ -687,7 +690,8 @@ result_t Message::decodeLastData(const PartType partType,
} else { } else {
offset = 0; 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) { if (result < RESULT_OK) {
return result; return result;
} }
@@ -700,13 +704,15 @@ result_t Message::decodeLastData(const PartType partType,
result_t Message::decodeLastData(ostringstream& output, OutputFormat outputFormat, result_t Message::decodeLastData(ostringstream& output, OutputFormat outputFormat,
bool leadingSeparator, const char* fieldName, signed char fieldIndex) { bool leadingSeparator, const char* fieldName, signed char fieldIndex) {
size_t startPos = output.str().length(); 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) { if (result < RESULT_OK) {
return result; return result;
} }
bool empty = result == RESULT_EMPTY; bool empty = result == RESULT_EMPTY;
leadingSeparator |= output.str().length() > startPos; 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) { if (result < RESULT_OK) {
return result; return result;
} }
@@ -938,7 +944,8 @@ bool ChainedMessage::checkId(Message& other) {
return false; 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(); size_t cnt = getCount();
if (index >= cnt) { if (index >= cnt) {
return RESULT_ERR_NOTFOUND; return RESULT_ERR_NOTFOUND;
@@ -1166,7 +1173,8 @@ result_t splitValues(string valueList, vector<unsigned int>& valueRanges) {
valueRanges.push_back(0); valueRanges.push_back(0);
} }
bool inclusive = str[1] == '='; 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) { if (result != RESULT_OK) {
return result; return result;
} }
@@ -1199,7 +1207,8 @@ result_t splitValues(string valueList, vector<unsigned int>& valueRanges) {
return RESULT_OK; 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) // name,circuit,messagename,[comment],[fieldname],[ZZ],values (name already skipped by caller)
string circuit = it == end ? "" : *(it++); // circuit string circuit = it == end ? "" : *(it++); // circuit
string name = it == end ? "" : *(it++); // messagename string name = it == end ? "" : *(it++); // messagename
@@ -1304,12 +1313,14 @@ CombinedCondition* SimpleCondition::combineAnd(Condition* other) {
return ret->combineAnd(this)->combineAnd(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) { if (m_message == NULL) {
Message* message; Message* message;
if (m_name.length() == 0) { if (m_name.length() == 0) {
message = messages->getScanMessage(m_dstAddress); 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 { } else {
message = messages->find(m_circuit, m_name, false); message = messages->find(m_circuit, m_name, false);
if (!message) { if (!message) {
@@ -1339,7 +1350,8 @@ result_t SimpleCondition::resolve(MessageMap* messages, ostringstream& errorMess
} else { } else {
Message* first = getFirstAvailable(*derived, message); Message* first = getFirstAvailable(*derived, message);
if (first == NULL) { 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; return RESULT_ERR_INVALID_ARG;
} }
message = first; 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++) { for (vector<Condition*>::iterator it = m_conditions.begin(); it != m_conditions.end(); it++) {
Condition* condition = *it; Condition* condition = *it;
ostringstream dummy; 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, result_t Instruction::create(const string contextPath, const string& defaultDest, const string& defaultCircuit,
Condition* condition, const string type, vector<string>::iterator& it, const vector<string>::iterator end, Instruction*& returnValue) { 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) // type[,argument]* (type already skipped by caller)
bool singleton = false; bool singleton = false;
if ((singleton=(type == "load")) || type == "include") { if ((singleton=(type == "load")) || type == "include") {
@@ -1494,7 +1508,8 @@ result_t LoadInstruction::execute(MessageMap* messages, ostringstream& log, Cond
log << ", "; log << ", ";
} }
if (result != RESULT_OK) { 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; return result;
} }
log << (isSingleton() ? "loaded \"" : "included \"") << m_filename << "\" for \"" << getDestination() << "\""; 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 nameKey = string(isPassive ? "-P" : (isWrite ? "-W" : "-R")) + name; // also store without circuit
map<string, vector<Message*> >::iterator nameIt = m_messagesByName.find(nameKey); map<string, vector<Message*> >::iterator nameIt = m_messagesByName.find(nameKey);
if (nameIt == m_messagesByName.end()) { 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 { } else {
vector<Message*>* messages = &nameIt->second; vector<Message*>* messages = &nameIt->second;
Message* first = messages->front(); Message* first = messages->front();
if (circuit < first->getCircuit()) { 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())) { } 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++; m_messageCount++;
@@ -1620,20 +1638,24 @@ result_t MessageMap::addDefaultFromFile(vector< vector<string> >& defaults, vect
if (row[1].length() == 0) { if (row[1].length() == 0) {
row[1] = defaultCircuit+defaultSuffix; // set default circuit and suffix: "circuit[.suffix]" row[1] = defaultCircuit+defaultSuffix; // set default circuit and suffix: "circuit[.suffix]"
} else if (row[1][0] == '#') { } else if (row[1][0] == '#') {
row[1] = defaultCircuit+defaultSuffix+row[1]; // move security suffix behind default circuit and suffix: "circuit[.suffix]#security" // 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 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('#'); size_t pos = row[1].find_first_of('#');
if (pos == string::npos) { if (pos == string::npos) {
row[1] += defaultSuffix; // append default suffix: "circuit.suffix" row[1] += defaultSuffix; // append default suffix: "circuit.suffix"
} else { } 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) { if (row.size() > 5 && defaultDest.length() > 0 && row[5].length() == 0) {
row[5] = defaultDest; // set default destination 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) { 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, 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, vector< vector<string> >* defaults, const string& defaultDest, const string& defaultCircuit,
const string& filename, unsigned int lineNo) { const string& defaultSuffix, const string& filename, unsigned int lineNo) {
vector<string>::iterator restart = begin; vector<string>::iterator restart = begin;
string types = *restart; string types = *restart;
Condition* condition = NULL; Condition* condition = NULL;
@@ -1709,7 +1731,8 @@ result_t MessageMap::addFromFile(vector<string>::iterator& begin, const vector<s
// instruction // instruction
types = types.substr(1); types = types.substr(1);
Instruction* instruction = NULL; 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) { if (instruction == NULL || result != RESULT_OK) {
m_lastError = "invalid instruction"; m_lastError = "invalid instruction";
return result; return result;
+57 -30
View File
@@ -229,7 +229,8 @@ class Message {
* @param circuit the new circuit name, or empty to use the current circuit name. * @param circuit the new circuit name, or empty to use the current circuit name.
* @return the derived @a Message instance. * @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. * Derive a new @a Message from this message.
@@ -647,7 +648,8 @@ class ChainedMessage : public Message {
virtual ~ChainedMessage(); virtual ~ChainedMessage();
// @copydoc // @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 // @copydoc
virtual unsigned char getIdLength() const { return (unsigned char)(m_ids[0].size() - 2); } 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. * @param returnValue the variable in which to store the created instance.
* @return @a RESULT_OK on success, or an error code. * @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. * 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. * @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. * @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. * Check and return whether this condition is fulfilled.
@@ -825,13 +829,16 @@ class SimpleCondition : public Condition {
* @param refName the reference name for dumping. * @param refName the reference name for dumping.
* @param circuit the circuit name. * @param circuit the circuit name.
* @param name the message name, or empty for scan message. * @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 field the field name.
* @param hasValues whether a value has to be checked against. * @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(), : 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. * Destructor.
@@ -848,7 +855,8 @@ class SimpleCondition : public Condition {
virtual CombinedCondition* combineAnd(Condition* other); virtual CombinedCondition* combineAnd(Condition* other);
// @copydoc // @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 // @copydoc
virtual bool isTrue(); virtual bool isTrue();
@@ -886,7 +894,8 @@ class SimpleCondition : public Condition {
/** the message name, or empty for scan message. */ /** the message name, or empty for scan message. */
const string m_name; 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; const unsigned char m_dstAddress;
/** the field name, or empty for first field. */ /** the field name, or empty for first field. */
@@ -915,7 +924,8 @@ class SimpleNumericCondition : public SimpleCondition {
* @param field the field name. * @param field the field name.
* @param valueRanges the valid value ranges (pairs of from/to inclusive), empty for @a m_message seen check. * @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), : SimpleCondition(condName, refName, circuit, name, dstAddress, field, true),
m_valueRanges(valueRanges) { } m_valueRanges(valueRanges) { }
@@ -951,7 +961,8 @@ class SimpleStringCondition : public SimpleCondition {
* @param field the field name. * @param field the field name.
* @param values the valid values. * @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), : SimpleCondition(condName, refName, circuit, name, dstAddress, field, true),
m_values(values) { } m_values(values) { }
@@ -998,7 +1009,8 @@ class CombinedCondition : public Condition {
virtual CombinedCondition* combineAnd(Condition* other) { m_conditions.push_back(other); return this; } virtual CombinedCondition* combineAnd(Condition* other) { m_conditions.push_back(other); return this; }
// @copydoc // @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 // @copydoc
virtual bool isTrue(); virtual bool isTrue();
@@ -1018,13 +1030,16 @@ class Instruction {
/** /**
* Construct a new instance. * Construct a new instance.
* @param condition the @a Condition this instruction requires, or null. * @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 defaultDest the default destination address, or empty.
* @param defaultCircuit the default circuit name, or empty. * @param defaultCircuit the default circuit name, or empty.
* @param defaultSuffix the default circuit name suffix (starting with a "."), 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) Instruction(Condition* condition, const bool singleton, const string& defaultDest, const string& defaultCircuit,
: m_condition(condition), m_singleton(singleton), m_defaultDest(defaultDest), m_defaultCircuit(defaultCircuit), m_defaultSuffix(defaultSuffix) { } const string& defaultSuffix)
: m_condition(condition), m_singleton(singleton), m_defaultDest(defaultDest), m_defaultCircuit(defaultCircuit),
m_defaultSuffix(defaultSuffix) { }
/** /**
* Destructor. * Destructor.
@@ -1044,8 +1059,9 @@ class Instruction {
* @param returnValue the variable in which to store the created instance. * @param returnValue the variable in which to store the created instance.
* @return @a RESULT_OK on success, or an error code. * @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, static result_t create(const string contextPath, const string& defaultDest, const string& defaultCircuit,
Condition* condition, const string type, vector<string>::iterator& it, const vector<string>::iterator end, Instruction*& returnValue); 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. * Return the @a Condition this instruction requires.
@@ -1054,8 +1070,10 @@ class Instruction {
Condition* getCondition() { return m_condition; } 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
* @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. * 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; } bool isSingleton() { return m_singleton; }
@@ -1079,7 +1097,8 @@ class Instruction {
/** the @a Condition this instruction requires, or null. */ /** the @a Condition this instruction requires, or null. */
Condition* m_condition; 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; bool m_singleton;
@@ -1103,13 +1122,16 @@ class LoadInstruction : public Instruction {
/** /**
* Construct a new instance. * Construct a new instance.
* @param condition the @a Condition this instruction requires, or null. * @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 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 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. * @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) { } : Instruction(condition, singleton, defaultDest, defaultCircuit, defaultSuffix), m_filename(filename) { }
/** /**
@@ -1174,8 +1196,8 @@ class MessageMap : public FileReader {
// @copydoc // @copydoc
virtual result_t addFromFile(vector<string>::iterator& begin, const vector<string>::iterator end, 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, vector< vector<string> >* defaults, const string& defaultDest, const string& defaultCircuit,
const string& filename, unsigned int lineNo); const string& defaultSuffix, const string& filename, unsigned int lineNo);
/** /**
* Get the scan @a Message instance for the specified address. * 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. * Get the loaded files for a participant.
* @param address the slave address. * @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); 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. * Find all active get @a Message instances for the specified circuit and name.
* @param circuit the circuit name, or empty for any. * @param circuit the circuit name, or empty for any.
* @param name the message 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 withRead true to include read messages (default true).
* @param withWrite true to include write messages (default false). * @param withWrite true to include write messages (default false).
* @param withPassive true to include passive messages (default false). * @param withPassive true to include passive messages (default false).
* @return the found @a Message instances. * @return the found @a Message instances.
* @param completeMatchIgnoreCircuitSuffix ignore different circuit suffixes (after "#") for completeMatch. * @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 onlyAvailable true to include only available messages (default true), false to also include messages that
* @param since the start time from which to add updates (inclusive, also removes messages with unset destination address), or 0 to ignore. * are currently not available (e.g. due to unresolved or false conditions).
* @param until the end time to which to add updates (exclusive, also removes messages with unset destination address), or 0 to ignore. * @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. * Note: the caller may not free the returned instances.
*/ */
deque<Message*> findAll(const string& circuit, const string& name, const bool completeMatch = true, deque<Message*> findAll(const string& circuit, const string& name, const bool completeMatch = true,
+24 -10
View File
@@ -68,7 +68,8 @@ namespace ebusd {
using std::string; using std::string;
using std::vector; 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 SYN = 0xAA; //!< synchronization symbol
static const unsigned char ACK = 0x00; //!< positive acknowledge static const unsigned char ACK = 0x00; //!< positive acknowledge
static const unsigned char NAK = 0xFF; //!< negative acknowledge static const unsigned char NAK = 0xFF; //!< negative acknowledge
@@ -114,24 +115,35 @@ class SymbolString {
* @param index the index of the symbol to return. * @param index the index of the symbol to return.
* @return the reference to the symbol at the specified index. * @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. * Return whether this instance is equal to the other instance.
* @param other 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. * Return whether this instance is different from the other instance.
* @param other the other instance. * @param other the other instance.
* @return true if this instance is different from 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. * @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), * @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, * 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 isEscaped whether the symbol is escaped.
* @param updateCRC whether to update the calculated CRC in @a m_crc. * @param updateCRC whether to update the calculated CRC in @a m_crc.
* @return RESULT_OK if another symbol was appended, * @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_IN_ESC if this is an unescaped instance and the symbol is escaped and the start of the escape sequence was
* RESULT_ERR_ESC if this is an unescaped instance and an invalid escaped sequence was detected. * 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); 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). * Return the slave address associated with the specified address (master or slave).
* @param addr the address to check. * @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); unsigned char getSlaveAddress(unsigned char addr);
/** /**
* Return the master address associated with the specified address (master or slave). * Return the master address associated with the specified address (master or slave).
* @param addr the address to check. * @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); unsigned char getMasterAddress(unsigned char addr);
+29 -13
View File
@@ -59,7 +59,8 @@ int main() {
{"x,,str:10", " ", "10fe07000a20202020202020202020", "00", ""}, {"x,,str:10", " ", "10fe07000a20202020202020202020", "00", ""},
{"x,,str:10", "", "10fe07000a20202020202020202020", "00", "R"}, {"x,,str:10", "", "10fe07000a20202020202020202020", "00", "R"},
{"x,,str:11", "", "10fe07000a20202020202020202020", "00", "rW"}, {"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:*", "abcde", "10fe0700056162636465", "00", ""},
{"x,,str,2", "", "", "", "c"}, {"x,,str,2", "", "", "", "c"},
{"x,,str:10,=dummy", "", "10fe07000a48616c6c6f2044752120", "00", "W"}, {"x,,str:10,=dummy", "", "10fe07000a48616c6c6f2044752120", "00", "W"},
@@ -73,7 +74,8 @@ int main() {
{"x,,nts:10", "", "10fe07000a00000000000000000000", "00", ""}, {"x,,nts:10", "", "10fe07000a00000000000000000000", "00", ""},
{"x,,nts:10", "abc", "10fe07000a6162630065666768696a", "00", "W"}, {"x,,nts:10", "abc", "10fe07000a6162630065666768696a", "00", "W"},
{"x,,nts:11", "", "10fe07000a20202020202020202020", "00", "rW"}, {"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", "10fe0700056162636465", "00", "W"},
{"x,,nts:*", "abcde", "10fe070006616263646500", "00", ""}, {"x,,nts:*", "abcde", "10fe070006616263646500", "00", ""},
{"x,,nts,2", "", "", "", "c"}, {"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=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", "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"}, {"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",
{",,bi3:2,0=off;1=on,ja/nein,Wahrheitswert", "\n \"0\": {\"name\": \"\", \"value\": \"on\"}", "10feffff0108", "00", "j"}, "00", "vj"},
{"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", "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}", "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",
{"x,,bi3:2,0=off;1=on,ja/nein,Wahrheitswert", "\n \"0\": {\"name\": \"x\", \"value\": 1}", "10feffff0108", "00", "nj"}, "\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,,uch,1=test;2=high;3=off;0x10=on", "on", "10feffff0110", "00", ""},
{"x,s,uch", "3", "1050ffff00", "0103", ""}, {"x,s,uch", "3", "1050ffff00", "0103", ""},
{"x,,d2b,,°C,Aussentemperatur", "x=18.004 °C [Aussentemperatur]", "10fe0700090112", "00", "vvv"}, {"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,,,,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", "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;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(); DataFieldTemplates* templates = new DataFieldTemplates();
DataField* fields = NULL; DataField* fields = NULL;
@@ -510,7 +520,8 @@ int main() {
fields = NULL; fields = NULL;
} }
vector<string>::iterator it = entries.begin(); 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 (failedCreate) {
if (result == RESULT_OK) { if (result == RESULT_OK) {
cout << "\"" << check[0] << "\": failed create error: unexpectedly succeeded" << endl; cout << "\"" << check[0] << "\": failed create error: unexpectedly succeeded" << endl;
@@ -555,18 +566,21 @@ int main() {
SymbolString writeMstr(false); SymbolString writeMstr(false);
result = writeMstr.parseHex(mstr.getDataStr(true, false).substr(0, 10)); result = writeMstr.parseHex(mstr.getDataStr(true, false).substr(0, 10));
if (result != RESULT_OK) { 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; error = true;
} }
SymbolString writeSstr(false); SymbolString writeSstr(false);
result = writeSstr.parseHex(sstr.getDataStr(true, false).substr(0, 2)); result = writeSstr.parseHex(sstr.getDataStr(true, false).substr(0, 2));
if (result != RESULT_OK) { 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; error = true;
} }
result = fields->read(pt_masterData, mstr, 0, output, verbosity|(numeric?OF_NUMERIC:0), -1, false); result = fields->read(pt_masterData, mstr, 0, output, verbosity|(numeric?OF_NUMERIC:0), -1, false);
if (result >= RESULT_OK) { 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 (failedRead) {
if (result >= RESULT_OK) { if (result >= RESULT_OK) {
@@ -607,7 +621,9 @@ int main() {
error = true; error = true;
} else { } else {
bool match = mstr == writeMstr && sstr == writeSstr; 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; delete fields;
+75 -35
View File
@@ -73,13 +73,23 @@ int main() {
{"pumpstate,UCH,0=off;1=on;2=overrun,,Pumpenstatus", "", "", "", "template"}, {"pumpstate,UCH,0=off;1=on;2=overrun,,Pumpenstatus", "", "", "", "template"},
{"tempsensor,temp;sensor,,Temperatursensor", "", "", "", "template"}, {"tempsensor,temp;sensor,,Temperatursensor", "", "", "", "template"},
{"tempsensorc,temp;sensorc,,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,,Status01,VL/RL/AussenTemp/VLWW/SpeicherTemp/Status,,08,B511,01,,,temp1;temp1;temp2;temp1;temp1;pumpstate",
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,tempsensor", "temp=-14.00 Temperatursensor [Temperatur];sensor=ok [Fühlerstatus]", "ff25b509030d2800", "0320ff00", "mD"}, "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,,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",
{"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"}, "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", "\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,,,tempsensor,,field unit,field comment",
{"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"}, "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,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,0d2800,,,tempsensorc", "-14.00", "ff25b509030d2800", "0320ff55", "m"},
{"r,,name,,,25,B509,0d28,,m,sensorc,,,,,,temp", "-14.00", "ff25b509030d2855", "0220ff", "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"}, {"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;10,b509,0d2800,,,time", "", "", "", "c"},
{"r,ehp,time,,,08;09,b509,0d2800,,,time", "15:00:17", "ff08b509030d2800", "0311000f", "md*"}, {"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,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,date,,,15,b524,020000003400,,,IGN:4,,,,,,date", "23.11.2015", "ff15b52406020000003400", "0703003400170b0f",
{"r,700,time,,,15,b524,030000003500,,,IGN:4,,,,,,HTI", "12:29:06", "ff15b52406030000003500", "07030035000c1d06", "d"}, "d"},
{"r,700,time,,,15,b524,030000003500,,,IGN:4,,,,,,HTI", "12:29:06", "ff15b52406030000003500", "07030035000c1d06",
"d"},
{"", "23.11.2015", "ff15b52406020000003400", "0703003400170b0f", "d"}, {"", "23.11.2015", "ff15b52406020000003400", "0703003400170b0f", "d"},
{"", "12:29:06", "ff15b52406030000003500", "07030035000c1d06", "d"}, {"", "12:29:06", "ff15b52406030000003500", "07030035000c1d06", "d"},
{"w,700,date,,,15,b524,020000003400,,,date", "23.11.2015", "ff15b52409020000003400170b0f", "00", "m"}, {"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", "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"}, {"r,ehp,error,,,08,b509,0d2800,index,m,UCH,,,,,,time", "index=3;time=15:00:17", "ff08b509040d280003", "0311000f",
{"u,ehp,ActualEnvironmentPower,Energiebezug,,08,B509,29BA00,,s,IGN:2,,,,,s,power", "8", "1008b5090329ba00", "03ba0008", "pm"}, "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"}, {"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"}, {"u,ehp,hwTankTemp,Speichertemperatur IST,,25,B509,290000,,,IGN:2,,,,,,tempsensor", "", "", "", "M"},
{"", "55.50;ok", "1025b50903290000", "050000780300", "d"}, {"", "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,datetime,Datum Uhrzeit,,50,B504,00,,,dcfstate,,,,time,,BTI,,,,date,,BDA,,,,temp,,temp2",
{"r,ehp,bad,invalid pos,,50,B5ff,000102,,m,HEX:8;tempsensor;tempsensor;tempsensor;tempsensor;power;power,,,", "", "", "", "c" }, "valid;08:24:51;31.12.2014;-0.875", "1050b5040100", "0a035124083112031420ff", "md" },
{"r,ehp,bad,invalid pos,,50,B5ff,,,s,HEX:8;tempsensor;tempsensor;tempsensor;tempsensor;tempsensor;power;power,,,", "", "", "", "c" }, {"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,ApplianceCode,,,08,b509,0d4301,,,UCH,", "9", "ff08b509030d4301", "0109", "d" },
{"r,ehp,,,,08,b509,0d", "", "", "", "defaults" }, {"r,ehp,,,,08,b509,0d", "", "", "", "defaults" },
{"w,ehp,,,,08,b509,0e", "", "", "", "defaults" }, {"w,ehp,,,,08,b509,0e", "", "", "", "defaults" },
@@ -113,22 +130,39 @@ int main() {
{"[airtowater]r,ehp,notavailable,,,,,0100,,,uch", "1", "", "", "c" }, {"[airtowater]r,ehp,notavailable,,,,,0100,,,uch", "1", "", "", "c" },
{"[brinetowater]r,ehp,available,,,,,0100,,,uch", "1", "ff08b509030d0100", "0101", "d" }, {"[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", "", "", "", "c" },
{"r,,x,,,,,\"6800\",,,UCH,,\"\",\"bit0=\"comment, continued comment\"", "=1 [bit0=\"comment, continued comment]", "ff08b509030d6800", "0101", "mD" }, {"r,,x,,,,,\"6800\",,,UCH,,\"\",\"bit0=\"comment, continued comment\"", "=1 [bit0=\"comment, continued comment]",
{"r,ehp,multi,,,,,0001:5;0002;0003,longname,,STR:15", "ABCDEFGHIJKLMNO", "ff08b509030d0001;ff08b509030d0003;ff08b509030d0002", "054142434445;054b4c4d4e4f;05464748494a", "mdC" }, "ff08b509030d6800", "0101", "mD" },
{"r,ehp,multi,,,,,01;02;03,longname,,STR:15", "ABCDEFGHIJKLMNO", "ff08b509020d01;ff08b509020d03;ff08b509020d02", "084142434445464748;054b4c4d4e4f;02494a", "mdC" }, {"r,ehp,multi,,,,,0001:5;0002;0003,longname,,STR:15", "ABCDEFGHIJKLMNO",
{"w,ehp,multi,,,,,01:8;02:2;03,longname,,STR:15", "ABCDEFGHIJKLMNO", "ff08b5090a0e014142434445464748;ff08b509040e02494a;ff08b509070e034b4c4d4e4f", "00;00;00", "mdC" }, "ff08b509030d0001;ff08b509030d0003;ff08b509030d0002", "054142434445;054b4c4d4e4f;05464748494a", "mdC" },
{"w,ehp,multi,,,,,01:8;02:2;0304,longname,,STR:15", "ABCDEFGHIJKLMNO", "ff08b5090a0e014142434445464748;ff08b509040e02494a;ff08b509070e034b4c4d4e4f", "00;00;00", "cC" }, {"r,ehp,multi,,,,,01;02;03,longname,,STR:15", "ABCDEFGHIJKLMNO", "ff08b509020d01;ff08b509020d03;ff08b509020d02",
{"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" }, "084142434445464748;054b4c4d4e4f;02494a", "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" }, {"w,ehp,multi,,,,,01:8;02:2;03,longname,,STR:15", "ABCDEFGHIJKLMNO",
{"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" }, "ff08b5090a0e014142434445464748;ff08b509040e02494a;ff08b509070e034b4c4d4e4f", "00;00;00", "mdC" },
{"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" }, {"w,ehp,multi,,,,,01:8;02:2;0304,longname,,STR:15", "ABCDEFGHIJKLMNO",
{"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" }, "ff08b5090a0e014142434445464748;ff08b509040e02494a;ff08b509070e034b4c4d4e4f", "00;00;00", "cC" },
{"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,ehp,scan,chained scan,,08,B509,24:9;25;26;27,,,IGN,,,,id4,,STR:28", "21074500100027790000000000N8",
{"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" }, "ff08b5090124;ff08b5090125;ff08b5090126;ff08b5090127",
{"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" }, "09003231303734353030;09313030303237373930;09303030303030303030;024E38", "mdC" },
{"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,,,,,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,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(); templates = new DataFieldTemplates();
MessageMap* messages = new MessageMap(); MessageMap* messages = new MessageMap();
@@ -174,7 +208,8 @@ int main() {
if (result != RESULT_OK) { if (result != RESULT_OK) {
cout << "\"" << check[0] << "\": template fields create error: " << getResultCode(result) << endl; cout << "\"" << check[0] << "\": template fields create error: " << getResultCode(result) << endl;
} else if (it != entries.end()) { } 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 { } else {
cout << "\"" << check[0] << "\": create template OK" << endl; cout << "\"" << check[0] << "\": create template OK" << endl;
result = templates->add(fields, "", true); result = templates->add(fields, "", true);
@@ -195,7 +230,8 @@ int main() {
if (result != RESULT_OK) { if (result != RESULT_OK) {
cout << "\"" << check[0] << "\": defaults read error: " << getResultCode(result) << endl; cout << "\"" << check[0] << "\": defaults read error: " << getResultCode(result) << endl;
} else if (it != entries.end()) { } 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 { } else {
cout << "\"" << check[0] << "\": read defaults OK" << endl; cout << "\"" << check[0] << "\": read defaults OK" << endl;
if (isCondition) { if (isCondition) {
@@ -204,7 +240,8 @@ int main() {
} else { } else {
result = messages->resolveConditions(); result = messages->resolveConditions();
if (result != RESULT_OK) { if (result != RESULT_OK) {
cout << " resolve conditions error: " << getResultCode(result) << " " << messages->getLastError() << endl; cout << " resolve conditions error: " << getResultCode(result) << " " << messages->getLastError()
<< endl;
} else { } else {
cout << " resolve conditions OK" << endl; cout << " resolve conditions OK" << endl;
} }
@@ -314,7 +351,8 @@ int main() {
continue; continue;
} }
if (it != entries.end()) { 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; continue;
} }
if (multi && deleteMessages.size() == 1) { if (multi && deleteMessages.size() == 1) {
@@ -368,7 +406,8 @@ int main() {
message->dump(output, NULL, true); message->dump(output, NULL, true);
output << ": "; 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) { if (result != RESULT_OK) {
cout << " \"" << check[2] << "\" / \"" << check[3] << "\": decode error: " cout << " \"" << check[2] << "\" / \"" << check[3] << "\": decode error: "
<< getResultCode(result) << endl; << getResultCode(result) << endl;
@@ -399,7 +438,8 @@ int main() {
cout << " \"" << inputStr << "\": prepare OK" << endl; cout << " \"" << inputStr << "\": prepare OK" << endl;
bool match = writeMstr == *mstrs[0]; 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));
} }
} }
-1
View File
@@ -71,7 +71,6 @@ bool setLogFacilities(const char* facilities) {
newFacilites |= 1 << val; newFacilites |= 1 << val;
} }
} }
//s_lastFacilities = newFacilites;
s_logFacilites = newFacilites; s_logFacilites = newFacilites;
free(input); free(input);
return true; return true;
+8 -4
View File
@@ -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)) #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. */ /** 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. */ /** 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. */ /** 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. */ /** 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_ #endif // LIB_UTILS_LOG_H_
+1 -1
View File
@@ -156,7 +156,7 @@ string fetchData(TCPSocket* socket, bool& listening) {
#endif #endif
#endif #endif
while(true) { while (true) {
#ifdef HAVE_PPOLL #ifdef HAVE_PPOLL
// wait for new fd event // wait for new fd event
ret = ppoll(fds, nfds, &tdiff, NULL); ret = ppoll(fds, nfds, &tdiff, NULL);