diff --git a/src/ebusd/bushandler.cpp b/src/ebusd/bushandler.cpp index 3d972038..1366ba90 100644 --- a/src/ebusd/bushandler.cpp +++ b/src/ebusd/bushandler.cpp @@ -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); diff --git a/src/ebusd/bushandler.h b/src/ebusd/bushandler.h index 95944c45..58d91c01 100644 --- a/src/ebusd/bushandler.h +++ b/src/ebusd/bushandler.h @@ -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]; diff --git a/src/ebusd/mainloop.cpp b/src/ebusd/mainloop.cpp index adead1ca..a4a02c51 100644 --- a/src/ebusd/mainloop.cpp +++ b/src/ebusd/mainloop.cpp @@ -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 &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 &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 &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 &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 &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 &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 &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 &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 &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 &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 &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); diff --git a/src/ebusd/states.png b/src/ebusd/states.png index 1a9cc6e7..e6f172a0 100644 Binary files a/src/ebusd/states.png and b/src/ebusd/states.png differ diff --git a/src/lib/ebus/contrib/test/test_tem.cpp b/src/lib/ebus/contrib/test/test_tem.cpp index 27217311..94031b88 100644 --- a/src/lib/ebus/contrib/test/test_tem.cpp +++ b/src/lib/ebus/contrib/test/test_tem.cpp @@ -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; diff --git a/src/lib/ebus/data.h b/src/lib/ebus/data.h index ac94dbc6..d18ce16f 100644 --- a/src/lib/ebus/data.h +++ b/src/lib/ebus/data.h @@ -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. diff --git a/src/lib/ebus/datatype.cpp b/src/lib/ebus/datatype.cpp index 91161ef5..73038e72 100644 --- a/src/lib/ebus/datatype.cpp +++ b/src/lib/ebus/datatype.cpp @@ -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(ret); -} - void printErrorPos(ostream& out, vector::iterator begin, const vector::iterator end, vector::iterator pos, string filename, size_t lineNo, result_t result) { if (pos > begin) { diff --git a/src/lib/ebus/datatype.h b/src/lib/ebus/datatype.h index 658d51c6..59e9e639 100644 --- a/src/lib/ebus/datatype.h +++ b/src/lib/ebus/datatype.h @@ -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. diff --git a/src/lib/ebus/message.cpp b/src/lib/ebus/message.cpp index 00c2155b..12103252 100644 --- a/src/lib/ebus/message.cpp +++ b/src/lib/ebus/message.cpp @@ -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(calloc(cnt, sizeof(time_t))); m_lastSlaveUpdateTimes = reinterpret_cast(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 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 diff --git a/src/lib/ebus/message.h b/src/lib/ebus/message.h index 297fd5f3..e54817bf 100644 --- a/src/lib/ebus/message.h +++ b/src/lib/ebus/message.h @@ -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; diff --git a/src/lib/ebus/result.cpp b/src/lib/ebus/result.cpp index 5acd5676..1489e23b 100644 --- a/src/lib/ebus/result.cpp +++ b/src/lib/ebus/result.cpp @@ -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: diff --git a/src/lib/ebus/result.h b/src/lib/ebus/result.h index c28041ed..a54ef3fc 100644 --- a/src/lib/ebus/result.h +++ b/src/lib/ebus/result.h @@ -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 }; diff --git a/src/lib/ebus/symbol.cpp b/src/lib/ebus/symbol.cpp index 28bd23f9..935b9edd 100644 --- a/src/lib/ebus/symbol.cpp +++ b/src/lib/ebus/symbol.cpp @@ -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 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(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(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. diff --git a/src/lib/ebus/symbol.h b/src/lib/ebus/symbol.h index ecb39162..88436cf7 100644 --- a/src/lib/ebus/symbol.h +++ b/src/lib/ebus/symbol.h @@ -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 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; }; diff --git a/src/lib/ebus/test/test_data.cpp b/src/lib/ebus/test/test_data.cpp index d9fbe216..361d3e52 100644 --- a/src/lib/ebus/test/test_data.cpp +++ b/src/lib/ebus/test/test_data.cpp @@ -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; diff --git a/src/lib/ebus/test/test_message.cpp b/src/lib/ebus/test/test_message.cpp index 95e3ee6e..107a3772 100644 --- a/src/lib/ebus/test/test_message.cpp +++ b/src/lib/ebus/test/test_message.cpp @@ -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()); } } diff --git a/src/lib/ebus/test/test_symbol.cpp b/src/lib/ebus/test/test_symbol.cpp index 0ee67f63..2ae51aac 100644 --- a/src/lib/ebus/test/test_symbol.cpp +++ b/src/lib/ebus/test/test_symbol.cpp @@ -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(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(expectCrc); expectStr = ostr.str(); @@ -77,19 +83,40 @@ int main(int argc, char** argv) { ostr << nouppercase << setw(2) << hex << setfill('0') << static_cast(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(4); + expectStr = ostr.str(); + ostr.str(""); + ostr << dec << static_cast(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(4); + expectStr = ostr.str(); + ostr.str(""); + ostr << dec << static_cast(sstr.getDataSize()); + gotStr = ostr.str(); + verify(false, "data size", "0427a90015a901", sstr.getDataSize() == 4, expectStr, gotStr); } return error ? 1 : 0;