added scanning and collection of seen bus addresses

This commit is contained in:
john30
2014-12-13 00:01:31 +01:00
parent 95d9c5fd08
commit 3d89fef6ae
2 changed files with 175 additions and 21 deletions
+90 -14
View File
@@ -28,6 +28,7 @@
#include <vector>
#include <cstring>
#include <time.h>
#include <iomanip>
using namespace std;
@@ -79,6 +80,27 @@ void PollRequest::notify(result_t result)
L.log(bus, event, "poll %s: %s", m_message->getName().c_str(), output.str().c_str());
}
result_t ScanRequest::prepare(unsigned char ownMasterAddress, unsigned char dstAddress)
{
istringstream input;
result_t result = m_message->prepareMaster(ownMasterAddress, m_master, input, UI_FIELD_SEPARATOR, dstAddress);
if (result == RESULT_OK)
L.log(bus, event, " scan msg: %s", m_master.getDataStr().c_str());
return result;
}
void ScanRequest::notify(result_t result)
{
if (result == RESULT_OK) {
m_scanResult << hex << setw(2) << setfill('0') << static_cast<unsigned>(m_master[1]) << UI_FIELD_SEPARATOR;
result = m_message->decode(pt_slaveData, m_slave, m_scanResult); // decode data
}
if (result != RESULT_OK)
L.log(bus, error, "scan %x failed: %s", m_master[1], getResultCode(result));
}
ActiveBusRequest::ActiveBusRequest(SymbolString& master, SymbolString& slave)
: BusRequest(master, slave, false), m_finished(false), m_result(RESULT_SYN)
{
@@ -131,7 +153,7 @@ result_t BusHandler::sendAndWait(SymbolString& master, SymbolString& slave)
result_t result = RESULT_SYN;
ActiveBusRequest* request = new ActiveBusRequest(master, slave);
for (int sendRetries=m_failedSendRetries+1, lostRetries=m_busLostRetries+1; sendRetries>=0; sendRetries--) {
for (int sendRetries=m_failedSendRetries+1; sendRetries>=0; sendRetries--) {
m_requests.add(request);
bool success = request->wait(1); // 1 second is still 3 times the theoretical worst-case request duration
if (success == false)
@@ -141,18 +163,11 @@ result_t BusHandler::sendAndWait(SymbolString& master, SymbolString& slave)
if (result == RESULT_OK)
break;
if (result == RESULT_ERR_BUS_LOST) {
if (--lostRetries > 0) {
sendRetries++; // try to get lock again, do not decrement send retries
L.log(bus, error, " %s, retry bus loss", getResultCode(result));
continue;
}
lostRetries = m_busLostRetries+1; // send retry: reset lock retries
}
L.log(bus, error, " %s, %s", getResultCode(result), sendRetries>0 ? "retry send" : "give up");
request->m_busLostRetries = 0;
}
delete request;
delete request; // TODO may be unsave while run() is using the request
return result;
}
@@ -541,12 +556,24 @@ result_t BusHandler::handleSymbol()
result_t BusHandler::setState(BusState state, result_t result, bool firstRepetition)
{
if (m_request != NULL) {
if (state == bs_sendSyn || (result != RESULT_OK && firstRepetition == false)) {
if (result == RESULT_ERR_BUS_LOST && m_request->m_busLostRetries < m_busLostRetries) {
L.log(bus, error, " %s, retry", getResultCode(result));
m_request->m_busLostRetries++;
m_requests.add(m_request); // repeat
m_request = NULL;
} else if (state == bs_sendSyn || (result != RESULT_OK && firstRepetition == false)) {
L.log(bus, debug, "notify request: %s", getResultCode(result));
m_request->m_slave = SymbolString(m_response, false, false);
m_request->notify(result);
if (m_request->m_isPoll == true)
if (m_request->m_deleteOnFinish == true) {
if (result == RESULT_OK && typeid(*m_request) == typeid(ScanRequest)) {
unsigned char dstAddress = m_request->m_master[1];
string res = ((ScanRequest*)m_request)->m_scanResult.str();
L.log(bus, debug, " scan result %x: %s", dstAddress, res.c_str());
m_scanResults[dstAddress] = res;
}
delete m_request;
}
m_request = NULL;
}
}
@@ -576,12 +603,16 @@ void BusHandler::receiveCompleted()
unsigned char dstAddress = m_command[1];
bool master = isMaster(dstAddress);
m_seenAddresses[m_command[0]] = true;
if (dstAddress == BROADCAST)
L.log(bus, trace, "received BC %s", m_command.getDataStr().c_str());
else if (master == true)
else if (master == true) {
L.log(bus, trace, "received MM %s", m_command.getDataStr().c_str());
else
m_seenAddresses[dstAddress] = true;
} else {
L.log(bus, trace, "received MS %s / %s", m_command.getDataStr().c_str(), m_response.getDataStr().c_str());
m_seenAddresses[dstAddress] = true;
}
Message* message = m_messages->find(m_command);
if (message != NULL) {
@@ -599,3 +630,48 @@ void BusHandler::receiveCompleted()
}
}
}
result_t BusHandler::startScan(bool full)
{
Message* scanMessage = m_scanMessage;
if (scanMessage == NULL) {
scanMessage = m_messages->find("", "scan", false);
}
if (scanMessage == NULL) {
DataFieldSet* identFields = DataFieldSet::createIdentFields();
scanMessage = m_scanMessage = new Message(false, false, 0x07, 0x04, identFields);
}
if (scanMessage == NULL)
return RESULT_ERR_NOTFOUND;
if (full == true)
m_scanResults.clear();
for (unsigned int slave=0; slave<=255; slave++) {
if (isValidAddress(slave, false) == false || isMaster(slave) == true)
continue;
if (full == false && m_seenAddresses[slave] == false) {
unsigned int master = slave+(256-5); // check if we saw the corresponding master already
if (isMaster(master) == false || m_seenAddresses[slave] == false)
continue;
}
ScanRequest* request = new ScanRequest(m_response, scanMessage);
result_t result = request->prepare(m_ownMasterAddress, slave);
if (result != RESULT_OK) {
delete request;
return result;
}
m_requests.add(request);
}
return RESULT_OK;
}
void BusHandler::formatScanResult(ostringstream& output)
{
for (unsigned int slave=0; slave<=255; slave++) {
map<unsigned char, string>::iterator it = m_scanResults.find(slave);
if (it != m_scanResults.end())
output << it->second << endl;
}
}
+85 -7
View File
@@ -31,6 +31,7 @@
#include <vector>
#include <map>
#include <pthread.h>
#include <typeinfo>
using namespace std;
@@ -72,10 +73,11 @@ public:
* @brief Constructor.
* @param master the master data @a SymbolString to send.
* @param slave the slave data @a SymbolString received.
* @param isPoll whether this is a poll request.
* @param deleteOnFinish whether to automatically delete this @a BusRequest when finished.
*/
BusRequest(SymbolString& master, SymbolString& slave, bool isPoll)
: m_master(master), m_slave(slave), m_isPoll(isPoll) {}
BusRequest(SymbolString& master, SymbolString& slave, bool deleteOnFinish)
: m_master(master), m_slave(slave), m_busLostRetries(0),
m_deleteOnFinish(deleteOnFinish) {}
/**
* @brief Destructor.
@@ -96,8 +98,11 @@ protected:
/** the slave data @a SymbolString received. */
SymbolString& m_slave;
/** whether this is a poll request. */
bool m_isPoll;
/** the number of times a send is repeated due to lost arbitration. */
unsigned int m_busLostRetries;
/** whether to automatically delete this @a BusRequest when finished. */
bool m_deleteOnFinish;
};
@@ -144,6 +149,52 @@ private:
};
/**
* @brief A scan @a BusRequest handled by @a BusHandler itself.
*/
class ScanRequest : public BusRequest
{
friend class BusHandler;
public:
/**
* @brief Constructor.
* @param slave the slave data @a SymbolString received.
* @param message the associated @a Message.
*/
ScanRequest(SymbolString& slave, Message* message)
: BusRequest(m_master, slave, true), m_message(message) {}
/**
* @brief Destructor.
*/
virtual ~ScanRequest() {}
/**
* @brief Prepare the master data.
* @param masterAddress the master bus address to use.
* @param dstAddress the destination address to set.
* @return the result code.
*/
result_t prepare(unsigned char masterAddress, unsigned char dstAddress);
// @copydoc
virtual void notify(result_t result);
private:
/** the master data @a SymbolString. */
SymbolString m_master;
/** the associated @a Message. */
Message* m_message;
/** the formatted scan result. */
ostringstream m_scanResult;
};
/**
* @brief An active @a BusRequest that can be waited for.
*/
@@ -224,12 +275,18 @@ public:
m_pollInterval(pollInterval), m_lastPoll(0),
m_request(NULL), m_nextSendPos(0),
m_state(bs_skip), m_repeat(false),
m_commandCrcValid(false), m_responseCrcValid(false) {}
m_commandCrcValid(false), m_responseCrcValid(false),
m_scanMessage(NULL) {
memset(m_seenAddresses, 0, sizeof(m_seenAddresses));
}
/**
* @brief Destructor.
*/
virtual ~BusHandler() {}
virtual ~BusHandler() {
if (m_scanMessage != NULL)
delete m_scanMessage;
}
/**
* @brief Send a message on the bus and wait for the answer.
@@ -250,6 +307,18 @@ public:
*/
string getReceivedData(Message* message);
/**
* @brief Initiate a scan of the slave addresses.
* @param full true for a full scan (all slaves), false for scanning only already seen slaves.
*/
result_t startScan(bool full=false);
/**
* @brief Format the scan result to the @a ostringstream.
* @param output the @a ostringstream to format the scan result to.
*/
void formatScanResult(ostringstream& output);
private:
/**
@@ -339,6 +408,15 @@ private:
/** whether the response CRC is valid. */
bool m_responseCrcValid;
/** the participating bus addresses seen so far. */
bool m_seenAddresses[256];
/** the @a Message instance used for scanning. */
Message* m_scanMessage;
/** the scan results by slave address. */
map<unsigned char, string> m_scanResults;
};