diff --git a/src/ebusd/Makefile.am b/src/ebusd/Makefile.am index 0fdeedfa..3cc2b07c 100644 --- a/src/ebusd/Makefile.am +++ b/src/ebusd/Makefile.am @@ -1,6 +1,7 @@ AM_CXXFLAGS = -fpic \ -Wall \ -Wextra \ + -Wconversion \ -isystem$(top_srcdir)/src/lib/utils \ -isystem$(top_srcdir)/src/lib/ebus \ -DSYSCONFDIR=\"$(sysconfdir)\" \ diff --git a/src/ebusd/bushandler.cpp b/src/ebusd/bushandler.cpp index 4e84fa2e..8bb95ea3 100644 --- a/src/ebusd/bushandler.cpp +++ b/src/ebusd/bushandler.cpp @@ -180,8 +180,8 @@ void BusHandler::run() symCount++; time_t now; time(&now); - if (now != lastTime) { - m_symPerSec = symCount / (now-lastTime); + if (now > lastTime) { + m_symPerSec = symCount / (unsigned int)(now-lastTime); if (m_symPerSec > m_maxSymPerSec) { m_maxSymPerSec = m_symPerSec; if (m_maxSymPerSec > 100) @@ -344,7 +344,7 @@ result_t BusHandler::handleSymbol() return setState(bs_ready, RESULT_ERR_SYN); } - unsigned char headerLen, crcPos; + unsigned int headerLen, crcPos; switch (m_state) { @@ -732,11 +732,11 @@ result_t BusHandler::startScan(bool full) m_scanResults.clear(); - for (unsigned int slave=0; slave<=255; slave++) { + for (unsigned char slave=1; slave != 0; slave++) { // 0 is known to be a master if (!isValidAddress(slave, false) || isMaster(slave)) continue; if (!full && !m_seenAddresses[slave]) { - unsigned int master = slave+(256-5); // check if we saw the corresponding master already + unsigned char master = (unsigned char)(slave+256-5); // check if we saw the corresponding master already if (!isMaster(master) || !m_seenAddresses[slave]) continue; } @@ -755,7 +755,7 @@ result_t BusHandler::startScan(bool full) void BusHandler::formatScanResult(ostringstream& output) { bool first = true; - for (unsigned int slave=0; slave<=255; slave++) { + for (unsigned char slave=1; slave != 0; slave++) { // 0 is known to be a master map::iterator it = m_scanResults.find(slave); if (it != m_scanResults.end()) { if (first) diff --git a/src/ebusd/bushandler.h b/src/ebusd/bushandler.h index bda74470..3e3aba37 100644 --- a/src/ebusd/bushandler.h +++ b/src/ebusd/bushandler.h @@ -267,7 +267,7 @@ public: const unsigned int busAcquireTimeout, const unsigned int slaveRecvTimeout, const unsigned int lockCount, const unsigned int pollInterval) : m_device(device), m_messages(messages), - m_ownMasterAddress(ownAddress), m_ownSlaveAddress((ownAddress+5)&0xff), m_answer(answer), + m_ownMasterAddress(ownAddress), m_ownSlaveAddress((unsigned char)(ownAddress+5)), m_answer(answer), m_busLostRetries(busLostRetries), m_failedSendRetries(failedSendRetries), m_busAcquireTimeout(busAcquireTimeout), m_slaveRecvTimeout(slaveRecvTimeout), m_lockCount(lockCount), m_remainLockCount(lockCount), diff --git a/src/ebusd/main.cpp b/src/ebusd/main.cpp index b0634e50..ac74dfcb 100644 --- a/src/ebusd/main.cpp +++ b/src/ebusd/main.cpp @@ -201,7 +201,7 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) // eBUS options: case 'a': // --address=FF - opt->address = parseInt(arg, 16, 0, 0xff, result); + opt->address = (unsigned char)parseInt(arg, 16, 0, 0xff, result); if (result != RESULT_OK || !isMaster(opt->address)) { argp_error(state, "invalid address"); return EINVAL; diff --git a/src/ebusd/mainloop.cpp b/src/ebusd/mainloop.cpp index 0ce978f2..58cf1bf2 100644 --- a/src/ebusd/mainloop.cpp +++ b/src/ebusd/mainloop.cpp @@ -229,14 +229,15 @@ string MainLoop::executeRead(vector &args) argPos++; } if (argPos == 0 || args.size() < argPos + 1 || args.size() > argPos + 2) - return "usage: read [-v] [-f] [-m SECONDS] [-c CLASS] NAME [FIELD]\n" + return "usage: read [-v] [-f] [-m SECONDS] [-c CLASS] NAME [FIELD[.N]]\n" " Read value(s).\n" " -v be verbose (include field names, units, and comments)\n" " -f force reading from the bus (same as '-m 0')\n" " -m SECONDS only return cached value if age is less than SECONDS [300]\n" " -c CLASS limit to messages of CLASS\n" " NAME the NAME of the message to send\n" - " FIELD only retrieve the single FIELD"; + " FIELD only retrieve the field named FIELD\n" + " N only retrieve the N'th field named FIELD (0-based)"; if (args.size() == argPos + 2) maxAge = 0; // force refresh to filter single field @@ -282,9 +283,18 @@ string MainLoop::executeRead(vector &args) ostringstream result; if (ret == RESULT_OK) { - if (args.size() == argPos + 2) - ret = message->decode(pt_slaveData, slave, result, false, verbose, args[argPos + 1].c_str()); - else + if (args.size() == argPos + 2) { + string fieldName = args[argPos + 1]; + size_t pos = fieldName.find_last_of('.'); + char fieldIndex = -1; + if (pos != string::npos) { + result_t result = RESULT_OK; + fieldIndex = (char)parseInt(fieldName.substr(pos+1).c_str(), 10, 0, MAX_POS, result); + if (result == RESULT_OK) + fieldName = fieldName.substr(0, pos); + } + ret = message->decode(pt_slaveData, slave, result, false, verbose, fieldName.c_str(), fieldIndex); + } else ret = message->decode(pt_slaveData, slave, result, false, verbose); // decode data } if (ret != RESULT_OK) { @@ -314,7 +324,7 @@ string MainLoop::executeWrite(vector &args) if (msg.str().size() < 4*2) // at least ZZ, PB, SB, NN return getResultCode(RESULT_ERR_INVALID_ARG); result_t ret; - unsigned int length = parseInt(msg.str().substr(3*2, 2).c_str(), 16, 0, 16, ret); + unsigned int length = parseInt(msg.str().substr(3*2, 2).c_str(), 16, 0, MAX_POS, ret); if (ret == RESULT_OK && (4+length)*2 != msg.str().size()) return getResultCode(RESULT_ERR_INVALID_ARG); @@ -397,7 +407,7 @@ string MainLoop::executeFind(vector &args) size_t argPos = 1; bool verbose = false, configFormat = false, withRead = true, withWrite = false, withPassive = true, first = true, onlyWithData = false; string clazz; - int pb = -1; + short pb = -1; while (args.size() > argPos && args[argPos][0] == '-') { if (args[argPos] == "-v") verbose = true; @@ -435,9 +445,9 @@ string MainLoop::executeFind(vector &args) const char* str = args[argPos].c_str(); result_t result = RESULT_OK; if (strncasecmp(str, "0x", 2) == 0) - pb = parseInt(str+2, 16, 0, 0xff, result); // hexadecimal + pb = (short)parseInt(str+2, 16, 0, 0xff, result); // hexadecimal else - pb = parseInt(str, 10, 0, 0xff, result); // decimal + pb = (short)parseInt(str, 10, 0, 0xff, result); // decimal if (result != RESULT_OK) { return getResultCode(result); } @@ -670,7 +680,7 @@ string MainLoop::executeQuit(vector &args, bool& connected) string MainLoop::executeHelp() { return "usage:\n" - " read|r Read value(s): read [-v] [-f] [-m SECONDS] [-c CLASS] NAME [FIELD]\n" + " read|r Read value(s): read [-v] [-f] [-m SECONDS] [-c CLASS] NAME [FIELD[.N]]\n" " write|w Write value(s): write [-c] CLASS NAME VALUE[;VALUE]*\n" " Write hex message: write -h ZZPBSBNNDx'\n" " find|f Find message(s): find [-v] [-r] [-w] [-p] [-d] [-i PB] [-f] [-c CLASS] [NAME]\n" diff --git a/src/lib/ebus/Makefile.am b/src/lib/ebus/Makefile.am index fc66a0dc..2c70be41 100644 --- a/src/lib/ebus/Makefile.am +++ b/src/lib/ebus/Makefile.am @@ -1,7 +1,8 @@ AM_CXXFLAGS = -fpic \ -Wall \ -Wextra \ - -Wno-unused-parameter + -Wno-unused-parameter \ + -Wconversion noinst_LIBRARIES = libebus.a diff --git a/src/lib/ebus/data.cpp b/src/lib/ebus/data.cpp index b64a4bb8..9eb999a5 100644 --- a/src/lib/ebus/data.cpp +++ b/src/lib/ebus/data.cpp @@ -29,22 +29,22 @@ using namespace std; static const dataType_t stringDataType = { - "STR",16*8,bt_str, ADJ, ' ', 1, 16, 0 // >= 1 byte character string filled up with space + "STR",MAX_POS*8,bt_str, ADJ, ' ', 1, MAX_POS, 0 // >= 1 byte character string filled up with space }; static const dataType_t pinDataType = { - "PIN", 16, bt_num, FIX|BCD|REV, 0xffff, 0, 0x9999, 1 // unsigned decimal in BCD, 0000 - 9999 (fixed length) + "PIN", 16, bt_num, FIX|BCD|REV, 0xffff, 0, 0x9999, 1 // unsigned decimal in BCD, 0000 - 9999 (fixed length) }; static const dataType_t uchDataType = { - "UCH", 8, bt_num, LST, 0xff, 0, 0xfe, 1 // unsigned integer, 0 - 254 + "UCH", 8, bt_num, LST, 0xff, 0, 0xfe, 1 // unsigned integer, 0 - 254 }; /** the known data field types. */ static const dataType_t dataTypes[] = { - {"IGN",16*8,bt_str, IGN|ADJ, 0, 1, 16, 0}, // >= 1 byte ignored data + {"IGN",MAX_POS*8,bt_str, IGN|ADJ, 0, 1, MAX_POS, 0}, // >= 1 byte ignored data stringDataType, - {"HEX",16*8,bt_hexstr, ADJ, 0, 2, 47, 0}, // >= 1 byte hex digit string, usually separated by space, e.g. 0a 1b 2c 3d + {"HEX",MAX_POS*8,bt_hexstr, ADJ, 0, 2, 47, 0}, // >= 1 byte hex digit string, usually separated by space, e.g. 0a 1b 2c 3d {"BDA", 32, bt_dat, BCD, 0, 10, 10, 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) {"BDA", 24, bt_dat, BCD, 0, 10, 10, 0}, // date in BCD, 01.01.2000 - 31.12.2099 (0x01,0x01,0x00 - 0x31,0x12,0x99) {"HDA", 32, bt_dat, 0, 0, 10, 10, 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)) @@ -82,17 +82,19 @@ static const dataType_t dataTypes[] = { {"BI7", 1, bt_num, ADJ|LST|REQ, 0, 0, 0x01, 7}, // bit 7 }; +/** the maximum divisor value. */ +#define MAX_DIVISOR 1000000000 + +/** the maximum value for value lists. */ +#define MAX_VALUE (1<<24) /** the week day names. */ static const char* dayNames[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; -/** the maximum position within master or slave data. */ -#define MAX_POS 16 - unsigned int parseInt(const char* str, int base, const unsigned int minValue, const unsigned int maxValue, result_t& result, unsigned int* length) { char* strEnd = NULL; - unsigned int ret = strtoul(str, &strEnd, base); + unsigned long int ret = strtoul(str, &strEnd, base); if (strEnd == NULL || *strEnd != 0) { result = RESULT_ERR_INVALID_NUM; // invalid value @@ -104,10 +106,10 @@ unsigned int parseInt(const char* str, int base, const unsigned int minValue, co return 0; } if (length != NULL) - *length = strEnd - str; + *length = (unsigned int)(strEnd - str); result = RESULT_OK; - return ret; + return (unsigned int)ret; } void printErrorPos(vector::iterator begin, const vector::iterator end, vector::iterator pos, string filename, size_t lineNo, result_t result) @@ -128,7 +130,7 @@ void printErrorPos(vector::iterator begin, const vector::iterato } } if (begin < pos) - cnt += 1+(*begin).length()+1; + cnt += 1+(unsigned int)(*begin).length()+1; else if (begin == pos) cnt++; @@ -208,23 +210,23 @@ result_t DataField::create(vector::iterator& it, const string divisorStr = *it++; if (!divisorStr.empty()) { if (divisorStr.find('=') == string::npos) - divisor = parseInt(divisorStr.c_str(), 10, 1, 10000, result); + divisor = parseInt(divisorStr.c_str(), 10, 1, MAX_DIVISOR, result); else { istringstream stream(divisorStr); while (getline(stream, token, VALUE_SEPARATOR) != 0) { const char* str = token.c_str(); char* strEnd = NULL; - unsigned int id; + unsigned long int id; if (strncasecmp(str, "0x", 2) == 0) id = strtoul(str+2, &strEnd, 16); // hexadecimal else id = strtoul(str, &strEnd, 10); // decimal - if (strEnd == NULL || strEnd == str || *strEnd != '=') { + if (strEnd == NULL || strEnd == str || *strEnd != '=' || id > MAX_VALUE) { result = RESULT_ERR_INVALID_LIST; break; } - values[id] = string(strEnd + 1); + values[(unsigned int)id] = string(strEnd + 1); } } if (result != RESULT_OK) @@ -261,7 +263,6 @@ result_t DataField::create(vector::iterator& it, if (templates != NULL) { istringstream stream(typeStr); bool found = false; - string lengthStr; while (result == RESULT_OK && getline(stream, token, VALUE_SEPARATOR) != 0) { DataField* templ = templates->get(token); if (templ == NULL) { @@ -282,7 +283,7 @@ result_t DataField::create(vector::iterator& it, typeName = typeStr; } else { - length = parseInt(typeStr.substr(pos+1).c_str(), 10, 1, MAX_POS, result); + length = (unsigned char)parseInt(typeStr.substr(pos+1).c_str(), 10, 1, MAX_POS, result); if (result != RESULT_OK) break; typeName = typeStr.substr(0, pos); @@ -294,7 +295,7 @@ result_t DataField::create(vector::iterator& it, const dataType_t* dataType = &dataTypes[i]; if (strcasecmp(typeNameStr, dataType->name) == 0) { unsigned char bitCount = dataType->bitCount; - unsigned char byteCount = (bitCount + 7) / 8; + unsigned char byteCount = (unsigned char)((bitCount + 7) / 8); if ((dataType->flags & ADJ) != 0) { // adjustable length if ((bitCount % 8) != 0) { if (length == 0) @@ -306,7 +307,7 @@ result_t DataField::create(vector::iterator& it, break; } - byteCount = (bitCount + 7) / 8; + byteCount = (unsigned char)((bitCount + 7) / 8); } else if (length == 0) byteCount = 1; //default byte count: 1 byte @@ -336,8 +337,13 @@ result_t DataField::create(vector::iterator& it, if (values.empty() || (dataType->flags & LST) == 0) { if (divisor == 0) divisor = 1; - if ((dataType->bitCount % 8) == 0) + if ((dataType->bitCount % 8) == 0) { divisor *= dataType->divisorOrFirstBit; + if (divisor > MAX_DIVISOR) { + result = RESULT_ERR_OUT_OF_RANGE; + break; + } + } add = new NumberDataField(name, comment, unit, *dataType, partType, byteCount, bitCount, divisor); break; @@ -403,7 +409,7 @@ void SingleDataField::dump(ostream& output) result_t SingleDataField::read(const PartType partType, SymbolString& data, unsigned char offset, ostringstream& output, bool leadingSeparator, - bool verbose, const char* filterName, + bool verbose, const char* fieldName, char fieldIndex, char separator) { if (partType != m_partType) @@ -412,15 +418,15 @@ result_t SingleDataField::read(const PartType partType, switch (m_partType) { case pt_masterData: - offset += 5; // skip QQ ZZ PB SB NN + offset = (unsigned char)(offset + 5); // skip QQ ZZ PB SB NN break; case pt_slaveData: - offset += 1; // skip NN + offset++; // skip NN break; default: return RESULT_ERR_INVALID_PART; } - if (isIgnored() || (filterName != NULL && m_name != filterName)) { + if (isIgnored() || (fieldName != NULL && (m_name != fieldName || fieldIndex > 0))) { if (offset + m_length > data.size()) { return RESULT_ERR_INVALID_POS; } @@ -455,10 +461,10 @@ result_t SingleDataField::write(istringstream& input, switch (m_partType) { case pt_masterData: - offset += 5; // skip QQ ZZ PB SB NN + offset = (unsigned char)(offset + 5); // skip QQ ZZ PB SB NN break; case pt_slaveData: - offset += 1; // skip NN + offset++; // skip NN break; default: return RESULT_ERR_INVALID_PART; @@ -521,7 +527,7 @@ result_t StringDataField::readSymbols(SymbolString& input, if ((m_dataType.flags & BCD) != 0) { if ((ch & 0xf0) > 0x90 || (ch & 0x0f) > 0x09) return RESULT_ERR_OUT_OF_RANGE; // invalid BCD - ch = (ch >> 4) * 10 + (ch & 0x0f); + ch = (unsigned char)((ch >> 4) * 10 + (ch & 0x0f)); } switch (m_dataType.type) { @@ -566,7 +572,7 @@ result_t StringDataField::readSymbols(SymbolString& input, count++; } else - ch = (ch % 6) * 10; // minutes + ch = (unsigned char)((ch % 6) * 10); // minutes } if (i == 0) { if (ch > 24) @@ -581,7 +587,7 @@ result_t StringDataField::readSymbols(SymbolString& input, break; default: if (ch < 0x20) - ch = m_dataType.replacement; + ch = (unsigned char)m_dataType.replacement; output << setw(0) << dec << static_cast(ch); break; } @@ -596,7 +602,7 @@ result_t StringDataField::writeSymbols(istringstream& input, { size_t start = 0, count = m_length; int incr = 1; - unsigned long int value = 0, last = 0, lastLast = 0; + unsigned int value = 0, last = 0, lastLast = 0; string token; if ((m_dataType.flags & REV) != 0) { // reverted binary representation (most significant byte first) @@ -606,7 +612,7 @@ result_t StringDataField::writeSymbols(istringstream& input, if (isIgnored() && (m_dataType.flags & REQ) == 0) { for (size_t offset = start, i = 0; i < count; offset += incr, i++) { - output[baseOffset + offset] = m_dataType.replacement; // fill up with replacement + output[baseOffset + offset] = (unsigned char)m_dataType.replacement; // fill up with replacement } return RESULT_OK; } @@ -622,10 +628,10 @@ result_t StringDataField::writeSymbols(istringstream& input, value = m_dataType.replacement; // fill up with replacement else { token.clear(); - token.push_back(input.get()); + token.push_back((unsigned char)input.get()); if (input.eof()) return RESULT_ERR_INVALID_NUM; // too short hex value - token.push_back(input.get()); + token.push_back((unsigned char)input.get()); if (input.eof()) return RESULT_ERR_INVALID_NUM; // too short hex value @@ -660,7 +666,7 @@ result_t StringDataField::writeSymbols(istringstream& input, return RESULT_ERR_INVALID_NUM; // invalid date unsigned char daysSinceSunday = (unsigned char)t.tm_wday; // Sun=0 if ((m_dataType.flags & BCD) != 0) - output[baseOffset + offset - incr] = (6+daysSinceSunday) % 7; // Sun=0x06 + output[baseOffset + offset - incr] = (unsigned char)((6+daysSinceSunday) % 7); // Sun=0x06 else output[baseOffset + offset - incr] = (daysSinceSunday==0 ? 7 : daysSinceSunday); // Sun=0x07 } @@ -771,7 +777,8 @@ result_t NumericDataField::readRawValue(SymbolString& input, } value = 0; - for (size_t offset = start, i = 0, exp = 1; i < count; offset += incr, i++) { + unsigned int exp = 1; + for (size_t offset = start, i = 0; i < count; offset += incr, i++) { ch = input[baseOffset + offset]; if ((m_dataType.flags & BCD) != 0) { if ((m_dataType.flags & REQ) == 0 && ch == (m_dataType.replacement & 0xff)) { @@ -781,7 +788,7 @@ result_t NumericDataField::readRawValue(SymbolString& input, if ((ch & 0xf0) > 0x90 || (ch & 0x0f) > 0x09) return RESULT_ERR_OUT_OF_RANGE; // invalid BCD - ch = (ch >> 4) * 10 + (ch & 0x0f); + ch = (unsigned char)((ch >> 4) * 10 + (ch & 0x0f)); value += ch * exp; exp *= 100; } @@ -823,8 +830,8 @@ result_t NumericDataField::writeRawValue(unsigned int value, if ((m_dataType.flags & REQ) == 0 && value == m_dataType.replacement) ch = m_dataType.replacement & 0xff; else { - ch = (value / exp) % 100; - ch = ((ch / 10) << 4) | (ch % 10); + ch = (unsigned char)((value / exp) % 100); + ch = (unsigned char)(((ch / 10) << 4) | (ch % 10)); } exp = exp * 100; } @@ -847,10 +854,10 @@ NumberDataField::NumberDataField(const string name, const string comment, const unsigned char length, const unsigned char bitCount, const unsigned int divisor) : NumericDataField(name, comment, unit, dataType, partType, length, bitCount, - (dataType.bitCount % 8) == 0 ? 0 : dataType.divisorOrFirstBit), + (dataType.bitCount % 8) == 0 ? 0 : (unsigned char)dataType.divisorOrFirstBit), m_divisor(divisor), m_precision(0) { - for (unsigned int exp = 1; exp < 1000000000; exp *= 10, m_precision++) + for (unsigned int exp = 1; exp < MAX_DIVISOR; exp *= 10, m_precision++) if (exp >= divisor) break; } @@ -870,8 +877,12 @@ result_t NumberDataField::derive(string name, string comment, unit = m_unit; if (divisor == 0) divisor = m_divisor; - else if ((m_dataType.bitCount % 8) == 0) + else if ((m_dataType.bitCount % 8) == 0) { divisor *= m_dataType.divisorOrFirstBit; + if (divisor > MAX_DIVISOR) { + return RESULT_ERR_OUT_OF_RANGE; + } + } if (!values.empty()) { if (divisor != 1) return RESULT_ERR_INVALID_ARG; // cannot use divisor != 1 for value list field @@ -917,7 +928,7 @@ result_t NumberDataField::readSymbols(SymbolString& input, output << static_cast(value); else output << setprecision(m_precision) - << fixed << static_cast(value / (float) m_divisor); + << fixed << static_cast((float)value / (float)m_divisor); return RESULT_OK; } signedValue = (int) value; // negative signed value @@ -934,7 +945,7 @@ result_t NumberDataField::readSymbols(SymbolString& input, } else output << setprecision(m_precision) - << fixed << static_cast(signedValue / (float) m_divisor); + << fixed << static_cast((float)signedValue / (float)m_divisor); return RESULT_OK; } @@ -953,14 +964,14 @@ result_t NumberDataField::writeSymbols(istringstream& input, char* strEnd = NULL; if (m_divisor <= 1) { if ((m_dataType.flags & SIG) != 0) { - int signedValue = strtol(str, &strEnd, 10); + long int signedValue = strtol(str, &strEnd, 10); if (signedValue < 0 && m_bitCount != 32) - value = (unsigned int) (signedValue + (1 << m_bitCount)); + value = (unsigned int)(signedValue + (1 << m_bitCount)); else - value = (unsigned int) signedValue; + value = (unsigned int)signedValue; } else - value = strtoul(str, &strEnd, 10); + value = (unsigned int)strtoul(str, &strEnd, 10); if (strEnd == NULL || *strEnd != 0) return RESULT_ERR_INVALID_NUM; // invalid value } @@ -974,9 +985,9 @@ result_t NumberDataField::writeSymbols(istringstream& input, if (dvalue < -(1LL << (8 * m_length)) || dvalue >= (1LL << (8 * m_length))) return RESULT_ERR_OUT_OF_RANGE; // value out of range if (dvalue < 0 && m_bitCount != 32) - value = (unsigned int) (dvalue + (1 << m_bitCount)); + value = (unsigned int)(dvalue + (1 << m_bitCount)); else - value = (unsigned int) dvalue; + value = (unsigned int)dvalue; } else { if (dvalue < 0.0 || dvalue >= (1LL << (8 * m_length))) @@ -1144,7 +1155,7 @@ unsigned char DataFieldSet::getLength(PartType partType) if (!previousFullByteOffset[partType] && !field->hasFullByteOffset(false)) length--; - length += field->getLength(partType); + length = (unsigned char)(length + field->getLength(partType)); previousFullByteOffset[partType] = field->hasFullByteOffset(true); } @@ -1185,10 +1196,10 @@ void DataFieldSet::dump(ostream& output) result_t DataFieldSet::read(const PartType partType, SymbolString& data, unsigned char offset, ostringstream& output, bool leadingSeparator, - bool verbose, const char* filterName, + bool verbose, const char* fieldName, char fieldIndex, char separator) { - bool previousFullByteOffset = true, found = false; + bool previousFullByteOffset = true, found = false, findFieldIndex = fieldName != NULL && fieldIndex >= 0; for (vector::iterator it = m_fields.begin(); it < m_fields.end(); it++) { SingleDataField* field = *it; if (partType != pt_any && field->getPartType() != partType) @@ -1197,19 +1208,29 @@ result_t DataFieldSet::read(const PartType partType, if (!previousFullByteOffset && !field->hasFullByteOffset(false)) offset--; - result_t result = field->read(partType, data, offset, output, leadingSeparator, verbose, filterName, separator); + result_t result = field->read(partType, data, offset, output, leadingSeparator, verbose, fieldName, fieldIndex, separator); if (result < RESULT_OK) return result; - offset += field->getLength(partType); + offset = (unsigned char)(offset + field->getLength(partType)); previousFullByteOffset = field->hasFullByteOffset(true); if (result != RESULT_EMPTY) { found = true; leadingSeparator = true; } + if (findFieldIndex && fieldName == field->getName()) { + if (fieldIndex == 0) { + if (!found) + return RESULT_ERR_NOTFOUND; + break; + } + fieldIndex--; + } } + if (findFieldIndex && !found) + return RESULT_ERR_NOTFOUND; if (verbose) { if (m_comment.length() > 0) output << " [" << m_comment << "]"; @@ -1249,7 +1270,7 @@ result_t DataFieldSet::write(istringstream& input, if (result != RESULT_OK) return result; - offset += field->getLength(partType); + offset = (unsigned char)(offset + field->getLength(partType)); previousFullByteOffset = field->hasFullByteOffset(true); } diff --git a/src/lib/ebus/data.h b/src/lib/ebus/data.h index b17878b4..a8a7a282 100644 --- a/src/lib/ebus/data.h +++ b/src/lib/ebus/data.h @@ -76,15 +76,18 @@ static const unsigned int REQ = 0x100;//!< value may not be NULL /** The structure for defining field types with their properties. */ typedef struct { const char* name; //!< field identifier - const unsigned int bitCount; //!< number of bits (maximum length if @a ADJ flag is set, must be multiple of 8 with flag @a BCD) + const unsigned char bitCount; //!< number of bits (maximum length if @a ADJ flag is set, must be multiple of 8 with flag @a BCD) const BaseType type; //!< base data type - const unsigned int flags; //!< flags (e.g. @a BCD) + const unsigned short flags; //!< flags (e.g. @a BCD) const unsigned int replacement; //!< replacement value (fill-up value for @a bt_str / @a bt_hexstr, no replacement if equal to @a minValueOrLength for @a bt_num) const unsigned int minValueOrLength; //!< minimum binary value (minimum length of string for @a StringDataField) const unsigned int maxValueOrLength; //!< maximum binary value (maximum length of string for @a StringDataField) - const unsigned int divisorOrFirstBit; //!< @a bt_number: divisor or offset to first bit (if (@a bitCount%8)!=0) + const unsigned short divisorOrFirstBit; //!< @a bt_number: divisor or offset to first bit (if (@a bitCount%8)!=0) } dataType_t; +/** the maximum position within master or slave data. */ +#define MAX_POS 16 + /** * Parse an unsigned int value. * @param str the string to parse. @@ -214,7 +217,7 @@ public: virtual result_t read(const PartType partType, SymbolString& data, unsigned char offset, ostringstream& output, bool leadingSeparator=false, - bool verbose=false, const char* filterName=NULL, + bool verbose=false, const char* fieldName=NULL, char fieldIndex=-1, char separator=UI_FIELD_SEPARATOR) = 0; /** @@ -306,7 +309,7 @@ public: virtual result_t read(const PartType partType, SymbolString& data, unsigned char offset, ostringstream& output, bool leadingSeparator=false, - bool verbose=false, const char* filterName=NULL, + bool verbose=false, const char* fieldName=NULL, char fieldIndex=-1, char separator=UI_FIELD_SEPARATOR); // @copydoc @@ -540,7 +543,7 @@ public: const unsigned char length, const unsigned char bitCount, const map values) : NumericDataField(name, comment, unit, dataType, partType, length, bitCount, - (dataType.bitCount < 8) ? dataType.divisorOrFirstBit : 0), + (dataType.bitCount < 8) ? (unsigned char)dataType.divisorOrFirstBit : 0), m_values(values) {} /** @@ -638,7 +641,7 @@ public: virtual result_t read(const PartType partType, SymbolString& data, unsigned char offset, ostringstream& output, bool leadingSeparator=false, - bool verbose=false, const char* filterName=NULL, + bool verbose=false, const char* fieldName=NULL, char fieldIndex=-1, char separator=UI_FIELD_SEPARATOR); // @copydoc diff --git a/src/lib/ebus/device.cpp b/src/lib/ebus/device.cpp index 7fde4119..0d9108c5 100644 --- a/src/lib/ebus/device.cpp +++ b/src/lib/ebus/device.cpp @@ -49,7 +49,7 @@ Device* Device::create(const char* name, const bool checkDevice, char* pos = strchr((char*)name, ':'); if (pos != NULL) { char* end = NULL; - unsigned int port = strtoul(pos+1, &end, 10); + unsigned long int port = strtoul(pos+1, &end, 10); if (end == NULL || *end != 0 || port < 1 || port > 65535) { return NULL; // invalid port } diff --git a/src/lib/ebus/message.cpp b/src/lib/ebus/message.cpp index df5d84e9..29cf9742 100644 --- a/src/lib/ebus/message.cpp +++ b/src/lib/ebus/message.cpp @@ -37,7 +37,7 @@ Message::Message(const string clazz, const string name, const bool isWrite, const bool isPassive, const string comment, const unsigned char srcAddress, const unsigned char dstAddress, const vector id, DataField* data, - const unsigned int pollPriority) + const unsigned char pollPriority) : m_class(clazz), m_name(name), m_isWrite(isWrite), m_isPassive(isPassive), m_comment(comment), m_srcAddress(srcAddress), m_dstAddress(dstAddress), @@ -94,7 +94,7 @@ result_t Message::create(vector::iterator& it, const vector::ite result_t result; bool isWrite = false, isPassive = false; string defaultName; - unsigned int pollPriority = 0; + unsigned char pollPriority = 0; size_t defaultPos = 1; if (it == end) return RESULT_ERR_EOF; @@ -108,7 +108,7 @@ result_t Message::create(vector::iterator& it, const vector::ite } else if (strncasecmp(str, "R", 1) == 0) { // active get char last = str[len-1]; if (last >= '0' && last <= '9') { // poll priority (=active get) - pollPriority = last - '0'; + pollPriority = (unsigned char)(last - '0'); defaultName = string(str).substr(0, len - 1); // cut off priority digit } else @@ -157,7 +157,7 @@ result_t Message::create(vector::iterator& it, const vector::ite if (*str == 0) srcAddress = SYN; // no specific source else { - srcAddress = parseInt(str, 16, 0, 0xff, result); + srcAddress = (unsigned char)parseInt(str, 16, 0, 0xff, result); if (result != RESULT_OK) return result; if (!isMaster(srcAddress)) @@ -171,7 +171,7 @@ result_t Message::create(vector::iterator& it, const vector::ite if (*str == 0) dstAddress = SYN; // no specific destination else { - dstAddress = parseInt(str, 16, 0, 0xff, result); + dstAddress = (unsigned char)parseInt(str, 16, 0, 0xff, result); if (result != RESULT_OK) return result; if (!isValidAddress(dstAddress)) @@ -197,13 +197,13 @@ result_t Message::create(vector::iterator& it, const vector::ite if (input.eof()) // no more digits break; token.clear(); - token.push_back(input.get()); + token.push_back((char)input.get()); if (input.eof()) { return RESULT_ERR_INVALID_ARG; // too short hex } - token.push_back(input.get()); + token.push_back((char)input.get()); - unsigned char value = parseInt(token.c_str(), 16, 0, 0xff, result); + unsigned char value = (unsigned char)parseInt(token.c_str(), 16, 0, 0xff, result); if (result != RESULT_OK) { return result; // invalid hex value } @@ -244,6 +244,11 @@ result_t Message::create(vector::iterator& it, const vector::ite if (result != RESULT_OK) { return result; } + if (id.size() + data->getLength(pt_masterData) > 2 + MAX_POS || data->getLength(pt_slaveData) > MAX_POS) { + // max NN exceeded + delete data; + return RESULT_ERR_INVALID_POS; + } returnValue = new Message(clazz, name, isWrite, isPassive, comment, srcAddress, dstAddress, id, data, pollPriority); return RESULT_OK; } @@ -273,7 +278,7 @@ result_t Message::prepareMaster(const unsigned char srcAddress, SymbolString& ma if (result != RESULT_OK) return result; unsigned char addData = m_data->getLength(pt_masterData); - result = master.push_back(m_id.size() - 2 + addData, false, false); + result = master.push_back((unsigned char)(m_id.size() - 2 + addData), false, false); if (result != RESULT_OK) return result; for (size_t i=2; iwrite(input, pt_masterData, master, m_id.size() - 2, separator); + result = m_data->write(input, pt_masterData, master, (unsigned char)(m_id.size() - 2), separator); if (result != RESULT_OK) return result; masterData.addAll(master); @@ -308,16 +313,16 @@ result_t Message::prepareSlave(SymbolString& slaveData) result_t Message::decode(const PartType partType, SymbolString& data, ostringstream& output, bool leadingSeparator, - bool verbose, const char* filterName, + bool verbose, const char* fieldName, char fieldIndex, char separator) { unsigned char offset; if (partType == pt_masterData) - offset = m_id.size() - 2; + offset = (unsigned char)(m_id.size() - 2); else offset = 0; size_t startPos = output.str().length(); - result_t result = m_data->read(partType, data, offset, output, leadingSeparator, verbose, filterName, separator); + result_t result = m_data->read(partType, data, offset, output, leadingSeparator, verbose, fieldName, fieldIndex, separator); if (result < RESULT_OK) { return result; } @@ -331,18 +336,17 @@ result_t Message::decode(const PartType partType, SymbolString& data, result_t Message::decode(SymbolString& masterData, SymbolString& slaveData, ostringstream& output, bool leadingSeparator, - bool verbose, const char* filterName, - char separator) + bool verbose, char separator) { - unsigned char offset = m_id.size() - 2; + unsigned char offset = (unsigned char)(m_id.size() - 2); size_t startPos = output.str().length(); - result_t result = m_data->read(pt_masterData, masterData, offset, output, leadingSeparator, verbose, filterName, separator); + result_t result = m_data->read(pt_masterData, masterData, offset, output, leadingSeparator, verbose, NULL, -1, separator); if (result < RESULT_OK) { return result; } offset = 0; leadingSeparator = output.str().length() > startPos; - result = m_data->read(pt_slaveData, slaveData, offset, output, leadingSeparator, verbose, filterName, separator); + result = m_data->read(pt_slaveData, slaveData, offset, output, leadingSeparator, verbose, NULL, -1, separator); if (result < RESULT_OK) { return result; } @@ -443,7 +447,7 @@ result_t MessageMap::add(Message* message) m_messagesByName[nameKey] = message; // only store first key without class } - unsigned char idLength = message->getId().size() - 2; + unsigned char idLength = (unsigned char)(message->getId().size() - 2); if (idLength < m_minIdLength) m_minIdLength = idLength; if (idLength > m_maxIdLength) diff --git a/src/lib/ebus/message.h b/src/lib/ebus/message.h index 0b50339c..530333ed 100644 --- a/src/lib/ebus/message.h +++ b/src/lib/ebus/message.h @@ -60,7 +60,7 @@ public: const bool isPassive, const string comment, const unsigned char srcAddress, const unsigned char dstAddress, const vector id, DataField* data, - const unsigned int pollPriority); + const unsigned char pollPriority); /** * Construct a new temporary instance. @@ -183,13 +183,14 @@ public: * @param leadingSeparator whether to prepend a separator before the formatted value. * @param verbose whether to prepend the name, append the unit (if present), and append * the comment in square brackets (if present). - * @param filterName the optional name of a field to limit the output to. + * @param fieldName the optional name of a field to limit the output to. + * @param fieldIndex the optional index of the named field to limit the output to, or -1. * @param separator the separator character between multiple fields. * @return @a RESULT_OK on success, or an error code. */ result_t decode(const PartType partType, SymbolString& data, ostringstream& output, bool leadingSeparator=false, - bool verbose=false, const char* filterName=NULL, + bool verbose=false, const char* fieldName=NULL, char fieldIndex=-1, char separator=UI_FIELD_SEPARATOR); /** @@ -200,14 +201,12 @@ public: * @param leadingSeparator whether to prepend a separator before the formatted value. * @param verbose whether to prepend the name, append the unit (if present), and append * the comment in square brackets (if present). - * @param filterName the optional name of a field to limit the output to. * @param separator the separator character between multiple fields. * @return @a RESULT_OK on success, or an error code. */ result_t decode(SymbolString& masterData, SymbolString& slaveData, ostringstream& output, bool leadingSeparator=false, - bool verbose=false, const char* filterName=NULL, - char separator=UI_FIELD_SEPARATOR); + bool verbose=false, char separator=UI_FIELD_SEPARATOR); /** * Get the last decoded value. diff --git a/src/lib/ebus/symbol.cpp b/src/lib/ebus/symbol.cpp index dded2a7f..10ed9d26 100644 --- a/src/lib/ebus/symbol.cpp +++ b/src/lib/ebus/symbol.cpp @@ -66,7 +66,7 @@ result_t SymbolString::parseHex(const string& str, const bool isEscaped) for (size_t i = 0; i < str.size(); i += 2) { char* strEnd = NULL; const char* strBegin = str.substr(i, 2).c_str(); - unsigned int value = strtoul(strBegin, &strEnd, 16); + unsigned long int value = strtoul(strBegin, &strEnd, 16); if (strEnd == NULL || *strEnd != 0 || strEnd != strBegin+2 || value > 0xff) return RESULT_ERR_INVALID_NUM; // invalid value @@ -206,20 +206,20 @@ unsigned char getMasterNumber(unsigned char addr) { switch (addrLo) { case 0x0: - priority = 0; - break; - case 0x1: priority = 1; break; - case 0x3: + case 0x1: priority = 2; break; - case 0x7: + case 0x3: priority = 3; break; - case 0xF: + case 0x7: priority = 4; break; + case 0xF: + priority = 5; + break; default: return 0; } @@ -227,15 +227,15 @@ unsigned char getMasterNumber(unsigned char addr) { switch (addrHi) { case 0x0: - return 5*0 + priority + 1; + return (unsigned char)(5*0 + priority); case 0x1: - return 5*1 + priority + 2; + return (unsigned char)(5*1 + priority); case 0x3: - return 5*2 + priority + 3; + return (unsigned char)(5*2 + priority); case 0x7: - return 5*3 + priority + 4; + return (unsigned char)(5*3 + priority); case 0xF: - return 5*4 + priority + 5; + return (unsigned char)(5*4 + priority); default: return 0; } diff --git a/src/lib/ebus/test/test_message.cpp b/src/lib/ebus/test/test_message.cpp index 50bf3dbd..7bfb84ad 100644 --- a/src/lib/ebus/test/test_message.cpp +++ b/src/lib/ebus/test/test_message.cpp @@ -64,6 +64,8 @@ int main() {"u,ehp,hwTankTemp,Speichertemperatur IST,,25,B509,290000,,,IGN:2,,,,,,tempsensor", "","","","M"}, {"", "55.50;ok","1025b50903290000","050000780300","d"}, {"r,ehp,datetime,Datum Uhrzeit,,50,B504,00,,,dcfstate,,,,time,,BTI,,,,date,,BDA,,,,temp,,temp2", "valid;08:24:51;31.12.2014;-0.875", "1050b5040100", "0a035124083112031420ff", "md" }, + {"r,ehp,bad,invalid pos,,50,B5ff,000102,,m,tempsensor;tempsensor;tempsensor;tempsensor;power;power,,,", "", "", "", "c" }, + {"r,ehp,bad,invalid pos,,50,B5ff,,,s,tempsensor;tempsensor;tempsensor;tempsensor;tempsensor;power;power,,,", "", "", "", "c" }, }; DataFieldTemplates* templates = new DataFieldTemplates(); MessageMap* messages = new MessageMap(); diff --git a/src/lib/utils/Makefile.am b/src/lib/utils/Makefile.am index 41c74a4c..6edc3ed4 100644 --- a/src/lib/utils/Makefile.am +++ b/src/lib/utils/Makefile.am @@ -1,6 +1,7 @@ AM_CXXFLAGS = -fpic \ -Wall \ - -Wextra + -Wextra \ + -Wconversion noinst_LIBRARIES = libutils.a diff --git a/src/lib/utils/tcpsocket.cpp b/src/lib/utils/tcpsocket.cpp index 0d1c119b..06eadeaf 100644 --- a/src/lib/utils/tcpsocket.cpp +++ b/src/lib/utils/tcpsocket.cpp @@ -29,7 +29,7 @@ using namespace std; TCPSocket::TCPSocket(int sfd, struct sockaddr_in* address) : m_sfd(sfd) { char ip[17]; - inet_ntop(AF_INET, (struct in_addr*)&(address->sin_addr.s_addr), ip, sizeof(ip)-1); + inet_ntop(AF_INET, (struct in_addr*)&(address->sin_addr.s_addr), ip, (socklen_t)sizeof(ip)-1); m_ip = ip; m_port = ntohs(address->sin_port); } diff --git a/src/tools/ebusctl.cpp b/src/tools/ebusctl.cpp index 48ba81a3..94ee51b8 100644 --- a/src/tools/ebusctl.cpp +++ b/src/tools/ebusctl.cpp @@ -40,10 +40,10 @@ using namespace std; struct options { const char* server; //!< ebusd server host (name or ip) [localhost] - int port; //!< ebusd server port [8888] + unsigned int port; //!< ebusd server port [8888] char* const *args; //!< arguments to pass to ebusd - int argCount; //!< number of arguments to pass to ebusd + unsigned int argCount; //!< number of arguments to pass to ebusd }; /** the program options. */ @@ -100,7 +100,7 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) opt->server = arg; break; case 'p': // --port=8888 - opt->port = strtol(arg, &strEnd, 10); + opt->port = (unsigned int)strtoul(arg, &strEnd, 10); if (strEnd == NULL || *strEnd != 0 || opt->port < 1 || opt->port > 65535) { argp_error(state, "invalid port"); return EINVAL; diff --git a/src/tools/ebusfeed.cpp b/src/tools/ebusfeed.cpp index c4d096fb..4ff8ea47 100644 --- a/src/tools/ebusfeed.cpp +++ b/src/tools/ebusfeed.cpp @@ -37,7 +37,7 @@ using namespace std; struct options { const char* device; //!< device to write to [/dev/ttyUSB60] - int time; //!< delay between bytes in us [10000] + unsigned int time; //!< delay between bytes in us [10000] const char* dumpFile; //!< dump file to read }; @@ -67,7 +67,7 @@ static const char argpdoc[] = " 2. create symbol links to appropriate devices, e.g.\n" " 'ln -s /dev/pts/2 /dev/ttyUSB60'\n" " 'ln -s /dev/pts/3 /dev/ttyUSB20'\n" - " 3. start "PACKAGE": '"PACKAGE" -f -d /dev/ttyUSB20'\n" + " 3. start "PACKAGE": '"PACKAGE" -f -d /dev/ttyUSB20 --nodevicecheck'\n" " 4. start ebusfeed: 'ebusfeed /path/to/ebus_dump.bin'\n"; /** the description of the accepted arguments. */ @@ -101,7 +101,7 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) opt->device = arg; break; case 't': // --time=10000 - opt->time = strtol(arg, &strEnd, 10); + opt->time = (unsigned int)strtoul(arg, &strEnd, 10); if (strEnd == NULL || *strEnd != 0 || opt->time < 1000 || opt->time > 100000000) { argp_error(state, "invalid time"); return EINVAL; @@ -131,7 +131,7 @@ int main(int argc, char* argv[]) if (argp_parse(&argp, argc, argv, ARGP_IN_ORDER, NULL, &opt) != 0) return EINVAL; - Device* device = Device::create(opt.device, true, NULL); + Device* device = Device::create(opt.device, false, NULL); if (device == NULL) { cout << "unable to create device " << opt.device << endl; return EINVAL; @@ -150,7 +150,7 @@ int main(int argc, char* argv[]) if (file.is_open()) { while (true) { - unsigned char byte = file.get(); + unsigned char byte = (unsigned char)file.get(); if (file.eof()) break; cout << hex << setw(2) << setfill('0')