added constant value data types
This commit is contained in:
+92
-4
@@ -101,11 +101,21 @@ result_t DataField::create(vector<string>::iterator& it,
|
||||
}
|
||||
|
||||
map<unsigned int, string> values;
|
||||
string constantValue;
|
||||
bool verifyValue = false;
|
||||
if (it != end) {
|
||||
const string divisorStr = *it++; // [divisor|values]
|
||||
if (!divisorStr.empty()) {
|
||||
if (divisorStr.find('=') == string::npos) {
|
||||
size_t equalPos = divisorStr.find('=');
|
||||
if (equalPos == string::npos) {
|
||||
divisor = parseSignedInt(divisorStr.c_str(), 10, -MAX_DIVISOR, MAX_DIVISOR, result);
|
||||
} else if (equalPos == 0 && divisorStr.length() > 1) {
|
||||
verifyValue = divisorStr[1]=='='; // == forced verification of constant value
|
||||
if (verifyValue && divisorStr.length() == 1) {
|
||||
result = RESULT_ERR_INVALID_LIST;
|
||||
break;
|
||||
}
|
||||
constantValue = divisorStr.substr(equalPos+(verifyValue?2:1));
|
||||
} else {
|
||||
istringstream stream(divisorStr);
|
||||
while (getline(stream, token, VALUE_SEPARATOR)) {
|
||||
@@ -190,12 +200,14 @@ result_t DataField::create(vector<string>::iterator& it,
|
||||
}
|
||||
transform(typeName.begin(), typeName.end(), typeName.begin(), ::toupper);
|
||||
SingleDataField* add = NULL;
|
||||
result = SingleDataField::create(typeName, length, firstType ? name : "", firstType ? comment : "", firstType ? unit : "", partType, divisor, values, add);
|
||||
result = SingleDataField::create(typeName, length, firstType ? name : "", firstType ? comment : "", firstType ? unit : "", partType, divisor, values, constantValue, verifyValue, add);
|
||||
if (add != NULL) {
|
||||
fields.push_back(add);
|
||||
} else if (result == RESULT_OK) {
|
||||
result = RESULT_ERR_NOTFOUND; // type not found
|
||||
}
|
||||
} else if (!constantValue.empty()) {
|
||||
result = RESULT_ERR_INVALID_ARG; // invalid value list
|
||||
} else { // template[:name]
|
||||
string fieldName;
|
||||
bool lastType = stream.eof();
|
||||
@@ -241,7 +253,7 @@ void DataField::dumpString(ostream& output, const string str, const bool prepend
|
||||
result_t SingleDataField::create(const string id, const unsigned char length,
|
||||
const string name, const string comment, const string unit,
|
||||
const PartType partType, int divisor, map<unsigned int, string> values,
|
||||
SingleDataField* &returnField)
|
||||
const string constantValue, const bool verifyValue, SingleDataField* &returnField)
|
||||
{
|
||||
DataType* dataType = DataTypeList::getInstance()->get(id, length==REMAIN_LEN ? (unsigned char)0 : length);
|
||||
if (!dataType) {
|
||||
@@ -268,6 +280,10 @@ result_t SingleDataField::create(const string id, const unsigned char length,
|
||||
return RESULT_ERR_OUT_OF_RANGE; // invalid length
|
||||
}
|
||||
}
|
||||
if (!constantValue.empty()) {
|
||||
returnField = new ConstantDataField(name, comment, unit, dataType, partType, byteCount, constantValue, verifyValue);
|
||||
return RESULT_OK;
|
||||
}
|
||||
if (dataType->isNumeric()) {
|
||||
NumberDataType* numType = (NumberDataType*)dataType;
|
||||
if (values.empty() && numType->hasFlag(DAY)) {
|
||||
@@ -285,7 +301,6 @@ result_t SingleDataField::create(const string id, const unsigned char length,
|
||||
if (values.begin()->first < numType->getMinValue() || values.rbegin()->first > numType->getMaxValue()) {
|
||||
return RESULT_ERR_OUT_OF_RANGE;
|
||||
}
|
||||
//TODO add special field for fixed values (exactly one value in the list of values)
|
||||
returnField = new ValueListDataField(name, comment, unit, numType, partType, byteCount, values);
|
||||
return RESULT_OK;
|
||||
}
|
||||
@@ -621,6 +636,79 @@ result_t ValueListDataField::writeSymbols(istringstream& input,
|
||||
}
|
||||
|
||||
|
||||
ConstantDataField* ConstantDataField::clone()
|
||||
{
|
||||
return new ConstantDataField(*this);
|
||||
}
|
||||
|
||||
result_t ConstantDataField::derive(string name, string comment,
|
||||
string unit, const PartType partType,
|
||||
int divisor, map<unsigned int, string> values,
|
||||
vector<SingleDataField*>& fields)
|
||||
{
|
||||
if (m_partType != pt_any && partType == pt_any)
|
||||
return RESULT_ERR_INVALID_PART; // cannot create a template from a concrete instance
|
||||
if (name.empty())
|
||||
name = m_name;
|
||||
if (comment.empty())
|
||||
comment = m_comment;
|
||||
if (unit.empty())
|
||||
unit = m_unit;
|
||||
if (divisor != 0)
|
||||
return RESULT_ERR_INVALID_ARG; // cannot use other than current divisor for constant value field
|
||||
if (!values.empty()) {
|
||||
return RESULT_ERR_INVALID_ARG; // cannot use value list for constant value field
|
||||
}
|
||||
fields.push_back(new ConstantDataField(name, comment, unit, m_dataType, partType, m_length, m_value, m_verify));
|
||||
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
void ConstantDataField::dump(ostream& output)
|
||||
{
|
||||
output << setw(0) << dec; // initialize formatting
|
||||
dumpString(output, m_name, false);
|
||||
output << FIELD_SEPARATOR;
|
||||
if (m_partType == pt_masterData)
|
||||
output << "m";
|
||||
else if (m_partType == pt_slaveData)
|
||||
output << "s";
|
||||
output << FIELD_SEPARATOR;
|
||||
if (!m_dataType->dump(output, m_length)) { // no divisor appended
|
||||
output << (m_verify?"==":"=") << m_value;
|
||||
} // else: impossible since divisor is not allowed for ConstantDataField
|
||||
dumpString(output, m_unit);
|
||||
dumpString(output, m_comment);
|
||||
}
|
||||
|
||||
result_t ConstantDataField::readSymbols(SymbolString& input, const bool isMaster,
|
||||
const unsigned char offset,
|
||||
ostringstream& output, OutputFormat outputFormat)
|
||||
{
|
||||
ostringstream coutput;
|
||||
result_t result = SingleDataField::readSymbols(input, isMaster, offset, coutput, 0);
|
||||
if (result != RESULT_OK) {
|
||||
return result;
|
||||
}
|
||||
if (m_verify) {
|
||||
string value = coutput.str();
|
||||
FileReader::trim(value);
|
||||
if (value!=m_value) {
|
||||
return RESULT_ERR_OUT_OF_RANGE;
|
||||
}
|
||||
}
|
||||
return RESULT_OK;
|
||||
}
|
||||
|
||||
result_t ConstantDataField::writeSymbols(istringstream& input,
|
||||
const unsigned char offset,
|
||||
SymbolString& output, const bool isMaster, unsigned char* usedLength)
|
||||
{
|
||||
istringstream cinput(m_value);
|
||||
return SingleDataField::writeSymbols(cinput, offset, output, isMaster, usedLength);
|
||||
}
|
||||
|
||||
|
||||
DataFieldSet* DataFieldSet::s_identFields = NULL;
|
||||
|
||||
DataFieldSet* DataFieldSet::getIdentFields()
|
||||
|
||||
+67
-1
@@ -256,6 +256,8 @@ public:
|
||||
* @param partType the message part in which the field is stored.
|
||||
* @param divisor the extra divisor (negative for reciprocal) to apply on the value, or 1 for none (if applicable).
|
||||
* @param values the value=text assignments.
|
||||
* @param constantValue the constant value as string, or empty.
|
||||
* @param verifyValue whether to verify the read value against the constant value.
|
||||
* @param returnField the variable in which the created @a SingleDataField instance shall be stored.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
* Note: the caller needs to free the created instance.
|
||||
@@ -263,7 +265,7 @@ public:
|
||||
static result_t create(const string id, const unsigned char length,
|
||||
const string name, const string comment, const string unit,
|
||||
const PartType partType, int divisor, map<unsigned int, string> values,
|
||||
SingleDataField* &returnField);
|
||||
const string constantValue, const bool verifyValue, SingleDataField* &returnField);
|
||||
|
||||
/**
|
||||
* Get the value unit.
|
||||
@@ -427,6 +429,70 @@ private:
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A data field with a constant value.
|
||||
*/
|
||||
class ConstantDataField : public SingleDataField
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructs a new instance.
|
||||
* @param name the field name.
|
||||
* @param comment the field comment.
|
||||
* @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 value the constant value.
|
||||
* @param verify whether to verify the read value against the constant value.
|
||||
*/
|
||||
ConstantDataField(const string name, const string comment,
|
||||
const string unit, DataType* dataType, const PartType partType,
|
||||
const unsigned char length, const string value, const bool verify)
|
||||
: SingleDataField(name, comment, unit, dataType, partType, length),
|
||||
m_value(value), m_verify(verify) {}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~ConstantDataField() {}
|
||||
|
||||
// @copydoc
|
||||
virtual ConstantDataField* clone();
|
||||
|
||||
// @copydoc
|
||||
virtual result_t derive(string name, string comment,
|
||||
string unit, const PartType partType, int divisor,
|
||||
map<unsigned int, string> values,
|
||||
vector<SingleDataField*>& fields);
|
||||
|
||||
// @copydoc
|
||||
virtual void dump(ostream& output);
|
||||
|
||||
protected:
|
||||
|
||||
// @copydoc
|
||||
virtual result_t readSymbols(SymbolString& input, const bool isMaster,
|
||||
const unsigned char offset,
|
||||
ostringstream& output, OutputFormat outputFormat);
|
||||
|
||||
// @copydoc
|
||||
virtual result_t writeSymbols(istringstream& input,
|
||||
const unsigned char offset,
|
||||
SymbolString& output, const bool isMaster, unsigned char* usedLength);
|
||||
|
||||
private:
|
||||
|
||||
/** the constant value. */
|
||||
const string m_value;
|
||||
|
||||
/** whether to verify the read value against the constant value. */
|
||||
const bool m_verify;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A set of @a DataField instances.
|
||||
*/
|
||||
|
||||
@@ -103,6 +103,7 @@ static const unsigned int EXP = 0x100; //!< exponential numeric representation
|
||||
static const unsigned int DAY = 0x200; //!< forced value list defaulting to week days
|
||||
static const unsigned int NUM = 0x400; //!< numeric type with base class @a NumberDataType
|
||||
static const unsigned int SPE = 0x800; //!< special marker for certain types
|
||||
static const unsigned int CON = 0x1000; //!< marker for a constant value
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -62,6 +62,10 @@ int main()
|
||||
{"x,,str:24", "abcdefghijklmnopqrstuvwx", "10fe0700186162636465666768696a6b6c6d6e6f707172737475767778", "00", ""},
|
||||
{"x,,str:*", "abcde", "10fe0700056162636465", "00", ""},
|
||||
{"x,,str,2", "", "", "", "c"},
|
||||
{"x,,str:10,=dummy", "", "10fe07000a48616c6c6f2044752120", "00", "W"},
|
||||
{"x,,str:10,==dummy", "", "10fe07000a48616c6c6f2044752120", "00", "rW"},
|
||||
{"x,,str:10,=dummy", "", "10fe07000a64756d6d792020202020", "00", ""},
|
||||
{"x,,str:10,==dummy", "", "10fe07000a64756d6d792020202020", "00", ""},
|
||||
{"x,,nts:10", "Hallo, Du!", "10fe07000a48616c6c6f2c20447521", "00", ""},
|
||||
{"x,,nts:10", "Hallo, Du!", "10fe07000a48616c6c6f2c20447521", "00", ""},
|
||||
{"x,,nts:10", "Hallo, Du", "10fe07000a48616c6c6f2c20447500", "00", ""},
|
||||
@@ -78,6 +82,10 @@ int main()
|
||||
{"x,,hex:*", "48 61 6c 6c 6f", "10fe07000548616c6c6f", "00", ""},
|
||||
{"x,,hex:11", "", "10fe07000a48616c6c6f2c20447521", "00", "rW"},
|
||||
{"x,,hex,2", "", "", "", "c"},
|
||||
{"x,,hex:5,=48 61 6c 6c 6f", "", "10fe070005ababababab", "00", "W"},
|
||||
{"x,,hex:5,==48 61 6c 6c 6f", "", "10fe070005ababababab", "00", "rW"},
|
||||
{"x,,hex:5,=48 61 6c 6c 6f", "", "10fe07000548616c6c6f", "00", ""},
|
||||
{"x,,hex:5,==48 61 6c 6c 6f", "", "10fe07000548616c6c6f", "00", ""},
|
||||
{"x,,bda", "26.10.2014","10fe07000426100614", "00", ""}, // Sunday
|
||||
{"x,,bda", "01.01.2000","10fe07000401010500", "00", ""}, // Saturday
|
||||
{"x,,bda", "31.12.2099","10fe07000431120399", "00", ""}, // Thursday
|
||||
@@ -255,6 +263,10 @@ int main()
|
||||
{"x,,uch", "-", "10feffff01ff", "00", ""},
|
||||
{"x,,uch,10", "3.8", "10feffff0126", "00", ""},
|
||||
{"x,,uch,-10", "380","10feffff0126", "00", ""},
|
||||
{"x,,uch,=48", "", "10feffff01ab", "00", "W"},
|
||||
{"x,,uch,==48", "", "10feffff01ab", "00", "rW"},
|
||||
{"x,,uch,=48", "", "10feffff0130", "00", ""},
|
||||
{"x,,uch,==48", "", "10feffff0130", "00", ""},
|
||||
{"x,,sch", "-90", "10feffff01a6", "00", ""},
|
||||
{"x,,sch", "0", "10feffff0100", "00", ""},
|
||||
{"x,,sch", "-1", "10feffff01ff", "00", ""},
|
||||
|
||||
@@ -65,8 +65,10 @@ int main()
|
||||
{"temp2,D2B,,°C,Temperatur", "", "", "", "template"},
|
||||
{"power,UCH,,kW", "", "", "", "template"},
|
||||
{"sensor,UCH,0=ok;85=circuit;170=cutoff,,Fühlerstatus", "", "", "", "template"},
|
||||
{"sensorc,UCH,=85,,Fühlerstatus", "", "", "", "template"},
|
||||
{"pumpstate,UCH,0=off;1=on;2=overrun,,Pumpenstatus", "", "", "", "template"},
|
||||
{"tempsensor,temp;sensor,,Temperatursensor", "", "", "", "template"},
|
||||
{"tempsensorc,temp;sensorc,,Temperatursensor", "", "", "", "template"},
|
||||
{"r,,Status01,VL/RL/AussenTemp/VLWW/SpeicherTemp/Status,,08,B511,01,,,temp1;temp1;temp2;temp1;temp1;pumpstate","28.0;24.0;4.938;35.0;41.0;4","ff08b5110101","093830f00446520400ff","d"},
|
||||
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,tempsensor", "temp=-14.00 Temperatursensor [Temperatur];sensor=ok [Fühlerstatus]", "ff25b509030d2800", "0320ff00", "mD"},
|
||||
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,tempsensor,,field unit,field comment", "temp=-14.00 field unit [field comment];sensor=ok [Fühlerstatus]", "ff25b509030d2800", "0320ff00", "mD"},
|
||||
@@ -74,6 +76,8 @@ int main()
|
||||
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,tempsensor,,field unit,field comment", "\n \"temp\": {\"value\": -14.00, \"unit\": \"field unit\", \"comment\": \"field comment\"},\n \"sensor\": {\"value\": \"ok\", \"comment\": \"Fühlerstatus\"}", "ff25b509030d2800", "0320ff00", "mJ"},
|
||||
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,temp,,field unit,field comment,,,sensor", "temp=-14.00 field unit [field comment];sensor=ok [Fühlerstatus]", "ff25b509030d2800", "0320ff00", "mD"},
|
||||
{"r,message circuit,message name,message comment,,25,B509,0d2800,,,D2C,,°C,Temperatur,,,sensor", "\n \"0\": {\"name\": \"\", \"value\": -14.00},\n \"1\": {\"name\": \"sensor\", \"value\": \"ok\"}", "ff25b509030d2800", "0320ff00", "mj"},
|
||||
{"r,,name,,,25,B509,0d2800,,,tempsensorc", "-14.00", "ff25b509030d2800", "0320ff55", "m"},
|
||||
{"r,,name,,,25,B509,0d28,,m,sensorc,,,,,,temp", "-14.00", "ff25b509030d2855", "0220ff", "m"},
|
||||
{"u,,first,,,fe,0700,,x,,bda", "26.10.2014", "fffe07000426100614", "00", "p"},
|
||||
{"u,broadcast,hwStatus,,,fe,b505,27,,,UCH,,,,,,UCH,,,,,,UCH,,,", "0;19;0", "10feb505042700130097", "00", ""},
|
||||
{"w,,first,,,15,b509,0400,date,,bda", "26.10.2014", "ff15b50906040026100614", "00", "m"},
|
||||
|
||||
Reference in New Issue
Block a user