diff --git a/src/lib/ebus/data.cpp b/src/lib/ebus/data.cpp index 6decd204..1d0f6fce 100644 --- a/src/lib/ebus/data.cpp +++ b/src/lib/ebus/data.cpp @@ -38,6 +38,7 @@ static const dataType_t dataTypes[] = { {"HDA", 32, bt_dat, 0, 0, 10, 10, 0, 0}, // date with weekday, 01.01.2000 - 31.12.2099 (0x01,0x01,WW,0x00 - 0x31,0x12,WW,0x99, 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 - 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) + {"HTI", 24, bt_tim, 0, 0, 5, 5, 0, 0}, // time, 00:00:00 - 23:59:59 (0x00,0x00,0x00 - 0x17,0x3b,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) {"BDY", 8, bt_num, DAY|LST, 0x07, 0, 6, 1, 0}, // weekday, "Mon" - "Sun" (0x00 - 0x06) [ebus type] @@ -97,7 +98,7 @@ unsigned int parseInt(const char* str, int base, const unsigned int minValue, co result_t DataField::create(vector::iterator& it, const vector::iterator end, - const map< string, DataField*> templates, + DataFieldTemplates* templates, DataField*& returnField, const bool isSetMessage, const unsigned char dstAddress) { @@ -199,20 +200,20 @@ result_t DataField::create(vector::iterator& it, if (pos == string::npos) { length = 0; // check for reference(s) to templates - if (templates.empty() == false) { + if (templates != NULL) { istringstream stream(typeStr); bool found = false; string lengthStr; while (getline(stream, token, VALUE_SEPARATOR) != 0) { - map::const_iterator ref = templates.find(token); - if (ref == templates.end()) { + DataField* templ = templates->get(token); + if (templ == NULL) { if (found == false) break; // fallback to direct definition result = RESULT_ERR_INVALID_ARG; // cannot mix reference and direct definition break; } found = true; - result = ref->second->derive(name, comment, unit, partType, divisor, values, fields); + result = templ->derive(name, comment, unit, partType, divisor, values, fields); if (result != RESULT_OK) break; } @@ -1030,3 +1031,41 @@ result_t DataFieldSet::write(istringstream& input, return RESULT_OK; } + + +void DataFieldTemplates::clear() +{ + for (map::iterator it=m_fieldsByName.begin(); it!=m_fieldsByName.end(); it++) { + delete it->second; + it->second = NULL; + } + m_fieldsByName.clear(); +} + +result_t DataFieldTemplates::add(DataField* field, bool replace) +{ + string name = field->getName(); + map::iterator it = m_fieldsByName.find(name); + if (it != m_fieldsByName.end()) { + if (replace == false) + return RESULT_ERR_INVALID_ARG; // duplicate key + + delete it->second; + it->second = field; + + return RESULT_OK; + } + + m_fieldsByName[name] = field; + + return RESULT_OK; +} + +DataField* DataFieldTemplates::get(const string name) +{ + map::const_iterator ref = m_fieldsByName.find(name); + if (ref == m_fieldsByName.end()) + return NULL; + + return ref->second; +} diff --git a/src/lib/ebus/data.h b/src/lib/ebus/data.h index 0045488b..874bbe61 100644 --- a/src/lib/ebus/data.h +++ b/src/lib/ebus/data.h @@ -79,6 +79,7 @@ typedef struct { unsigned int parseInt(const char* str, int base, const unsigned int minValue, const unsigned int maxValue, result_t& result, unsigned int* length=NULL); +class DataFieldTemplates; class SingleDataField; /** @@ -103,7 +104,7 @@ public: * @brief Factory method for creating new instances. * @param it the iterator to traverse for the definition parts. * @param end the iterator pointing to the end of the definition parts. - * @param templates a map of @a DataField templates to be referenced by name. + * @param templates the @a DataFieldTemplates to be referenced by name, or NULL. * @param returnField the variable in which to store the created instance. * @param isSetMessage whether the field is part of a set message (default false). * @param dstAddress the destination bus address (default @a SYN for creating a template @a DataField). @@ -111,7 +112,7 @@ public: * Note: the caller needs to free the created instance. */ static result_t create(vector::iterator& it, const vector::iterator end, - const map templates, DataField*& returnField, + DataFieldTemplates* templates, DataField*& returnField, const bool isSetMessage=false, const unsigned char dstAddress=SYN); /** * @brief Returns the length of this field (or contained fields) in bytes. @@ -279,6 +280,8 @@ protected: */ virtual result_t writeSymbols(istringstream& input, const unsigned char offset, SymbolString& output) = 0; +protected: + /** the value unit. */ const string m_unit; /** the data type definition. */ @@ -386,7 +389,6 @@ protected: /** the offset to the first bit in the binary value. */ const unsigned char m_bitOffset; - }; @@ -431,6 +433,8 @@ protected: // @copydoc virtual result_t writeSymbols(istringstream& input, const unsigned char offset, SymbolString& output); +private: + /** the combined divisor to apply on the value, or 1 for none. */ const unsigned int m_divisor; @@ -478,6 +482,8 @@ protected: // @copydoc virtual result_t writeSymbols(istringstream& input, const unsigned char offset, SymbolString& output); +private: + /** the value=text assignments. */ map m_values; @@ -540,7 +546,7 @@ public: SymbolString& slaveData, unsigned char slaveOffset, char separator); -protected: +private: /** the @a vector of @a SingleDataField instances part of this set. */ vector m_fields; @@ -548,4 +554,45 @@ protected: }; +/** + * @brief A map of template @a DataField instances. + */ +class DataFieldTemplates +{ +public: + + /** + * @brief Constructs a new instance. + */ + DataFieldTemplates() {} + /** + * @brief Destructor. + */ + virtual ~DataFieldTemplates() { clear(); } + /** + * @brief Removes all @a DataField instances. + */ + void clear(); + /** + * @brief Adds a template @a DataField instance to this map. + * @param field the @a DataField instance to add. + * @param replace whether replacing an already stored instance is allowed. + * @return @a RESULT_OK on success, or an error code. + * Note: the caller may not free the added instance on success. + */ + result_t add(DataField* message, bool replace=false); + /** + * @brief Gets the template @a DataField instance with the specified name. + * @return the template @a DataField instance, or NULL. + * Note: the caller may not free the returned instance. + */ + DataField* get(string name); + +private: + + /** the known template @a DataField instances by name. */ + map m_fieldsByName; + +}; + #endif // LIBEBUS_DATA_H_