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
+219 -138
View File
@@ -46,13 +46,17 @@ const char* getStateCode(BusState state) {
case bs_skip: return "skip";
case bs_ready: return "ready";
case bs_sendCmd: return "send command";
case bs_recvCmdCrc: return "receive command CRC";
case bs_recvCmdAck: return "receive command ACK";
case bs_recvRes: return "receive response";
case bs_recvResCrc: return "receive response CRC";
case bs_sendResAck: return "send response ACK";
case bs_recvCmd: return "receive command";
case bs_recvResAck: return "receive response ACK";
case bs_sendCmdCrc: return "send command CRC";
case bs_sendCmdAck: return "send command ACK";
case bs_sendRes: return "send response";
case bs_sendResCrc: return "send response CRC";
case bs_sendSyn: return "send SYN";
default: return "unknown";
}
@@ -181,22 +185,22 @@ bool ActiveBusRequest::notify(result_t result, SymbolString& slave) {
logDebug(lf_bus, "read res: %s", slave.getDataStr().c_str());
}
m_result = result;
m_slave.addAll(slave, true);
m_slave = slave;
return false;
}
void GrabbedMessage::setLastData(SymbolString& master, SymbolString& slave) {
m_lastMaster.clear(false);
m_lastMaster.addAll(master);
m_lastSlave.clear(false);
m_lastSlave.addAll(slave);
m_lastMaster.clear();
m_lastMaster = master;
m_lastSlave.clear();
m_lastSlave = slave;
m_count++;
}
/**
* Decode the input @a SymbolString with the specified @a DataType and length.
* @param type the @a DataType.
* @param input the unescaped @a SymbolString to read the binary value from.
* @param input the @a SymbolString to read the binary value from.
* @param isMaster whether the @a SymbolString is the master part.
* @param baseOffset the base offset in the @a SymbolString.
* @param length the number of symbols to read.
@@ -208,7 +212,7 @@ void GrabbedMessage::setLastData(SymbolString& master, SymbolString& slave) {
bool decodeType(DataType* type, SymbolString *input, bool isMaster, unsigned char baseOffset, unsigned char length,
unsigned char offsets, ostringstream& output, bool firstOnly = false) {
bool first = true;
string in = input->getDataStr(true, true, baseOffset);
string in = input->getDataStr(baseOffset);
for (unsigned char offset = 0; offset <= offsets; offset++) {
ostringstream out;
result_t result = type->readSymbols(*input, isMaster, (unsigned char)(baseOffset+offset), (unsigned char)length,
@@ -352,7 +356,7 @@ result_t BusHandler::readFromBus(Message* message, string inputStr, const unsign
unsigned char masterAddress = srcAddress == SYN ? m_ownMasterAddress : srcAddress;
result_t ret = RESULT_EMPTY;
SymbolString master(true);
SymbolString slave(false);
SymbolString slave;
for (unsigned char index = 0; index < message->getCount(); index++) {
istringstream input(inputStr);
ret = message->prepareMaster(masterAddress, master, input, UI_FIELD_SEPARATOR, dstAddress, index);
@@ -463,11 +467,13 @@ result_t BusHandler::handleSymbol() {
break;
case bs_recvCmd:
case bs_recvCmdCrc:
case bs_recvCmdAck:
timeout = m_slaveRecvTimeout;
break;
case bs_recvRes:
case bs_recvResCrc:
if (m_response.size() > 0 || m_slaveRecvTimeout > SYN_TIMEOUT) {
timeout = m_slaveRecvTimeout;
} else {
@@ -481,28 +487,42 @@ result_t BusHandler::handleSymbol() {
case bs_sendCmd:
if (m_currentRequest != NULL) {
sendSymbol = m_currentRequest->m_master[m_nextSendPos]; // escaped command
sendSymbol = m_currentRequest->m_master[m_nextSendPos]; // unescaped command
sending = true;
}
break;
case bs_sendCmdCrc:
if (m_currentRequest != NULL) {
sendSymbol = m_crc;
sending = true;
}
break;
case bs_sendResAck:
if (m_currentRequest != NULL) {
sendSymbol = m_responseCrcValid ? ACK : NAK;
sendSymbol = m_crcValid ? ACK : NAK;
sending = true;
}
break;
case bs_sendCmdAck:
if (m_answer) {
sendSymbol = m_commandCrcValid ? ACK : NAK;
sendSymbol = m_crcValid ? ACK : NAK;
sending = true;
}
break;
case bs_sendRes:
if (m_answer) {
sendSymbol = m_response[m_nextSendPos]; // escaped response
sendSymbol = m_response[m_nextSendPos]; // unescaped response
sending = true;
}
break;
case bs_sendResCrc:
if (m_currentRequest != NULL) {
sendSymbol = m_crc;
sending = true;
}
break;
@@ -516,6 +536,14 @@ result_t BusHandler::handleSymbol() {
// send symbol if necessary
result_t result;
if (sending) {
if (m_state != bs_sendSyn && (sendSymbol == ESC || sendSymbol == SYN)) {
if (m_escape) {
sendSymbol = sendSymbol == ESC ? 0x00 : 0x01;
} else {
m_escape = sendSymbol;
sendSymbol = ESC;
}
}
result = m_device->send(sendSymbol);
if (result == RESULT_OK) {
if (m_state == bs_ready) {
@@ -587,7 +615,39 @@ result_t BusHandler::handleSymbol() {
return setState(bs_ready, m_state == bs_skip ? RESULT_OK : RESULT_ERR_SYN);
}
unsigned int headerLen, crcPos;
switch (m_state) {
case bs_ready:
case bs_recvCmd:
case bs_recvRes:
case bs_sendCmd:
case bs_sendRes:
SymbolString::updateCrc(m_crc, recvSymbol);
break;
default:
break;
}
if (m_escape) {
// check escape/unescape state
if (sending) {
if (recvSymbol != sendSymbol) {
return setState(bs_skip, RESULT_ERR_SYMBOL);
}
if (sendSymbol == ESC) {
return RESULT_OK;
}
sendSymbol = recvSymbol = m_escape;
} else {
if (recvSymbol > 0x01) {
return setState(bs_skip, RESULT_ERR_ESC);
}
recvSymbol = recvSymbol == 0x00 ? ESC : SYN;
}
m_escape = 0;
} else if (!sending && recvSymbol == ESC) {
m_escape = ESC;
return RESULT_OK;
}
switch (m_state) {
case bs_noSignal:
@@ -617,59 +677,55 @@ result_t BusHandler::handleSymbol() {
}
setState(m_state, RESULT_ERR_BUS_LOST); // try again later
}
result = m_command.push_back(recvSymbol, false); // expect no escaping for master address
if (result < RESULT_OK) {
return setState(bs_skip, result);
}
m_command.push_back(recvSymbol);
m_repeat = false;
return setState(bs_recvCmd, RESULT_OK);
case bs_recvCmd:
headerLen = 4;
// header symbols are never escaped
crcPos = m_command.size() > headerLen ? headerLen + 1 + m_command[headerLen] : 0xff;
result = m_command.push_back(recvSymbol, true, m_command.size() < crcPos);
if (result < RESULT_OK) {
return setState(bs_skip, result);
}
if (result == RESULT_OK && crcPos != 0xff && m_command.size() == crcPos + 1) { // CRC received
unsigned char dstAddress = m_command[1];
// header symbols are never escaped
m_commandCrcValid = m_command[headerLen + 1 + m_command[headerLen]] == m_command.getCRC();
if (m_commandCrcValid) {
if (dstAddress == BROADCAST) {
receiveCompleted();
return setState(bs_skip, RESULT_OK);
}
addSeenAddress(m_command[0]);
if (m_answer && (dstAddress == m_ownMasterAddress || dstAddress == m_ownSlaveAddress)) {
return setState(bs_sendCmdAck, RESULT_OK);
}
return setState(bs_recvCmdAck, RESULT_OK);
}
if (dstAddress == BROADCAST) {
return setState(bs_skip, RESULT_ERR_CRC);
}
if (m_answer && (dstAddress == m_ownMasterAddress || dstAddress == m_ownSlaveAddress)) {
return setState(bs_sendCmdAck, RESULT_ERR_CRC);
}
if (m_repeat) {
return setState(bs_skip, RESULT_ERR_CRC);
}
return setState(bs_recvCmdAck, RESULT_ERR_CRC);
m_command.push_back(recvSymbol);
if (m_command.isComplete()) { // all data received
return setState(bs_recvCmdCrc, RESULT_OK);
}
return RESULT_OK;
case bs_recvCmdCrc:
m_crcValid = recvSymbol == m_crc;
if (m_command[1] == BROADCAST) {
if (m_crcValid) {
receiveCompleted();
return setState(bs_skip, RESULT_OK);
}
return setState(bs_skip, RESULT_ERR_CRC);
}
if (m_answer) {
unsigned char dstAddress = m_command[1];
if (dstAddress == m_ownMasterAddress || dstAddress == m_ownSlaveAddress) {
if (m_crcValid) {
addSeenAddress(m_command[0]);
return setState(bs_sendCmdAck, RESULT_OK);
}
return setState(bs_sendCmdAck, RESULT_ERR_CRC);
}
}
if (m_crcValid) {
addSeenAddress(m_command[0]);
return setState(bs_recvCmdAck, RESULT_OK);
}
if (m_repeat) {
return setState(bs_skip, RESULT_ERR_CRC);
}
return setState(bs_recvCmdAck, RESULT_ERR_CRC);
case bs_recvCmdAck:
if (recvSymbol == ACK) {
if (!m_commandCrcValid) {
if (!m_crcValid) {
return setState(bs_skip, RESULT_ERR_ACK);
}
if (m_currentRequest != NULL) {
if (isMaster(m_currentRequest->m_master[1])) {
return setState(bs_sendSyn, RESULT_OK);
}
} else if (isMaster(m_command[1])) { // header symbols are never escaped
} else if (isMaster(m_command[1])) {
receiveCompleted();
return setState(bs_skip, RESULT_OK);
}
@@ -680,6 +736,7 @@ result_t BusHandler::handleSymbol() {
if (recvSymbol == NAK) {
if (!m_repeat) {
m_repeat = true;
m_crc = 0;
m_nextSendPos = 0;
m_command.clear();
if (m_currentRequest != NULL) {
@@ -692,36 +749,34 @@ result_t BusHandler::handleSymbol() {
return setState(bs_skip, RESULT_ERR_ACK);
case bs_recvRes:
headerLen = 0;
crcPos = m_response.size() > headerLen ? headerLen + 1 + m_response[headerLen] : 0xff;
result = m_response.push_back(recvSymbol, true, m_response.size() < crcPos);
if (result < RESULT_OK) {
return setState(bs_skip, result);
}
if (result == RESULT_OK && crcPos != 0xff && m_response.size() == crcPos + 1) { // CRC received
m_responseCrcValid = m_response[headerLen + 1 + m_response[headerLen]] == m_response.getCRC();
if (m_responseCrcValid) {
if (m_currentRequest != NULL) {
return setState(bs_sendResAck, RESULT_OK);
}
return setState(bs_recvResAck, RESULT_OK);
}
if (m_repeat) {
if (m_currentRequest != NULL) {
return setState(bs_sendSyn, RESULT_ERR_CRC);
}
return setState(bs_skip, RESULT_ERR_CRC);
}
if (m_currentRequest != NULL) {
return setState(bs_sendResAck, RESULT_ERR_CRC);
}
return setState(bs_recvResAck, RESULT_ERR_CRC);
m_response.push_back(recvSymbol);
if (m_response.isComplete()) { // all data received
return setState(bs_recvResCrc, RESULT_OK);
}
return RESULT_OK;
case bs_recvResCrc:
m_crcValid = recvSymbol == m_crc;
if (m_crcValid) {
if (m_currentRequest != NULL) {
return setState(bs_sendResAck, RESULT_OK);
}
return setState(bs_recvResAck, RESULT_OK);
}
if (m_repeat) {
if (m_currentRequest != NULL) {
return setState(bs_sendSyn, RESULT_ERR_CRC);
}
return setState(bs_skip, RESULT_ERR_CRC);
}
if (m_currentRequest != NULL) {
return setState(bs_sendResAck, RESULT_ERR_CRC);
}
return setState(bs_recvResAck, RESULT_ERR_CRC);
case bs_recvResAck:
if (recvSymbol == ACK) {
if (!m_responseCrcValid) {
if (!m_crcValid) {
return setState(bs_skip, RESULT_ERR_ACK);
}
receiveCompleted();
@@ -738,54 +793,66 @@ result_t BusHandler::handleSymbol() {
return setState(bs_skip, RESULT_ERR_ACK);
case bs_sendCmd:
if (m_currentRequest != NULL && sending && recvSymbol == sendSymbol) {
// successfully sent
m_nextSendPos++;
if (m_nextSendPos >= m_currentRequest->m_master.size()) {
// master data completely sent
if (m_currentRequest->m_master[1] == BROADCAST) {
return setState(bs_sendSyn, RESULT_OK);
}
m_commandCrcValid = true;
return setState(bs_recvCmdAck, RESULT_OK);
}
return RESULT_OK;
if (!sending || m_currentRequest == NULL) {
return setState(bs_skip, RESULT_ERR_INVALID_ARG);
}
return setState(bs_skip, RESULT_ERR_INVALID_ARG);
if (recvSymbol != sendSymbol) {
return setState(bs_skip, RESULT_ERR_SYMBOL);
}
m_nextSendPos++;
if (m_nextSendPos >= m_currentRequest->m_master.size()) {
return setState(bs_sendCmdCrc, RESULT_OK);
}
return RESULT_OK;
case bs_sendResAck:
if (m_currentRequest != NULL && sending && recvSymbol == sendSymbol) {
// successfully sent
if (!m_responseCrcValid) {
if (!m_repeat) {
m_repeat = true;
m_response.clear();
return setState(bs_recvRes, RESULT_ERR_NAK, true);
}
return setState(bs_sendSyn, RESULT_ERR_ACK);
}
case bs_sendCmdCrc:
if (m_currentRequest->m_master[1] == BROADCAST) {
return setState(bs_sendSyn, RESULT_OK);
}
return setState(bs_skip, RESULT_ERR_INVALID_ARG);
m_crcValid = true;
return setState(bs_recvCmdAck, RESULT_OK);
case bs_sendResAck:
if (!sending || m_currentRequest == NULL) {
return setState(bs_skip, RESULT_ERR_INVALID_ARG);
}
if (recvSymbol != sendSymbol) {
return setState(bs_skip, RESULT_ERR_SYMBOL);
}
if (!m_crcValid) {
if (!m_repeat) {
m_repeat = true;
m_response.clear();
return setState(bs_recvRes, RESULT_ERR_NAK, true);
}
return setState(bs_sendSyn, RESULT_ERR_ACK);
}
return setState(bs_sendSyn, RESULT_OK);
case bs_sendCmdAck:
if (sending && m_answer && recvSymbol == sendSymbol) {
// successfully sent
if (!m_commandCrcValid) {
if (!m_repeat) {
m_repeat = true;
m_command.clear();
return setState(bs_recvCmd, RESULT_ERR_NAK, true);
}
return setState(bs_skip, RESULT_ERR_ACK);
}
if (isMaster(m_command[1])) {
receiveCompleted(); // decode command and store value
return setState(bs_skip, RESULT_OK);
if (!sending || !m_answer) {
return setState(bs_skip, RESULT_ERR_INVALID_ARG);
}
if (recvSymbol != sendSymbol) {
return setState(bs_skip, RESULT_ERR_SYMBOL);
}
if (!m_crcValid) {
if (!m_repeat) {
m_repeat = true;
m_crc = 0;
m_command.clear();
return setState(bs_recvCmd, RESULT_ERR_NAK, true);
}
return setState(bs_skip, RESULT_ERR_ACK);
}
if (isMaster(m_command[1])) {
receiveCompleted(); // decode command and store value
return setState(bs_skip, RESULT_OK);
}
m_nextSendPos = 0;
m_repeat = false;
m_nextSendPos = 0;
m_repeat = false;
{
Message* message;
istringstream input; // TODO create input from database of internal variables
message = m_messages->find(m_command);
@@ -803,33 +870,45 @@ result_t BusHandler::handleSymbol() {
input.str(SCAN_ANSWER);
}
// build response and store in m_response for sending back to requesting master
m_response.clear(true); // escape while sending response
m_response.clear();
result = message->prepareSlave(input, m_response);
if (result != RESULT_OK) {
return setState(bs_skip, result);
}
return setState(bs_sendRes, RESULT_OK);
}
return setState(bs_skip, RESULT_ERR_INVALID_ARG);
return setState(bs_sendRes, RESULT_OK);
case bs_sendRes:
if (sending && m_answer && recvSymbol == sendSymbol) {
// successfully sent
m_nextSendPos++;
if (m_nextSendPos >= m_response.size()) {
// slave data completely sent
return setState(bs_recvResAck, RESULT_OK);
}
return RESULT_OK;
if (!sending || !m_answer) {
return setState(bs_skip, RESULT_ERR_INVALID_ARG);
}
return setState(bs_skip, RESULT_ERR_INVALID_ARG);
if (recvSymbol != sendSymbol) {
return setState(bs_skip, RESULT_ERR_SYMBOL);
}
m_nextSendPos++;
if (m_nextSendPos >= m_response.size()) {
// slave data completely sent
return setState(bs_sendResCrc, RESULT_OK);
}
return RESULT_OK;
case bs_sendResCrc:
if (!sending || m_currentRequest == NULL) {
return setState(bs_skip, RESULT_ERR_INVALID_ARG);
}
if (recvSymbol != sendSymbol) {
return setState(bs_skip, RESULT_ERR_SYMBOL);
}
return setState(bs_recvResAck, RESULT_OK);
case bs_sendSyn:
if (sending && recvSymbol == sendSymbol) {
// successfully sent
return setState(bs_skip, RESULT_OK);
if (!sending) {
return setState(bs_skip, RESULT_ERR_INVALID_ARG);
}
return setState(bs_skip, RESULT_ERR_INVALID_ARG);
if (recvSymbol != sendSymbol) {
return setState(bs_skip, RESULT_ERR_SYMBOL);
}
return setState(bs_skip, RESULT_OK);
}
return RESULT_OK;
}
@@ -863,7 +942,7 @@ result_t BusHandler::setState(BusState state, result_t result, bool firstRepetit
}
if (state == bs_noSignal) { // notify all requests
m_response.clear(false); // notify with empty response
m_response.clear(); // notify with empty response
while ((m_currentRequest = m_nextRequests.pop()) != NULL) {
bool restart = m_currentRequest->notify(RESULT_ERR_NO_SIGNAL, m_response);
if (restart) { // should not occur with no signal
@@ -877,6 +956,7 @@ result_t BusHandler::setState(BusState state, result_t result, bool firstRepetit
}
}
m_escape = 0;
if (state == m_state) {
return result;
}
@@ -895,12 +975,13 @@ result_t BusHandler::setState(BusState state, result_t result, bool firstRepetit
if (state == bs_ready || state == bs_skip) {
m_command.clear();
m_commandCrcValid = false;
m_response.clear(false); // unescape while receiving response
m_responseCrcValid = false;
m_crc = 0;
m_crcValid = false;
m_response.clear();
m_nextSendPos = 0;
} else if (state == bs_recvRes || state == bs_sendRes) {
m_crc = 0;
}
return result;
}
@@ -1182,7 +1263,7 @@ result_t BusHandler::scanAndWait(unsigned char dstAddress, SymbolString& slave)
return RESULT_ERR_NOTFOUND;
}
istringstream input;
SymbolString master;
SymbolString master(true);
result_t result = scanMessage->prepareMaster(m_ownMasterAddress, master, input, UI_FIELD_SEPARATOR, dstAddress);
if (result == RESULT_OK) {
result = sendAndWait(master, slave);
+27 -21
View File
@@ -66,13 +66,17 @@ enum BusState {
bs_skip, //!< skip all symbols until next @a SYN
bs_ready, //!< ready for next master (after @a SYN symbol, send/receive QQ)
bs_recvCmd, //!< receive command (ZZ, PBSB, master data) [passive set]
bs_recvCmdCrc, //!< receive command CRC [passive set]
bs_recvCmdAck, //!< receive command ACK/NACK [passive set + active set+get]
bs_recvRes, //!< receive response (slave data) [passive set + active get]
bs_recvResCrc, //!< receive response CRC [passive set + active get]
bs_recvResAck, //!< receive response ACK/NACK [passive set]
bs_sendCmd, //!< send command (ZZ, PBSB, master data) [active set+get]
bs_sendCmdCrc, //!< send command CRC [active set+get]
bs_sendResAck, //!< send response ACK/NACK [active get]
bs_sendCmdAck, //!< send command ACK/NACK [passive get]
bs_sendRes, //!< send response (slave data) [passive get]
bs_sendResCrc, //!< send response CRC [passive get]
bs_sendSyn, //!< send SYN for completed transfer [active set+get]
};
@@ -102,7 +106,7 @@ class BusRequest {
public:
/**
* Constructor.
* @param master the escaped master data @a SymbolString to send.
* @param master the master data @a SymbolString to send.
* @param deleteOnFinish whether to automatically delete this @a BusRequest when finished.
*/
BusRequest(SymbolString& master, const bool deleteOnFinish)
@@ -124,7 +128,7 @@ class BusRequest {
protected:
/** the escaped master data @a SymbolString to send. */
/** the master data @a SymbolString to send. */
SymbolString& m_master;
/** the number of times a send is repeated due to lost arbitration. */
@@ -166,8 +170,8 @@ class PollRequest : public BusRequest {
private:
/** the escaped master data @a SymbolString. */
SymbolString m_master;
/** the master data @a SymbolString. */
SymbolString m_master{true};
/** the associated @a Message. */
Message* m_message;
@@ -218,8 +222,8 @@ class ScanRequest : public BusRequest {
/** the @a MessageMap instance. */
MessageMap* m_messageMap;
/** the escaped master data @a SymbolString. */
SymbolString m_master;
/** the master data @a SymbolString. */
SymbolString m_master{true};
/** the currently queried @a Message. */
Message* m_message;
@@ -253,7 +257,7 @@ class ActiveBusRequest : public BusRequest {
public:
/**
* Constructor.
* @param master the escaped master data @a SymbolString to send.
* @param master the master data @a SymbolString to send.
* @param slave reference to @a SymbolString for filling in the received slave data.
*/
ActiveBusRequest(SymbolString& master, SymbolString& slave)
@@ -292,8 +296,8 @@ class GrabbedMessage {
* @param other the @a GrabbedMessage to copy from.
*/
GrabbedMessage(const GrabbedMessage& other) : m_count(other.m_count) {
m_lastMaster.addAll(other.m_lastMaster);
m_lastSlave.addAll(other.m_lastSlave);
m_lastMaster = other.m_lastMaster;
m_lastSlave = other.m_lastSlave;
}
/**
@@ -364,8 +368,7 @@ class BusHandler : public WaitThread {
m_pollInterval(pollInterval), m_lastReceive(0), m_lastPoll(0),
m_currentRequest(NULL), m_runningScans(0), m_nextSendPos(0),
m_symPerSec(0), m_maxSymPerSec(0),
m_state(bs_noSignal), m_repeat(false),
m_command(false), m_commandCrcValid(false), m_response(false), m_responseCrcValid(false),
m_state(bs_noSignal), m_escape(0), m_crc(0), m_crcValid(false), m_repeat(false),
m_grabMessages(true) {
memset(m_seenAddresses, 0, sizeof(m_seenAddresses));
}
@@ -398,7 +401,7 @@ class BusHandler : public WaitThread {
/**
* Send a message on the bus and wait for the answer.
* @param master the escaped @a SymbolString with the master data to send.
* @param master the @a SymbolString with the master data to send.
* @param slave the @a SymbolString that will be filled with retrieved slave data.
* @return the result code.
*/
@@ -632,21 +635,24 @@ class BusHandler : public WaitThread {
/** the current @a BusState. */
BusState m_state;
/** 0 when not escaping/unescaping, or @a ESC when receiving, or the original value when sending. */
unsigned char m_escape;
/** the calculated CRC. */
unsigned char m_crc;
/** whether the CRC matched. */
bool m_crcValid;
/** whether the current message part is being repeated. */
bool m_repeat;
/** the unescaped received command. */
SymbolString m_command;
/** the received command. */
SymbolString m_command{true};
/** whether the command CRC is valid. */
bool m_commandCrcValid;
/** the unescaped received response or escaped response to send. */
/** the received response or response to send. */
SymbolString m_response;
/** whether the response CRC is valid. */
bool m_responseCrcValid;
/** the participating bus addresses seen so far (0 if not seen yet, or combination of @a SEEN bits). */
unsigned char m_seenAddresses[256];
+32 -37
View File
@@ -233,7 +233,7 @@ void MainLoop::run() {
result = m_busHandler->startScan(true, "*");
} else {
logNotice(lf_main, "starting initial scan for %2.2x", m_initialScan);
SymbolString slave(false);
SymbolString slave;
result = m_busHandler->scanAndWait(m_initialScan, slave);
Message* message = m_messages->getScanMessage(m_initialScan);
if (result == RESULT_OK && message != NULL) {
@@ -257,7 +257,7 @@ void MainLoop::run() {
taskDelay = 5;
lastScanAddress = 0;
} else {
SymbolString slave(false);
SymbolString slave;
if (scanned) {
Message* message = m_messages->getScanMessage(lastScanAddress);
slave = message->getLastSlaveData();
@@ -486,13 +486,14 @@ result_t MainLoop::parseHexMaster(vector<string> &args, size_t argPos, SymbolStr
}
result_t ret;
unsigned int length = parseInt(msg.str().substr(3*2, 2).c_str(), 16, 0, MAX_POS, ret);
if (ret == RESULT_OK && (4+length)*2 != msg.str().size()) {
if (ret != RESULT_OK) {
return ret;
}
if ((4+length)*2 != msg.str().size()) {
return RESULT_ERR_INVALID_ARG;
}
ret = master.push_back(srcAddress == SYN ? m_address : srcAddress, false);
if (ret == RESULT_OK) {
ret = master.parseHex(msg.str());
}
master.push_back(srcAddress == SYN ? m_address : srcAddress);
ret = master.parseHex(msg.str());
if (ret == RESULT_OK && !isValidAddress(master[1])) {
ret = RESULT_ERR_INVALID_ADDR;
}
@@ -613,18 +614,18 @@ string MainLoop::executeRead(vector<string> &args, const string levels) {
time(&now);
if (hex && argPos > 0) {
SymbolString cacheMaster(false);
result_t ret = parseHexMaster(args, argPos, cacheMaster, srcAddress);
SymbolString master(true);
result_t ret = parseHexMaster(args, argPos, master, srcAddress);
if (ret != RESULT_OK) {
return getResultCode(ret);
}
if (cacheMaster[1] == BROADCAST || isMaster(cacheMaster[1])) {
if (master[1] == BROADCAST || isMaster(master[1])) {
return getResultCode(RESULT_ERR_INVALID_ARG);
}
logNotice(lf_main, "read hex cmd: %s", cacheMaster.getDataStr(true, false).c_str());
logNotice(lf_main, "read hex cmd: %s", master.getDataStr().c_str());
// find message
Message* message = m_messages->find(cacheMaster, false, true, false, false);
Message* message = m_messages->find(master, false, true, false, false);
if (message == NULL) {
return getResultCode(RESULT_ERR_NOTFOUND);
@@ -643,17 +644,15 @@ string MainLoop::executeRead(vector<string> &args, const string levels) {
|| (message->isPassive() && message->getLastUpdateTime() != 0))) {
SymbolString& slave = message->getLastSlaveData();
logNotice(lf_main, "hex read %s %s from cache", message->getCircuit().c_str(), message->getName().c_str());
return slave.getDataStr(true, false);
return slave.getDataStr();
}
// send message
SymbolString master(true);
master.addAll(cacheMaster);
SymbolString slave(false);
SymbolString slave;
ret = m_busHandler->sendAndWait(master, slave);
if (ret == RESULT_OK) {
ret = message->storeLastData(cacheMaster, slave);
ret = message->storeLastData(master, slave);
ostringstream result;
if (ret == RESULT_OK) {
ret = message->decodeLastData(result);
@@ -665,7 +664,7 @@ string MainLoop::executeRead(vector<string> &args, const string levels) {
logError(lf_main, "read hex %s %s cache update: %s", message->getCircuit().c_str(), message->getName().c_str(),
getResultCode(ret));
}
return slave.getDataStr(true, false);
return slave.getDataStr();
}
logError(lf_main, "read hex %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(),
getResultCode(ret));
@@ -822,15 +821,15 @@ string MainLoop::executeWrite(vector<string> &args, const string levels) {
}
if (hex && argPos > 0) {
SymbolString cacheMaster(false);
result_t ret = parseHexMaster(args, argPos, cacheMaster, srcAddress);
SymbolString master(true);
result_t ret = parseHexMaster(args, argPos, master, srcAddress);
if (ret != RESULT_OK) {
return getResultCode(ret);
}
logNotice(lf_main, "write hex cmd: %s", cacheMaster.getDataStr(true, false).c_str());
logNotice(lf_main, "write hex cmd: %s", master.getDataStr().c_str());
// find message
Message* message = m_messages->find(cacheMaster, false, false, true, false);
Message* message = m_messages->find(master, false, false, true, false);
if (message == NULL) {
return getResultCode(RESULT_ERR_NOTFOUND);
@@ -845,14 +844,12 @@ string MainLoop::executeWrite(vector<string> &args, const string levels) {
return getResultCode(RESULT_ERR_INVALID_ARG); // non-matching circuit
}
// send message
SymbolString master(true);
master.addAll(cacheMaster);
SymbolString slave(false);
SymbolString slave;
ret = m_busHandler->sendAndWait(master, slave);
if (ret == RESULT_OK) {
// also update read messages
ret = message->storeLastData(cacheMaster, slave);
ret = message->storeLastData(master, slave);
ostringstream result;
if (ret == RESULT_OK) {
ret = message->decodeLastData(result);
@@ -870,7 +867,7 @@ string MainLoop::executeWrite(vector<string> &args, const string levels) {
if (isMaster(master[1])) {
return getResultCode(RESULT_OK);
}
return slave.getDataStr(true, false);
return slave.getDataStr();
}
logError(lf_main, "write hex %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(),
getResultCode(ret));
@@ -959,17 +956,15 @@ string MainLoop::executeHex(vector<string> &args) {
}
if (argPos > 0) {
SymbolString cacheMaster(false);
result_t ret = parseHexMaster(args, argPos, cacheMaster, srcAddress);
SymbolString master(true);
result_t ret = parseHexMaster(args, argPos, master, srcAddress);
if (ret != RESULT_OK) {
return getResultCode(ret);
}
logNotice(lf_main, "hex cmd: %s", cacheMaster.getDataStr(true, false).c_str());
logNotice(lf_main, "hex cmd: %s", master.getDataStr().c_str());
// send message
SymbolString master(true);
master.addAll(cacheMaster);
SymbolString slave(false);
SymbolString slave;
ret = m_busHandler->sendAndWait(master, slave);
if (ret == RESULT_OK) {
@@ -979,7 +974,7 @@ string MainLoop::executeHex(vector<string> &args) {
if (isMaster(master[1])) {
return getResultCode(RESULT_OK);
}
return slave.getDataStr(true, false);
return slave.getDataStr();
}
logError(lf_main, "hex: %s", getResultCode(ret));
return getResultCode(ret);
@@ -1171,13 +1166,13 @@ string MainLoop::executeFind(vector<string> &args, string levels) {
result << "no data stored";
} else if (hexFormat) {
result << message->getLastMasterData().getDataStr()
<< " / " << message->getLastSlaveData().getDataStr(true, false);
<< " / " << message->getLastSlaveData().getDataStr();
} else {
result_t ret = message->decodeLastData(result, verbosity);
if (ret != RESULT_OK) {
result << " (" << getResultCode(ret)
<< " for " << message->getLastMasterData().getDataStr()
<< " / " << message->getLastSlaveData().getDataStr(true, false) << ")";
<< " / " << message->getLastSlaveData().getDataStr() << ")";
}
}
if (verbosity == (OF_NAMES|OF_UNITS|OF_COMMENTS)) {
@@ -1310,7 +1305,7 @@ string MainLoop::executeScan(vector<string> &args, string levels) {
if (result != RESULT_OK) {
return getResultCode(result);
}
SymbolString slave(false);
SymbolString slave;
result = m_busHandler->scanAndWait(dstAddress, slave);
if (result != RESULT_OK) {
return getResultCode(result);
Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

After

Width:  |  Height:  |  Size: 92 KiB

+10 -10
View File
@@ -77,14 +77,14 @@ int main() {
string check[5] = checks[i];
istringstream isstr(check[0]);
string expectStr = check[1];
SymbolString mstr(false);
SymbolString mstr(true);
result_t result = mstr.parseHex(check[2]);
if (result != RESULT_OK) {
cout << "\"" << check[0] << "\": parse \"" << check[2] << "\" error: " << getResultCode(result) << endl;
error = true;
continue;
}
SymbolString sstr(false);
SymbolString sstr;
result = sstr.parseHex(check[3]);
if (result != RESULT_OK) {
cout << "\"" << check[0] << "\": parse \"" << check[3] << "\" error: " << getResultCode(result) << endl;
@@ -130,17 +130,17 @@ int main() {
cout << "\": create OK" << endl;
ostringstream output;
SymbolString writeMstr(false);
result = writeMstr.parseHex(mstr.getDataStr(true, false).substr(0, 10));
SymbolString writeMstr(true);
result = writeMstr.parseHex(mstr.getDataStr().substr(0, 10));
if (result != RESULT_OK) {
cout << " parse \"" << mstr.getDataStr(true, false).substr(0, 10) << "\" error: " << getResultCode(result)
cout << " parse \"" << mstr.getDataStr().substr(0, 10) << "\" error: " << getResultCode(result)
<< endl;
error = true;
}
SymbolString writeSstr(false);
result = writeSstr.parseHex(sstr.getDataStr(true, false).substr(0, 2));
SymbolString writeSstr;
result = writeSstr.parseHex(sstr.getDataStr().substr(0, 2));
if (result != RESULT_OK) {
cout << " parse \"" << sstr.getDataStr(true, false).substr(0, 2) << "\" error: " << getResultCode(result)
cout << " parse \"" << sstr.getDataStr().substr(0, 2) << "\" error: " << getResultCode(result)
<< endl;
error = true;
}
@@ -186,8 +186,8 @@ int main() {
error = true;
} else {
bool match = mstr == writeMstr && sstr == writeSstr;
verify(failedWriteMatch, "write", expectStr, match, mstr.getDataStr(true, false) + " "
+ sstr.getDataStr(true, false), writeMstr.getDataStr(true, false) + " " + writeSstr.getDataStr(true, false));
verify(failedWriteMatch, "write", expectStr, match, mstr.getDataStr() + " "
+ sstr.getDataStr(), writeMstr.getDataStr() + " " + writeSstr.getDataStr());
}
delete fields;
fields = NULL;
+4 -4
View File
@@ -163,7 +163,7 @@ class DataField {
/**
* Reads the numeric value from the @a SymbolString.
* @param partType the @a PartType of the data.
* @param data the unescaped data @a SymbolString for reading binary data.
* @param data the data @a SymbolString for reading binary data.
* @param offset the additional offset to add for reading binary data.
* @param output the variable in which to store the numeric value.
* @param fieldName the name of the field to read, or NULL for the first field.
@@ -180,7 +180,7 @@ class DataField {
/**
* Reads the value from the @a SymbolString.
* @param partType the @a PartType of the data.
* @param data the unescaped data @a SymbolString for reading binary data.
* @param data the data @a SymbolString for reading binary data.
* @param offset the additional offset to add for reading binary data.
* @param output the @a ostringstream to append the formatted value to.
* @param outputFormat the @a OutputFormat options to use.
@@ -332,7 +332,7 @@ class SingleDataField : public DataField {
protected:
/**
* Internal method for reading the field from a @a SymbolString.
* @param input the unescaped @a SymbolString to read the binary value from.
* @param input the @a SymbolString to read the binary value from.
* @param isMaster whether the @a SymbolString is the master part.
* @param offset the offset in the @a SymbolString.
* @param output the ostringstream to append the formatted value to.
@@ -347,7 +347,7 @@ class SingleDataField : public DataField {
* Internal method for writing the field to a @a SymbolString.
* @param input the @a istringstream to parse the formatted value from.
* @param offset the offset in the @a SymbolString.
* @param output the unescaped @a SymbolString to write the binary value to.
* @param output the @a SymbolString to write the binary value to.
* @param isMaster whether the @a SymbolString is the master part.
* @param usedLength the variable in which to store the used length in bytes, or NULL.
* @return @a RESULT_OK on success, or an error code.
-44
View File
@@ -40,50 +40,6 @@ using std::setfill;
using std::setprecision;
using std::setw;
unsigned int parseInt(const char* str, int base, const unsigned int minValue, const unsigned int maxValue,
result_t& result, unsigned int* length) {
char* strEnd = NULL;
unsigned long ret = strtoul(str, &strEnd, base);
if (strEnd == NULL || strEnd == str || *strEnd != 0) {
result = RESULT_ERR_INVALID_NUM; // invalid value
return 0;
}
if (minValue > ret || ret > maxValue) {
result = RESULT_ERR_OUT_OF_RANGE; // invalid value
return 0;
}
if (length != NULL) {
*length = (unsigned int)(strEnd - str);
}
result = RESULT_OK;
return (unsigned int)ret;
}
int parseSignedInt(const char* str, int base, const int minValue, const int maxValue, result_t& result,
unsigned int* length) {
char* strEnd = NULL;
long ret = strtol(str, &strEnd, base);
if (strEnd == NULL || *strEnd != 0) {
result = RESULT_ERR_INVALID_NUM; // invalid value
return 0;
}
if (minValue > ret || ret > maxValue) {
result = RESULT_ERR_OUT_OF_RANGE; // invalid value
return 0;
}
if (length != NULL) {
*length = (unsigned int)(strEnd - str);
}
result = RESULT_OK;
return static_cast<int>(ret);
}
void printErrorPos(ostream& out, vector<string>::iterator begin, const vector<string>::iterator end,
vector<string>::iterator pos, string filename, size_t lineNo, result_t result) {
if (pos > begin) {
+8 -32
View File
@@ -123,7 +123,8 @@ enum PartType {
/** bit flag for @a DataType: value may not be NULL. */
#define REQ 0x40
/** bit flag for @a DataType: binary representation is hex converted to decimal and interpreted as 2 digits (also requires #BCD). */
/** bit flag for @a DataType: binary representation is hex converted to decimal and interpreted as 2 digits
* (also requires #BCD). */
#define HCD 0x80
/** bit flag for @a DataType: exponential numeric representation. */
@@ -142,32 +143,6 @@ enum PartType {
#define CON 0x1000
/**
* 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);
/**
* 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);
/**
* Print the error position of the iterator.
* @param out the @a ostream to print to.
@@ -253,7 +228,7 @@ class DataType {
/**
* Internal method for reading the numeric raw value from a @a SymbolString.
* @param input the unescaped @a SymbolString to read the binary value from.
* @param input the @a SymbolString to read the binary value from.
* @param offset the offset in the @a SymbolString.
* @param length the number of symbols to read.
* @param value the variable in which to store the numeric raw value.
@@ -265,7 +240,7 @@ class DataType {
/**
* Internal method for reading the field from a @a SymbolString.
* @param input the unescaped @a SymbolString to read the binary value from.
* @param input the @a SymbolString to read the binary value from.
* @param isMaster whether the @a SymbolString is the master part.
* @param offset the offset in the @a SymbolString.
* @param length the number of symbols to read.
@@ -282,7 +257,7 @@ class DataType {
* @param input the @a istringstream to parse the formatted value from.
* @param offset the offset in the @a SymbolString.
* @param length the number of symbols to write, or @a REMAIN_LEN.
* @param output the unescaped @a SymbolString to write the binary value to.
* @param output the @a SymbolString to write the binary value to.
* @param isMaster whether the @a SymbolString is the master part.
* @param usedLength the variable in which to store the used length in bytes, or NULL.
* @return @a RESULT_OK on success, or an error code.
@@ -369,7 +344,8 @@ class DateTimeDataType : public DataType {
*/
DateTimeDataType(const string id, const unsigned char bitCount, const uint16_t flags, const unsigned int replacement,
const bool hasDate, const bool hasTime, const int16_t resolution)
: DataType(id, bitCount, flags, replacement), m_hasDate(hasDate), m_hasTime(hasTime), m_resolution(resolution == 0 ? 1 : resolution) {}
: DataType(id, bitCount, flags, replacement), m_hasDate(hasDate), m_hasTime(hasTime),
m_resolution(resolution == 0 ? 1 : resolution) {}
/**
* Destructor.
@@ -521,7 +497,7 @@ class NumberDataType : public DataType {
* @param value the numeric raw value to write.
* @param offset the offset in the @a SymbolString.
* @param length the number of symbols to write, or @a REMAIN_LEN.
* @param output the unescaped @a SymbolString to write the binary value to.
* @param output the @a SymbolString to write the binary value to.
* @param usedLength the variable in which to store the used length in bytes,
* or NULL.
* @return @a RESULT_OK on success, or an error code.
+27 -61
View File
@@ -590,43 +590,29 @@ bool Message::hasField(const char* fieldName, bool numeric) {
return m_data->hasField(fieldName, numeric);
}
result_t Message::prepareMaster(const unsigned char srcAddress, SymbolString& masterData,
result_t Message::prepareMaster(const unsigned char srcAddress, SymbolString& master,
istringstream& input, char separator,
const unsigned char dstAddress, unsigned char index) {
if (m_isPassive) {
return RESULT_ERR_INVALID_ARG; // prepare not possible
}
SymbolString master(false);
result_t result = master.push_back(srcAddress, false, false);
if (result != RESULT_OK) {
return result;
}
master.clear();
master.push_back(srcAddress);
if (dstAddress == SYN) {
if (m_dstAddress == SYN) {
return RESULT_ERR_INVALID_ADDR;
}
result = master.push_back(m_dstAddress, false, false);
master.push_back(m_dstAddress);
} else {
result = master.push_back(dstAddress, false, false);
master.push_back(dstAddress);
}
master.push_back(m_id[0]);
master.push_back(m_id[1]);
result_t result = prepareMasterPart(master, input, separator, index);
if (result != RESULT_OK) {
return result;
}
result = master.push_back(m_id[0], false, false);
if (result != RESULT_OK) {
return result;
}
result = master.push_back(m_id[1], false, false);
if (result != RESULT_OK) {
return result;
}
result = prepareMasterPart(master, input, separator, index);
if (result != RESULT_OK) {
return result;
}
masterData.clear();
masterData.addAll(master);
result = storeLastData(pt_masterData, masterData, index);
result = storeLastData(pt_masterData, master, index);
if (result < RESULT_OK) {
return result;
}
@@ -638,17 +624,11 @@ result_t Message::prepareMasterPart(SymbolString& master, istringstream& input,
return RESULT_ERR_NOTFOUND;
}
unsigned char pos = master.size();
result_t result = master.push_back(0, false, false); // length, will be set later
if (result != RESULT_OK) {
return result;
}
master.push_back(0); // length, will be set later
for (size_t i = 2; i < m_id.size(); i++) {
result = master.push_back(m_id[i], false, false);
if (result != RESULT_OK) {
return result;
}
master.push_back(m_id[i]);
}
result = m_data->write(input, pt_masterData, master, getIdLength(), separator);
result_t result = m_data->write(input, pt_masterData, master, getIdLength(), separator);
if (result != RESULT_OK) {
return result;
}
@@ -656,16 +636,13 @@ result_t Message::prepareMasterPart(SymbolString& master, istringstream& input,
return result;
}
result_t Message::prepareSlave(istringstream& input, SymbolString& slaveData) {
result_t Message::prepareSlave(istringstream& input, SymbolString& slave) {
if (m_isWrite) {
return RESULT_ERR_INVALID_ARG; // prepare not possible
}
SymbolString slave(false);
result_t result = slave.push_back(0, false, false); // length, will be set later
if (result != RESULT_OK) {
return result;
}
result = m_data->write(input, pt_slaveData, slave, 0);
slave.clear();
slave.push_back(0); // length, will be set later
result_t result = m_data->write(input, pt_slaveData, slave, 0);
if (result != RESULT_OK) {
return result;
}
@@ -675,8 +652,6 @@ result_t Message::prepareSlave(istringstream& input, SymbolString& slaveData) {
m_lastChangeTime = m_lastUpdateTime;
m_lastSlaveData = slave;
}
slaveData.clear();
slaveData.addAll(slave);
return result;
}
@@ -695,7 +670,7 @@ result_t Message::storeLastData(const PartType partType, SymbolString& data, uns
time(&m_lastUpdateTime);
}
if (partType == pt_masterData) {
switch (data.compareMaster(m_lastMasterData)) {
switch (data.compareTo(m_lastMasterData)) {
case 1: // completely different
m_lastChangeTime = m_lastUpdateTime;
m_lastMasterData = data;
@@ -903,7 +878,7 @@ ChainedMessage::ChainedMessage(const string circuit, const string level, const s
m_lastMasterUpdateTimes = reinterpret_cast<time_t*>(calloc(cnt, sizeof(time_t)));
m_lastSlaveUpdateTimes = reinterpret_cast<time_t*>(calloc(cnt, sizeof(time_t)));
for (size_t index = 0; index < cnt; index++) {
m_lastMasterDatas[index] = new SymbolString();
m_lastMasterDatas[index] = new SymbolString(true);
m_lastSlaveDatas[index] = new SymbolString();
}
}
@@ -1000,7 +975,7 @@ result_t ChainedMessage::prepareMasterPart(SymbolString& master, istringstream&
if (index >= cnt) {
return RESULT_ERR_NOTFOUND;
}
SymbolString allData(false);
SymbolString allData(true);
result_t result = m_data->write(input, pt_masterData, allData, 0, separator);
if (result != RESULT_OK) {
return result;
@@ -1017,21 +992,12 @@ result_t ChainedMessage::prepareMasterPart(SymbolString& master, istringstream&
return RESULT_ERR_INVALID_POS;
}
vector<unsigned char> id = m_ids[index];
result = master.push_back((unsigned char)(id.size()-2+addData), false, false); // NN
if (result != RESULT_OK) {
return result;
}
master.push_back((unsigned char)(id.size()-2+addData)); // NN
for (size_t i = 2; i < id.size(); i++) {
result = master.push_back(id[i], false, false);
if (result != RESULT_OK) {
return result;
}
master.push_back(id[i]);
}
for (size_t i = 0; i < addData; i++) {
result = master.push_back(allData[pos+i], false, false);
if (result != RESULT_OK) {
return result;
}
master.push_back(allData[pos+i]);
}
if (index == 0) {
for (size_t i = 0; i < cnt; i++) {
@@ -1059,7 +1025,7 @@ result_t ChainedMessage::storeLastData(const PartType partType, SymbolString& da
return RESULT_ERR_INVALID_ARG;
}
if (partType == pt_masterData) {
switch (data.compareMaster(*m_lastMasterDatas[index])) {
switch (data.compareTo(*m_lastMasterDatas[index])) {
case 1: // completely different
*m_lastMasterDatas[index] = data;
break;
@@ -1098,19 +1064,19 @@ result_t ChainedMessage::storeLastData(const PartType partType, SymbolString& da
}
}
// everything was completely retrieved in short time
SymbolString master(false);
SymbolString slave(false);
SymbolString master(true);
SymbolString slave;
size_t offset = 5+(m_ids[0].size()-2); // skip QQ, ZZ, PB, SB, NN
for (index = 0; index < m_ids.size(); index++) {
SymbolString* add = m_lastMasterDatas[index];
size_t end = 5+(*add)[4];
for (size_t pos = index == 0 ? 0 : offset; pos < end; pos++) {
master.push_back((*add)[pos], false, false);
master.push_back((*add)[pos]);
}
add = m_lastSlaveDatas[index];
end = 1+(*add)[0];
for (size_t pos = index == 0 ? 0 : 1; pos < end; pos++) {
slave.push_back((*add)[pos], false, false);
slave.push_back((*add)[pos]);
}
}
// adjust NN
+5 -5
View File
@@ -421,14 +421,14 @@ class Message {
/**
* Prepare the master @a SymbolString for sending a query or command to the bus.
* @param srcAddress the source address to set.
* @param masterData the master data @a SymbolString for writing symbols to.
* @param master the master data @a SymbolString for writing symbols to.
* @param input the @a istringstream to parse the formatted value(s) from.
* @param separator the separator character between multiple fields.
* @param dstAddress the destination address to set, or @a SYN to keep the address defined during construction.
* @param index the index of the part to prepare.
* @return @a RESULT_OK on success, or an error code.
*/
result_t prepareMaster(const unsigned char srcAddress, SymbolString& masterData,
result_t prepareMaster(const unsigned char srcAddress, SymbolString& master,
istringstream& input, char separator = UI_FIELD_SEPARATOR,
const unsigned char dstAddress = SYN, unsigned char index = 0);
@@ -449,10 +449,10 @@ class Message {
/**
* Prepare the slave @a SymbolString for sending an answer to the bus.
* @param input the @a istringstream to parse the formatted value(s) from.
* @param slaveData the slave data @a SymbolString for writing symbols to.
* @param slave the slave data @a SymbolString for writing symbols to.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t prepareSlave(istringstream& input, SymbolString& slaveData);
virtual result_t prepareSlave(istringstream& input, SymbolString& slave);
/**
* Store the last seen master and slave data.
@@ -631,7 +631,7 @@ class Message {
Condition* m_condition;
/** the last seen master data. */
SymbolString m_lastMasterData;
SymbolString m_lastMasterData{true};
/** the last seen slave data. */
SymbolString m_lastSlaveData;
+1
View File
@@ -49,6 +49,7 @@ const char* getResultCode(result_t resultCode) {
case RESULT_ERR_NAK: return "ERR: NAK received";
case RESULT_ERR_NO_SIGNAL: return "ERR: no signal";
case RESULT_ERR_SYN: return "ERR: SYN received";
case RESULT_ERR_SYMBOL: return "ERR: wrong symbol received";
case RESULT_ERR_NOTAUTHORIZED: return "ERR: not authorized";
default:
+3 -2
View File
@@ -33,7 +33,7 @@ namespace ebusd {
enum result_t {
RESULT_OK = 0, //!< success
RESULT_CONTINUE = 1, //!< more input data is needed (e.g. start of escape sequence received)
RESULT_CONTINUE = 1, //!< more input data is needed
RESULT_EMPTY = 2, //!< empty result
RESULT_ERR_GENERIC_IO = -1, //!< generic I/O error (usually fatal)
@@ -62,8 +62,9 @@ enum result_t {
RESULT_ERR_NO_SIGNAL = -22, //!< no signal found on the bus
RESULT_ERR_SYN = -23, //!< SYN received instead of answer
RESULT_ERR_SYMBOL = -24, //!< wrong symbol received instead of sent symbol
RESULT_ERR_NOTAUTHORIZED = -24 //!< not authorized for this action
RESULT_ERR_NOTAUTHORIZED = -25 //!< not authorized for this action
};
+95 -116
View File
@@ -54,64 +54,103 @@ static const unsigned char CRC_LOOKUP_TABLE[] = {
};
void SymbolString::addAll(const SymbolString& str, bool skipLastSymbol) {
bool addCrc = m_unescapeState == 0;
bool isEscaped = str.m_unescapeState == 0;
vector<unsigned char> data = str.m_data;
size_t end = data.size();
if (end > 0 && skipLastSymbol) {
end--;
unsigned int parseInt(const char* str, int base, const unsigned int minValue, const unsigned int maxValue,
result_t& result, unsigned int* length) {
char* strEnd = NULL;
unsigned long ret = strtoul(str, &strEnd, base);
if (strEnd == NULL || strEnd == str || *strEnd != 0) {
result = RESULT_ERR_INVALID_NUM; // invalid value
return 0;
}
for (size_t i = 0; i < end; i++) {
push_back(data[i], isEscaped, addCrc);
if (minValue > ret || ret > maxValue) {
result = RESULT_ERR_OUT_OF_RANGE; // invalid value
return 0;
}
if (addCrc) {
push_back(m_crc, false, false); // add CRC
if (length != NULL) {
*length = (unsigned int)(strEnd - str);
}
result = RESULT_OK;
return (unsigned int)ret;
}
result_t SymbolString::parseHex(const string& str, const bool isEscaped) {
bool addCrc = m_unescapeState == 0;
for (size_t i = 0; i < str.size(); i += 2) {
char* strEnd = NULL;
const char* strBegin = str.substr(i, 2).c_str();
unsigned long value = strtoul(strBegin, &strEnd, 16);
int parseSignedInt(const char* str, int base, const int minValue, const int maxValue, result_t& result,
unsigned int* length) {
char* strEnd = NULL;
if (strEnd == NULL || strEnd != strBegin+2 || value > 0xff) {
return RESULT_ERR_INVALID_NUM; // invalid value
}
push_back((unsigned char)value, isEscaped, addCrc);
long ret = strtol(str, &strEnd, base);
if (strEnd == NULL || *strEnd != 0) {
result = RESULT_ERR_INVALID_NUM; // invalid value
return 0;
}
if (addCrc) {
push_back(m_crc, false, false); // add CRC
if (minValue > ret || ret > maxValue) {
result = RESULT_ERR_OUT_OF_RANGE; // invalid value
return 0;
}
if (length != NULL) {
*length = (unsigned int)(strEnd - str);
}
result = RESULT_OK;
return static_cast<int>(ret);
}
void SymbolString::updateCrc(unsigned char& crc, const unsigned char value) {
crc = CRC_LOOKUP_TABLE[crc]^value;
}
result_t SymbolString::parseHex(const string& str) {
result_t result;
for (size_t i = 0; i < str.size(); i += 2) {
unsigned char value = (unsigned char)parseInt(str.substr(i, 2).c_str(), 16, 0, 0xff, result);
if (result != RESULT_OK) {
return result;
}
m_data.push_back(value);
}
return RESULT_OK;
}
const string SymbolString::getDataStr(const bool unescape, const bool skipLastSymbol,
unsigned char skipFirstSymbols) {
bool previousEscape = false;
result_t SymbolString::parseHexEscaped(const string& str) {
result_t result;
bool inEscape = false;
for (size_t i = 0; i < str.size(); i += 2) {
unsigned char value = (unsigned char)parseInt(str.substr(i, 2).c_str(), 16, 0, 0xff, result);
if (result != RESULT_OK) {
return result;
}
if (inEscape) {
if (value == 0x00) {
m_data.push_back(ESC);
inEscape = false;
} else if (value == 0x01) {
m_data.push_back(SYN);
inEscape = false;
} else {
return RESULT_ERR_ESC; // invalid escape sequence
}
} else if (value == ESC) {
inEscape = true;
} else if (value == SYN) {
return RESULT_ERR_ESC; // invalid escape sequence
} else {
m_data.push_back(value);
}
}
return inEscape ? RESULT_ERR_ESC : RESULT_OK;
}
const string SymbolString::getDataStr(unsigned char skipFirstSymbols) {
ostringstream sstr;
for (size_t i = 0; i < m_data.size(); i++) {
unsigned char value = m_data[i];
if (m_unescapeState == 0 && unescape && previousEscape) {
if (skipFirstSymbols > 0) {
skipFirstSymbols--;
} else if (!skipLastSymbol || i+1 < m_data.size()) {
if (value == 0x00) {
sstr << "a9"; // ESC
} else if (value == 0x01) {
sstr << "aa"; // SYN
} else {
sstr << "XX"; // invalid escape sequence
}
}
previousEscape = false;
} else if (m_unescapeState == 0 && unescape && value == ESC) {
previousEscape = true; // escape sequence not yet finished
} else if (skipFirstSymbols > 0) {
if (skipFirstSymbols > 0) {
skipFirstSymbols--;
} else if (!skipLastSymbol || i+1 < m_data.size()) {
} else {
unsigned char value = m_data[i];
sstr << nouppercase << setw(2) << hex
<< setfill('0') << static_cast<unsigned>(value);
}
@@ -119,83 +158,23 @@ const string SymbolString::getDataStr(const bool unescape, const bool skipLastSy
return sstr.str();
}
result_t SymbolString::push_back(const unsigned char value, const bool isEscaped, const bool updateCRC) {
if (m_unescapeState == 0) { // store escaped data
if (!isEscaped && value == ESC) {
m_data.push_back(ESC);
m_data.push_back(0x00);
if (updateCRC) {
addCRC(ESC);
addCRC(0x00);
}
} else if (!isEscaped && value == SYN) {
m_data.push_back(ESC);
m_data.push_back(0x01);
if (updateCRC) {
addCRC(ESC);
addCRC(0x01);
}
unsigned char SymbolString::calcCrc() const {
unsigned char crc = 0;
for (size_t i = 0; i < m_data.size(); i++) {
unsigned char value = m_data[i];
if (value == ESC) {
updateCrc(crc, ESC);
updateCrc(crc, 0x00);
} else if (value == SYN) {
updateCrc(crc, ESC);
updateCrc(crc, 0x01);
} else {
m_data.push_back(value);
if (updateCRC) {
addCRC(value);
}
updateCrc(crc, value);
}
return RESULT_OK;
}
if (!isEscaped) {
if (m_unescapeState != 1) {
return RESULT_ERR_ESC; // invalid unescape state
}
m_data.push_back(value);
if (updateCRC) {
if (value == ESC) {
addCRC(ESC);
addCRC(0x00);
} else if (value == SYN) {
addCRC(ESC);
addCRC(0x01);
} else {
addCRC(value);
}
}
return RESULT_OK;
}
if (m_unescapeState != 1) {
if (updateCRC) {
addCRC(value);
}
if (value == 0x00) {
m_data.push_back(ESC);
m_unescapeState = 1;
return RESULT_OK;
}
if (value == 0x01) {
m_data.push_back(SYN);
m_unescapeState = 1;
return RESULT_OK;
}
return RESULT_ERR_ESC; // invalid escape sequence
}
if (value == ESC) {
if (updateCRC) {
addCRC(value);
}
m_unescapeState = 2;
return RESULT_CONTINUE;
}
if (updateCRC) {
addCRC(value);
}
m_data.push_back(value);
return RESULT_OK;
return crc;
}
void SymbolString::addCRC(const unsigned char value) {
m_crc = CRC_LOOKUP_TABLE[m_crc]^value;
}
/**
* Return the index of the upper or lower 4 bits of a master address.
+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;
};
+11 -11
View File
@@ -473,14 +473,14 @@ int main() {
string check[5] = checks[i];
istringstream isstr(check[0]);
string expectStr = check[1];
SymbolString mstr(false);
SymbolString mstr(true);
result_t result = mstr.parseHex(check[2]);
if (result != RESULT_OK) {
cout << "\"" << check[0] << "\": parse \"" << check[2] << "\" error: " << getResultCode(result) << endl;
error = true;
continue;
}
SymbolString sstr(false);
SymbolString sstr;
result = sstr.parseHex(check[3]);
if (result != RESULT_OK) {
cout << "\"" << check[0] << "\": parse \"" << check[3] << "\" error: " << getResultCode(result) << endl;
@@ -563,17 +563,17 @@ int main() {
}
ostringstream output;
SymbolString writeMstr(false);
result = writeMstr.parseHex(mstr.getDataStr(true, false).substr(0, 10));
SymbolString writeMstr(true);
result = writeMstr.parseHex(mstr.getDataStr().substr(0, 10));
if (result != RESULT_OK) {
cout << " parse \"" << mstr.getDataStr(true, false).substr(0, 10) << "\" error: " << getResultCode(result)
cout << " parse \"" << mstr.getDataStr().substr(0, 10) << "\" error: " << getResultCode(result)
<< endl;
error = true;
}
SymbolString writeSstr(false);
result = writeSstr.parseHex(sstr.getDataStr(true, false).substr(0, 2));
SymbolString writeSstr;
result = writeSstr.parseHex(sstr.getDataStr().substr(0, 2));
if (result != RESULT_OK) {
cout << " parse \"" << sstr.getDataStr(true, false).substr(0, 2) << "\" error: " << getResultCode(result)
cout << " parse \"" << sstr.getDataStr().substr(0, 2) << "\" error: " << getResultCode(result)
<< endl;
error = true;
}
@@ -621,9 +621,9 @@ int main() {
error = true;
} else {
bool match = mstr == writeMstr && sstr == writeSstr;
verify(failedWriteMatch, "write", expectStr, match, mstr.getDataStr(true, false) + " "
+ sstr.getDataStr(true, false), writeMstr.getDataStr(true, false) + " "
+ writeSstr.getDataStr(true, false));
verify(failedWriteMatch, "write", expectStr, match, mstr.getDataStr() + " "
+ sstr.getDataStr(), writeMstr.getDataStr() + " "
+ writeSstr.getDataStr());
}
}
delete fields;
+7 -7
View File
@@ -260,7 +260,7 @@ int main() {
} else if (mstrs[pos] != NULL) {
delete mstrs[pos];
}
mstrs[pos] = new SymbolString(false);
mstrs[pos] = new SymbolString(true);
result = mstrs[pos]->parseHex(token);
if (result != RESULT_OK) {
cout << "\"" << check[0] << "\": parse \"" << token << "\" error: " << getResultCode(result) << endl;
@@ -277,7 +277,7 @@ int main() {
} else if (sstrs[pos] != NULL) {
delete sstrs[pos];
}
sstrs[pos] = new SymbolString(false);
sstrs[pos] = new SymbolString();
result = sstrs[pos]->parseHex(token);
if (result != RESULT_OK) {
cout << "\"" << check[0] << "\": parse \"" << token << "\" error: " << getResultCode(result) << endl;
@@ -292,7 +292,7 @@ int main() {
if (mstrs[0] != NULL) {
delete mstrs[0];
}
mstrs[0] = new SymbolString(false);
mstrs[0] = new SymbolString(true);
result = mstrs[0]->parseHex(check[2]);
if (result != RESULT_OK) {
cout << "\"" << check[0] << "\": parse \"" << check[2] << "\" error: " << getResultCode(result) << endl;
@@ -301,7 +301,7 @@ int main() {
if (sstrs[0] != NULL) {
delete sstrs[0];
}
sstrs[0] = new SymbolString(false);
sstrs[0] = new SymbolString();
result = sstrs[0]->parseHex(check[3]);
if (result != RESULT_OK) {
cout << "\"" << check[0] << "\": parse \"" << check[3] << "\" error: " << getResultCode(result) << endl;
@@ -419,7 +419,7 @@ int main() {
}
if (!message->isPassive() && (withInput || !decode)) {
istringstream input(inputStr);
SymbolString writeMstr(false);
SymbolString writeMstr(true);
result = message->prepareMaster(0xff, writeMstr, input);
if (failedPrepare) {
if (result == RESULT_OK) {
@@ -438,8 +438,8 @@ int main() {
cout << " \"" << inputStr << "\": prepare OK" << endl;
bool match = writeMstr == *mstrs[0];
verify(failedPrepareMatch, "prepare", inputStr, match, mstrs[0]->getDataStr(true, false),
writeMstr.getDataStr(true, false));
verify(failedPrepareMatch, "prepare", inputStr, match, mstrs[0]->getDataStr(),
writeMstr.getDataStr());
}
}
+42 -15
View File
@@ -50,26 +50,32 @@ int main(int argc, char** argv) {
SymbolString sstr(true);
if (argc > 1) {
result_t result = sstr.parseHex(argv[1], true);
result_t result;
if (argc > 2 && strcmp("escaped", argv[1]) == 0) {
result = sstr.parseHexEscaped(argv[2]);
} else {
result = sstr.parseHex(argv[1]);
}
if (result != RESULT_OK) {
cout << "parse escaped error: " << getResultCode(result) << endl;
} else {
unsigned char gotCrc = sstr.getCRC();
unsigned char gotCrc = sstr.calcCrc();
cout << "calculated CRC: 0x"
<< nouppercase << setw(2) << hex << setfill('0')
<< static_cast<unsigned>(gotCrc) << endl;
}
return 0;
}
string gotStr, expectStr;
result_t result = sstr.parseHex("10feb5050427a915aa", false);
result_t result = sstr.parseHex("10feb5050427a915aa");
if (result != RESULT_OK) {
cout << "parse escaped error: " << getResultCode(result) << endl;
cout << "parse unescaped error: " << getResultCode(result) << endl;
error = true;
} else {
gotStr = sstr.getDataStr(false, false), expectStr = "10feb5050427a90015a90177";
verify(false, "parse escaped", "10feb5050427a915aa", true, expectStr, gotStr);
unsigned char gotCrc = sstr.getCRC(), expectCrc = 0x77;
gotStr = sstr.getDataStr(), expectStr = "10feb5050427a915aa";
verify(false, "parse unescaped", "10feb5050427a915aa", true, expectStr, gotStr);
unsigned char gotCrc = sstr.calcCrc(), expectCrc = 0x77;
ostringstream ostr;
ostr << nouppercase << setw(2) << hex << setfill('0') << static_cast<unsigned>(expectCrc);
expectStr = ostr.str();
@@ -77,19 +83,40 @@ int main(int argc, char** argv) {
ostr << nouppercase << setw(2) << hex << setfill('0') << static_cast<unsigned>(gotCrc);
gotStr = ostr.str();
verify(false, "CRC", "10feb5050427a915aa", gotCrc == expectCrc, expectStr, gotStr);
gotStr = sstr.getDataStr(true, false), expectStr = "10feb5050427a915aa77";
verify(false, "unescape", "10feb5050427a915aa", true, expectStr, gotStr);
}
sstr = SymbolString(false);
result = sstr.parseHex("10feb5050427a90015a90177", true);
sstr.clear();
result = sstr.parseHexEscaped("10feb5050427a90015a901");
if (result != RESULT_OK) {
cout << "parse unescaped error: " << getResultCode(result) << endl;
cout << "parse escaped error: " << getResultCode(result) << endl;
error = true;
} else {
gotStr = sstr.getDataStr(true, false), expectStr = "10feb5050427a915aa77";
verify(false, "parse unescaped", "10feb5050427a90015a90177", true, expectStr, gotStr);
gotStr = sstr.getDataStr(), expectStr = "10feb5050427a915aa";
verify(false, "parse escaped", "10feb5050427a90015a901", true, expectStr, gotStr);
ostringstream ostr;
ostr << dec << static_cast<unsigned>(4);
expectStr = ostr.str();
ostr.str("");
ostr << dec << static_cast<unsigned>(sstr.getDataSize());
gotStr = ostr.str();
verify(false, "data size", "10feb5050427a90015a901", sstr.getDataSize() == 4, expectStr, gotStr);
}
sstr = SymbolString(); // slave
result = sstr.parseHexEscaped("0427a90015a901");
if (result != RESULT_OK) {
cout << "parse escaped error: " << getResultCode(result) << endl;
error = true;
} else {
gotStr = sstr.getDataStr(), expectStr = "0427a915aa";
verify(false, "parse escaped", "0427a90015a901", true, expectStr, gotStr);
ostringstream ostr;
ostr << dec << static_cast<unsigned>(4);
expectStr = ostr.str();
ostr.str("");
ostr << dec << static_cast<unsigned>(sstr.getDataSize());
gotStr = ostr.str();
verify(false, "data size", "0427a90015a901", sstr.getDataSize() == 4, expectStr, gotStr);
}
return error ? 1 : 0;