Merge pull request #24 from john30/master

completed individual scan
This commit is contained in:
Roland Jax
2014-12-14 19:33:51 +01:00
10 changed files with 176 additions and 92 deletions
+4
View File
@@ -351,6 +351,10 @@ string BaseLoop::decodeMessage(const string& data)
break; break;
SymbolString master(msg.str()); SymbolString master(msg.str());
if (isValidAddress(master[1]) == false) {
result << "invalid destination";
break;
}
L.log(bas, event, "write hex cmd: %s", master.getDataStr().c_str()); L.log(bas, event, "write hex cmd: %s", master.getDataStr().c_str());
// send message // send message
+51 -18
View File
@@ -26,6 +26,7 @@
#include "appl.h" #include "appl.h"
#include <string> #include <string>
#include <vector> #include <vector>
#include <deque>
#include <cstring> #include <cstring>
#include <time.h> #include <time.h>
#include <iomanip> #include <iomanip>
@@ -68,16 +69,18 @@ result_t PollRequest::prepare(unsigned char ownMasterAddress)
return result; return result;
} }
void PollRequest::notify(result_t result) bool PollRequest::notify(result_t result, SymbolString& slave)
{ {
ostringstream output; ostringstream output;
if (result == RESULT_OK) { if (result == RESULT_OK) {
result = m_message->decode(pt_slaveData, m_slave, output); // decode data result = m_message->decode(pt_slaveData, slave, output); // decode data
} }
if (result != RESULT_OK) if (result != RESULT_OK)
L.log(bus, error, "poll %s failed: %s", m_message->getName().c_str(), getResultCode(result)); L.log(bus, error, "poll %s failed: %s", m_message->getName().c_str(), getResultCode(result));
else else
L.log(bus, event, "poll %s: %s", m_message->getName().c_str(), output.str().c_str()); L.log(bus, event, "poll %s: %s", m_message->getName().c_str(), output.str().c_str());
return false;
} }
@@ -90,27 +93,47 @@ result_t ScanRequest::prepare(unsigned char ownMasterAddress, unsigned char dstA
return result; return result;
} }
void ScanRequest::notify(result_t result) bool ScanRequest::notify(result_t result, SymbolString& slave)
{ {
unsigned char dstAddress = m_master[1]; unsigned char dstAddress = m_master[1];
bool append = m_scanResults != NULL && m_scanResults->find(dstAddress) != m_scanResults->end();
ostringstream scanResult; ostringstream scanResult;
if (result == RESULT_OK) { if (result == RESULT_OK) {
if (append == false)
scanResult << hex << setw(2) << setfill('0') << static_cast<unsigned>(dstAddress) << UI_FIELD_SEPARATOR; scanResult << hex << setw(2) << setfill('0') << static_cast<unsigned>(dstAddress) << UI_FIELD_SEPARATOR;
result = m_message->decode(pt_slaveData, m_slave, scanResult); // decode data result = m_message->decode(pt_slaveData, slave, scanResult, append); // decode data
} }
if (result != RESULT_OK) if (result != RESULT_OK) {
L.log(bus, error, "scan %2.2x failed: %s", dstAddress, getResultCode(result)); L.log(bus, error, "scan %2.2x failed: %s", dstAddress, getResultCode(result));
else { return false;
}
string str = scanResult.str(); string str = scanResult.str();
L.log(bus, event, "scan: %s", str.c_str()); L.log(bus, event, "scan: %s", str.c_str());
if (m_scanResults != NULL) if (m_scanResults != NULL) {
if (append == true)
(*m_scanResults)[dstAddress] += str;
else
(*m_scanResults)[dstAddress] = str; (*m_scanResults)[dstAddress] = str;
} }
// check for remaining secondary messages
if (m_messages.empty() == true)
return false;
m_message = m_messages.front();
m_messages.pop_front();
result = prepare(m_master[0], dstAddress);
if (result != RESULT_OK)
return false; // give up
return true;
} }
ActiveBusRequest::ActiveBusRequest(SymbolString& master, SymbolString& slave) ActiveBusRequest::ActiveBusRequest(SymbolString& master, SymbolString& slave)
: BusRequest(master, slave, false), m_finished(false), m_result(RESULT_SYN) : BusRequest(master, false), m_finished(false), m_result(RESULT_SYN), m_slave(slave)
{ {
pthread_mutex_init(&m_mutex, NULL); pthread_mutex_init(&m_mutex, NULL);
pthread_cond_init(&m_cond, NULL); pthread_cond_init(&m_cond, NULL);
@@ -144,18 +167,20 @@ bool ActiveBusRequest::wait(int timeout)
return result == 0; return result == 0;
} }
void ActiveBusRequest::notify(result_t result) bool ActiveBusRequest::notify(result_t result, SymbolString& slave)
{ {
if (result == RESULT_OK) if (result == RESULT_OK)
L.log(bus, event, "read res: %s", m_slave.getDataStr().c_str()); L.log(bus, event, "read res: %s", slave.getDataStr().c_str());
pthread_mutex_lock(&m_mutex); pthread_mutex_lock(&m_mutex);
m_result = result; m_result = result;
m_slave = SymbolString(slave, false, false);
m_finished = true; m_finished = true;
pthread_cond_signal(&m_cond); pthread_cond_signal(&m_cond);
pthread_mutex_unlock(&m_mutex); pthread_mutex_unlock(&m_mutex);
return false;
} }
@@ -226,7 +251,7 @@ result_t BusHandler::handleSymbol()
Message* message = m_messages->getNextPoll(); Message* message = m_messages->getNextPoll();
if (message != NULL) { if (message != NULL) {
m_lastPoll = now; m_lastPoll = now;
PollRequest* request = new PollRequest(m_response, message); PollRequest* request = new PollRequest(message);
result_t ret = request->prepare(m_ownMasterAddress); result_t ret = request->prepare(m_ownMasterAddress);
if (ret != RESULT_OK) { if (ret != RESULT_OK) {
L.log(bus, error, "prepare poll message: %s", getResultCode(ret)); L.log(bus, error, "prepare poll message: %s", getResultCode(ret));
@@ -574,12 +599,15 @@ result_t BusHandler::setState(BusState state, result_t result, bool firstRepetit
m_request = NULL; m_request = NULL;
} else if (state == bs_sendSyn || (result != RESULT_OK && firstRepetition == false)) { } else 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 = SymbolString(m_response, false, false); bool restart = m_request->notify(result, m_response);
unsigned char dstAddress = m_request->m_master[1]; unsigned char dstAddress = m_request->m_master[1];
if (result == RESULT_OK && isValidAddress(dstAddress, false) == true) if (result == RESULT_OK && isValidAddress(dstAddress, false) == true)
m_seenAddresses[dstAddress] = true; m_seenAddresses[dstAddress] = true;
m_request->notify(result); if (restart == true) {
if (m_request->m_deleteOnFinish == true) { m_request->m_busLostRetries = 0;
m_requests.add(m_request);
}
else if (m_request->m_deleteOnFinish == true) {
delete m_request; delete m_request;
} }
m_request = NULL; m_request = NULL;
@@ -642,8 +670,14 @@ void BusHandler::receiveCompleted()
result_t BusHandler::startScan(bool full) result_t BusHandler::startScan(bool full)
{ {
Message* scanMessage = m_scanMessage; Message* scanMessage = m_scanMessage;
if (scanMessage == NULL) { deque<Message*> messages = m_messages->findAll("scan", "", -1);
scanMessage = m_messages->find("", "scan", false); for (deque<Message*>::iterator it = messages.begin(); it < messages.end();) {
Message* message = *it++;
if (message->getId()[0] == 0x07 && message->getId()[1] == 0x04) {
if (scanMessage == NULL)
scanMessage = message;
messages.erase(it - 1); // query pb 0x07 / sb 0x04 only once
}
} }
if (scanMessage == NULL) { if (scanMessage == NULL) {
DataFieldSet* identFields = DataFieldSet::createIdentFields(); DataFieldSet* identFields = DataFieldSet::createIdentFields();
@@ -652,7 +686,6 @@ result_t BusHandler::startScan(bool full)
if (scanMessage == NULL) if (scanMessage == NULL)
return RESULT_ERR_NOTFOUND; return RESULT_ERR_NOTFOUND;
if (full == true)
m_scanResults.clear(); m_scanResults.clear();
for (unsigned int slave=0; slave<=255; slave++) { for (unsigned int slave=0; slave<=255; slave++) {
@@ -664,7 +697,7 @@ result_t BusHandler::startScan(bool full)
continue; continue;
} }
ScanRequest* request = new ScanRequest(m_response, scanMessage, &m_scanResults); ScanRequest* request = new ScanRequest(scanMessage, messages, &m_scanResults);
result_t result = request->prepare(m_ownMasterAddress, slave); result_t result = request->prepare(m_ownMasterAddress, slave);
if (result != RESULT_OK) { if (result != RESULT_OK) {
delete request; delete request;
+24 -19
View File
@@ -71,11 +71,10 @@ 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 deleteOnFinish whether to automatically delete this @a BusRequest when finished. * @param deleteOnFinish whether to automatically delete this @a BusRequest when finished.
*/ */
BusRequest(SymbolString& master, SymbolString& slave, bool deleteOnFinish) BusRequest(SymbolString& master, const bool deleteOnFinish)
: m_master(master), m_slave(slave), m_busLostRetries(0), : m_master(master), m_busLostRetries(0),
m_deleteOnFinish(deleteOnFinish) {} m_deleteOnFinish(deleteOnFinish) {}
/** /**
@@ -86,22 +85,21 @@ public:
/** /**
* @brief Notify the request of the specified result. * @brief Notify the request of the specified result.
* @param result the result of the request. * @param result the result of the request.
* @param slave the slave data @a SymbolString received.
* @return true if the request needs to be restarted.
*/ */
virtual void notify(result_t result) = 0; virtual bool notify(result_t result, SymbolString& slave) = 0;
protected: protected:
/** the master data @a SymbolString to send. */ /** the master data @a SymbolString to send. */
SymbolString& m_master; SymbolString& m_master;
/** the slave data @a SymbolString received. */
SymbolString& m_slave;
/** the number of times a send is repeated due to lost arbitration. */ /** the number of times a send is repeated due to lost arbitration. */
unsigned int m_busLostRetries; unsigned int m_busLostRetries;
/** whether to automatically delete this @a BusRequest when finished. */ /** whether to automatically delete this @a BusRequest when finished. */
bool m_deleteOnFinish; const bool m_deleteOnFinish;
}; };
@@ -119,8 +117,8 @@ public:
* @param slave the slave data @a SymbolString received. * @param slave the slave data @a SymbolString received.
* @param message the associated @a Message. * @param message the associated @a Message.
*/ */
PollRequest(SymbolString& slave, Message* message) PollRequest(Message* message)
: BusRequest(m_master, slave, true), m_message(message) {} : BusRequest(m_master, true), m_message(message) {}
/** /**
* @brief Destructor. * @brief Destructor.
@@ -135,7 +133,7 @@ public:
result_t prepare(unsigned char masterAddress); result_t prepare(unsigned char masterAddress);
// @copydoc // @copydoc
virtual void notify(result_t result); virtual bool notify(result_t result, SymbolString& slave);
private: private:
@@ -159,12 +157,13 @@ public:
/** /**
* @brief Constructor. * @brief Constructor.
* @param slave the slave data @a SymbolString received. * @param slave the slave data @a SymbolString received.
* @param message the associated @a Message. * @param message the primary query @a Message.
* @param messages the optional secondary query @a Message instances (to be queried only when the primary was successful).
* @param scanResults the map in which to store the formatted scan result by slave address. * @param scanResults the map in which to store the formatted scan result by slave address.
*/ */
ScanRequest(SymbolString& slave, Message* message, ScanRequest(Message* message, deque<Message*> messages,
map<unsigned char, string>* scanResults) map<unsigned char, string>* scanResults)
: BusRequest(m_master, slave, true), m_message(message), : BusRequest(m_master, true), m_message(message), m_messages(messages),
m_scanResults(scanResults) {} m_scanResults(scanResults) {}
/** /**
@@ -181,16 +180,19 @@ public:
result_t prepare(unsigned char masterAddress, unsigned char dstAddress); result_t prepare(unsigned char masterAddress, unsigned char dstAddress);
// @copydoc // @copydoc
virtual void notify(result_t result); virtual bool notify(result_t result, SymbolString& slave);
private: private:
/** the master data @a SymbolString. */ /** the master data @a SymbolString. */
SymbolString m_master; SymbolString m_master;
/** the associated @a Message. */ /** the currently queried @a Message. */
Message* m_message; Message* m_message;
/** the remaining secondary @a Message instances. */
deque<Message*> m_messages;
/** the map in which to store the formatted scan result by slave address. */ /** the map in which to store the formatted scan result by slave address. */
map<unsigned char, string>* m_scanResults; map<unsigned char, string>* m_scanResults;
@@ -207,8 +209,8 @@ public:
/** /**
* @brief Constructor. * @brief Constructor.
* @param master the master data @a SymbolString to send. * @param master reference to the master data @a SymbolString to send.
* @param slave the slave data @a SymbolString received. * @param slave reference to @a SymbolString for filling in the received slave data.
*/ */
ActiveBusRequest(SymbolString& master, SymbolString& slave); ActiveBusRequest(SymbolString& master, SymbolString& slave);
@@ -225,7 +227,7 @@ public:
bool wait(int timeout); bool wait(int timeout);
// @copydoc // @copydoc
virtual void notify(result_t result); virtual bool notify(result_t result, SymbolString& slave);
private: private:
@@ -235,6 +237,9 @@ private:
/** the result of handling the request. */ /** the result of handling the request. */
result_t m_result; result_t m_result;
/** reference to @a SymbolString for filling in the received slave data. */
SymbolString& m_slave;
/** a mutex for wait/notify. */ /** a mutex for wait/notify. */
pthread_mutex_t m_mutex; pthread_mutex_t m_mutex;
+14 -13
View File
@@ -32,11 +32,11 @@ static const dataType_t stringDataType = {
"STR",16*8,bt_str, ADJ, ' ', 1, 16, 0, 0 // >= 1 byte character string filled up with space "STR",16*8,bt_str, ADJ, ' ', 1, 16, 0, 0 // >= 1 byte character string filled up with space
}; };
static const dataType_t bcdDataType = { static const dataType_t pinDataType = {
"BCD", 8, bt_num, BCD|LST, 0xff, 0, 0x99, 1, 0 // unsigned decimal in BCD, 0 - 99 "PIN", 16, bt_num, FIX|BCD|REV, 0xffff, 0, 0x9999, 1, 0 // unsigned decimal in BCD, 0000 - 9999 (fixed length)
}; };
static const dataType_t ucharDataType = { static const dataType_t uchDataType = {
"UCH", 8, bt_num, LST, 0xff, 0, 0xfe, 1, 0 // unsigned integer, 0 - 254 "UCH", 8, bt_num, LST, 0xff, 0, 0xfe, 1, 0 // unsigned integer, 0 - 254
}; };
@@ -56,8 +56,9 @@ static const dataType_t dataTypes[] = {
{"TTM", 8, bt_tim, 0, 0x90, 5, 5, 0, 0}, // truncated time (only multiple of 10 minutes), 00:00 - 24:00 (minutes div 10 + hour * 6 as integer) {"TTM", 8, bt_tim, 0, 0x90, 5, 5, 0, 0}, // truncated time (only multiple of 10 minutes), 00:00 - 24:00 (minutes div 10 + hour * 6 as integer)
{"BDY", 8, bt_num, DAY|LST, 0x07, 0, 6, 1, 0}, // weekday, "Mon" - "Sun" (0x00 - 0x06) [ebus type] {"BDY", 8, bt_num, DAY|LST, 0x07, 0, 6, 1, 0}, // weekday, "Mon" - "Sun" (0x00 - 0x06) [ebus type]
{"HDY", 8, bt_num, DAY|LST, 0x00, 1, 7, 1, 0}, // weekday, "Mon" - "Sun" (0x01 - 0x07) [Vaillant type] {"HDY", 8, bt_num, DAY|LST, 0x00, 1, 7, 1, 0}, // weekday, "Mon" - "Sun" (0x01 - 0x07) [Vaillant type]
bcdDataType, {"BCD", 8, bt_num, BCD|LST, 0xff, 0, 0x99, 1, 0}, // unsigned decimal in BCD, 0 - 99
ucharDataType, pinDataType,
uchDataType,
{"SCH", 8, bt_num, SIG, 0x80, 0x81, 0x7f, 1, 0}, // signed integer, -127 - +127 {"SCH", 8, bt_num, SIG, 0x80, 0x81, 0x7f, 1, 0}, // signed integer, -127 - +127
{"D1B", 8, bt_num, SIG, 0x80, 0x81, 0x7f, 1, 0}, // signed integer, -127 - +127 {"D1B", 8, bt_num, SIG, 0x80, 0x81, 0x7f, 1, 0}, // signed integer, -127 - +127
{"D1C", 8, bt_num, 0, 0xff, 0x00, 0xc8, 2, 1}, // unsigned number (fraction 1/2), 0 - 100 (0x00 - 0xc8, replacement 0xff) {"D1C", 8, bt_num, 0, 0xff, 0x00, 0xc8, 2, 1}, // unsigned number (fraction 1/2), 0 - 100 (0x00 - 0xc8, replacement 0xff)
@@ -861,9 +862,11 @@ result_t NumberDataField::readSymbols(SymbolString& input,
else else
signedValue = (int) value; signedValue = (int) value;
if (m_divisor <= 1) if (m_divisor <= 1) {
output << static_cast<int>(signedValue); if ((m_dataType.flags & (FIX|BCD)) == (FIX|BCD))
else output << setw(m_length * 2) << setfill('0');
output << static_cast<int>(signedValue) << setw(0);
} else
output << setprecision((m_bitCount % 8) == 0 ? m_dataType.precisionOrFirstBit : 0) output << setprecision((m_bitCount % 8) == 0 ? m_dataType.precisionOrFirstBit : 0)
<< fixed << static_cast<float>(signedValue / (float) m_divisor); << fixed << static_cast<float>(signedValue / (float) m_divisor);
@@ -1048,12 +1051,10 @@ DataFieldSet* DataFieldSet::createIdentFields()
manufacturers[0xb5] = "Joh. Vaillant GmbH & Co."; manufacturers[0xb5] = "Joh. Vaillant GmbH & Co.";
manufacturers[0xc0] = "Toby AG"; manufacturers[0xc0] = "Toby AG";
manufacturers[0xc5] = "Max Weishaupt GmbH"; manufacturers[0xc5] = "Max Weishaupt GmbH";
fields.push_back(new ValueListDataField("manufacturer", "", "", ucharDataType, pt_slaveData, 1, 8, manufacturers)); fields.push_back(new ValueListDataField("manufacturer", "", "", uchDataType, pt_slaveData, 1, 8, manufacturers));
fields.push_back(new StringDataField("id", "", "", stringDataType, pt_slaveData, 5)); fields.push_back(new StringDataField("id", "", "", stringDataType, pt_slaveData, 5));
fields.push_back(new NumberDataField("swv", "", "", bcdDataType, pt_slaveData, 1, 8, 0)); fields.push_back(new NumberDataField("software", "", "", pinDataType, pt_slaveData, 2, 16, 0));
fields.push_back(new NumberDataField("swr", "", "", bcdDataType, pt_slaveData, 1, 8, 0)); fields.push_back(new NumberDataField("hardware", "", "", pinDataType, pt_slaveData, 2, 16, 0));
fields.push_back(new NumberDataField("hwv", "", "", bcdDataType, pt_slaveData, 1, 8, 0));
fields.push_back(new NumberDataField("hwr", "", "", bcdDataType, pt_slaveData, 1, 8, 0));
return new DataFieldSet("ident", "", fields); return new DataFieldSet("ident", "", fields);
} }
+1
View File
@@ -68,6 +68,7 @@ const unsigned int SIG = 0x08; // signed value
const unsigned int LST = 0x10; // value list is possible (without applied divisor) const unsigned int LST = 0x10; // value list is possible (without applied divisor)
const unsigned int DAY = 0x20; // forced value list defaulting to week days const unsigned int DAY = 0x20; // forced value list defaulting to week days
const unsigned int IGN = 0x40; // ignore value during read and write const unsigned int IGN = 0x40; // ignore value during read and write
const unsigned int FIX = 0x80; // fixed width formatting
/** the structure for defining field types with their properties. */ /** the structure for defining field types with their properties. */
typedef struct { typedef struct {
+40 -12
View File
@@ -71,21 +71,20 @@ Message::Message(const bool isSet, const bool isPassive,
* @param pos the position in defaults. * @param pos the position in defaults.
* @return the default if available and value is empty, or the value. * @return the default if available and value is empty, or the value.
*/ */
string getDefault(string value, vector<string>* defaults, size_t pos) string getDefault(const string value, vector<string>* defaults, size_t pos)
{ {
if (value.length() > 0 || defaults == NULL || pos > defaults->size()) { if (value.length() > 0 || defaults == NULL || pos > defaults->size()) {
return value; return value;
} }
value = defaults->at(pos); return defaults->at(pos);
return value;
} }
result_t Message::create(vector<string>::iterator& it, const vector<string>::iterator end, result_t Message::create(vector<string>::iterator& it, const vector<string>::iterator end,
vector< vector<string> >* defaultsRows, vector< vector<string> >* defaultsRows,
DataFieldTemplates* templates, Message*& returnValue) DataFieldTemplates* templates, Message*& returnValue)
{ {
// [type],[class],name,[comment],[QQ],ZZ,id,fields... // [type],[class],name,[comment],[QQ],[ZZ],id,fields...
result_t result; result_t result;
bool isSet = false, isPassive = false; bool isSet = false, isPassive = false;
string defaultName; string defaultName;
@@ -148,24 +147,28 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
return RESULT_ERR_EOF; return RESULT_ERR_EOF;
unsigned char srcAddress; unsigned char srcAddress;
if (*str == 0) if (*str == 0)
srcAddress = SYN; // no specific source defined srcAddress = SYN; // no specific source
else { else {
srcAddress = parseInt(str, 16, 0, 0xff, result); srcAddress = parseInt(str, 16, 0, 0xff, result);
if (result != RESULT_OK) if (result != RESULT_OK)
return result; return result;
if (isMaster(srcAddress) == false) if (isMaster(srcAddress) == false)
return RESULT_ERR_INVALID_ARG; return RESULT_ERR_INVALID_ADDR;
} }
str = getDefault(*it++, defaults, defaultPos++).c_str(); str = getDefault(*it++, defaults, defaultPos++).c_str();
if (it == end) if (it == end)
return RESULT_ERR_EOF; return RESULT_ERR_EOF;
unsigned char dstAddress;
unsigned char dstAddress = parseInt(str, 16, 0, 0xff, result); if (*str == 0)
dstAddress = SYN; // no specific destination
else {
dstAddress = parseInt(str, 16, 0, 0xff, result);
if (result != RESULT_OK) if (result != RESULT_OK)
return result; return result;
if (isValidAddress(dstAddress) == false) if (isValidAddress(dstAddress) == false)
return RESULT_ERR_INVALID_ARG; return RESULT_ERR_INVALID_ADDR;
}
vector<unsigned char> id; vector<unsigned char> id;
for (int pos=0, useDefaults=1; pos<2; pos++) { // message id (PBSB, optional master data) for (int pos=0, useDefaults=1; pos<2; pos++) { // message id (PBSB, optional master data)
@@ -229,7 +232,7 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
} }
} }
DataField* data = NULL; DataField* data = NULL;
result = DataField::create(it, realEnd, templates, data, isSet, dstAddress); result = DataField::create(it, realEnd, templates, data, isSet, dstAddress==SYN ? ESC : dstAddress);
if (result != RESULT_OK) { if (result != RESULT_OK) {
return result; return result;
} }
@@ -246,9 +249,11 @@ result_t Message::prepareMaster(const unsigned char srcAddress, SymbolString& ma
result_t result = master.push_back(srcAddress, false, false); result_t result = master.push_back(srcAddress, false, false);
if (result != RESULT_OK) if (result != RESULT_OK)
return result; return result;
if (dstAddress == SYN) if (dstAddress == SYN) {
if (m_dstAddress == SYN)
return RESULT_ERR_INVALID_ADDR;
result = master.push_back(m_dstAddress, false, false); result = master.push_back(m_dstAddress, false, false);
else } else
result = master.push_back(dstAddress, false, false); result = master.push_back(dstAddress, false, false);
if (result != RESULT_OK) if (result != RESULT_OK)
return result; return result;
@@ -413,6 +418,29 @@ Message* MessageMap::find(const string& clazz, const string& name, const bool is
return NULL; return NULL;
} }
deque<Message*> MessageMap::findAll(const string& clazz, const string& name, const short pb)
{
deque<Message*> ret;
bool checkClass = clazz.length() > 0;
bool checkName = name.length() > 0;
bool checkPb = pb >= 0;
for (map<string, Message*>::iterator it = m_messagesByName.begin(); it != m_messagesByName.end(); it++) {
if (it->first[0] != '-') // avoid duplicates: instances stored multiple times have a key starting with "-"
continue;
Message* message = it->second;
if (checkClass == true && message->getClass() != clazz)
continue;
if (checkName == true && message->getName() != name)
continue;
if (checkPb == true && message->getId()[0] != pb)
continue;
ret.push_back(message);
}
return ret;
}
Message* MessageMap::find(SymbolString& master) Message* MessageMap::find(SymbolString& master)
{ {
if (master.size() < 5) if (master.size() < 5)
+12 -2
View File
@@ -25,6 +25,7 @@
#include "symbol.h" #include "symbol.h"
#include <string> #include <string>
#include <vector> #include <vector>
#include <deque>
#include <map> #include <map>
using namespace std; using namespace std;
@@ -48,7 +49,7 @@ public:
* false if message can be initiated by any participant. * false if message can be initiated by any participant.
* @param comment the comment. * @param comment the comment.
* @param srcAddress the source address, or @a SYN for any (only relevant if passive). * @param srcAddress the source address, or @a SYN for any (only relevant if passive).
* @param dstAddress the destination address. * @param dstAddress the destination address, or @a SYN for any (set later).
* @param id the primary, secondary, and optional further ID bytes. * @param id the primary, secondary, and optional further ID bytes.
* @param data the @a DataField for encoding/decoding the message. * @param data the @a DataField for encoding/decoding the message.
* @param pollPriority the priority for polling, or 0 for no polling at all. * @param pollPriority the priority for polling, or 0 for no polling at all.
@@ -120,7 +121,7 @@ public:
unsigned char getSrcAddress() const { return m_srcAddress; } unsigned char getSrcAddress() const { return m_srcAddress; }
/** /**
* @brief Get the destination address. * @brief Get the destination address.
* @return the destination address. * @return the destination address, or @a SYN for any.
*/ */
unsigned char getDstAddress() const { return m_dstAddress; } unsigned char getDstAddress() const { return m_dstAddress; }
/** /**
@@ -280,6 +281,15 @@ public:
* Note: the caller may not free the returned instance. * Note: the caller may not free the returned instance.
*/ */
Message* find(const string& clazz, const string& name, const bool isSet, const bool isPassive=false); Message* find(const string& clazz, const string& name, const bool isSet, const bool isPassive=false);
/**
* @brief Find all active get @a Message instances for the specified class and name.
* @param class the device class, or empty for any.
* @param name the message name, or empty for any.
* @param pb the primary ID byte, or -1 for any.
* @return the found @a Message instances.
* Note: the caller may not free the returned instances.
*/
deque<Message*> findAll(const string& clazz, const string& name, const short pb);
/** /**
* @brief Find the @a Message instance for the specified master data. * @brief Find the @a Message instance for the specified master data.
* @param master the master @a SymbolString for identifying the @a Message. * @param master the master @a SymbolString for identifying the @a Message.
+4 -3
View File
@@ -25,9 +25,9 @@ using namespace std;
const char* getResultCode(result_t resultCode) { const char* getResultCode(result_t resultCode) {
switch (resultCode) { switch (resultCode) {
case RESULT_OK: return "success"; case RESULT_OK: return "success";
case RESULT_IN_ESC: return "success: escape sequence received"; case RESULT_IN_ESC: return "escape sequence received";
case RESULT_SYN: return "success: SYN received"; case RESULT_SYN: return "SYN received";
case RESULT_EMPTY: return "success: empty"; case RESULT_EMPTY: return "empty";
case RESULT_ERR_GENERIC_IO: return "ERR: generic I/O error"; case RESULT_ERR_GENERIC_IO: return "ERR: generic I/O error";
case RESULT_ERR_DEVICE: return "ERR: generic device error"; case RESULT_ERR_DEVICE: return "ERR: generic device error";
case RESULT_ERR_SEND: return "ERR: send error"; case RESULT_ERR_SEND: return "ERR: send error";
@@ -37,6 +37,7 @@ const char* getResultCode(result_t resultCode) {
case RESULT_ERR_EOF: return "ERR: end of input reached"; case RESULT_ERR_EOF: return "ERR: end of input reached";
case RESULT_ERR_INVALID_ARG: return "ERR: invalid argument"; case RESULT_ERR_INVALID_ARG: return "ERR: invalid argument";
case RESULT_ERR_INVALID_NUM: return "ERR: invalid numeric argument"; case RESULT_ERR_INVALID_NUM: return "ERR: invalid numeric argument";
case RESULT_ERR_INVALID_ADDR: return "ERR: invalid address";
case RESULT_ERR_INVALID_POS: return "ERR: invalid position"; case RESULT_ERR_INVALID_POS: return "ERR: invalid position";
case RESULT_ERR_OUT_OF_RANGE: return "ERR: argument value out of valid range"; case RESULT_ERR_OUT_OF_RANGE: return "ERR: argument value out of valid range";
case RESULT_ERR_INVALID_PART: return "ERR: invalid part type value"; case RESULT_ERR_INVALID_PART: return "ERR: invalid part type value";
+11 -10
View File
@@ -36,17 +36,18 @@ static const int RESULT_ERR_NOTFOUND = -6; // file/element not found or not
static const int RESULT_ERR_EOF = -7; // end of input reached static const int RESULT_ERR_EOF = -7; // end of input reached
static const int RESULT_ERR_INVALID_ARG = -8; // invalid argument static const int RESULT_ERR_INVALID_ARG = -8; // invalid argument
static const int RESULT_ERR_INVALID_NUM = -9; // invalid numeric argument static const int RESULT_ERR_INVALID_NUM = -9; // invalid numeric argument
static const int RESULT_ERR_INVALID_POS = -10; // invalid position static const int RESULT_ERR_INVALID_ADDR = -10; // invalid address
static const int RESULT_ERR_OUT_OF_RANGE = -11; // argument value out of valid range static const int RESULT_ERR_INVALID_POS = -11; // invalid position
static const int RESULT_ERR_INVALID_PART = -12; // invalid part type value static const int RESULT_ERR_OUT_OF_RANGE = -12; // argument value out of valid range
static const int RESULT_ERR_MISSING_TYPE = -13; // missing data type static const int RESULT_ERR_INVALID_PART = -13; // invalid part type value
static const int RESULT_ERR_INVALID_LIST = -14; // invalid value list static const int RESULT_ERR_MISSING_TYPE = -14; // missing data type
static const int RESULT_ERR_DUPLICATE = -15; // duplicate entry static const int RESULT_ERR_INVALID_LIST = -15; // invalid value list
static const int RESULT_ERR_DUPLICATE = -16; // duplicate entry
static const int RESULT_ERR_BUS_LOST = -16; // arbitration lost static const int RESULT_ERR_BUS_LOST = -17; // arbitration lost
static const int RESULT_ERR_CRC = -17; // CRC error static const int RESULT_ERR_CRC = -18; // CRC error
static const int RESULT_ERR_ACK = -18; // ACK error static const int RESULT_ERR_ACK = -19; // ACK error
static const int RESULT_ERR_NAK = -19; // NAK received static const int RESULT_ERR_NAK = -20; // NAK received
/** type for result code. */ /** type for result code. */
typedef int result_t; typedef int result_t;
+6 -6
View File
@@ -250,17 +250,17 @@ int main()
SymbolString writeMstr(mstr.getDataStr().substr(0, 10), false); SymbolString writeMstr(mstr.getDataStr().substr(0, 10), false);
SymbolString writeSstr(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);
} }
if (failedRead == true) if (failedRead == true)
if (result == RESULT_OK) if (result >= RESULT_OK)
cout << " failed read " << fields->getName() << " >" cout << " failed read " << fields->getName() << " >"
<< check[2] << "< error: unexpectedly succeeded" << endl; << check[2] << "< error: unexpectedly succeeded" << endl;
else else
cout << " failed read " << fields->getName() << " >" cout << " failed read " << fields->getName() << " >"
<< check[2] << "< OK" << endl; << check[2] << "< OK" << endl;
else if (result != RESULT_OK) { else if (result < RESULT_OK) {
cout << " read " << fields->getName() << " >" << check[2] cout << " read " << fields->getName() << " >" << check[2]
<< "< error: " << getResultCode(result) << endl; << "< error: " << getResultCode(result) << endl;
} }
@@ -272,17 +272,17 @@ int main()
if (verbose == false) { if (verbose == false) {
istringstream input(expectStr); istringstream input(expectStr);
result = fields->write(input, pt_masterData, writeMstr, 0); result = fields->write(input, pt_masterData, writeMstr, 0);
if (result == RESULT_OK) if (result >= RESULT_OK)
result = fields->write(input, pt_slaveData, writeSstr, 0); result = fields->write(input, pt_slaveData, writeSstr, 0);
if (failedWrite == true) { if (failedWrite == true) {
if (result == RESULT_OK) if (result >= RESULT_OK)
cout << " failed write " << fields->getName() << " >" cout << " failed write " << fields->getName() << " >"
<< expectStr << "< error: unexpectedly succeeded" << endl; << expectStr << "< error: unexpectedly succeeded" << endl;
else else
cout << " failed write " << fields->getName() << " >" cout << " failed write " << fields->getName() << " >"
<< expectStr << "< OK" << endl; << expectStr << "< OK" << endl;
} }
else if (result != RESULT_OK) { else if (result < RESULT_OK) {
cout << " write " << fields->getName() << " >" << expectStr cout << " write " << fields->getName() << " >" << expectStr
<< "< error: " << getResultCode(result) << endl; << "< error: " << getResultCode(result) << endl;
} }