Merge pull request #20 from john30/master

added scanning, bugfixes
This commit is contained in:
Roland Jax
2014-12-13 00:08:11 +01:00
16 changed files with 688 additions and 307 deletions
Executable → Regular
View File
+43 -31
View File
@@ -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_messages->size()); L.log(bas, event, "message DB: %d ", m_messages->size());
L.log(bas, event, " cycle DB: %d ", m_messages->size(true)); L.log(bas, event, "updates DB: %d ", m_messages->size(true));
L.log(bas, event, " polling DB: %d ", m_messages->sizePoll()); 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");
@@ -242,11 +242,11 @@ string BaseLoop::decodeMessage(const string& data)
istringstream input; istringstream input;
result_t ret = message->prepareMaster(m_ownAddress, master, input); result_t ret = message->prepareMaster(m_ownAddress, master, input);
if (ret != RESULT_OK) { if (ret != RESULT_OK) {
L.log(bas, error, " prepare message: %s", getResultCode(ret)); L.log(bas, error, " prepare read: %s", getResultCode(ret));
result << getResultCode(ret); result << getResultCode(ret);
break; break;
} }
L.log(bas, event, " msg: %s", master.getDataStr().c_str()); L.log(bas, event, " read msg: %s", master.getDataStr().c_str());
// send message // send message
SymbolString slave; SymbolString slave;
@@ -257,12 +257,12 @@ string BaseLoop::decodeMessage(const string& data)
ret = message->decode(pt_slaveData, slave, result); // decode data ret = message->decode(pt_slaveData, slave, result); // decode data
} }
if (ret != RESULT_OK) { if (ret != RESULT_OK) {
L.log(bas, error, " %s", getResultCode(ret)); L.log(bas, error, " read: %s", getResultCode(ret));
result << getResultCode(ret); result << getResultCode(ret);
} }
} else { } else {
result << "ebus command not found"; result << "get command not found";
} }
break; break;
@@ -280,11 +280,11 @@ string BaseLoop::decodeMessage(const string& data)
istringstream input(cmd[3]); istringstream input(cmd[3]);
result_t ret = message->prepareMaster(m_ownAddress, master, input); result_t ret = message->prepareMaster(m_ownAddress, master, input);
if (ret != RESULT_OK) { if (ret != RESULT_OK) {
L.log(bas, error, " prepare message: %s", getResultCode(ret)); L.log(bas, error, " prepare write: %s", getResultCode(ret));
result << getResultCode(ret); result << getResultCode(ret);
break; break;
} }
L.log(bas, event, " msg: %s", master.getDataStr().c_str()); L.log(bas, event, " write msg: %s", master.getDataStr().c_str());
// send message // send message
SymbolString slave; SymbolString slave;
@@ -293,16 +293,19 @@ string BaseLoop::decodeMessage(const string& data)
if (ret == RESULT_OK) { if (ret == RESULT_OK) {
if (master[1] == BROADCAST || isMaster(master[1])) if (master[1] == BROADCAST || isMaster(master[1]))
result << "done"; result << "done";
else else {
ret = message->decode(pt_slaveData, slave, result); // decode data ret = message->decode(pt_slaveData, slave, result); // decode data
if (ret == RESULT_OK && result.str().empty() == true)
result << "done";
}
} }
if (ret != RESULT_OK) { if (ret != RESULT_OK) {
L.log(bas, error, " %s", getResultCode(ret)); L.log(bas, error, " write: %s", getResultCode(ret));
result << getResultCode(ret); result << getResultCode(ret);
} }
} else { } else {
result << "ebus command not found"; result << "set command not found";
} }
break; break;
@@ -326,7 +329,7 @@ string BaseLoop::decodeMessage(const string& data)
result << "no data stored"; result << "no data stored";
} }
} else { } else {
result << "ebus command not found"; result << "cyc command not found";
} }
break; break;
@@ -344,18 +347,20 @@ string BaseLoop::decodeMessage(const string& data)
msg << hex << setw(2) << setfill('0') << static_cast<unsigned>(m_ownAddress); msg << hex << setw(2) << setfill('0') << static_cast<unsigned>(m_ownAddress);
msg << cmd[1]; msg << cmd[1];
SymbolString master(msg.str()); SymbolString master(msg.str());
L.log(bas, event, " msg: %s", master.getDataStr().c_str()); L.log(bas, event, " hex msg: %s", master.getDataStr().c_str());
// send message // send message
SymbolString slave; SymbolString slave;
result_t ret = m_busHandler->sendAndWait(master, slave); result_t ret = m_busHandler->sendAndWait(master, slave);
if (ret == RESULT_OK) if (ret == RESULT_OK) {
// decode data if (master[1] == BROADCAST || isMaster(master[1]))
result << slave.getDataStr(); result << "done";
else
result << slave.getDataStr();
}
if (ret != RESULT_OK) { if (ret != RESULT_OK) {
L.log(bas, error, " %s", getResultCode(ret)); L.log(bas, error, " hex: %s", getResultCode(ret));
result << getResultCode(ret); result << getResultCode(ret);
} }
@@ -363,31 +368,38 @@ string BaseLoop::decodeMessage(const string& data)
break; break;
/*case ct_scan: case ct_scan:
if (cmd.size() == 1) { if (cmd.size() == 1) {
m_busloop->scan(); result_t ret = m_busHandler->startScan();
result << "done"; if (ret != RESULT_OK) {
L.log(bas, error, " scan: %s", getResultCode(ret));
result << getResultCode(ret);
}
else
result << "scan initiated";
break; break;
} }
if (strcasecmp(cmd[1].c_str(), "FULL") == 0) { if (strcasecmp(cmd[1].c_str(), "FULL") == 0) {
m_busloop->scan(true); result_t ret = m_busHandler->startScan(true);
result << "done"; if (ret != RESULT_OK) {
L.log(bas, error, " full scan: %s", getResultCode(ret));
result << getResultCode(ret);
}
else
result << "done";
break; break;
} }
if (strcasecmp(cmd[1].c_str(), "RESULT") == 0) { if (strcasecmp(cmd[1].c_str(), "RESULT") == 0) {
// TODO format scan results m_busHandler->formatScanResult(result);
for (size_t i = 0; i < m_commands->sizeScanDB(); i++)
result << m_commands->getScanData(i) << endl;
break; break;
} }
result << "usage: 'scan'" << endl result << "usage: 'scan'" << endl
<< " 'scan full'" << endl << " 'scan full'" << endl
<< " 'scan result'"; << " 'scan result'";
break;*/ break;
case ct_log: case ct_log:
if (cmd.size() != 3 ) { if (cmd.size() != 3 ) {
@@ -458,9 +470,9 @@ string BaseLoop::decodeMessage(const string& data)
case ct_help: case ct_help:
result << "commands:" << endl result << "commands:" << endl
<< " get - fetch ebus data 'get class cmd (sub)'" << endl << " get - fetch ebus data 'get [class] cmd (sub)'" << endl
<< " set - set ebus values 'set class cmd value'" << endl << " set - set ebus values 'set class cmd value'" << endl
<< " cyc - fetch cycle data 'cyc class cmd (sub)'" << endl << " cyc - fetch cycle data 'cyc [class] cmd (sub)'" << endl
<< " hex - send given hex value 'hex type value' (value: ZZPBSBNNDx)" << endl << endl << " hex - send given hex value 'hex type value' (value: ZZPBSBNNDx)" << endl << endl
<< " scan - scan ebus kown addresses 'scan'" << endl << " scan - scan ebus kown addresses 'scan'" << endl
<< " - scan ebus all addresses 'scan full'" << endl << " - scan ebus all addresses 'scan full'" << endl
+176 -30
View File
@@ -28,6 +28,7 @@
#include <vector> #include <vector>
#include <cstring> #include <cstring>
#include <time.h> #include <time.h>
#include <iomanip>
using namespace std; using namespace std;
@@ -79,6 +80,27 @@ void PollRequest::notify(result_t result)
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());
} }
result_t ScanRequest::prepare(unsigned char ownMasterAddress, unsigned char dstAddress)
{
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 msg: %s", m_master.getDataStr().c_str());
return result;
}
void ScanRequest::notify(result_t result)
{
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
}
if (result != RESULT_OK)
L.log(bus, error, "scan %x failed: %s", m_master[1], getResultCode(result));
}
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, slave, false), m_finished(false), m_result(RESULT_SYN)
{ {
@@ -131,7 +153,7 @@ result_t BusHandler::sendAndWait(SymbolString& master, SymbolString& slave)
result_t result = RESULT_SYN; result_t result = RESULT_SYN;
ActiveBusRequest* request = new ActiveBusRequest(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; sendRetries>=0; sendRetries--) {
m_requests.add(request); m_requests.add(request);
bool success = request->wait(1); // 1 second is still 3 times the theoretical worst-case request duration bool success = request->wait(1); // 1 second is still 3 times the theoretical worst-case request duration
if (success == false) if (success == false)
@@ -141,18 +163,11 @@ result_t BusHandler::sendAndWait(SymbolString& master, SymbolString& slave)
if (result == RESULT_OK) if (result == RESULT_OK)
break; break;
if (result == RESULT_ERR_BUS_LOST) {
if (--lostRetries > 0) {
sendRetries++; // try to get lock again, do not decrement send retries
L.log(bus, error, " %s, retry bus loss", getResultCode(result));
continue;
}
lostRetries = m_busLostRetries+1; // send retry: reset lock retries
}
L.log(bus, error, " %s, %s", getResultCode(result), sendRetries>0 ? "retry send" : "give up"); L.log(bus, error, " %s, %s", getResultCode(result), sendRetries>0 ? "retry send" : "give up");
request->m_busLostRetries = 0;
} }
delete request; delete request; // TODO may be unsave while run() is using the request
return result; return result;
} }
@@ -241,6 +256,20 @@ result_t BusHandler::handleSymbol()
} }
break; break;
case bs_sendCmdAck:
if (m_request != NULL) {
sendSymbol = m_commandCrcValid ? ACK : NAK;
sending = true;
}
break;
case bs_sendRes:
if (m_request != NULL) {
sendSymbol = m_response[m_nextSendPos];
sending = true;
}
break;
case bs_sendSyn: case bs_sendSyn:
sendSymbol = SYN; sendSymbol = SYN;
sending = true; sending = true;
@@ -319,25 +348,25 @@ result_t BusHandler::handleSymbol()
if (result == RESULT_OK && crcPos != 0xff && m_command.size() == crcPos + 1) { // CRC received if (result == RESULT_OK && crcPos != 0xff && m_command.size() == crcPos + 1) { // CRC received
unsigned char dstAddress = m_command[1]; unsigned char dstAddress = m_command[1];
//if (isValidAddress(dstAddress) == false || isMaster(m_command[0]) == false)
// return setState(bs_skip, RESULT_ERR_INVALID_ADDR);
m_commandCrcValid = m_command[headerLen + 1 + m_command[headerLen]] == m_command.getCRC(); m_commandCrcValid = m_command[headerLen + 1 + m_command[headerLen]] == m_command.getCRC();
if (m_commandCrcValid) { if (m_commandCrcValid) {
if (dstAddress == BROADCAST) { if (dstAddress == BROADCAST) {
receiveCompleted(); receiveCompleted();
return setState(bs_skip, RESULT_OK); return setState(bs_skip, RESULT_OK);
} }
//if (dstAddress == m_ownMasterAddress || dstAddress == m_ownSlaveAddress) if (m_answer == true
// return setState(bs_sendCmdAck, RESULT_OK); && (dstAddress == m_ownMasterAddress || dstAddress == m_ownSlaveAddress))
return setState(bs_sendCmdAck, RESULT_OK);
return setState(bs_recvCmdAck, RESULT_OK); return setState(bs_recvCmdAck, RESULT_OK);
} }
if (dstAddress == BROADCAST) if (dstAddress == BROADCAST)
return setState(bs_skip, RESULT_OK); return setState(bs_skip, RESULT_ERR_CRC);
//if (dstAddress == m_ownMasterAddress || dstAddress == m_ownSlaveAddress) if (m_answer == true
// return setState(bs_sendCmdAck, RESULT_ERR_CRC); && (dstAddress == m_ownMasterAddress || dstAddress == m_ownSlaveAddress)) {
return setState(bs_sendCmdAck, RESULT_ERR_CRC);
}
if (m_repeat == true) if (m_repeat == true)
return setState(bs_skip, RESULT_ERR_CRC); return setState(bs_skip, RESULT_ERR_CRC);
return setState(bs_recvCmdAck, RESULT_ERR_CRC); return setState(bs_recvCmdAck, RESULT_ERR_CRC);
@@ -401,7 +430,7 @@ result_t BusHandler::handleSymbol()
} }
if (m_repeat == true) { if (m_repeat == true) {
if (m_request != NULL) if (m_request != NULL)
return setState(bs_skip, RESULT_ERR_CRC); return setState(bs_sendSyn, RESULT_ERR_CRC);
return setState(bs_skip, RESULT_ERR_CRC); return setState(bs_skip, RESULT_ERR_CRC);
} }
@@ -452,11 +481,64 @@ result_t BusHandler::handleSymbol()
if (m_request != NULL && sending == true) { if (m_request != NULL && sending == true) {
if (recvSymbol == sendSymbol) { if (recvSymbol == sendSymbol) {
// successfully sent // successfully sent
if (m_responseCrcValid == false) {
if (m_repeat == false) {
m_repeat = true;
m_response.clear();
return setState(bs_recvRes, RESULT_ERR_NAK, true);
}
return setState(bs_sendSyn, RESULT_ERR_ACK);
}
return setState(bs_sendSyn, RESULT_OK); return setState(bs_sendSyn, RESULT_OK);
} }
} }
return setState(bs_skip, RESULT_ERR_INVALID_ARG); return setState(bs_skip, RESULT_ERR_INVALID_ARG);
case bs_sendCmdAck:
if (sending == true && m_answer == true) {
if (recvSymbol == sendSymbol) {
// successfully sent
if (m_commandCrcValid == false) {
if (m_repeat == false) {
m_repeat = true;
m_command.clear();
return setState(bs_recvCmd, RESULT_ERR_NAK, true);
}
return setState(bs_skip, RESULT_ERR_ACK);
}
if (isMaster(m_command[1]) == true)
receiveCompleted(); // decode command and store value
return setState(bs_skip, RESULT_OK);
m_nextSendPos = 0;
m_repeat = false;
Message* message = m_messages->find(m_command);
if (message == NULL || message->isPassive() == false || message->isSet() == true)
return setState(bs_skip, RESULT_ERR_INVALID_ARG); // don't know this request or definition has wrong direction, deny
// build response and store in m_response for sending back to requesting master
result = message->prepareSlave(m_response);
if (result != RESULT_OK)
return setState(bs_skip, result);
return setState(bs_sendRes, RESULT_OK);
}
}
return setState(bs_skip, RESULT_ERR_INVALID_ARG);
case bs_sendRes:
if (sending == true && m_answer == true) {
if (recvSymbol == sendSymbol) {
// successfully sent
m_nextSendPos++;
if (m_nextSendPos >= m_response.size()) {
// slave data completely sent
return setState(bs_recvResAck, RESULT_OK);
}
return RESULT_OK;
}
}
return setState(bs_skip, RESULT_ERR_INVALID_ARG);
case bs_sendSyn: case bs_sendSyn:
if (sending == true) { if (sending == true) {
if (recvSymbol == sendSymbol) { if (recvSymbol == sendSymbol) {
@@ -474,12 +556,24 @@ result_t BusHandler::handleSymbol()
result_t BusHandler::setState(BusState state, result_t result, bool firstRepetition) result_t BusHandler::setState(BusState state, result_t result, bool firstRepetition)
{ {
if (m_request != NULL) { if (m_request != NULL) {
if (state == bs_sendSyn || (result != RESULT_OK && firstRepetition == false)) { if (result == RESULT_ERR_BUS_LOST && m_request->m_busLostRetries < m_busLostRetries) {
L.log(bus, error, " %s, retry", getResultCode(result));
m_request->m_busLostRetries++;
m_requests.add(m_request); // repeat
m_request = NULL;
} 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); m_request->m_slave = SymbolString(m_response, false, false);
m_request->notify(result); m_request->notify(result);
if (m_request->m_isPoll == true) if (m_request->m_deleteOnFinish == true) {
if (result == RESULT_OK && typeid(*m_request) == typeid(ScanRequest)) {
unsigned char dstAddress = m_request->m_master[1];
string res = ((ScanRequest*)m_request)->m_scanResult.str();
L.log(bus, debug, " scan result %x: %s", dstAddress, res.c_str());
m_scanResults[dstAddress] = res;
}
delete m_request; delete m_request;
}
m_request = NULL; m_request = NULL;
} }
} }
@@ -506,26 +600,78 @@ result_t BusHandler::setState(BusState state, result_t result, bool firstRepetit
void BusHandler::receiveCompleted() void BusHandler::receiveCompleted()
{ {
unsigned char dstAddress = m_command[1];
bool master = isMaster(dstAddress);
m_seenAddresses[m_command[0]] = true;
if (dstAddress == BROADCAST)
L.log(bus, trace, "received BC %s", m_command.getDataStr().c_str());
else if (master == true) {
L.log(bus, trace, "received MM %s", m_command.getDataStr().c_str());
m_seenAddresses[dstAddress] = true;
} else {
L.log(bus, trace, "received MS %s / %s", m_command.getDataStr().c_str(), m_response.getDataStr().c_str());
m_seenAddresses[dstAddress] = true;
}
Message* message = m_messages->find(m_command); Message* message = m_messages->find(m_command);
if (message != NULL) { if (message != NULL) {
string clazz = message->getClass(); string clazz = message->getClass();
string name = message->getName(); string name = message->getName();
ostringstream output; ostringstream output;
result_t result = message->decode(pt_masterData, m_command, output); result_t result = message->decode(pt_masterData, m_command, output);
if (result == RESULT_OK) if (result == RESULT_OK && dstAddress != BROADCAST && master == false)
result = message->decode(pt_slaveData, m_response, output, output.str().empty() == false); result = message->decode(pt_slaveData, m_response, output, output.str().empty() == false);
if (result != RESULT_OK) if (result != RESULT_OK)
L.log(bus, error, "unable to parse %s %s from %s / %s: %s", clazz.c_str(), name.c_str(), m_command.getDataStr().c_str(), m_response.getDataStr().c_str(), getResultCode(result)); L.log(bus, error, "unable to parse %s %s from %s / %s: %s", clazz.c_str(), name.c_str(), m_command.getDataStr().c_str(), m_response.getDataStr().c_str(), getResultCode(result));
else { else {
string data = output.str(); string data = output.str();
L.log(bus, trace, "%s %s: %s", clazz.c_str(), name.c_str(), data.c_str()); L.log(bus, event, "%s %s: %s", clazz.c_str(), name.c_str(), data.c_str());
} }
return;
} }
if (m_command[1] == BROADCAST) }
L.log(bus, trace, "received broadcast %s", m_command.getDataStr().c_str());
else if (isMaster(m_command[1]) == true) result_t BusHandler::startScan(bool full)
L.log(bus, trace, "received master-master %s", m_command.getDataStr().c_str()); {
else Message* scanMessage = m_scanMessage;
L.log(bus, trace, "received master-slave %s / %s", m_command.getDataStr().c_str(), m_response.getDataStr().c_str()); if (scanMessage == NULL) {
scanMessage = m_messages->find("", "scan", false);
}
if (scanMessage == NULL) {
DataFieldSet* identFields = DataFieldSet::createIdentFields();
scanMessage = m_scanMessage = new Message(false, false, 0x07, 0x04, identFields);
}
if (scanMessage == NULL)
return RESULT_ERR_NOTFOUND;
if (full == true)
m_scanResults.clear();
for (unsigned int slave=0; slave<=255; slave++) {
if (isValidAddress(slave, false) == false || isMaster(slave) == true)
continue;
if (full == false && m_seenAddresses[slave] == false) {
unsigned int master = slave+(256-5); // check if we saw the corresponding master already
if (isMaster(master) == false || m_seenAddresses[slave] == false)
continue;
}
ScanRequest* request = new ScanRequest(m_response, scanMessage);
result_t result = request->prepare(m_ownMasterAddress, slave);
if (result != RESULT_OK) {
delete request;
return result;
}
m_requests.add(request);
}
return RESULT_OK;
}
void BusHandler::formatScanResult(ostringstream& output)
{
for (unsigned int slave=0; slave<=255; slave++) {
map<unsigned char, string>::iterator it = m_scanResults.find(slave);
if (it != m_scanResults.end())
output << it->second << endl;
}
} }
+87 -9
View File
@@ -31,6 +31,7 @@
#include <vector> #include <vector>
#include <map> #include <map>
#include <pthread.h> #include <pthread.h>
#include <typeinfo>
using namespace std; using namespace std;
@@ -53,8 +54,8 @@ enum BusState {
bs_recvResAck, // receive response ACK/NACK [passive set] bs_recvResAck, // receive response ACK/NACK [passive set]
bs_sendCmd, // send command (ZZ, PBSB, master data) [active set+get] bs_sendCmd, // send command (ZZ, PBSB, master data) [active set+get]
bs_sendResAck, // send response ACK/NACK [active get] bs_sendResAck, // send response ACK/NACK [active get]
// bs_sendRes, // send response (slave data) [passive get] // TODO implement bs_sendCmdAck, // send command ACK/NACK [passive get]
// bs_sendCmdAck, // send command ACK/NACK [passive get] // TODO implement bs_sendRes, // send response (slave data) [passive get]
bs_sendSyn, // send SYN for completed transfer [active set+get] bs_sendSyn, // send SYN for completed transfer [active set+get]
}; };
@@ -72,10 +73,11 @@ 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. * @param deleteOnFinish whether to automatically delete this @a BusRequest when finished.
*/ */
BusRequest(SymbolString& master, SymbolString& slave, bool isPoll) BusRequest(SymbolString& master, SymbolString& slave, bool deleteOnFinish)
: m_master(master), m_slave(slave), m_isPoll(isPoll) {} : m_master(master), m_slave(slave), m_busLostRetries(0),
m_deleteOnFinish(deleteOnFinish) {}
/** /**
* @brief Destructor. * @brief Destructor.
@@ -96,8 +98,11 @@ protected:
/** the slave data @a SymbolString received. */ /** the slave data @a SymbolString received. */
SymbolString& m_slave; SymbolString& m_slave;
/** whether this is a poll request. */ /** the number of times a send is repeated due to lost arbitration. */
bool m_isPoll; unsigned int m_busLostRetries;
/** whether to automatically delete this @a BusRequest when finished. */
bool m_deleteOnFinish;
}; };
@@ -144,6 +149,52 @@ private:
}; };
/**
* @brief A scan @a BusRequest handled by @a BusHandler itself.
*/
class ScanRequest : public BusRequest
{
friend class BusHandler;
public:
/**
* @brief Constructor.
* @param slave the slave data @a SymbolString received.
* @param message the associated @a Message.
*/
ScanRequest(SymbolString& slave, Message* message)
: BusRequest(m_master, slave, true), m_message(message) {}
/**
* @brief Destructor.
*/
virtual ~ScanRequest() {}
/**
* @brief Prepare the master data.
* @param masterAddress the master bus address to use.
* @param dstAddress the destination address to set.
* @return the result code.
*/
result_t prepare(unsigned char masterAddress, unsigned char dstAddress);
// @copydoc
virtual void notify(result_t result);
private:
/** the master data @a SymbolString. */
SymbolString m_master;
/** the associated @a Message. */
Message* m_message;
/** the formatted scan result. */
ostringstream m_scanResult;
};
/** /**
* @brief An active @a BusRequest that can be waited for. * @brief An active @a BusRequest that can be waited for.
*/ */
@@ -224,12 +275,18 @@ public:
m_pollInterval(pollInterval), m_lastPoll(0), 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),
m_scanMessage(NULL) {
memset(m_seenAddresses, 0, sizeof(m_seenAddresses));
}
/** /**
* @brief Destructor. * @brief Destructor.
*/ */
virtual ~BusHandler() {} virtual ~BusHandler() {
if (m_scanMessage != NULL)
delete m_scanMessage;
}
/** /**
* @brief Send a message on the bus and wait for the answer. * @brief Send a message on the bus and wait for the answer.
@@ -250,6 +307,18 @@ public:
*/ */
string getReceivedData(Message* message); string getReceivedData(Message* message);
/**
* @brief Initiate a scan of the slave addresses.
* @param full true for a full scan (all slaves), false for scanning only already seen slaves.
*/
result_t startScan(bool full=false);
/**
* @brief Format the scan result to the @a ostringstream.
* @param output the @a ostringstream to format the scan result to.
*/
void formatScanResult(ostringstream& output);
private: private:
/** /**
@@ -339,6 +408,15 @@ private:
/** whether the response CRC is valid. */ /** whether the response CRC is valid. */
bool m_responseCrcValid; bool m_responseCrcValid;
/** the participating bus addresses seen so far. */
bool m_seenAddresses[256];
/** the @a Message instance used for scanning. */
Message* m_scanMessage;
/** the scan results by slave address. */
map<unsigned char, string> m_scanResults;
}; };
Executable → Regular
View File
+77 -14
View File
@@ -28,10 +28,22 @@
using namespace std; using namespace std;
static const dataType_t stringDataType = {
"STR",16*8,bt_str, ADJ, ' ', 1, 16, 0, 0 // >= 1 byte character string filled up with space
};
static const dataType_t bcdDataType = {
"BCD", 8, bt_num, BCD|LST, 0xff, 0, 0x99, 1, 0 // unsigned decimal in BCD, 0 - 99
};
static const dataType_t ucharDataType = {
"UCH", 8, bt_num, LST, 0xff, 0, 0xfe, 1, 0 // unsigned integer, 0 - 254
};
/** the known data field types. */ /** the known data field types. */
static const dataType_t dataTypes[] = { static const dataType_t dataTypes[] = {
{"IGN",16*8,bt_str, IGN|ADJ, 0, 1, 16, 0, 0}, // >= 1 byte ignored data {"IGN",16*8,bt_str, IGN|ADJ, 0, 1, 16, 0, 0}, // >= 1 byte ignored data
{"STR",16*8,bt_str, ADJ, ' ', 1, 16, 0, 0}, // >= 1 byte character string filled up with space stringDataType,
{"HEX",16*8,bt_hexstr, ADJ, 0, 2, 47, 0, 0}, // >= 1 byte hex digit string, usually separated by space, e.g. 0a 1b 2c 3d {"HEX",16*8,bt_hexstr, ADJ, 0, 2, 47, 0, 0}, // >= 1 byte hex digit string, usually separated by space, e.g. 0a 1b 2c 3d
{"BDA", 32, bt_dat, BCD, 0, 10, 10, 0, 0}, // date with weekday in BCD, 01.01.2000 - 31.12.2099 (0x01,0x01,WW,0x00 - 0x31,0x12,WW,0x99, WW is weekday Mon=0x00 - Sun=0x06) {"BDA", 32, bt_dat, BCD, 0, 10, 10, 0, 0}, // date with weekday in BCD, 01.01.2000 - 31.12.2099 (0x01,0x01,WW,0x00 - 0x31,0x12,WW,0x99, WW is weekday Mon=0x00 - Sun=0x06)
{"BDA", 24, bt_dat, BCD, 0, 10, 10, 0, 0}, // date in BCD, 01.01.2000 - 31.12.2099 (0x01,0x01,0x00 - 0x31,0x12,0x99) {"BDA", 24, bt_dat, BCD, 0, 10, 10, 0, 0}, // date in BCD, 01.01.2000 - 31.12.2099 (0x01,0x01,0x00 - 0x31,0x12,0x99)
@@ -44,8 +56,8 @@ 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]
{"BCD", 8, bt_num, BCD|LST, 0xff, 0, 0x99, 1, 0}, // unsigned decimal in BCD, 0 - 99 bcdDataType,
{"UCH", 8, bt_num, LST, 0xff, 0, 0xfe, 1, 0}, // unsigned integer, 0 - 254 ucharDataType,
{"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)
@@ -70,9 +82,6 @@ static const dataType_t dataTypes[] = {
/** the week day names. */ /** the week day names. */
static const char* dayNames[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; static const char* dayNames[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
#define VALUE_SEPARATOR ','
#define LENGTH_SEPARATOR ':'
#define NULL_VALUE "-"
#define MAX_POS 16 #define MAX_POS 16
unsigned int parseInt(const char* str, int base, const unsigned int minValue, const unsigned int maxValue, result_t& result, unsigned int* length) { unsigned int parseInt(const char* str, int base, const unsigned int minValue, const unsigned int maxValue, result_t& result, unsigned int* length) {
@@ -96,7 +105,7 @@ unsigned int parseInt(const char* str, int base, const unsigned int minValue, co
return ret; return ret;
} }
void printErrorPos(vector<string>::iterator begin, const vector<string>::iterator end, vector<string>::iterator pos, char separator) void printErrorPos(vector<string>::iterator begin, const vector<string>::iterator end, vector<string>::iterator pos)
{ {
cout << "Erroneous item is here:" << endl; cout << "Erroneous item is here:" << endl;
bool first = true; bool first = true;
@@ -107,7 +116,7 @@ void printErrorPos(vector<string>::iterator begin, const vector<string>::iterato
if (first == true) if (first == true)
first = false; first = false;
else { else {
cout << separator; cout << FIELD_SEPARATOR;
if (begin <= pos) { if (begin <= pos) {
cnt++; cnt++;
} }
@@ -141,7 +150,7 @@ result_t DataField::create(vector<string>::iterator& it,
const bool isTemplate = dstAddress == SYN; const bool isTemplate = dstAddress == SYN;
string token; string token;
// name;part;type[:len][;[divisor|values][;[unit][;[comment]]]] // name,part,type[:len][,[divisor|values][,[unit][,[comment]]]]
const string name = *it++; const string name = *it++;
if (it == end) if (it == end)
break; break;
@@ -317,7 +326,7 @@ result_t DataField::create(vector<string>::iterator& it,
result = RESULT_ERR_OUT_OF_RANGE; result = RESULT_ERR_OUT_OF_RANGE;
break; break;
} }
//TODO add special field for fixed values (exactly one value in the list of values)
add = new ValueListDataField(name, comment, unit, dataType, partType, useLength, bitCount, values); add = new ValueListDataField(name, comment, unit, dataType, partType, useLength, bitCount, values);
break; break;
} }
@@ -469,6 +478,19 @@ result_t StringDataField::readSymbols(SymbolString& input,
incr = -1; incr = -1;
} }
switch (m_dataType.type) // initialize output
{
case bt_hexstr:
output << setw(2) << hex << setfill('0');
break;
case bt_dat:
case bt_tim:
output << setw(2) << dec << setfill('0');
break;
default:
output << setw(0) << dec;
}
for (size_t offset = start, i = 0; i < count; offset += incr, i++) { for (size_t offset = start, i = 0; i < count; offset += incr, i++) {
if (m_length == 4 && i == 2 && m_dataType.type == bt_dat) if (m_length == 4 && i == 2 && m_dataType.type == bt_dat)
continue; // skip weekday in between continue; // skip weekday in between
@@ -483,8 +505,7 @@ result_t StringDataField::readSymbols(SymbolString& input,
case bt_hexstr: case bt_hexstr:
if (i > 0) if (i > 0)
output << ' '; output << ' ';
output << nouppercase << setw(2) << hex << setfill('0') output << static_cast<unsigned>(ch);
<< static_cast<unsigned>(ch);
break; break;
case bt_dat: case bt_dat:
if (i + 1 == m_length) if (i + 1 == m_length)
@@ -492,7 +513,7 @@ result_t StringDataField::readSymbols(SymbolString& input,
else if (ch < 1 || (i == 0 && ch > 31) || (i == 1 && ch > 12)) else if (ch < 1 || (i == 0 && ch > 31) || (i == 1 && ch > 12))
return RESULT_ERR_OUT_OF_RANGE; // invalid date return RESULT_ERR_OUT_OF_RANGE; // invalid date
else else
output << setw(2) << setfill('0') << static_cast<unsigned>(ch) << "."; output << static_cast<unsigned>(ch) << ".";
break; break;
case bt_tim: case bt_tim:
if (m_dataType.replacement != 0 && ch == m_dataType.replacement) { if (m_dataType.replacement != 0 && ch == m_dataType.replacement) {
@@ -518,7 +539,7 @@ result_t StringDataField::readSymbols(SymbolString& input,
return RESULT_ERR_OUT_OF_RANGE; // invalid time return RESULT_ERR_OUT_OF_RANGE; // invalid time
if (i > 0) if (i > 0)
output << ":"; output << ":";
output << setw(2) << setfill('0') << static_cast<unsigned>(ch); output << static_cast<unsigned>(ch);
break; break;
default: default:
if (ch < 0x20) if (ch < 0x20)
@@ -824,6 +845,8 @@ result_t NumberDataField::readSymbols(SymbolString& input,
if (result != RESULT_OK) if (result != RESULT_OK)
return result; return result;
output << setw(0) << dec; // initialize output
if (value == m_dataType.replacement) { if (value == m_dataType.replacement) {
output << NULL_VALUE; output << NULL_VALUE;
return RESULT_OK; return RESULT_OK;
@@ -970,6 +993,8 @@ result_t ValueListDataField::readSymbols(SymbolString& input,
if (result != RESULT_OK) if (result != RESULT_OK)
return result; return result;
output << setw(0) << dec; // initialize output
map<unsigned int, string>::iterator it = m_values.find(value); map<unsigned int, string>::iterator it = m_values.find(value);
if (it != m_values.end()) { if (it != m_values.end()) {
output << it->second; output << it->second;
@@ -1002,6 +1027,44 @@ result_t ValueListDataField::writeSymbols(istringstream& input,
return RESULT_ERR_NOTFOUND; // value assignment not found return RESULT_ERR_NOTFOUND; // value assignment not found
} }
DataFieldSet* DataFieldSet::createIdentFields()
{
vector<SingleDataField*> fields;
map<unsigned int, string> manufacturers;
manufacturers[0x06] = "Karl Dungs GmbH";
manufacturers[0x0f] = "FH Braunschweig/Wolfenbüttel";
manufacturers[0x10] = "TEM AG für Elektronik Intertem Vertriebs AG";
manufacturers[0x11] = "Lamberti Elektronik";
manufacturers[0x14] = "CEB Compagnie Européenne de Brûleurs S.A.";
manufacturers[0x15] = "Landis & Staefa";
manufacturers[0x16] = "FERRO Wärmetechnik GmbH & Co.KG";
manufacturers[0x17] = "MONDIAL electronic Ges.mbH";
manufacturers[0x18] = "Wikon Kommunikationstechnik GmbH";
manufacturers[0x19] = "Wolf GmbH";
manufacturers[0x20] = "RAWE Electronic GmbH";
manufacturers[0x30] = "Satronic AG";
manufacturers[0x40] = "ENCON Electronics";
manufacturers[0x50] = "G. Kromschröder AG";
manufacturers[0x60] = "Eberle Controls GmbH";
manufacturers[0x65] = "EBV Elektronikbau";
manufacturers[0x75] = "Grässlin GmbH & Co.KG";
manufacturers[0x85] = "Motoren und Ventilatoren Landshut GmbH";
manufacturers[0x95] = "SIG Berger Lahr GmbH & Co KG";
manufacturers[0xa5] = "Theben Zeitschaltautomatik";
manufacturers[0xa7] = "Thermowatt s.p.a.";
manufacturers[0xb5] = "Joh. Vaillant GmbH & Co.";
manufacturers[0xc0] = "Toby AG";
manufacturers[0xc5] = "Max Weishaupt GmbH";
fields.push_back(new ValueListDataField("manufacturer", "", "", ucharDataType, pt_slaveData, 1, 8, manufacturers));
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("swr", "", "", bcdDataType, pt_slaveData, 1, 8, 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);
}
DataFieldSet::~DataFieldSet() DataFieldSet::~DataFieldSet()
{ {
while (m_fields.empty() == false) { while (m_fields.empty() == false) {
+26 -8
View File
@@ -31,7 +31,20 @@
using namespace std; using namespace std;
#define FIELD_SEPARATOR ';' /** the separator character used between fields (in CSV only). */
#define FIELD_SEPARATOR ','
/** the separator character used between multiple values (in CSV only). */
#define VALUE_SEPARATOR ';'
/** the separator character used between base type name and length (in CSV only). */
#define LENGTH_SEPARATOR ':'
/** the replacement string for undefined values (in UI and CSV). */
#define NULL_VALUE "-"
/** the separator character used between fields (in UI only). */
#define UI_FIELD_SEPARATOR ';'
/** the message part in which a data field is stored. */ /** the message part in which a data field is stored. */
enum PartType { enum PartType {
@@ -90,7 +103,7 @@ unsigned int parseInt(const char* str, int base, const unsigned int minValue, co
* @param pos the iterator with the erroneous position. * @param pos the iterator with the erroneous position.
* @param separator the character to place between items. * @param separator the character to place between items.
*/ */
void printErrorPos(vector<string>::iterator begin, const vector<string>::iterator end, vector<string>::iterator pos, char separator=';'); void printErrorPos(vector<string>::iterator begin, const vector<string>::iterator end, vector<string>::iterator pos);
class DataFieldTemplates; class DataFieldTemplates;
@@ -178,7 +191,7 @@ public:
virtual result_t read(const PartType partType, virtual result_t read(const PartType partType,
SymbolString& data, unsigned char offset, SymbolString& data, unsigned char offset,
ostringstream& output, bool leadingSeparator=false, ostringstream& output, bool leadingSeparator=false,
bool verbose=false, char separator=';') = 0; bool verbose=false, char separator=UI_FIELD_SEPARATOR) = 0;
/** /**
* @brief Writes the value to the master or slave @a SymbolString. * @brief Writes the value to the master or slave @a SymbolString.
* @param input the @a istringstream to parse the formatted value from. * @param input the @a istringstream to parse the formatted value from.
@@ -190,7 +203,7 @@ public:
*/ */
virtual result_t write(istringstream& input, virtual result_t write(istringstream& input,
const PartType partType, SymbolString& data, const PartType partType, SymbolString& data,
unsigned char offset, char separator=';') = 0; unsigned char offset, char separator=UI_FIELD_SEPARATOR) = 0;
protected: protected:
@@ -259,11 +272,11 @@ public:
virtual result_t read(const PartType partType, virtual result_t read(const PartType partType,
SymbolString& data, unsigned char offset, SymbolString& data, unsigned char offset,
ostringstream& output, bool leadingSeparator=false, ostringstream& output, bool leadingSeparator=false,
bool verbose=false, char separator=';'); bool verbose=false, char separator=UI_FIELD_SEPARATOR);
// @copydoc // @copydoc
virtual result_t write(istringstream& input, virtual result_t write(istringstream& input,
const PartType partType, SymbolString& data, const PartType partType, SymbolString& data,
unsigned char offset, char separator=';');//TODO replace unsigned char offset, char separator=UI_FIELD_SEPARATOR);
protected: protected:
@@ -509,6 +522,11 @@ class DataFieldSet : public DataField
{ {
public: public:
/**
* @brief Create the @a DataFieldSet for parsing the identification message (service 0x07 0x04).
* @return the @a DataFieldSet for parsing the identification message.
*/
static DataFieldSet* createIdentFields();
/** /**
* @brief Constructs a new instance. * @brief Constructs a new instance.
* @param name the field name. * @param name the field name.
@@ -553,11 +571,11 @@ public:
virtual result_t read(const PartType partType, virtual result_t read(const PartType partType,
SymbolString& data, unsigned char offset, SymbolString& data, unsigned char offset,
ostringstream& output, bool leadingSeparator=false, ostringstream& output, bool leadingSeparator=false,
bool verbose=false, char separator=';'); bool verbose=false, char separator=UI_FIELD_SEPARATOR);
// @copydoc // @copydoc
virtual result_t write(istringstream& input, virtual result_t write(istringstream& input,
const PartType partType, SymbolString& data, const PartType partType, SymbolString& data,
unsigned char offset, char separator=';'); unsigned char offset, char separator=UI_FIELD_SEPARATOR);
private: private:
+67 -48
View File
@@ -28,10 +28,10 @@
using namespace std; using namespace std;
Message::Message(const string clazz, const string name, const bool isSet, Message::Message(const string clazz, const string name, const bool isSet,
const bool isPassive, const string comment, const bool isPassive, const string comment,
const unsigned char srcAddress, const unsigned char dstAddress, const unsigned char srcAddress, const unsigned char dstAddress,
const vector<unsigned char> id, DataField* data, const vector<unsigned char> id, DataField* data,
const unsigned int pollPriority) const unsigned int pollPriority)
: m_class(clazz), m_name(name), m_isSet(isSet), : m_class(clazz), m_name(name), m_isSet(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),
@@ -50,6 +50,20 @@ Message::Message(const string clazz, const string name, const bool isSet,
m_key = key; m_key = key;
} }
Message::Message(const bool isSet, const bool isPassive,
const unsigned char pb, const unsigned char sb,
DataField* data)
: m_class(), m_name(), m_isSet(isSet),
m_isPassive(isPassive), m_comment(),
m_srcAddress(SYN), m_dstAddress(SYN),
m_data(data), m_pollPriority(0),
m_lastUpdateTime(0), m_pollCount(0), m_lastPollTime(0)
{
m_id.push_back(pb);
m_id.push_back(sb);
m_key = 0;
}
/** /**
* @brief Helper method for getting a default if the value is empty. * @brief Helper method for getting a default if the value is empty.
* @param value the value to check. * @param value the value to check.
@@ -59,19 +73,11 @@ Message::Message(const string clazz, const string name, const bool isSet,
*/ */
string getDefault(string value, vector<string>* defaults, size_t pos) string getDefault(string value, vector<string>* defaults, size_t pos)
{ {
/*cout<<"getDefault("<<value<<",";
if (defaults==NULL)
cout<<"NULL";
else
cout<<static_cast<unsigned>(defaults->size());
cout<<","<<static_cast<unsigned>(pos)<<"=";*/
if (value.length() > 0 || defaults == NULL || pos > defaults->size()) { if (value.length() > 0 || defaults == NULL || pos > defaults->size()) {
//cout<<value<<endl;
return value; return value;
} }
value = defaults->at(pos); value = defaults->at(pos);
//cout<<value<<endl;
return value; return value;
} }
@@ -79,10 +85,10 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
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;
char defaultsChar; string defaultName;
unsigned int pollPriority = 0; unsigned int pollPriority = 0;
size_t defaultPos = 1; size_t defaultPos = 1;
if (it == end) if (it == end)
@@ -91,38 +97,31 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
const char* str = (*it++).c_str(); const char* str = (*it++).c_str();
if (it == end) if (it == end)
return RESULT_ERR_EOF; return RESULT_ERR_EOF;
if (str[0] == 0 || strncasecmp(str, "R", 1) == 0) { // default: active get size_t len = strlen(str);
defaultsChar = 'r'; if (len == 0) { // default: active get
defaultName = "r";
} else if (strncasecmp(str, "R", 1) == 0) { // active get
char last = str[len-1];
if (last >= '0' && last <= '9') { // poll priority (=active get)
pollPriority = last - '0';
defaultName = string(str).substr(0, len-1); // cut off priority digit
}
else
defaultName = str;
} else if (strncasecmp(str, "W", 1) == 0) { // active set } else if (strncasecmp(str, "W", 1) == 0) { // active set
isSet = true; isSet = true;
defaultsChar = 'w'; defaultName = str;
} else if (strncasecmp(str, "P", 1) == 0) { // poll (=active get)
if (str[1] == 0)
pollPriority = 1;
else {
result_t result;
pollPriority = parseInt(str+1, 10, 1, 9, result);
if (result != RESULT_OK)
return result;
}
defaultsChar = 'r';
} else if (str[0] >= '0' && str[0] <= '9') { // poll priority (=active get)
result_t result;
pollPriority = parseInt(str, 10, 1, 9, result);
if (result != RESULT_OK)
return result;
defaultsChar = 'r';
} else { // any other: passive set/get } else { // any other: passive set/get
isPassive = true; isPassive = true;
isSet = strncasecmp(str+1, "W", 1) == 0; isSet = strcasecmp(str+len-1, "W") == 0; // if type ends with "w" it is treated as passive set
defaultsChar = str[0]; defaultName = str;
} }
vector<string>* defaults = NULL; vector<string>* defaults = NULL;
if (defaultsRows != NULL && defaultsRows->size() > 0) { if (defaultsRows != NULL && defaultsRows->size() > 0) {
for (vector< vector<string> >::reverse_iterator it = defaultsRows->rbegin(); it != defaultsRows->rend(); it++) { for (vector< vector<string> >::reverse_iterator it = defaultsRows->rbegin(); it != defaultsRows->rend(); it++) {
string check = (*it)[0]; string check = (*it)[0];
if (check[0] == defaultsChar) { if (check == defaultName) {
defaults = &(*it); defaults = &(*it);
break; break;
} }
@@ -238,17 +237,19 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
return RESULT_OK; return RESULT_OK;
} }
result_t Message::prepareMaster(const unsigned char srcAddress, SymbolString& masterData, istringstream& input, char separator) result_t Message::prepareMaster(const unsigned char srcAddress, SymbolString& masterData, istringstream& input, char separator, const unsigned char dstAddress)
{ {
if (m_isPassive == true) if (m_isPassive == true)
return RESULT_ERR_INVALID_ARG; // prepare not possible return RESULT_ERR_INVALID_ARG; // prepare not possible
SymbolString master; SymbolString master;
master.clear();
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;
result = master.push_back(m_dstAddress, false, false); if (dstAddress == SYN)
result = master.push_back(m_dstAddress, false, false);
else
result = master.push_back(dstAddress, false, false);
if (result != RESULT_OK) if (result != RESULT_OK)
return result; return result;
result = master.push_back(m_id[0], false, false); result = master.push_back(m_id[0], false, false);
@@ -273,6 +274,24 @@ result_t Message::prepareMaster(const unsigned char srcAddress, SymbolString& ma
return result; return result;
} }
result_t Message::prepareSlave(SymbolString& slaveData)
{
if (m_isPassive == false || m_isSet == true)
return RESULT_ERR_INVALID_ARG; // prepare not possible
SymbolString slave;
unsigned char addData = m_data->getLength(pt_slaveData);
result_t result = slave.push_back(addData, false, false);
if (result != RESULT_OK)
return result;
istringstream input;
result = m_data->write(input, pt_slaveData, slave, 0);
if (result != RESULT_OK)
return result;
slaveData = SymbolString(slave, true);
return result;
}
result_t Message::decode(const PartType partType, SymbolString& data, result_t Message::decode(const PartType partType, SymbolString& data,
ostringstream& output, bool leadingSeparator, char separator) ostringstream& output, bool leadingSeparator, char separator)
{ {
@@ -323,7 +342,7 @@ result_t MessageMap::add(Message* message)
bool isSet = message->isSet(); bool isSet = message->isSet();
string clazz = message->getClass(); string clazz = message->getClass();
string name = message->getName(); string name = message->getName();
string key = string(isPassive ? "P" : (isSet ? "W" : "R")) + clazz + ";" + name; string key = string(isPassive ? "P" : (isSet ? "W" : "R")) + clazz + FIELD_SEPARATOR + name;
map<string, Message*>::iterator nameIt = m_messagesByName.find(key); map<string, Message*>::iterator nameIt = m_messagesByName.find(key);
if (nameIt != m_messagesByName.end()) { if (nameIt != m_messagesByName.end()) {
return RESULT_ERR_DUPLICATE; // duplicate key return RESULT_ERR_DUPLICATE; // duplicate key
@@ -332,7 +351,7 @@ result_t MessageMap::add(Message* message)
m_messagesByName[key] = message; m_messagesByName[key] = message;
m_messageCount++; 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
if (message->isPassive() == true) { if (message->isPassive() == true) {
@@ -360,7 +379,7 @@ result_t MessageMap::addFromFile(vector<string>& row, DataFieldTemplates* arg, v
istringstream stream(types); istringstream stream(types);
string type; string type;
while (getline(stream, type, ',') != 0) { while (getline(stream, type, VALUE_SEPARATOR) != 0) {
row[0] = type; row[0] = type;
vector<string>::iterator it = row.begin(); vector<string>::iterator it = row.begin();
result = Message::create(it, row.end(), defaults, arg, message); result = Message::create(it, row.end(), defaults, arg, message);
@@ -376,14 +395,14 @@ result_t MessageMap::addFromFile(vector<string>& row, DataFieldTemplates* arg, v
return result; return result;
} }
Message* MessageMap::find(const string& clazz, const string& name, const bool isSet,const bool isPassive) Message* MessageMap::find(const string& clazz, const string& name, const bool isSet, const bool isPassive)
{ {
for (int i=0; i<2; i++) { for (int i=0; i<2; i++) {
string key; string key;
if (i==0) if (i==0)
key = string(isPassive ? "P" : (isSet ? "W" : "R")) + clazz + ";" + name; key = string(isPassive ? "P" : (isSet ? "W" : "R")) + clazz + FIELD_SEPARATOR + name;
else else
key = string(isPassive ? "-P;" : (isSet ? "-W;" : "-R;")) + name; // second try: without class key = string(isPassive ? "-P" : (isSet ? "-W" : "-R")) + name; // second try: without class
map<string, Message*>::iterator it = m_messagesByName.find(key); map<string, Message*>::iterator it = m_messagesByName.find(key);
if (it != m_messagesByName.end()) if (it != m_messagesByName.end())
return it->second; return it->second;
@@ -405,7 +424,7 @@ Message* MessageMap::find(SymbolString& master)
return NULL; return NULL;
unsigned long long sourceMask = 0x1fLL << (8 * 7); unsigned long long sourceMask = 0x1fLL << (8 * 7);
for (int idLength=maxIdLength; idLength>=m_minIdLength; idLength--) { for (int idLength = maxIdLength; idLength >= m_minIdLength; idLength--) {
int exp = 7; int exp = 7;
unsigned long long key = (unsigned long long)idLength << (8 * exp + 5); unsigned long long key = (unsigned long long)idLength << (8 * exp + 5);
key |= (unsigned long long)getMasterNumber(master[0]) << (8 * exp--); key |= (unsigned long long)getMasterNumber(master[0]) << (8 * exp--);
@@ -438,8 +457,8 @@ void MessageMap::clear()
m_pollMessages.pop(); m_pollMessages.pop();
} }
// free message instances // 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: instances stored multiple times have a key starting with "-"
delete it->second; delete it->second;
it->second = NULL; it->second = NULL;
} }
+28 -4
View File
@@ -58,6 +58,18 @@ public:
const unsigned char srcAddress, const unsigned char dstAddress, const unsigned char srcAddress, const unsigned char dstAddress,
const vector<unsigned char> id, DataField* data, const vector<unsigned char> id, DataField* data,
const unsigned int pollPriority); const unsigned int pollPriority);
/**
* @brief Construct a new temporary instance.
* @param isSet whether this is a set message.
* @param isPassive true if message can only be initiated by a participant other than us,
* false if message can be initiated by any participant.
* @param pb the primary ID byte.
* @param sb the secondary ID byte.
* @param data the @a DataField for encoding/decoding the message.
*/
Message(const bool isSet, const bool isPassive,
const unsigned char pb, const unsigned char sb,
DataField* data);
/** /**
* @brief Destructor. * @brief Destructor.
*/ */
@@ -126,15 +138,27 @@ public:
* @return the polling priority, or 0 for no polling at all. * @return the polling priority, or 0 for no polling at all.
*/ */
unsigned char getPollPriority() const { return m_pollPriority; } unsigned char getPollPriority() const { return m_pollPriority; }
/** /**
* @brief Prepare master @a SymbolString for sending to the bus. * @brief Prepare the master @a SymbolString for sending a query or command to the bus.
* @param srcAddress the source address to set.
* @param masterData the master data @a SymbolString for writing symbols to. * @param masterData the master data @a SymbolString for writing symbols to.
* @param input the @a istringstream to parse the formatted value(s) from. * @param input the @a istringstream to parse the formatted value(s) from.
* @param separator the separator character between multiple fields. * @param separator the separator character between multiple fields.
* @param dstAddress the destination address to set, or @a SYN to keep the address defined during construction.
* @return @a RESULT_OK on success, or an error code. * @return @a RESULT_OK on success, or an error code.
*/ */
result_t prepareMaster(const unsigned char srcAddress, SymbolString& masterData, result_t prepareMaster(const unsigned char srcAddress, SymbolString& masterData,
istringstream& input, char separator=';'); istringstream& input, char separator=UI_FIELD_SEPARATOR,
const unsigned char dstAddress=SYN);
/**
* @brief Prepare the slave @a SymbolString for sending an answer to the bus.
* @param slaveData the slave data @a SymbolString for writing symbols to.
* @return @a RESULT_OK on success, or an error code.
*/
result_t prepareSlave(SymbolString& masterData);
/** /**
* @brief Decode a received message. * @brief Decode a received message.
* @param partType the @a PartType of the data. * @param partType the @a PartType of the data.
@@ -145,7 +169,7 @@ public:
* @return @a RESULT_OK on success, or an error code. * @return @a RESULT_OK on success, or an error code.
*/ */
result_t decode(const PartType partType, SymbolString& data, result_t decode(const PartType partType, SymbolString& data,
ostringstream& output, bool leadingSeparator=false, char separator=';'); ostringstream& output, bool leadingSeparator=false, char separator=UI_FIELD_SEPARATOR);
/** /**
* @brief Get the last decoded value. * @brief Get the last decoded value.
@@ -190,7 +214,7 @@ private:
/** the destination address. */ /** the destination address. */
const unsigned char m_dstAddress; const unsigned char m_dstAddress;
/** the primary, secondary, and optionally further command ID bytes. */ /** the primary, secondary, and optionally further command ID bytes. */
const vector<unsigned char> m_id; vector<unsigned char> m_id;
/** the key for storing in @a MessageSet. */ /** the key for storing in @a MessageSet. */
unsigned long long m_key; unsigned long long m_key;
/** the @a DataField for encoding/decoding the message. */ /** the @a DataField for encoding/decoding the message. */
+33
View File
@@ -281,6 +281,39 @@ Port::Port(const string deviceName, const bool noDeviceCheck,
setDumpRaw(dumpRaw); // open fstream if necessary setDumpRaw(dumpRaw); // open fstream if necessary
} }
ssize_t Port::send(const unsigned char* buffer, size_t nbytes)
{
ssize_t ret = m_device->sendBytes(buffer, nbytes);
if (ret>0 && m_logRaw == true && m_logRawFunc != NULL)
(*m_logRawFunc)(buffer[0], false);
return ret;
}
ssize_t Port::recv(const long timeout, size_t maxCount, unsigned char* buffer)
{
ssize_t ret = m_device->recvBytes(timeout, maxCount, buffer);
if (buffer && ret > 0) {
if (m_logRaw == true && m_logRawFunc != NULL) {
for (size_t pos = 0; pos < ret; pos++)
(*m_logRawFunc)(buffer[pos], true);
}
if (m_dumpRaw == true && m_dumpRawStream.is_open() == true) {
m_dumpRawStream.write((char*)buffer, ret);
if (m_dumpRawStream.tellp() >= m_dumpRawMaxSize * 1024) {
string oldfile = m_dumpRawFile + ".old";
if (rename(m_dumpRawFile.c_str(), oldfile.c_str()) == 0) {
m_dumpRawStream.close();
m_dumpRawStream.open(m_dumpRawFile.c_str(), ios::out | ios::binary | ios::app);
}
}
}
}
return ret;
}
unsigned char Port::byte() unsigned char Port::byte()
{ {
unsigned char byte = m_device->getByte(); unsigned char byte = m_device->getByte();
+2 -14
View File
@@ -240,13 +240,7 @@ public:
* @param nbytes number of bytes to send. * @param nbytes number of bytes to send.
* @return number of written bytes or -1 if an error has occured. * @return number of written bytes or -1 if an error has occured.
*/ */
ssize_t send(const unsigned char* buffer, size_t nbytes = MAX_WRITE_SIZE) ssize_t send(const unsigned char* buffer, size_t nbytes = MAX_WRITE_SIZE);
{
ssize_t ret = m_device->sendBytes(buffer, nbytes);
if (ret>0 && m_logRaw == true && m_logRawFunc != NULL)
(*m_logRawFunc)(buffer[0], false);
return ret;
}
/** /**
* @brief recv read bytes from opened file descriptor. * @brief recv read bytes from opened file descriptor.
@@ -255,13 +249,7 @@ public:
* @param buffer optional direct buffer to write to (instead of queuing the data). * @param buffer optional direct buffer to write to (instead of queuing the data).
* @return number of read bytes (never 0) or a negative result_t code. * @return number of read bytes (never 0) or a negative result_t code.
*/ */
ssize_t recv(const long timeout, size_t maxCount = MAX_READ_SIZE, unsigned char* buffer=NULL) ssize_t recv(const long timeout, size_t maxCount = MAX_READ_SIZE, unsigned char* buffer = NULL);
{
ssize_t ret = m_device->recvBytes(timeout, maxCount, buffer);
if (buffer && ret>0 && m_logRaw == true && m_logRawFunc != NULL)
(*m_logRawFunc)(buffer[0], true);
return ret;
}
/** /**
* @brief fetch first byte from receive buffer. * @brief fetch first byte from receive buffer.
Executable → Regular
View File
+140 -140
View File
@@ -44,145 +44,145 @@ int main()
{ {
string checks[][5] = { string checks[][5] = {
//name;[len];type[;[divisor|values][;[unit][;[comment]]]], decoded value, master, slave, flags //name;[len];type[;[divisor|values][;[unit][;[comment]]]], decoded value, master, slave, flags
{"x;;ign:10", "", "10fe07000a00000000000000000000", "00", ""}, {"x,,ign:10", "", "10fe07000a00000000000000000000", "00", ""},
{"x;;str:10", "Hallo, Du!", "10fe07000a48616c6c6f2c20447521", "00", ""}, {"x,,str:10", "Hallo, Du!", "10fe07000a48616c6c6f2c20447521", "00", ""},
{"x;;str:10", "Hallo, Du!", "10fe07000a48616c6c6f2c20447521", "00", ""}, {"x,,str:10", "Hallo, Du!", "10fe07000a48616c6c6f2c20447521", "00", ""},
{"x;;str:10", "Hallo, Du ", "10fe07000a48616c6c6f2c20447520", "00", ""}, {"x,,str:10", "Hallo, Du ", "10fe07000a48616c6c6f2c20447520", "00", ""},
{"x;;str:10", " ", "10fe07000a20202020202020202020", "00", ""}, {"x,,str:10", " ", "10fe07000a20202020202020202020", "00", ""},
{"x;;str:11", "", "10fe07000a20202020202020202020", "00", "rW"}, {"x,,str:11", "", "10fe07000a20202020202020202020", "00", "rW"},
{"x;;hex", "20", "10fe07000120", "00", ""}, {"x,,hex", "20", "10fe07000120", "00", ""},
{"x;;hex:10", "48 61 6c 6c 6f 2c 20 44 75 21", "10fe07000a48616c6c6f2c20447521", "00", ""}, {"x,,hex:10", "48 61 6c 6c 6f 2c 20 44 75 21", "10fe07000a48616c6c6f2c20447521", "00", ""},
{"x;;hex:11", "", "10fe07000a48616c6c6f2c20447521", "00", "rW"}, {"x,,hex:11", "", "10fe07000a48616c6c6f2c20447521", "00", "rW"},
{"x;;bda", "26.10.2014","10fe07000426100614", "00", ""}, // Sunday {"x,,bda", "26.10.2014","10fe07000426100614", "00", ""}, // Sunday
{"x;;hda", "26.10.2014","10fe07000426100714", "00", ""}, // Sunday {"x,,hda", "26.10.2014","10fe07000426100714", "00", ""}, // Sunday
{"x;;bda", "01.01.2000","10fe07000401010500", "00", ""}, // Saturday {"x,,bda", "01.01.2000","10fe07000401010500", "00", ""}, // Saturday
{"x;;hda", "01.01.2000","10fe07000401010600", "00", ""}, // Saturday {"x,,hda", "01.01.2000","10fe07000401010600", "00", ""}, // Saturday
{"x;;bda", "31.12.2099","10fe07000431120399", "00", ""}, // Thursday {"x,,bda", "31.12.2099","10fe07000431120399", "00", ""}, // Thursday
{"x;;hda", "31.12.2099","10fe07000431120499", "00", ""}, // Thursday {"x,,hda", "31.12.2099","10fe07000431120499", "00", ""}, // Thursday
{"x;;bda", "", "10fe07000432100014", "00", "rw"}, {"x,,bda", "", "10fe07000432100014", "00", "rw"},
{"x;;bda:3", "26.10.2014","10fe070003261014", "00", ""}, {"x,,bda:3", "26.10.2014","10fe070003261014", "00", ""},
{"x;;bda:3", "01.01.2000","10fe070003010100", "00", ""}, {"x,,bda:3", "01.01.2000","10fe070003010100", "00", ""},
{"x;;bda:3", "31.12.2099","10fe070003311299", "00", ""}, {"x,,bda:3", "31.12.2099","10fe070003311299", "00", ""},
{"x;;bda:3", "", "10fe070003321299", "00", "rw"}, {"x,,bda:3", "", "10fe070003321299", "00", "rw"},
{"x;;bti", "21:04:58", "10fe070003580421", "00", ""}, {"x,,bti", "21:04:58", "10fe070003580421", "00", ""},
{"x;;bti", "00:00:00", "10fe070003000000", "00", ""}, {"x,,bti", "00:00:00", "10fe070003000000", "00", ""},
{"x;;bti", "23:59:59", "10fe070003595923", "00", ""}, {"x,,bti", "23:59:59", "10fe070003595923", "00", ""},
{"x;;bti", "", "10fe070003605923", "00", "rw"}, {"x,,bti", "", "10fe070003605923", "00", "rw"},
{"x;;hti", "21:04:58", "10fe07000315043a", "00", ""}, {"x,,hti", "21:04:58", "10fe07000315043a", "00", ""},
{"x;;vti", "21:04:58", "10fe0700033a0415", "00", ""}, {"x,,vti", "21:04:58", "10fe0700033a0415", "00", ""},
{"x;;vti", "-:-:-", "10fe070003636363", "00", ""}, {"x,,vti", "-:-:-", "10fe070003636363", "00", ""},
{"x;;htm", "21:04", "10fe0700021504", "00", ""}, {"x,,htm", "21:04", "10fe0700021504", "00", ""},
{"x;;htm", "00:00", "10fe0700020000", "00", ""}, {"x,,htm", "00:00", "10fe0700020000", "00", ""},
{"x;;htm", "23:59", "10fe070002173b", "00", ""}, {"x,,htm", "23:59", "10fe070002173b", "00", ""},
{"x;;htm", "24:00", "10fe0700021800", "00", ""}, {"x,,htm", "24:00", "10fe0700021800", "00", ""},
{"x;;htm", "", "10fe070002183b", "00", "rw"}, {"x,,htm", "", "10fe070002183b", "00", "rw"},
{"x;;htm", "24:01", "10fe0700021801", "00", "rw"}, {"x,,htm", "24:01", "10fe0700021801", "00", "rw"},
{"x;;ttm", "22:40", "10fe07000188", "00", ""}, {"x,,ttm", "22:40", "10fe07000188", "00", ""},
{"x;;ttm", "00:00", "10fe07000100", "00", ""}, {"x,,ttm", "00:00", "10fe07000100", "00", ""},
{"x;;ttm", "23:50", "10fe0700018f", "00", ""}, {"x,,ttm", "23:50", "10fe0700018f", "00", ""},
{"x;;ttm", "-:-", "10fe07000190", "00", ""}, {"x,,ttm", "-:-", "10fe07000190", "00", ""},
{"x;;ttm", "", "10fe07000191", "00", "rw"}, {"x,,ttm", "", "10fe07000191", "00", "rw"},
{"x;;bdy", "Mon", "10fe07000300", "00", ""}, {"x,,bdy", "Mon", "10fe07000300", "00", ""},
{"x;;bdy", "Sun", "10fe07000306", "00", ""}, {"x,,bdy", "Sun", "10fe07000306", "00", ""},
{"x;;bdy", "", "10fe07000308", "00", "rw"}, {"x,,bdy", "", "10fe07000308", "00", "rw"},
{"x;;hdy", "Mon", "10fe07000301", "00", ""}, {"x,,hdy", "Mon", "10fe07000301", "00", ""},
{"x;;hdy", "Sun", "10fe07000307", "00", ""}, {"x,,hdy", "Sun", "10fe07000307", "00", ""},
{"x;;hdy", "", "10fe07000308", "00", "rw"}, {"x,,hdy", "", "10fe07000308", "00", "rw"},
{"x;;bcd", "26", "10feffff0126", "00", ""}, {"x,,bcd", "26", "10feffff0126", "00", ""},
{"x;;bcd", "0", "10feffff0100", "00", ""}, {"x,,bcd", "0", "10feffff0100", "00", ""},
{"x;;bcd", "99", "10feffff0199", "00", ""}, {"x,,bcd", "99", "10feffff0199", "00", ""},
{"x;;bcd", "-", "10feffff01ff", "00", ""}, {"x,,bcd", "-", "10feffff01ff", "00", ""},
{"x;;bcd", "", "10feffff019a", "00", "rw"}, {"x,,bcd", "", "10feffff019a", "00", "rw"},
{"x;;str:16", "0123456789ABCDEF", "10feffff1130313233343536373839414243444546", "00", ""}, {"x,,str:16", "0123456789ABCDEF", "10feffff1130313233343536373839414243444546", "00", ""},
{"x;;uch:17", "", "10feffff00", "00", "c"}, {"x,,uch:17", "", "10feffff00", "00", "c"},
{"x;s;uch", "0", "1025ffff0310111213", "0300010203", "W"}, {"x,s,uch", "0", "1025ffff0310111213", "0300010203", "W"},
{"x;s;uch", "0", "1025ffff00", "0100", ""}, {"x,s,uch", "0", "1025ffff00", "0100", ""},
{"x;s;uch;;;;y;m;uch", "3;2","1025ffff0103", "0102", ""}, {"x,s,uch,,,,y,m,uch", "3;2","1025ffff0103", "0102", ""},
{"x;;uch", "38", "10feffff0126", "00", ""}, {"x,,uch", "38", "10feffff0126", "00", ""},
{"x;;uch", "0", "10feffff0100", "00", ""}, {"x,,uch", "0", "10feffff0100", "00", ""},
{"x;;uch", "254", "10feffff01fe", "00", ""}, {"x,,uch", "254", "10feffff01fe", "00", ""},
{"x;;uch", "-", "10feffff01ff", "00", ""}, {"x,,uch", "-", "10feffff01ff", "00", ""},
{"x;;sch", "-90", "10feffff01a6", "00", ""}, {"x,,sch", "-90", "10feffff01a6", "00", ""},
{"x;;sch", "0", "10feffff0100", "00", ""}, {"x,,sch", "0", "10feffff0100", "00", ""},
{"x;;sch", "-1", "10feffff01ff", "00", ""}, {"x,,sch", "-1", "10feffff01ff", "00", ""},
{"x;;sch", "-", "10feffff0180", "00", ""}, {"x,,sch", "-", "10feffff0180", "00", ""},
{"x;;sch", "-127", "10feffff0181", "00", ""}, {"x,,sch", "-127", "10feffff0181", "00", ""},
{"x;;sch", "127", "10feffff017f", "00", ""}, {"x,,sch", "127", "10feffff017f", "00", ""},
{"x;;d1b", "-90", "10feffff01a6", "00", ""}, {"x,,d1b", "-90", "10feffff01a6", "00", ""},
{"x;;d1b", "0", "10feffff0100", "00", ""}, {"x,,d1b", "0", "10feffff0100", "00", ""},
{"x;;d1b", "-1", "10feffff01ff", "00", ""}, {"x,,d1b", "-1", "10feffff01ff", "00", ""},
{"x;;d1b", "-", "10feffff0180", "00", ""}, {"x,,d1b", "-", "10feffff0180", "00", ""},
{"x;;d1b", "-127", "10feffff0181", "00", ""}, {"x,,d1b", "-127", "10feffff0181", "00", ""},
{"x;;d1b", "127", "10feffff017f", "00", ""}, {"x,,d1b", "127", "10feffff017f", "00", ""},
{"x;;d1c", "19.5", "10feffff0127", "00", ""}, {"x,,d1c", "19.5", "10feffff0127", "00", ""},
{"x;;d1c", "0.0", "10feffff0100", "00", ""}, {"x,,d1c", "0.0", "10feffff0100", "00", ""},
{"x;;d1c", "100.0", "10feffff01c8", "00", ""}, {"x,,d1c", "100.0", "10feffff01c8", "00", ""},
{"x;;d1c", "-", "10feffff01ff", "00", ""}, {"x,,d1c", "-", "10feffff01ff", "00", ""},
{"x;;uin", "38", "10feffff022600", "00", ""}, {"x,,uin", "38", "10feffff022600", "00", ""},
{"x;;uin", "0", "10feffff020000", "00", ""}, {"x,,uin", "0", "10feffff020000", "00", ""},
{"x;;uin", "65534", "10feffff02feff", "00", ""}, {"x,,uin", "65534", "10feffff02feff", "00", ""},
{"x;;uin", "-", "10feffff02ffff", "00", ""}, {"x,,uin", "-", "10feffff02ffff", "00", ""},
{"x;;sin", "-90", "10feffff02a6ff", "00", ""}, {"x,,sin", "-90", "10feffff02a6ff", "00", ""},
{"x;;sin", "0", "10feffff020000", "00", ""}, {"x,,sin", "0", "10feffff020000", "00", ""},
{"x;;sin", "-1", "10feffff02ffff", "00", ""}, {"x,,sin", "-1", "10feffff02ffff", "00", ""},
{"x;;sin", "-", "10feffff020080", "00", ""}, {"x,,sin", "-", "10feffff020080", "00", ""},
{"x;;sin", "-32767", "10feffff020180", "00", ""}, {"x,,sin", "-32767", "10feffff020180", "00", ""},
{"x;;sin", "32767", "10feffff02ff7f", "00", ""}, {"x,,sin", "32767", "10feffff02ff7f", "00", ""},
{"x;;flt", "-0.090", "10feffff02a6ff", "00", ""}, {"x,,flt", "-0.090", "10feffff02a6ff", "00", ""},
{"x;;flt", "0.000", "10feffff020000", "00", ""}, {"x,,flt", "0.000", "10feffff020000", "00", ""},
{"x;;flt", "-0.001", "10feffff02ffff", "00", ""}, {"x,,flt", "-0.001", "10feffff02ffff", "00", ""},
{"x;;flt", "-", "10feffff020080", "00", ""}, {"x,,flt", "-", "10feffff020080", "00", ""},
{"x;;flt","-32.767", "10feffff020180", "00", ""}, {"x,,flt","-32.767", "10feffff020180", "00", ""},
{"x;;flt", "32.767", "10feffff02ff7f", "00", ""}, {"x,,flt", "32.767", "10feffff02ff7f", "00", ""},
{"x;;d2b", "18.004", "10fe0700090112", "00", ""}, {"x,,d2b", "18.004", "10fe0700090112", "00", ""},
{"x;;d2b", "0.000", "10feffff020000", "00", ""}, {"x,,d2b", "0.000", "10feffff020000", "00", ""},
{"x;;d2b", "-0.004", "10feffff02ffff", "00", ""}, {"x,,d2b", "-0.004", "10feffff02ffff", "00", ""},
{"x;;d2b", "-", "10feffff020080", "00", ""}, {"x,,d2b", "-", "10feffff020080", "00", ""},
{"x;;d2b","-127.996","10feffff020180", "00", ""}, {"x,,d2b","-127.996","10feffff020180", "00", ""},
{"x;;d2b", "127.996","10feffff02ff7f", "00", ""}, {"x,,d2b", "127.996","10feffff02ff7f", "00", ""},
{"x;;d2c", "288.06", "10fe0700090112", "00", ""}, {"x,,d2c", "288.06", "10fe0700090112", "00", ""},
{"x;;d2c", "0.00", "10feffff020000", "00", ""}, {"x,,d2c", "0.00", "10feffff020000", "00", ""},
{"x;;d2c", "-0.06", "10feffff02ffff", "00", ""}, {"x,,d2c", "-0.06", "10feffff02ffff", "00", ""},
{"x;;d2c", "-", "10feffff020080", "00", ""}, {"x,,d2c", "-", "10feffff020080", "00", ""},
{"x;;d2c","-2047.94","10feffff020180", "00", ""}, {"x,,d2c","-2047.94","10feffff020180", "00", ""},
{"x;;d2c", "2047.94","10feffff02ff7f", "00", ""}, {"x,,d2c", "2047.94","10feffff02ff7f", "00", ""},
{"x;;ulg", "38", "10feffff0426000000", "00", ""}, {"x,,ulg", "38", "10feffff0426000000", "00", ""},
{"x;;ulg", "0", "10feffff0400000000", "00", ""}, {"x,,ulg", "0", "10feffff0400000000", "00", ""},
{"x;;ulg", "4294967294", "10feffff04feffffff", "00", ""}, {"x,,ulg", "4294967294", "10feffff04feffffff", "00", ""},
{"x;;ulg", "-", "10feffff04ffffffff", "00", ""}, {"x,,ulg", "-", "10feffff04ffffffff", "00", ""},
{"x;;slg", "-90", "10feffff04a6ffffff", "00", ""}, {"x,,slg", "-90", "10feffff04a6ffffff", "00", ""},
{"x;;slg", "0", "10feffff0400000000", "00", ""}, {"x,,slg", "0", "10feffff0400000000", "00", ""},
{"x;;slg", "-1", "10feffff04ffffffff", "00", ""}, {"x,,slg", "-1", "10feffff04ffffffff", "00", ""},
{"x;;bi3", "1", "10feffff0108", "00", ""}, {"x,,bi3", "1", "10feffff0108", "00", ""},
{"x;;bi3", "-", "10feffff0100", "00", ""}, {"x,,bi3", "-", "10feffff0100", "00", ""},
{"x;;bi3;0=off,1=on","on", "10feffff0108", "00", ""}, {"x,,bi3,0=off;1=on","on", "10feffff0108", "00", ""},
{"x;;bi3;0=off,1=on","off","10feffff0100", "00", ""}, {"x,,bi3,0=off;1=on","off","10feffff0100", "00", ""},
{"x;;bi3:2", "1", "10feffff0108", "00", ""}, {"x,,bi3:2", "1", "10feffff0108", "00", ""},
{"x;;bi3:2", "1", "10feffff01ef", "00", "W"}, {"x,,bi3:2", "1", "10feffff01ef", "00", "W"},
{"x;;bi3:2", "-", "10feffff0100", "00", ""}, {"x,,bi3:2", "-", "10feffff0100", "00", ""},
{"x;;bi3:2", "3", "10feffff0118", "00", ""}, {"x,,bi3:2", "3", "10feffff0118", "00", ""},
{"x;;bi3:2;1=on","on", "10feffff0108", "00", ""}, {"x,,bi3:2,1=on","on", "10feffff0108", "00", ""},
{"x;;bi3:2;1=on","-", "10feffff0100", "00", ""}, {"x,,bi3:2,1=on","-", "10feffff0100", "00", ""},
{"x;;bi3:2;0=off,1=on,2=auto,3=eco","auto", "10feffff0110", "00", ""}, {"x,,bi3:2,0=off;1=on;2=auto;3=eco","auto", "10feffff0110", "00", ""},
{"x;;bi3:2;0=off,1=on","on", "10feffff0108", "00", ""}, {"x,,bi3:2,0=off;1=on","on", "10feffff0108", "00", ""},
{"x;;bi3:2;0=off,1=on","off","10feffff0100", "00", ""}, {"x,,bi3:2,0=off;1=on","off","10feffff0100", "00", ""},
{"x;;uch;1=test,2=high,3=off,4=on","on","10feffff0104", "00", ""}, {"x,,uch,1=test;2=high;3=off;4=on","on","10feffff0104", "00", ""},
{"x;s;uch","3","1050ffff00", "0103", ""}, {"x,s,uch","3","1050ffff00", "0103", ""},
{"x;;d2b;;C;Aussentemperatur","x=18.004 C [Aussentemperatur]","10fe0700090112", "00", "v"}, {"x,,d2b,,°C,Aussentemperatur","x=18.004 °C [Aussentemperatur]","10fe0700090112", "00", "v"},
{"x;;bti;;;;y;;bda;;;;z;;bdy", "21:04:58;26.10.2014;Sun","10fe0700085804212610061406", "00", ""}, // combination {"x,,bti,,,,y,,bda,,,,z,,bdy", "21:04:58;26.10.2014;Sun","10fe0700085804212610061406", "00", ""}, // combination
{"x;;bi3;;;;y;;bi5", "1;-", "10feffff0108", "00", ""}, // bit combination {"x,,bi3,,,,y,,bi5", "1;-", "10feffff0108", "00", ""}, // bit combination
{"x;;bi3;;;;y;;bi5", "1;1", "10feffff0128", "00", ""}, // bit combination {"x,,bi3,,,,y,,bi5", "1;1", "10feffff0128", "00", ""}, // bit combination
{"x;;bi3;;;;y;;bi5", "-;1", "10feffff0120", "00", ""}, // bit combination {"x,,bi3,,,,y,,bi5", "-;1", "10feffff0120", "00", ""}, // bit combination
{"x;;bi3;;;;y;;bi5", "-;-", "10feffff0100", "00", ""}, // bit combination {"x,,bi3,,,,y,,bi5", "-;-", "10feffff0100", "00", ""}, // bit combination
{"x;;bi3;;;;y;;bi7;;;;t;;uch", "-;-;9","10feffff020009", "00", ""}, // bit combination {"x,,bi3,,,,y,,bi7,,,,t,,uch", "-;-;9","10feffff020009", "00", ""}, // bit combination
{"x;;bi6:2;;;;y;;bi0:2;;;;t;;uch", "2;1;9","10feffff03800109", "00", ""}, // bit combination {"x,,bi6:2,,,,y,,bi0:2,,,,t,,uch", "2;1;9","10feffff03800109", "00", ""}, // bit combination
{"temp;;d2b;;C;Aussentemperatur","","", "", "t"}, // template with relative pos {"temp,,d2b,,°C,Aussentemperatur","","", "", "t"}, // template with relative pos
{"x;;temp","18.004","10fe0700020112", "00", ""}, // reference to template {"x,,temp","18.004","10fe0700020112", "00", ""}, // reference to template
{"relrel;;d2b;;;;y;;d1c","","", "", "t"}, // template struct with relative pos {"relrel,,d2b,,,,y,,d1c","","", "", "t"}, // template struct with relative pos
{"x;;relrel","18.004;9.5","10fe070003011213", "00", ""}, // reference to template struct {"x,,relrel","18.004;9.5","10fe070003011213", "00", ""}, // reference to template struct
{"trelrel;;temp,temp","","", "", "t"}, // template struct with relative pos and ref to templates {"trelrel,,temp;temp","","", "", "t"}, // template struct with relative pos and ref to templates
{"x;;trelrel","18.004;19.008","10fe07000401120213", "00", ""}, // reference to template struct {"x,,trelrel","18.004;19.008","10fe07000401120213", "00", ""}, // reference to template struct
{"x;;temp;;;;y;;d1c","18.004;9.5","10fe070003011213", "00", ""}, // reference to template, normal def {"x,,temp,,,,y,,d1c","18.004;9.5","10fe070003011213", "00", ""}, // reference to template, normal def
}; };
DataFieldTemplates* templates = new DataFieldTemplates(); DataFieldTemplates* templates = new DataFieldTemplates();
DataField* fields = NULL; DataField* fields = NULL;
@@ -204,7 +204,7 @@ int main()
string item; string item;
vector<string> entries; vector<string> entries;
while (getline(isstr, item, ';') != 0) while (getline(isstr, item, FIELD_SEPARATOR) != 0)
entries.push_back(item); entries.push_back(item);
if (fields != NULL) { if (fields != NULL) {
+9 -9
View File
@@ -47,14 +47,14 @@ 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", "fffe07000426100614", "00", "p"}, {"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"}, {"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,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"}, {"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",""},
{"","no;25","10feb505042700190023","",""}, //{"","no;25","10feb505042700190023","",""},
}; };
DataFieldTemplates* templates = new DataFieldTemplates(); DataFieldTemplates* templates = new DataFieldTemplates();
result_t result = templates->readFromFile("_types.csv"); result_t result = templates->readFromFile("_types.csv");
@@ -64,7 +64,7 @@ int main()
cout << "read templates error: " << getResultCode(result) << endl; cout << "read templates error: " << getResultCode(result) << endl;
MessageMap* messages = new MessageMap(); MessageMap* messages = new MessageMap();
result = messages->readFromFile("neu-ehp00.csv", templates); result = messages->readFromFile("ehp00.csv", templates);
if (result == RESULT_OK) if (result == RESULT_OK)
cout << "read messages OK" << endl; cout << "read messages OK" << endl;
else else
@@ -86,7 +86,7 @@ int main()
string item; string item;
vector<string> entries; vector<string> entries;
while (getline(isstr, item, ';') != 0) while (getline(isstr, item, FIELD_SEPARATOR) != 0)
entries.push_back(item); entries.push_back(item);
if (deleteMessage != NULL) { if (deleteMessage != NULL) {
Executable → Regular
View File
Executable → Regular
View File