fixes for answer mode, fix for duplicate counting of own master address, fix for empty scan and missing seen state, added answer to scan message in answer mode, solved TODO

This commit is contained in:
john30
2016-01-02 01:13:48 +01:00
parent 7b1a4de64d
commit d3e077b32e
4 changed files with 73 additions and 52 deletions
+1
View File
@@ -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_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_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_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_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], []) AC_CHECK_PROGS([HAVE_DOXYGEN], [doxygen], [])
+54 -38
View File
@@ -22,6 +22,7 @@
#include "result.h" #include "result.h"
#include "symbol.h" #include "symbol.h"
#include "log.h" #include "log.h"
#include "config.h"
#include <unistd.h> #include <unistd.h>
#include <string> #include <string>
#include <vector> #include <vector>
@@ -56,7 +57,6 @@ const char* getStateCode(BusState state) {
} }
} }
result_t PollRequest::prepare(unsigned char ownMasterAddress) result_t PollRequest::prepare(unsigned char ownMasterAddress)
{ {
istringstream input; istringstream input;
@@ -323,14 +323,14 @@ result_t BusHandler::handleSymbol()
break; break;
case bs_sendCmdAck: case bs_sendCmdAck:
if (m_currentRequest != NULL) { if (m_answer) {
sendSymbol = m_commandCrcValid ? ACK : NAK; sendSymbol = m_commandCrcValid ? ACK : NAK;
sending = true; sending = true;
} }
break; break;
case bs_sendRes: case bs_sendRes:
if (m_currentRequest != NULL) { if (m_answer) {
sendSymbol = m_response[m_nextSendPos]; // escaped response sendSymbol = m_response[m_nextSendPos]; // escaped response
sending = true; sending = true;
} }
@@ -379,10 +379,14 @@ result_t BusHandler::handleSymbol()
logError(lf_bus, "unable to receive sent AUTO-SYN symbol: %s", getResultCode(result)); logError(lf_bus, "unable to receive sent AUTO-SYN symbol: %s", getResultCode(result));
else if (recvSymbol != SYN) { else if (recvSymbol != SYN) {
logError(lf_bus, "received %2.2x instead of AUTO-SYN symbol", recvSymbol); logError(lf_bus, "received %2.2x instead of AUTO-SYN symbol", recvSymbol);
} else if (m_generateSynInterval != SYN_TIMEOUT) { } else {
// received own AUTO-SYN symbol back again: act as AUTO-SYN generator now if (m_generateSynInterval != SYN_TIMEOUT) {
m_generateSynInterval = SYN_TIMEOUT; // received own AUTO-SYN symbol back again: act as AUTO-SYN generator now
logNotice(lf_bus, "acting as AUTO-SYN generator"); 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); return setState(bs_skip, result);
@@ -466,6 +470,7 @@ result_t BusHandler::handleSymbol()
&& (dstAddress == m_ownMasterAddress || dstAddress == m_ownSlaveAddress)) && (dstAddress == m_ownMasterAddress || dstAddress == m_ownSlaveAddress))
return setState(bs_sendCmdAck, RESULT_OK); return setState(bs_sendCmdAck, RESULT_OK);
addSeenAddress(m_command[0]);
return setState(bs_recvCmdAck, RESULT_OK); return setState(bs_recvCmdAck, RESULT_OK);
} }
if (dstAddress == BROADCAST) if (dstAddress == BROADCAST)
@@ -597,34 +602,43 @@ result_t BusHandler::handleSymbol()
return setState(bs_skip, RESULT_ERR_INVALID_ARG); return setState(bs_skip, RESULT_ERR_INVALID_ARG);
case bs_sendCmdAck: case bs_sendCmdAck:
if (sending && m_answer) { if (sending && m_answer && recvSymbol == sendSymbol) {
if (recvSymbol == sendSymbol) { // successfully sent
// successfully sent if (!m_commandCrcValid) {
if (!m_commandCrcValid) { if (!m_repeat) {
if (!m_repeat) { m_repeat = true;
m_repeat = true; m_command.clear();
m_command.clear(); return setState(bs_recvCmd, RESULT_ERR_NAK, true);
return setState(bs_recvCmd, RESULT_ERR_NAK, true);
}
return setState(bs_skip, RESULT_ERR_ACK);
} }
if (isMaster(m_command[1])) return setState(bs_skip, RESULT_ERR_ACK);
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);
} }
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); return setState(bs_skip, RESULT_ERR_INVALID_ARG);
@@ -739,10 +753,12 @@ void BusHandler::addSeenAddress(unsigned char address)
return; return;
} }
if ((m_seenAddresses[address]&SEEN)==0) { if ((m_seenAddresses[address]&SEEN)==0) {
m_masterCount++; if (!m_answer || address!=m_ownMasterAddress) {
if (m_autoLockCount && m_masterCount>m_lockCount) m_masterCount++;
m_lockCount = m_masterCount; if (m_autoLockCount && m_masterCount>m_lockCount)
logNotice(lf_bus, "new master %2.2x, master count %d", address, m_masterCount); m_lockCount = m_masterCount;
logNotice(lf_bus, "new master %2.2x, master count %d", address, m_masterCount);
}
m_seenAddresses[address] |= SEEN; m_seenAddresses[address] |= SEEN;
} }
} }
@@ -843,7 +859,7 @@ result_t BusHandler::startScan(bool full)
result_t result = request->prepare(m_ownMasterAddress); result_t result = request->prepare(m_ownMasterAddress);
if (result < RESULT_OK) { if (result < RESULT_OK) {
delete request; delete request;
return result; return result==RESULT_ERR_EOF ? RESULT_EMPTY : result;
} }
m_nextRequests.push(request); m_nextRequests.push(request);
return RESULT_OK; return RESULT_OK;
+11 -10
View File
@@ -378,11 +378,11 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
return RESULT_OK; 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, return new Message(m_circuit, m_name, m_isWrite,
m_isPassive, m_comment, m_isPassive, m_comment,
m_srcAddress, dstAddress, srcAddress==SYN ? m_srcAddress : srcAddress, dstAddress,
m_id, m_data, false, m_id, m_data, false,
m_pollPriority, m_condition); m_pollPriority, m_condition);
} }
@@ -419,10 +419,10 @@ bool Message::checkId(SymbolString& master, unsigned char* index)
bool Message::checkId(Message& other) bool Message::checkId(Message& other)
{ {
unsigned char idLen = getIdLength(); unsigned char idLen = getIdLength();
if (idLen != other.getIdLength()) if (idLen != other.getIdLength() || getCount() > 1) // not supported for chained messages
return false; return false;
for (unsigned char pos = 0; pos < idLen; pos++) { 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 false;
} }
return true; return true;
@@ -517,17 +517,16 @@ result_t Message::prepareMasterPart(SymbolString& master, istringstream& input,
return m_data->write(input, pt_masterData, master, getIdLength(), separator); 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) if (m_isWrite)
return RESULT_ERR_INVALID_ARG; // prepare not possible return RESULT_ERR_INVALID_ARG; // prepare not possible
SymbolString slave(false); SymbolString slave(false);
unsigned char addData = m_data->getLength(pt_slaveData); unsigned char addData = m_data->getLength(pt_slaveData);
result_t result = slave.push_back(addData, false, false); result_t result = slave.push_back(addData, false, false);
if (result != RESULT_OK) if (result != RESULT_OK)
return result; return result;
istringstream input; // TODO create input from database of internal variables
result = m_data->write(input, pt_slaveData, slave, 0); result = m_data->write(input, pt_slaveData, slave, 0);
if (result != RESULT_OK) if (result != RESULT_OK)
return result; return result;
@@ -1456,7 +1455,7 @@ deque<Message*> MessageMap::findAll(const string& circuit, const string& name, c
return ret; return ret;
} }
Message* MessageMap::find(SymbolString& master) Message* MessageMap::find(SymbolString& master, bool anyDestination)
{ {
if (master.size() < 5) if (master.size() < 5)
return NULL; return NULL;
@@ -1465,8 +1464,10 @@ Message* MessageMap::find(SymbolString& master)
maxIdLength = m_maxIdLength; maxIdLength = m_maxIdLength;
if (master.size() < 5+maxIdLength) if (master.size() < 5+maxIdLength)
return NULL; 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 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[2] << (8 * 5); // PB
baseKey |= (unsigned long long)master[3] << (8 * 4); // SB baseKey |= (unsigned long long)master[3] << (8 * 4); // SB
for (unsigned char idLength = maxIdLength; true; idLength--) { for (unsigned char idLength = maxIdLength; true; idLength--) {
+7 -4
View File
@@ -142,9 +142,10 @@ public:
/** /**
* Derive a new @a Message from this message. * Derive a new @a Message from this message.
* @param dstAddress the new destination address. * @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. * @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. * Get the optional circuit name.
@@ -227,7 +228,7 @@ public:
* @param other the other @a Message to check against. * @param other the other @a Message to check against.
* @return true if the ID matches, false otherwise. * @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. * 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. * 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 slaveData the slave data @a SymbolString for writing symbols to.
* @return @a RESULT_OK on success, or an error code. * @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. * Store the last seen master and slave data.
@@ -917,10 +919,11 @@ public:
/** /**
* Find the @a Message instance for the specified master data. * Find the @a Message instance for the specified master data.
* @param master the master @a SymbolString for identifying the @a Message. * @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. * @return the @a Message instance, or NULL.
* Note: the caller may not free the returned instance. * 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. * Invalidate cached data of the @a Message and all other instances with a matching name key.