diff --git a/src/ebusd/baseloop.cpp b/src/ebusd/baseloop.cpp old mode 100644 new mode 100755 index 42bd1ce0..93a78098 --- a/src/ebusd/baseloop.cpp +++ b/src/ebusd/baseloop.cpp @@ -47,9 +47,9 @@ BaseLoop::BaseLoop() else 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, " cycle DB: %d ", m_commands->sizeCycDB()); - L.log(bas, event, " polling DB: %d ", m_commands->sizePollDB());*/ + L.log(bas, event, "commands DB: %d ", m_messages->size()); + L.log(bas, event, " cycle DB: %d ", m_messages->size(true)); + L.log(bas, event, " polling DB: %d ", m_messages->sizePoll()); m_ownAddress = A.getOptVal("address") & 0xff; const bool answer = A.getOptVal("answer"); @@ -65,6 +65,12 @@ BaseLoop::BaseLoop() const unsigned int busAcquireWaitTime = A.getOptVal("acquiretimeout"); const unsigned int slaveRecvTimeout = A.getOptVal("recvtimeout"); const unsigned int lockCount = A.getOptVal("lockcounter"); + int pollInterval = A.getOptVal("pollinterval"); + if (pollInterval <= 0) { + m_pollActive = false; + pollInterval = 0; + } else + m_pollActive = true; // create Port m_port = new Port(A.getOptVal("device"), A.getOptVal("nodevicecheck"), logRaw, &BaseLoop::logRaw, dumpRaw, dumpRawFile, dumpRawMaxSize); @@ -75,10 +81,10 @@ BaseLoop::BaseLoop() // create BusHandler m_busHandler = new BusHandler(m_port, m_messages, - answer ? m_ownAddress : SYN, answer ? (m_ownAddress+5)&0xff : SYN, + m_ownAddress, answer, busLostRetries, failedSendRetries, busAcquireWaitTime, slaveRecvTimeout, - lockCount); + lockCount, pollInterval); m_busHandler->start("bushandler"); // create network @@ -221,23 +227,16 @@ string BaseLoop::decodeMessage(const string& data) if (message != NULL) { - /*if (message->getPollPriority() > 0) + if (m_pollActive == true && message->getPollPriority() > 0) { // get polldata - polldata = m_commands->getPollData(index); - if (polldata != "") { - // decode data - Command* command = new Command(index, (*m_commands)[index], polldata); - - // return result - result << command->calcResult(cmd); - - delete command; + token = message->getLastValue(); + if (token.empty() == false) { + result << token; } else { result << "no data stored"; } - break; - }*/ + } SymbolString master; istringstream input; diff --git a/src/ebusd/baseloop.h b/src/ebusd/baseloop.h index 73f6407b..79343201 100644 --- a/src/ebusd/baseloop.h +++ b/src/ebusd/baseloop.h @@ -96,6 +96,9 @@ private: /** the own master address for sending on the bus. */ unsigned char m_ownAddress; + /** whether polling the messages is active. */ + bool m_pollActive; + /** the @a Port instance. */ Port* m_port; diff --git a/src/ebusd/bushandler.cpp b/src/ebusd/bushandler.cpp old mode 100644 new mode 100755 index 30d43e08..a37906af --- a/src/ebusd/bushandler.cpp +++ b/src/ebusd/bushandler.cpp @@ -58,20 +58,41 @@ const char* getStateCode(BusState state) { } -BusRequest::BusRequest(SymbolString& master, SymbolString& slave) - : m_master(master), m_slave(slave), m_finished(false), m_result(RESULT_SYN) +result_t PollRequest::prepare(unsigned char ownMasterAddress) +{ + 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_cond_init(&m_cond, NULL); } -BusRequest::~BusRequest() +ActiveBusRequest::~ActiveBusRequest() { pthread_mutex_destroy(&m_mutex); pthread_cond_destroy(&m_cond); } -bool BusRequest::wait(int timeout) +bool ActiveBusRequest::wait(int timeout) { m_finished = false; m_result = RESULT_SYN; @@ -93,7 +114,7 @@ bool BusRequest::wait(int timeout) return result == 0; } -void BusRequest::notify(result_t result) +void ActiveBusRequest::notify(result_t result) { 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 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--) { 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 if (m_remainLockCount == 0) { 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 sendSymbol = m_request->m_master[0]; sending = true; @@ -435,8 +476,10 @@ result_t BusHandler::setState(BusState state, result_t result, bool firstRepetit if (m_request != NULL) { if (state == bs_sendSyn || (result != RESULT_OK && firstRepetition == false)) { 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); + if (m_request->m_isPoll == true) + delete m_request; m_request = NULL; } } diff --git a/src/ebusd/bushandler.h b/src/ebusd/bushandler.h index 8ad6e474..268a1d3d 100644 --- a/src/ebusd/bushandler.h +++ b/src/ebusd/bushandler.h @@ -58,23 +58,10 @@ enum BusState { 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; /** - * @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 { @@ -85,13 +72,96 @@ 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. */ - BusRequest(SymbolString& master, SymbolString& slave); + BusRequest(SymbolString& master, SymbolString& slave, bool isPoll) + : m_master(master), m_slave(slave), m_isPoll(isPoll) {} /** * @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. @@ -100,19 +170,11 @@ public: */ bool wait(int timeout); - /** - * @brief Notify all waiting threads. - */ - void notify(result_t result); + // @copydoc + virtual void notify(result_t result); 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. */ bool m_finished; @@ -139,24 +201,26 @@ public: * @brief Construct a new instance. * @param port the @a Port instance for accessing the bus. * @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 ownSlaveAddress the own slave address to react on master-slave messages, or @a SYN to ignore. + * @param ownAddress the own master address. + * @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 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 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 pollInterval the interval in seconds in which poll messages are cycled, or 0 if disabled. */ 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 busAcquireTimeout, const unsigned int slaveRecvTimeout, - const unsigned int lockCount) + const unsigned int lockCount, const unsigned int pollInterval) : 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_busAcquireTimeout(busAcquireTimeout), m_slaveRecvTimeout(slaveRecvTimeout), m_lockCount(lockCount), m_remainLockCount(lockCount), + 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) {} @@ -213,12 +277,15 @@ private: /** the @a MessageMap instance with all known @a Message instances. */ 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; - /** the own slave address to react on master-slave messages, or @a SYN to ignore. */ + /** the own slave address. */ 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. */ const unsigned int m_busLostRetries; @@ -237,6 +304,12 @@ private: /** the remaining number of AUTO-SYN symbols before sending is allowed again. */ 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. */ WQueue m_requests;