Regular → Executable
+16
-17
@@ -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<int>("address") & 0xff;
|
||||
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 slaveRecvTimeout = A.getOptVal<unsigned int>("recvtimeout");
|
||||
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
|
||||
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
|
||||
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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+107
-33
@@ -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,97 @@ 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 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.
|
||||
@@ -100,19 +171,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 +202,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 +278,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 +305,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<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_srcAddress(srcAddress), m_dstAddress(dstAddress),
|
||||
m_id(id), m_data(data), m_pollPriority(pollPriority),
|
||||
m_lastUpdateTime(0)
|
||||
m_lastUpdateTime(0), m_pollCount(0), m_lastPollTime(0)
|
||||
{
|
||||
int exp = 7;
|
||||
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);
|
||||
if (result != RESULT_OK)
|
||||
return result;
|
||||
masterData = SymbolString(master);
|
||||
masterData = SymbolString(master, true);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -298,6 +298,18 @@ result_t Message::decode(const PartType partType, SymbolString& data,
|
||||
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)
|
||||
{
|
||||
unsigned long long pkey = message->getKey();
|
||||
@@ -318,6 +330,7 @@ result_t MessageMap::add(Message* message)
|
||||
}
|
||||
|
||||
m_messagesByName[key] = message;
|
||||
m_messageCount++;
|
||||
|
||||
key = string(isPassive ? "-P;" : (isSet ? "-W;" : "-R;")) + name; // also store without class
|
||||
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_pollMessages.push()
|
||||
if (message->getPollPriority() > 0)
|
||||
m_pollMessages.push(message);
|
||||
|
||||
return RESULT_OK;
|
||||
}
|
||||
@@ -418,12 +432,34 @@ Message* MessageMap::find(SymbolString& master)
|
||||
|
||||
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++) {
|
||||
if (it->first[0] != '-') // avoid double free
|
||||
delete it->second;
|
||||
it->second = NULL;
|
||||
}
|
||||
// clear messages by name
|
||||
m_messageCount = 0;
|
||||
m_messagesByName.clear();
|
||||
// clear messages by key
|
||||
m_passiveMessagesByKey.clear();
|
||||
m_minIdLength = 4;
|
||||
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;
|
||||
|
||||
class MessageMap;
|
||||
|
||||
/**
|
||||
* @brief Defines parameters of a message sent or received on the bus.
|
||||
*/
|
||||
class Message
|
||||
{
|
||||
friend class MessageMap;
|
||||
public:
|
||||
|
||||
/**
|
||||
@@ -151,11 +154,24 @@ public:
|
||||
string getLastValue() { return m_lastValue; }
|
||||
|
||||
/**
|
||||
* @brief Get the system 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.
|
||||
* @brief Get the time when @a m_lastValue was updated.
|
||||
* @return the time when @a m_lastValue was updated, or 0 if this message was not decoded yet.
|
||||
*/
|
||||
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:
|
||||
|
||||
/** the optional device class. */
|
||||
@@ -183,10 +199,24 @@ private:
|
||||
const unsigned char m_pollPriority;
|
||||
/** the last decoded value. */
|
||||
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;
|
||||
/** 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.
|
||||
*/
|
||||
@@ -197,7 +227,7 @@ public:
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
@@ -232,6 +262,23 @@ public:
|
||||
* @brief Removes all @a Message instances.
|
||||
*/
|
||||
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:
|
||||
|
||||
@@ -241,12 +288,18 @@ private:
|
||||
/** the maximum ID length used by any of the known @a Message instances. */
|
||||
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. */
|
||||
map<string, Message*> m_messagesByName;
|
||||
|
||||
/** the known passive @a Message instances by key. */
|
||||
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_
|
||||
|
||||
@@ -60,15 +60,15 @@ SymbolString::SymbolString(const string& str) //TODO use a factory method instea
|
||||
push_back(m_crc, false, false);
|
||||
}
|
||||
|
||||
SymbolString::SymbolString(const SymbolString& str)
|
||||
: m_unescapeState(0), m_crc(0)
|
||||
SymbolString::SymbolString(const SymbolString& str, const bool escape, const bool addCrc)
|
||||
: m_unescapeState(escape == true ? 0 : 1), m_crc(0)
|
||||
{
|
||||
// escape
|
||||
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
|
||||
push_back(m_crc, false, false);
|
||||
if (addCrc == true)
|
||||
// add CRC
|
||||
push_back(m_crc, false, false);
|
||||
}
|
||||
|
||||
SymbolString::SymbolString(const string& str, bool isEscaped)
|
||||
|
||||
+11
-3
@@ -52,10 +52,10 @@ public:
|
||||
*/
|
||||
SymbolString(const string& str);
|
||||
/**
|
||||
* @brief Creates a new escaped instance from an unescaped @a SymbolString and adds the calculated CRC.
|
||||
* @param str the unescaped SymbolString.
|
||||
* @brief Creates a new escaped or unescaped instance from another @a SymbolString and adds the calculated CRC.
|
||||
* @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.
|
||||
* @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; }
|
||||
|
||||
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.
|
||||
* @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];
|
||||
istringstream isstr(check[0]);
|
||||
string expectStr = check[1];
|
||||
SymbolString mstr = SymbolString(check[2], false);
|
||||
SymbolString sstr = SymbolString(check[3], false);
|
||||
SymbolString mstr(check[2], false);
|
||||
SymbolString sstr(check[3], false);
|
||||
string flags = check[4];
|
||||
bool isSet = flags.find('s') != string::npos;
|
||||
bool failedCreate = flags.find('c') != string::npos;
|
||||
@@ -247,8 +247,8 @@ int main()
|
||||
}
|
||||
|
||||
ostringstream output;
|
||||
SymbolString writeMstr = SymbolString(mstr.getDataStr().substr(0, 10), false);
|
||||
SymbolString writeSstr = SymbolString(sstr.getDataStr().substr(0, 2), false);
|
||||
SymbolString writeMstr(mstr.getDataStr().substr(0, 10), false);
|
||||
SymbolString writeSstr(sstr.getDataStr().substr(0, 2), false);
|
||||
result = fields->read(pt_masterData, mstr, 0, output, false, verbose);
|
||||
if (result == RESULT_OK) {
|
||||
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]]]]
|
||||
string checks[][5] = {
|
||||
// "message", "flags"
|
||||
{"u;;first;;;fe;0700;;x;;bda", "26.10.2014", "fffe0700042610061451", "00", "p"},
|
||||
{"w;;first;;;15;b509;0400;date;;bda", "26.10.2014", "ff15b5090604002610061445", "00", "m"},
|
||||
{"r;ehp;time;;;08;b509;0d2800;;;time", "15:00:17", "ff08b509030d2800ea", "0311000f00", "m"},
|
||||
{"r;ehp;date;;;08;b509;0d2900;;;hda:3", "23.11.2014", "ff08b509030d290071", "03170b0e5a", "m"},
|
||||
{"u;;first;;;fe;0700;;x;;bda", "26.10.2014", "fffe07000426100614", "00", "p"},
|
||||
{"w;;first;;;15;b509;0400;date;;bda", "26.10.2014", "ff15b50906040026100614", "00", "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", "ff08b509030d2900", "03170b0e", "m"},
|
||||
{"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"},
|
||||
{"","55.50;ok","1025b50903290000","050000780300",""},
|
||||
@@ -76,8 +76,8 @@ int main()
|
||||
string check[5] = checks[i];
|
||||
istringstream isstr(check[0]);
|
||||
string inputStr = check[1];
|
||||
SymbolString mstr = SymbolString(check[2], false);
|
||||
SymbolString sstr = SymbolString(check[3], false);
|
||||
SymbolString mstr(check[2]);
|
||||
SymbolString sstr(check[3]);
|
||||
string flags = check[4];
|
||||
bool dontMap = flags.find('m') != string::npos;
|
||||
bool failedCreate = flags.find('c') != string::npos;
|
||||
@@ -147,7 +147,7 @@ int main()
|
||||
message = deleteMessage;
|
||||
}
|
||||
istringstream input(inputStr);
|
||||
SymbolString writeMstr = SymbolString();
|
||||
SymbolString writeMstr;
|
||||
if (message->isPassive() == true) {
|
||||
ostringstream output;
|
||||
result = message->decode(pt_masterData, mstr, output);
|
||||
|
||||
@@ -25,7 +25,7 @@ using namespace std;
|
||||
|
||||
int main ()
|
||||
{
|
||||
SymbolString sstr = SymbolString("10feb5050427a915aa");
|
||||
SymbolString sstr("10feb5050427a915aa");
|
||||
|
||||
std::string gotStr = sstr.getDataStr(false), expectStr = "10feb5050427a90015a90177";
|
||||
|
||||
|
||||
Reference in New Issue
Block a user