added polling by priority

This commit is contained in:
john30
2014-12-07 14:49:44 +01:00
parent a8c1343218
commit 1a138dfe1c
4 changed files with 175 additions and 57 deletions
Regular → Executable
+16 -17
View File
@@ -47,9 +47,9 @@ BaseLoop::BaseLoop()
else else
L.log(bas, error, "error reading config files: %s", getResultCode(result)); L.log(bas, error, "error reading config files: %s", getResultCode(result));
/*L.log(bas, event, "commands DB: %d ", m_commands->sizeCmdDB()); L.log(bas, event, "commands DB: %d ", m_messages->size());
L.log(bas, event, " cycle DB: %d ", m_commands->sizeCycDB()); L.log(bas, event, " cycle DB: %d ", m_messages->size(true));
L.log(bas, event, " polling DB: %d ", m_commands->sizePollDB());*/ L.log(bas, event, " polling DB: %d ", m_messages->sizePoll());
m_ownAddress = A.getOptVal<int>("address") & 0xff; m_ownAddress = A.getOptVal<int>("address") & 0xff;
const bool answer = A.getOptVal<bool>("answer"); const bool answer = A.getOptVal<bool>("answer");
@@ -65,6 +65,12 @@ BaseLoop::BaseLoop()
const unsigned int busAcquireWaitTime = A.getOptVal<unsigned int>("acquiretimeout"); const unsigned int busAcquireWaitTime = A.getOptVal<unsigned int>("acquiretimeout");
const unsigned int slaveRecvTimeout = A.getOptVal<unsigned int>("recvtimeout"); const unsigned int slaveRecvTimeout = A.getOptVal<unsigned int>("recvtimeout");
const unsigned int lockCount = A.getOptVal<unsigned int>("lockcounter"); const unsigned int lockCount = A.getOptVal<unsigned int>("lockcounter");
int pollInterval = A.getOptVal<unsigned int>("pollinterval");
if (pollInterval <= 0) {
m_pollActive = false;
pollInterval = 0;
} else
m_pollActive = true;
// create Port // create Port
m_port = new Port(A.getOptVal<const char*>("device"), A.getOptVal<bool>("nodevicecheck"), logRaw, &BaseLoop::logRaw, dumpRaw, dumpRawFile, dumpRawMaxSize); m_port = new Port(A.getOptVal<const char*>("device"), A.getOptVal<bool>("nodevicecheck"), logRaw, &BaseLoop::logRaw, dumpRaw, dumpRawFile, dumpRawMaxSize);
@@ -75,10 +81,10 @@ BaseLoop::BaseLoop()
// create BusHandler // create BusHandler
m_busHandler = new BusHandler(m_port, m_messages, m_busHandler = new BusHandler(m_port, m_messages,
answer ? m_ownAddress : SYN, answer ? (m_ownAddress+5)&0xff : SYN, m_ownAddress, answer,
busLostRetries, failedSendRetries, busLostRetries, failedSendRetries,
busAcquireWaitTime, slaveRecvTimeout, busAcquireWaitTime, slaveRecvTimeout,
lockCount); lockCount, pollInterval);
m_busHandler->start("bushandler"); m_busHandler->start("bushandler");
// create network // create network
@@ -221,23 +227,16 @@ string BaseLoop::decodeMessage(const string& data)
if (message != NULL) { if (message != NULL) {
/*if (message->getPollPriority() > 0) if (m_pollActive == true && message->getPollPriority() > 0) {
// get polldata // get polldata
polldata = m_commands->getPollData(index); token = message->getLastValue();
if (polldata != "") { if (token.empty() == false) {
// decode data result << token;
Command* command = new Command(index, (*m_commands)[index], polldata);
// return result
result << command->calcResult(cmd);
delete command;
} else { } else {
result << "no data stored"; result << "no data stored";
} }
break; break;
}*/ }
SymbolString master; SymbolString master;
istringstream input; istringstream input;
+3
View File
@@ -96,6 +96,9 @@ private:
/** the own master address for sending on the bus. */ /** the own master address for sending on the bus. */
unsigned char m_ownAddress; unsigned char m_ownAddress;
/** whether polling the messages is active. */
bool m_pollActive;
/** the @a Port instance. */ /** the @a Port instance. */
Port* m_port; Port* m_port;
Regular → Executable
+50 -7
View File
@@ -58,20 +58,41 @@ const char* getStateCode(BusState state) {
} }
BusRequest::BusRequest(SymbolString& master, SymbolString& slave) result_t PollRequest::prepare(unsigned char ownMasterAddress)
: m_master(master), m_slave(slave), m_finished(false), m_result(RESULT_SYN) {
istringstream input;
result_t result = m_message->prepareMaster(ownMasterAddress, m_master, input);
if (result == RESULT_OK)
L.log(bus, event, " poll msg: %s", m_master.getDataStr().c_str());
return result;
}
void PollRequest::notify(result_t result)
{
ostringstream output;
if (result == RESULT_OK) {
result = m_message->decode(pt_slaveData, m_slave, output); // decode data
}
if (result != RESULT_OK)
L.log(bus, error, "poll %s failed: %s", m_message->getName().c_str(), getResultCode(result));
else
L.log(bus, event, "poll %s: %s", m_message->getName().c_str(), output.str().c_str());
}
ActiveBusRequest::ActiveBusRequest(SymbolString& master, SymbolString& slave)
: BusRequest(master, slave, false), m_finished(false), m_result(RESULT_SYN)
{ {
pthread_mutex_init(&m_mutex, NULL); pthread_mutex_init(&m_mutex, NULL);
pthread_cond_init(&m_cond, NULL); pthread_cond_init(&m_cond, NULL);
} }
BusRequest::~BusRequest() ActiveBusRequest::~ActiveBusRequest()
{ {
pthread_mutex_destroy(&m_mutex); pthread_mutex_destroy(&m_mutex);
pthread_cond_destroy(&m_cond); pthread_cond_destroy(&m_cond);
} }
bool BusRequest::wait(int timeout) bool ActiveBusRequest::wait(int timeout)
{ {
m_finished = false; m_finished = false;
m_result = RESULT_SYN; m_result = RESULT_SYN;
@@ -93,7 +114,7 @@ bool BusRequest::wait(int timeout)
return result == 0; return result == 0;
} }
void BusRequest::notify(result_t result) void ActiveBusRequest::notify(result_t result)
{ {
pthread_mutex_lock(&m_mutex); pthread_mutex_lock(&m_mutex);
@@ -108,7 +129,7 @@ void BusRequest::notify(result_t result)
result_t BusHandler::sendAndWait(SymbolString& master, SymbolString& slave) result_t BusHandler::sendAndWait(SymbolString& master, SymbolString& slave)
{ {
result_t result = RESULT_SYN; result_t result = RESULT_SYN;
BusRequest* request = new BusRequest(master, slave); 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, lostRetries=m_busLostRetries+1; sendRetries>=0; sendRetries--) {
m_requests.add(request); m_requests.add(request);
@@ -172,6 +193,26 @@ result_t BusHandler::handleSymbol()
setState(bs_ready, RESULT_ERR_TIMEOUT); // just to be sure an old BusRequest is cleaned up setState(bs_ready, RESULT_ERR_TIMEOUT); // just to be sure an old BusRequest is cleaned up
if (m_remainLockCount == 0) { if (m_remainLockCount == 0) {
m_request = m_requests.next(false); m_request = m_requests.next(false);
if (m_request == NULL && m_pollInterval > 0) { // check for poll/scan
time_t now;
time(&now);
if (m_lastPoll == 0 || difftime(now, m_lastPoll) > m_pollInterval) {
Message* message = m_messages->getNextPoll();
if (message != NULL) {
m_lastPoll = now;
PollRequest* request = new PollRequest(m_response, message);
result_t ret = request->prepare(m_ownMasterAddress);
if (ret != RESULT_OK) {
L.log(bus, error, " prepare poll message: %s", getResultCode(ret));
delete request;
}
else {
m_request = request;
m_requests.add(request);
}
}
}
}
if (m_request != NULL) { // initiate arbitration if (m_request != NULL) { // initiate arbitration
sendSymbol = m_request->m_master[0]; sendSymbol = m_request->m_master[0];
sending = true; sending = true;
@@ -435,8 +476,10 @@ result_t BusHandler::setState(BusState state, result_t result, bool firstRepetit
if (m_request != NULL) { if (m_request != NULL) {
if (state == bs_sendSyn || (result != RESULT_OK && firstRepetition == false)) { if (state == bs_sendSyn || (result != RESULT_OK && firstRepetition == false)) {
L.log(bus, debug, "notify request: %s", getResultCode(result)); L.log(bus, debug, "notify request: %s", getResultCode(result));
m_request->m_slave = m_response; // TODO nicer m_request->m_slave = SymbolString(m_response, false, false);
m_request->notify(result); m_request->notify(result);
if (m_request->m_isPoll == true)
delete m_request;
m_request = NULL; m_request = NULL;
} }
} }
+106 -33
View File
@@ -58,23 +58,10 @@ enum BusState {
bs_sendSyn, // send SYN for completed transfer [active set+get] bs_sendSyn, // send SYN for completed transfer [active set+get]
}; };
/** the possible combinations of participants in a single message exchange. */
enum MessageDirection {
md_thisToAll, // message from us to all (broadcast)
md_thisToMaster, // message from us to another master
md_thisToSlave, // message from us to another slave
md_otherToAll, // message from a master (other than us) to all (broadcast)
md_otherToMaster, // message from a master (other than us) to another master (other than us)
md_otherToSlave, // message from a master (other than us) to another slave (other than us)
md_otherToThisMaster, // message from a master (other than us) to us (as master)
md_otherToThisSlave, // message from a master (other than us) to us (as slave)
md_undefined,
};
class BusHandler; class BusHandler;
/** /**
* @brief Handles input from and output to the bus with respect to the ebus protocol. * @brief Generic request for sending to and receiving from the bus.
*/ */
class BusRequest class BusRequest
{ {
@@ -85,13 +72,96 @@ public:
* @brief Constructor. * @brief Constructor.
* @param master the master data @a SymbolString to send. * @param master the master data @a SymbolString to send.
* @param slave the slave data @a SymbolString received. * @param slave the slave data @a SymbolString received.
* @param isPoll whether this is a poll request.
*/ */
BusRequest(SymbolString& master, SymbolString& slave); BusRequest(SymbolString& master, SymbolString& slave, bool isPoll)
: m_master(master), m_slave(slave), m_isPoll(isPoll) {}
/** /**
* @brief Destructor. * @brief Destructor.
*/ */
virtual ~BusRequest(); virtual ~BusRequest() {}
/**
* @brief Notify all waiting threads.
*/
virtual void notify(result_t result) = 0;
protected:
/** the master data @a SymbolString to send. */
SymbolString& m_master;
/** the slave data @a SymbolString received. */
SymbolString& m_slave;
/** whether this is a poll request. */
bool m_isPoll;
};
/**
* @brief A poll @a BusRequest handled by @a BusHandler itself.
*/
class PollRequest : public BusRequest
{
friend class BusHandler;
public:
/**
* @brief Constructor.
* @param slave the slave data @a SymbolString received.
* @param message the associated @a Message.
*/
PollRequest(SymbolString& slave, Message* message)
: BusRequest(m_master, slave, true), m_message(message) {}
/**
* @brief Destructor.
*/
virtual ~PollRequest() {}
/**
* @brief Prepare the master data.
* @param masterAddress the master bus address to use.
* @return the result code.
*/
result_t prepare(unsigned char masterAddress);
// @copydoc
virtual void notify(result_t result);
private:
/** the master data @a SymbolString. */
SymbolString m_master;
/** the associated @a Message. */
Message* m_message;
};
/**
* @brief An active @a BusRequest that can be waited for.
*/
class ActiveBusRequest : public BusRequest
{
friend class BusHandler;
public:
/**
* @brief Constructor.
* @param master the master data @a SymbolString to send.
* @param slave the slave data @a SymbolString received.
*/
ActiveBusRequest(SymbolString& master, SymbolString& slave);
/**
* @brief Destructor.
*/
virtual ~ActiveBusRequest();
/** /**
* @brief Wait for notification. * @brief Wait for notification.
@@ -100,19 +170,11 @@ public:
*/ */
bool wait(int timeout); bool wait(int timeout);
/** // @copydoc
* @brief Notify all waiting threads. virtual void notify(result_t result);
*/
void notify(result_t result);
private: private:
/** the master data @a SymbolString to send. */
SymbolString& m_master;
/** the slave data @a SymbolString received. */
SymbolString& m_slave;
/** true once the request is finished. */ /** true once the request is finished. */
bool m_finished; bool m_finished;
@@ -139,24 +201,26 @@ public:
* @brief Construct a new instance. * @brief Construct a new instance.
* @param port the @a Port instance for accessing the bus. * @param port the @a Port instance for accessing the bus.
* @param messages the @a MessageMap instance with all known @a Message instances. * @param messages the @a MessageMap instance with all known @a Message instances.
* @param ownMasterAddress the own master address to react on master-master messages, or @a SYN to ignore. * @param ownAddress the own master address.
* @param ownSlaveAddress the own slave address to react on master-slave messages, or @a SYN to ignore. * @param answer whether to answer queries for the own master/slave address.
* @param busLostRetries the number of times a send is repeated due to lost arbitration. * @param busLostRetries the number of times a send is repeated due to lost arbitration.
* @param failedSendRetries the number of times a failed send is repeated (other than lost arbitration). * @param failedSendRetries the number of times a failed send is repeated (other than lost arbitration).
* @param slaveRecvTimeout the maximum time in microseconds an addressed slave is expected to acknowledge. * @param slaveRecvTimeout the maximum time in microseconds an addressed slave is expected to acknowledge.
* @param busAcquireTimeout the maximum time in microseconds for bus acquisition. * @param busAcquireTimeout the maximum time in microseconds for bus acquisition.
* @param lockCount the number of AUTO-SYN symbols before sending is allowed after lost arbitration. * @param lockCount the number of AUTO-SYN symbols before sending is allowed after lost arbitration.
* @param pollInterval the interval in seconds in which poll messages are cycled, or 0 if disabled.
*/ */
BusHandler(Port* port, MessageMap* messages, BusHandler(Port* port, MessageMap* messages,
const unsigned char ownMasterAddress, const unsigned char ownSlaveAddress, const unsigned char ownAddress, const bool answer,
const unsigned int busLostRetries, const unsigned int failedSendRetries, const unsigned int busLostRetries, const unsigned int failedSendRetries,
const unsigned int busAcquireTimeout, const unsigned int slaveRecvTimeout, const unsigned int busAcquireTimeout, const unsigned int slaveRecvTimeout,
const unsigned int lockCount) const unsigned int lockCount, const unsigned int pollInterval)
: m_port(port), m_messages(messages), : m_port(port), m_messages(messages),
m_ownMasterAddress(ownMasterAddress), m_ownSlaveAddress(ownSlaveAddress), m_ownMasterAddress(ownAddress), m_ownSlaveAddress((ownAddress+5)&0xff), m_answer(answer),
m_busLostRetries(busLostRetries), m_failedSendRetries(failedSendRetries), m_busLostRetries(busLostRetries), m_failedSendRetries(failedSendRetries),
m_busAcquireTimeout(busAcquireTimeout), m_slaveRecvTimeout(slaveRecvTimeout), m_busAcquireTimeout(busAcquireTimeout), m_slaveRecvTimeout(slaveRecvTimeout),
m_lockCount(lockCount), m_remainLockCount(lockCount), m_lockCount(lockCount), m_remainLockCount(lockCount),
m_pollInterval(pollInterval), m_lastPoll(0),
m_request(NULL), m_nextSendPos(0), m_request(NULL), m_nextSendPos(0),
m_state(bs_skip), m_repeat(false), m_state(bs_skip), m_repeat(false),
m_commandCrcValid(false), m_responseCrcValid(false) {} m_commandCrcValid(false), m_responseCrcValid(false) {}
@@ -213,12 +277,15 @@ private:
/** the @a MessageMap instance with all known @a Message instances. */ /** the @a MessageMap instance with all known @a Message instances. */
MessageMap* m_messages; MessageMap* m_messages;
/** the own master address to react on master-master messages, or @a SYN to ignore. */ /** the own master address. */
const unsigned char m_ownMasterAddress; const unsigned char m_ownMasterAddress;
/** the own slave address to react on master-slave messages, or @a SYN to ignore. */ /** the own slave address. */
const unsigned char m_ownSlaveAddress; const unsigned char m_ownSlaveAddress;
/** whether to answer queries for the own master/slave address. */
const bool m_answer;
/** the number of times a send is repeated due to lost arbitration. */ /** the number of times a send is repeated due to lost arbitration. */
const unsigned int m_busLostRetries; const unsigned int m_busLostRetries;
@@ -237,6 +304,12 @@ private:
/** the remaining number of AUTO-SYN symbols before sending is allowed again. */ /** the remaining number of AUTO-SYN symbols before sending is allowed again. */
unsigned int m_remainLockCount; unsigned int m_remainLockCount;
/** the interval in seconds in which poll messages are cycled, or 0 if disabled. */
const unsigned int m_pollInterval;
/** the time of the last poll, or 0 for never. */
time_t m_lastPoll;
/** the queue of @a BusRequests that shall be handled. */ /** the queue of @a BusRequests that shall be handled. */
WQueue<BusRequest*> m_requests; WQueue<BusRequest*> m_requests;