Regular → Executable
+16
-17
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+107
-33
@@ -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,97 @@ 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 the request of the specified result.
|
||||||
|
* @param result the result of the request.
|
||||||
|
*/
|
||||||
|
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 +171,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 +202,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 +278,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 +305,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;
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ Message::Message(const string clazz, const string name, const bool isSet,
|
|||||||
m_isPassive(isPassive), m_comment(comment),
|
m_isPassive(isPassive), m_comment(comment),
|
||||||
m_srcAddress(srcAddress), m_dstAddress(dstAddress),
|
m_srcAddress(srcAddress), m_dstAddress(dstAddress),
|
||||||
m_id(id), m_data(data), m_pollPriority(pollPriority),
|
m_id(id), m_data(data), m_pollPriority(pollPriority),
|
||||||
m_lastUpdateTime(0)
|
m_lastUpdateTime(0), m_pollCount(0), m_lastPollTime(0)
|
||||||
{
|
{
|
||||||
int exp = 7;
|
int exp = 7;
|
||||||
unsigned long long key = (unsigned long long)(id.size()-2) << (8 * exp + 5);
|
unsigned long long key = (unsigned long long)(id.size()-2) << (8 * exp + 5);
|
||||||
@@ -269,7 +269,7 @@ result_t Message::prepareMaster(const unsigned char srcAddress, SymbolString& ma
|
|||||||
result = m_data->write(input, pt_masterData, master, m_id.size() - 2, separator);
|
result = m_data->write(input, pt_masterData, master, m_id.size() - 2, separator);
|
||||||
if (result != RESULT_OK)
|
if (result != RESULT_OK)
|
||||||
return result;
|
return result;
|
||||||
masterData = SymbolString(master);
|
masterData = SymbolString(master, true);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,6 +298,18 @@ result_t Message::decode(const PartType partType, SymbolString& data,
|
|||||||
return RESULT_OK;
|
return RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Message::isLessPollWeight(Message* other) {
|
||||||
|
if (m_pollPriority * m_pollCount < other->m_pollPriority * other->m_pollCount)
|
||||||
|
return true;
|
||||||
|
if (m_pollPriority < other->m_pollPriority)
|
||||||
|
return true;
|
||||||
|
if (m_lastPollTime < other->m_lastPollTime)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
result_t MessageMap::add(Message* message)
|
result_t MessageMap::add(Message* message)
|
||||||
{
|
{
|
||||||
unsigned long long pkey = message->getKey();
|
unsigned long long pkey = message->getKey();
|
||||||
@@ -318,6 +330,7 @@ result_t MessageMap::add(Message* message)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_messagesByName[key] = message;
|
m_messagesByName[key] = message;
|
||||||
|
m_messageCount++;
|
||||||
|
|
||||||
key = string(isPassive ? "-P;" : (isSet ? "-W;" : "-R;")) + name; // also store without class
|
key = string(isPassive ? "-P;" : (isSet ? "-W;" : "-R;")) + name; // also store without class
|
||||||
m_messagesByName[key] = message; // last key without class overrides previous
|
m_messagesByName[key] = message; // last key without class overrides previous
|
||||||
@@ -331,7 +344,8 @@ result_t MessageMap::add(Message* message)
|
|||||||
m_passiveMessagesByKey[pkey] = message;
|
m_passiveMessagesByKey[pkey] = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
//m_pollMessages.push()
|
if (message->getPollPriority() > 0)
|
||||||
|
m_pollMessages.push(message);
|
||||||
|
|
||||||
return RESULT_OK;
|
return RESULT_OK;
|
||||||
}
|
}
|
||||||
@@ -418,12 +432,34 @@ Message* MessageMap::find(SymbolString& master)
|
|||||||
|
|
||||||
void MessageMap::clear()
|
void MessageMap::clear()
|
||||||
{
|
{
|
||||||
|
// clear poll messages
|
||||||
|
while (m_pollMessages.empty() == false) {
|
||||||
|
m_pollMessages.top();
|
||||||
|
m_pollMessages.pop();
|
||||||
|
}
|
||||||
|
// free message instances
|
||||||
for (map<string, Message*>::iterator it=m_messagesByName.begin(); it!=m_messagesByName.end(); it++) {
|
for (map<string, Message*>::iterator it=m_messagesByName.begin(); it!=m_messagesByName.end(); it++) {
|
||||||
if (it->first[0] != '-') // avoid double free
|
if (it->first[0] != '-') // avoid double free
|
||||||
delete it->second;
|
delete it->second;
|
||||||
it->second = NULL;
|
it->second = NULL;
|
||||||
}
|
}
|
||||||
|
// clear messages by name
|
||||||
|
m_messageCount = 0;
|
||||||
m_messagesByName.clear();
|
m_messagesByName.clear();
|
||||||
|
// clear messages by key
|
||||||
m_passiveMessagesByKey.clear();
|
m_passiveMessagesByKey.clear();
|
||||||
|
m_minIdLength = 4;
|
||||||
m_maxIdLength = 0;
|
m_maxIdLength = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Message* MessageMap::getNextPoll()
|
||||||
|
{
|
||||||
|
if (m_pollMessages.empty() == true)
|
||||||
|
return NULL;
|
||||||
|
Message* ret = m_pollMessages.top();
|
||||||
|
m_pollMessages.pop();
|
||||||
|
ret->m_pollCount++;
|
||||||
|
time(&(ret->m_lastPollTime));
|
||||||
|
m_pollMessages.push(ret); // re-insert at new position
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|||||||
+57
-4
@@ -29,11 +29,14 @@
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
class MessageMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Defines parameters of a message sent or received on the bus.
|
* @brief Defines parameters of a message sent or received on the bus.
|
||||||
*/
|
*/
|
||||||
class Message
|
class Message
|
||||||
{
|
{
|
||||||
|
friend class MessageMap;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -151,11 +154,24 @@ public:
|
|||||||
string getLastValue() { return m_lastValue; }
|
string getLastValue() { return m_lastValue; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the system time when @a m_lastValue was updated.
|
* @brief Get the time when @a m_lastValue was updated.
|
||||||
* @return the system time when @a m_lastValue was updated, or 0 if this message was not decoded yet.
|
* @return the time when @a m_lastValue was updated, or 0 if this message was not decoded yet.
|
||||||
*/
|
*/
|
||||||
time_t getLastUpdateTime() { return m_lastUpdateTime; }
|
time_t getLastUpdateTime() { return m_lastUpdateTime; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the time when this message was last polled for.
|
||||||
|
* @return the time when this message was last polled for, or 0 for never.
|
||||||
|
*/
|
||||||
|
time_t getLastPollTime() { return m_lastPollTime; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Return whether this @a Message needs to be polled before the other one.
|
||||||
|
* @param other the other @a Message to compare with.
|
||||||
|
* @return true if this @a Message needs to be polled before the other one.
|
||||||
|
*/
|
||||||
|
bool isLessPollWeight(Message* other);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/** the optional device class. */
|
/** the optional device class. */
|
||||||
@@ -183,10 +199,24 @@ private:
|
|||||||
const unsigned char m_pollPriority;
|
const unsigned char m_pollPriority;
|
||||||
/** the last decoded value. */
|
/** the last decoded value. */
|
||||||
string m_lastValue;
|
string m_lastValue;
|
||||||
/** the system time when @a m_lastValue was updated. */
|
/** the system time when @a m_lastValue was updated, 0 for never. */
|
||||||
time_t m_lastUpdateTime;
|
time_t m_lastUpdateTime;
|
||||||
|
/** the number of times this messages was already polled for. */
|
||||||
|
unsigned int m_pollCount;
|
||||||
|
/** the system time when this message was last polled for, 0 for never. */
|
||||||
|
time_t m_lastPollTime;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A function that compares the poll priority of two @a Message instances.
|
||||||
|
*/
|
||||||
|
struct compareMessagePriority : binary_function <Message*,Message*,bool> {
|
||||||
|
bool operator() (Message* x, Message* y) const { return x->isLessPollWeight(y) == false; };
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Holds a map of all known @a Message instances.
|
* @brief Holds a map of all known @a Message instances.
|
||||||
*/
|
*/
|
||||||
@@ -197,7 +227,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @brief Construct a new instance.
|
* @brief Construct a new instance.
|
||||||
*/
|
*/
|
||||||
MessageMap() : FileReader(true), m_minIdLength(4), m_maxIdLength(0) {}
|
MessageMap() : FileReader(true), m_minIdLength(4), m_maxIdLength(0), m_messageCount(0) {}
|
||||||
/**
|
/**
|
||||||
* @brief Destructor.
|
* @brief Destructor.
|
||||||
*/
|
*/
|
||||||
@@ -232,6 +262,23 @@ public:
|
|||||||
* @brief Removes all @a Message instances.
|
* @brief Removes all @a Message instances.
|
||||||
*/
|
*/
|
||||||
void clear();
|
void clear();
|
||||||
|
/**
|
||||||
|
* @brief Get the number of stored @a Message instances.
|
||||||
|
* @param passiveOnly true to count only passive messages, false to count all messages.
|
||||||
|
* @return the the number of stored @a Message instances.
|
||||||
|
*/
|
||||||
|
int size(const bool passiveOnly=false) { return passiveOnly ? m_passiveMessagesByKey.size() : m_messageCount; }
|
||||||
|
/**
|
||||||
|
* @brief Get the number of stored @a Message instances with a poll priority.
|
||||||
|
* @return the the number of stored @a Message instances with a poll priority.
|
||||||
|
*/
|
||||||
|
int sizePoll() { return m_pollMessages.size(); }
|
||||||
|
/**
|
||||||
|
* @brief Get the next @a Message to poll.
|
||||||
|
* @return the next @a Message to poll, or NULL.
|
||||||
|
* Note: the caller may not free the returned instance.
|
||||||
|
*/
|
||||||
|
Message* getNextPoll();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -241,12 +288,18 @@ private:
|
|||||||
/** the maximum ID length used by any of the known @a Message instances. */
|
/** the maximum ID length used by any of the known @a Message instances. */
|
||||||
unsigned char m_maxIdLength;
|
unsigned char m_maxIdLength;
|
||||||
|
|
||||||
|
/** the number of distinct @a Message instances stored in @a m_messagesByName. */
|
||||||
|
int m_messageCount;
|
||||||
|
|
||||||
/** the known @a Message instances by class and name. */
|
/** the known @a Message instances by class and name. */
|
||||||
map<string, Message*> m_messagesByName;
|
map<string, Message*> m_messagesByName;
|
||||||
|
|
||||||
/** the known passive @a Message instances by key. */
|
/** the known passive @a Message instances by key. */
|
||||||
map<unsigned long long, Message*> m_passiveMessagesByKey;
|
map<unsigned long long, Message*> m_passiveMessagesByKey;
|
||||||
|
|
||||||
|
/** the known @a Message instances to poll, by priority. */
|
||||||
|
priority_queue<Message*, vector<Message*>, compareMessagePriority> m_pollMessages;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // LIBEBUS_MESSAGE_H_
|
#endif // LIBEBUS_MESSAGE_H_
|
||||||
|
|||||||
@@ -60,15 +60,15 @@ SymbolString::SymbolString(const string& str) //TODO use a factory method instea
|
|||||||
push_back(m_crc, false, false);
|
push_back(m_crc, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
SymbolString::SymbolString(const SymbolString& str)
|
SymbolString::SymbolString(const SymbolString& str, const bool escape, const bool addCrc)
|
||||||
: m_unescapeState(0), m_crc(0)
|
: m_unescapeState(escape == true ? 0 : 1), m_crc(0)
|
||||||
{
|
{
|
||||||
// escape
|
|
||||||
for (size_t i = 0; i < str.size(); i++) {
|
for (size_t i = 0; i < str.size(); i++) {
|
||||||
push_back(str[i], false, true);
|
push_back(str[i], str.m_unescapeState == 0, true);
|
||||||
}
|
}
|
||||||
// add CRC + escape
|
if (addCrc == true)
|
||||||
push_back(m_crc, false, false);
|
// add CRC
|
||||||
|
push_back(m_crc, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
SymbolString::SymbolString(const string& str, bool isEscaped)
|
SymbolString::SymbolString(const string& str, bool isEscaped)
|
||||||
|
|||||||
+11
-3
@@ -52,10 +52,10 @@ public:
|
|||||||
*/
|
*/
|
||||||
SymbolString(const string& str);
|
SymbolString(const string& str);
|
||||||
/**
|
/**
|
||||||
* @brief Creates a new escaped instance from an unescaped @a SymbolString and adds the calculated CRC.
|
* @brief Creates a new escaped or unescaped instance from another @a SymbolString and adds the calculated CRC.
|
||||||
* @param str the unescaped SymbolString.
|
* @param str the @a SymbolString top copy from.
|
||||||
*/
|
*/
|
||||||
SymbolString(const SymbolString& str);
|
SymbolString(const SymbolString& str, const bool escape, const bool addCrc=true);
|
||||||
/**
|
/**
|
||||||
* @brief Creates a new unescaped instance from a hex string.
|
* @brief Creates a new unescaped instance from a hex string.
|
||||||
* @param isEscaped whether the hex string is escaped and shall be unescaped.
|
* @param isEscaped whether the hex string is escaped and shall be unescaped.
|
||||||
@@ -125,6 +125,14 @@ public:
|
|||||||
void clear() { m_data.clear(); m_unescapeState = m_unescapeState==0 ? 0 : 1; m_crc = 0; }
|
void clear() { m_data.clear(); m_unescapeState = m_unescapeState==0 ? 0 : 1; m_crc = 0; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Hidden copy constructor.
|
||||||
|
* @param str the @a SymbolString to copy from.
|
||||||
|
*/
|
||||||
|
SymbolString(const SymbolString& str)
|
||||||
|
: m_data(str.m_data), m_unescapeState(str.m_unescapeState), m_crc(str.m_crc) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Updates the calculated CRC in @a m_crc by adding a value.
|
* @brief Updates the calculated CRC in @a m_crc by adding a value.
|
||||||
* @param value the (escaped) value to add to the calculated CRC in @a m_crc.
|
* @param value the (escaped) value to add to the calculated CRC in @a m_crc.
|
||||||
|
|||||||
@@ -190,8 +190,8 @@ int main()
|
|||||||
string check[5] = checks[i];
|
string check[5] = checks[i];
|
||||||
istringstream isstr(check[0]);
|
istringstream isstr(check[0]);
|
||||||
string expectStr = check[1];
|
string expectStr = check[1];
|
||||||
SymbolString mstr = SymbolString(check[2], false);
|
SymbolString mstr(check[2], false);
|
||||||
SymbolString sstr = SymbolString(check[3], false);
|
SymbolString sstr(check[3], false);
|
||||||
string flags = check[4];
|
string flags = check[4];
|
||||||
bool isSet = flags.find('s') != string::npos;
|
bool isSet = flags.find('s') != string::npos;
|
||||||
bool failedCreate = flags.find('c') != string::npos;
|
bool failedCreate = flags.find('c') != string::npos;
|
||||||
@@ -247,8 +247,8 @@ int main()
|
|||||||
}
|
}
|
||||||
|
|
||||||
ostringstream output;
|
ostringstream output;
|
||||||
SymbolString writeMstr = SymbolString(mstr.getDataStr().substr(0, 10), false);
|
SymbolString writeMstr(mstr.getDataStr().substr(0, 10), false);
|
||||||
SymbolString writeSstr = SymbolString(sstr.getDataStr().substr(0, 2), false);
|
SymbolString writeSstr(sstr.getDataStr().substr(0, 2), false);
|
||||||
result = fields->read(pt_masterData, mstr, 0, output, false, verbose);
|
result = fields->read(pt_masterData, mstr, 0, output, false, verbose);
|
||||||
if (result == RESULT_OK) {
|
if (result == RESULT_OK) {
|
||||||
result = fields->read(pt_slaveData, sstr, 0, output, output.str().empty() == false, verbose);
|
result = fields->read(pt_slaveData, sstr, 0, output, output.str().empty() == false, verbose);
|
||||||
|
|||||||
@@ -47,10 +47,10 @@ int main()
|
|||||||
// field= name;[pos];type[;[divisor|values][;[unit][;[comment]]]]
|
// field= name;[pos];type[;[divisor|values][;[unit][;[comment]]]]
|
||||||
string checks[][5] = {
|
string checks[][5] = {
|
||||||
// "message", "flags"
|
// "message", "flags"
|
||||||
{"u;;first;;;fe;0700;;x;;bda", "26.10.2014", "fffe0700042610061451", "00", "p"},
|
{"u;;first;;;fe;0700;;x;;bda", "26.10.2014", "fffe07000426100614", "00", "p"},
|
||||||
{"w;;first;;;15;b509;0400;date;;bda", "26.10.2014", "ff15b5090604002610061445", "00", "m"},
|
{"w;;first;;;15;b509;0400;date;;bda", "26.10.2014", "ff15b50906040026100614", "00", "m"},
|
||||||
{"r;ehp;time;;;08;b509;0d2800;;;time", "15:00:17", "ff08b509030d2800ea", "0311000f00", "m"},
|
{"r;ehp;time;;;08;b509;0d2800;;;time", "15:00:17", "ff08b509030d2800", "0311000f", "m"},
|
||||||
{"r;ehp;date;;;08;b509;0d2900;;;hda:3", "23.11.2014", "ff08b509030d290071", "03170b0e5a", "m"},
|
{"r;ehp;date;;;08;b509;0d2900;;;hda:3", "23.11.2014", "ff08b509030d2900", "03170b0e", "m"},
|
||||||
{"u;ehp;ActualEnvironmentPower;Energiebezug;;08;B509;29BA00;;s;IGN:2;;;;;s;power", "8", "1008b5090329ba00", "03ba0008", "pm"},
|
{"u;ehp;ActualEnvironmentPower;Energiebezug;;08;B509;29BA00;;s;IGN:2;;;;;s;power", "8", "1008b5090329ba00", "03ba0008", "pm"},
|
||||||
{"uw;ehp;test;Test;;08;B5de;ab;;;power;;;;;s;hex:1", "8;39", "1008b5de02ab08", "0139", "pm"},
|
{"uw;ehp;test;Test;;08;B5de;ab;;;power;;;;;s;hex:1", "8;39", "1008b5de02ab08", "0139", "pm"},
|
||||||
{"","55.50;ok","1025b50903290000","050000780300",""},
|
{"","55.50;ok","1025b50903290000","050000780300",""},
|
||||||
@@ -76,8 +76,8 @@ int main()
|
|||||||
string check[5] = checks[i];
|
string check[5] = checks[i];
|
||||||
istringstream isstr(check[0]);
|
istringstream isstr(check[0]);
|
||||||
string inputStr = check[1];
|
string inputStr = check[1];
|
||||||
SymbolString mstr = SymbolString(check[2], false);
|
SymbolString mstr(check[2]);
|
||||||
SymbolString sstr = SymbolString(check[3], false);
|
SymbolString sstr(check[3]);
|
||||||
string flags = check[4];
|
string flags = check[4];
|
||||||
bool dontMap = flags.find('m') != string::npos;
|
bool dontMap = flags.find('m') != string::npos;
|
||||||
bool failedCreate = flags.find('c') != string::npos;
|
bool failedCreate = flags.find('c') != string::npos;
|
||||||
@@ -147,7 +147,7 @@ int main()
|
|||||||
message = deleteMessage;
|
message = deleteMessage;
|
||||||
}
|
}
|
||||||
istringstream input(inputStr);
|
istringstream input(inputStr);
|
||||||
SymbolString writeMstr = SymbolString();
|
SymbolString writeMstr;
|
||||||
if (message->isPassive() == true) {
|
if (message->isPassive() == true) {
|
||||||
ostringstream output;
|
ostringstream output;
|
||||||
result = message->decode(pt_masterData, mstr, output);
|
result = message->decode(pt_masterData, mstr, output);
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ using namespace std;
|
|||||||
|
|
||||||
int main ()
|
int main ()
|
||||||
{
|
{
|
||||||
SymbolString sstr = SymbolString("10feb5050427a915aa");
|
SymbolString sstr("10feb5050427a915aa");
|
||||||
|
|
||||||
std::string gotStr = sstr.getDataStr(false), expectStr = "10feb5050427a90015a90177";
|
std::string gotStr = sstr.getDataStr(false), expectStr = "10feb5050427a90015a90177";
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user