made SymbolString master/slave aware and contain only unescaped data, moved CRC tracking and escpaing/enscaping to BusHandler, moved parseInt/parseSignedInt from datatype.h to symbol.h, added new error code for retrival of unexpted symbol after a send to the bus

This commit is contained in:
john30
2017-02-26 16:31:32 +01:00
parent 5087ece9a4
commit 1a878694d2
17 changed files with 586 additions and 565 deletions
+95 -62
View File
@@ -32,9 +32,9 @@ namespace ebusd {
/** @file lib/ebus/symbol.h
* Classes, functions, and constants related to symbols on the eBUS.
*
* The @a SymbolString class is used for escaping or unescaping a sequence of
* bytes in preparation for sending to the bus or after reception of bytes from
* the bus, as well as calculating and verifying the CRC of a message part.
* The @a SymbolString class is used for holding a sequence of bytes received
* from or sent to the bus, as well as calculating and verifying the CRC of a
* message part.
*
* A message on the bus always consists of a command part, i.e. the data sent
* from a master to the bus. The command part starts with the sending master
@@ -70,51 +70,83 @@ using std::vector;
/** escape symbol, either followed by 0x00 for the value 0xA9, or 0x01 for the value 0xAA. */
#define ESC 0xA9
/** synchronization symbol. */
#define SYN 0xAA
/** positive acknowledge symbol. */
#define ACK 0x00
/** negative acknowledge symbol. */
#define NAK 0xFF
/** the broadcast destination address. */
#define BROADCAST 0xFE
/**
* Parse an unsigned int value.
* @param str the string to parse.
* @param base the numerical base.
* @param minValue the minimum resulting value.
* @param maxValue the maximum resulting value.
* @param result the variable in which to store an error code when parsing failed or the value is out of bounds.
* @param length the optional variable in which to store the number of read characters.
* @return the parsed value.
*/
unsigned int parseInt(const char* str, int base, const unsigned int minValue, const unsigned int maxValue,
result_t& result, unsigned int* length = NULL);
/**
* A string of escaped or unescaped bus symbols.
* Parse a signed int value.
* @param str the string to parse.
* @param base the numerical base.
* @param minValue the minimum resulting value.
* @param maxValue the maximum resulting value.
* @param result the variable in which to store an error code when parsing failed or the value is out of bounds.
* @param length the optional variable in which to store the number of read characters.
* @return the parsed value.
*/
int parseSignedInt(const char* str, int base, const int minValue, const int maxValue, result_t& result,
unsigned int* length = NULL);
/**
* A string of unescaped bus symbols.
*/
class SymbolString {
public:
/**
* Creates a new empty escaped or unescaped instance.
* @param escaped whether to create an escaped instance.
* Creates a new empty instance.
* @param isMaster whether this instance if for the master part.
*/
explicit SymbolString(const bool escaped = true) : m_unescapeState(escaped ? 0 : 1), m_crc(0) {}
explicit SymbolString(const bool isMaster = false) { m_isMaster = isMaster; }
/**
* Add all symbols from the other @a SymbolString and the calculated CRC if escaped.
* @param str the @a SymbolString to copy from.
* @param skipLastSymbol whether to skip the last symbol (probably the CRC).
* Update the CRC by adding a value.
* @param crc the current CRC to update.
* @param value the escaped value to add to the current CRC.
*/
void addAll(const SymbolString& str, const bool skipLastSymbol = false);
static void updateCrc(unsigned char& crc, const unsigned char value);
/**
* Parse the escaped or unescaped hex @a string, add all symbols, and add the calculated CRC if escaped.
* Parse the hex @a string and add all symbols.
* @param str the hex @a string.
* @param isEscaped whether the hex string is escaped.
* @return @a RESULT_OK on success, or an error code.
*/
result_t parseHex(const string& str, const bool isEscaped = false);
result_t parseHex(const string& str);
/**
* Parse the escaped hex @a string and add all symbols.
* @param str the hex @a string.
* @return @a RESULT_OK on success, or an error code.
*/
result_t parseHexEscaped(const string& str);
/**
* Return the symbols as hex string.
* @param unescape whether to unescape an escaped instance.
* @param skipLastSymbol whether to skip the last symbol (probably the CRC).
* @param skipFirstSymbols the number of first symbols to skip.
* @return the symbols as hex string.
*/
const string getDataStr(const bool unescape = true, const bool skipLastSymbol = true,
unsigned char skipFirstSymbols = 0);
const string getDataStr(unsigned char skipFirstSymbols = 0);
/**
* Return a reference to the symbol at the specified index.
@@ -131,11 +163,10 @@ class SymbolString {
/**
* Return whether this instance is equal to the other instance.
* @param other the other instance.
* @return true if this instance is equal to the other instance (i.e. both escaped or both unescaped and same
* symbols).
* @return true if this instance is equal to the other instance.
*/
bool operator == (SymbolString& other) {
return m_unescapeState == other.m_unescapeState && m_data == other.m_data;
return m_isMaster == other.m_isMaster && m_data == other.m_data;
}
/**
@@ -144,24 +175,26 @@ class SymbolString {
* @return true if this instance is different from the other instance.
*/
bool operator != (SymbolString& other) {
return m_unescapeState != other.m_unescapeState || m_data != other.m_data;
return m_isMaster != other.m_isMaster || m_data != other.m_data;
}
/**
* Compares this instance to the other instance while treating both as master data (i.e. starting with the master
* address and ending with the CRC).
* Compare the data in this instance to that of the other instance.
* @param other the other instance.
* @return 0 if this instance is equal to the other instance (i.e. both escaped or both unescaped and same symbols),
* 1 if this instance is completely different to the other instance,
* 2 if this instance only differs from the other instance in the first byte (the master address).
* @return 0 if the data is equal,
* 1 if the data is completely different,
* 2 if both instances are a master part and the data only differs in the first byte (the master address).
*/
int compareMaster(SymbolString& other) {
if (m_unescapeState != other.m_unescapeState || m_data.size() != other.m_data.size()) {
int compareTo(SymbolString& other) {
if (m_data.size() != other.m_data.size()) {
return 1;
}
if (m_data == other.m_data) {
return 0;
}
if (!m_isMaster) {
return 1;
}
if (m_data.size() == 1) {
return 2;
}
@@ -172,15 +205,10 @@ class SymbolString {
}
/**
* Appends a the symbol to the end of the symbol string and escapes/unescapes it if necessary.
* Append a symbol to the end of the symbol string.
* @param value the symbol to append.
* @param isEscaped whether the symbol is escaped.
* @param updateCRC whether to update the calculated CRC in @a m_crc.
* @return RESULT_OK if another symbol was appended,
* RESULT_IN_ESC if this is an unescaped instance and the symbol is escaped and the start of the escape sequence was
* received, RESULT_ERR_ESC if this is an unescaped instance and an invalid escaped sequence was detected.
*/
result_t push_back(const unsigned char value, const bool isEscaped = true, const bool updateCRC = true);
void push_back(const unsigned char value) { m_data.push_back(value); }
/**
* Return the number of symbols in this symbol string.
@@ -189,21 +217,39 @@ class SymbolString {
unsigned char size() const { return (unsigned char)m_data.size(); }
/**
* Return the calculated CRC.
* Return the offset to the first data byte DD.
* @return the offset to the first data byte DD.
*/
unsigned char getDataOffset() const { return m_isMaster ? 5 : 1; }
/**
* Return the number of data bytes DD.
* @return the number of data bytes DD.
*/
unsigned char getDataSize() const { return m_data.size() > (m_isMaster ? 4 : 0) ? m_data[m_isMaster ? 4 : 0] : 0; }
/**
* Return whether the byte sequence is complete with regard to the header and length field.
* @return true if the sequence is complete.
*/
bool isComplete() {
size_t lengthOffset = (m_isMaster ? 4 : 0);
if (m_data.size() < lengthOffset + 1) {
return false;
}
return m_data.size() >= lengthOffset + 1 + m_data[lengthOffset];
}
/**
* Calculate the CRC.
* @return the calculated CRC.
*/
unsigned char getCRC() const { return m_crc; }
unsigned char calcCrc() const;
/**
* Clear the symbols.
*/
void clear() { m_data.clear(); m_unescapeState = m_unescapeState == 0 ? 0 : 1; m_crc = 0; }
/**
* Clear the symbols and adjust the escape mode.
* @param escape true to set to an escaped instance, false to set to an unescaped instance.
*/
void clear(const bool escape) { m_data.clear(); m_unescapeState = escape ? 0 : 1; m_crc = 0; }
void clear() { m_data.clear(); }
private:
@@ -212,26 +258,13 @@ class SymbolString {
* @param str the @a SymbolString to copy from.
*/
SymbolString(const SymbolString& str)
: m_data(str.m_data), m_unescapeState(str.m_unescapeState), m_crc(str.m_crc) {}
: m_data(str.m_data), m_isMaster(str.m_isMaster) {}
/**
* Update the calculated CRC in @a m_crc by adding a value.
* @param value the (escaped) value to add to the calculated CRC in @a m_crc.
*/
void addCRC(const unsigned char value);
/** the string of bus symbols. */
/** the string of unescaped symbols. */
vector<unsigned char> m_data;
/**
* 0 if the symbols in @a m_data are escaped,
* 1 if the symbols in @a m_data are unescaped and the last symbol passed to @a push_back was a normal symbol,
* 2 if the symbols in @a m_data are unescaped and the last symbol passed to @a push_back was the escape symbol.
*/
int m_unescapeState;
/** the calculated CRC. */
unsigned char m_crc;
/** whether this instance if for the master part. */
bool m_isMaster;
};