Merge pull request #22 from john30/master
full feature set for baseloop, added verbose read and max age arguments
This commit is contained in:
+124
-95
@@ -20,6 +20,7 @@
|
||||
#include "baseloop.h"
|
||||
#include "logger.h"
|
||||
#include "appl.h"
|
||||
#include "data.h"
|
||||
#include <dirent.h>
|
||||
#include <iomanip>
|
||||
|
||||
@@ -30,26 +31,10 @@ extern Appl& A;
|
||||
|
||||
BaseLoop::BaseLoop()
|
||||
{
|
||||
// create commands DB
|
||||
// load messages and templates
|
||||
m_templates = new DataFieldTemplates();
|
||||
m_messages = new MessageMap();
|
||||
|
||||
string confdir = A.getOptVal<const char*>("ebusconfdir");
|
||||
L.log(bas, trace, "ebus configuration dir: %s", confdir.c_str());
|
||||
result_t result = m_templates->readFromFile(confdir+"/_types.csv");
|
||||
if (result == RESULT_OK)
|
||||
L.log(bas, trace, "read templates");
|
||||
else
|
||||
L.log(bas, error, "error reading templates: %s", getResultCode(result));
|
||||
result = readConfigFiles(confdir, ".csv");
|
||||
if (result == RESULT_OK)
|
||||
L.log(bas, trace, "read config files");
|
||||
else
|
||||
L.log(bas, error, "error reading config files: %s", getResultCode(result));
|
||||
|
||||
L.log(bas, event, "message DB: %d ", m_messages->size());
|
||||
L.log(bas, event, "updates DB: %d ", m_messages->size(true));
|
||||
L.log(bas, event, "polling DB: %d ", m_messages->sizePoll());
|
||||
loadMessages();
|
||||
|
||||
m_ownAddress = A.getOptVal<int>("address") & 0xff;
|
||||
const bool answer = A.getOptVal<bool>("answer");
|
||||
@@ -113,6 +98,31 @@ BaseLoop::~BaseLoop()
|
||||
delete m_templates;
|
||||
}
|
||||
|
||||
result_t BaseLoop::loadMessages()
|
||||
{
|
||||
string confdir = A.getOptVal<const char*>("ebusconfdir");
|
||||
L.log(bas, trace, "ebus configuration dir: %s", confdir.c_str());
|
||||
m_messages->clear();
|
||||
m_templates->clear();
|
||||
result_t result = m_templates->readFromFile(confdir+"/_types.csv");
|
||||
if (result == RESULT_OK)
|
||||
L.log(bas, trace, "read templates");
|
||||
else
|
||||
L.log(bas, error, "error reading templates: %s", getResultCode(result));
|
||||
|
||||
result = readConfigFiles(confdir, ".csv");
|
||||
if (result == RESULT_OK) {
|
||||
L.log(bas, trace, "read config files");
|
||||
|
||||
L.log(bas, event, "message DB: %d ", m_messages->size());
|
||||
L.log(bas, event, "updates DB: %d ", m_messages->size(true));
|
||||
L.log(bas, event, "polling DB: %d ", m_messages->sizePoll());
|
||||
} else
|
||||
L.log(bas, error, "error reading config files: %s", getResultCode(result));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
result_t BaseLoop::readConfigFiles(const string path, const string extension)
|
||||
{
|
||||
DIR* dir = opendir(path.c_str());
|
||||
@@ -132,7 +142,7 @@ result_t BaseLoop::readConfigFiles(const string path, const string extension)
|
||||
if (result != RESULT_OK)
|
||||
return result;
|
||||
}
|
||||
} else if (d->d_type == DT_REG) {
|
||||
} else if (d->d_type == DT_REG || d->d_type == DT_LNK) {
|
||||
string fn = d->d_name;
|
||||
|
||||
if (fn.find(extension, (fn.length() - extension.length())) != string::npos
|
||||
@@ -208,7 +218,6 @@ string BaseLoop::decodeMessage(const string& data)
|
||||
return "command missing";
|
||||
|
||||
size_t argPos = 1;
|
||||
bool force = false;
|
||||
|
||||
switch (getCase(args[0])) {
|
||||
case ct_invalid:
|
||||
@@ -216,24 +225,51 @@ string BaseLoop::decodeMessage(const string& data)
|
||||
break;
|
||||
|
||||
case ct_read: {
|
||||
if (args.size() > argPos && args[argPos] == "-f") {
|
||||
force = true;
|
||||
unsigned int maxAge = 5*60;
|
||||
bool verbose = false;
|
||||
while (args.size() > argPos && args[argPos][0] == '-') {
|
||||
if (args[argPos]== "-f") {
|
||||
maxAge = 0;
|
||||
} else if (args[argPos] == "-v") {
|
||||
verbose = true;
|
||||
} else if (args[argPos] == "-m") {
|
||||
argPos++;
|
||||
if (args.size() > argPos) {
|
||||
result_t result;
|
||||
maxAge = parseInt(args[argPos].c_str(), 10, 0, 24*60*60, result);
|
||||
if (result != RESULT_OK) {
|
||||
argPos = args.size(); // print usage
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
argPos = args.size(); // print usage
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
argPos = args.size(); // print usage
|
||||
break;
|
||||
}
|
||||
argPos++;
|
||||
}
|
||||
if (args.size() < argPos + 1 || args.size() > argPos + 3) {
|
||||
result << "usage: 'read [-f] [class] cmd' or 'read [-f] class cmd sub'";
|
||||
result << "usage: 'read [-v] [-f] [-m seconds] [class] cmd' or 'read [-v] [-f] [-m seconds] class cmd sub'";
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
time_t now;
|
||||
time(&now);
|
||||
|
||||
Message* updateMessage = NULL;
|
||||
if (force == false) {
|
||||
if (maxAge > 0 && verbose == false) {
|
||||
if (args.size() == argPos + 1)
|
||||
updateMessage = m_messages->find("", args[argPos], false, true);
|
||||
else
|
||||
updateMessage = m_messages->find(args[argPos], args[argPos + 1], false, true);
|
||||
|
||||
if (updateMessage != NULL) {
|
||||
token = updateMessage->getLastValue();
|
||||
if (updateMessage != NULL && updateMessage->getLastUpdateTime() + maxAge > now) {
|
||||
token = updateMessage->getLastValue(); // TODO switch from last value to last master/slave to support verbose cached/polled values as well
|
||||
if (token.empty() == false) {
|
||||
result << token;
|
||||
break;
|
||||
@@ -248,8 +284,8 @@ string BaseLoop::decodeMessage(const string& data)
|
||||
message = m_messages->find(args[argPos], args[argPos + 1], false);
|
||||
|
||||
if (message != NULL) {
|
||||
|
||||
if (m_pollActive == true && message->getPollPriority() > 0) {
|
||||
if (maxAge > 0 && m_pollActive == true && message->getPollPriority() > 0
|
||||
&& message->getLastUpdateTime() + maxAge > now) {
|
||||
// get polldata
|
||||
token = message->getLastValue();
|
||||
if (token.empty() == false) {
|
||||
@@ -266,15 +302,17 @@ string BaseLoop::decodeMessage(const string& data)
|
||||
result << getResultCode(ret);
|
||||
break;
|
||||
}
|
||||
L.log(bas, event, "read cmd: %s", master.getDataStr().c_str());
|
||||
L.log(bas, trace, "read cmd: %s", master.getDataStr().c_str());
|
||||
|
||||
// send message
|
||||
SymbolString slave;
|
||||
ret = m_busHandler->sendAndWait(master, slave);
|
||||
|
||||
if (ret == RESULT_OK) {
|
||||
// TODO reduce to requested variable only
|
||||
ret = message->decode(pt_slaveData, slave, result); // decode data
|
||||
if (args.size() == argPos + 3)
|
||||
ret = message->decode(pt_slaveData, slave, result, false, verbose, args[argPos + 2].c_str());
|
||||
else
|
||||
ret = message->decode(pt_slaveData, slave, result, false, verbose); // decode data
|
||||
}
|
||||
if (ret != RESULT_OK) {
|
||||
L.log(bas, error, "read: %s", getResultCode(ret));
|
||||
@@ -289,8 +327,49 @@ string BaseLoop::decodeMessage(const string& data)
|
||||
break;
|
||||
}
|
||||
case ct_write: {
|
||||
if (args.size() > argPos && args[argPos] == "-h") {
|
||||
argPos++;
|
||||
|
||||
if (args.size() < argPos + 1) {
|
||||
result << "usage: 'write -h ZZPBSBNNDx'";
|
||||
break;
|
||||
}
|
||||
|
||||
ostringstream msg;
|
||||
msg << hex << setw(2) << setfill('0') << static_cast<unsigned>(m_ownAddress) << setw(0);
|
||||
while (argPos < args.size()) {
|
||||
if ((args[argPos].length() % 2) != 0) {
|
||||
result << "invalid hex string";
|
||||
msg.str("");
|
||||
break;
|
||||
}
|
||||
msg << args[argPos++];
|
||||
}
|
||||
if (msg.str().length() == 0)
|
||||
break;
|
||||
|
||||
SymbolString master(msg.str());
|
||||
L.log(bas, event, "write hex cmd: %s", master.getDataStr().c_str());
|
||||
|
||||
// send message
|
||||
SymbolString slave;
|
||||
result_t ret = m_busHandler->sendAndWait(master, slave);
|
||||
|
||||
if (ret == RESULT_OK) {
|
||||
if (master[1] == BROADCAST || isMaster(master[1]))
|
||||
result << "done";
|
||||
else
|
||||
result << slave.getDataStr();
|
||||
}
|
||||
if (ret != RESULT_OK) {
|
||||
L.log(bas, error, "write hex: %s", getResultCode(ret));
|
||||
result << getResultCode(ret);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (args.size() != argPos + 3) {
|
||||
result << "usage: 'write class cmd value[;value]*'";
|
||||
result << "usage: 'write class cmd value[;value]*' or 'write -h ZZPBSBNNDx'";
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -305,7 +384,7 @@ string BaseLoop::decodeMessage(const string& data)
|
||||
result << getResultCode(ret);
|
||||
break;
|
||||
}
|
||||
L.log(bas, event, "write cmd: %s", master.getDataStr().c_str());
|
||||
L.log(bas, trace, "write cmd: %s", master.getDataStr().c_str());
|
||||
|
||||
// send message
|
||||
SymbolString slave;
|
||||
@@ -330,44 +409,6 @@ string BaseLoop::decodeMessage(const string& data)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ct_hex: {
|
||||
if (args.size() < argPos + 1) {
|
||||
result << "usage: 'hex value' (value: ZZPBSBNNDx)";
|
||||
break;
|
||||
}
|
||||
|
||||
ostringstream msg;
|
||||
msg << hex << setw(2) << setfill('0') << static_cast<unsigned>(m_ownAddress) << setw(0);
|
||||
while (argPos < args.size()) {
|
||||
if ((args[argPos].length() % 2) != 0) {
|
||||
result << "invalid hex string";
|
||||
msg.str("");
|
||||
break;
|
||||
}
|
||||
msg << args[argPos++];
|
||||
}
|
||||
if (msg.str().length() == 0)
|
||||
break;
|
||||
|
||||
SymbolString master(msg.str());
|
||||
L.log(bas, event, "hex cmd: %s", master.getDataStr().c_str());
|
||||
|
||||
// send message
|
||||
SymbolString slave;
|
||||
result_t ret = m_busHandler->sendAndWait(master, slave);
|
||||
|
||||
if (ret == RESULT_OK) {
|
||||
if (master[1] == BROADCAST || isMaster(master[1]))
|
||||
result << "done";
|
||||
else
|
||||
result << slave.getDataStr();
|
||||
}
|
||||
if (ret != RESULT_OK) {
|
||||
L.log(bas, error, "hex: %s", getResultCode(ret));
|
||||
result << getResultCode(ret);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ct_scan: {
|
||||
if (args.size() == argPos) {
|
||||
result_t ret = m_busHandler->startScan();
|
||||
@@ -408,7 +449,6 @@ string BaseLoop::decodeMessage(const string& data)
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: check for possible areas and level
|
||||
if (strcasecmp(args[argPos].c_str(), "AREAS") == 0) {
|
||||
L.getSink(0)->setAreas(calcAreas(args[argPos + 1]));
|
||||
result << "done";
|
||||
@@ -447,36 +487,27 @@ string BaseLoop::decodeMessage(const string& data)
|
||||
result << (enabled ? "dump enabled" : "dump disabled");
|
||||
break;
|
||||
}
|
||||
/*case ct_reload:
|
||||
if (cmd.size() != 1) {
|
||||
case ct_reload: {
|
||||
if (args.size() != 1) {
|
||||
result << "usage: 'reload'";
|
||||
break;
|
||||
}
|
||||
|
||||
{
|
||||
// create commands DB
|
||||
Commands* commands = ConfigCommands(A.getOptVal<const char*>("ebusconfdir"), ft_csv).getCommands();
|
||||
L.log(bas, trace, "ebus configuration dir: %s", A.getOptVal<const char*>("ebusconfdir"));
|
||||
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());
|
||||
|
||||
delete m_commands;
|
||||
m_commands = commands;
|
||||
m_busloop->reload(m_commands);
|
||||
|
||||
// create commands DB
|
||||
result_t ret = loadMessages();
|
||||
if (ret == RESULT_OK)
|
||||
result << "done";
|
||||
break;
|
||||
}*/
|
||||
|
||||
else
|
||||
result << getResultCode(ret);
|
||||
break;
|
||||
}
|
||||
case ct_help:
|
||||
result << "commands:" << endl
|
||||
<< " read - read ebus values 'read [-f] [class] cmd [sub]'" << endl
|
||||
<< " write - write ebus values 'write class cmd value[;value]*'" << endl
|
||||
<< " hex - send given hex value 'hex type value' (value: ZZPBSBNNDx)" << endl << endl
|
||||
<< " read - read ebus values 'read [-v] [-f] [-m seconds] [class] cmd' or 'read [-v] [-f] [-m seconds] class cmd sub'" << endl
|
||||
<< " write - write ebus values 'write class cmd value[;value]*' or 'write -h ZZPBSBNNDx'" << endl
|
||||
<< " scan - scan ebus kown addresses 'scan'" << endl
|
||||
<< " - scan ebus all addresses 'scan full'" << endl
|
||||
<< " - show results 'scan result'" << endl << endl
|
||||
<< " - show scan results 'scan result'" << endl << endl
|
||||
<< " log - change log areas 'log areas area,area,..' (areas: bas|net|bus|upd|all)" << endl
|
||||
<< " - change log level 'log level level' (level: error|event|trace|debug)" << endl << endl
|
||||
<< " raw - toggle log raw data 'raw'" << endl
|
||||
@@ -487,8 +518,6 @@ string BaseLoop::decodeMessage(const string& data)
|
||||
<< " help - print this page 'help'";
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return result.str();
|
||||
|
||||
@@ -32,7 +32,6 @@ using namespace std;
|
||||
enum CommandType {
|
||||
ct_read, /*!< read ebus values */
|
||||
ct_write, /*!< write ebus values */
|
||||
ct_hex, /*!< send hex data */
|
||||
ct_scan, /*!< scan ebus */
|
||||
ct_log, /*!< logger settings */
|
||||
ct_raw, /*!< toggle log raw data */
|
||||
@@ -59,10 +58,17 @@ public:
|
||||
*/
|
||||
~BaseLoop();
|
||||
|
||||
/**
|
||||
* @brief Load the message definitions.
|
||||
* @return the result code.
|
||||
*/
|
||||
result_t loadMessages();
|
||||
|
||||
/**
|
||||
* @brief Read the configuration files from the specified path.
|
||||
* @param path the path from which to read the files.
|
||||
* @param extension the filename extension of the files to read.
|
||||
* @return the result code.
|
||||
*/
|
||||
result_t readConfigFiles(const string path, const string extension);
|
||||
|
||||
@@ -119,7 +125,6 @@ private:
|
||||
{
|
||||
if (strcasecmp(item.c_str(), "READ") == 0) return ct_read;
|
||||
if (strcasecmp(item.c_str(), "WRITE") == 0) return ct_write;
|
||||
if (strcasecmp(item.c_str(), "HEX") == 0) return ct_hex;
|
||||
if (strcasecmp(item.c_str(), "SCAN") == 0) return ct_scan;
|
||||
if (strcasecmp(item.c_str(), "LOG") == 0) return ct_log;
|
||||
if (strcasecmp(item.c_str(), "RAW") == 0) return ct_raw;
|
||||
|
||||
+18
-16
@@ -51,8 +51,8 @@ const char* getStateCode(BusState state) {
|
||||
case bs_sendResAck: return "send response ACK";
|
||||
case bs_recvCmd: return "receive command";
|
||||
case bs_recvResAck: return "receive response ACK";
|
||||
// case bs_sendRes: return "send response";
|
||||
// case bs_sendCmdAck: return "send command ACK";
|
||||
case bs_sendCmdAck: return "send command ACK";
|
||||
case bs_sendRes: return "send response";
|
||||
case bs_sendSyn: return "send SYN";
|
||||
default: return "unknown";
|
||||
}
|
||||
@@ -64,7 +64,7 @@ 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 cmd: %s", m_master.getDataStr().c_str());
|
||||
L.log(bus, trace, "poll cmd: %s", m_master.getDataStr().c_str());
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -86,20 +86,26 @@ result_t ScanRequest::prepare(unsigned char ownMasterAddress, unsigned char dstA
|
||||
istringstream input;
|
||||
result_t result = m_message->prepareMaster(ownMasterAddress, m_master, input, UI_FIELD_SEPARATOR, dstAddress);
|
||||
if (result == RESULT_OK)
|
||||
L.log(bus, event, "scan cmd: %s", m_master.getDataStr().c_str());
|
||||
L.log(bus, trace, "scan cmd: %s", m_master.getDataStr().c_str());
|
||||
return result;
|
||||
}
|
||||
|
||||
void ScanRequest::notify(result_t result)
|
||||
{
|
||||
unsigned char dstAddress = m_master[1];
|
||||
ostringstream scanResult;
|
||||
if (result == RESULT_OK) {
|
||||
m_scanResult << hex << setw(2) << setfill('0') << static_cast<unsigned>(m_master[1]) << UI_FIELD_SEPARATOR;
|
||||
result = m_message->decode(pt_slaveData, m_slave, m_scanResult); // decode data
|
||||
scanResult << hex << setw(2) << setfill('0') << static_cast<unsigned>(dstAddress) << UI_FIELD_SEPARATOR;
|
||||
result = m_message->decode(pt_slaveData, m_slave, scanResult); // decode data
|
||||
}
|
||||
if (result != RESULT_OK)
|
||||
L.log(bus, error, "scan %2.2x failed: %s", dstAddress, getResultCode(result));
|
||||
else {
|
||||
string str = scanResult.str();
|
||||
L.log(bus, event, "scan: %s", str.c_str());
|
||||
if (m_scanResults != NULL)
|
||||
(*m_scanResults)[dstAddress] = str;
|
||||
}
|
||||
if (result == RESULT_OK)
|
||||
L.log(bus, event, "scan result: %s", m_scanResult.str().c_str());
|
||||
else
|
||||
L.log(bus, error, "scan %2.2x failed: %s", m_master[1], getResultCode(result));
|
||||
}
|
||||
|
||||
|
||||
@@ -141,7 +147,7 @@ bool ActiveBusRequest::wait(int timeout)
|
||||
void ActiveBusRequest::notify(result_t result)
|
||||
{
|
||||
if (result == RESULT_OK)
|
||||
L.log(bus, trace, "read res: %s", m_slave.getDataStr().c_str());
|
||||
L.log(bus, event, "read res: %s", m_slave.getDataStr().c_str());
|
||||
|
||||
pthread_mutex_lock(&m_mutex);
|
||||
|
||||
@@ -574,10 +580,6 @@ result_t BusHandler::setState(BusState state, result_t result, bool firstRepetit
|
||||
m_seenAddresses[dstAddress] = true;
|
||||
m_request->notify(result);
|
||||
if (m_request->m_deleteOnFinish == true) {
|
||||
if (result == RESULT_OK && typeid(*m_request) == typeid(ScanRequest)) {
|
||||
string res = ((ScanRequest*)m_request)->m_scanResult.str();
|
||||
m_scanResults[dstAddress] = res;
|
||||
}
|
||||
delete m_request;
|
||||
}
|
||||
m_request = NULL;
|
||||
@@ -662,7 +664,7 @@ result_t BusHandler::startScan(bool full)
|
||||
continue;
|
||||
}
|
||||
|
||||
ScanRequest* request = new ScanRequest(m_response, scanMessage);
|
||||
ScanRequest* request = new ScanRequest(m_response, scanMessage, &m_scanResults);
|
||||
result_t result = request->prepare(m_ownMasterAddress, slave);
|
||||
if (result != RESULT_OK) {
|
||||
delete request;
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <pthread.h>
|
||||
#include <typeinfo>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -161,9 +160,12 @@ public:
|
||||
* @brief Constructor.
|
||||
* @param slave the slave data @a SymbolString received.
|
||||
* @param message the associated @a Message.
|
||||
* @param scanResults the map in which to store the formatted scan result by slave address.
|
||||
*/
|
||||
ScanRequest(SymbolString& slave, Message* message)
|
||||
: BusRequest(m_master, slave, true), m_message(message) {}
|
||||
ScanRequest(SymbolString& slave, Message* message,
|
||||
map<unsigned char, string>* scanResults)
|
||||
: BusRequest(m_master, slave, true), m_message(message),
|
||||
m_scanResults(scanResults) {}
|
||||
|
||||
/**
|
||||
* @brief Destructor.
|
||||
@@ -189,8 +191,8 @@ private:
|
||||
/** the associated @a Message. */
|
||||
Message* m_message;
|
||||
|
||||
/** the formatted scan result. */
|
||||
ostringstream m_scanResult;
|
||||
/** the map in which to store the formatted scan result by slave address. */
|
||||
map<unsigned char, string>* m_scanResults;
|
||||
|
||||
};
|
||||
|
||||
|
||||
+14
-14
@@ -373,7 +373,8 @@ void SingleDataField::dump(ostream& output)
|
||||
result_t SingleDataField::read(const PartType partType,
|
||||
SymbolString& data, unsigned char offset,
|
||||
ostringstream& output, bool leadingSeparator,
|
||||
bool verbose, char separator)
|
||||
bool verbose, const char* filterName,
|
||||
char separator)
|
||||
{
|
||||
if (partType != m_partType)
|
||||
return RESULT_OK;
|
||||
@@ -389,11 +390,11 @@ result_t SingleDataField::read(const PartType partType,
|
||||
default:
|
||||
return RESULT_ERR_INVALID_PART;
|
||||
}
|
||||
if (isIgnored() == true) {
|
||||
if (isIgnored() == true || (filterName != NULL && m_name != filterName)) {
|
||||
if (offset + m_length > data.size()) {
|
||||
return RESULT_ERR_INVALID_POS;
|
||||
}
|
||||
return RESULT_OK;
|
||||
return RESULT_EMPTY;
|
||||
}
|
||||
|
||||
if (leadingSeparator == true)
|
||||
@@ -1111,12 +1112,10 @@ void DataFieldSet::dump(ostream& output)
|
||||
result_t DataFieldSet::read(const PartType partType,
|
||||
SymbolString& data, unsigned char offset,
|
||||
ostringstream& output, bool leadingSeparator,
|
||||
bool verbose, char separator)
|
||||
bool verbose, const char* filterName,
|
||||
char separator)
|
||||
{
|
||||
if (verbose)
|
||||
output << m_name << "={ ";
|
||||
|
||||
bool previousFullByteOffset = true;
|
||||
bool previousFullByteOffset = true, found = false;
|
||||
for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) {
|
||||
SingleDataField* field = *it;
|
||||
if (partType != pt_any && field->getPartType() != partType)
|
||||
@@ -1125,24 +1124,25 @@ result_t DataFieldSet::read(const PartType partType,
|
||||
if (previousFullByteOffset == false && field->hasFullByteOffset(false) == false)
|
||||
offset--;
|
||||
|
||||
//cout<<"read "<<field->getName().c_str()<<" in part "<<static_cast<unsigned>(field->getPartType())<<" offset "<<static_cast<unsigned>(offsets[field->getPartType()])<<endl;
|
||||
result_t result = field->read(partType, data, offset, output, leadingSeparator, verbose, separator);
|
||||
result_t result = field->read(partType, data, offset, output, leadingSeparator, verbose, filterName, separator);
|
||||
|
||||
if (result != RESULT_OK)
|
||||
if (result < RESULT_OK)
|
||||
return result;
|
||||
|
||||
offset += field->getLength(partType);
|
||||
previousFullByteOffset = field->hasFullByteOffset(true);
|
||||
leadingSeparator |= field->isIgnored() == false;
|
||||
if (result != RESULT_EMPTY) {
|
||||
found = true;
|
||||
leadingSeparator = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (verbose == true) {
|
||||
if (m_comment.length() > 0)
|
||||
output << " [" << m_comment << "]";
|
||||
output << "}";
|
||||
}
|
||||
|
||||
return RESULT_OK;
|
||||
return found == true ? RESULT_OK : RESULT_EMPTY;
|
||||
}
|
||||
|
||||
result_t DataFieldSet::write(istringstream& input,
|
||||
|
||||
+10
-4
@@ -183,13 +183,17 @@ public:
|
||||
* @param leadingSeparator whether to prepend a separator before the formatted value.
|
||||
* @param verbose whether to prepend the name, append the unit (if present), and append
|
||||
* the comment in square brackets (if present).
|
||||
* @param filterName the optional name of a field to limit the output to.
|
||||
* @param separator the separator character between multiple fields.
|
||||
* @return @a RESULT_OK on success (or if the partType does not match), or an error code.
|
||||
* @return @a RESULT_OK on success (or if the partType does not match),
|
||||
* or @a RESULT_EMPTY if the field was skipped (either ignored or due to @a filterName),
|
||||
* or an error code.
|
||||
*/
|
||||
virtual result_t read(const PartType partType,
|
||||
SymbolString& data, unsigned char offset,
|
||||
ostringstream& output, bool leadingSeparator=false,
|
||||
bool verbose=false, char separator=UI_FIELD_SEPARATOR) = 0;
|
||||
bool verbose=false, const char* filterName=NULL,
|
||||
char separator=UI_FIELD_SEPARATOR) = 0;
|
||||
/**
|
||||
* @brief Writes the value to the master or slave @a SymbolString.
|
||||
* @param input the @a istringstream to parse the formatted value from.
|
||||
@@ -270,7 +274,8 @@ public:
|
||||
virtual result_t read(const PartType partType,
|
||||
SymbolString& data, unsigned char offset,
|
||||
ostringstream& output, bool leadingSeparator=false,
|
||||
bool verbose=false, char separator=UI_FIELD_SEPARATOR);
|
||||
bool verbose=false, const char* filterName=NULL,
|
||||
char separator=UI_FIELD_SEPARATOR);
|
||||
// @copydoc
|
||||
virtual result_t write(istringstream& input,
|
||||
const PartType partType, SymbolString& data,
|
||||
@@ -569,7 +574,8 @@ public:
|
||||
virtual result_t read(const PartType partType,
|
||||
SymbolString& data, unsigned char offset,
|
||||
ostringstream& output, bool leadingSeparator=false,
|
||||
bool verbose=false, char separator=UI_FIELD_SEPARATOR);
|
||||
bool verbose=false, const char* filterName=NULL,
|
||||
char separator=UI_FIELD_SEPARATOR);
|
||||
// @copydoc
|
||||
virtual result_t write(istringstream& input,
|
||||
const PartType partType, SymbolString& data,
|
||||
|
||||
@@ -293,7 +293,9 @@ result_t Message::prepareSlave(SymbolString& slaveData)
|
||||
}
|
||||
|
||||
result_t Message::decode(const PartType partType, SymbolString& data,
|
||||
ostringstream& output, bool leadingSeparator, char separator)
|
||||
ostringstream& output, bool leadingSeparator,
|
||||
bool verbose, const char* filterName,
|
||||
char separator)
|
||||
{
|
||||
unsigned char offset;
|
||||
if (partType == pt_masterData)
|
||||
@@ -301,7 +303,7 @@ result_t Message::decode(const PartType partType, SymbolString& data,
|
||||
else
|
||||
offset = 0;
|
||||
int startPos = output.str().length();
|
||||
result_t result = m_data->read(partType, data, offset, output, leadingSeparator, false, separator);
|
||||
result_t result = m_data->read(partType, data, offset, output, leadingSeparator, verbose, filterName, separator);
|
||||
time(&m_lastUpdateTime);
|
||||
if (result != RESULT_OK) {
|
||||
m_lastValue.clear();
|
||||
|
||||
@@ -165,11 +165,16 @@ public:
|
||||
* @param data the unescaped data @a SymbolString for reading binary data.
|
||||
* @param output the @a ostringstream to append the formatted value to.
|
||||
* @param leadingSeparator whether to prepend a separator before the formatted value.
|
||||
* @param verbose whether to prepend the name, append the unit (if present), and append
|
||||
* the comment in square brackets (if present).
|
||||
* @param filterName the optional name of a field to limit the output to.
|
||||
* @param separator the separator character between multiple fields.
|
||||
* @return @a RESULT_OK on success, or an error code.
|
||||
*/
|
||||
result_t decode(const PartType partType, SymbolString& data,
|
||||
ostringstream& output, bool leadingSeparator=false, char separator=UI_FIELD_SEPARATOR);
|
||||
ostringstream& output, bool leadingSeparator=false,
|
||||
bool verbose=false, const char* filterName=NULL,
|
||||
char separator=UI_FIELD_SEPARATOR);
|
||||
|
||||
/**
|
||||
* @brief Get the last decoded value.
|
||||
|
||||
@@ -27,6 +27,7 @@ const char* getResultCode(result_t resultCode) {
|
||||
case RESULT_OK: return "success";
|
||||
case RESULT_IN_ESC: return "success: escape sequence received";
|
||||
case RESULT_SYN: return "success: SYN received";
|
||||
case RESULT_EMPTY: return "success: empty";
|
||||
case RESULT_ERR_GENERIC_IO: return "ERR: generic I/O error";
|
||||
case RESULT_ERR_DEVICE: return "ERR: generic device error";
|
||||
case RESULT_ERR_SEND: return "ERR: send error";
|
||||
|
||||
@@ -24,6 +24,7 @@ static const int RESULT_OK = 0; // success
|
||||
|
||||
static const int RESULT_IN_ESC = 1; // start of escape sequence received
|
||||
static const int RESULT_SYN = 2; // regular SYN after message received
|
||||
static const int RESULT_EMPTY = 3; // empty result
|
||||
|
||||
static const int RESULT_ERR_GENERIC_IO = -1; // generic I/O error (usually fatal)
|
||||
static const int RESULT_ERR_DEVICE = -2; // generic device error (usually fatal)
|
||||
|
||||
Reference in New Issue
Block a user