reworked result codes, added new base type VTI (vaillant specific time), added support for replacement value for time types
This commit is contained in:
@@ -102,7 +102,7 @@ result_t BaseLoop::readConfigFiles(const string path, const string extension)
|
|||||||
DIR* dir = opendir(path.c_str());
|
DIR* dir = opendir(path.c_str());
|
||||||
|
|
||||||
if (dir == NULL)
|
if (dir == NULL)
|
||||||
return RESULT_ERR_FILENOTFOUND;
|
return RESULT_ERR_NOTFOUND;
|
||||||
|
|
||||||
dirent* d = readdir(dir);
|
dirent* d = readdir(dir);
|
||||||
|
|
||||||
|
|||||||
+85
-59
@@ -39,6 +39,7 @@ static const dataType_t dataTypes[] = {
|
|||||||
{"HDA", 24, bt_dat, 0, 0, 10, 10, 0, 0}, // date, 01.01.2000 - 31.12.2099 (0x01,0x01,0x00 - 0x31,0x12,0x99) // TODO remove duplicate of BDA
|
{"HDA", 24, bt_dat, 0, 0, 10, 10, 0, 0}, // date, 01.01.2000 - 31.12.2099 (0x01,0x01,0x00 - 0x31,0x12,0x99) // TODO remove duplicate of BDA
|
||||||
{"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)
|
{"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)
|
{"HTI", 24, bt_tim, 0, 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, 0, 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)
|
{"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]
|
{"BDY", 8, bt_num, DAY|LST, 0x07, 0, 6, 1, 0}, // weekday, "Mon" - "Sun" (0x00 - 0x06) [ebus type]
|
||||||
@@ -80,12 +81,12 @@ unsigned int parseInt(const char* str, int base, const unsigned int minValue, co
|
|||||||
unsigned int ret = strtoul(str, &strEnd, base);
|
unsigned int ret = strtoul(str, &strEnd, base);
|
||||||
|
|
||||||
if (strEnd == NULL || *strEnd != 0) {
|
if (strEnd == NULL || *strEnd != 0) {
|
||||||
result = RESULT_ERR_INVALID_ARG; // invalid value
|
result = RESULT_ERR_INVALID_NUM; // invalid value
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret < minValue || ret > maxValue) {
|
if (ret < minValue || ret > maxValue) {
|
||||||
result = RESULT_ERR_INVALID_ARG; // invalid value
|
result = RESULT_ERR_OUT_OF_RANGE; // invalid value
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (length != NULL)
|
if (length != NULL)
|
||||||
@@ -130,7 +131,10 @@ result_t DataField::create(vector<string>::iterator& it,
|
|||||||
vector<SingleDataField*> fields;
|
vector<SingleDataField*> fields;
|
||||||
string firstName, firstComment;
|
string firstName, firstComment;
|
||||||
result_t result = RESULT_OK;
|
result_t result = RESULT_OK;
|
||||||
while (it != end && result == RESULT_OK) {
|
if (it == end)
|
||||||
|
return RESULT_ERR_EOF;
|
||||||
|
|
||||||
|
do {
|
||||||
string unit, comment;
|
string unit, comment;
|
||||||
PartType partType;
|
PartType partType;
|
||||||
unsigned int divisor = 0;
|
unsigned int divisor = 0;
|
||||||
@@ -163,14 +167,14 @@ result_t DataField::create(vector<string>::iterator& it,
|
|||||||
partType = pt_any;
|
partType = pt_any;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result = RESULT_ERR_INVALID_ARG;
|
result = RESULT_ERR_INVALID_PART;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
string typeStr = *it++;
|
string typeStr = *it++;
|
||||||
if (typeStr.empty() == true) {
|
if (typeStr.empty() == true) {
|
||||||
if (name.empty() == false || partStr[0] != 0)
|
if (name.empty() == false || partStr[0] != 0)
|
||||||
result = RESULT_ERR_INVALID_ARG;
|
result = RESULT_ERR_MISSING_TYPE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,11 +182,8 @@ result_t DataField::create(vector<string>::iterator& it,
|
|||||||
if (it != end) {
|
if (it != end) {
|
||||||
string divisorStr = *it++;
|
string divisorStr = *it++;
|
||||||
if (divisorStr.empty() == false) {
|
if (divisorStr.empty() == false) {
|
||||||
if (divisorStr.find('=') == string::npos) {
|
if (divisorStr.find('=') == string::npos)
|
||||||
divisor = parseInt(divisorStr.c_str(), 10, 1, 10000, result);
|
divisor = parseInt(divisorStr.c_str(), 10, 1, 10000, result);
|
||||||
if (result != RESULT_OK)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
istringstream stream(divisorStr);
|
istringstream stream(divisorStr);
|
||||||
while (getline(stream, token, VALUE_SEPARATOR) != 0) {
|
while (getline(stream, token, VALUE_SEPARATOR) != 0) {
|
||||||
@@ -190,17 +191,17 @@ result_t DataField::create(vector<string>::iterator& it,
|
|||||||
char* strEnd = NULL;
|
char* strEnd = NULL;
|
||||||
unsigned int id = strtoul(str, &strEnd, 10);
|
unsigned int id = strtoul(str, &strEnd, 10);
|
||||||
if (strEnd == NULL || strEnd == str || *strEnd != '=') {
|
if (strEnd == NULL || strEnd == str || *strEnd != '=') {
|
||||||
result = RESULT_ERR_INVALID_ARG;
|
result = RESULT_ERR_INVALID_LIST;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
values[id] = string(strEnd + 1);
|
values[id] = string(strEnd + 1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (result != RESULT_OK)
|
if (result != RESULT_OK)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (it == end)
|
if (it == end)
|
||||||
unit = "";
|
unit = "";
|
||||||
@@ -227,18 +228,17 @@ result_t DataField::create(vector<string>::iterator& it,
|
|||||||
istringstream stream(typeStr);
|
istringstream stream(typeStr);
|
||||||
bool found = false;
|
bool found = false;
|
||||||
string lengthStr;
|
string lengthStr;
|
||||||
while (getline(stream, token, VALUE_SEPARATOR) != 0) {
|
while (result == RESULT_OK && getline(stream, token, VALUE_SEPARATOR) != 0) {
|
||||||
DataField* templ = templates->get(token);
|
DataField* templ = templates->get(token);
|
||||||
if (templ == NULL) {
|
if (templ == NULL) {
|
||||||
if (found == false)
|
if (found == false)
|
||||||
break; // fallback to direct definition
|
break; // fallback to direct definition
|
||||||
result = RESULT_ERR_INVALID_ARG; // cannot mix reference and direct definition
|
result = RESULT_ERR_NOTFOUND; // cannot mix reference and direct definition
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
found = true;
|
found = true;
|
||||||
result = templ->derive("", "", "", partType, divisor, values, fields);
|
result = templ->derive("", "", "", partType, divisor, values, fields);
|
||||||
if (result != RESULT_OK)
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (result != RESULT_OK)
|
if (result != RESULT_OK)
|
||||||
break;
|
break;
|
||||||
@@ -267,7 +267,7 @@ result_t DataField::create(vector<string>::iterator& it,
|
|||||||
bitCount = 1; // default count: 1 bit
|
bitCount = 1; // default count: 1 bit
|
||||||
}
|
}
|
||||||
else if (length > bitCount) {
|
else if (length > bitCount) {
|
||||||
result = RESULT_ERR_INVALID_ARG; // invalid length
|
result = RESULT_ERR_OUT_OF_RANGE; // invalid length
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -282,7 +282,7 @@ result_t DataField::create(vector<string>::iterator& it,
|
|||||||
useLength = length;
|
useLength = length;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
result = RESULT_ERR_INVALID_ARG; // invalid length
|
result = RESULT_ERR_OUT_OF_RANGE; // invalid length
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -314,7 +314,7 @@ result_t DataField::create(vector<string>::iterator& it,
|
|||||||
}
|
}
|
||||||
if (values.begin()->first < dataType.minValueOrLength
|
if (values.begin()->first < dataType.minValueOrLength
|
||||||
|| values.rbegin()->first > dataType.maxValueOrLength) {
|
|| values.rbegin()->first > dataType.maxValueOrLength) {
|
||||||
result = RESULT_ERR_INVALID_ARG;
|
result = RESULT_ERR_OUT_OF_RANGE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,10 +326,12 @@ result_t DataField::create(vector<string>::iterator& it,
|
|||||||
if (add != NULL)
|
if (add != NULL)
|
||||||
fields.push_back(add);
|
fields.push_back(add);
|
||||||
else if (result == RESULT_OK)
|
else if (result == RESULT_OK)
|
||||||
result = RESULT_ERR_INVALID_ARG; // type not found
|
result = RESULT_ERR_NOTFOUND; // type not found
|
||||||
}
|
|
||||||
|
} while (it != end && result == RESULT_OK);
|
||||||
|
|
||||||
if (fields.empty() == true || result != RESULT_OK) {
|
if (fields.empty() == true || result != RESULT_OK) {
|
||||||
while (fields.empty() == false) {
|
while (fields.empty() == false) { // cleanup already created fields
|
||||||
delete fields.back();
|
delete fields.back();
|
||||||
fields.pop_back();
|
fields.pop_back();
|
||||||
}
|
}
|
||||||
@@ -371,11 +373,11 @@ result_t SingleDataField::read(SymbolString& masterData, unsigned char masterOff
|
|||||||
offset = 1 + slaveOffset; // skip NN
|
offset = 1 + slaveOffset; // skip NN
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return RESULT_ERR_INVALID_ARG; // invalid part type
|
return RESULT_ERR_INVALID_PART;
|
||||||
}
|
}
|
||||||
if (isIgnored() == true) {
|
if (isIgnored() == true) {
|
||||||
if (offset + m_length > input.size()) {
|
if (offset + m_length > input.size()) {
|
||||||
return RESULT_ERR_INVALID_ARG;
|
return RESULT_ERR_INVALID_POS;
|
||||||
}
|
}
|
||||||
return RESULT_OK;
|
return RESULT_OK;
|
||||||
}
|
}
|
||||||
@@ -411,7 +413,7 @@ result_t SingleDataField::write(istringstream& input,
|
|||||||
offset = 1 + slaveOffset; // skip NN
|
offset = 1 + slaveOffset; // skip NN
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return RESULT_ERR_INVALID_ARG;
|
return RESULT_ERR_INVALID_PART;
|
||||||
}
|
}
|
||||||
return writeSymbols(input, offset, output);
|
return writeSymbols(input, offset, output);
|
||||||
}
|
}
|
||||||
@@ -423,7 +425,7 @@ result_t StringDataField::derive(string name, string comment,
|
|||||||
vector<SingleDataField*>& fields)
|
vector<SingleDataField*>& fields)
|
||||||
{
|
{
|
||||||
if (m_partType != pt_any && partType == pt_any)
|
if (m_partType != pt_any && partType == pt_any)
|
||||||
return RESULT_ERR_INVALID_ARG; // cannot create a template from a concrete instance
|
return RESULT_ERR_INVALID_PART; // cannot create a template from a concrete instance
|
||||||
if (divisor != 0 || values.empty() == false)
|
if (divisor != 0 || values.empty() == false)
|
||||||
return RESULT_ERR_INVALID_ARG; // cannot set divisor or values for string field
|
return RESULT_ERR_INVALID_ARG; // cannot set divisor or values for string field
|
||||||
if (name.empty() == true)
|
if (name.empty() == true)
|
||||||
@@ -455,7 +457,7 @@ result_t StringDataField::readSymbols(SymbolString& input,
|
|||||||
unsigned char ch, last = 0;
|
unsigned char ch, last = 0;
|
||||||
|
|
||||||
if (baseOffset + m_length > input.size()) {
|
if (baseOffset + m_length > input.size()) {
|
||||||
return RESULT_ERR_INVALID_ARG;
|
return RESULT_ERR_INVALID_POS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((m_dataType.flags & REV) != 0) { // reverted binary representation (most significant byte first)
|
if ((m_dataType.flags & REV) != 0) { // reverted binary representation (most significant byte first)
|
||||||
@@ -469,7 +471,7 @@ result_t StringDataField::readSymbols(SymbolString& input,
|
|||||||
ch = input[baseOffset + offset];
|
ch = input[baseOffset + offset];
|
||||||
if ((m_dataType.flags & BCD) != 0 || m_dataType.type == bt_dat) {
|
if ((m_dataType.flags & BCD) != 0 || m_dataType.type == bt_dat) {
|
||||||
if ((ch & 0xf0) > 0x90 || (ch & 0x0f) > 0x09)
|
if ((ch & 0xf0) > 0x90 || (ch & 0x0f) > 0x09)
|
||||||
return RESULT_ERR_INVALID_ARG; // invalid BCD
|
return RESULT_ERR_OUT_OF_RANGE; // invalid BCD
|
||||||
ch = (ch >> 4) * 10 + (ch & 0x0f);
|
ch = (ch >> 4) * 10 + (ch & 0x0f);
|
||||||
}
|
}
|
||||||
switch (m_dataType.type)
|
switch (m_dataType.type)
|
||||||
@@ -484,11 +486,21 @@ result_t StringDataField::readSymbols(SymbolString& input,
|
|||||||
if (i + 1 == m_length)
|
if (i + 1 == m_length)
|
||||||
output << (2000 + ch);
|
output << (2000 + ch);
|
||||||
else if (ch < 1 || (i == 0 && ch > 31) || (i == 1 && ch > 12))
|
else if (ch < 1 || (i == 0 && ch > 31) || (i == 1 && ch > 12))
|
||||||
return RESULT_ERR_INVALID_ARG; // invalid date
|
return RESULT_ERR_OUT_OF_RANGE; // invalid date
|
||||||
else
|
else
|
||||||
output << setw(2) << setfill('0') << static_cast<unsigned>(ch) << ".";
|
output << setw(2) << setfill('0') << static_cast<unsigned>(ch) << ".";
|
||||||
break;
|
break;
|
||||||
case bt_tim:
|
case bt_tim:
|
||||||
|
if (m_dataType.replacement != 0 && ch == m_dataType.replacement) {
|
||||||
|
if (m_length == 1) { // truncated time
|
||||||
|
output << NULL_VALUE << ":" << NULL_VALUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i > 0)
|
||||||
|
output << ":";
|
||||||
|
output << NULL_VALUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (m_length == 1) { // truncated time
|
if (m_length == 1) { // truncated time
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
ch /= 6; // hours
|
ch /= 6; // hours
|
||||||
@@ -499,7 +511,7 @@ result_t StringDataField::readSymbols(SymbolString& input,
|
|||||||
ch = (ch % 6) * 10; // minutes
|
ch = (ch % 6) * 10; // minutes
|
||||||
}
|
}
|
||||||
if ((i == 0 && ch > 24) || (i > 0 && (ch > 59 || (last == 24 && ch > 0) )))
|
if ((i == 0 && ch > 24) || (i > 0 && (ch > 59 || (last == 24 && ch > 0) )))
|
||||||
return RESULT_ERR_INVALID_ARG; // invalid time
|
return RESULT_ERR_OUT_OF_RANGE; // invalid time
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
output << ":";
|
output << ":";
|
||||||
output << setw(2) << setfill('0') << static_cast<unsigned>(ch);
|
output << setw(2) << setfill('0') << static_cast<unsigned>(ch);
|
||||||
@@ -549,10 +561,10 @@ result_t StringDataField::writeSymbols(istringstream& input,
|
|||||||
token.clear();
|
token.clear();
|
||||||
token.push_back(input.get());
|
token.push_back(input.get());
|
||||||
if (input.eof() == true)
|
if (input.eof() == true)
|
||||||
return RESULT_ERR_INVALID_ARG; // too short hex value
|
return RESULT_ERR_INVALID_NUM; // too short hex value
|
||||||
token.push_back(input.get());
|
token.push_back(input.get());
|
||||||
if (input.eof() == true)
|
if (input.eof() == true)
|
||||||
return RESULT_ERR_INVALID_ARG; // too short hex value
|
return RESULT_ERR_INVALID_NUM; // too short hex value
|
||||||
|
|
||||||
value = parseInt(token.c_str(), 16, 0, 0xff, result);
|
value = parseInt(token.c_str(), 16, 0, 0xff, result);
|
||||||
if (result != RESULT_OK)
|
if (result != RESULT_OK)
|
||||||
@@ -563,7 +575,7 @@ result_t StringDataField::writeSymbols(istringstream& input,
|
|||||||
if (m_length == 4 && i == 2)
|
if (m_length == 4 && i == 2)
|
||||||
continue; // skip weekday in between
|
continue; // skip weekday in between
|
||||||
if (input.eof() == true || getline(input, token, '.') == 0)
|
if (input.eof() == true || getline(input, token, '.') == 0)
|
||||||
return RESULT_ERR_INVALID_ARG; // incomplete
|
return RESULT_ERR_EOF; // incomplete
|
||||||
value = parseInt(token.c_str(), 10, 0, 2099, result);
|
value = parseInt(token.c_str(), 10, 0, 2099, result);
|
||||||
if (result != RESULT_OK)
|
if (result != RESULT_OK)
|
||||||
return result; // invalid date part
|
return result; // invalid date part
|
||||||
@@ -578,7 +590,7 @@ result_t StringDataField::writeSymbols(istringstream& input,
|
|||||||
t.tm_year = (value < 100 ? value + 2000 : value) - 1900;
|
t.tm_year = (value < 100 ? value + 2000 : value) - 1900;
|
||||||
t.tm_isdst = 0; // automatic
|
t.tm_isdst = 0; // automatic
|
||||||
if (mktime(&t) < 0)
|
if (mktime(&t) < 0)
|
||||||
return RESULT_ERR_INVALID_ARG; // invalid date
|
return RESULT_ERR_INVALID_NUM; // invalid date
|
||||||
unsigned char daysSinceSunday = (unsigned char)t.tm_wday; // Sun=0
|
unsigned char daysSinceSunday = (unsigned char)t.tm_wday; // Sun=0
|
||||||
if ((m_dataType.flags & BCD) != 0)
|
if ((m_dataType.flags & BCD) != 0)
|
||||||
output[baseOffset + offset - incr] = (6+daysSinceSunday) % 7; // Sun=0x06
|
output[baseOffset + offset - incr] = (6+daysSinceSunday) % 7; // Sun=0x06
|
||||||
@@ -588,18 +600,32 @@ result_t StringDataField::writeSymbols(istringstream& input,
|
|||||||
if (value >= 2000)
|
if (value >= 2000)
|
||||||
value -= 2000;
|
value -= 2000;
|
||||||
else if (value > 99)
|
else if (value > 99)
|
||||||
return RESULT_ERR_INVALID_ARG; // invalid year
|
return RESULT_ERR_OUT_OF_RANGE; // invalid year
|
||||||
} else if (value < 1 || (i == 0 && value > 31) || (i == 1 && value > 12))
|
} else if (value < 1 || (i == 0 && value > 31) || (i == 1 && value > 12))
|
||||||
return RESULT_ERR_INVALID_ARG; // invalid date part
|
return RESULT_ERR_OUT_OF_RANGE; // invalid date part
|
||||||
break;
|
break;
|
||||||
case bt_tim:
|
case bt_tim:
|
||||||
if (input.eof() == true || getline(input, token, LENGTH_SEPARATOR) == 0)
|
if (input.eof() == true || getline(input, token, LENGTH_SEPARATOR) == 0)
|
||||||
return RESULT_ERR_INVALID_ARG; // incomplete
|
return RESULT_ERR_EOF; // incomplete
|
||||||
|
if (m_dataType.replacement != 0 && strcmp(token.c_str(), NULL_VALUE) == 0) {
|
||||||
|
value = m_dataType.replacement;
|
||||||
|
if (m_length == 1) { // truncated time
|
||||||
|
if (i == 0) {
|
||||||
|
last = value;
|
||||||
|
offset -= incr; // repeat for minutes
|
||||||
|
count++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (last != m_dataType.replacement)
|
||||||
|
return RESULT_ERR_INVALID_NUM; // invalid truncated time minutes
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
value = parseInt(token.c_str(), 10, 0, 59, result);
|
value = parseInt(token.c_str(), 10, 0, 59, result);
|
||||||
if (result != RESULT_OK)
|
if (result != RESULT_OK)
|
||||||
return result; // invalid time part
|
return result; // invalid time part
|
||||||
if ((i == 0 && value > 24) || (i > 0 && (last == 24 && value > 0) ))
|
if ((i == 0 && value > 24) || (i > 0 && (last == 24 && value > 0) ))
|
||||||
return RESULT_ERR_INVALID_ARG; // invalid time part
|
return RESULT_ERR_OUT_OF_RANGE; // invalid time part
|
||||||
if (m_length == 1) { // truncated time
|
if (m_length == 1) { // truncated time
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
last = value;
|
last = value;
|
||||||
@@ -608,10 +634,10 @@ result_t StringDataField::writeSymbols(istringstream& input,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((value % 10) != 0)
|
if ((value % 10) != 0)
|
||||||
return RESULT_ERR_INVALID_ARG; // invalid truncated time minutes
|
return RESULT_ERR_INVALID_NUM; // invalid truncated time minutes
|
||||||
value = last * 6 + (value / 10);
|
value = last * 6 + (value / 10);
|
||||||
if (value > 24 * 6)
|
if (value > 24 * 6)
|
||||||
return RESULT_ERR_INVALID_ARG; // invalid time
|
return RESULT_ERR_OUT_OF_RANGE; // invalid time
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -628,16 +654,16 @@ result_t StringDataField::writeSymbols(istringstream& input,
|
|||||||
last = value;
|
last = value;
|
||||||
if ((m_dataType.flags & BCD) != 0 || m_dataType.type == bt_dat) {
|
if ((m_dataType.flags & BCD) != 0 || m_dataType.type == bt_dat) {
|
||||||
if (value > 99)
|
if (value > 99)
|
||||||
return RESULT_ERR_INVALID_ARG; // invalid BCD
|
return RESULT_ERR_OUT_OF_RANGE; // invalid BCD
|
||||||
value = ((value / 10) << 4) | (value % 10);
|
value = ((value / 10) << 4) | (value % 10);
|
||||||
}
|
}
|
||||||
if (value > 0xff)
|
if (value > 0xff)
|
||||||
return RESULT_ERR_INVALID_ARG; // value out of range
|
return RESULT_ERR_OUT_OF_RANGE; // value out of range
|
||||||
output[baseOffset + offset] = (unsigned char)value;
|
output[baseOffset + offset] = (unsigned char)value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i < m_length)
|
if (i < m_length)
|
||||||
return RESULT_ERR_INVALID_ARG; // input too short
|
return RESULT_ERR_EOF; // input too short
|
||||||
|
|
||||||
return RESULT_OK;
|
return RESULT_OK;
|
||||||
}
|
}
|
||||||
@@ -669,7 +695,7 @@ result_t NumericDataField::readRawValue(SymbolString& input,
|
|||||||
unsigned char ch;
|
unsigned char ch;
|
||||||
|
|
||||||
if (baseOffset + m_length > input.size())
|
if (baseOffset + m_length > input.size())
|
||||||
return RESULT_ERR_INVALID_ARG; // not enough data available
|
return RESULT_ERR_INVALID_POS; // not enough data available
|
||||||
|
|
||||||
if ((m_dataType.flags & REV) != 0) { // reverted binary representation (most significant byte first)
|
if ((m_dataType.flags & REV) != 0) { // reverted binary representation (most significant byte first)
|
||||||
start = m_length - 1;
|
start = m_length - 1;
|
||||||
@@ -685,7 +711,7 @@ result_t NumericDataField::readRawValue(SymbolString& input,
|
|||||||
return RESULT_OK;
|
return RESULT_OK;
|
||||||
}
|
}
|
||||||
if ((ch & 0xf0) > 0x90 || (ch & 0x0f) > 0x09)
|
if ((ch & 0xf0) > 0x90 || (ch & 0x0f) > 0x09)
|
||||||
return RESULT_ERR_INVALID_ARG; // invalid BCD
|
return RESULT_ERR_OUT_OF_RANGE; // invalid BCD
|
||||||
|
|
||||||
ch = (ch >> 4) * 10 + (ch & 0x0f);
|
ch = (ch >> 4) * 10 + (ch & 0x0f);
|
||||||
value += ch * exp;
|
value += ch * exp;
|
||||||
@@ -720,7 +746,7 @@ result_t NumericDataField::writeRawValue(unsigned int value,
|
|||||||
|
|
||||||
if ((m_dataType.flags & BCD) == 0) {
|
if ((m_dataType.flags & BCD) == 0) {
|
||||||
if ((m_bitCount % 8) != 0 && (value & ~((1 << m_bitCount) - 1)) != 0)
|
if ((m_bitCount % 8) != 0 && (value & ~((1 << m_bitCount) - 1)) != 0)
|
||||||
return RESULT_ERR_INVALID_ARG;
|
return RESULT_ERR_OUT_OF_RANGE;
|
||||||
|
|
||||||
value <<= m_bitOffset;
|
value <<= m_bitOffset;
|
||||||
}
|
}
|
||||||
@@ -754,7 +780,7 @@ result_t NumberDataField::derive(string name, string comment,
|
|||||||
vector<SingleDataField*>& fields)
|
vector<SingleDataField*>& fields)
|
||||||
{
|
{
|
||||||
if (m_partType != pt_any && partType == pt_any)
|
if (m_partType != pt_any && partType == pt_any)
|
||||||
return RESULT_ERR_INVALID_ARG; // cannot create a template from a concrete instance
|
return RESULT_ERR_INVALID_PART; // cannot create a template from a concrete instance
|
||||||
if (name.empty() == true)
|
if (name.empty() == true)
|
||||||
name = m_name;
|
name = m_name;
|
||||||
if (comment.empty() == true)
|
if (comment.empty() == true)
|
||||||
@@ -834,7 +860,7 @@ result_t NumberDataField::writeSymbols(istringstream& input,
|
|||||||
if (isIgnored() == true || strcasecmp(str, NULL_VALUE) == 0)
|
if (isIgnored() == true || strcasecmp(str, NULL_VALUE) == 0)
|
||||||
value = m_dataType.replacement; // replacement value
|
value = m_dataType.replacement; // replacement value
|
||||||
else if (str == NULL || *str == 0)
|
else if (str == NULL || *str == 0)
|
||||||
return RESULT_ERR_INVALID_ARG; // input too short
|
return RESULT_ERR_EOF; // input too short
|
||||||
else {
|
else {
|
||||||
char* strEnd = NULL;
|
char* strEnd = NULL;
|
||||||
if (m_divisor <= 1) {
|
if (m_divisor <= 1) {
|
||||||
@@ -848,17 +874,17 @@ result_t NumberDataField::writeSymbols(istringstream& input,
|
|||||||
else
|
else
|
||||||
value = strtoul(str, &strEnd, 10);
|
value = strtoul(str, &strEnd, 10);
|
||||||
if (strEnd == NULL || *strEnd != 0)
|
if (strEnd == NULL || *strEnd != 0)
|
||||||
return RESULT_ERR_INVALID_ARG; // invalid value
|
return RESULT_ERR_INVALID_NUM; // invalid value
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
char* strEnd = NULL;
|
char* strEnd = NULL;
|
||||||
double dvalue = strtod(str, &strEnd);
|
double dvalue = strtod(str, &strEnd);
|
||||||
if (strEnd == NULL || *strEnd != 0)
|
if (strEnd == NULL || *strEnd != 0)
|
||||||
return RESULT_ERR_INVALID_ARG; // invalid value
|
return RESULT_ERR_INVALID_NUM; // invalid value
|
||||||
dvalue = round(dvalue * m_divisor);
|
dvalue = round(dvalue * m_divisor);
|
||||||
if ((m_dataType.flags & SIG) != 0) {
|
if ((m_dataType.flags & SIG) != 0) {
|
||||||
if (dvalue < -(1LL << (8 * m_length)) || dvalue >= (1LL << (8 * m_length)))
|
if (dvalue < -(1LL << (8 * m_length)) || dvalue >= (1LL << (8 * m_length)))
|
||||||
return RESULT_ERR_INVALID_ARG; // value out of range
|
return RESULT_ERR_OUT_OF_RANGE; // value out of range
|
||||||
if (dvalue < 0 && m_bitCount != 32)
|
if (dvalue < 0 && m_bitCount != 32)
|
||||||
value = (unsigned int) (dvalue + (1 << m_bitCount));
|
value = (unsigned int) (dvalue + (1 << m_bitCount));
|
||||||
else
|
else
|
||||||
@@ -866,7 +892,7 @@ result_t NumberDataField::writeSymbols(istringstream& input,
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (dvalue < 0.0 || dvalue >= (1LL << (8 * m_length)))
|
if (dvalue < 0.0 || dvalue >= (1LL << (8 * m_length)))
|
||||||
return RESULT_ERR_INVALID_ARG; // value out of range
|
return RESULT_ERR_OUT_OF_RANGE; // value out of range
|
||||||
value = (unsigned int) dvalue;
|
value = (unsigned int) dvalue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -874,13 +900,13 @@ result_t NumberDataField::writeSymbols(istringstream& input,
|
|||||||
if ((m_dataType.flags & SIG) != 0) { // signed value
|
if ((m_dataType.flags & SIG) != 0) { // signed value
|
||||||
if ((value & (1 << (m_bitCount - 1))) != 0) { // negative signed value
|
if ((value & (1 << (m_bitCount - 1))) != 0) { // negative signed value
|
||||||
if (value < m_dataType.minValueOrLength)
|
if (value < m_dataType.minValueOrLength)
|
||||||
return RESULT_ERR_INVALID_ARG; // value out of range
|
return RESULT_ERR_OUT_OF_RANGE; // value out of range
|
||||||
}
|
}
|
||||||
else if (value > m_dataType.maxValueOrLength)
|
else if (value > m_dataType.maxValueOrLength)
|
||||||
return RESULT_ERR_INVALID_ARG; // value out of range
|
return RESULT_ERR_OUT_OF_RANGE; // value out of range
|
||||||
}
|
}
|
||||||
else if (value < m_dataType.minValueOrLength || value > m_dataType.maxValueOrLength)
|
else if (value < m_dataType.minValueOrLength || value > m_dataType.maxValueOrLength)
|
||||||
return RESULT_ERR_INVALID_ARG; // value out of range
|
return RESULT_ERR_OUT_OF_RANGE; // value out of range
|
||||||
}
|
}
|
||||||
|
|
||||||
return writeRawValue(value, baseOffset, output);
|
return writeRawValue(value, baseOffset, output);
|
||||||
@@ -893,7 +919,7 @@ result_t ValueListDataField::derive(string name, string comment,
|
|||||||
vector<SingleDataField*>& fields)
|
vector<SingleDataField*>& fields)
|
||||||
{
|
{
|
||||||
if (m_partType != pt_any && partType == pt_any)
|
if (m_partType != pt_any && partType == pt_any)
|
||||||
return RESULT_ERR_INVALID_ARG; // cannot create a template from a concrete instance
|
return RESULT_ERR_INVALID_PART; // cannot create a template from a concrete instance
|
||||||
if (name.empty() == true)
|
if (name.empty() == true)
|
||||||
name = m_name;
|
name = m_name;
|
||||||
if (comment.empty() == true)
|
if (comment.empty() == true)
|
||||||
@@ -951,7 +977,7 @@ result_t ValueListDataField::readSymbols(SymbolString& input,
|
|||||||
return RESULT_OK;
|
return RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
return RESULT_ERR_INVALID_ARG; // value assignment not found
|
return RESULT_ERR_NOTFOUND; // value assignment not found
|
||||||
}
|
}
|
||||||
|
|
||||||
result_t ValueListDataField::writeSymbols(istringstream& input,
|
result_t ValueListDataField::writeSymbols(istringstream& input,
|
||||||
@@ -969,7 +995,7 @@ result_t ValueListDataField::writeSymbols(istringstream& input,
|
|||||||
if (strcasecmp(str, NULL_VALUE) == 0)
|
if (strcasecmp(str, NULL_VALUE) == 0)
|
||||||
return writeRawValue(m_dataType.replacement, baseOffset, output); // replacement value
|
return writeRawValue(m_dataType.replacement, baseOffset, output); // replacement value
|
||||||
|
|
||||||
return RESULT_ERR_INVALID_ARG; // value assignment not found
|
return RESULT_ERR_NOTFOUND; // value assignment not found
|
||||||
}
|
}
|
||||||
|
|
||||||
DataFieldSet::~DataFieldSet()
|
DataFieldSet::~DataFieldSet()
|
||||||
@@ -1095,7 +1121,7 @@ result_t DataFieldSet::write(istringstream& input,
|
|||||||
if (ignored == true)
|
if (ignored == true)
|
||||||
token.clear();
|
token.clear();
|
||||||
else if (getline(input, token, separator) == 0)
|
else if (getline(input, token, separator) == 0)
|
||||||
return RESULT_ERR_INVALID_ARG; // incomplete
|
return RESULT_ERR_EOF; // incomplete
|
||||||
|
|
||||||
istringstream single(token);
|
istringstream single(token);
|
||||||
result = (*it)->write(single, masterData, offsets[pt_masterData], slaveData, offsets[pt_slaveData], separator);
|
result = (*it)->write(single, masterData, offsets[pt_masterData], slaveData, offsets[pt_slaveData], separator);
|
||||||
|
|||||||
+1
-1
@@ -614,7 +614,7 @@ public:
|
|||||||
ifstream ifs;
|
ifstream ifs;
|
||||||
ifs.open(filename.c_str(), ifstream::in);
|
ifs.open(filename.c_str(), ifstream::in);
|
||||||
if (ifs.is_open() == false)
|
if (ifs.is_open() == false)
|
||||||
return RESULT_ERR_FILENOTFOUND;
|
return RESULT_ERR_NOTFOUND;
|
||||||
|
|
||||||
string line;
|
string line;
|
||||||
unsigned int lineNo = 0;
|
unsigned int lineNo = 0;
|
||||||
|
|||||||
+23
-16
@@ -24,24 +24,31 @@ using namespace std;
|
|||||||
|
|
||||||
const char* getResultCode(result_t resultCode) {
|
const char* getResultCode(result_t resultCode) {
|
||||||
switch (resultCode) {
|
switch (resultCode) {
|
||||||
case RESULT_ERR_SEND: return "ERR_SEND: send error";
|
case RESULT_IN_ESC: return "success: escape sequence received";
|
||||||
case RESULT_ERR_EXTRA_DATA: return "ERR_EXTRA_DATA: received bytes > sent bytes";
|
case RESULT_SYN: return "success: SYN received";
|
||||||
case RESULT_ERR_NAK: return "ERR_NAK: NAK received";
|
case RESULT_ERR_GENERIC_IO: return "ERR: generic I/O error";
|
||||||
case RESULT_ERR_CRC: return "ERR_CRC: CRC error";
|
case RESULT_ERR_DEVICE: return "ERR: generic device error";
|
||||||
case RESULT_ERR_ACK: return "ERR_ACK: ACK error";
|
case RESULT_ERR_SEND: return "ERR: send error";
|
||||||
case RESULT_ERR_TIMEOUT: return "ERR_TIMEOUT: read timeout";
|
case RESULT_ERR_ESC: return "ERR: invalid escape sequence";
|
||||||
case RESULT_ERR_SYN: return "ERR_SYN: SYN received";
|
case RESULT_ERR_TIMEOUT: return "ERR: read timeout";
|
||||||
case RESULT_ERR_BUS_LOST: return "ERR_BUS_LOST: lost bus arbitration";
|
case RESULT_ERR_NOTFOUND: return "ERR: file/element not found or not readable";
|
||||||
case RESULT_ERR_ESC: return "ERR_ESC: invalid escape sequence received";
|
case RESULT_ERR_EOF: return "ERR: end of input reached";
|
||||||
case RESULT_ERR_INVALID_ARG: return "ERR_INVALID_ARG: invalid argument specified";
|
case RESULT_ERR_INVALID_ARG: return "ERR: invalid argument";
|
||||||
case RESULT_ERR_DEVICE: return "ERR_DEVICE: generic device error";
|
case RESULT_ERR_INVALID_NUM: return "ERR: invalid numeric argument";
|
||||||
case RESULT_ERR_EOF: return "ERR_EOF: end of input reached";
|
case RESULT_ERR_INVALID_POS: return "ERR: invalid position";
|
||||||
case RESULT_ERR_FILENOTFOUND: return "ERR_FILENOTFOUND: file not found or not readable";
|
case RESULT_ERR_OUT_OF_RANGE: return "ERR: argument value out of valid range";
|
||||||
case RESULT_ERR_DUPLICATE: return "ERR_DUPLICATE: duplicate entry";
|
case RESULT_ERR_INVALID_PART: return "ERR: invalid part type value";
|
||||||
|
case RESULT_ERR_MISSING_TYPE: return "ERR: missing data type";
|
||||||
|
case RESULT_ERR_INVALID_LIST: return "ERR: invalid value list";
|
||||||
|
case RESULT_ERR_DUPLICATE: return "ERR: duplicate entry";
|
||||||
|
case RESULT_ERR_BUS_LOST: return "ERR: arbitration lost";
|
||||||
|
case RESULT_ERR_CRC: return "ERR: CRC error";
|
||||||
|
case RESULT_ERR_ACK: return "ERR: ACK error";
|
||||||
|
case RESULT_ERR_NAK: return "ERR: NAK received";
|
||||||
default:
|
default:
|
||||||
if (resultCode >= 0)
|
if (resultCode >= 0)
|
||||||
return "success";
|
return "success: unknown result code";
|
||||||
return "ERR: unknown error code";
|
return "ERR: unknown result code";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+24
-21
@@ -20,29 +20,32 @@
|
|||||||
#ifndef LIBEBUS_RESULT_H_
|
#ifndef LIBEBUS_RESULT_H_
|
||||||
#define LIBEBUS_RESULT_H_
|
#define LIBEBUS_RESULT_H_
|
||||||
|
|
||||||
static const int RESULT_OK = 0;
|
static const int RESULT_OK = 0; // success
|
||||||
|
|
||||||
static const int RESULT_BUS_ACQUIRED = 1; // bus successfully acquired
|
static const int RESULT_IN_ESC = 1; // start of escape sequence received
|
||||||
static const int RESULT_DATA = 2; // some data received
|
static const int RESULT_SYN = 2; // regular SYN after message received
|
||||||
static const int RESULT_SYN = 3; // regular SYN after message received
|
|
||||||
static const int RESULT_BUS_LOCKED = 4; // bus is locked for access
|
|
||||||
static const int RESULT_BUS_PRIOR_RETRY = 5; // retry to access bus
|
|
||||||
static const int RESULT_IN_ESC = 6; // start of escape sequence received
|
|
||||||
|
|
||||||
static const int RESULT_ERR_SEND = -1; // send error
|
static const int RESULT_ERR_GENERIC_IO = -1; // generic I/O error (usually fatal)
|
||||||
static const int RESULT_ERR_EXTRA_DATA = -2; // received bytes > sent bytes
|
static const int RESULT_ERR_DEVICE = -2; // generic device error (usually fatal)
|
||||||
static const int RESULT_ERR_NAK = -3; // NAK received
|
static const int RESULT_ERR_SEND = -3; // send error
|
||||||
static const int RESULT_ERR_CRC = -4; // CRC error
|
static const int RESULT_ERR_ESC = -4; // invalid escape sequence
|
||||||
static const int RESULT_ERR_ACK = -5; // ACK error
|
static const int RESULT_ERR_TIMEOUT = -5; // read timeout
|
||||||
static const int RESULT_ERR_TIMEOUT = -6; // read timeout
|
|
||||||
static const int RESULT_ERR_SYN = -7; // SYN received
|
static const int RESULT_ERR_NOTFOUND = -6; // file/element not found or not readable
|
||||||
static const int RESULT_ERR_BUS_LOST = -8; // arbitration lost
|
static const int RESULT_ERR_EOF = -7; // end of input reached
|
||||||
static const int RESULT_ERR_ESC = -9; // invalid escape sequence received
|
static const int RESULT_ERR_INVALID_ARG = -8; // invalid argument
|
||||||
static const int RESULT_ERR_INVALID_ARG = -10; // invalid argument
|
static const int RESULT_ERR_INVALID_NUM = -9; // invalid numeric argument
|
||||||
static const int RESULT_ERR_DEVICE = -11; // generic device error (usually fatal)
|
static const int RESULT_ERR_INVALID_POS = -10; // invalid position
|
||||||
static const int RESULT_ERR_EOF = -12; // end of input reached
|
static const int RESULT_ERR_OUT_OF_RANGE = -11; // argument value out of valid range
|
||||||
static const int RESULT_ERR_FILENOTFOUND = -13;// file not found or not readable
|
static const int RESULT_ERR_INVALID_PART = -12; // invalid part type value
|
||||||
static const int RESULT_ERR_DUPLICATE = -14; // duplicate entry
|
static const int RESULT_ERR_MISSING_TYPE = -13; // missing data type
|
||||||
|
static const int RESULT_ERR_INVALID_LIST = -14; // invalid value list
|
||||||
|
static const int RESULT_ERR_DUPLICATE = -15; // duplicate entry
|
||||||
|
|
||||||
|
static const int RESULT_ERR_BUS_LOST = -16; // arbitration lost
|
||||||
|
static const int RESULT_ERR_CRC = -17; // CRC error
|
||||||
|
static const int RESULT_ERR_ACK = -18; // ACK error
|
||||||
|
static const int RESULT_ERR_NAK = -19; // NAK received
|
||||||
|
|
||||||
/** type for result code. */
|
/** type for result code. */
|
||||||
typedef int result_t;
|
typedef int result_t;
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ int main()
|
|||||||
{"x;;bti", "23:59:59", "10fe070003595923", "00", ""},
|
{"x;;bti", "23:59:59", "10fe070003595923", "00", ""},
|
||||||
{"x;;bti", "", "10fe070003605923", "00", "rw"},
|
{"x;;bti", "", "10fe070003605923", "00", "rw"},
|
||||||
{"x;;hti", "21:04:58", "10fe07000315043a", "00", ""},
|
{"x;;hti", "21:04:58", "10fe07000315043a", "00", ""},
|
||||||
|
{"x;;vti", "21:04:58", "10fe0700033a0415", "00", ""},
|
||||||
|
{"x;;vti", "-:-:-", "10fe070003636363", "00", ""},
|
||||||
{"x;;htm", "21:04", "10fe0700021504", "00", ""},
|
{"x;;htm", "21:04", "10fe0700021504", "00", ""},
|
||||||
{"x;;htm", "00:00", "10fe0700020000", "00", ""},
|
{"x;;htm", "00:00", "10fe0700020000", "00", ""},
|
||||||
{"x;;htm", "23:59", "10fe070002173b", "00", ""},
|
{"x;;htm", "23:59", "10fe070002173b", "00", ""},
|
||||||
@@ -78,7 +80,7 @@ int main()
|
|||||||
{"x;;ttm", "22:40", "10fe07000188", "00", ""},
|
{"x;;ttm", "22:40", "10fe07000188", "00", ""},
|
||||||
{"x;;ttm", "00:00", "10fe07000100", "00", ""},
|
{"x;;ttm", "00:00", "10fe07000100", "00", ""},
|
||||||
{"x;;ttm", "23:50", "10fe0700018f", "00", ""},
|
{"x;;ttm", "23:50", "10fe0700018f", "00", ""},
|
||||||
{"x;;ttm", "24:00", "10fe07000190", "00", ""},
|
{"x;;ttm", "-:-", "10fe07000190", "00", ""},
|
||||||
{"x;;ttm", "", "10fe07000191", "00", "rw"},
|
{"x;;ttm", "", "10fe07000191", "00", "rw"},
|
||||||
{"x;;bdy", "Mon", "10fe07000300", "00", ""},
|
{"x;;bdy", "Mon", "10fe07000300", "00", ""},
|
||||||
{"x;;bdy", "Sun", "10fe07000306", "00", ""},
|
{"x;;bdy", "Sun", "10fe07000306", "00", ""},
|
||||||
|
|||||||
Reference in New Issue
Block a user