added scanning and collection of seen bus addresses
This commit is contained in:
+90
-14
@@ -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
@@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user