diff --git a/configure.ac b/configure.ac index ddae744c..af150511 100644 --- a/configure.ac +++ b/configure.ac @@ -51,6 +51,7 @@ AC_CONFIG_FILES([Makefile AC_DEFINE_UNQUOTED(PACKAGE_PIDFILE, LOCALSTATEDIR "/run/" PACKAGE ".pid", [The path and name of the PID file.]) AC_DEFINE_UNQUOTED(PACKAGE_LOGFILE, LOCALSTATEDIR "/log/" PACKAGE ".log", [The path and name of the log file.]) AC_DEFINE_UNQUOTED(PACKAGE_CONFIGPATH, SYSCONFDIR "/" PACKAGE, [The default path of the configuration files.]) +AC_DEFINE(SCAN_VERSION, "[m4_esyscmd_s([sed -e 's#^\([1-9]\)\.#0\1.#' -e 's#\.\([0-9]\)[^0-9]*$#.0\1#' -e 's#\.##' VERSION])]", [The version of the package formatted for the scan result.]) AC_DEFINE(REVISION, "[m4_esyscmd_s([git describe --always 2>/dev/null || (echo -n 'p'; date +%Y%m%d)])]", [The revision of the package.]) AC_CHECK_PROGS([HAVE_DOXYGEN], [doxygen], []) diff --git a/src/ebusd/bushandler.cpp b/src/ebusd/bushandler.cpp index 0250ce92..48e61aad 100644 --- a/src/ebusd/bushandler.cpp +++ b/src/ebusd/bushandler.cpp @@ -22,6 +22,7 @@ #include "result.h" #include "symbol.h" #include "log.h" +#include "config.h" #include #include #include @@ -56,7 +57,6 @@ const char* getStateCode(BusState state) { } } - result_t PollRequest::prepare(unsigned char ownMasterAddress) { istringstream input; @@ -323,14 +323,14 @@ result_t BusHandler::handleSymbol() break; case bs_sendCmdAck: - if (m_currentRequest != NULL) { + if (m_answer) { sendSymbol = m_commandCrcValid ? ACK : NAK; sending = true; } break; case bs_sendRes: - if (m_currentRequest != NULL) { + if (m_answer) { sendSymbol = m_response[m_nextSendPos]; // escaped response sending = true; } @@ -379,10 +379,14 @@ result_t BusHandler::handleSymbol() logError(lf_bus, "unable to receive sent AUTO-SYN symbol: %s", getResultCode(result)); else if (recvSymbol != SYN) { logError(lf_bus, "received %2.2x instead of AUTO-SYN symbol", recvSymbol); - } else if (m_generateSynInterval != SYN_TIMEOUT) { - // received own AUTO-SYN symbol back again: act as AUTO-SYN generator now - m_generateSynInterval = SYN_TIMEOUT; - logNotice(lf_bus, "acting as AUTO-SYN generator"); + } else { + if (m_generateSynInterval != SYN_TIMEOUT) { + // received own AUTO-SYN symbol back again: act as AUTO-SYN generator now + m_generateSynInterval = SYN_TIMEOUT; + logNotice(lf_bus, "acting as AUTO-SYN generator"); + } + m_remainLockCount = 0; + return setState(bs_ready, result); } } return setState(bs_skip, result); @@ -466,6 +470,7 @@ result_t BusHandler::handleSymbol() && (dstAddress == m_ownMasterAddress || dstAddress == m_ownSlaveAddress)) return setState(bs_sendCmdAck, RESULT_OK); + addSeenAddress(m_command[0]); return setState(bs_recvCmdAck, RESULT_OK); } if (dstAddress == BROADCAST) @@ -597,34 +602,43 @@ result_t BusHandler::handleSymbol() return setState(bs_skip, RESULT_ERR_INVALID_ARG); case bs_sendCmdAck: - if (sending && m_answer) { - if (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 (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); } - if (isMaster(m_command[1])) - receiveCompleted(); // decode command and store value - return setState(bs_skip, RESULT_OK); - - m_nextSendPos = 0; - m_repeat = false; - Message* message = m_messages->find(m_command); - if (message == NULL || !message->isPassive() || message->isWrite()) - return setState(bs_skip, RESULT_ERR_INVALID_ARG); // don't know this request or definition has wrong direction, deny - - // build response and store in m_response for sending back to requesting master - m_response.clear(true); // escape while sending response - result = message->prepareSlave(m_response); - if (result != RESULT_OK) - return setState(bs_skip, result); - return setState(bs_sendRes, RESULT_OK); + 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; + Message* message; + istringstream input; // TODO create input from database of internal variables + message = m_messages->find(m_command); + if (message == NULL) { + message = m_messages->find(m_command, true); + if (message!=NULL && message->getSrcAddress()!=SYN) + message = NULL; + } + if (message == NULL || message->isWrite()) + return setState(bs_skip, RESULT_ERR_INVALID_ARG); // don't know this request or definition has wrong direction, deny + if (message == m_messages->getScanMessage()) { + input.str("ebusd;EBUSD;" SCAN_VERSION ";0100"); + } + + // build response and store in m_response for sending back to requesting master + m_response.clear(true); // escape while sending response + 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); @@ -739,10 +753,12 @@ void BusHandler::addSeenAddress(unsigned char address) return; } if ((m_seenAddresses[address]&SEEN)==0) { - m_masterCount++; - if (m_autoLockCount && m_masterCount>m_lockCount) - m_lockCount = m_masterCount; - logNotice(lf_bus, "new master %2.2x, master count %d", address, m_masterCount); + if (!m_answer || address!=m_ownMasterAddress) { + m_masterCount++; + if (m_autoLockCount && m_masterCount>m_lockCount) + m_lockCount = m_masterCount; + logNotice(lf_bus, "new master %2.2x, master count %d", address, m_masterCount); + } m_seenAddresses[address] |= SEEN; } } @@ -843,7 +859,7 @@ result_t BusHandler::startScan(bool full) result_t result = request->prepare(m_ownMasterAddress); if (result < RESULT_OK) { delete request; - return result; + return result==RESULT_ERR_EOF ? RESULT_EMPTY : result; } m_nextRequests.push(request); return RESULT_OK; diff --git a/src/lib/ebus/message.cpp b/src/lib/ebus/message.cpp index fbcc3945..898b9bc4 100644 --- a/src/lib/ebus/message.cpp +++ b/src/lib/ebus/message.cpp @@ -378,11 +378,11 @@ result_t Message::create(vector::iterator& it, const vector::ite return RESULT_OK; } -Message* Message::derive(const unsigned char dstAddress) +Message* Message::derive(const unsigned char dstAddress, unsigned char srcAddress=SYN) { return new Message(m_circuit, m_name, m_isWrite, m_isPassive, m_comment, - m_srcAddress, dstAddress, + srcAddress==SYN ? m_srcAddress : srcAddress, dstAddress, m_id, m_data, false, m_pollPriority, m_condition); } @@ -419,10 +419,10 @@ bool Message::checkId(SymbolString& master, unsigned char* index) bool Message::checkId(Message& other) { unsigned char idLen = getIdLength(); - if (idLen != other.getIdLength()) + if (idLen != other.getIdLength() || getCount() > 1) // not supported for chained messages return false; for (unsigned char pos = 0; pos < idLen; pos++) { - if (m_id[2+pos] != other.m_id[2+pos])//TODO chain + if (m_id[2+pos] != other.m_id[2+pos]) return false; } return true; @@ -517,17 +517,16 @@ result_t Message::prepareMasterPart(SymbolString& master, istringstream& input, return m_data->write(input, pt_masterData, master, getIdLength(), separator); } -result_t Message::prepareSlave(SymbolString& slaveData) +result_t Message::prepareSlave(istringstream& input, SymbolString& slaveData) { - if (!m_isPassive || m_isWrite) - return RESULT_ERR_INVALID_ARG; // prepare not possible + if (m_isWrite) + return RESULT_ERR_INVALID_ARG; // prepare not possible SymbolString slave(false); unsigned char addData = m_data->getLength(pt_slaveData); result_t result = slave.push_back(addData, false, false); if (result != RESULT_OK) return result; - istringstream input; // TODO create input from database of internal variables result = m_data->write(input, pt_slaveData, slave, 0); if (result != RESULT_OK) return result; @@ -1456,7 +1455,7 @@ deque MessageMap::findAll(const string& circuit, const string& name, c return ret; } -Message* MessageMap::find(SymbolString& master) +Message* MessageMap::find(SymbolString& master, bool anyDestination) { if (master.size() < 5) return NULL; @@ -1465,8 +1464,10 @@ Message* MessageMap::find(SymbolString& master) maxIdLength = m_maxIdLength; if (master.size() < 5+maxIdLength) return NULL; + if (maxIdLength == 0 && anyDestination && master[2] == 0x07 && master[3] == 0x04) + return m_scanMessage; unsigned long long baseKey = (unsigned long long)getMasterNumber(master[0]) << (8 * 7); // QQ address for passive message - baseKey |= (unsigned long long)master[1] << (8 * 6); // ZZ address + baseKey |= (unsigned long long)(anyDestination ? SYN : master[1]) << (8 * 6); // ZZ address baseKey |= (unsigned long long)master[2] << (8 * 5); // PB baseKey |= (unsigned long long)master[3] << (8 * 4); // SB for (unsigned char idLength = maxIdLength; true; idLength--) { diff --git a/src/lib/ebus/message.h b/src/lib/ebus/message.h index 6e48e833..37e1c34e 100644 --- a/src/lib/ebus/message.h +++ b/src/lib/ebus/message.h @@ -142,9 +142,10 @@ public: /** * Derive a new @a Message from this message. * @param dstAddress the new destination address. + * @param srcAddress the new source address, or @a SYN to keep the current source address. * @return the derived @a Message instance. */ - virtual Message* derive(const unsigned char dstAddress); + virtual Message* derive(const unsigned char dstAddress, unsigned char srcAddress); /** * Get the optional circuit name. @@ -227,7 +228,7 @@ public: * @param other the other @a Message to check against. * @return true if the ID matches, false otherwise. */ - virtual bool checkId(Message& other); + bool checkId(Message& other); /** * Return the key for storing in @a MessageMap. @@ -315,10 +316,11 @@ public: /** * 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. * @return @a RESULT_OK on success, or an error code. */ - virtual result_t prepareSlave(SymbolString& slaveData); + virtual result_t prepareSlave(istringstream& input, SymbolString& slaveData); /** * Store the last seen master and slave data. @@ -917,10 +919,11 @@ public: /** * Find the @a Message instance for the specified master data. * @param master the master @a SymbolString for identifying the @a Message. + * @param anyDestination true to only return messages without a particular destination. * @return the @a Message instance, or NULL. * Note: the caller may not free the returned instance. */ - Message* find(SymbolString& master); + Message* find(SymbolString& master, bool anyDestination=false); /** * Invalidate cached data of the @a Message and all other instances with a matching name key.