From bc84dd389f8fd0772606746df2cfc29fa18b8667 Mon Sep 17 00:00:00 2001 From: john30 Date: Sun, 3 Jan 2016 18:55:45 +0100 Subject: [PATCH] added special length '*' for consuming remaining input --- src/lib/ebus/data.cpp | 226 ++++++++++++++++++-------------- src/lib/ebus/data.h | 40 ++++-- src/lib/ebus/message.cpp | 16 ++- src/lib/ebus/test/test_data.cpp | 4 + 4 files changed, 168 insertions(+), 118 deletions(-) diff --git a/src/lib/ebus/data.cpp b/src/lib/ebus/data.cpp index 10aee0a9..b444990d 100644 --- a/src/lib/ebus/data.cpp +++ b/src/lib/ebus/data.cpp @@ -312,7 +312,9 @@ result_t DataField::create(vector::iterator& it, size_t pos = token.find(LENGTH_SEPARATOR); if (pos == string::npos) length = 0; // no length specified - else { + else if (pos+2==token.length() && token[pos+1]=='*') { + length = REMAIN_LEN; + } else { length = (unsigned char)parseInt(token.substr(pos+1).c_str(), 10, 1, maxFieldLength, result); if (result != RESULT_OK) break; @@ -367,81 +369,82 @@ result_t SingleDataField::create(const char* typeNameStr, const unsigned char le { for (size_t i = 0; i < sizeof(dataTypes) / sizeof(dataType_t); i++) { // TODO use a map const dataType_t* dataType = &dataTypes[i]; - if (strcasecmp(typeNameStr, dataType->name) == 0) { - unsigned char bitCount = dataType->bitCount; - unsigned char byteCount = (unsigned char)((bitCount + 7) / 8); - if ((dataType->flags & ADJ) != 0) { // adjustable length - if ((bitCount % 8) != 0) { - if (length == 0) - bitCount = 1; // default bit count: 1 bit - else if (length <= bitCount) - bitCount = length; - else - return RESULT_ERR_OUT_OF_RANGE; // invalid length + if (strcasecmp(typeNameStr, dataType->name) != 0) + continue; - byteCount = (unsigned char)((bitCount + 7) / 8); - } - else if (length == 0) - byteCount = 1; //default byte count: 1 byte - else if (length <= byteCount) - byteCount = length; + unsigned char bitCount = dataType->bitCount; + unsigned char byteCount = (unsigned char)((bitCount + 7) / 8); + if ((dataType->flags & ADJ) != 0) { // adjustable length + if ((bitCount % 8) != 0) { + if (length == 0) + bitCount = 1; // default bit count: 1 bit + else if (length <= bitCount) + bitCount = length; else return RESULT_ERR_OUT_OF_RANGE; // invalid length + + byteCount = (unsigned char)((bitCount + 7) / 8); } - else if (length > 0 && length != byteCount) - continue; // check for another one with same name but different length + else if (length == 0) + byteCount = 1; //default byte count: 1 byte + else if (length <= byteCount || length == REMAIN_LEN) + byteCount = length; + else + return RESULT_ERR_OUT_OF_RANGE; // invalid length + } + else if (length > 0 && length != byteCount) + continue; // check for another one with same name but different length - switch (dataType->type) - { - case bt_str: - case bt_hexstr: - case bt_dat: - case bt_tim: - if (divisor != 0 || !values.empty()) - return RESULT_ERR_INVALID_ARG; // cannot set divisor or values for string field - returnField = new StringDataField(name, comment, unit, *dataType, partType, byteCount); - return RESULT_OK; - case bt_num: - if (values.empty() && (dataType->flags & DAY) != 0) { - for (unsigned int i = 0; i < sizeof(dayNames) / sizeof(dayNames[0]); i++) - values[dataType->minValue + i] = dayNames[i]; + switch (dataType->type) + { + case bt_str: + case bt_hexstr: + case bt_dat: + case bt_tim: + if (divisor != 0 || !values.empty()) + return RESULT_ERR_INVALID_ARG; // cannot set divisor or values for string field + returnField = new StringDataField(name, comment, unit, *dataType, partType, byteCount); + return RESULT_OK; + case bt_num: + if (values.empty() && (dataType->flags & DAY) != 0) { + for (unsigned int i = 0; i < sizeof(dayNames) / sizeof(dayNames[0]); i++) + values[dataType->minValue + i] = dayNames[i]; + } + if (values.empty() || (dataType->flags & LST) == 0) { + if (divisor == 0) + divisor = 1; + + if ((dataType->bitCount % 8) == 0) { + if (divisor < 0) { + if (dataType->divisorOrFirstBit > 1) + return RESULT_ERR_INVALID_ARG; + + if (dataType->divisorOrFirstBit < 0) + divisor *= -dataType->divisorOrFirstBit; + } else if (dataType->divisorOrFirstBit < 0) { + if (divisor > 1) + return RESULT_ERR_INVALID_ARG; + + if (divisor < 0) + divisor *= -dataType->divisorOrFirstBit; + } else + divisor *= dataType->divisorOrFirstBit; + + if (-MAX_DIVISOR > divisor || divisor > MAX_DIVISOR) + return RESULT_ERR_OUT_OF_RANGE; } - if (values.empty() || (dataType->flags & LST) == 0) { - if (divisor == 0) - divisor = 1; - if ((dataType->bitCount % 8) == 0) { - if (divisor < 0) { - if (dataType->divisorOrFirstBit > 1) - return RESULT_ERR_INVALID_ARG; - - if (dataType->divisorOrFirstBit < 0) - divisor *= -dataType->divisorOrFirstBit; - } else if (dataType->divisorOrFirstBit < 0) { - if (divisor > 1) - return RESULT_ERR_INVALID_ARG; - - if (divisor < 0) - divisor *= -dataType->divisorOrFirstBit; - } else - divisor *= dataType->divisorOrFirstBit; - - if (-MAX_DIVISOR > divisor || divisor > MAX_DIVISOR) - return RESULT_ERR_OUT_OF_RANGE; - } - - returnField = new NumberDataField(name, comment, unit, *dataType, partType, byteCount, bitCount, divisor); - return RESULT_OK; - } - if (values.begin()->first < dataType->minValue || values.rbegin()->first > dataType->maxValue) - return RESULT_ERR_OUT_OF_RANGE; - - if (divisor != 0) - return RESULT_ERR_INVALID_ARG; // cannot use divisor != 1 for value list field - //TODO add special field for fixed values (exactly one value in the list of values) - returnField = new ValueListDataField(name, comment, unit, *dataType, partType, byteCount, bitCount, values); + returnField = new NumberDataField(name, comment, unit, *dataType, partType, byteCount, bitCount, divisor); return RESULT_OK; } + if (values.begin()->first < dataType->minValue || values.rbegin()->first > dataType->maxValue) + return RESULT_ERR_OUT_OF_RANGE; + + if (divisor != 0) + return RESULT_ERR_INVALID_ARG; // cannot use divisor != 1 for value list field + //TODO add special field for fixed values (exactly one value in the list of values) + returnField = new ValueListDataField(name, comment, unit, *dataType, partType, byteCount, bitCount, values); + return RESULT_OK; } } return RESULT_ERR_NOTFOUND; @@ -479,7 +482,8 @@ result_t SingleDataField::read(const PartType partType, return RESULT_ERR_INVALID_PART; } if (isIgnored() || (fieldName != NULL && (m_name != fieldName || fieldIndex > 0))) { - if (offset + m_length > data.size()) { + bool remainder = m_length==REMAIN_LEN && (m_dataType.flags & ADJ)!=0; + if (!remainder && offset + m_length > data.size()) { return RESULT_ERR_INVALID_POS; } return RESULT_EMPTY; @@ -507,7 +511,8 @@ result_t SingleDataField::read(const PartType partType, return RESULT_ERR_INVALID_PART; } if (isIgnored() || (fieldName != NULL && (m_name != fieldName || fieldIndex > 0))) { - if (offset + m_length > data.size()) { + bool remainder = m_length==REMAIN_LEN && (m_dataType.flags & ADJ)!=0; + if (!remainder && offset + m_length > data.size()) { return RESULT_ERR_INVALID_POS; } return RESULT_EMPTY; @@ -552,7 +557,7 @@ result_t SingleDataField::read(const PartType partType, result_t SingleDataField::write(istringstream& input, const PartType partType, SymbolString& data, - unsigned char offset, char separator) + unsigned char offset, char separator, unsigned char* length) { if (partType != m_partType) return RESULT_OK; @@ -568,7 +573,7 @@ result_t SingleDataField::write(istringstream& input, default: return RESULT_ERR_INVALID_PART; } - return writeSymbols(input, offset, data); + return writeSymbols(input, offset, data, length); } StringDataField* StringDataField::clone() @@ -605,8 +610,12 @@ bool StringDataField::hasField(const char* fieldName, bool numeric) void StringDataField::dump(ostream& output) { SingleDataField::dump(output); - if ((m_dataType.flags & ADJ) != 0) - output << ":" << static_cast(m_length); + if ((m_dataType.flags & ADJ) != 0) { + if (m_length==REMAIN_LEN) + output << ":*"; + else + output << ":" << static_cast(m_length); + } output << FIELD_SEPARATOR; // no value list, no divisor dumpString(output, m_unit); dumpString(output, m_comment); @@ -623,8 +632,9 @@ result_t StringDataField::readSymbols(SymbolString& input, const unsigned char b size_t start = 0, count = m_length; int incr = 1; unsigned char ch, last = 0, hour = 0; - - if (baseOffset + m_length > input.size()) { + if (count==REMAIN_LEN && input.size()>baseOffset) { + count = input.size()-baseOffset; + } else if (baseOffset + count > input.size()) { return RESULT_ERR_INVALID_POS; } if ((m_dataType.flags & REV) != 0) { // reverted binary representation (most significant byte first) @@ -714,9 +724,10 @@ result_t StringDataField::readSymbols(SymbolString& input, const unsigned char b } result_t StringDataField::writeSymbols(istringstream& input, - unsigned char baseOffset, SymbolString& output) + unsigned char baseOffset, SymbolString& output, unsigned char* length) { size_t start = 0, count = m_length; + bool remainder = count==REMAIN_LEN && (m_dataType.flags & ADJ)!=0; int incr = 1; unsigned int value = 0, last = 0, lastLast = 0; string token; @@ -725,11 +736,15 @@ result_t StringDataField::writeSymbols(istringstream& input, start = m_length - 1; incr = -1; } - if (isIgnored() && (m_dataType.flags & REQ) == 0) { + if (remainder) { + count = 1; + } for (size_t offset = start, i = 0; i < count; offset += incr, i++) { output[baseOffset + offset] = (unsigned char)m_dataType.replacement; // fill up with replacement } + if (length!=NULL) + *length = (unsigned char)count; return RESULT_OK; } result_t result; @@ -740,9 +755,9 @@ result_t StringDataField::writeSymbols(istringstream& input, case bt_hexstr: while (!input.eof() && input.peek() == ' ') input.get(); - if (input.eof()) // no more digits + if (input.eof()) { // no more digits value = m_dataType.replacement; // fill up with replacement - else { + } else { token.clear(); token.push_back((unsigned char)input.get()); if (input.eof()) @@ -841,6 +856,10 @@ result_t StringDataField::writeSymbols(istringstream& input, } break; } + if (remainder && input.eof() && i > 0) { + count = (offset-start)*incr; + break; + } lastLast = last; last = value; if ((m_dataType.flags & BCD) != 0 && ((m_dataType.flags & REQ) != 0 || value != m_dataType.replacement)) { @@ -853,9 +872,10 @@ result_t StringDataField::writeSymbols(istringstream& input, output[baseOffset + offset] = (unsigned char)value; } - if (i < m_length) + if (!remainder && i < m_length) // TODO check with bt_tim and m_length == 1 return RESULT_ERR_EOF; // input too short - + if (length!=NULL) + *length = (unsigned char)count; return RESULT_OK; } @@ -932,7 +952,7 @@ result_t NumericDataField::readRawValue(SymbolString& input, } result_t NumericDataField::writeRawValue(unsigned int value, - unsigned char baseOffset, SymbolString& output) + unsigned char baseOffset, SymbolString& output, unsigned char* length) { size_t start = 0, count = m_length; int incr = 1; @@ -968,7 +988,8 @@ result_t NumericDataField::writeRawValue(unsigned int value, else output[baseOffset + offset] = ch; } - + if (length!=NULL) + *length = m_length; return RESULT_OK; } @@ -1109,7 +1130,7 @@ result_t NumberDataField::readSymbols(SymbolString& input, const unsigned char b } result_t NumberDataField::writeSymbols(istringstream& input, - unsigned char baseOffset, SymbolString& output) + unsigned char baseOffset, SymbolString& output, unsigned char* length) { unsigned int value; @@ -1168,7 +1189,7 @@ result_t NumberDataField::writeSymbols(istringstream& input, return RESULT_ERR_OUT_OF_RANGE; // value out of range } - return writeRawValue(value, baseOffset, output); + return writeRawValue(value, baseOffset, output, length); } @@ -1250,19 +1271,19 @@ result_t ValueListDataField::readSymbols(SymbolString& input, const unsigned cha } result_t ValueListDataField::writeSymbols(istringstream& input, - unsigned char baseOffset, SymbolString& output) + unsigned char baseOffset, SymbolString& output, unsigned char* length) { if (isIgnored()) - return writeRawValue(m_dataType.replacement, baseOffset, output); // replacement value + return writeRawValue(m_dataType.replacement, baseOffset, output, length); // replacement value const char* str = input.str().c_str(); for (map::iterator it = m_values.begin(); it != m_values.end(); it++) if (it->second.compare(str) == 0) - return writeRawValue(it->first, baseOffset, output); + return writeRawValue(it->first, baseOffset, output, length); if (strcasecmp(str, NULL_VALUE) == 0) - return writeRawValue(m_dataType.replacement, baseOffset, output); // replacement value + return writeRawValue(m_dataType.replacement, baseOffset, output, length); // replacement value char* strEnd = NULL; // fall back to raw value in input unsigned int value; @@ -1270,7 +1291,7 @@ result_t ValueListDataField::writeSymbols(istringstream& input, if (strEnd == NULL || strEnd == str || (*strEnd != 0 && *strEnd != '.')) return RESULT_ERR_INVALID_NUM; // invalid value if (m_values.find(value) != m_values.end()) - return writeRawValue(value, baseOffset, output); + return writeRawValue(value, baseOffset, output, length); return RESULT_ERR_NOTFOUND; // value assignment not found } @@ -1334,7 +1355,7 @@ DataFieldSet* DataFieldSet::clone() return new DataFieldSet(m_name, m_comment, fields); } -unsigned char DataFieldSet::getLength(PartType partType) +unsigned char DataFieldSet::getLength(PartType partType, unsigned char maxLength) { unsigned char length = 0; @@ -1346,7 +1367,12 @@ unsigned char DataFieldSet::getLength(PartType partType) if (!previousFullByteOffset[partType] && !field->hasFullByteOffset(false)) length--; - length = (unsigned char)(length + field->getLength(partType)); + unsigned char fieldLength = field->getLength(partType, maxLength); + if (fieldLength>=maxLength) + maxLength = 0; + else + maxLength = (unsigned char)(maxLength-fieldLength); + length = (unsigned char)(length + fieldLength); previousFullByteOffset[partType] = field->hasFullByteOffset(true); } @@ -1413,7 +1439,7 @@ result_t DataFieldSet::read(const PartType partType, if (result < RESULT_OK) return result; - offset = (unsigned char)(offset + field->getLength(partType)); + offset = (unsigned char)(offset + field->getLength(partType, (unsigned char)(data.size()-offset))); previousFullByteOffset = field->hasFullByteOffset(true); if (result != RESULT_EMPTY) { found = true; @@ -1458,7 +1484,7 @@ result_t DataFieldSet::read(const PartType partType, if (result < RESULT_OK) return result; - offset = (unsigned char)(offset + field->getLength(partType)); + offset = (unsigned char)(offset + field->getLength(partType, (unsigned char)(data.size()-offset))); previousFullByteOffset = field->hasFullByteOffset(true); if (result != RESULT_EMPTY) { found = true; @@ -1491,11 +1517,12 @@ result_t DataFieldSet::read(const PartType partType, result_t DataFieldSet::write(istringstream& input, const PartType partType, SymbolString& data, - unsigned char offset, char separator) + unsigned char offset, char separator, unsigned char* length) { string token; bool previousFullByteOffset = true; + unsigned char baseOffset = offset; for (vector::iterator it = m_fields.begin(); it < m_fields.end(); it++) { SingleDataField* field = *it; if (partType != pt_any && field->getPartType() != partType) @@ -1505,6 +1532,7 @@ result_t DataFieldSet::write(istringstream& input, offset--; result_t result; + unsigned char fieldLength; if (m_fields.size() > 1) { if (field->isIgnored()) token.clear(); @@ -1512,18 +1540,20 @@ result_t DataFieldSet::write(istringstream& input, token.clear(); istringstream single(token); - result = (*it)->write(single, partType, data, offset, separator); + result = (*it)->write(single, partType, data, offset, separator, &fieldLength); } else - result = (*it)->write(input, partType, data, offset, separator); + result = (*it)->write(input, partType, data, offset, separator, &fieldLength); if (result != RESULT_OK) return result; - offset = (unsigned char)(offset + field->getLength(partType)); + offset = (unsigned char)(offset+fieldLength); previousFullByteOffset = field->hasFullByteOffset(true); } + if (length!=NULL) + *length = (unsigned char)(offset-baseOffset); return RESULT_OK; } diff --git a/src/lib/ebus/data.h b/src/lib/ebus/data.h index 9082f64e..7b66e96a 100644 --- a/src/lib/ebus/data.h +++ b/src/lib/ebus/data.h @@ -126,6 +126,9 @@ typedef struct dataType_s { /** the maximum allowed field length. */ #define MAX_LEN 31 +/** the field length indicating remainder of input. */ +#define REMAIN_LEN 255 + /** * Parse an unsigned int value. * @param str the string to parse. @@ -222,9 +225,10 @@ public: /** * Returns the length of this field (or contained fields) in bytes. * @param partType the message part of the contained fields to limit the length calculation to. + * @param maxLength the maximum length for calculating remainder of input. * @return the length of this field (or contained fields) in bytes. */ - virtual unsigned char getLength(PartType partType) = 0; + virtual unsigned char getLength(PartType partType, unsigned char maxLength=MAX_LEN) = 0; /** * Derive a new @a DataField from this field. @@ -312,11 +316,12 @@ public: * @param data the unescaped data @a SymbolString for writing binary data. * @param offset the additional offset to add for writing binary data. * @param separator the separator character between multiple fields. + * @param length the variable in which to store the used length in bytes, or NULL. * @return @a RESULT_OK on success, or an error code. */ virtual result_t write(istringstream& input, const PartType partType, SymbolString& data, - unsigned char offset, char separator=UI_FIELD_SEPARATOR) = 0; + unsigned char offset, char separator=UI_FIELD_SEPARATOR, unsigned char* length=NULL) = 0; protected: @@ -363,7 +368,7 @@ public: /** * Factory method for creating a new @a SingleDataField instance derived from a base type. * @param typeNameStr the base type name string. - * @param length the base type length, or 0 for default. + * @param length the base type length, or 0 for default, or @a REMAIN_LEN for remainder within same message part. * @param name the field name. * @param comment the field comment. * @param unit the value unit. @@ -398,8 +403,13 @@ public: PartType getPartType() const { return m_partType; } // @copydoc - virtual unsigned char getLength(PartType partType) { return partType == m_partType ? m_length : (unsigned char)0; }; - // re-use same position as previous field as not all bits of fully consumed yet + virtual unsigned char getLength(PartType partType, unsigned char maxLength=MAX_LEN) { + if (partType != m_partType) { + return (unsigned char)0; + } + bool remainder = m_length==REMAIN_LEN && (m_dataType.flags & ADJ)!=0; + return remainder ? maxLength : m_length; + } /** * Get whether this field uses a full byte offset. @@ -426,7 +436,7 @@ public: // @copydoc virtual result_t write(istringstream& input, const PartType partType, SymbolString& data, - unsigned char offset, char separator=UI_FIELD_SEPARATOR); + unsigned char offset, char separator=UI_FIELD_SEPARATOR, unsigned char* length=NULL); protected: @@ -455,9 +465,10 @@ protected: * @param input the @a istringstream to parse the formatted value from. * @param offset the offset in the @a SymbolString. * @param output the unescaped @a SymbolString to write the binary value to. + * @param length the variable in which to store the used length in bytes, or NULL. * @return @a RESULT_OK on success, or an error code. */ - virtual result_t writeSymbols(istringstream& input, const unsigned char offset, SymbolString& output) = 0; + virtual result_t writeSymbols(istringstream& input, const unsigned char offset, SymbolString& output, unsigned char* length) = 0; protected: @@ -490,7 +501,7 @@ public: * @param unit the value unit. * @param dataType the data type definition. * @param partType the message part in which the field is stored. - * @param length the number of symbols in the message part in which the field is stored. + * @param length the number of symbols in the message part in which the field is stored, or @a REMAIN_LEN for remainder within same message part. */ StringDataField(const string name, const string comment, const string unit, const dataType_t dataType, const PartType partType, @@ -527,7 +538,7 @@ protected: ostringstream& output, OutputFormat outputFormat); // @copydoc - virtual result_t writeSymbols(istringstream& input, const unsigned char offset, SymbolString& output); + virtual result_t writeSymbols(istringstream& input, const unsigned char offset, SymbolString& output, unsigned char* length); }; @@ -583,9 +594,10 @@ protected: * @param value the raw value to write. * @param offset the offset in the @a SymbolString. * @param output the unescaped @a SymbolString to write the binary value to. + * @param length the variable in which to store the used length in bytes, or NULL. * @return @a RESULT_OK on success, or an error code. */ - result_t writeRawValue(unsigned int value, const unsigned char offset, SymbolString& output); + result_t writeRawValue(unsigned int value, const unsigned char offset, SymbolString& output, unsigned char* length=NULL); /** the number of bits in the binary value. */ const unsigned char m_bitCount; @@ -643,7 +655,7 @@ protected: ostringstream& output, OutputFormat outputFormat); // @copydoc - virtual result_t writeSymbols(istringstream& input, const unsigned char offset, SymbolString& output); + virtual result_t writeSymbols(istringstream& input, const unsigned char offset, SymbolString& output, unsigned char* length); private: @@ -706,7 +718,7 @@ protected: ostringstream& output, OutputFormat outputFormat); // @copydoc - virtual result_t writeSymbols(istringstream& input, const unsigned char offset, SymbolString& output); + virtual result_t writeSymbols(istringstream& input, const unsigned char offset, SymbolString& output, unsigned char* length); private: @@ -768,7 +780,7 @@ public: virtual DataFieldSet* clone(); // @copydoc - virtual unsigned char getLength(PartType partType); + virtual unsigned char getLength(PartType partType, unsigned char maxLength=MAX_LEN); // @copydoc virtual result_t derive(string name, string comment, @@ -816,7 +828,7 @@ public: // @copydoc virtual result_t write(istringstream& input, const PartType partType, SymbolString& data, - unsigned char offset, char separator=UI_FIELD_SEPARATOR); + unsigned char offset, char separator=UI_FIELD_SEPARATOR, unsigned char* length=NULL); private: diff --git a/src/lib/ebus/message.cpp b/src/lib/ebus/message.cpp index e23b82aa..da27496e 100644 --- a/src/lib/ebus/message.cpp +++ b/src/lib/ebus/message.cpp @@ -353,7 +353,7 @@ result_t Message::create(vector::iterator& it, const vector::ite return result; } } - if (id.size() + data->getLength(pt_masterData) > 2 + maxLength || data->getLength(pt_slaveData) > maxLength) { + if (id.size() + data->getLength(pt_masterData, (unsigned char)maxLength) > 2 + maxLength || data->getLength(pt_slaveData, (unsigned char)maxLength) > maxLength) { // max NN exceeded delete data; return RESULT_ERR_INVALID_POS; @@ -515,8 +515,8 @@ result_t Message::prepareMasterPart(SymbolString& master, istringstream& input, { if (index!=0) return RESULT_ERR_NOTFOUND; - unsigned char addData = m_data->getLength(pt_masterData); - result_t result = master.push_back((unsigned char)(getIdLength() + addData), false, false); + unsigned char pos = master.size(); + result_t result = master.push_back(0, false, false); // length, will be set later if (result != RESULT_OK) return result; for (size_t i = 2; i < m_id.size(); i++) { @@ -524,7 +524,11 @@ result_t Message::prepareMasterPart(SymbolString& master, istringstream& input, if (result != RESULT_OK) return result; } - return m_data->write(input, pt_masterData, master, getIdLength(), separator); + result = m_data->write(input, pt_masterData, master, getIdLength(), separator); + if (result != RESULT_OK) + return result; + master[pos] = (unsigned char)(master.size()-pos-1); + return result; } result_t Message::prepareSlave(istringstream& input, SymbolString& slaveData) @@ -533,13 +537,13 @@ result_t Message::prepareSlave(istringstream& input, SymbolString& slaveData) return RESULT_ERR_INVALID_ARG; // prepare not possible SymbolString slave(false); - unsigned char addData = m_data->getLength(pt_slaveData); - result_t result = slave.push_back(addData, false, false); + result_t result = slave.push_back(0, false, false); // length, will be set later if (result != RESULT_OK) return result; result = m_data->write(input, pt_slaveData, slave, 0); if (result != RESULT_OK) return result; + slave[0] = (unsigned char)(slave.size()-1); time(&m_lastUpdateTime); if (slave != m_lastSlaveData) { m_lastChangeTime = m_lastUpdateTime; diff --git a/src/lib/ebus/test/test_data.cpp b/src/lib/ebus/test/test_data.cpp index c896178a..4a48b6c0 100644 --- a/src/lib/ebus/test/test_data.cpp +++ b/src/lib/ebus/test/test_data.cpp @@ -46,16 +46,20 @@ int main() // entry: definition, decoded value, master data, slave data, flags // definition: name,part,type[:len][,[divisor|values][,[unit][,[comment]]]] {"x,,ign:10", "", "10fe07000a00000000000000000000", "00", ""}, + {"x,,ign:*", "", "10fe07000a00000000000000000000", "00", "W"}, {"x,,ign,2", "", "", "", "c"}, {"x,,str:10", "Hallo, Du!", "10fe07000a48616c6c6f2c20447521", "00", ""}, {"x,,str:10", "Hallo, Du!", "10fe07000a48616c6c6f2c20447521", "00", ""}, {"x,,str:10", "Hallo, Du ", "10fe07000a48616c6c6f2c20447520", "00", ""}, {"x,,str:10", " ", "10fe07000a20202020202020202020", "00", ""}, + {"x,,str:10", " ", "10fe07000a20202020202020202020", "00", ""}, {"x,,str:11", "", "10fe07000a20202020202020202020", "00", "rW"}, {"x,,str:24", "abcdefghijklmnopqrstuvwx", "10fe0700186162636465666768696a6b6c6d6e6f707172737475767778", "00", ""}, + {"x,,str:*", "abcde", "10fe0700056162636465", "00", ""}, {"x,,str,2", "", "", "", "c"}, {"x,,hex", "20", "10fe07000120", "00", ""}, {"x,,hex:10", "48 61 6c 6c 6f 2c 20 44 75 21", "10fe07000a48616c6c6f2c20447521", "00", ""}, + {"x,,hex:*", "48 61 6c 6c 6f", "10fe07000548616c6c6f", "00", ""}, {"x,,hex:11", "", "10fe07000a48616c6c6f2c20447521", "00", "rW"}, {"x,,hex,2", "", "", "", "c"}, {"x,,bda", "26.10.2014","10fe07000426100614", "00", ""}, // Sunday