diff --git a/src/lib/ebus/data.cpp b/src/lib/ebus/data.cpp index 5e5dfc3e..66208632 100644 --- a/src/lib/ebus/data.cpp +++ b/src/lib/ebus/data.cpp @@ -33,7 +33,7 @@ static const dataType_t stringDataType = { }; static const dataType_t pinDataType = { - "PIN", 16, bt_num, FIX|BCD|REV, 0xffff, 0, 0x9999, 1, 0 // unsigned decimal in BCD, 0000 - 9999 (fixed length) + "PIN", 16, bt_num, FIX|BCD|REV|REQ, 0xffff, 0, 0x9999, 1, 0 // unsigned decimal in BCD, 0000 - 9999 (fixed length) }; static const dataType_t uchDataType = { @@ -49,10 +49,10 @@ static const dataType_t dataTypes[] = { {"BDA", 24, bt_dat, BCD, 0, 10, 10, 0, 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, 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)) {"HDA", 24, bt_dat, 0, 0, 10, 10, 0, 0}, // date, 01.01.2000 - 31.12.2099 (0x01,0x01,0x00 - 0x1f,0x0c,0x63) - {"BTI", 24, bt_tim, BCD|REV, 0, 8, 8, 0, 0}, // time in BCD, 00:00:00 - 23:59:59 (0x00,0x00,0x00 - 0x59,0x59,0x23) - {"HTI", 24, bt_tim, 0, 0, 8, 8, 0, 0}, // time, 00:00:00 - 23:59:59 (0x00,0x00,0x00 - 0x17,0x3b,0x3b) + {"BTI", 24, bt_tim, BCD|REV|REQ, 0, 8, 8, 0, 0}, // time in BCD, 00:00:00 - 23:59:59 (0x00,0x00,0x00 - 0x59,0x59,0x23) + {"HTI", 24, bt_tim, REQ, 0, 8, 8, 0, 0}, // time, 00:00:00 - 23:59:59 (0x00,0x00,0x00 - 0x17,0x3b,0x3b) {"VTI", 24, bt_tim, REV, 0x63, 8, 8, 0, 0}, // time, 00:00:00 - 23:59:59 (0x00,0x00,0x00 - 0x3b,0x3b,0x17, replacement 0x63) [Vaillant type] - {"HTM", 16, bt_tim, 0, 0, 5, 5, 0, 0}, // time as hh:mm, 00:00 - 23:59 (0x00,0x00 - 0x17,0x3b) + {"HTM", 16, bt_tim, REQ, 0, 5, 5, 0, 0}, // time as hh:mm, 00:00 - 23:59 (0x00,0x00 - 0x17,0x3b) {"TTM", 8, bt_tim, 0, 0x90, 5, 5, 0, 0}, // truncated time (only multiple of 10 minutes), 00:00 - 24:00 (minutes div 10 + hour * 6 as integer) {"BDY", 8, bt_num, DAY|LST, 0x07, 0, 6, 1, 0}, // weekday, "Mon" - "Sun" (0x00 - 0x06) [ebus type] {"HDY", 8, bt_num, DAY|LST, 0x00, 1, 7, 1, 0}, // weekday, "Mon" - "Sun" (0x01 - 0x07) [Vaillant type] @@ -72,14 +72,14 @@ static const dataType_t dataTypes[] = { {"D2C", 16, bt_num, SIG, 0x8000, 0x8001, 0x7fff, 16, 2}, // signed number (fraction 1/16), -2047.9 - +2047.9 {"ULG", 32, bt_num, LST, 0xffffffff, 0, 0xfffffffe, 1, 0}, // unsigned integer, 0 - 4294967294 {"SLG", 32, bt_num, SIG, 0x80000000, 0x80000001, 0xffffffff, 1, 0}, // signed integer, -2147483647 - +2147483647 - {"BI0", 7, bt_num, ADJ|LST, 0, 0, 0xef, 1, 0}, // bit 0 (up to 7 bits until bit 6) - {"BI1", 7, bt_num, ADJ|LST, 0, 0, 0x7f, 1, 1}, // bit 1 (up to 7 bits until bit 7) - {"BI2", 6, bt_num, ADJ|LST, 0, 0, 0x3f, 1, 2}, // bit 2 (up to 6 bits until bit 7) - {"BI3", 5, bt_num, ADJ|LST, 0, 0, 0x1f, 1, 3}, // bit 3 (up to 5 bits until bit 7) - {"BI4", 4, bt_num, ADJ|LST, 0, 0, 0x0f, 1, 4}, // bit 4 (up to 4 bits until bit 7) - {"BI5", 3, bt_num, ADJ|LST, 0, 0, 0x07, 1, 5}, // bit 5 (up to 3 bits until bit 7) - {"BI6", 2, bt_num, ADJ|LST, 0, 0, 0x03, 1, 6}, // bit 6 (up to 2 bits until bit 7) - {"BI7", 1, bt_num, ADJ|LST, 0, 0, 0x01, 1, 7}, // bit 7 + {"BI0", 7, bt_num, ADJ|LST|REQ, 0, 0, 0xef, 1, 0}, // bit 0 (up to 7 bits until bit 6) + {"BI1", 7, bt_num, ADJ|LST|REQ, 0, 0, 0x7f, 1, 1}, // bit 1 (up to 7 bits until bit 7) + {"BI2", 6, bt_num, ADJ|LST|REQ, 0, 0, 0x3f, 1, 2}, // bit 2 (up to 6 bits until bit 7) + {"BI3", 5, bt_num, ADJ|LST|REQ, 0, 0, 0x1f, 1, 3}, // bit 3 (up to 5 bits until bit 7) + {"BI4", 4, bt_num, ADJ|LST|REQ, 0, 0, 0x0f, 1, 4}, // bit 4 (up to 4 bits until bit 7) + {"BI5", 3, bt_num, ADJ|LST|REQ, 0, 0, 0x07, 1, 5}, // bit 5 (up to 3 bits until bit 7) + {"BI6", 2, bt_num, ADJ|LST|REQ, 0, 0, 0x03, 1, 6}, // bit 6 (up to 2 bits until bit 7) + {"BI7", 1, bt_num, ADJ|LST|REQ, 0, 0, 0x01, 1, 7}, // bit 7 }; @@ -513,6 +513,16 @@ result_t StringDataField::readSymbols(SymbolString& input, output << setw(2) << hex << setfill('0') << static_cast(ch); break; case bt_dat: + if ((m_dataType.flags & REQ) == 0 && ch == m_dataType.replacement) { + if (i + 1 != m_length) { + output << NULL_VALUE << "."; + break; + } + else if (last == m_dataType.replacement) { + output << NULL_VALUE; + break; + } + } if (i + 1 == m_length) output << (2000 + ch); else if (ch < 1 || (i == 0 && ch > 31) || (i == 1 && ch > 12)) @@ -521,7 +531,7 @@ result_t StringDataField::readSymbols(SymbolString& input, output << setw(2) << dec << setfill('0') << static_cast(ch) << "."; break; case bt_tim: - if (m_dataType.replacement != 0 && ch == m_dataType.replacement) { + if ((m_dataType.flags & REQ) == 0 && ch == m_dataType.replacement) { if (m_length == 1) { // truncated time output << NULL_VALUE << ":" << NULL_VALUE; break; @@ -571,7 +581,7 @@ result_t StringDataField::writeSymbols(istringstream& input, incr = -1; } - if (isIgnored() == true) { + if (isIgnored() == true && (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 } @@ -606,6 +616,10 @@ result_t StringDataField::writeSymbols(istringstream& input, continue; // skip weekday in between if (input.eof() == true || getline(input, token, '.') == 0) return RESULT_ERR_EOF; // incomplete + if ((m_dataType.flags & REQ) == 0 && strcmp(token.c_str(), NULL_VALUE) == 0) { + value = m_dataType.replacement; + break; + } value = parseInt(token.c_str(), 10, 0, 2099, result); if (result != RESULT_OK) return result; // invalid date part @@ -637,7 +651,7 @@ result_t StringDataField::writeSymbols(istringstream& input, case bt_tim: if (input.eof() == true || getline(input, token, LENGTH_SEPARATOR) == 0) return RESULT_ERR_EOF; // incomplete - if (m_dataType.replacement != 0 && strcmp(token.c_str(), NULL_VALUE) == 0) { + if ((m_dataType.flags & REQ) == 0 && strcmp(token.c_str(), NULL_VALUE) == 0) { value = m_dataType.replacement; if (m_length == 1) { // truncated time if (i == 0) { @@ -736,7 +750,7 @@ result_t NumericDataField::readRawValue(SymbolString& input, for (size_t offset = start, i = 0, exp = 1; i < count; offset += incr, i++) { ch = input[baseOffset + offset]; if ((m_dataType.flags & BCD) != 0) { - if (ch == (m_dataType.replacement & 0xff)) { + if ((m_dataType.flags & REQ) == 0 && ch == (m_dataType.replacement & 0xff)) { value = m_dataType.replacement; return RESULT_OK; } @@ -782,7 +796,7 @@ result_t NumericDataField::writeRawValue(unsigned int value, } for (size_t offset = start, i = 0, exp = 1; i < count; offset += incr, i++) { if ((m_dataType.flags & BCD) != 0) { - if (value == m_dataType.replacement) + if ((m_dataType.flags & REQ) == 0 && value == m_dataType.replacement) ch = m_dataType.replacement & 0xff; else { ch = (value / exp) % 100; @@ -852,7 +866,7 @@ result_t NumberDataField::readSymbols(SymbolString& input, output << setw(0) << dec; // initialize output - if (value == m_dataType.replacement) { + if ((m_dataType.flags & REQ) == 0 && value == m_dataType.replacement) { output << NULL_VALUE; return RESULT_OK; } @@ -891,7 +905,7 @@ result_t NumberDataField::writeSymbols(istringstream& input, unsigned int value; const char* str = input.str().c_str(); - if (isIgnored() == true || strcasecmp(str, NULL_VALUE) == 0) + if ((m_dataType.flags & REQ) == 0 && (isIgnored() == true || strcasecmp(str, NULL_VALUE) == 0)) value = m_dataType.replacement; // replacement value else if (str == NULL || *str == 0) return RESULT_ERR_EOF; // input too short diff --git a/src/lib/ebus/data.h b/src/lib/ebus/data.h index 17f4bc26..060a2e84 100644 --- a/src/lib/ebus/data.h +++ b/src/lib/ebus/data.h @@ -71,6 +71,7 @@ static const unsigned int LST = 0x10; //!< value list is possible (without appli static const unsigned int DAY = 0x20; //!< forced value list defaulting to week days static const unsigned int IGN = 0x40; //!< ignore value during read and write static const unsigned int FIX = 0x80; //!< fixed width formatting +static const unsigned int REQ = 0x100;//!< value may not be NULL /** @brief The structure for defining field types with their properties. */ typedef struct { diff --git a/src/lib/ebus/test/test_data.cpp b/src/lib/ebus/test/test_data.cpp index 08faf8d3..afde64eb 100644 --- a/src/lib/ebus/test/test_data.cpp +++ b/src/lib/ebus/test/test_data.cpp @@ -54,19 +54,24 @@ int main() {"x,,hex:10", "48 61 6c 6c 6f 2c 20 44 75 21", "10fe07000a48616c6c6f2c20447521", "00", ""}, {"x,,hex:11", "", "10fe07000a48616c6c6f2c20447521", "00", "rW"}, {"x,,bda", "26.10.2014","10fe07000426100614", "00", ""}, // Sunday - {"x,,hda", "26.10.2014","10fe0700041a0a070e", "00", ""}, // Sunday {"x,,bda", "01.01.2000","10fe07000401010500", "00", ""}, // Saturday - {"x,,hda", "01.01.2000","10fe07000401010600", "00", ""}, // Saturday {"x,,bda", "31.12.2099","10fe07000431120399", "00", ""}, // Thursday - {"x,,hda", "31.12.2099","10fe0700041f0c0463", "00", ""}, // Thursday + {"x,,bda", "-.-.-", "10fe07000400000000", "00", ""}, {"x,,bda", "", "10fe07000432100014", "00", "rw"}, {"x,,bda:3", "26.10.2014","10fe070003261014", "00", ""}, {"x,,bda:3", "01.01.2000","10fe070003010100", "00", ""}, {"x,,bda:3", "31.12.2099","10fe070003311299", "00", ""}, + {"x,,bda:3", "-.-.-", "10fe070003000000", "00", ""}, {"x,,bda:3", "", "10fe070003321299", "00", "rw"}, + {"x,,hda", "26.10.2014","10fe0700041a0a070e", "00", ""}, // Sunday + {"x,,hda", "01.01.2000","10fe07000401010600", "00", ""}, // Saturday + {"x,,hda", "31.12.2099","10fe0700041f0c0463", "00", ""}, // Thursday + {"x,,hda", "-.-.-", "10fe07000400000000", "00", ""}, + {"x,,hda", "", "10fe070004200c0463", "00", "rw"}, {"x,,hda:3", "26.10.2014","10fe0700031a0a0e", "00", ""}, {"x,,hda:3", "01.01.2000","10fe070003010100", "00", ""}, {"x,,hda:3", "31.12.2099","10fe0700031f0c63", "00", ""}, + {"x,,hda:3", "-.-.-", "10fe070003000000", "00", ""}, {"x,,hda:3", "", "10fe070003200c63", "00", "rw"}, {"x,,bti", "21:04:58", "10fe070003580421", "00", ""}, {"x,,bti", "00:00:00", "10fe070003000000", "00", ""}, @@ -173,12 +178,12 @@ int main() {"x,,slg", "0", "10feffff0400000000", "00", ""}, {"x,,slg", "-1", "10feffff04ffffffff", "00", ""}, {"x,,bi3", "1", "10feffff0108", "00", ""}, - {"x,,bi3", "-", "10feffff0100", "00", ""}, + {"x,,bi3", "0", "10feffff0100", "00", ""}, {"x,,bi3,0=off;1=on","on", "10feffff0108", "00", ""}, {"x,,bi3,0=off;1=on","off","10feffff0100", "00", ""}, {"x,,bi3:2", "1", "10feffff0108", "00", ""}, {"x,,bi3:2", "1", "10feffff01ef", "00", "W"}, - {"x,,bi3:2", "-", "10feffff0100", "00", ""}, + {"x,,bi3:2", "0", "10feffff0100", "00", ""}, {"x,,bi3:2", "3", "10feffff0118", "00", ""}, {"x,,bi3:2,1=on","on", "10feffff0108", "00", ""}, {"x,,bi3:2,1=on","-", "10feffff0100", "00", ""}, @@ -189,11 +194,11 @@ int main() {"x,s,uch","3","1050ffff00", "0103", ""}, {"x,,d2b,,°C,Aussentemperatur","x=18.004 °C [Aussentemperatur]","10fe0700090112", "00", "v"}, {"x,,bti,,,,y,,bda,,,,z,,bdy", "21:04:58;26.10.2014;Sun","10fe0700085804212610061406", "00", ""}, // combination - {"x,,bi3,,,,y,,bi5", "1;-", "10feffff0108", "00", ""}, // bit combination + {"x,,bi3,,,,y,,bi5", "1;0", "10feffff0108", "00", ""}, // bit combination {"x,,bi3,,,,y,,bi5", "1;1", "10feffff0128", "00", ""}, // bit combination - {"x,,bi3,,,,y,,bi5", "-;1", "10feffff0120", "00", ""}, // bit combination - {"x,,bi3,,,,y,,bi5", "-;-", "10feffff0100", "00", ""}, // bit combination - {"x,,bi3,,,,y,,bi7,,,,t,,uch", "-;-;9","10feffff020009", "00", ""}, // bit combination + {"x,,bi3,,,,y,,bi5", "0;1", "10feffff0120", "00", ""}, // bit combination + {"x,,bi3,,,,y,,bi5", "0;0", "10feffff0100", "00", ""}, // bit combination + {"x,,bi3,,,,y,,bi7,,,,t,,uch", "0;0;9","10feffff020009", "00", ""}, // bit combination {"x,,bi6:2,,,,y,,bi0:2,,,,t,,uch", "2;1;9","10feffff03800109", "00", ""}, // bit combination {"temp,d2b,,°C,Aussentemperatur","","", "", "t"}, // template with relative pos {"x,,temp","18.004","10fe0700020112", "00", ""}, // reference to template