code style

This commit is contained in:
john30
2017-01-14 13:00:04 +01:00
parent d13b271a05
commit b3bb2e08ac
49 changed files with 1853 additions and 1858 deletions
+145 -148
View File
@@ -16,22 +16,23 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "bushandler.h" #include "bushandler.h"
#include <unistd.h>
#include <time.h>
#include <string>
#include <vector>
#include <deque>
#include <cstring>
#include <iomanip>
#include "message.h" #include "message.h"
#include "data.h" #include "data.h"
#include "result.h" #include "result.h"
#include "symbol.h" #include "symbol.h"
#include "log.h" #include "log.h"
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <unistd.h>
#include <string>
#include <vector>
#include <deque>
#include <cstring>
#include <time.h>
#include <iomanip>
using namespace std; using namespace std;
@@ -62,17 +63,16 @@ const char* getStateCode(BusState state) {
} }
} }
result_t PollRequest::prepare(unsigned char ownMasterAddress) result_t PollRequest::prepare(unsigned char ownMasterAddress) {
{
istringstream input; istringstream input;
result_t result = m_message->prepareMaster(ownMasterAddress, m_master, input, UI_FIELD_SEPARATOR, SYN, m_index); result_t result = m_message->prepareMaster(ownMasterAddress, m_master, input, UI_FIELD_SEPARATOR, SYN, m_index);
if (result == RESULT_OK) if (result == RESULT_OK) {
logInfo(lf_bus, "poll cmd: %s", m_master.getDataStr().c_str()); logInfo(lf_bus, "poll cmd: %s", m_master.getDataStr().c_str());
}
return result; return result;
} }
bool PollRequest::notify(result_t result, SymbolString& slave) bool PollRequest::notify(result_t result, SymbolString& slave) {
{
if (result == RESULT_OK) { if (result == RESULT_OK) {
result = m_message->storeLastData(pt_slaveData, slave, m_index); result = m_message->storeLastData(pt_slaveData, slave, m_index);
if (result >= RESULT_OK && m_index+1 < m_message->getCount()) { if (result >= RESULT_OK && m_index+1 < m_message->getCount()) {
@@ -84,34 +84,35 @@ bool PollRequest::notify(result_t result, SymbolString& slave)
} }
} }
ostringstream output; ostringstream output;
if (result==RESULT_OK) if (result == RESULT_OK) {
result = m_message->decodeLastData(output); // decode data result = m_message->decodeLastData(output); // decode data
if (result < RESULT_OK) }
if (result < RESULT_OK) {
logError(lf_bus, "poll %s %s failed: %s", m_message->getCircuit().c_str(), m_message->getName().c_str(), getResultCode(result)); logError(lf_bus, "poll %s %s failed: %s", m_message->getCircuit().c_str(), m_message->getName().c_str(), getResultCode(result));
else } else {
logNotice(lf_bus, "poll %s %s: %s", m_message->getCircuit().c_str(), m_message->getName().c_str(), output.str().c_str()); logNotice(lf_bus, "poll %s %s: %s", m_message->getCircuit().c_str(), m_message->getName().c_str(), output.str().c_str());
}
return false; return false;
} }
result_t ScanRequest::prepare(unsigned char ownMasterAddress) result_t ScanRequest::prepare(unsigned char ownMasterAddress) {
{ if (m_slaves.empty()) {
if (m_slaves.empty())
return RESULT_ERR_EOF; return RESULT_ERR_EOF;
}
unsigned char dstAddress = m_slaves.front(); unsigned char dstAddress = m_slaves.front();
if (m_index==0 && m_messages.size()==m_allMessages.size()) // first message for this address if (m_index == 0 && m_messages.size() == m_allMessages.size()) { // first message for this address
m_busHandler->setScanResult(dstAddress, ""); m_busHandler->setScanResult(dstAddress, "");
}
istringstream input; istringstream input;
result_t result = m_message->prepareMaster(ownMasterAddress, m_master, input, UI_FIELD_SEPARATOR, dstAddress, m_index); result_t result = m_message->prepareMaster(ownMasterAddress, m_master, input, UI_FIELD_SEPARATOR, dstAddress, m_index);
if (result >= RESULT_OK) if (result >= RESULT_OK) {
logInfo(lf_bus, "scan %2.2x cmd: %s", dstAddress, m_master.getDataStr().c_str()); logInfo(lf_bus, "scan %2.2x cmd: %s", dstAddress, m_master.getDataStr().c_str());
}
return result; return result;
} }
bool ScanRequest::notify(result_t result, SymbolString& slave) bool ScanRequest::notify(result_t result, SymbolString& slave) {
{
unsigned char dstAddress = m_master[1]; unsigned char dstAddress = m_master[1];
if (result == RESULT_OK) { if (result == RESULT_OK) {
if (m_message == m_messageMap->getScanMessage()) { if (m_message == m_messageMap->getScanMessage()) {
@@ -129,28 +130,33 @@ bool ScanRequest::notify(result_t result, SymbolString& slave)
if (result >= RESULT_OK && m_index+1 < m_message->getCount()) { if (result >= RESULT_OK && m_index+1 < m_message->getCount()) {
m_index++; m_index++;
result = prepare(m_master[0]); result = prepare(m_master[0]);
if (result >= RESULT_OK) if (result >= RESULT_OK) {
return true; return true;
} }
if (result==RESULT_OK) }
if (result == RESULT_OK) {
result = m_message->decodeLastData(m_scanResult, 0, true); // decode data result = m_message->decodeLastData(m_scanResult, 0, true); // decode data
} }
}
if (result < RESULT_OK) { if (result < RESULT_OK) {
if (!m_slaves.empty()) if (!m_slaves.empty()) {
m_slaves.pop_front(); m_slaves.pop_front();
if (result == RESULT_ERR_TIMEOUT) }
if (result == RESULT_ERR_TIMEOUT) {
logNotice(lf_bus, "scan %2.2x timed out (%d slaves left)", dstAddress, m_slaves.size()); logNotice(lf_bus, "scan %2.2x timed out (%d slaves left)", dstAddress, m_slaves.size());
else } else {
logError(lf_bus, "scan %2.2x failed (%d slaves left): %s", dstAddress, m_slaves.size(), getResultCode(result)); logError(lf_bus, "scan %2.2x failed (%d slaves left): %s", dstAddress, m_slaves.size(), getResultCode(result));
}
m_messages.clear(); // skip remaining secondary messages m_messages.clear(); // skip remaining secondary messages
} else if (m_messages.empty()) { } else if (m_messages.empty()) {
if (!m_slaves.empty()) if (!m_slaves.empty()) {
m_slaves.pop_front(); m_slaves.pop_front();
}
logNotice(lf_bus, "scan %2.2x completed (%d slaves left)", dstAddress, m_slaves.size()); logNotice(lf_bus, "scan %2.2x completed (%d slaves left)", dstAddress, m_slaves.size());
} }
if (m_messages.empty()) // last message for this address if (m_messages.empty()) { // last message for this address
m_busHandler->setScanResult(dstAddress, m_scanResult.str()); m_busHandler->setScanResult(dstAddress, m_scanResult.str());
}
if (m_slaves.empty()) { if (m_slaves.empty()) {
logNotice(lf_bus, "scan finished"); logNotice(lf_bus, "scan finished");
m_busHandler->setScanFinished(); m_busHandler->setScanFinished();
@@ -172,19 +178,16 @@ bool ScanRequest::notify(result_t result, SymbolString& slave)
} }
bool ActiveBusRequest::notify(result_t result, SymbolString& slave) bool ActiveBusRequest::notify(result_t result, SymbolString& slave) {
{ if (result == RESULT_OK) {
if (result == RESULT_OK)
logDebug(lf_bus, "read res: %s", slave.getDataStr().c_str()); logDebug(lf_bus, "read res: %s", slave.getDataStr().c_str());
}
m_result = result; m_result = result;
m_slave.addAll(slave, true); m_slave.addAll(slave, true);
return false; return false;
} }
void GrabbedMessage::setLastData(SymbolString& master, SymbolString& slave) void GrabbedMessage::setLastData(SymbolString& master, SymbolString& slave) {
{
m_lastMaster.clear(false); m_lastMaster.clear(false);
m_lastMaster.addAll(master); m_lastMaster.addAll(master);
m_lastSlave.clear(false); m_lastSlave.clear(false);
@@ -192,8 +195,7 @@ void GrabbedMessage::setLastData(SymbolString& master, SymbolString& slave)
m_count++; m_count++;
} }
bool GrabbedMessage::dump(const bool unknown, MessageMap* messages, bool first, ostringstream& output) bool GrabbedMessage::dump(const bool unknown, MessageMap* messages, bool first, ostringstream& output) {
{
Message* message = messages->find(m_lastMaster); Message* message = messages->find(m_lastMaster);
if (unknown && message) { if (unknown && message) {
return false; return false;
@@ -214,15 +216,13 @@ bool GrabbedMessage::dump(const bool unknown, MessageMap* messages, bool first,
} }
void BusHandler::clear() void BusHandler::clear() {
{
memset(m_seenAddresses, 0, sizeof(m_seenAddresses)); memset(m_seenAddresses, 0, sizeof(m_seenAddresses));
m_masterCount = 1; m_masterCount = 1;
m_scanResults.clear(); m_scanResults.clear();
} }
result_t BusHandler::sendAndWait(SymbolString& master, SymbolString& slave) result_t BusHandler::sendAndWait(SymbolString& master, SymbolString& slave) {
{
result_t result = RESULT_ERR_NO_SIGNAL; result_t result = RESULT_ERR_NO_SIGNAL;
slave.clear(); slave.clear();
ActiveBusRequest request(master, slave); ActiveBusRequest request(master, slave);
@@ -232,11 +232,11 @@ result_t BusHandler::sendAndWait(SymbolString& master, SymbolString& slave)
m_nextRequests.push(&request); m_nextRequests.push(&request);
bool success = m_finishedRequests.remove(&request, true); bool success = m_finishedRequests.remove(&request, true);
result = success ? request.m_result : RESULT_ERR_TIMEOUT; result = success ? request.m_result : RESULT_ERR_TIMEOUT;
if (result == RESULT_OK) { if (result == RESULT_OK) {
Message* message = m_messages->find(master); Message* message = m_messages->find(master);
if (message != NULL) if (message != NULL) {
m_messages->invalidateCache(message); m_messages->invalidateCache(message);
}
break; break;
} }
if (!success || result == RESULT_ERR_NO_SIGNAL || result == RESULT_ERR_SEND || result == RESULT_ERR_DEVICE) { if (!success || result == RESULT_ERR_NO_SIGNAL || result == RESULT_ERR_SEND || result == RESULT_ERR_DEVICE) {
@@ -244,15 +244,12 @@ result_t BusHandler::sendAndWait(SymbolString& master, SymbolString& slave)
break; break;
} }
logError(lf_bus, "send to %2.2x: %s%s", master[1], getResultCode(result), sendRetries > 0 ? ", retry" : ""); logError(lf_bus, "send to %2.2x: %s%s", master[1], getResultCode(result), sendRetries > 0 ? ", retry" : "");
request.m_busLostRetries = 0; request.m_busLostRetries = 0;
} }
return result; return result;
} }
result_t BusHandler::readFromBus(Message* message, string inputStr, const unsigned char dstAddress) result_t BusHandler::readFromBus(Message* message, string inputStr, const unsigned char dstAddress) {
{
result_t ret = RESULT_EMPTY; result_t ret = RESULT_EMPTY;
SymbolString master(true); SymbolString master(true);
SymbolString slave(false); SymbolString slave(false);
@@ -278,16 +275,16 @@ result_t BusHandler::readFromBus(Message* message, string inputStr, const unsign
return ret; return ret;
} }
void BusHandler::run() void BusHandler::run() {
{
unsigned int symCount = 0; unsigned int symCount = 0;
time_t lastTime; time_t lastTime;
time(&lastTime); time(&lastTime);
do { do {
if (m_device->isValid() && !m_reconnect) { if (m_device->isValid() && !m_reconnect) {
result_t result = handleSymbol(); result_t result = handleSymbol();
if (result != RESULT_ERR_TIMEOUT) if (result != RESULT_ERR_TIMEOUT) {
symCount++; symCount++;
}
time_t now; time_t now;
time(&now); time(&now);
if (now > lastTime) { if (now > lastTime) {
@@ -318,8 +315,7 @@ void BusHandler::run()
} while (isRunning()); } while (isRunning());
} }
result_t BusHandler::handleSymbol() result_t BusHandler::handleSymbol() {
{
long timeout = SYN_TIMEOUT; long timeout = SYN_TIMEOUT;
unsigned char sendSymbol = ESC; unsigned char sendSymbol = ESC;
bool sending = false; bool sending = false;
@@ -373,10 +369,11 @@ result_t BusHandler::handleSymbol()
break; break;
case bs_recvRes: case bs_recvRes:
if (m_response.size() > 0 || m_slaveRecvTimeout > SYN_TIMEOUT) if (m_response.size() > 0 || m_slaveRecvTimeout > SYN_TIMEOUT) {
timeout = m_slaveRecvTimeout; timeout = m_slaveRecvTimeout;
else } else {
timeout = SYN_TIMEOUT; timeout = SYN_TIMEOUT;
}
break; break;
case bs_recvResAck: case bs_recvResAck:
@@ -422,10 +419,11 @@ result_t BusHandler::handleSymbol()
if (sending) { if (sending) {
result = m_device->send(sendSymbol); result = m_device->send(sendSymbol);
if (result == RESULT_OK) { if (result == RESULT_OK) {
if (m_state == bs_ready) if (m_state == bs_ready) {
timeout = m_transferLatency+m_busAcquireTimeout; timeout = m_transferLatency+m_busAcquireTimeout;
else } else {
timeout = m_transferLatency+SEND_TIMEOUT; timeout = m_transferLatency+SEND_TIMEOUT;
}
} else { } else {
sending = false; sending = false;
timeout = SYN_TIMEOUT; timeout = SYN_TIMEOUT;
@@ -450,9 +448,9 @@ result_t BusHandler::handleSymbol()
if (result == RESULT_ERR_TIMEOUT) { if (result == RESULT_ERR_TIMEOUT) {
return setState(bs_noSignal, result); return setState(bs_noSignal, result);
} }
if (result != RESULT_OK) if (result != RESULT_OK) {
logError(lf_bus, "unable to receive sent AUTO-SYN symbol: %s", getResultCode(result)); logError(lf_bus, "unable to receive sent AUTO-SYN symbol: %s", getResultCode(result));
else if (recvSymbol != SYN) { } else if (recvSymbol != SYN) {
logError(lf_bus, "received %2.2x instead of AUTO-SYN symbol", recvSymbol); logError(lf_bus, "received %2.2x instead of AUTO-SYN symbol", recvSymbol);
} else { } else {
if (m_generateSynInterval != SYN_TIMEOUT) { if (m_generateSynInterval != SYN_TIMEOUT) {
@@ -473,19 +471,19 @@ result_t BusHandler::handleSymbol()
m_currentRequest = startRequest; // force the failed request to be notified m_currentRequest = startRequest; // force the failed request to be notified
} }
if ((m_generateSynInterval != SYN_TIMEOUT && difftime(now, m_lastReceive) > 1) // at least one full second has passed since last received symbol if ((m_generateSynInterval != SYN_TIMEOUT && difftime(now, m_lastReceive) > 1) // at least one full second has passed since last received symbol
|| m_state == bs_noSignal) || m_state == bs_noSignal) {
return setState(bs_noSignal, result); return setState(bs_noSignal, result);
}
return setState(bs_skip, result); return setState(bs_skip, result);
} }
m_lastReceive = now; m_lastReceive = now;
if ((recvSymbol == SYN) && (m_state != bs_sendSyn)) { if ((recvSymbol == SYN) && (m_state != bs_sendSyn)) {
if (!sending && m_remainLockCount > 0 && m_command.size() != 1) if (!sending && m_remainLockCount > 0 && m_command.size() != 1) {
m_remainLockCount--; m_remainLockCount--;
else if (!sending && m_remainLockCount == 0 && m_command.size() == 1) } else if (!sending && m_remainLockCount == 0 && m_command.size() == 1) {
m_remainLockCount = 1; // wait for next AUTO-SYN after SYN / address / SYN (bus locked for own priority) m_remainLockCount = 1; // wait for next AUTO-SYN after SYN / address / SYN (bus locked for own priority)
}
return setState(bs_ready, m_state == bs_skip ? RESULT_OK : RESULT_ERR_SYN); return setState(bs_ready, m_state == bs_skip ? RESULT_OK : RESULT_ERR_SYN);
} }
@@ -514,15 +512,16 @@ result_t BusHandler::handleSymbol()
} }
// arbitration lost. if same priority class found, try again after next AUTO-SYN // arbitration lost. if same priority class found, try again after next AUTO-SYN
m_remainLockCount = isMaster(recvSymbol) ? 2 : 1; // number of SYN to wait for before next send try m_remainLockCount = isMaster(recvSymbol) ? 2 : 1; // number of SYN to wait for before next send try
if ((recvSymbol & 0x0f) != (sendSymbol & 0x0f) && m_lockCount > m_remainLockCount) if ((recvSymbol & 0x0f) != (sendSymbol & 0x0f) && m_lockCount > m_remainLockCount) {
// if different priority class found, try again after N AUTO-SYN symbols (at least next AUTO-SYN) // if different priority class found, try again after N AUTO-SYN symbols (at least next AUTO-SYN)
m_remainLockCount = m_lockCount; m_remainLockCount = m_lockCount;
}
setState(m_state, RESULT_ERR_BUS_LOST); // try again later setState(m_state, RESULT_ERR_BUS_LOST); // try again later
} }
result = m_command.push_back(recvSymbol, false); // expect no escaping for master address result = m_command.push_back(recvSymbol, false); // expect no escaping for master address
if (result < RESULT_OK) if (result < RESULT_OK) {
return setState(bs_skip, result); return setState(bs_skip, result);
}
m_repeat = false; m_repeat = false;
return setState(bs_recvCmd, RESULT_OK); return setState(bs_recvCmd, RESULT_OK);
@@ -530,9 +529,9 @@ result_t BusHandler::handleSymbol()
headerLen = 4; headerLen = 4;
crcPos = m_command.size() > headerLen ? headerLen + 1 + m_command[headerLen] : 0xff; // header symbols are never escaped crcPos = m_command.size() > headerLen ? headerLen + 1 + m_command[headerLen] : 0xff; // header symbols are never escaped
result = m_command.push_back(recvSymbol, true, m_command.size() < crcPos); result = m_command.push_back(recvSymbol, true, m_command.size() < crcPos);
if (result < RESULT_OK) if (result < RESULT_OK) {
return setState(bs_skip, result); return setState(bs_skip, result);
}
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];
m_commandCrcValid = m_command[headerLen + 1 + m_command[headerLen]] == m_command.getCRC(); // header symbols are never escaped m_commandCrcValid = m_command[headerLen + 1 + m_command[headerLen]] == m_command.getCRC(); // header symbols are never escaped
@@ -542,36 +541,34 @@ result_t BusHandler::handleSymbol()
return setState(bs_skip, RESULT_OK); return setState(bs_skip, RESULT_OK);
} }
addSeenAddress(m_command[0]); addSeenAddress(m_command[0]);
if (m_answer if (m_answer && (dstAddress == m_ownMasterAddress || dstAddress == m_ownSlaveAddress)) {
&& (dstAddress == m_ownMasterAddress || dstAddress == m_ownSlaveAddress))
return setState(bs_sendCmdAck, RESULT_OK); 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_ERR_CRC); return setState(bs_skip, RESULT_ERR_CRC);
}
if (m_answer if (m_answer && (dstAddress == m_ownMasterAddress || dstAddress == m_ownSlaveAddress)) {
&& (dstAddress == m_ownMasterAddress || dstAddress == m_ownSlaveAddress)) {
return setState(bs_sendCmdAck, RESULT_ERR_CRC); return setState(bs_sendCmdAck, RESULT_ERR_CRC);
} }
if (m_repeat) if (m_repeat) {
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);
} }
return RESULT_OK; return RESULT_OK;
case bs_recvCmdAck: case bs_recvCmdAck:
if (recvSymbol == ACK) { if (recvSymbol == ACK) {
if (!m_commandCrcValid) if (!m_commandCrcValid) {
return setState(bs_skip, RESULT_ERR_ACK); return setState(bs_skip, RESULT_ERR_ACK);
}
if (m_currentRequest != NULL) { if (m_currentRequest != NULL) {
if (isMaster(m_currentRequest->m_master[1])) { if (isMaster(m_currentRequest->m_master[1])) {
return setState(bs_sendSyn, RESULT_OK); return setState(bs_sendSyn, RESULT_OK);
} }
} } else if (isMaster(m_command[1])) { // header symbols are never escaped
else if (isMaster(m_command[1])) { // header symbols are never escaped
receiveCompleted(); receiveCompleted();
return setState(bs_skip, RESULT_OK); return setState(bs_skip, RESULT_OK);
} }
@@ -584,50 +581,48 @@ result_t BusHandler::handleSymbol()
m_repeat = true; m_repeat = true;
m_nextSendPos = 0; m_nextSendPos = 0;
m_command.clear(); m_command.clear();
if (m_currentRequest != NULL) if (m_currentRequest != NULL) {
return setState(bs_sendCmd, RESULT_ERR_NAK, true); return setState(bs_sendCmd, RESULT_ERR_NAK, true);
}
return setState(bs_recvCmd, RESULT_ERR_NAK); return setState(bs_recvCmd, RESULT_ERR_NAK);
} }
return setState(bs_skip, RESULT_ERR_NAK); return setState(bs_skip, RESULT_ERR_NAK);
} }
return setState(bs_skip, RESULT_ERR_ACK); return setState(bs_skip, RESULT_ERR_ACK);
case bs_recvRes: case bs_recvRes:
headerLen = 0; headerLen = 0;
crcPos = m_response.size() > headerLen ? headerLen + 1 + m_response[headerLen] : 0xff; crcPos = m_response.size() > headerLen ? headerLen + 1 + m_response[headerLen] : 0xff;
result = m_response.push_back(recvSymbol, true, m_response.size() < crcPos); result = m_response.push_back(recvSymbol, true, m_response.size() < crcPos);
if (result < RESULT_OK) if (result < RESULT_OK) {
return setState(bs_skip, result); return setState(bs_skip, result);
}
if (result == RESULT_OK && crcPos != 0xff && m_response.size() == crcPos + 1) { // CRC received if (result == RESULT_OK && crcPos != 0xff && m_response.size() == crcPos + 1) { // CRC received
m_responseCrcValid = m_response[headerLen + 1 + m_response[headerLen]] == m_response.getCRC(); m_responseCrcValid = m_response[headerLen + 1 + m_response[headerLen]] == m_response.getCRC();
if (m_responseCrcValid) { if (m_responseCrcValid) {
if (m_currentRequest != NULL) if (m_currentRequest != NULL) {
return setState(bs_sendResAck, RESULT_OK); return setState(bs_sendResAck, RESULT_OK);
}
return setState(bs_recvResAck, RESULT_OK); return setState(bs_recvResAck, RESULT_OK);
} }
if (m_repeat) { if (m_repeat) {
if (m_currentRequest != NULL) if (m_currentRequest != NULL) {
return setState(bs_sendSyn, RESULT_ERR_CRC); return setState(bs_sendSyn, RESULT_ERR_CRC);
}
return setState(bs_skip, RESULT_ERR_CRC); return setState(bs_skip, RESULT_ERR_CRC);
} }
if (m_currentRequest != NULL) if (m_currentRequest != NULL) {
return setState(bs_sendResAck, RESULT_ERR_CRC); return setState(bs_sendResAck, RESULT_ERR_CRC);
}
return setState(bs_recvResAck, RESULT_ERR_CRC); return setState(bs_recvResAck, RESULT_ERR_CRC);
} }
return RESULT_OK; return RESULT_OK;
case bs_recvResAck: case bs_recvResAck:
if (recvSymbol == ACK) { if (recvSymbol == ACK) {
if (!m_responseCrcValid) if (!m_responseCrcValid) {
return setState(bs_skip, RESULT_ERR_ACK); return setState(bs_skip, RESULT_ERR_ACK);
}
receiveCompleted(); receiveCompleted();
return setState(bs_skip, RESULT_OK); return setState(bs_skip, RESULT_OK);
} }
@@ -647,9 +642,9 @@ result_t BusHandler::handleSymbol()
m_nextSendPos++; m_nextSendPos++;
if (m_nextSendPos >= m_currentRequest->m_master.size()) { if (m_nextSendPos >= m_currentRequest->m_master.size()) {
// master data completely sent // master data completely sent
if (m_currentRequest->m_master[1] == BROADCAST) if (m_currentRequest->m_master[1] == BROADCAST) {
return setState(bs_sendSyn, RESULT_OK); return setState(bs_sendSyn, RESULT_OK);
}
m_commandCrcValid = true; m_commandCrcValid = true;
return setState(bs_recvCmdAck, RESULT_OK); return setState(bs_recvCmdAck, RESULT_OK);
} }
@@ -695,20 +690,22 @@ result_t BusHandler::handleSymbol()
message = m_messages->find(m_command); message = m_messages->find(m_command);
if (message == NULL) { if (message == NULL) {
message = m_messages->find(m_command, true); message = m_messages->find(m_command, true);
if (message!=NULL && message->getSrcAddress()!=SYN) if (message != NULL && message->getSrcAddress() != SYN) {
message = NULL; message = NULL;
} }
if (message == NULL || message->isWrite()) }
if (message == NULL || message->isWrite()) {
return setState(bs_skip, RESULT_ERR_INVALID_ARG); // don't know this request or definition has wrong direction, deny return setState(bs_skip, RESULT_ERR_INVALID_ARG); // don't know this request or definition has wrong direction, deny
}
if (message == m_messages->getScanMessage(m_ownSlaveAddress)) { if (message == m_messages->getScanMessage(m_ownSlaveAddress)) {
input.str(SCAN_ANSWER); input.str(SCAN_ANSWER);
} }
// build response and store in m_response for sending back to requesting master // build response and store in m_response for sending back to requesting master
m_response.clear(true); // escape while sending response m_response.clear(true); // escape while sending response
result = message->prepareSlave(input, m_response); result = message->prepareSlave(input, m_response);
if (result != RESULT_OK) if (result != RESULT_OK) {
return setState(bs_skip, result); return setState(bs_skip, result);
}
return setState(bs_sendRes, RESULT_OK); return setState(bs_sendRes, RESULT_OK);
} }
return setState(bs_skip, RESULT_ERR_INVALID_ARG); return setState(bs_skip, RESULT_ERR_INVALID_ARG);
@@ -733,12 +730,10 @@ result_t BusHandler::handleSymbol()
return setState(bs_skip, RESULT_ERR_INVALID_ARG); return setState(bs_skip, RESULT_ERR_INVALID_ARG);
} }
return RESULT_OK; return RESULT_OK;
} }
result_t BusHandler::setState(BusState state, result_t result, bool firstRepetition) result_t BusHandler::setState(BusState state, result_t result, bool firstRepetition) {
{
if (m_currentRequest != NULL) { if (m_currentRequest != NULL) {
if (result == RESULT_ERR_BUS_LOST && m_currentRequest->m_busLostRetries < m_busLostRetries) { if (result == RESULT_ERR_BUS_LOST && m_currentRequest->m_busLostRetries < m_busLostRetries) {
logDebug(lf_bus, "%s during %s, retry", getResultCode(result), getStateCode(m_state)); logDebug(lf_bus, "%s during %s, retry", getResultCode(result), getStateCode(m_state));
@@ -808,8 +803,7 @@ result_t BusHandler::setState(BusState state, result_t result, bool firstRepetit
return result; return result;
} }
void BusHandler::addSeenAddress(unsigned char address) void BusHandler::addSeenAddress(unsigned char address) {
{
if (!isValidAddress(address, false)) { if (!isValidAddress(address, false)) {
return; return;
} }
@@ -843,8 +837,7 @@ void BusHandler::addSeenAddress(unsigned char address)
} }
} }
void BusHandler::receiveCompleted() void BusHandler::receiveCompleted() {
{
unsigned char srcAddress = m_command[0], dstAddress = m_command[1]; unsigned char srcAddress = m_command[0], dstAddress = m_command[1];
if (srcAddress == dstAddress) { if (srcAddress == dstAddress) {
logError(lf_bus, "invalid self-addressed message from %2.2x", srcAddress); logError(lf_bus, "invalid self-addressed message from %2.2x", srcAddress);
@@ -933,30 +926,32 @@ void BusHandler::receiveCompleted()
} }
} }
result_t BusHandler::startScan(bool full) result_t BusHandler::startScan(bool full) {
{
deque<Message*> messages = m_messages->findAll("scan", "", true); deque<Message*> messages = m_messages->findAll("scan", "", true);
for (deque<Message*>::iterator it = messages.begin(); it < messages.end(); it++) { for (deque<Message*>::iterator it = messages.begin(); it < messages.end(); it++) {
Message* message = *it; Message* message = *it;
if (message->getPrimaryCommand() == 0x07 && message->getSecondaryCommand() == 0x04) if (message->getPrimaryCommand() == 0x07 && message->getSecondaryCommand() == 0x04) {
messages.erase(it--); // query pb 0x07 / sb 0x04 only once messages.erase(it--); // query pb 0x07 / sb 0x04 only once
} }
}
Message* scanMessage = m_messages->getScanMessage(); Message* scanMessage = m_messages->getScanMessage();
if (scanMessage==NULL) if (scanMessage == NULL) {
return RESULT_ERR_NOTFOUND; return RESULT_ERR_NOTFOUND;
}
m_scanResults.clear(); m_scanResults.clear();
deque<unsigned char> slaves; deque<unsigned char> slaves;
for (unsigned char slave = 1; slave != 0; slave++) { // 0 is known to be a master for (unsigned char slave = 1; slave != 0; slave++) { // 0 is known to be a master
if (!isValidAddress(slave, false) || isMaster(slave)) if (!isValidAddress(slave, false) || isMaster(slave)) {
continue; continue;
}
if (!full && (m_seenAddresses[slave]&SEEN) == 0) { if (!full && (m_seenAddresses[slave]&SEEN) == 0) {
unsigned char master = getMasterAddress(slave); // check if we saw the corresponding master already unsigned char master = getMasterAddress(slave); // check if we saw the corresponding master already
if (master == SYN || (m_seenAddresses[master]&SEEN)==0) if (master == SYN || (m_seenAddresses[master]&SEEN) == 0) {
continue; continue;
} }
}
slaves.push_back(slave); slaves.push_back(slave);
} }
messages.push_front(scanMessage); messages.push_front(scanMessage);
@@ -971,8 +966,7 @@ result_t BusHandler::startScan(bool full)
return RESULT_OK; return RESULT_OK;
} }
void BusHandler::setScanResult(unsigned char dstAddress, string str) void BusHandler::setScanResult(unsigned char dstAddress, string str) {
{
m_seenAddresses[dstAddress] |= SCAN_INIT; m_seenAddresses[dstAddress] |= SCAN_INIT;
if (str.length() > 0) { if (str.length() > 0) {
m_seenAddresses[dstAddress] |= SCAN_DONE; m_seenAddresses[dstAddress] |= SCAN_DONE;
@@ -981,14 +975,13 @@ void BusHandler::setScanResult(unsigned char dstAddress, string str)
} }
} }
void BusHandler::setScanFinished() void BusHandler::setScanFinished() {
{ if (m_runningScans > 0) {
if (m_runningScans>0)
m_runningScans--; m_runningScans--;
} }
}
void BusHandler::formatScanResult(ostringstream& output) void BusHandler::formatScanResult(ostringstream& output) {
{
if (m_runningScans > 0) { if (m_runningScans > 0) {
output << static_cast<unsigned>(m_runningScans) << " scan(s) still running" << endl; output << static_cast<unsigned>(m_runningScans) << " scan(s) still running" << endl;
} }
@@ -996,10 +989,11 @@ void BusHandler::formatScanResult(ostringstream& output)
for (unsigned char slave = 1; slave != 0; slave++) { // 0 is known to be a master for (unsigned char slave = 1; slave != 0; slave++) { // 0 is known to be a master
map<unsigned char, string>::iterator it = m_scanResults.find(slave); map<unsigned char, string>::iterator it = m_scanResults.find(slave);
if (it != m_scanResults.end()) { if (it != m_scanResults.end()) {
if (first) if (first) {
first = false; first = false;
else } else {
output << endl; output << endl;
}
output << hex << setw(2) << setfill('0') << static_cast<unsigned>(slave) << it->second; output << hex << setw(2) << setfill('0') << static_cast<unsigned>(slave) << it->second;
} }
} }
@@ -1009,10 +1003,11 @@ void BusHandler::formatScanResult(ostringstream& output)
if (isValidAddress(slave, false) && !isMaster(slave) && (m_seenAddresses[slave]&SCAN_DONE) != 0) { if (isValidAddress(slave, false) && !isMaster(slave) && (m_seenAddresses[slave]&SCAN_DONE) != 0) {
Message* message = m_messages->getScanMessage(slave); Message* message = m_messages->getScanMessage(slave);
if (message != NULL && message->getLastUpdateTime() > 0) { if (message != NULL && message->getLastUpdateTime() > 0) {
if (first) if (first) {
first = false; first = false;
else } else {
output << endl; output << endl;
}
output << hex << setw(2) << setfill('0') << static_cast<unsigned>(slave); output << hex << setw(2) << setfill('0') << static_cast<unsigned>(slave);
message->decodeLastData(output, 0, true); message->decodeLastData(output, 0, true);
} }
@@ -1021,8 +1016,7 @@ void BusHandler::formatScanResult(ostringstream& output)
} }
} }
void BusHandler::formatSeenInfo(ostringstream& output) void BusHandler::formatSeenInfo(ostringstream& output) {
{
unsigned char address = 0; unsigned char address = 0;
for (int index = 0; index < 256; index++, address++) { for (int index = 0; index < 256; index++, address++) {
if (isValidAddress(address, false) if (isValidAddress(address, false)
@@ -1036,8 +1030,9 @@ void BusHandler::formatSeenInfo(ostringstream& output)
output << ": slave"; output << ": slave";
master = getMasterAddress(address); master = getMasterAddress(address);
} }
if (master != SYN) if (master != SYN) {
output << " #" << setw(0) << dec << static_cast<unsigned>(getMasterNumber(master)); output << " #" << setw(0) << dec << static_cast<unsigned>(getMasterNumber(master));
}
if (!m_device->isReadOnly() && (address == m_ownMasterAddress || address == m_ownSlaveAddress)) { if (!m_device->isReadOnly() && (address == m_ownMasterAddress || address == m_ownSlaveAddress)) {
output << ", ebusd"; output << ", ebusd";
if (m_answer) { if (m_answer) {
@@ -1062,16 +1057,17 @@ void BusHandler::formatSeenInfo(ostringstream& output)
} }
} }
string loadedFiles = m_messages->getLoadedFiles(address); string loadedFiles = m_messages->getLoadedFiles(address);
if (!loadedFiles.empty()) if (!loadedFiles.empty()) {
output << ", loaded " << loadedFiles; output << ", loaded " << loadedFiles;
} }
} }
} }
}
result_t BusHandler::scanAndWait(unsigned char dstAddress, SymbolString& slave) result_t BusHandler::scanAndWait(unsigned char dstAddress, SymbolString& slave) {
{ if (!isValidAddress(dstAddress) || isMaster(dstAddress)) {
if (!isValidAddress(dstAddress) || isMaster(dstAddress))
return RESULT_ERR_INVALID_ADDR; return RESULT_ERR_INVALID_ADDR;
}
m_seenAddresses[dstAddress] |= SCAN_INIT; m_seenAddresses[dstAddress] |= SCAN_INIT;
Message* scanMessage = m_messages->getScanMessage(); Message* scanMessage = m_messages->getScanMessage();
if (scanMessage == NULL) { if (scanMessage == NULL) {
@@ -1089,17 +1085,17 @@ result_t BusHandler::scanAndWait(unsigned char dstAddress, SymbolString& slave)
scanMessage->storeLastData(pt_masterData, master, 0); // update the cache, expected to work since this is a clone scanMessage->storeLastData(pt_masterData, master, 0); // update the cache, expected to work since this is a clone
} }
} }
if (result!=RESULT_ERR_NO_SIGNAL) if (result != RESULT_ERR_NO_SIGNAL) {
m_seenAddresses[dstAddress] |= SCAN_DONE; m_seenAddresses[dstAddress] |= SCAN_DONE;
} }
if (result != RESULT_OK || slave.size() == 0) // avoid "invalid position" during decode }
if (result != RESULT_OK || slave.size() == 0) { // avoid "invalid position" during decode
return result; return result;
}
return scanMessage->storeLastData(pt_slaveData, slave, 0); // update the cache return scanMessage->storeLastData(pt_slaveData, slave, 0); // update the cache
} }
bool BusHandler::enableGrab(bool enable) bool BusHandler::enableGrab(bool enable) {
{
if (enable == m_grabMessages) { if (enable == m_grabMessages) {
return false; return false;
} }
@@ -1110,8 +1106,7 @@ bool BusHandler::enableGrab(bool enable)
return true; return true;
} }
void BusHandler::formatGrabResult(const bool unknown, ostringstream& output) void BusHandler::formatGrabResult(const bool unknown, ostringstream& output) {
{
if (!m_grabMessages) { if (!m_grabMessages) {
output << "grab disabled"; output << "grab disabled";
} else { } else {
@@ -1125,11 +1120,13 @@ void BusHandler::formatGrabResult(const bool unknown, ostringstream& output)
} }
unsigned char BusHandler::getNextScanAddress(unsigned char lastAddress, bool& scanned) { unsigned char BusHandler::getNextScanAddress(unsigned char lastAddress, bool& scanned) {
if (lastAddress==SYN) if (lastAddress == SYN) {
return SYN; return SYN;
}
while (++lastAddress != 0) { // 0 is known to be a master while (++lastAddress != 0) { // 0 is known to be a master
if (!isValidAddress(lastAddress, false) || isMaster(lastAddress)) if (!isValidAddress(lastAddress, false) || isMaster(lastAddress)) {
continue; continue;
}
if ((m_seenAddresses[lastAddress]&(SEEN|LOAD_INIT)) == SEEN) { if ((m_seenAddresses[lastAddress]&(SEEN|LOAD_INIT)) == SEEN) {
scanned = (m_seenAddresses[lastAddress]&SCAN_INIT) != 0; scanned = (m_seenAddresses[lastAddress]&SCAN_INIT) != 0;
return lastAddress; return lastAddress;
+8 -7
View File
@@ -16,9 +16,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef BUSHANDLER_H_ #ifndef EBUSD_BUSHANDLER_H_
#define BUSHANDLER_H_ #define EBUSD_BUSHANDLER_H_
#include <pthread.h>
#include <string>
#include <vector>
#include <map>
#include <deque>
#include "message.h" #include "message.h"
#include "data.h" #include "data.h"
#include "symbol.h" #include "symbol.h"
@@ -26,10 +31,6 @@
#include "device.h" #include "device.h"
#include "queue.h" #include "queue.h"
#include "thread.h" #include "thread.h"
#include <string>
#include <vector>
#include <map>
#include <pthread.h>
/** @file bushandler.h /** @file bushandler.h
* Classes, functions, and constants related to handling of symbols on the eBUS. * Classes, functions, and constants related to handling of symbols on the eBUS.
@@ -666,4 +667,4 @@ private:
}; };
#endif // BUSHANDLER_H_ #endif // EBUSD_BUSHANDLER_H_
+6 -8
View File
@@ -16,11 +16,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "datahandler.h"
#include <list>
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
# include <config.h> # include <config.h>
#endif #endif
#include "datahandler.h"
#include <list>
#ifdef HAVE_MQTT #ifdef HAVE_MQTT
# include "mqtthandler.h" # include "mqtthandler.h"
#endif #endif
@@ -38,8 +39,7 @@ static struct argp_child g_argp_children[
+1 +1
]; ];
const struct argp_child* datahandler_getargs() const struct argp_child* datahandler_getargs() {
{
size_t count = 0; size_t count = 0;
#ifdef HAVE_MQTT #ifdef HAVE_MQTT
g_argp_children[count++] = *mqtthandler_getargs(); g_argp_children[count++] = *mqtthandler_getargs();
@@ -51,8 +51,7 @@ const struct argp_child* datahandler_getargs()
return NULL; return NULL;
} }
bool datahandler_register(BusHandler* busHandler, MessageMap* messages, list<DataHandler*>& handlers) bool datahandler_register(BusHandler* busHandler, MessageMap* messages, list<DataHandler*>& handlers) {
{
bool success = true; bool success = true;
#ifdef HAVE_MQTT #ifdef HAVE_MQTT
DataHandler* handler = mqtthandler_register(busHandler, messages); DataHandler* handler = mqtthandler_register(busHandler, messages);
@@ -65,7 +64,6 @@ bool datahandler_register(BusHandler* busHandler, MessageMap* messages, list<Dat
return success; return success;
} }
void DataSink::notifyUpdate(Message* message) void DataSink::notifyUpdate(Message* message) {
{
m_updatedMessages[message]++; m_updatedMessages[message]++;
} }
+6 -4
View File
@@ -16,12 +16,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef DATAHANDLER_H_ #ifndef EBUSD_DATAHANDLER_H_
#define DATAHANDLER_H_ #define EBUSD_DATAHANDLER_H_
#include <argp.h>
#include <map>
#include <list>
#include "bushandler.h" #include "bushandler.h"
#include "message.h" #include "message.h"
#include <argp.h>
/** @file datahandler.h /** @file datahandler.h
* Classes and functions for implementing and registering generic data sinks * Classes and functions for implementing and registering generic data sinks
@@ -148,4 +150,4 @@ protected:
}; };
#endif // DATAHANDLER_H_ #endif // EBUSD_DATAHANDLER_H_
+52 -54
View File
@@ -21,19 +21,22 @@
#endif #endif
#include "main.h" #include "main.h"
#include "mainloop.h" #include <dirent.h>
#include "bushandler.h" #include <sys/types.h>
#include "log.h" #include <sys/stat.h>
#include "rotatefile.h"
#include <stdlib.h> #include <stdlib.h>
#include <argp.h> #include <argp.h>
#include <csignal> #include <csignal>
#include <iostream> #include <iostream>
#include <algorithm> #include <algorithm>
#include <iomanip> #include <iomanip>
#include <dirent.h> #include <map>
#include <sys/types.h> #include <string>
#include <sys/stat.h> #include <vector>
#include "mainloop.h"
#include "bushandler.h"
#include "log.h"
#include "rotatefile.h"
/** the path and name of the PID file. */ /** the path and name of the PID file. */
#ifdef PACKAGE_PIDFILE #ifdef PACKAGE_PIDFILE
@@ -207,8 +210,7 @@ static map<string, DataFieldTemplates*> s_templatesByPath;
* @param arg the option argument, or NULL. * @param arg the option argument, or NULL.
* @param state the parsing state. * @param state the parsing state.
*/ */
error_t parse_opt(int key, char *arg, struct argp_state *state) error_t parse_opt(int key, char *arg, struct argp_state *state) {
{
struct options *opt = (struct options*)state->input; struct options *opt = (struct options*)state->input;
result_t result = RESULT_OK; result_t result = RESULT_OK;
@@ -278,8 +280,9 @@ error_t parse_opt(int key, char *arg, struct argp_state *state)
} }
break; break;
case O_CHKCFG: // --checkconfig case O_CHKCFG: // --checkconfig
if (opt->checkConfig==0) if (opt->checkConfig == 0) {
opt->checkConfig = 1; opt->checkConfig = 1;
}
break; break;
case O_DMPCFG: // --dumpconfig case O_DMPCFG: // --dumpconfig
opt->checkConfig = 2; opt->checkConfig = 2;
@@ -466,8 +469,7 @@ error_t parse_opt(int key, char *arg, struct argp_state *state)
return 0; return 0;
} }
void daemonize() void daemonize() {
{
// fork off the parent process // fork off the parent process
pid_t pid = fork(); pid_t pid = fork();
@@ -477,9 +479,9 @@ void daemonize()
} }
// If we got a good PID, then we can exit the parent process // If we got a good PID, then we can exit the parent process
if (pid > 0) if (pid > 0) {
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
}
// At this point we are executing as the child process // At this point we are executing as the child process
// Create a new SID for the child process and // Create a new SID for the child process and
@@ -522,12 +524,11 @@ void daemonize()
isDaemon = true; isDaemon = true;
} }
void closePidFile() void closePidFile() {
{
if (pidFile != NULL) { if (pidFile != NULL) {
if (fclose(pidFile) != 0) if (fclose(pidFile) != 0) {
return; return;
}
remove(opt.pidFile); remove(opt.pidFile);
} }
} }
@@ -535,8 +536,7 @@ void closePidFile()
/** /**
* Helper method performing shutdown. * Helper method performing shutdown.
*/ */
void shutdown() void shutdown() {
{
// stop main loop and all dependent components // stop main loop and all dependent components
if (s_mainLoop != NULL) { if (s_mainLoop != NULL) {
delete s_mainLoop; delete s_mainLoop;
@@ -573,8 +573,7 @@ void shutdown()
* The signal handling function. * The signal handling function.
* @param sig the received signal. * @param sig the received signal.
*/ */
void signalHandler(int sig) void signalHandler(int sig) {
{
switch (sig) { switch (sig) {
case SIGHUP: case SIGHUP:
logNotice(lf_main, "SIGHUP received"); logNotice(lf_main, "SIGHUP received");
@@ -604,30 +603,29 @@ void signalHandler(int sig)
* @return the result code. * @return the result code.
*/ */
static result_t collectConfigFiles(const string path, const string prefix, const string extension, static result_t collectConfigFiles(const string path, const string prefix, const string extension,
vector<string>& files, vector<string>* dirs=NULL, bool* hasTemplates=NULL) vector<string>& files, vector<string>* dirs = NULL, bool* hasTemplates = NULL) {
{
DIR* dir = opendir(path.c_str()); DIR* dir = opendir(path.c_str());
if (dir == NULL) if (dir == NULL) {
return RESULT_ERR_NOTFOUND; return RESULT_ERR_NOTFOUND;
}
dirent* d; dirent* d;
while ((d = readdir(dir)) != NULL) { while ((d = readdir(dir)) != NULL) {
string name = d->d_name; string name = d->d_name;
if (name == "." || name == "..") if (name == "." || name == "..") {
continue; continue;
}
const string p = path + "/" + name; const string p = path + "/" + name;
struct stat stat_buf; struct stat stat_buf;
if (stat(p.c_str(), &stat_buf) != 0) if (stat(p.c_str(), &stat_buf) != 0) {
continue; continue;
}
if (S_ISDIR(stat_buf.st_mode)) { if (S_ISDIR(stat_buf.st_mode)) {
if (dirs!=NULL) if (dirs != NULL) {
dirs->push_back(p); dirs->push_back(p);
}
} else if (S_ISREG(stat_buf.st_mode) && name.length() >= extension.length() } else if (S_ISREG(stat_buf.st_mode) && name.length() >= extension.length()
&& name.substr(name.length()-extension.length()) == extension) { && name.substr(name.length()-extension.length()) == extension) {
if (name == "_templates"+extension) { if (name == "_templates"+extension) {
@@ -700,40 +698,40 @@ static bool readTemplates(const string path, const string extension, bool availa
* @param verbose whether to verbosely log problems. * @param verbose whether to verbosely log problems.
* @return the result code. * @return the result code.
*/ */
static result_t readConfigFiles(const string path, const string extension, MessageMap* messages, bool recursive, bool verbose) static result_t readConfigFiles(const string path, const string extension, MessageMap* messages, bool recursive, bool verbose) {
{
vector<string> files, dirs; vector<string> files, dirs;
bool hasTemplates = false; bool hasTemplates = false;
result_t result = collectConfigFiles(path, "", extension, files, &dirs, &hasTemplates); result_t result = collectConfigFiles(path, "", extension, files, &dirs, &hasTemplates);
if (result!=RESULT_OK) if (result != RESULT_OK) {
return result; return result;
}
readTemplates(path, extension, hasTemplates, verbose); readTemplates(path, extension, hasTemplates, verbose);
for (vector<string>::iterator it = files.begin(); it != files.end(); it++) { for (vector<string>::iterator it = files.begin(); it != files.end(); it++) {
string name = *it; string name = *it;
logInfo(lf_main, "reading file %s", name.c_str()); logInfo(lf_main, "reading file %s", name.c_str());
result_t result = messages->readFromFile(name, verbose); result_t result = messages->readFromFile(name, verbose);
if (result != RESULT_OK) if (result != RESULT_OK) {
return result; return result;
} }
}
if (recursive) { if (recursive) {
for (vector<string>::iterator it = dirs.begin(); it != dirs.end(); it++) { for (vector<string>::iterator it = dirs.begin(); it != dirs.end(); it++) {
string name = *it; string name = *it;
logInfo(lf_main, "reading dir %s", name.c_str()); logInfo(lf_main, "reading dir %s", name.c_str());
result_t result = readConfigFiles(name, extension, messages, true, verbose); result_t result = readConfigFiles(name, extension, messages, true, verbose);
if (result != RESULT_OK) if (result != RESULT_OK) {
return result; return result;
} }
} }
}
return RESULT_OK; return RESULT_OK;
}; }
/** /**
* Helper method for immediate reading of a @a Message from the bus. * Helper method for immediate reading of a @a Message from the bus.
* @param message the @a Message to read. * @param message the @a Message to read.
*/ */
void readMessage(Message* message) void readMessage(Message* message) {
{
if (!s_mainLoop || !message) { if (!s_mainLoop || !message) {
return; return;
} }
@@ -749,8 +747,7 @@ void readMessage(Message* message)
* @param messages the @a MessageMap instance. * @param messages the @a MessageMap instance.
* @param verbose whether to verbosely log all problems. * @param verbose whether to verbosely log all problems.
*/ */
void executeInstructions(MessageMap* messages, bool verbose) void executeInstructions(MessageMap* messages, bool verbose) {
{
result_t result = messages->resolveConditions(verbose); result_t result = messages->resolveConditions(verbose);
if (result != RESULT_OK) { if (result != RESULT_OK) {
logError(lf_main, "error resolving conditions: %s, last error: %s", getResultCode(result), messages->getLastError().c_str()); logError(lf_main, "error resolving conditions: %s, last error: %s", getResultCode(result), messages->getLastError().c_str());
@@ -765,8 +762,7 @@ void executeInstructions(MessageMap* messages, bool verbose)
logNotice(lf_main, "found messages: %d (%d conditional on %d conditions, %d poll, %d update)", messages->size(), messages->sizeConditional(), messages->sizeConditions(), messages->sizePoll(), messages->sizePassive()); logNotice(lf_main, "found messages: %d (%d conditional on %d conditions, %d poll, %d update)", messages->size(), messages->sizeConditional(), messages->sizeConditions(), messages->sizePoll(), messages->sizePassive());
} }
result_t loadConfigFiles(MessageMap* messages, bool verbose, bool denyRecursive) result_t loadConfigFiles(MessageMap* messages, bool verbose, bool denyRecursive) {
{
logInfo(lf_main, "loading configuration files from %s", opt.configPath); logInfo(lf_main, "loading configuration files from %s", opt.configPath);
messages->clear(); messages->clear();
s_globalTemplates.clear(); s_globalTemplates.clear();
@@ -788,8 +784,7 @@ result_t loadConfigFiles(MessageMap* messages, bool verbose, bool denyRecursive)
return RESULT_OK; return RESULT_OK;
} }
result_t loadScanConfigFile(MessageMap* messages, unsigned char address, SymbolString& data, string& relativeFile, bool verbose) result_t loadScanConfigFile(MessageMap* messages, unsigned char address, SymbolString& data, string& relativeFile, bool verbose) {
{
PartType partType; PartType partType;
if (isMaster(address)) { if (isMaster(address)) {
address = (unsigned char)(data[0]+5); // slave address of sending master address = (unsigned char)(data[0]+5); // slave address of sending master
@@ -812,8 +807,9 @@ result_t loadScanConfigFile(MessageMap* messages, unsigned char address, SymbolS
unsigned char offset = 0; unsigned char offset = 0;
size_t field = 0; size_t field = 0;
result_t result = (*identFields)[field]->read(partType, data, offset, out, 0); // manufacturer name result_t result = (*identFields)[field]->read(partType, data, offset, out, 0); // manufacturer name
if (result==RESULT_ERR_NOTFOUND) if (result == RESULT_ERR_NOTFOUND) {
result = (*identFields)[field]->read(partType, data, offset, out, OF_NUMERIC); // manufacturer name result = (*identFields)[field]->read(partType, data, offset, out, OF_NUMERIC); // manufacturer name
}
if (result == RESULT_OK) { if (result == RESULT_OK) {
path = out.str(); path = out.str();
transform(path.begin(), path.end(), path.begin(), ::tolower); transform(path.begin(), path.end(), path.begin(), ::tolower);
@@ -883,8 +879,9 @@ result_t loadScanConfigFile(MessageMap* messages, unsigned char address, SymbolS
matches = true; matches = true;
break; break;
} }
if (remain[remain.length()-1]<'0' || remain[remain.length()-1]>'9') if (remain[remain.length()-1] < '0' || remain[remain.length()-1] > '9') {
break; break;
}
remain.erase(remain.length()-1); // remove trailing digit remain.erase(remain.length()-1); // remove trailing digit
} }
if (!matches) { if (!matches) {
@@ -912,19 +909,21 @@ result_t loadScanConfigFile(MessageMap* messages, unsigned char address, SymbolS
for (vector<string>::iterator it = files.begin(); it != files.end(); it++) { for (vector<string>::iterator it = files.begin(); it != files.end(); it++) {
string name = *it; string name = *it;
name = name.substr(path.length()+1, name.length()-path.length()-strlen(".csv")); // *. name = name.substr(path.length()+1, name.length()-path.length()-strlen(".csv")); // *.
if (name=="_templates.") // skip templates if (name == "_templates.") { // skip templates
continue; continue;
}
if (name.length() < 3 || name.find_first_of('.') != 2) { // different from the scheme "ZZ." if (name.length() < 3 || name.find_first_of('.') != 2) { // different from the scheme "ZZ."
name = *it; name = *it;
result = messages->readFromFile(name, opt.checkConfig); result = messages->readFromFile(name, opt.checkConfig);
if (result==RESULT_OK) if (result == RESULT_OK) {
logNotice(lf_main, "read common config file %s", name.c_str()); logNotice(lf_main, "read common config file %s", name.c_str());
else } else {
logError(lf_main, "error reading common config file %s: %s", name.c_str(), getResultCode(result)); logError(lf_main, "error reading common config file %s: %s", name.c_str(), getResultCode(result));
} }
} }
} }
} }
}
result = messages->readFromFile(best, opt.checkConfig, "", ident); result = messages->readFromFile(best, opt.checkConfig, "", ident);
if (result != RESULT_OK) { if (result != RESULT_OK) {
logError(lf_main, "error reading scan config file %s for ID \"%s\", SW%4.4d, HW%4.4d: %s", best.c_str(), ident.c_str(), sw, hw, getResultCode(result)); logError(lf_main, "error reading scan config file %s for ID \"%s\", SW%4.4d, HW%4.4d: %s", best.c_str(), ident.c_str(), sw, hw, getResultCode(result));
@@ -943,8 +942,7 @@ result_t loadScanConfigFile(MessageMap* messages, unsigned char address, SymbolS
* @param argc the number of command line arguments. * @param argc the number of command line arguments.
* @param argv the command line arguments. * @param argv the command line arguments.
*/ */
int main(int argc, char* argv[]) int main(int argc, char* argv[]) {
{
struct argp aargp = { argpoptions, parse_opt, NULL, argpdoc, datahandler_getargs(), NULL, NULL }; struct argp aargp = { argpoptions, parse_opt, NULL, argpdoc, datahandler_getargs(), NULL, NULL };
int arg_index = -1; int arg_index = -1;
setenv("ARGP_HELP_FMT", "no-dup-args-note", 0); setenv("ARGP_HELP_FMT", "no-dup-args-note", 0);
+7 -7
View File
@@ -16,19 +16,19 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef MAIN_H_ #ifndef EBUSD_MAIN_H_
#define MAIN_H_ #define EBUSD_MAIN_H_
#include "result.h" #include <stdint.h>
#include <string>
#include "data.h" #include "data.h"
#include "message.h" #include "message.h"
#include <stdint.h> #include "result.h"
/** \file main.h */ /** \file main.h */
/** A structure holding all program options. */ /** A structure holding all program options. */
struct options struct options {
{
const char* device; //!< eBUS device (serial device or [udp:]ip:port) [/dev/ttyUSB0] const char* device; //!< eBUS device (serial device or [udp:]ip:port) [/dev/ttyUSB0]
bool noDeviceCheck; //!< skip serial eBUS device test bool noDeviceCheck; //!< skip serial eBUS device test
bool readOnly; //!< read-only access to the device bool readOnly; //!< read-only access to the device
@@ -96,4 +96,4 @@ result_t loadConfigFiles(MessageMap* messages, bool verbose=false, bool denyRecu
*/ */
result_t loadScanConfigFile(MessageMap* messages, unsigned char address, SymbolString& data, string& relativeFile, bool verbose = false); result_t loadScanConfigFile(MessageMap* messages, unsigned char address, SymbolString& data, string& relativeFile, bool verbose = false);
#endif // MAIN_H_ #endif // EBUSD_MAIN_H_
+222 -186
View File
@@ -16,8 +16,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "mainloop.h" #include "mainloop.h"
#include <iomanip> #include <iomanip>
#include <deque>
#include "main.h" #include "main.h"
#include "log.h" #include "log.h"
#include "data.h" #include "data.h"
@@ -60,8 +65,7 @@ static const size_t columnCount = sizeof(columnNames) / sizeof(char*);
MainLoop::MainLoop(const struct options opt, Device *device, MessageMap* messages) MainLoop::MainLoop(const struct options opt, Device *device, MessageMap* messages)
: Thread(), m_device(device), m_reconnectCount(0), m_messages(messages), : Thread(), m_device(device), m_reconnectCount(0), m_messages(messages),
m_address(opt.address), m_scanConfig(opt.scanConfig), m_address(opt.address), m_scanConfig(opt.scanConfig),
m_initialScan(opt.initialScan), m_enableHex(opt.enableHex) m_initialScan(opt.initialScan), m_enableHex(opt.enableHex) {
{
// open Device // open Device
result_t result = m_device->open(); result_t result = m_device->open();
if (result != RESULT_OK) { if (result != RESULT_OK) {
@@ -105,8 +109,7 @@ MainLoop::MainLoop(const struct options opt, Device *device, MessageMap* message
} }
} }
MainLoop::~MainLoop() MainLoop::~MainLoop() {
{
join(); join();
for (list<DataHandler*>::iterator it = m_dataHandlers.begin(); it != m_dataHandlers.end(); it++) { for (list<DataHandler*>::iterator it = m_dataHandlers.begin(); it != m_dataHandlers.end(); it++) {
@@ -138,8 +141,7 @@ MainLoop::~MainLoop()
} }
} }
void MainLoop::run() void MainLoop::run() {
{
bool reload = true; bool reload = true;
time_t lastTaskRun, now, lastSignal = 0, since, sinkSince = 1; time_t lastTaskRun, now, lastSignal = 0, since, sinkSince = 1;
int taskDelay = 5; int taskDelay = 5;
@@ -216,9 +218,9 @@ void MainLoop::run()
} else { } else {
result_t result = m_busHandler->scanAndWait(lastScanAddress, slave); result_t result = m_busHandler->scanAndWait(lastScanAddress, slave);
taskDelay = (result == RESULT_ERR_NO_SIGNAL) ? 10 : 1; taskDelay = (result == RESULT_ERR_NO_SIGNAL) ? 10 : 1;
if (result!=RESULT_OK) if (result != RESULT_OK) {
logError(lf_main, "scan config %2.2x message: %s", lastScanAddress, getResultCode(result)); logError(lf_main, "scan config %2.2x message: %s", lastScanAddress, getResultCode(result));
else { } else {
scanned = true; scanned = true;
logInfo(lf_main, "scan config %2.2x message received", lastScanAddress); logInfo(lf_main, "scan config %2.2x message received", lastScanAddress);
} }
@@ -292,8 +294,7 @@ void MainLoop::run()
} }
} }
void MainLoop::notifyDeviceData(const unsigned char byte, bool received) void MainLoop::notifyDeviceData(const unsigned char byte, bool received) {
{
if (received && m_dumpFile) { if (received && m_dumpFile) {
m_dumpFile->write((unsigned char*)&byte, 1); m_dumpFile->write((unsigned char*)&byte, 1);
} }
@@ -308,8 +309,7 @@ void MainLoop::notifyDeviceData(const unsigned char byte, bool received)
} }
} }
string MainLoop::decodeMessage(const string& data, const bool isHttp, bool& connected, bool& listening, bool& reload) string MainLoop::decodeMessage(const string& data, const bool isHttp, bool& connected, bool& listening, bool& reload) {
{
// prepare data // prepare data
string token, previous; string token, previous;
istringstream stream(data); istringstream stream(data);
@@ -326,85 +326,99 @@ string MainLoop::decodeMessage(const string& data, const bool isHttp, bool& conn
escaped = false; escaped = false;
} }
token = previous + " " + token; token = previous + " " + token;
} } else if (token.length() == 0) { // allow multiple space chars for a single delimiter
else if (token.length() == 0) // allow multiple space chars for a single delimiter
continue; continue;
else if (token[0] == '"') { } else if (token[0] == '"') {
token.erase(0, 1); token.erase(0, 1);
if (token.length() > 0 && token[token.length()-1] == '"') if (token.length() > 0 && token[token.length()-1] == '"') {
token.erase(token.length() - 1, 1); token.erase(token.length() - 1, 1);
else } else {
escaped = true; escaped = true;
} }
} }
}
args.push_back(token); args.push_back(token);
previous = token; previous = token;
if (isHttp) if (isHttp) {
delim = (args.size() == 1) ? '?' : '\n'; delim = (args.size() == 1) ? '?' : '\n';
} }
}
if (isHttp) { if (isHttp) {
const char* str = args.size() > 0 ? args[0].c_str() : ""; const char* str = args.size() > 0 ? args[0].c_str() : "";
if (strcmp(str, "GET") == 0) if (strcmp(str, "GET") == 0) {
return executeGet(args, connected); return executeGet(args, connected);
}
connected = false; connected = false;
return "HTTP/1.0 405 Method Not Allowed\r\n\r\n"; return "HTTP/1.0 405 Method Not Allowed\r\n\r\n";
} }
if (args.size() == 0) if (args.size() == 0) {
return executeHelp(); return executeHelp();
}
const char* str = args[0].c_str(); const char* str = args[0].c_str();
if (args.size() == 2) { if (args.size() == 2) {
// check for "CMD -h" // check for "CMD -h"
if (strcasecmp(args[1].c_str(), "-h") == 0 || strcasecmp(args[1].c_str(), "-?") == 0 || strcasecmp(args[1].c_str(), "--help") == 0) if (strcasecmp(args[1].c_str(), "-h") == 0 || strcasecmp(args[1].c_str(), "-?") == 0 || strcasecmp(args[1].c_str(), "--help") == 0) {
args.clear(); // empty args is used as command help indicator args.clear(); // empty args is used as command help indicator
else if (strcasecmp(args[0].c_str(), "H") == 0 || strcasecmp(args[0].c_str(), "HELP") == 0) { // check for "HELP CMD" } else if (strcasecmp(args[0].c_str(), "H") == 0 || strcasecmp(args[0].c_str(), "HELP") == 0) { // check for "HELP CMD"
str = args[1].c_str(); str = args[1].c_str();
args.clear(); // empty args is used as command help indicator args.clear(); // empty args is used as command help indicator
} }
} }
if (strcasecmp(str, "R") == 0 || strcasecmp(str, "READ") == 0) if (strcasecmp(str, "R") == 0 || strcasecmp(str, "READ") == 0) {
return executeRead(args); return executeRead(args);
if (strcasecmp(str, "W") == 0 || strcasecmp(str, "WRITE") == 0) }
if (strcasecmp(str, "W") == 0 || strcasecmp(str, "WRITE") == 0) {
return executeWrite(args); return executeWrite(args);
}
if (strcasecmp(str, "HEX") == 0) { if (strcasecmp(str, "HEX") == 0) {
if (m_enableHex) if (m_enableHex) {
return executeHex(args); return executeHex(args);
}
return "ERR: command not enabled"; return "ERR: command not enabled";
} }
if (strcasecmp(str, "F") == 0 || strcasecmp(str, "FIND") == 0) if (strcasecmp(str, "F") == 0 || strcasecmp(str, "FIND") == 0) {
return executeFind(args); return executeFind(args);
if (strcasecmp(str, "L") == 0 || strcasecmp(str, "LISTEN") == 0) }
if (strcasecmp(str, "L") == 0 || strcasecmp(str, "LISTEN") == 0) {
return executeListen(args, listening); return executeListen(args, listening);
if (strcasecmp(str, "S") == 0 || strcasecmp(str, "STATE") == 0) }
if (strcasecmp(str, "S") == 0 || strcasecmp(str, "STATE") == 0) {
return executeState(args); return executeState(args);
if (strcasecmp(str, "G") == 0 || strcasecmp(str, "GRAB") == 0) }
if (strcasecmp(str, "G") == 0 || strcasecmp(str, "GRAB") == 0) {
return executeGrab(args); return executeGrab(args);
if (strcasecmp(str, "SCAN") == 0) }
if (strcasecmp(str, "SCAN") == 0) {
return executeScan(args); return executeScan(args);
if (strcasecmp(str, "LOG") == 0) }
if (strcasecmp(str, "LOG") == 0) {
return executeLog(args); return executeLog(args);
if (strcasecmp(str, "RAW") == 0) }
if (strcasecmp(str, "RAW") == 0) {
return executeRaw(args); return executeRaw(args);
if (strcasecmp(str, "DUMP") == 0) }
if (strcasecmp(str, "DUMP") == 0) {
return executeDump(args); return executeDump(args);
}
if (strcasecmp(str, "RELOAD") == 0) { if (strcasecmp(str, "RELOAD") == 0) {
reload = true; reload = true;
return executeReload(args); return executeReload(args);
} }
if (strcasecmp(str, "Q") == 0 || strcasecmp(str, "QUIT") == 0) if (strcasecmp(str, "Q") == 0 || strcasecmp(str, "QUIT") == 0) {
return executeQuit(args, connected); return executeQuit(args, connected);
if (strcasecmp(str, "I") == 0 || strcasecmp(str, "INFO") == 0) }
if (strcasecmp(str, "I") == 0 || strcasecmp(str, "INFO") == 0) {
return executeInfo(args); return executeInfo(args);
if (strcasecmp(str, "H") == 0 || strcasecmp(str, "HELP") == 0) }
if (strcasecmp(str, "H") == 0 || strcasecmp(str, "HELP") == 0) {
return executeHelp(); return executeHelp();
}
return "ERR: command not found"; return "ERR: command not found";
} }
result_t MainLoop::parseHexMaster(vector<string> &args, size_t argPos, SymbolString& master) result_t MainLoop::parseHexMaster(vector<string> &args, size_t argPos, SymbolString& master) {
{
ostringstream msg; ostringstream msg;
while (argPos < args.size()) { while (argPos < args.size()) {
if ((args[argPos].length() % 2) != 0) { if ((args[argPos].length() % 2) != 0) {
@@ -412,25 +426,25 @@ result_t MainLoop::parseHexMaster(vector<string> &args, size_t argPos, SymbolStr
} }
msg << args[argPos++]; msg << args[argPos++];
} }
if (msg.str().size() < 4*2) // at least ZZ, PB, SB, NN if (msg.str().size() < 4*2) { // at least ZZ, PB, SB, NN
return RESULT_ERR_INVALID_ARG; return RESULT_ERR_INVALID_ARG;
}
result_t ret; result_t ret;
unsigned int length = parseInt(msg.str().substr(3*2, 2).c_str(), 16, 0, MAX_POS, ret); unsigned int length = parseInt(msg.str().substr(3*2, 2).c_str(), 16, 0, MAX_POS, ret);
if (ret == RESULT_OK && (4+length)*2 != msg.str().size()) if (ret == RESULT_OK && (4+length)*2 != msg.str().size()) {
return RESULT_ERR_INVALID_ARG; return RESULT_ERR_INVALID_ARG;
}
ret = master.push_back(m_address, false); ret = master.push_back(m_address, false);
if (ret == RESULT_OK) if (ret == RESULT_OK) {
ret = master.parseHex(msg.str()); ret = master.parseHex(msg.str());
if (ret == RESULT_OK && !isValidAddress(master[1])) }
if (ret == RESULT_OK && !isValidAddress(master[1])) {
ret = RESULT_ERR_INVALID_ADDR; ret = RESULT_ERR_INVALID_ADDR;
}
return ret; return ret;
} }
string MainLoop::executeRead(vector<string> &args) string MainLoop::executeRead(vector<string> &args) {
{
size_t argPos = 1; size_t argPos = 1;
bool hex = false, numeric = false; bool hex = false, numeric = false;
OutputFormat verbosity = 0; OutputFormat verbosity = 0;
@@ -469,8 +483,7 @@ string MainLoop::executeRead(vector<string> &args)
argPos = 0; // print usage argPos = 0; // print usage
break; break;
} }
} } else {
else {
argPos = 0; // print usage argPos = 0; // print usage
break; break;
} }
@@ -489,8 +502,9 @@ string MainLoop::executeRead(vector<string> &args)
} }
result_t ret; result_t ret;
dstAddress = (unsigned char)parseInt(args[argPos].c_str(), 16, 0, 0xff, ret); dstAddress = (unsigned char)parseInt(args[argPos].c_str(), 16, 0, 0xff, ret);
if (ret != RESULT_OK || !isValidAddress(dstAddress) || isMaster(dstAddress)) if (ret != RESULT_OK || !isValidAddress(dstAddress) || isMaster(dstAddress)) {
return getResultCode(RESULT_ERR_INVALID_ADDR); return getResultCode(RESULT_ERR_INVALID_ADDR);
}
} else if (args[argPos] == "-p") { } else if (args[argPos] == "-p") {
argPos++; argPos++;
if (argPos >= args.size()) { if (argPos >= args.size()) {
@@ -499,8 +513,9 @@ string MainLoop::executeRead(vector<string> &args)
} }
result_t ret; result_t ret;
pollPriority = (unsigned char)parseInt(args[argPos].c_str(), 10, 1, 9, ret); pollPriority = (unsigned char)parseInt(args[argPos].c_str(), 10, 1, 9, ret);
if (ret != RESULT_OK) if (ret != RESULT_OK) {
return getResultCode(RESULT_ERR_INVALID_NUM); return getResultCode(RESULT_ERR_INVALID_NUM);
}
} else if (args[argPos] == "-i") { } else if (args[argPos] == "-i") {
argPos++; argPos++;
if (argPos >= args.size()) { if (argPos >= args.size()) {
@@ -524,22 +539,26 @@ string MainLoop::executeRead(vector<string> &args)
if (hex && argPos > 0) { if (hex && argPos > 0) {
SymbolString cacheMaster(false); SymbolString cacheMaster(false);
result_t ret = parseHexMaster(args, argPos, cacheMaster); result_t ret = parseHexMaster(args, argPos, cacheMaster);
if (ret != RESULT_OK) if (ret != RESULT_OK) {
return getResultCode(ret); return getResultCode(ret);
if (cacheMaster[1] == BROADCAST || isMaster(cacheMaster[1])) }
if (cacheMaster[1] == BROADCAST || isMaster(cacheMaster[1])) {
return getResultCode(RESULT_ERR_INVALID_ARG); return getResultCode(RESULT_ERR_INVALID_ARG);
}
logNotice(lf_main, "read hex cmd: %s", cacheMaster.getDataStr(true, false).c_str()); logNotice(lf_main, "read hex cmd: %s", cacheMaster.getDataStr(true, false).c_str());
// find message // find message
Message* message = m_messages->find(cacheMaster, false, true, false, false); Message* message = m_messages->find(cacheMaster, false, true, false, false);
if (message == NULL) if (message == NULL) {
return getResultCode(RESULT_ERR_NOTFOUND); return getResultCode(RESULT_ERR_NOTFOUND);
if (message->isWrite()) }
if (message->isWrite()) {
return getResultCode(RESULT_ERR_INVALID_ARG); return getResultCode(RESULT_ERR_INVALID_ARG);
if (circuit.length() > 0 && circuit!=message->getCircuit()) }
if (circuit.length() > 0 && circuit != message->getCircuit()) {
return getResultCode(RESULT_ERR_INVALID_ARG); // non-matching circuit return getResultCode(RESULT_ERR_INVALID_ARG); // non-matching circuit
}
if (message->getLastUpdateTime() + maxAge > now || (message->isPassive() && message->getLastUpdateTime() != 0)) { if (message->getLastUpdateTime() + maxAge > now || (message->isPassive() && message->getLastUpdateTime() != 0)) {
SymbolString& slave = message->getLastSlaveData(); SymbolString& slave = message->getLastSlaveData();
logNotice(lf_main, "hex read %s %s from cache", message->getCircuit().c_str(), message->getName().c_str()); logNotice(lf_main, "hex read %s %s from cache", message->getCircuit().c_str(), message->getName().c_str());
@@ -555,18 +574,20 @@ string MainLoop::executeRead(vector<string> &args)
if (ret == RESULT_OK) { if (ret == RESULT_OK) {
ret = message->storeLastData(cacheMaster, slave); ret = message->storeLastData(cacheMaster, slave);
ostringstream result; ostringstream result;
if (ret==RESULT_OK) if (ret == RESULT_OK) {
ret = message->decodeLastData(result); ret = message->decodeLastData(result);
if (ret >= RESULT_OK) }
if (ret >= RESULT_OK) {
logInfo(lf_main, "read hex %s %s cache update: %s", message->getCircuit().c_str(), message->getName().c_str(), result.str().c_str()); logInfo(lf_main, "read hex %s %s cache update: %s", message->getCircuit().c_str(), message->getName().c_str(), result.str().c_str());
else } else {
logError(lf_main, "read hex %s %s cache update: %s", message->getCircuit().c_str(), message->getName().c_str(), getResultCode(ret)); logError(lf_main, "read hex %s %s cache update: %s", message->getCircuit().c_str(), message->getName().c_str(), getResultCode(ret));
}
return slave.getDataStr(true, false); return slave.getDataStr(true, false);
} }
logError(lf_main, "read hex %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(), getResultCode(ret)); logError(lf_main, "read hex %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(), getResultCode(ret));
return getResultCode(ret); return getResultCode(ret);
} }
if (argPos == 0 || args.size() < argPos + 1 || args.size() > argPos + 2) if (argPos == 0 || args.size() < argPos + 1 || args.size() > argPos + 2) {
return "usage: read [-f] [-m SECONDS] [-c CIRCUIT] [-d ZZ] [-p PRIO] [-v|-V] [-n] [-i VALUE[;VALUE]*] NAME [FIELD[.N]]\n" return "usage: read [-f] [-m SECONDS] [-c CIRCUIT] [-d ZZ] [-p PRIO] [-v|-V] [-n] [-i VALUE[;VALUE]*] NAME [FIELD[.N]]\n"
" or: read [-f] [-m SECONDS] [-c CIRCUIT] -h ZZPBSBNNDx\n" " or: read [-f] [-m SECONDS] [-c CIRCUIT] -h ZZPBSBNNDx\n"
" Read value(s) or hex message.\n" " Read value(s) or hex message.\n"
@@ -587,7 +608,7 @@ string MainLoop::executeRead(vector<string> &args)
" PB SB primary/secondary command byte\n" " PB SB primary/secondary command byte\n"
" NN number of following data bytes\n" " NN number of following data bytes\n"
" Dx data byte(s) to send"; " Dx data byte(s) to send";
}
string fieldName; string fieldName;
signed char fieldIndex = -2; signed char fieldIndex = -2;
if (args.size() == argPos + 2) { if (args.size() == argPos + 2) {
@@ -597,10 +618,11 @@ string MainLoop::executeRead(vector<string> &args)
if (pos != string::npos) { if (pos != string::npos) {
result_t result = RESULT_OK; result_t result = RESULT_OK;
fieldIndex = (char)parseInt(fieldName.substr(pos+1).c_str(), 10, 0, MAX_POS, result); fieldIndex = (char)parseInt(fieldName.substr(pos+1).c_str(), 10, 0, MAX_POS, result);
if (result == RESULT_OK) if (result == RESULT_OK) {
fieldName = fieldName.substr(0, pos); fieldName = fieldName.substr(0, pos);
} }
} }
}
ostringstream result; ostringstream result;
Message* message = m_messages->find(circuit, args[argPos], false); Message* message = m_messages->find(circuit, args[argPos], false);
@@ -622,29 +644,31 @@ string MainLoop::executeRead(vector<string> &args)
} }
result_t ret = cacheMessage->decodeLastData(result, verbosity|(numeric?OF_NUMERIC:0), false, fieldIndex == -2 ? NULL : fieldName.c_str(), fieldIndex); result_t ret = cacheMessage->decodeLastData(result, verbosity|(numeric?OF_NUMERIC:0), false, fieldIndex == -2 ? NULL : fieldName.c_str(), fieldIndex);
if (ret != RESULT_OK) { if (ret != RESULT_OK) {
if (ret < RESULT_OK) if (ret < RESULT_OK) {
logError(lf_main, "read %s %s cached: %s", cacheMessage->getCircuit().c_str(), cacheMessage->getName().c_str(), getResultCode(ret)); logError(lf_main, "read %s %s cached: %s", cacheMessage->getCircuit().c_str(), cacheMessage->getName().c_str(), getResultCode(ret));
}
return getResultCode(ret); return getResultCode(ret);
} }
logInfo(lf_main, "read %s %s cached: %s", cacheMessage->getCircuit().c_str(), cacheMessage->getName().c_str(), result.str().c_str()); logInfo(lf_main, "read %s %s cached: %s", cacheMessage->getCircuit().c_str(), cacheMessage->getName().c_str(), result.str().c_str());
return result.str(); return result.str();
} }
if (message == NULL && hasCache) if (message == NULL && hasCache) {
return "ERR: no data stored"; return "ERR: no data stored";
// else: read directly from bus } // else: read directly from bus
} }
if (message == NULL) if (message == NULL) {
return getResultCode(RESULT_ERR_NOTFOUND); return getResultCode(RESULT_ERR_NOTFOUND);
if (message->getDstAddress()==SYN && dstAddress==SYN) }
if (message->getDstAddress() == SYN && dstAddress == SYN) {
return getResultCode(RESULT_ERR_INVALID_ADDR); return getResultCode(RESULT_ERR_INVALID_ADDR);
}
// read directly from bus // read directly from bus
result_t ret = m_busHandler->readFromBus(message, params, dstAddress); result_t ret = m_busHandler->readFromBus(message, params, dstAddress);
if (ret != RESULT_OK) if (ret != RESULT_OK) {
return getResultCode(ret); return getResultCode(ret);
}
if (verbosity & OF_NAMES) { if (verbosity & OF_NAMES) {
result << message->getCircuit() << " " << message->getName() << " "; result << message->getCircuit() << " " << message->getName() << " ";
} }
@@ -655,14 +679,14 @@ string MainLoop::executeRead(vector<string> &args)
result << getResultCode(ret) << " in decode"; result << getResultCode(ret) << " in decode";
return result.str(); return result.str();
} }
if (ret > RESULT_OK) if (ret > RESULT_OK) {
return getResultCode(ret); return getResultCode(ret);
}
logInfo(lf_main, "read %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(), result.str().c_str()); logInfo(lf_main, "read %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(), result.str().c_str());
return result.str(); return result.str();
} }
string MainLoop::executeWrite(vector<string> &args) string MainLoop::executeWrite(vector<string> &args) {
{
size_t argPos = 1; size_t argPos = 1;
bool hex = false; bool hex = false;
string circuit; string circuit;
@@ -678,8 +702,9 @@ string MainLoop::executeWrite(vector<string> &args)
} }
result_t ret; result_t ret;
dstAddress = (unsigned char)parseInt(args[argPos].c_str(), 16, 0, 0xff, ret); dstAddress = (unsigned char)parseInt(args[argPos].c_str(), 16, 0, 0xff, ret);
if (ret != RESULT_OK || !isValidAddress(dstAddress) || isMaster(dstAddress)) if (ret != RESULT_OK || !isValidAddress(dstAddress) || isMaster(dstAddress)) {
return getResultCode(RESULT_ERR_INVALID_ADDR); return getResultCode(RESULT_ERR_INVALID_ADDR);
}
} else if (args[argPos] == "-c") { } else if (args[argPos] == "-c") {
argPos++; argPos++;
if (argPos >= args.size()) { if (argPos >= args.size()) {
@@ -701,21 +726,23 @@ string MainLoop::executeWrite(vector<string> &args)
if (hex && argPos > 0) { if (hex && argPos > 0) {
SymbolString cacheMaster(false); SymbolString cacheMaster(false);
result_t ret = parseHexMaster(args, argPos, cacheMaster); result_t ret = parseHexMaster(args, argPos, cacheMaster);
if (ret != RESULT_OK) if (ret != RESULT_OK) {
return getResultCode(ret); return getResultCode(ret);
}
logNotice(lf_main, "write hex cmd: %s", cacheMaster.getDataStr(true, false).c_str()); logNotice(lf_main, "write hex cmd: %s", cacheMaster.getDataStr(true, false).c_str());
// find message // find message
Message* message = m_messages->find(cacheMaster, false, false, true, false); Message* message = m_messages->find(cacheMaster, false, false, true, false);
if (message == NULL) if (message == NULL) {
return getResultCode(RESULT_ERR_NOTFOUND); return getResultCode(RESULT_ERR_NOTFOUND);
if (!message->isWrite()) }
if (!message->isWrite()) {
return getResultCode(RESULT_ERR_INVALID_ARG); return getResultCode(RESULT_ERR_INVALID_ARG);
if (circuit.length() > 0 && circuit!=message->getCircuit()) }
if (circuit.length() > 0 && circuit != message->getCircuit()) {
return getResultCode(RESULT_ERR_INVALID_ARG); // non-matching circuit return getResultCode(RESULT_ERR_INVALID_ARG); // non-matching circuit
}
// send message // send message
SymbolString master(true); SymbolString master(true);
master.addAll(cacheMaster); master.addAll(cacheMaster);
@@ -726,23 +753,27 @@ string MainLoop::executeWrite(vector<string> &args)
// also update read messages // also update read messages
ret = message->storeLastData(cacheMaster, slave); ret = message->storeLastData(cacheMaster, slave);
ostringstream result; ostringstream result;
if (ret==RESULT_OK) if (ret == RESULT_OK) {
ret = message->decodeLastData(result); ret = message->decodeLastData(result);
if (ret >= RESULT_OK) }
if (ret >= RESULT_OK) {
logInfo(lf_main, "write hex %s %s cache update: %s", message->getCircuit().c_str(), message->getName().c_str(), result.str().c_str()); logInfo(lf_main, "write hex %s %s cache update: %s", message->getCircuit().c_str(), message->getName().c_str(), result.str().c_str());
else } else {
logError(lf_main, "write hex %s %s cache update: %s", message->getCircuit().c_str(), message->getName().c_str(), getResultCode(ret)); logError(lf_main, "write hex %s %s cache update: %s", message->getCircuit().c_str(), message->getName().c_str(), getResultCode(ret));
if (master[1] == BROADCAST) }
if (master[1] == BROADCAST) {
return "done broadcast"; return "done broadcast";
if (isMaster(master[1])) }
if (isMaster(master[1])) {
return getResultCode(RESULT_OK); return getResultCode(RESULT_OK);
}
return slave.getDataStr(true, false); return slave.getDataStr(true, false);
} }
logError(lf_main, "write hex %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(), getResultCode(ret)); logError(lf_main, "write hex %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(), getResultCode(ret));
return getResultCode(ret); return getResultCode(ret);
} }
if (argPos == 0 || circuit.empty() || (args.size() != argPos + 2 && args.size() != argPos + 1)) if (argPos == 0 || circuit.empty() || (args.size() != argPos + 2 && args.size() != argPos + 1)) {
return "usage: write [-d ZZ] -c CIRCUIT NAME [VALUE[;VALUE]*]\n" return "usage: write [-d ZZ] -c CIRCUIT NAME [VALUE[;VALUE]*]\n"
" or: write [-c CIRCUIT] -h ZZPBSBNNDx\n" " or: write [-c CIRCUIT] -h ZZPBSBNNDx\n"
" Write value(s) or hex message.\n" " Write value(s) or hex message.\n"
@@ -755,14 +786,15 @@ string MainLoop::executeWrite(vector<string> &args)
" PB SB primary/secondary command byte\n" " PB SB primary/secondary command byte\n"
" NN number of following data bytes\n" " NN number of following data bytes\n"
" Dx data byte(s) to send"; " Dx data byte(s) to send";
}
Message* message = m_messages->find(circuit, args[argPos], true); Message* message = m_messages->find(circuit, args[argPos], true);
if (message == NULL) if (message == NULL) {
return getResultCode(RESULT_ERR_NOTFOUND); return getResultCode(RESULT_ERR_NOTFOUND);
if (message->getDstAddress()==SYN && dstAddress==SYN) }
if (message->getDstAddress() == SYN && dstAddress == SYN) {
return getResultCode(RESULT_ERR_INVALID_ADDR); return getResultCode(RESULT_ERR_INVALID_ADDR);
}
result_t ret = m_busHandler->readFromBus(message, args.size() == argPos + 1 ? "" : args[argPos + 1], dstAddress); // allow missing values result_t ret = m_busHandler->readFromBus(message, args.size() == argPos + 1 ? "" : args[argPos + 1], dstAddress); // allow missing values
if (ret != RESULT_OK) { if (ret != RESULT_OK) {
logError(lf_main, "write %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(), getResultCode(ret)); logError(lf_main, "write %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(), getResultCode(ret));
@@ -772,8 +804,9 @@ string MainLoop::executeWrite(vector<string> &args)
ostringstream result; ostringstream result;
if (dstAddress == BROADCAST || isMaster(dstAddress)) { if (dstAddress == BROADCAST || isMaster(dstAddress)) {
logNotice(lf_main, "write %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(), getResultCode(ret)); logNotice(lf_main, "write %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(), getResultCode(ret));
if (dstAddress == BROADCAST) if (dstAddress == BROADCAST) {
return "done broadcast"; return "done broadcast";
}
return getResultCode(RESULT_OK); return getResultCode(RESULT_OK);
} }
@@ -792,8 +825,7 @@ string MainLoop::executeWrite(vector<string> &args)
return result.str(); return result.str();
} }
string MainLoop::executeHex(vector<string> &args) string MainLoop::executeHex(vector<string> &args) {
{
size_t argPos = 1; size_t argPos = 1;
if (args.size() < argPos + 1 || (args.size() > argPos && args[argPos][0] == '-')) { if (args.size() < argPos + 1 || (args.size() > argPos && args[argPos][0] == '-')) {
argPos = 0; // print usage argPos = 0; // print usage
@@ -802,9 +834,9 @@ string MainLoop::executeHex(vector<string> &args)
if (argPos > 0) { if (argPos > 0) {
SymbolString cacheMaster(false); SymbolString cacheMaster(false);
result_t ret = parseHexMaster(args, argPos, cacheMaster); result_t ret = parseHexMaster(args, argPos, cacheMaster);
if (ret != RESULT_OK) if (ret != RESULT_OK) {
return getResultCode(ret); return getResultCode(ret);
}
logNotice(lf_main, "hex cmd: %s", cacheMaster.getDataStr(true, false).c_str()); logNotice(lf_main, "hex cmd: %s", cacheMaster.getDataStr(true, false).c_str());
// send message // send message
@@ -814,10 +846,12 @@ string MainLoop::executeHex(vector<string> &args)
ret = m_busHandler->sendAndWait(master, slave); ret = m_busHandler->sendAndWait(master, slave);
if (ret == RESULT_OK) { if (ret == RESULT_OK) {
if (master[1] == BROADCAST) if (master[1] == BROADCAST) {
return "done broadcast"; return "done broadcast";
if (isMaster(master[1])) }
if (isMaster(master[1])) {
return getResultCode(RESULT_OK); return getResultCode(RESULT_OK);
}
return slave.getDataStr(true, false); return slave.getDataStr(true, false);
} }
logError(lf_main, "hex: %s", getResultCode(ret)); logError(lf_main, "hex: %s", getResultCode(ret));
@@ -832,8 +866,7 @@ string MainLoop::executeHex(vector<string> &args)
" Dx data byte(s) to send"; " Dx data byte(s) to send";
} }
string MainLoop::executeFind(vector<string> &args) string MainLoop::executeFind(vector<string> &args) {
{
size_t argPos = 1; size_t argPos = 1;
bool configFormat = false, exact = false, withRead = true, withWrite = false, withPassive = true, first = true, onlyWithData = false, hexFormat = false; bool configFormat = false, exact = false, withRead = true, withWrite = false, withPassive = true, first = true, onlyWithData = false, hexFormat = false;
OutputFormat verbosity = 0; OutputFormat verbosity = 0;
@@ -944,7 +977,7 @@ string MainLoop::executeFind(vector<string> &args)
} }
argPos++; argPos++;
} }
if (argPos == 0 || args.size() < argPos || args.size() > argPos + 1) if (argPos == 0 || args.size() < argPos || args.size() > argPos + 1) {
return "usage: find [-v|-V] [-r] [-w] [-p] [-d] [-h] [-i ID] [-f] [-F COL[,COL]*] [-e] [-c CIRCUIT] [NAME]\n" return "usage: find [-v|-V] [-r] [-w] [-p] [-d] [-h] [-i ID] [-f] [-F COL[,COL]*] [-e] [-c CIRCUIT] [NAME]\n"
" Find message(s).\n" " Find message(s).\n"
" -v increase verbosity (include names/units/comments+destination address+update time)\n" " -v increase verbosity (include names/units/comments+destination address+update time)\n"
@@ -961,7 +994,7 @@ string MainLoop::executeFind(vector<string> &args)
" -e match NAME and optional CIRCUIT exactly (ignoring case)\n" " -e match NAME and optional CIRCUIT exactly (ignoring case)\n"
" -c CIRCUIT limit to messages of CIRCUIT (or a part thereof without '-e')\n" " -c CIRCUIT limit to messages of CIRCUIT (or a part thereof without '-e')\n"
" NAME NAME of the messages to find (or a part thereof without '-e')"; " NAME NAME of the messages to find (or a part thereof without '-e')";
}
deque<Message*> messages = m_messages->findAll( deque<Message*> messages = m_messages->findAll(
circuit, args.size() == argPos ? "" : args[argPos], exact, withRead, withWrite, withPassive circuit, args.size() == argPos ? "" : args[argPos], exact, withRead, withWrite, withPassive
); );
@@ -975,19 +1008,23 @@ string MainLoop::executeFind(vector<string> &args)
continue; continue;
} }
time_t lastup = message->getLastUpdateTime(); time_t lastup = message->getLastUpdateTime();
if (onlyWithData && lastup == 0) if (onlyWithData && lastup == 0) {
continue; continue;
}
if (configFormat) { if (configFormat) {
if (found) if (found) {
result << endl; result << endl;
}
message->dump(result); message->dump(result);
} else if (!columns.empty()) { } else if (!columns.empty()) {
if (found) if (found) {
result << endl; result << endl;
}
message->dump(result, &columns); message->dump(result, &columns);
} else { } else {
if (found) if (found) {
result << endl; result << endl;
}
result << message->getCircuit() << " " << message->getName() << " = "; result << message->getCircuit() << " " << message->getName() << " = ";
if (lastup == 0) { if (lastup == 0) {
result << "no data stored"; result << "no data stored";
@@ -1004,12 +1041,13 @@ string MainLoop::executeFind(vector<string> &args)
} }
if (verbosity == (OF_NAMES|OF_UNITS|OF_COMMENTS)) { if (verbosity == (OF_NAMES|OF_UNITS|OF_COMMENTS)) {
unsigned char dstAddress = message->getDstAddress(); unsigned char dstAddress = message->getDstAddress();
if (dstAddress != SYN) if (dstAddress != SYN) {
sprintf(str, "%02x", dstAddress); sprintf(str, "%02x", dstAddress);
else if (lastup != 0 && message->getLastMasterData().size()>1) } else if (lastup != 0 && message->getLastMasterData().size() > 1) {
sprintf(str, "%02x", message->getLastMasterData()[1]); sprintf(str, "%02x", message->getLastMasterData()[1]);
else } else {
sprintf(str, "any"); sprintf(str, "any");
}
if (lastup != 0) { if (lastup != 0) {
struct tm* td = localtime(&lastup); struct tm* td = localtime(&lastup);
sprintf(str+strlen(str), ", lastup=%04d-%02d-%02d %02d:%02d:%02d", sprintf(str+strlen(str), ", lastup=%04d-%02d-%02d %02d:%02d:%02d",
@@ -1017,49 +1055,48 @@ string MainLoop::executeFind(vector<string> &args)
td->tm_hour, td->tm_min, td->tm_sec); td->tm_hour, td->tm_min, td->tm_sec);
} }
result << " [ZZ=" << str; result << " [ZZ=" << str;
if (message->isPassive()) if (message->isPassive()) {
result << ", passive"; result << ", passive";
else } else {
result << ", active"; result << ", active";
}
if (message->isWrite()) if (message->isWrite()) {
result << " write]"; result << " write]";
else } else {
result << " read]"; result << " read]";
} }
} }
}
found = true; found = true;
} }
if (!found) if (!found) {
return getResultCode(RESULT_ERR_NOTFOUND); return getResultCode(RESULT_ERR_NOTFOUND);
}
return result.str(); return result.str();
} }
string MainLoop::executeListen(vector<string> &args, bool& listening) string MainLoop::executeListen(vector<string> &args, bool& listening) {
{
if (args.size() == 1) { if (args.size() == 1) {
if (listening) if (listening) {
return "listen continued"; return "listen continued";
}
listening = true; listening = true;
return "listen started"; return "listen started";
} }
if (args.size() != 2 || args[1] != "stop") if (args.size() != 2 || args[1] != "stop") {
return "usage: listen [stop]\n" return "usage: listen [stop]\n"
" Listen for updates or stop it."; " Listen for updates or stop it.";
}
listening = false; listening = false;
return "listen stopped"; return "listen stopped";
} }
string MainLoop::executeState(vector<string> &args) string MainLoop::executeState(vector<string> &args) {
{ if (args.size() == 0) {
if (args.size() == 0)
return "usage: state\n" return "usage: state\n"
" Report bus state."; " Report bus state.";
}
if (m_busHandler->hasSignal()) { if (m_busHandler->hasSignal()) {
ostringstream result; ostringstream result;
result << "signal acquired, " result << "signal acquired, "
@@ -1071,8 +1108,7 @@ string MainLoop::executeState(vector<string> &args)
return "no signal"; return "no signal";
} }
string MainLoop::executeGrab(vector<string> &args) string MainLoop::executeGrab(vector<string> &args) {
{
if (args.size() == 1) { if (args.size() == 1) {
return m_busHandler->enableGrab(true) ? "grab started" : "grab continued"; return m_busHandler->enableGrab(true) ? "grab started" : "grab continued";
} }
@@ -1091,22 +1127,21 @@ string MainLoop::executeGrab(vector<string> &args)
" Start or stop grabbing, or report unknown or all grabbed messages."; " Start or stop grabbing, or report unknown or all grabbed messages.";
} }
string MainLoop::executeScan(vector<string> &args) string MainLoop::executeScan(vector<string> &args) {
{
if (args.size() == 1) { if (args.size() == 1) {
result_t result = m_busHandler->startScan(); result_t result = m_busHandler->startScan();
if (result != RESULT_OK) if (result != RESULT_OK) {
logError(lf_main, "scan: %s", getResultCode(result)); logError(lf_main, "scan: %s", getResultCode(result));
}
return getResultCode(result); return getResultCode(result);
} }
if (args.size() == 2) { if (args.size() == 2) {
if (strcasecmp(args[1].c_str(), "FULL") == 0) { if (strcasecmp(args[1].c_str(), "FULL") == 0) {
result_t result = m_busHandler->startScan(true); result_t result = m_busHandler->startScan(true);
if (result != RESULT_OK) if (result != RESULT_OK) {
logError(lf_main, "full scan: %s", getResultCode(result)); logError(lf_main, "full scan: %s", getResultCode(result));
}
return getResultCode(result); return getResultCode(result);
} }
@@ -1118,23 +1153,24 @@ string MainLoop::executeScan(vector<string> &args)
result_t result; result_t result;
unsigned char dstAddress = (unsigned char)parseInt(args[1].c_str(), 16, 0, 0xff, result); unsigned char dstAddress = (unsigned char)parseInt(args[1].c_str(), 16, 0, 0xff, result);
if (result == RESULT_OK && !isValidAddress(dstAddress, false)) if (result == RESULT_OK && !isValidAddress(dstAddress, false)) {
result = RESULT_ERR_INVALID_ADDR; result = RESULT_ERR_INVALID_ADDR;
if (result != RESULT_OK) }
if (result != RESULT_OK) {
return getResultCode(result); return getResultCode(result);
}
SymbolString slave(false); SymbolString slave(false);
result = m_busHandler->scanAndWait(dstAddress, slave); result = m_busHandler->scanAndWait(dstAddress, slave);
if (result != RESULT_OK) if (result != RESULT_OK) {
return getResultCode(result); return getResultCode(result);
}
Message* message = m_messages->getScanMessage(dstAddress); // never NULL due to scanAndWait() == RESULT_OK && dstAddress != BROADCAST Message* message = m_messages->getScanMessage(dstAddress); // never NULL due to scanAndWait() == RESULT_OK && dstAddress != BROADCAST
ostringstream ret; ostringstream ret;
ret << hex << setw(2) << setfill('0') << static_cast<unsigned>(dstAddress); ret << hex << setw(2) << setfill('0') << static_cast<unsigned>(dstAddress);
result = message->decodeLastData(ret, 0, true); // decode data result = message->decodeLastData(ret, 0, true); // decode data
if (result != RESULT_OK) if (result != RESULT_OK) {
return getResultCode(result); return getResultCode(result);
}
return ret.str(); return ret.str();
} }
@@ -1143,8 +1179,7 @@ string MainLoop::executeScan(vector<string> &args)
" Scan seen slaves, all slaves (full), a single slave (address ZZ), or report scan result."; " Scan seen slaves, all slaves (full), a single slave (address ZZ), or report scan result.";
} }
string MainLoop::executeLog(vector<string> &args) string MainLoop::executeLog(vector<string> &args) {
{
if (args.size() == 1) { if (args.size() == 1) {
ostringstream ret; ostringstream ret;
char str[32]; char str[32];
@@ -1156,28 +1191,27 @@ string MainLoop::executeLog(vector<string> &args)
} }
bool result; bool result;
// old format: log areas AREA[,AREA]*, log level LEVEL // old format: log areas AREA[,AREA]*, log level LEVEL
if ((args.size() == 3 || args.size() == 2) && strcasecmp(args[1].c_str(), "AREAS") == 0) if ((args.size() == 3 || args.size() == 2) && strcasecmp(args[1].c_str(), "AREAS") == 0) {
result = setLogFacilities(args.size() == 3 ? args[2].c_str() : ""); result = setLogFacilities(args.size() == 3 ? args[2].c_str() : "");
else if (args.size() == 3 && strcasecmp(args[1].c_str(), "LEVEL") == 0) } else if (args.size() == 3 && strcasecmp(args[1].c_str(), "LEVEL") == 0) {
result = setLogLevel(args[2].c_str()); result = setLogLevel(args[2].c_str());
else if (args.size() == 2) } else if (args.size() == 2) {
result = setLogLevel(args[1].c_str()) || setLogFacilities(args[1].c_str()); result = setLogLevel(args[1].c_str()) || setLogFacilities(args[1].c_str());
else if (args.size() == 3) } else if (args.size() == 3) {
result = setLogFacilities(args[1].c_str()) && setLogLevel(args[2].c_str()); result = setLogFacilities(args[1].c_str()) && setLogLevel(args[2].c_str());
else } else {
return "usage: log [AREA[,AREA]*] [LEVEL]\n" return "usage: log [AREA[,AREA]*] [LEVEL]\n"
" Set log area(s) and/or log level or get current settings.\n" " Set log area(s) and/or log level or get current settings.\n"
" AREA log area to include (main|network|bus|update|all)\n" " AREA log area to include (main|network|bus|update|all)\n"
" LEVEL log level to set (error|notice|info|debug)"; " LEVEL log level to set (error|notice|info|debug)";
}
if (result) if (result) {
return getResultCode(RESULT_OK); return getResultCode(RESULT_OK);
}
return getResultCode(RESULT_ERR_INVALID_ARG); return getResultCode(RESULT_ERR_INVALID_ARG);
} }
string MainLoop::executeRaw(vector<string> &args) string MainLoop::executeRaw(vector<string> &args) {
{
if (args.size() != 1) { if (args.size() != 1) {
return "usage: raw\n" return "usage: raw\n"
" Toggle logging of each byte."; " Toggle logging of each byte.";
@@ -1193,8 +1227,7 @@ string MainLoop::executeRaw(vector<string> &args)
return enabled ? "raw logging enabled" : "raw logging disabled"; return enabled ? "raw logging enabled" : "raw logging disabled";
} }
string MainLoop::executeDump(vector<string> &args) string MainLoop::executeDump(vector<string> &args) {
{
if (args.size() != 1) { if (args.size() != 1) {
return "usage: dump\n" return "usage: dump\n"
" Toggle binary dump of received bytes."; " Toggle binary dump of received bytes.";
@@ -1207,24 +1240,21 @@ string MainLoop::executeDump(vector<string> &args)
return enabled ? "dump enabled" : "dump disabled"; return enabled ? "dump enabled" : "dump disabled";
} }
string MainLoop::executeReload(vector<string> &args) string MainLoop::executeReload(vector<string> &args) {
{ if (args.size() != 1) {
if (args.size() != 1)
return "usage: reload\n" return "usage: reload\n"
" Reload CSV config files."; " Reload CSV config files.";
}
m_busHandler->clear(); m_busHandler->clear();
result_t result = loadConfigFiles(m_messages); result_t result = loadConfigFiles(m_messages);
return getResultCode(result); return getResultCode(result);
} }
string MainLoop::executeInfo(vector<string> &args) string MainLoop::executeInfo(vector<string> &args) {
{ if (args.size() == 0) {
if (args.size() == 0)
return "usage: info\n" return "usage: info\n"
" Report information about the daemon, the configuration, and seen devices."; " Report information about the daemon, the configuration, and seen devices.";
}
ostringstream result; ostringstream result;
result << "version: " << PACKAGE_STRING "." REVISION "\n"; result << "version: " << PACKAGE_STRING "." REVISION "\n";
if (m_busHandler->hasSignal()) { if (m_busHandler->hasSignal()) {
@@ -1243,19 +1273,16 @@ string MainLoop::executeInfo(vector<string> &args)
return result.str(); return result.str();
} }
string MainLoop::executeQuit(vector<string> &args, bool& connected) string MainLoop::executeQuit(vector<string> &args, bool& connected) {
{
if (args.size() == 1) { if (args.size() == 1) {
connected = false; connected = false;
return "connection closed"; return "connection closed";
} }
return "usage: quit\n" return "usage: quit\n"
" Close client connection."; " Close client connection.";
} }
string MainLoop::executeHelp() string MainLoop::executeHelp() {
{
return "usage:\n" return "usage:\n"
" read|r Read value(s): read [-f] [-m SECONDS] [-c CIRCUIT] [-d ZZ] [-p PRIO] [-v|-V] [-n] [-i VALUE[;VALUE]*] NAME [FIELD[.N]]\n" " read|r Read value(s): read [-f] [-m SECONDS] [-c CIRCUIT] [-d ZZ] [-p PRIO] [-v|-V] [-n] [-i VALUE[;VALUE]*] NAME [FIELD[.N]]\n"
" Read hex message: read [-f] [-m SECONDS] [-c CIRCUIT] -h ZZPBSBNNDx\n" " Read hex message: read [-f] [-m SECONDS] [-c CIRCUIT] -h ZZPBSBNNDx\n"
@@ -1280,8 +1307,7 @@ string MainLoop::executeHelp()
" help|h Print help help [COMMAND]"; " help|h Print help help [COMMAND]";
} }
string MainLoop::executeGet(vector<string> &args, bool& connected) string MainLoop::executeGet(vector<string> &args, bool& connected) {
{
result_t ret = RESULT_OK; result_t ret = RESULT_OK;
bool numeric = false, required = false; bool numeric = false, required = false;
OutputFormat verbosity = OF_NAMES; OutputFormat verbosity = OF_NAMES;
@@ -1334,10 +1360,11 @@ string MainLoop::executeGet(vector<string> &args, bool& connected)
} else if (strcmp(qname.c_str(), "required") == 0) { } else if (strcmp(qname.c_str(), "required") == 0) {
required = value.length() == 0 || strcmp(value.c_str(), "1") == 0; required = value.length() == 0 || strcmp(value.c_str(), "1") == 0;
} }
if (ret != RESULT_OK) if (ret != RESULT_OK) {
break; break;
} }
} }
}
deque<Message*> messages = m_messages->findAll(circuit, name, exact, true, false, true); deque<Message*> messages = m_messages->findAll(circuit, name, exact, true, false, true);
bool first = true; bool first = true;
@@ -1347,35 +1374,43 @@ string MainLoop::executeGet(vector<string> &args, bool& connected)
for (deque<Message*>::iterator it = messages.begin(); ret == RESULT_OK && it != messages.end();) { for (deque<Message*>::iterator it = messages.begin(); ret == RESULT_OK && it != messages.end();) {
Message* message = *it++; Message* message = *it++;
unsigned char dstAddress = message->getDstAddress(); unsigned char dstAddress = message->getDstAddress();
if (dstAddress == SYN) if (dstAddress == SYN) {
continue; continue;
if (pollPriority > 0 && message->setPollPriority(pollPriority)) }
if (pollPriority > 0 && message->setPollPriority(pollPriority)) {
m_messages->addPollMessage(message); m_messages->addPollMessage(message);
}
time_t lastup = message->getLastUpdateTime(); time_t lastup = message->getLastUpdateTime();
if (lastup == 0 && required) { if (lastup == 0 && required) {
// read directly from bus // read directly from bus
if (message->isPassive()) if (message->isPassive()) {
continue; // not possible to actively read this message continue; // not possible to actively read this message
if (m_busHandler->readFromBus(message, "") != RESULT_OK) }
if (m_busHandler->readFromBus(message, "") != RESULT_OK) {
continue; continue;
}
lastup = message->getLastUpdateTime(); lastup = message->getLastUpdateTime();
} else { } else {
if (since > 0 && lastup <= since) if (since > 0 && lastup <= since) {
continue; continue;
if (lastup > maxLastUp) }
if (lastup > maxLastUp) {
maxLastUp = lastup; maxLastUp = lastup;
} }
}
if (message->getCircuit() != lastCircuit) { if (message->getCircuit() != lastCircuit) {
if (lastCircuit.length() > 0) if (lastCircuit.length() > 0) {
result << "\n },"; result << "\n },";
}
lastCircuit = message->getCircuit(); lastCircuit = message->getCircuit();
result << "\n \"" << lastCircuit << "\": {"; result << "\n \"" << lastCircuit << "\": {";
first = true; first = true;
} }
if (first) if (first) {
first = false; first = false;
else } else {
result << ","; result << ",";
}
result << "\n \"" << message->getName() << "\": {"; result << "\n \"" << message->getName() << "\": {";
result << "\n \"lastup\": " << setw(0) << dec << static_cast<unsigned>(lastup); result << "\n \"lastup\": " << setw(0) << dec << static_cast<unsigned>(lastup);
if (lastup != 0) { if (lastup != 0) {
@@ -1398,8 +1433,9 @@ string MainLoop::executeGet(vector<string> &args, bool& connected)
} }
if (ret == RESULT_OK) { if (ret == RESULT_OK) {
if (lastCircuit.length() > 0) if (lastCircuit.length() > 0) {
result << "\n },"; result << "\n },";
}
result << "\n \"global\": {"; result << "\n \"global\": {";
result << "\n \"signal\": " << (m_busHandler->hasSignal() ? "1" : "0"); result << "\n \"signal\": " << (m_busHandler->hasSignal() ? "1" : "0");
result << ",\n \"lastup\": " << setw(0) << dec << static_cast<unsigned>(maxLastUp); result << ",\n \"lastup\": " << setw(0) << dec << static_cast<unsigned>(maxLastUp);
@@ -1412,9 +1448,9 @@ string MainLoop::executeGet(vector<string> &args, bool& connected)
ret = RESULT_ERR_INVALID_ARG; ret = RESULT_ERR_INVALID_ARG;
} else { } else {
string filename = m_htmlPath+uri; string filename = m_htmlPath+uri;
if (uri[uri.length()-1] == '/') if (uri[uri.length()-1] == '/') {
filename += "index.html"; filename += "index.html";
}
size_t pos = filename.find_last_of('.'); size_t pos = filename.find_last_of('.');
if (pos != string::npos && pos != filename.length() - 1 && pos >= filename.length() - 5) { if (pos != string::npos && pos != filename.length() - 1 && pos >= filename.length() - 5) {
string ext = filename.substr(pos+1); string ext = filename.substr(pos+1);
+11 -14
View File
@@ -16,17 +16,17 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef MAINLOOP_H_ #ifndef EBUSD_MAINLOOP_H_
#define MAINLOOP_H_ #define EBUSD_MAINLOOP_H_
#include "message.h" #include <string>
#include "network.h" #include <list>
#include <vector>
#include "bushandler.h" #include "bushandler.h"
#include "datahandler.h" #include "datahandler.h"
#include "network.h"
#include "message.h"
#include "rotatefile.h" #include "rotatefile.h"
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
/** \file mainloop.h */ /** \file mainloop.h */
@@ -35,10 +35,8 @@ using namespace std;
/** /**
* The main loop handling requests from connected clients. * The main loop handling requests from connected clients.
*/ */
class MainLoop : public Thread, DeviceListener class MainLoop : public Thread, DeviceListener {
{
public: public:
/** /**
* Construct the main loop and create network and bus handling components. * Construct the main loop and create network and bus handling components.
* @param opt the program options. * @param opt the program options.
@@ -67,13 +65,13 @@ public:
// @copydoc // @copydoc
virtual void notifyDeviceData(const unsigned char byte, bool received); virtual void notifyDeviceData(const unsigned char byte, bool received);
protected:
protected:
// @copydoc // @copydoc
virtual void run(); virtual void run();
private:
private:
/** /**
* Decode and execute client message. * Decode and execute client message.
* @param data the data string to decode (may be empty). * @param data the data string to decode (may be empty).
@@ -252,7 +250,6 @@ private:
/** the registered @a DataHandler instances. */ /** the registered @a DataHandler instances. */
list<DataHandler*> m_dataHandlers; list<DataHandler*> m_dataHandlers;
}; };
#endif // MAINLOOP_H_ #endif // EBUSD_MAINLOOP_H_
+16 -28
View File
@@ -16,12 +16,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "mqtthandler.h"
#include "log.h"
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
# include <config.h> # include <config.h>
#endif #endif
#include "mqtthandler.h"
#include "log.h"
using namespace std; using namespace std;
/** the definition of the MQTT arguments. */ /** the definition of the MQTT arguments. */
@@ -43,8 +44,7 @@ static const char* g_topic = PACKAGE; //!< MQTT topic to use (prefix if without
* @param arg the option argument, or NULL. * @param arg the option argument, or NULL.
* @param state the parsing state. * @param state the parsing state.
*/ */
static error_t mqtt_parse_opt(int key, char *arg, struct argp_state *state) static error_t mqtt_parse_opt(int key, char *arg, struct argp_state *state) {
{
result_t result = RESULT_OK; result_t result = RESULT_OK;
switch (key) { switch (key) {
@@ -72,13 +72,11 @@ static error_t mqtt_parse_opt(int key, char *arg, struct argp_state *state)
static const struct argp g_mqtt_argp = { g_mqtt_argp_options, mqtt_parse_opt, NULL, NULL, NULL, NULL, NULL }; static const struct argp g_mqtt_argp = { g_mqtt_argp_options, mqtt_parse_opt, NULL, NULL, NULL, NULL, NULL };
static const struct argp_child g_mqtt_argp_child = {&g_mqtt_argp, 0, "", 1}; static const struct argp_child g_mqtt_argp_child = {&g_mqtt_argp, 0, "", 1};
const struct argp_child* mqtthandler_getargs() const struct argp_child* mqtthandler_getargs() {
{
return &g_mqtt_argp_child; return &g_mqtt_argp_child;
} }
DataHandler* mqtthandler_register(BusHandler* busHandler, MessageMap* messages) DataHandler* mqtthandler_register(BusHandler* busHandler, MessageMap* messages) {
{
return new MqttHandler(busHandler, messages); return new MqttHandler(busHandler, messages);
} }
@@ -142,8 +140,7 @@ bool parseTopic(const string topic, vector<string> &strs, vector<size_t> &cols)
MqttHandler::MqttHandler(BusHandler* busHandler, MessageMap* messages) MqttHandler::MqttHandler(BusHandler* busHandler, MessageMap* messages)
: DataSink(), DataSource(busHandler), Thread(), m_messages(messages) : DataSink(), DataSource(busHandler), Thread(), m_messages(messages) {
{
bool enabled = g_port != 0; bool enabled = g_port != 0;
m_publishByField = false; m_publishByField = false;
m_mosquitto = NULL; m_mosquitto = NULL;
@@ -221,8 +218,7 @@ MqttHandler::MqttHandler(BusHandler* busHandler, MessageMap* messages)
} }
} }
MqttHandler::~MqttHandler() MqttHandler::~MqttHandler() {
{
join(); join();
if (m_mosquitto) { if (m_mosquitto) {
mosquitto_destroy(m_mosquitto); mosquitto_destroy(m_mosquitto);
@@ -231,8 +227,7 @@ MqttHandler::~MqttHandler()
mosquitto_lib_cleanup(); mosquitto_lib_cleanup();
} }
void MqttHandler::start() void MqttHandler::start() {
{
if (m_mosquitto) { if (m_mosquitto) {
Thread::start("MQTT"); Thread::start("MQTT");
} }
@@ -242,8 +237,7 @@ void on_message(
#if (LIBMOSQUITTO_MAJOR >= 1) #if (LIBMOSQUITTO_MAJOR >= 1)
struct mosquitto *mosq, struct mosquitto *mosq,
#endif #endif
void *obj, const struct mosquitto_message *message) void *obj, const struct mosquitto_message *message) {
{
MqttHandler* handler = (MqttHandler*)obj; MqttHandler* handler = (MqttHandler*)obj;
if (!handler || !message || !handler->isRunning()) { if (!handler || !message || !handler->isRunning()) {
return; return;
@@ -253,8 +247,7 @@ void on_message(
handler->notifyTopic(topic, data); handler->notifyTopic(topic, data);
} }
void MqttHandler::notifyTopic(string topic, string data) void MqttHandler::notifyTopic(string topic, string data) {
{
size_t pos = topic.rfind('/'); size_t pos = topic.rfind('/');
if (pos == string::npos) { if (pos == string::npos) {
return; return;
@@ -343,8 +336,7 @@ void MqttHandler::notifyTopic(string topic, string data)
publishMessage(message, ostream); publishMessage(message, ostream);
} }
void MqttHandler::run() void MqttHandler::run() {
{
time_t lastTaskRun, now, start, lastSignal = 0; time_t lastTaskRun, now, start, lastSignal = 0;
bool signal = false; bool signal = false;
string signalTopic = m_globalTopic+"signal"; string signalTopic = m_globalTopic+"signal";
@@ -401,8 +393,7 @@ void MqttHandler::run()
} }
} }
void MqttHandler::handleTraffic() void MqttHandler::handleTraffic() {
{
if (m_mosquitto) { if (m_mosquitto) {
mosquitto_loop(m_mosquitto, -1 mosquitto_loop(m_mosquitto, -1
#if (LIBMOSQUITTO_MAJOR >= 1) #if (LIBMOSQUITTO_MAJOR >= 1)
@@ -412,8 +403,7 @@ void MqttHandler::handleTraffic()
} }
} }
string MqttHandler::getTopic(Message* message, signed char fieldIndex) string MqttHandler::getTopic(Message* message, signed char fieldIndex) {
{
ostringstream ret; ostringstream ret;
for (size_t i = 0; i < m_topicStrs.size(); i++) { for (size_t i = 0; i < m_topicStrs.size(); i++) {
ret << m_topicStrs[i]; ret << m_topicStrs[i];
@@ -431,8 +421,7 @@ string MqttHandler::getTopic(Message* message, signed char fieldIndex)
return ret.str(); return ret.str();
} }
void MqttHandler::publishMessage(Message* message, ostringstream& updates) void MqttHandler::publishMessage(Message* message, ostringstream& updates) {
{
result_t result = message->decodeLastData(updates); result_t result = message->decodeLastData(updates);
if (result != RESULT_OK) { if (result != RESULT_OK) {
logOtherError("mqtt", "decode %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(), getResultCode(result)); logOtherError("mqtt", "decode %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(), getResultCode(result));
@@ -452,8 +441,7 @@ void MqttHandler::publishMessage(Message* message, ostringstream& updates)
} }
} }
void MqttHandler::publishTopic(string topic, string data, bool retain) void MqttHandler::publishTopic(string topic, string data, bool retain) {
{
logOtherDebug("mqtt", "publish %s %s", topic.c_str(), data.c_str()); logOtherDebug("mqtt", "publish %s %s", topic.c_str(), data.c_str());
mosquitto_publish(m_mosquitto, NULL, topic.c_str(), (uint32_t)data.size(), (uint8_t*)(data.c_str()), 0, retain); mosquitto_publish(m_mosquitto, NULL, topic.c_str(), (uint32_t)data.size(), (uint8_t*)(data.c_str()), 0, retain);
} }
+7 -4
View File
@@ -16,13 +16,16 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef MQTTHANDLER_H_ #ifndef EBUSD_MQTTHANDLER_H_
#define MQTTHANDLER_H_ #define EBUSD_MQTTHANDLER_H_
#include <mosquitto.h>
#include <string>
#include <vector>
#include <map>
#include "datahandler.h" #include "datahandler.h"
#include "bushandler.h" #include "bushandler.h"
#include "message.h" #include "message.h"
#include <mosquitto.h>
/** @file mqtthandler.h /** @file mqtthandler.h
* A data handler enabling MQTT support via mosquitto. * A data handler enabling MQTT support via mosquitto.
@@ -128,4 +131,4 @@ private:
}; };
#endif // DATAHANDLER_H_ #endif // EBUSD_DATAHANDLER_H_
+7 -13
View File
@@ -21,19 +21,17 @@
#endif #endif
#include "network.h" #include "network.h"
#include "log.h"
#include <cstring>
#ifdef HAVE_PPOLL #ifdef HAVE_PPOLL
# include <poll.h> # include <poll.h>
#endif #endif
#include <cstring>
#include "log.h"
using namespace std; using namespace std;
int Connection::m_ids = 0; int Connection::m_ids = 0;
void Connection::run() void Connection::run() {
{
int ret; int ret;
struct timespec tdiff; struct timespec tdiff;
@@ -153,8 +151,7 @@ void Connection::run()
Network::Network(const bool local, const uint16_t port, const uint16_t httpPort, Queue<NetMessage*>* netQueue) Network::Network(const bool local, const uint16_t port, const uint16_t httpPort, Queue<NetMessage*>* netQueue)
: Thread(), m_netQueue(netQueue), m_listening(false) : Thread(), m_netQueue(netQueue), m_listening(false) {
{
m_tcpServer = new TCPServer(port, local ? "127.0.0.1" : "0.0.0.0"); m_tcpServer = new TCPServer(port, local ? "127.0.0.1" : "0.0.0.0");
if (m_tcpServer != NULL && m_tcpServer->start() == 0) { if (m_tcpServer != NULL && m_tcpServer->start() == 0) {
@@ -168,8 +165,7 @@ Network::Network(const bool local, const uint16_t port, const uint16_t httpPort,
} }
} }
Network::~Network() Network::~Network() {
{
stop(); stop();
while (!m_connections.empty()) { while (!m_connections.empty()) {
Connection* connection = m_connections.back(); Connection* connection = m_connections.back();
@@ -188,8 +184,7 @@ Network::~Network()
join(); join();
} }
void Network::run() void Network::run() {
{
if (!m_listening) { if (!m_listening) {
return; return;
} }
@@ -294,8 +289,7 @@ void Network::run()
} }
} }
void Network::cleanConnections() void Network::cleanConnections() {
{
list<Connection*>::iterator c_it; list<Connection*>::iterator c_it;
for (c_it = m_connections.begin(); c_it != m_connections.end(); c_it++) { for (c_it = m_connections.begin(); c_it != m_connections.end(); c_it++) {
if (!(*c_it)->isRunning()) { if (!(*c_it)->isRunning()) {
+10 -8
View File
@@ -16,16 +16,17 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef NETWORK_H_ #ifndef EBUSD_NETWORK_H_
#define NETWORK_H_ #define EBUSD_NETWORK_H_
#include <string>
#include <cstdio>
#include <algorithm>
#include <list>
#include "tcpsocket.h" #include "tcpsocket.h"
#include "queue.h" #include "queue.h"
#include "notify.h" #include "notify.h"
#include "thread.h" #include "thread.h"
#include <string>
#include <cstdio>
#include <algorithm>
/** \file network.h */ /** \file network.h */
@@ -94,8 +95,9 @@ public:
pos = 0; pos = 0;
while ((pos=m_request.find('%', pos)) != string::npos && pos+2 <= m_request.length()) { while ((pos=m_request.find('%', pos)) != string::npos && pos+2 <= m_request.length()) {
unsigned int value1, value2; unsigned int value1, value2;
if (sscanf("%1x%1x", m_request.c_str()+pos+1, &value1, &value2)<2) if (sscanf("%1x%1x", m_request.c_str()+pos+1, &value1, &value2) < 2) {
break; break;
}
m_request[pos] = (char)(((value1&0x0f)<<4) | (value2&0x0f)); m_request[pos] = (char)(((value1&0x0f)<<4) | (value2&0x0f));
m_request.erase(pos+1, 2); m_request.erase(pos+1, 2);
} }
@@ -163,7 +165,7 @@ public:
* @param listenSince set to the start time from which to add updates (inclusive). * @param listenSince set to the start time from which to add updates (inclusive).
* @return whether the client is in listening mode. * @return whether the client is in listening mode.
*/ */
bool isListening(time_t* listenSince=NULL) { if (listenSince) *listenSince = m_listenSince; return m_listening; } bool isListening(time_t* listenSince=NULL) { if (listenSince) { *listenSince = m_listenSince; } return m_listening; }
/** /**
* Return whether the client shall be disconnected. * Return whether the client shall be disconnected.
@@ -313,5 +315,5 @@ private:
}; };
#endif // NETWORK_H_ #endif // EBUSD_NETWORK_H_
+1
View File
@@ -16,6 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "contrib.h"
#include "tem.h" #include "tem.h"
using namespace std; using namespace std;
+3 -3
View File
@@ -16,8 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef LIBEBUS_CONTRIB_H_ #ifndef LIB_EBUS_CONTRIB_H_
#define LIBEBUS_CONTRIB_H_ #define LIB_EBUS_CONTRIB_H_
/** @file contrib.h /** @file contrib.h
* Contributed sources that may be excluded from regular builds. * Contributed sources that may be excluded from regular builds.
@@ -32,4 +32,4 @@ using namespace std;
*/ */
bool libebus_contrib_register(); bool libebus_contrib_register();
#endif // LIBEBUS_CONTRIB_H_ #endif // LIB_EBUS_CONTRIB_H_
+5 -8
View File
@@ -20,14 +20,14 @@
# include <config.h> # include <config.h>
#endif #endif
#include "datatype.h"
#include "tem.h" #include "tem.h"
#include <math.h>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <iomanip> #include <iomanip>
#include <vector> #include <vector>
#include <cstring> #include <cstring>
#include <math.h> #include "datatype.h"
using namespace std; using namespace std;
@@ -35,8 +35,7 @@ void contrib_tem_register() {
DataTypeList::getInstance()->add(new TemParamDataType("TEM_P")); DataTypeList::getInstance()->add(new TemParamDataType("TEM_P"));
} }
result_t TemParamDataType::derive(int divisor, unsigned char bitCount, NumberDataType* &derived) result_t TemParamDataType::derive(int divisor, unsigned char bitCount, NumberDataType* &derived) {
{
if (divisor == 0) { if (divisor == 0) {
divisor = 1; divisor = 1;
} }
@@ -52,8 +51,7 @@ result_t TemParamDataType::derive(int divisor, unsigned char bitCount, NumberDat
result_t TemParamDataType::readSymbols(SymbolString& input, const bool isMaster, result_t TemParamDataType::readSymbols(SymbolString& input, const bool isMaster,
const unsigned char offset, const unsigned char length, const unsigned char offset, const unsigned char length,
ostringstream& output, OutputFormat outputFormat) ostringstream& output, OutputFormat outputFormat) {
{
unsigned int value = 0; unsigned int value = 0;
result_t result = readRawValue(input, offset, length, value); result_t result = readRawValue(input, offset, length, value);
@@ -90,8 +88,7 @@ result_t TemParamDataType::readSymbols(SymbolString& input, const bool isMaster,
result_t TemParamDataType::writeSymbols(istringstream& input, result_t TemParamDataType::writeSymbols(istringstream& input,
const unsigned char offset, const unsigned char length, const unsigned char offset, const unsigned char length,
SymbolString& output, const bool isMaster, unsigned char* usedLength) SymbolString& output, const bool isMaster, unsigned char* usedLength) {
{
unsigned int value; unsigned int value;
int grp, num; int grp, num;
string token; string token;
+6 -6
View File
@@ -16,12 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef LIBEBUS_CONTRIB_TEM_H_ #ifndef LIB_EBUS_CONTRIB_TEM_H_
#define LIBEBUS_CONTRIB_TEM_H_ #define LIB_EBUS_CONTRIB_TEM_H_
#include "symbol.h"
#include "result.h"
#include "datatype.h"
#include <string> #include <string>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
@@ -29,6 +26,9 @@
#include <vector> #include <vector>
#include <list> #include <list>
#include <map> #include <map>
#include "symbol.h"
#include "result.h"
#include "datatype.h"
/** @file tem.h /** @file tem.h
* Contributed data types for TEM devices not part of regular releases. * Contributed data types for TEM devices not part of regular releases.
@@ -71,4 +71,4 @@ public:
*/ */
void contrib_tem_register(); void contrib_tem_register();
#endif // LIBEBUS_CONTRIB_TEM_H_ #endif // LIB_EBUS_CONTRIB_TEM_H_
+12 -14
View File
@@ -16,18 +16,19 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "tem.h"
#include "data.h"
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <string>
#include <vector>
#include "tem.h"
#include "data.h"
using namespace std; using namespace std;
static bool error = false; static bool error = false;
void verify(bool expectFailMatch, string type, string input, void verify(bool expectFailMatch, string type, string input,
bool match, string expectStr, string gotStr) bool match, string expectStr, string gotStr) {
{
match = match && expectStr == gotStr; match = match && expectStr == gotStr;
if (expectFailMatch) { if (expectFailMatch) {
if (match) { if (match) {
@@ -46,8 +47,7 @@ void verify(bool expectFailMatch, string type, string input,
} }
} }
int main() int main() {
{
DataType* type = DataTypeList::getInstance()->get("TEM_P"); DataType* type = DataTypeList::getInstance()->get("TEM_P");
if (type == NULL) { if (type == NULL) {
cout << "datatype not registered" << endl; cout << "datatype not registered" << endl;
@@ -145,7 +145,7 @@ int main()
if (result >= RESULT_OK) { if (result >= RESULT_OK) {
result = fields->read(pt_slaveData, sstr, 0, output, 0, -1, !output.str().empty()); result = fields->read(pt_slaveData, sstr, 0, output, 0, -1, !output.str().empty());
} }
if (failedRead) if (failedRead) {
if (result >= RESULT_OK) { if (result >= RESULT_OK) {
cout << " failed read " << fields->getName() << " >" << check[2] << " " << check[3] cout << " failed read " << fields->getName() << " >" << check[2] << " " << check[3]
<< "< error: unexpectedly succeeded" << endl; << "< error: unexpectedly succeeded" << endl;
@@ -154,20 +154,20 @@ int main()
cout << " failed read " << fields->getName() << " >" << check[2] << " " << check[3] cout << " failed read " << fields->getName() << " >" << check[2] << " " << check[3]
<< "< OK" << endl; << "< OK" << endl;
} }
else if (result < RESULT_OK) { } else if (result < RESULT_OK) {
cout << " read " << fields->getName() << " >" << check[2] << " " << check[3] cout << " read " << fields->getName() << " >" << check[2] << " " << check[3]
<< "< error: " << getResultCode(result) << endl; << "< error: " << getResultCode(result) << endl;
error = true; error = true;
} } else {
else {
bool match = strcasecmp(output.str().c_str(), expectStr.c_str()) == 0; bool match = strcasecmp(output.str().c_str(), expectStr.c_str()) == 0;
verify(failedReadMatch, "read", check[2], match, expectStr, output.str()); verify(failedReadMatch, "read", check[2], match, expectStr, output.str());
} }
istringstream input(expectStr); istringstream input(expectStr);
result = fields->write(input, pt_masterData, writeMstr, 0); result = fields->write(input, pt_masterData, writeMstr, 0);
if (result >= RESULT_OK) if (result >= RESULT_OK) {
result = fields->write(input, pt_slaveData, writeSstr, 0); result = fields->write(input, pt_slaveData, writeSstr, 0);
}
if (failedWrite) { if (failedWrite) {
if (result >= RESULT_OK) { if (result >= RESULT_OK) {
cout << " failed write " << fields->getName() << " >" cout << " failed write " << fields->getName() << " >"
@@ -177,8 +177,7 @@ int main()
cout << " failed write " << fields->getName() << " >" cout << " failed write " << fields->getName() << " >"
<< expectStr << "< OK" << endl; << expectStr << "< OK" << endl;
} }
} } else if (result < RESULT_OK) {
else if (result < RESULT_OK) {
cout << " write " << fields->getName() << " >" << expectStr cout << " write " << fields->getName() << " >" << expectStr
<< "< error: " << getResultCode(result) << endl; << "< error: " << getResultCode(result) << endl;
error = true; error = true;
@@ -191,6 +190,5 @@ int main()
} }
delete templates; delete templates;
return error ? 1 : 0; return error ? 1 : 0;
} }
+174 -184
View File
@@ -21,12 +21,13 @@
#endif #endif
#include "data.h" #include "data.h"
#include <math.h>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <iomanip> #include <iomanip>
#include <vector> #include <vector>
#include <cstring> #include <cstring>
#include <math.h> #include <algorithm>
using namespace std; using namespace std;
@@ -39,14 +40,13 @@ result_t DataField::create(vector<string>::iterator& it,
DataFieldTemplates* templates, DataField*& returnField, DataFieldTemplates* templates, DataField*& returnField,
const bool isWriteMessage, const bool isWriteMessage,
const bool isTemplate, const bool isBroadcastOrMasterDestination, const bool isTemplate, const bool isBroadcastOrMasterDestination,
const unsigned char maxFieldLength) const unsigned char maxFieldLength) {
{
vector<SingleDataField*> fields; vector<SingleDataField*> fields;
string firstName, firstComment; string firstName, firstComment;
result_t result = RESULT_OK; result_t result = RESULT_OK;
if (it == end) if (it == end) {
return RESULT_ERR_EOF; return RESULT_ERR_EOF;
}
while (it != end && result == RESULT_OK) { while (it != end && result == RESULT_OK) {
string unit, comment; string unit, comment;
PartType partType; PartType partType;
@@ -58,8 +58,9 @@ result_t DataField::create(vector<string>::iterator& it,
// std: name,part,basetype[:len]|template[:name][,[divisor|values][,[unit][,[comment]]]] // std: name,part,basetype[:len]|template[:name][,[divisor|values][,[unit][,[comment]]]]
const string name = *it++; // name const string name = *it++; // name
if (it == end) { if (it == end) {
if (!name.empty()) if (!name.empty()) {
result = RESULT_ERR_MISSING_TYPE; result = RESULT_ERR_MISSING_TYPE;
}
break; break;
} }
@@ -69,8 +70,9 @@ result_t DataField::create(vector<string>::iterator& it,
const char* partStr = (*it++).c_str(); // part const char* partStr = (*it++).c_str(); // part
hasPartStr = partStr[0] != 0; hasPartStr = partStr[0] != 0;
if (it == end) { if (it == end) {
if (!name.empty() || hasPartStr) if (!name.empty() || hasPartStr) {
result = RESULT_ERR_MISSING_TYPE; result = RESULT_ERR_MISSING_TYPE;
}
break; break;
} }
if (isBroadcastOrMasterDestination if (isBroadcastOrMasterDestination
@@ -245,8 +247,7 @@ result_t DataField::create(vector<string>::iterator& it,
return RESULT_OK; return RESULT_OK;
} }
void DataField::dumpString(ostream& output, const string str, const bool prependFieldSeparator) void DataField::dumpString(ostream& output, const string str, const bool prependFieldSeparator) {
{
if (prependFieldSeparator) { if (prependFieldSeparator) {
output << FIELD_SEPARATOR; output << FIELD_SEPARATOR;
} }
@@ -260,8 +261,7 @@ void DataField::dumpString(ostream& output, const string str, const bool prepend
result_t SingleDataField::create(const string id, const unsigned char length, result_t SingleDataField::create(const string id, const unsigned char length,
const string name, const string comment, const string unit, const string name, const string comment, const string unit,
const PartType partType, int divisor, map<unsigned int, string> values, const PartType partType, int divisor, map<unsigned int, string> values,
const string constantValue, const bool verifyValue, SingleDataField* &returnField) const string constantValue, const bool verifyValue, SingleDataField* &returnField) {
{
DataType* dataType = DataTypeList::getInstance()->get(id, length == REMAIN_LEN ? (unsigned char)0 : length); DataType* dataType = DataTypeList::getInstance()->get(id, length == REMAIN_LEN ? (unsigned char)0 : length);
if (!dataType) { if (!dataType) {
return RESULT_ERR_NOTFOUND; return RESULT_ERR_NOTFOUND;
@@ -318,15 +318,15 @@ result_t SingleDataField::create(const string id, const unsigned char length,
return RESULT_OK; return RESULT_OK;
} }
void SingleDataField::dump(ostream& output) void SingleDataField::dump(ostream& output) {
{
output << setw(0) << dec; // initialize formatting output << setw(0) << dec; // initialize formatting
dumpString(output, m_name, false); dumpString(output, m_name, false);
output << FIELD_SEPARATOR; output << FIELD_SEPARATOR;
if (m_partType == pt_masterData) if (m_partType == pt_masterData) {
output << "m"; output << "m";
else if (m_partType == pt_slaveData) } else if (m_partType == pt_slaveData) {
output << "s"; output << "s";
}
output << FIELD_SEPARATOR; output << FIELD_SEPARATOR;
m_dataType->dump(output, m_length); m_dataType->dump(output, m_length);
dumpString(output, m_unit); dumpString(output, m_unit);
@@ -336,11 +336,10 @@ void SingleDataField::dump(ostream& output)
result_t SingleDataField::read(const PartType partType, result_t SingleDataField::read(const PartType partType,
SymbolString& data, unsigned char offset, SymbolString& data, unsigned char offset,
unsigned int& output, const char* fieldName, signed char fieldIndex) unsigned int& output, const char* fieldName, signed char fieldIndex) {
{ if (partType != m_partType) {
if (partType != m_partType)
return RESULT_EMPTY; return RESULT_EMPTY;
}
switch (m_partType) switch (m_partType)
{ {
case pt_masterData: case pt_masterData:
@@ -365,8 +364,7 @@ result_t SingleDataField::read(const PartType partType,
result_t SingleDataField::read(const PartType partType, result_t SingleDataField::read(const PartType partType,
SymbolString& data, unsigned char offset, SymbolString& data, unsigned char offset,
ostringstream& output, OutputFormat outputFormat, signed char outputIndex, ostringstream& output, OutputFormat outputFormat, signed char outputIndex,
bool leadingSeparator, const char* fieldName, signed char fieldIndex) bool leadingSeparator, const char* fieldName, signed char fieldIndex) {
{
if (partType != m_partType) { if (partType != m_partType) {
return RESULT_OK; return RESULT_OK;
} }
@@ -433,8 +431,7 @@ result_t SingleDataField::read(const PartType partType,
result_t SingleDataField::write(istringstream& input, result_t SingleDataField::write(istringstream& input,
const PartType partType, SymbolString& data, const PartType partType, SymbolString& data,
unsigned char offset, char separator, unsigned char* length) unsigned char offset, char separator, unsigned char* length) {
{
if (partType != m_partType) { if (partType != m_partType) {
return RESULT_OK; return RESULT_OK;
} }
@@ -454,45 +451,47 @@ result_t SingleDataField::write(istringstream& input,
result_t SingleDataField::readSymbols(SymbolString& input, const bool isMaster, result_t SingleDataField::readSymbols(SymbolString& input, const bool isMaster,
const unsigned char offset, const unsigned char offset,
ostringstream& output, OutputFormat outputFormat) ostringstream& output, OutputFormat outputFormat) {
{
return m_dataType->readSymbols(input, isMaster, offset, m_length, output, outputFormat); return m_dataType->readSymbols(input, isMaster, offset, m_length, output, outputFormat);
} }
result_t SingleDataField::writeSymbols(istringstream& input, result_t SingleDataField::writeSymbols(istringstream& input,
const unsigned char offset, const unsigned char offset,
SymbolString& output, const bool isMaster, unsigned char* usedLength) SymbolString& output, const bool isMaster, unsigned char* usedLength) {
{
return m_dataType->writeSymbols(input, offset, m_length, output, isMaster, usedLength); return m_dataType->writeSymbols(input, offset, m_length, output, isMaster, usedLength);
} }
SingleDataField* SingleDataField::clone() SingleDataField* SingleDataField::clone() {
{
return new SingleDataField(*this); return new SingleDataField(*this);
} }
result_t SingleDataField::derive(string name, string comment, result_t SingleDataField::derive(string name, string comment,
string unit, const PartType partType, string unit, const PartType partType,
int divisor, map<unsigned int, string> values, int divisor, map<unsigned int, string> values,
vector<SingleDataField*>& fields) vector<SingleDataField*>& fields) {
{ if (m_partType != pt_any && partType == pt_any) {
if (m_partType != pt_any && partType == pt_any)
return RESULT_ERR_INVALID_PART; // cannot create a template from a concrete instance return RESULT_ERR_INVALID_PART; // cannot create a template from a concrete instance
}
bool numeric = m_dataType->isNumeric(); bool numeric = m_dataType->isNumeric();
if (!numeric && (divisor != 0 || !values.empty())) if (!numeric && (divisor != 0 || !values.empty())) {
return RESULT_ERR_INVALID_ARG; // cannot set divisor or values for non-numeric field return RESULT_ERR_INVALID_ARG; // cannot set divisor or values for non-numeric field
if (name.empty()) }
if (name.empty()) {
name = m_name; name = m_name;
if (comment.empty()) }
if (comment.empty()) {
comment = m_comment; comment = m_comment;
if (unit.empty()) }
if (unit.empty()) {
unit = m_unit; unit = m_unit;
}
DataType* dataType = m_dataType; DataType* dataType = m_dataType;
if (numeric) { if (numeric) {
NumberDataType* numType = (NumberDataType*)m_dataType; NumberDataType* numType = (NumberDataType*)m_dataType;
result_t result = numType->derive(divisor, 0, numType); result_t result = numType->derive(divisor, 0, numType);
if (result != RESULT_OK) if (result != RESULT_OK) {
return result; return result;
}
dataType = numType; dataType = numType;
} }
if (values.empty()) { if (values.empty()) {
@@ -503,14 +502,12 @@ result_t SingleDataField::derive(string name, string comment,
return RESULT_OK; return RESULT_OK;
} }
bool SingleDataField::hasField(const char* fieldName, bool numeric) bool SingleDataField::hasField(const char* fieldName, bool numeric) {
{
bool numericType = m_dataType->isNumeric(); bool numericType = m_dataType->isNumeric();
return numeric == numericType && (fieldName == NULL || fieldName == m_name); return numeric == numericType && (fieldName == NULL || fieldName == m_name);
} }
unsigned char SingleDataField::getLength(PartType partType, unsigned char maxLength) unsigned char SingleDataField::getLength(PartType partType, unsigned char maxLength) {
{
if (partType != m_partType) { if (partType != m_partType) {
return (unsigned char)0; return (unsigned char)0;
} }
@@ -518,8 +515,7 @@ unsigned char SingleDataField::getLength(PartType partType, unsigned char maxLen
return remainder ? maxLength : m_length; return remainder ? maxLength : m_length;
} }
bool SingleDataField::hasFullByteOffset(bool after) bool SingleDataField::hasFullByteOffset(bool after) {
{
if (m_length > 1 || !m_dataType->isNumeric()) { if (m_length > 1 || !m_dataType->isNumeric()) {
return true; return true;
} }
@@ -529,49 +525,50 @@ bool SingleDataField::hasFullByteOffset(bool after)
} }
ValueListDataField* ValueListDataField::clone() ValueListDataField* ValueListDataField::clone() {
{
return new ValueListDataField(*this); return new ValueListDataField(*this);
} }
result_t ValueListDataField::derive(string name, string comment, result_t ValueListDataField::derive(string name, string comment,
string unit, const PartType partType, string unit, const PartType partType,
int divisor, map<unsigned int, string> values, int divisor, map<unsigned int, string> values,
vector<SingleDataField*>& fields) vector<SingleDataField*>& fields) {
{ if (m_partType != pt_any && partType == pt_any) {
if (m_partType != pt_any && partType == pt_any)
return RESULT_ERR_INVALID_PART; // cannot create a template from a concrete instance return RESULT_ERR_INVALID_PART; // cannot create a template from a concrete instance
if (name.empty()) }
if (name.empty()) {
name = m_name; name = m_name;
if (comment.empty()) }
if (comment.empty()) {
comment = m_comment; comment = m_comment;
if (unit.empty()) }
if (unit.empty()) {
unit = m_unit; unit = m_unit;
if (divisor != 0 && divisor != 1) }
return RESULT_ERR_INVALID_ARG; // cannot use divisor != 1 for value list field if (divisor != 0 && divisor != 1) {
if (!values.empty()) {
NumberDataType* num = (NumberDataType*)m_dataType;
if (values.begin()->first < num->getMinValue() || values.rbegin()->first > num->getMaxValue())
return RESULT_ERR_INVALID_ARG; // cannot use divisor != 1 for value list field return RESULT_ERR_INVALID_ARG; // cannot use divisor != 1 for value list field
} }
else if (!values.empty()) {
NumberDataType* num = (NumberDataType*)m_dataType;
if (values.begin()->first < num->getMinValue() || values.rbegin()->first > num->getMaxValue()) {
return RESULT_ERR_INVALID_ARG; // cannot use divisor != 1 for value list field
}
} else {
values = m_values; values = m_values;
}
fields.push_back(new ValueListDataField(name, comment, unit, (NumberDataType*)m_dataType, partType, m_length, values)); fields.push_back(new ValueListDataField(name, comment, unit, (NumberDataType*)m_dataType, partType, m_length, values));
return RESULT_OK; return RESULT_OK;
} }
void ValueListDataField::dump(ostream& output) void ValueListDataField::dump(ostream& output) {
{
output << setw(0) << dec; // initialize formatting output << setw(0) << dec; // initialize formatting
dumpString(output, m_name, false); dumpString(output, m_name, false);
output << FIELD_SEPARATOR; output << FIELD_SEPARATOR;
if (m_partType == pt_masterData) if (m_partType == pt_masterData) {
output << "m"; output << "m";
else if (m_partType == pt_slaveData) } else if (m_partType == pt_slaveData) {
output << "s"; output << "s";
}
output << FIELD_SEPARATOR; output << FIELD_SEPARATOR;
if (!m_dataType->dump(output, m_length)) { // no divisor appended if (!m_dataType->dump(output, m_length)) { // no divisor appended
for (map<unsigned int, string>::iterator it = m_values.begin(); it != m_values.end(); it++) { for (map<unsigned int, string>::iterator it = m_values.begin(); it != m_values.end(); it++) {
@@ -587,13 +584,13 @@ void ValueListDataField::dump(ostream& output)
result_t ValueListDataField::readSymbols(SymbolString& input, const bool isMaster, result_t ValueListDataField::readSymbols(SymbolString& input, const bool isMaster,
const unsigned char offset, const unsigned char offset,
ostringstream& output, OutputFormat outputFormat) ostringstream& output, OutputFormat outputFormat) {
{
unsigned int value = 0; unsigned int value = 0;
result_t result = m_dataType->readRawValue(input, offset, m_length, value); result_t result = m_dataType->readRawValue(input, offset, m_length, value);
if (result != RESULT_OK) if (result != RESULT_OK) {
return result; return result;
}
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() && value != m_dataType->getReplacement()) { if (it == m_values.end() && value != m_dataType->getReplacement()) {
// fall back to raw value in input // fall back to raw value in input
@@ -601,85 +598,90 @@ result_t ValueListDataField::readSymbols(SymbolString& input, const bool isMaste
return RESULT_OK; return RESULT_OK;
} }
if (it == m_values.end()) { if (it == m_values.end()) {
if (outputFormat & OF_JSON) if (outputFormat & OF_JSON) {
output << "null"; output << "null";
else if (value == m_dataType->getReplacement()) } else if (value == m_dataType->getReplacement()) {
output << NULL_VALUE; output << NULL_VALUE;
} else if (outputFormat & OF_NUMERIC) }
} else if (outputFormat & OF_NUMERIC) {
output << setw(0) << dec << static_cast<unsigned>(value); output << setw(0) << dec << static_cast<unsigned>(value);
else if (outputFormat & OF_JSON) } else if (outputFormat & OF_JSON) {
output << '"' << it->second << '"'; output << '"' << it->second << '"';
else } else {
output << it->second; output << it->second;
}
return RESULT_OK; return RESULT_OK;
} }
result_t ValueListDataField::writeSymbols(istringstream& input, result_t ValueListDataField::writeSymbols(istringstream& input,
const unsigned char offset, const unsigned char offset,
SymbolString& output, const bool isMaster, unsigned char* usedLength) SymbolString& output, const bool isMaster, unsigned char* usedLength) {
{
NumberDataType* numType = (NumberDataType*)m_dataType; NumberDataType* numType = (NumberDataType*)m_dataType;
if (isIgnored()) if (isIgnored()) {
return numType->writeRawValue(numType->getReplacement(), offset, m_length, output, usedLength); // replacement value return numType->writeRawValue(numType->getReplacement(), offset, m_length, output, usedLength); // replacement value
}
const char* str = input.str().c_str(); const char* str = input.str().c_str();
for (map<unsigned int, string>::iterator it = m_values.begin(); it != m_values.end(); it++) for (map<unsigned int, string>::iterator it = m_values.begin(); it != m_values.end(); it++) {
if (it->second.compare(str) == 0) if (it->second.compare(str) == 0) {
return numType->writeRawValue(it->first, offset, m_length, output, usedLength); return numType->writeRawValue(it->first, offset, m_length, output, usedLength);
}
if (strcasecmp(str, NULL_VALUE) == 0) }
if (strcasecmp(str, NULL_VALUE) == 0) {
return numType->writeRawValue(numType->getReplacement(), offset, m_length, output, usedLength); // replacement value return numType->writeRawValue(numType->getReplacement(), offset, m_length, output, usedLength); // replacement value
}
char* strEnd = NULL; // fall back to raw value in input char* strEnd = NULL; // fall back to raw value in input
unsigned int value; unsigned int value;
value = (unsigned int)strtoul(str, &strEnd, 10); value = (unsigned int)strtoul(str, &strEnd, 10);
if (strEnd == NULL || strEnd == str || (*strEnd != 0 && *strEnd != '.')) if (strEnd == NULL || strEnd == str || (*strEnd != 0 && *strEnd != '.')) {
return RESULT_ERR_INVALID_NUM; // invalid value return RESULT_ERR_INVALID_NUM; // invalid value
if (m_values.find(value) != m_values.end()) }
if (m_values.find(value) != m_values.end()) {
return numType->writeRawValue(value, offset, m_length, output, usedLength); return numType->writeRawValue(value, offset, m_length, output, usedLength);
}
return RESULT_ERR_NOTFOUND; // value assignment not found return RESULT_ERR_NOTFOUND; // value assignment not found
} }
ConstantDataField* ConstantDataField::clone() ConstantDataField* ConstantDataField::clone() {
{
return new ConstantDataField(*this); return new ConstantDataField(*this);
} }
result_t ConstantDataField::derive(string name, string comment, result_t ConstantDataField::derive(string name, string comment,
string unit, const PartType partType, string unit, const PartType partType,
int divisor, map<unsigned int, string> values, int divisor, map<unsigned int, string> values,
vector<SingleDataField*>& fields) vector<SingleDataField*>& fields) {
{ if (m_partType != pt_any && partType == pt_any) {
if (m_partType != pt_any && partType == pt_any)
return RESULT_ERR_INVALID_PART; // cannot create a template from a concrete instance return RESULT_ERR_INVALID_PART; // cannot create a template from a concrete instance
if (name.empty()) }
if (name.empty()) {
name = m_name; name = m_name;
if (comment.empty()) }
if (comment.empty()) {
comment = m_comment; comment = m_comment;
if (unit.empty()) }
if (unit.empty()) {
unit = m_unit; unit = m_unit;
if (divisor != 0) }
if (divisor != 0) {
return RESULT_ERR_INVALID_ARG; // cannot use other than current divisor for constant value field return RESULT_ERR_INVALID_ARG; // cannot use other than current divisor for constant value field
}
if (!values.empty()) { if (!values.empty()) {
return RESULT_ERR_INVALID_ARG; // cannot use value list for constant value field return RESULT_ERR_INVALID_ARG; // cannot use value list for constant value field
} }
fields.push_back(new ConstantDataField(name, comment, unit, m_dataType, partType, m_length, m_value, m_verify)); fields.push_back(new ConstantDataField(name, comment, unit, m_dataType, partType, m_length, m_value, m_verify));
return RESULT_OK; return RESULT_OK;
} }
void ConstantDataField::dump(ostream& output) void ConstantDataField::dump(ostream& output) {
{
output << setw(0) << dec; // initialize formatting output << setw(0) << dec; // initialize formatting
dumpString(output, m_name, false); dumpString(output, m_name, false);
output << FIELD_SEPARATOR; output << FIELD_SEPARATOR;
if (m_partType == pt_masterData) if (m_partType == pt_masterData) {
output << "m"; output << "m";
else if (m_partType == pt_slaveData) } else if (m_partType == pt_slaveData) {
output << "s"; output << "s";
}
output << FIELD_SEPARATOR; output << FIELD_SEPARATOR;
if (!m_dataType->dump(output, m_length)) { // no divisor appended if (!m_dataType->dump(output, m_length)) { // no divisor appended
output << (m_verify?"==":"=") << m_value; output << (m_verify?"==":"=") << m_value;
@@ -690,8 +692,7 @@ void ConstantDataField::dump(ostream& output)
result_t ConstantDataField::readSymbols(SymbolString& input, const bool isMaster, result_t ConstantDataField::readSymbols(SymbolString& input, const bool isMaster,
const unsigned char offset, const unsigned char offset,
ostringstream& output, OutputFormat outputFormat) ostringstream& output, OutputFormat outputFormat) {
{
ostringstream coutput; ostringstream coutput;
result_t result = SingleDataField::readSymbols(input, isMaster, offset, coutput, 0); result_t result = SingleDataField::readSymbols(input, isMaster, offset, coutput, 0);
if (result != RESULT_OK) { if (result != RESULT_OK) {
@@ -709,8 +710,7 @@ result_t ConstantDataField::readSymbols(SymbolString& input, const bool isMaster
result_t ConstantDataField::writeSymbols(istringstream& input, result_t ConstantDataField::writeSymbols(istringstream& input,
const unsigned char offset, const unsigned char offset,
SymbolString& output, const bool isMaster, unsigned char* usedLength) SymbolString& output, const bool isMaster, unsigned char* usedLength) {
{
istringstream cinput(m_value); istringstream cinput(m_value);
return SingleDataField::writeSymbols(cinput, offset, output, isMaster, usedLength); return SingleDataField::writeSymbols(cinput, offset, output, isMaster, usedLength);
} }
@@ -718,8 +718,7 @@ result_t ConstantDataField::writeSymbols(istringstream& input,
DataFieldSet* DataFieldSet::s_identFields = NULL; DataFieldSet* DataFieldSet::s_identFields = NULL;
DataFieldSet* DataFieldSet::getIdentFields() DataFieldSet* DataFieldSet::getIdentFields() {
{
if (s_identFields == NULL) { if (s_identFields == NULL) {
NumberDataType* uchDataType = (NumberDataType*)DataTypeList::getInstance()->get("UCH"); NumberDataType* uchDataType = (NumberDataType*)DataTypeList::getInstance()->get("UCH");
StringDataType* stringDataType = (StringDataType*)DataTypeList::getInstance()->get("STR"); StringDataType* stringDataType = (StringDataType*)DataTypeList::getInstance()->get("STR");
@@ -760,16 +759,14 @@ DataFieldSet* DataFieldSet::getIdentFields()
return s_identFields; return s_identFields;
} }
DataFieldSet::~DataFieldSet() DataFieldSet::~DataFieldSet() {
{
while (!m_fields.empty()) { while (!m_fields.empty()) {
delete m_fields.back(); delete m_fields.back();
m_fields.pop_back(); m_fields.pop_back();
} }
} }
DataFieldSet* DataFieldSet::clone() DataFieldSet* DataFieldSet::clone() {
{
vector<SingleDataField*> fields; vector<SingleDataField*> fields;
for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) { for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) {
fields.push_back((*it)->clone()); fields.push_back((*it)->clone());
@@ -777,23 +774,22 @@ DataFieldSet* DataFieldSet::clone()
return new DataFieldSet(m_name, m_comment, fields); return new DataFieldSet(m_name, m_comment, fields);
} }
unsigned char DataFieldSet::getLength(PartType partType, unsigned char maxLength) unsigned char DataFieldSet::getLength(PartType partType, unsigned char maxLength) {
{
unsigned char length = 0; unsigned char length = 0;
bool previousFullByteOffset[] = { true, true, true, true }; bool previousFullByteOffset[] = { true, true, true, true };
for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) { for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) {
SingleDataField* field = *it; SingleDataField* field = *it;
if (field->getPartType() == partType) { if (field->getPartType() == partType) {
if (!previousFullByteOffset[partType] && !field->hasFullByteOffset(false)) if (!previousFullByteOffset[partType] && !field->hasFullByteOffset(false)) {
length--; length--;
}
unsigned char fieldLength = field->getLength(partType, maxLength); unsigned char fieldLength = field->getLength(partType, maxLength);
if (fieldLength>=maxLength) if (fieldLength >= maxLength) {
maxLength = 0; maxLength = 0;
else } else {
maxLength = (unsigned char)(maxLength-fieldLength); maxLength = (unsigned char)(maxLength-fieldLength);
}
length = (unsigned char)(length + fieldLength); length = (unsigned char)(length + fieldLength);
previousFullByteOffset[partType] = field->hasFullByteOffset(true); previousFullByteOffset[partType] = field->hasFullByteOffset(true);
@@ -803,8 +799,7 @@ unsigned char DataFieldSet::getLength(PartType partType, unsigned char maxLength
return length; return length;
} }
string DataFieldSet::getName(signed char fieldIndex) string DataFieldSet::getName(signed char fieldIndex) {
{
if (fieldIndex < 0) { if (fieldIndex < 0) {
return m_name; return m_name;
} }
@@ -822,33 +817,33 @@ string DataFieldSet::getName(signed char fieldIndex)
result_t DataFieldSet::derive(string name, string comment, result_t DataFieldSet::derive(string name, string comment,
string unit, const PartType partType, string unit, const PartType partType,
int divisor, map<unsigned int, string> values, int divisor, map<unsigned int, string> values,
vector<SingleDataField*>& fields) vector<SingleDataField*>& fields) {
{ if (!values.empty()) {
if (!values.empty())
return RESULT_ERR_INVALID_ARG; // value list not allowed in set derive return RESULT_ERR_INVALID_ARG; // value list not allowed in set derive
}
bool first = true; bool first = true;
for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) { for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) {
result_t result = (*it)->derive("", first?comment:"", first?unit:"", partType, divisor, values, fields); result_t result = (*it)->derive("", first?comment:"", first?unit:"", partType, divisor, values, fields);
if (result != RESULT_OK) if (result != RESULT_OK) {
return result; return result;
}
first = false; first = false;
} }
return RESULT_OK; return RESULT_OK;
} }
bool DataFieldSet::hasField(const char* fieldName, bool numeric) bool DataFieldSet::hasField(const char* fieldName, bool numeric) {
{
for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) { for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) {
SingleDataField* field = *it; SingleDataField* field = *it;
if (field->hasField(fieldName, numeric)==0) if (field->hasField(fieldName, numeric) == 0) {
return true; return true;
} }
}
return false; return false;
} }
void DataFieldSet::dump(ostream& output) void DataFieldSet::dump(ostream& output) {
{
bool first = true; bool first = true;
for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) { for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) {
if (first) { if (first) {
@@ -862,22 +857,20 @@ void DataFieldSet::dump(ostream& output)
result_t DataFieldSet::read(const PartType partType, result_t DataFieldSet::read(const PartType partType,
SymbolString& data, unsigned char offset, SymbolString& data, unsigned char offset,
unsigned int& output, const char* fieldName, signed char fieldIndex) unsigned int& output, const char* fieldName, signed char fieldIndex) {
{
bool previousFullByteOffset = true, found = false, findFieldIndex = fieldName != NULL && fieldIndex >= 0; bool previousFullByteOffset = true, found = false, findFieldIndex = fieldName != NULL && fieldIndex >= 0;
for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) { for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) {
SingleDataField* field = *it; SingleDataField* field = *it;
if (partType != pt_any && field->getPartType() != partType) if (partType != pt_any && field->getPartType() != partType) {
continue; continue;
}
if (!previousFullByteOffset && !field->hasFullByteOffset(false)) if (!previousFullByteOffset && !field->hasFullByteOffset(false)) {
offset--; offset--;
}
result_t result = field->read(partType, data, offset, output, fieldName, fieldIndex); result_t result = field->read(partType, data, offset, output, fieldName, fieldIndex);
if (result < RESULT_OK) {
if (result < RESULT_OK)
return result; return result;
}
offset = (unsigned char)(offset + field->getLength(partType, (unsigned char)(data.size()-offset))); offset = (unsigned char)(offset + field->getLength(partType, (unsigned char)(data.size()-offset)));
previousFullByteOffset = field->hasFullByteOffset(true); previousFullByteOffset = field->hasFullByteOffset(true);
if (result != RESULT_EMPTY) { if (result != RESULT_EMPTY) {
@@ -885,8 +878,9 @@ result_t DataFieldSet::read(const PartType partType,
} }
if (findFieldIndex && fieldName == field->getName()) { if (findFieldIndex && fieldName == field->getName()) {
if (fieldIndex == 0) { if (fieldIndex == 0) {
if (!found) if (!found) {
return RESULT_ERR_NOTFOUND; return RESULT_ERR_NOTFOUND;
}
break; break;
} }
fieldIndex--; fieldIndex--;
@@ -903,26 +897,26 @@ result_t DataFieldSet::read(const PartType partType,
result_t DataFieldSet::read(const PartType partType, result_t DataFieldSet::read(const PartType partType,
SymbolString& data, unsigned char offset, SymbolString& data, unsigned char offset,
ostringstream& output, OutputFormat outputFormat, signed char outputIndex, ostringstream& output, OutputFormat outputFormat, signed char outputIndex,
bool leadingSeparator, const char* fieldName, signed char fieldIndex) bool leadingSeparator, const char* fieldName, signed char fieldIndex) {
{
bool previousFullByteOffset = true, found = false, findFieldIndex = fieldName != NULL && fieldIndex >= 0; bool previousFullByteOffset = true, found = false, findFieldIndex = fieldName != NULL && fieldIndex >= 0;
if (!m_uniqueNames && outputIndex<0) if (!m_uniqueNames && outputIndex < 0) {
outputIndex = 0; outputIndex = 0;
}
for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) { for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) {
SingleDataField* field = *it; SingleDataField* field = *it;
if (partType != pt_any && field->getPartType() != partType) { if (partType != pt_any && field->getPartType() != partType) {
if (outputIndex>=0 && !field->isIgnored()) if (outputIndex >= 0 && !field->isIgnored()) {
outputIndex++; outputIndex++;
}
continue; continue;
} }
if (!previousFullByteOffset && !field->hasFullByteOffset(false)) if (!previousFullByteOffset && !field->hasFullByteOffset(false)) {
offset--; offset--;
}
result_t result = field->read(partType, data, offset, output, outputFormat, outputIndex, leadingSeparator, fieldName, fieldIndex); result_t result = field->read(partType, data, offset, output, outputFormat, outputIndex, leadingSeparator, fieldName, fieldIndex);
if (result < RESULT_OK) {
if (result < RESULT_OK)
return result; return result;
}
offset = (unsigned char)(offset + field->getLength(partType, (unsigned char)(data.size()-offset))); offset = (unsigned char)(offset + field->getLength(partType, (unsigned char)(data.size()-offset)));
previousFullByteOffset = field->hasFullByteOffset(true); previousFullByteOffset = field->hasFullByteOffset(true);
if (result != RESULT_EMPTY) { if (result != RESULT_EMPTY) {
@@ -931,15 +925,17 @@ result_t DataFieldSet::read(const PartType partType,
} }
if (findFieldIndex && fieldName == field->getName()) { if (findFieldIndex && fieldName == field->getName()) {
if (fieldIndex == 0) { if (fieldIndex == 0) {
if (!found) if (!found) {
return RESULT_ERR_NOTFOUND; return RESULT_ERR_NOTFOUND;
}
break; break;
} }
fieldIndex--; fieldIndex--;
} }
if (outputIndex>=0 && !field->isIgnored()) if (outputIndex >= 0 && !field->isIgnored()) {
outputIndex++; outputIndex++;
} }
}
if (!found) { if (!found) {
return RESULT_EMPTY; return RESULT_EMPTY;
@@ -957,57 +953,54 @@ result_t DataFieldSet::read(const PartType partType,
result_t DataFieldSet::write(istringstream& input, result_t DataFieldSet::write(istringstream& input,
const PartType partType, SymbolString& data, const PartType partType, SymbolString& data,
unsigned char offset, char separator, unsigned char* length) unsigned char offset, char separator, unsigned char* length) {
{
string token; string token;
bool previousFullByteOffset = true; bool previousFullByteOffset = true;
unsigned char baseOffset = offset; unsigned char baseOffset = offset;
for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) { for (vector<SingleDataField*>::iterator it = m_fields.begin(); it < m_fields.end(); it++) {
SingleDataField* field = *it; SingleDataField* field = *it;
if (partType != pt_any && field->getPartType() != partType) if (partType != pt_any && field->getPartType() != partType) {
continue; continue;
}
if (!previousFullByteOffset && !field->hasFullByteOffset(false)) if (!previousFullByteOffset && !field->hasFullByteOffset(false)) {
offset--; offset--;
}
result_t result; result_t result;
unsigned char fieldLength; unsigned char fieldLength;
if (m_fields.size() > 1) { if (m_fields.size() > 1) {
if (field->isIgnored()) if (field->isIgnored()) {
token.clear(); token.clear();
else if (!getline(input, token, separator)) } else if (!getline(input, token, separator)) {
token.clear(); token.clear();
}
istringstream single(token); istringstream single(token);
result = (*it)->write(single, partType, data, offset, separator, &fieldLength); result = (*it)->write(single, partType, data, offset, separator, &fieldLength);
} } else {
else
result = (*it)->write(input, partType, data, offset, separator, &fieldLength); result = (*it)->write(input, partType, data, offset, separator, &fieldLength);
}
if (result != RESULT_OK) if (result != RESULT_OK) {
return result; return result;
}
offset = (unsigned char)(offset+fieldLength); offset = (unsigned char)(offset+fieldLength);
previousFullByteOffset = field->hasFullByteOffset(true); previousFullByteOffset = field->hasFullByteOffset(true);
} }
if (length!=NULL) if (length != NULL) {
*length = (unsigned char)(offset-baseOffset); *length = (unsigned char)(offset-baseOffset);
}
return RESULT_OK; return RESULT_OK;
} }
DataFieldTemplates::DataFieldTemplates(DataFieldTemplates& other) DataFieldTemplates::DataFieldTemplates(DataFieldTemplates& other)
: FileReader::FileReader(false) : FileReader::FileReader(false) {
{
for (map<string, DataField*>::iterator it = other.m_fieldsByName.begin(); it != other.m_fieldsByName.end(); it++) { for (map<string, DataField*>::iterator it = other.m_fieldsByName.begin(); it != other.m_fieldsByName.end(); it++) {
m_fieldsByName[it->first] = it->second->clone(); m_fieldsByName[it->first] = it->second->clone();
} }
} }
void DataFieldTemplates::clear() void DataFieldTemplates::clear() {
{
for (map<string, DataField*>::iterator it = m_fieldsByName.begin(); it != m_fieldsByName.end(); it++) { for (map<string, DataField*>::iterator it = m_fieldsByName.begin(); it != m_fieldsByName.end(); it++) {
delete it->second; delete it->second;
it->second = NULL; it->second = NULL;
@@ -1015,30 +1008,27 @@ void DataFieldTemplates::clear()
m_fieldsByName.clear(); m_fieldsByName.clear();
} }
result_t DataFieldTemplates::add(DataField* field, string name, bool replace) result_t DataFieldTemplates::add(DataField* field, string name, bool replace) {
{ if (name.length() == 0) {
if (name.length() == 0)
name = field->getName(); name = field->getName();
}
map<string, DataField*>::iterator it = m_fieldsByName.find(name); map<string, DataField*>::iterator it = m_fieldsByName.find(name);
if (it != m_fieldsByName.end()) { if (it != m_fieldsByName.end()) {
if (!replace) if (!replace) {
return RESULT_ERR_DUPLICATE_NAME; // duplicate key return RESULT_ERR_DUPLICATE_NAME; // duplicate key
}
delete it->second; delete it->second;
it->second = field; it->second = field;
return RESULT_OK; return RESULT_OK;
} }
m_fieldsByName[name] = field; m_fieldsByName[name] = field;
return RESULT_OK; return RESULT_OK;
} }
result_t DataFieldTemplates::addFromFile(vector<string>::iterator& begin, const vector<string>::iterator end, result_t DataFieldTemplates::addFromFile(vector<string>::iterator& begin, const vector<string>::iterator end,
vector< vector<string> >* defaults, const string& defaultDest, const string& defaultCircuit, const string& defaultSuffix, vector< vector<string> >* defaults, const string& defaultDest, const string& defaultCircuit, const string& defaultSuffix,
const string& filename, unsigned int lineNo) const string& filename, unsigned int lineNo) {
{
vector<string>::iterator restart = begin; vector<string>::iterator restart = begin;
DataField* field = NULL; DataField* field = NULL;
string name; string name;
@@ -1050,23 +1040,23 @@ result_t DataFieldTemplates::addFromFile(vector<string>::iterator& begin, const
} }
} }
result_t result = DataField::create(begin, end, this, field, false, true, false); result_t result = DataField::create(begin, end, this, field, false, true, false);
if (result != RESULT_OK) if (result != RESULT_OK) {
return result; return result;
}
result = add(field, name, true); result = add(field, name, true);
if (result==RESULT_ERR_DUPLICATE_NAME) if (result == RESULT_ERR_DUPLICATE_NAME) {
begin = restart+1; // mark name as invalid begin = restart+1; // mark name as invalid
if (result != RESULT_OK) }
if (result != RESULT_OK) {
delete field; delete field;
}
return result; return result;
} }
DataField* DataFieldTemplates::get(const string name) DataField* DataFieldTemplates::get(const string name) {
{
map<string, DataField*>::const_iterator ref = m_fieldsByName.find(name); map<string, DataField*>::const_iterator ref = m_fieldsByName.find(name);
if (ref == m_fieldsByName.end()) if (ref == m_fieldsByName.end()) {
return NULL; return NULL;
}
return ref->second; return ref->second;
} }
+12 -10
View File
@@ -16,19 +16,19 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef LIBEBUS_DATA_H_ #ifndef LIB_EBUS_DATA_H_
#define LIBEBUS_DATA_H_ #define LIB_EBUS_DATA_H_
#include "symbol.h"
#include "result.h"
#include "filereader.h"
#include "datatype.h"
#include <string> #include <string>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <fstream> #include <fstream>
#include <vector> #include <vector>
#include <map> #include <map>
#include "symbol.h"
#include "result.h"
#include "filereader.h"
#include "datatype.h"
/** @file data.h /** @file data.h
* Classes related to defining fields based on data types in symbols on the * Classes related to defining fields based on data types in symbols on the
@@ -528,7 +528,9 @@ public:
map<string, string> names; map<string, string> names;
for (vector<SingleDataField*>::const_iterator it = fields.begin(); it != fields.end(); it++) { for (vector<SingleDataField*>::const_iterator it = fields.begin(); it != fields.end(); it++) {
SingleDataField* field = *it; SingleDataField* field = *it;
if (field->isIgnored()) continue; if (field->isIgnored()) {
continue;
}
string name = field->getName(); string name = field->getName();
if (name.empty() || names.find(name) != names.end()) { if (name.empty() || names.find(name) != names.end()) {
uniqueNames = false; uniqueNames = false;
@@ -564,14 +566,14 @@ public:
* @param index the index of the @a SingleDataField to return. * @param index the index of the @a SingleDataField to return.
* @return the @a SingleDataField at the specified index, or NULL. * @return the @a SingleDataField at the specified index, or NULL.
*/ */
SingleDataField* operator[](const size_t index) { if (index >= m_fields.size()) return NULL; return m_fields[index]; } SingleDataField* operator[](const size_t index) { if (index >= m_fields.size()) { return NULL; } return m_fields[index]; }
/** /**
* Returns the @a SingleDataField at the specified index. * Returns the @a SingleDataField at the specified index.
* @param index the index of the @a SingleDataField to return. * @param index the index of the @a SingleDataField to return.
* @return the @a SingleDataField at the specified index, or NULL. * @return the @a SingleDataField at the specified index, or NULL.
*/ */
const SingleDataField* operator[](const size_t index) const { if (index >= m_fields.size()) return NULL; return m_fields[index]; } const SingleDataField* operator[](const size_t index) const { if (index >= m_fields.size()) { return NULL; } return m_fields[index]; }
/** /**
* Returns the number of @a SingleDataFields instances in this set. * Returns the number of @a SingleDataFields instances in this set.
@@ -675,4 +677,4 @@ private:
}; };
#endif // LIBEBUS_DATA_H_ #endif // LIB_EBUS_DATA_H_
+30 -43
View File
@@ -21,13 +21,12 @@
#endif #endif
#include "datatype.h" #include "datatype.h"
#include <math.h>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
#include <iomanip> #include <iomanip>
#include <vector> #include <vector>
#include <cstring> #include <cstring>
#include <math.h>
#ifdef HAVE_CONTRIB #ifdef HAVE_CONTRIB
# include "contrib/contrib.h" # include "contrib/contrib.h"
#endif #endif
@@ -76,8 +75,7 @@ int parseSignedInt(const char* str, int base, const int minValue, const int maxV
return (int)ret; return (int)ret;
} }
void printErrorPos(ostream& out, vector<string>::iterator begin, const vector<string>::iterator end, vector<string>::iterator pos, string filename, size_t lineNo, result_t result) void printErrorPos(ostream& out, vector<string>::iterator begin, const vector<string>::iterator end, vector<string>::iterator pos, string filename, size_t lineNo, result_t result) {
{
if (pos > begin) { if (pos > begin) {
pos--; pos--;
} }
@@ -141,15 +139,13 @@ bool DataType::dump(ostream& output, const unsigned char length) const
result_t StringDataType::readRawValue(SymbolString& input, const unsigned char offset, result_t StringDataType::readRawValue(SymbolString& input, const unsigned char offset,
const unsigned char length, unsigned int& value) const unsigned char length, unsigned int& value) {
{
return RESULT_EMPTY; return RESULT_EMPTY;
} }
result_t StringDataType::readSymbols(SymbolString& input, const bool isMaster, result_t StringDataType::readSymbols(SymbolString& input, const bool isMaster,
const unsigned char baseOffset, const unsigned char length, const unsigned char baseOffset, const unsigned char length,
ostringstream& output, OutputFormat outputFormat) ostringstream& output, OutputFormat outputFormat) {
{
size_t start = 0, count = length; size_t start = 0, count = length;
int incr = 1; int incr = 1;
unsigned char ch; unsigned char ch;
@@ -200,8 +196,7 @@ result_t StringDataType::readSymbols(SymbolString& input, const bool isMaster,
result_t StringDataType::writeSymbols(istringstream& input, result_t StringDataType::writeSymbols(istringstream& input,
unsigned char baseOffset, const unsigned char length, unsigned char baseOffset, const unsigned char length,
SymbolString& output, const bool isMaster, unsigned char* usedLength) SymbolString& output, const bool isMaster, unsigned char* usedLength) {
{
size_t start = 0, count = length; size_t start = 0, count = length;
bool remainder = count == REMAIN_LEN && hasFlag(ADJ); bool remainder = count == REMAIN_LEN && hasFlag(ADJ);
int incr = 1; int incr = 1;
@@ -244,18 +239,20 @@ result_t StringDataType::writeSymbols(istringstream& input,
return RESULT_ERR_INVALID_NUM; // too short hex value return RESULT_ERR_INVALID_NUM; // too short hex value
} }
value = parseInt(token.c_str(), 16, 0, 0xff, result); value = parseInt(token.c_str(), 16, 0, 0xff, result);
if (result != RESULT_OK) if (result != RESULT_OK) {
return result; // invalid hex value return result; // invalid hex value
} }
}
} else { } else {
if (input.eof()) { if (input.eof()) {
value = m_replacement; value = m_replacement;
} else { } else {
value = input.get(); value = input.get();
if (input.eof() || value < 0x20) if (input.eof() || value < 0x20) {
value = m_replacement; value = m_replacement;
} }
} }
}
if (remainder && input.eof() && i > 0) { if (remainder && input.eof() && i > 0) {
if (value == 0x00 && !m_isHex) { if (value == 0x00 && !m_isHex) {
output[baseOffset + offset] = 0; output[baseOffset + offset] = 0;
@@ -280,15 +277,13 @@ result_t StringDataType::writeSymbols(istringstream& input,
result_t DateTimeDataType::readRawValue(SymbolString& input, const unsigned char offset, result_t DateTimeDataType::readRawValue(SymbolString& input, const unsigned char offset,
const unsigned char length, unsigned int& value) const unsigned char length, unsigned int& value) {
{
return RESULT_EMPTY; return RESULT_EMPTY;
} }
result_t DateTimeDataType::readSymbols(SymbolString& input, const bool isMaster, result_t DateTimeDataType::readSymbols(SymbolString& input, const bool isMaster,
const unsigned char baseOffset, const unsigned char length, const unsigned char baseOffset, const unsigned char length,
ostringstream& output, OutputFormat outputFormat) ostringstream& output, OutputFormat outputFormat) {
{
size_t start = 0, count = length; size_t start = 0, count = length;
int incr = 1; int incr = 1;
unsigned char ch, last = 0, hour = 0; unsigned char ch, last = 0, hour = 0;
@@ -402,8 +397,9 @@ result_t DateTimeDataType::readSymbols(SymbolString& input, const bool isMaster,
} else if (ch > 59 || (hour == 24 && ch > 0)) { } else if (ch > 59 || (hour == 24 && ch > 0)) {
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) << dec << setfill('0') << static_cast<unsigned>(ch); output << setw(2) << dec << setfill('0') << static_cast<unsigned>(ch);
break; break;
} }
@@ -417,8 +413,7 @@ result_t DateTimeDataType::readSymbols(SymbolString& input, const bool isMaster,
result_t DateTimeDataType::writeSymbols(istringstream& input, result_t DateTimeDataType::writeSymbols(istringstream& input,
unsigned char baseOffset, const unsigned char length, unsigned char baseOffset, const unsigned char length,
SymbolString& output, const bool isMaster, unsigned char* usedLength) SymbolString& output, const bool isMaster, unsigned char* usedLength) {
{
size_t start = 0, count = length; size_t start = 0, count = length;
bool remainder = count == REMAIN_LEN && hasFlag(ADJ); bool remainder = count == REMAIN_LEN && hasFlag(ADJ);
int incr = 1; int incr = 1;
@@ -450,8 +445,9 @@ result_t DateTimeDataType::writeSymbols(istringstream& input,
switch (type) switch (type)
{ {
case 2: // date only case 2: // date only
if (length == 4 && i == 2) if (length == 4 && i == 2) {
continue; // skip weekday in between continue; // skip weekday in between
}
if (input.eof() || !getline(input, token, '.')) { if (input.eof() || !getline(input, token, '.')) {
return RESULT_ERR_EOF; // incomplete return RESULT_ERR_EOF; // incomplete
} }
@@ -607,8 +603,7 @@ bool NumberDataType::dump(ostream& output, unsigned char length) const
return false; return false;
} }
result_t NumberDataType::derive(int divisor, unsigned char bitCount, NumberDataType* &derived) result_t NumberDataType::derive(int divisor, unsigned char bitCount, NumberDataType* &derived) {
{
if (divisor == 0) { if (divisor == 0) {
divisor = 1; divisor = 1;
} }
@@ -663,8 +658,7 @@ result_t NumberDataType::derive(int divisor, unsigned char bitCount, NumberDataT
result_t NumberDataType::readRawValue(SymbolString& input, result_t NumberDataType::readRawValue(SymbolString& input,
unsigned char baseOffset, const unsigned char length, unsigned char baseOffset, const unsigned char length,
unsigned int& value) unsigned int& value) {
{
size_t start = 0, count = length; size_t start = 0, count = length;
int incr = 1; int incr = 1;
unsigned char ch; unsigned char ch;
@@ -687,12 +681,13 @@ result_t NumberDataType::readRawValue(SymbolString& input,
return RESULT_OK; return RESULT_OK;
} }
if (!hasFlag(HCD)) { if (!hasFlag(HCD)) {
if ((ch & 0xf0) > 0x90 || (ch & 0x0f) > 0x09) if ((ch & 0xf0) > 0x90 || (ch & 0x0f) > 0x09) {
return RESULT_ERR_OUT_OF_RANGE; // invalid BCD return RESULT_ERR_OUT_OF_RANGE; // invalid BCD
}
ch = (unsigned char)((ch >> 4) * 10 + (ch & 0x0f)); ch = (unsigned char)((ch >> 4) * 10 + (ch & 0x0f));
} else if (ch > 0x63) } else if (ch > 0x63) {
return RESULT_ERR_OUT_OF_RANGE; // invalid HCD return RESULT_ERR_OUT_OF_RANGE; // invalid HCD
}
value += ch * exp; value += ch * exp;
exp *= 100; exp *= 100;
} else { } else {
@@ -711,8 +706,7 @@ result_t NumberDataType::readRawValue(SymbolString& input,
result_t NumberDataType::readSymbols(SymbolString& input, const bool isMaster, result_t NumberDataType::readSymbols(SymbolString& input, const bool isMaster,
const unsigned char baseOffset, const unsigned char length, const unsigned char baseOffset, const unsigned char length,
ostringstream& output, OutputFormat outputFormat) ostringstream& output, OutputFormat outputFormat) {
{
unsigned int value = 0; unsigned int value = 0;
int signedValue; int signedValue;
@@ -810,8 +804,7 @@ result_t NumberDataType::readSymbols(SymbolString& input, const bool isMaster,
result_t NumberDataType::writeRawValue(unsigned int value, result_t NumberDataType::writeRawValue(unsigned int value,
const unsigned char baseOffset, const unsigned char length, const unsigned char baseOffset, const unsigned char length,
SymbolString& output, unsigned char* usedLength) SymbolString& output, unsigned char* usedLength) {
{
size_t start = 0, count = length; size_t start = 0, count = length;
int incr = 1; int incr = 1;
unsigned char ch; unsigned char ch;
@@ -857,8 +850,7 @@ result_t NumberDataType::writeRawValue(unsigned int value,
result_t NumberDataType::writeSymbols(istringstream& input, result_t NumberDataType::writeSymbols(istringstream& input,
const unsigned char baseOffset, const unsigned char length, const unsigned char baseOffset, const unsigned char length,
SymbolString& output, const bool isMaster, unsigned char* usedLength) SymbolString& output, const bool isMaster, unsigned char* usedLength) {
{
unsigned int value; unsigned int value;
const char* str = input.str().c_str(); const char* str = input.str().c_str();
@@ -972,8 +964,7 @@ bool DataTypeList::s_contrib_initialized = libebus_contrib_register();
#endif #endif
DataTypeList::DataTypeList() DataTypeList::DataTypeList() {
{
add(new StringDataType("STR", MAX_LEN*8, ADJ, ' ')); // >= 1 byte character string filled up with space add(new StringDataType("STR", MAX_LEN*8, ADJ, ' ')); // >= 1 byte character string filled up with space
add(new NumberDataType("PIN", 16, FIX|BCD|REV, 0xffff, 0, 0x9999, 1)); // unsigned decimal in BCD, 0000 - 9999 (fixed length) add(new NumberDataType("PIN", 16, FIX|BCD|REV, 0xffff, 0, 0x9999, 1)); // unsigned decimal in BCD, 0000 - 9999 (fixed length)
add(new NumberDataType("UCH", 8, 0, 0xff, 0, 0xfe, 1)); // unsigned integer, 0 - 254 add(new NumberDataType("UCH", 8, 0, 0xff, 0, 0xfe, 1)); // unsigned integer, 0 - 254
@@ -1036,13 +1027,11 @@ DataTypeList::DataTypeList()
add(new NumberDataType("BI7", 1, ADJ|REQ, 0, 7, 1)); // bit 7 add(new NumberDataType("BI7", 1, ADJ|REQ, 0, 7, 1)); // bit 7
} }
DataTypeList* DataTypeList::getInstance() DataTypeList* DataTypeList::getInstance() {
{
return &s_instance; return &s_instance;
} }
void DataTypeList::clear() void DataTypeList::clear() {
{
for (list<DataType*>::iterator it = m_cleanupTypes.begin(); it != m_cleanupTypes.end(); it++) { for (list<DataType*>::iterator it = m_cleanupTypes.begin(); it != m_cleanupTypes.end(); it++) {
delete *it; delete *it;
} }
@@ -1051,8 +1040,7 @@ void DataTypeList::clear()
m_typesById.clear(); m_typesById.clear();
} }
result_t DataTypeList::add(DataType* dataType) result_t DataTypeList::add(DataType* dataType) {
{
if (!dataType->isAdjustableLength()) { if (!dataType->isAdjustableLength()) {
ostringstream str; ostringstream str;
unsigned char bitCount = dataType->getBitCount(); unsigned char bitCount = dataType->getBitCount();
@@ -1074,8 +1062,7 @@ result_t DataTypeList::add(DataType* dataType)
return RESULT_OK; return RESULT_OK;
} }
DataType* DataTypeList::get(const string id, const unsigned char length) DataType* DataTypeList::get(const string id, const unsigned char length) {
{
DataType* dataType = NULL; DataType* dataType = NULL;
if (length > 0) { if (length > 0) {
ostringstream str; ostringstream str;
+6 -6
View File
@@ -16,12 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef LIBEBUS_DATATYPE_H_ #ifndef LIB_EBUS_DATATYPE_H_
#define LIBEBUS_DATATYPE_H_ #define LIB_EBUS_DATATYPE_H_
#include "symbol.h"
#include "result.h"
#include "filereader.h"
#include <string> #include <string>
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
@@ -29,6 +26,9 @@
#include <vector> #include <vector>
#include <list> #include <list>
#include <map> #include <map>
#include "symbol.h"
#include "result.h"
#include "filereader.h"
/** @file datatype.h /** @file datatype.h
* Classes, functions, and constants related to decoding/encoding of symbols * Classes, functions, and constants related to decoding/encoding of symbols
@@ -599,4 +599,4 @@ private:
}; };
#endif // LIBEBUS_DATATYPE_H_ #endif // LIB_EBUS_DATATYPE_H_
+18 -33
View File
@@ -21,31 +21,28 @@
#endif #endif
#include "device.h" #include "device.h"
#include "data.h"
#include <cstdlib>
#include <cstring>
#include <fcntl.h> #include <fcntl.h>
#include <fstream>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/file.h> #include <sys/file.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <netinet/tcp.h> #include <netinet/tcp.h>
#include <errno.h> #include <errno.h>
#ifdef HAVE_PPOLL #ifdef HAVE_PPOLL
# include <poll.h> # include <poll.h>
#endif #endif
#include <cstdlib>
#include <cstring>
#include <fstream>
#include "data.h"
using namespace std; using namespace std;
Device::~Device() Device::~Device() {
{
close(); close();
} }
Device* Device::create(const char* name, const bool checkDevice, const bool readOnly, const bool initialSend) Device* Device::create(const char* name, const bool checkDevice, const bool readOnly, const bool initialSend) {
{
if (strchr(name, '/') == NULL && strchr(name, ':') != NULL) { if (strchr(name, '/') == NULL && strchr(name, ':') != NULL) {
char* in = strdup(name); char* in = strdup(name);
bool udp = false; bool udp = false;
@@ -84,16 +81,14 @@ Device* Device::create(const char* name, const bool checkDevice, const bool read
return new SerialDevice(name, checkDevice, readOnly, initialSend); return new SerialDevice(name, checkDevice, readOnly, initialSend);
} }
void Device::close() void Device::close() {
{
if (m_fd != -1) { if (m_fd != -1) {
::close(m_fd); ::close(m_fd);
m_fd = -1; m_fd = -1;
} }
} }
bool Device::isValid() bool Device::isValid() {
{
if (m_fd == -1) { if (m_fd == -1) {
return false; return false;
} }
@@ -103,8 +98,7 @@ bool Device::isValid()
return m_fd != -1; return m_fd != -1;
} }
result_t Device::send(const unsigned char value) result_t Device::send(const unsigned char value) {
{
if (!isValid()) { if (!isValid()) {
return RESULT_ERR_DEVICE; return RESULT_ERR_DEVICE;
} }
@@ -117,8 +111,7 @@ result_t Device::send(const unsigned char value)
return RESULT_OK; return RESULT_OK;
} }
result_t Device::recv(const long timeout, unsigned char& value) result_t Device::recv(const long timeout, unsigned char& value) {
{
if (!isValid()) { if (!isValid()) {
return RESULT_ERR_DEVICE; return RESULT_ERR_DEVICE;
} }
@@ -175,8 +168,7 @@ result_t Device::recv(const long timeout, unsigned char& value)
} }
result_t SerialDevice::open() result_t SerialDevice::open() {
{
if (m_fd != -1) { if (m_fd != -1) {
close(); close();
} }
@@ -228,8 +220,7 @@ result_t SerialDevice::open()
return RESULT_OK; return RESULT_OK;
} }
void SerialDevice::close() void SerialDevice::close() {
{
if (m_fd != -1) { if (m_fd != -1) {
// empty device buffer // empty device buffer
tcflush(m_fd, TCIOFLUSH); tcflush(m_fd, TCIOFLUSH);
@@ -240,8 +231,7 @@ void SerialDevice::close()
Device::close(); Device::close();
} }
void SerialDevice::checkDevice() void SerialDevice::checkDevice() {
{
int port; int port;
if (ioctl(m_fd, TIOCMGET, &port) == -1) { if (ioctl(m_fd, TIOCMGET, &port) == -1) {
close(); close();
@@ -249,8 +239,7 @@ void SerialDevice::checkDevice()
} }
result_t NetworkDevice::open() result_t NetworkDevice::open() {
{
if (m_fd != -1) { if (m_fd != -1) {
close(); close();
} }
@@ -296,8 +285,7 @@ result_t NetworkDevice::open()
return RESULT_OK; return RESULT_OK;
} }
void NetworkDevice::checkDevice() void NetworkDevice::checkDevice() {
{
unsigned char value; unsigned char value;
ssize_t c = ::recv(m_fd, &value, 1, MSG_PEEK | MSG_DONTWAIT); ssize_t c = ::recv(m_fd, &value, 1, MSG_PEEK | MSG_DONTWAIT);
if (c == 0 || (c < 0 && errno != EAGAIN)) { if (c == 0 || (c < 0 && errno != EAGAIN)) {
@@ -306,19 +294,16 @@ void NetworkDevice::checkDevice()
} }
} }
bool NetworkDevice::available() bool NetworkDevice::available() {
{
return m_buffer && m_bufLen > 0; return m_buffer && m_bufLen > 0;
} }
ssize_t NetworkDevice::write(const unsigned char value) ssize_t NetworkDevice::write(const unsigned char value) {
{
m_bufLen = 0; // flush read buffer m_bufLen = 0; // flush read buffer
return Device::write(value); return Device::write(value);
} }
ssize_t NetworkDevice::read(unsigned char& value) ssize_t NetworkDevice::read(unsigned char& value) {
{
if (available()) { if (available()) {
value = m_buffer[m_bufPos]; value = m_buffer[m_bufPos];
m_bufPos = (unsigned char)((m_bufPos+1)%m_bufSize); m_bufPos = (unsigned char)((m_bufPos+1)%m_bufSize);
+5 -5
View File
@@ -16,15 +16,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef LIBEBUS_DEVICE_H_ #ifndef LIB_EBUS_DEVICE_H_
#define LIBEBUS_DEVICE_H_ #define LIB_EBUS_DEVICE_H_
#include <unistd.h> #include <unistd.h>
#include <termios.h> #include <termios.h>
#include <iostream>
#include <fstream>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netdb.h> #include <netdb.h>
#include <iostream>
#include <fstream>
#include "result.h" #include "result.h"
/** @file device.h /** @file device.h
@@ -290,4 +290,4 @@ private:
}; };
#endif // LIBEBUS_DEVICE_H_ #endif // LIB_EBUS_DEVICE_H_
+18 -15
View File
@@ -16,11 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef LIBEBUS_FILEREADER_H_ #ifndef LIB_EBUS_FILEREADER_H_
#define LIBEBUS_FILEREADER_H_ #define LIB_EBUS_FILEREADER_H_
#include "symbol.h"
#include "result.h"
#include <climits> #include <climits>
#include <string> #include <string>
#include <iostream> #include <iostream>
@@ -28,6 +26,8 @@
#include <fstream> #include <fstream>
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
#include "symbol.h"
#include "result.h"
/** @file filereader.h /** @file filereader.h
* Helper class and constants for reading configuration files. * Helper class and constants for reading configuration files.
@@ -114,9 +114,9 @@ public:
vector<string> row; vector<string> row;
vector< vector<string> > defaults; vector< vector<string> > defaults;
while (splitFields(ifs, row, lineNo)) { while (splitFields(ifs, row, lineNo)) {
if (row.empty()) if (row.empty()) {
continue; continue;
}
result_t result; result_t result;
vector<string>::iterator it = row.begin(); vector<string>::iterator it = row.begin();
const vector<string>::iterator end = row.end(); const vector<string>::iterator end = row.end();
@@ -124,14 +124,15 @@ public:
if (row[0][0] == '*') { if (row[0][0] == '*') {
row[0] = row[0].substr(1); row[0] = row[0].substr(1);
result = addDefaultFromFile(defaults, row, it, defaultDest, defaultCircuit, defaultSuffix, filename, lineNo); result = addDefaultFromFile(defaults, row, it, defaultDest, defaultCircuit, defaultSuffix, filename, lineNo);
if (result == RESULT_OK) if (result == RESULT_OK) {
continue; continue;
} else }
} else {
result = addFromFile(it, end, &defaults, defaultDest, defaultCircuit, defaultSuffix, filename, lineNo); result = addFromFile(it, end, &defaults, defaultDest, defaultCircuit, defaultSuffix, filename, lineNo);
} }
else } else {
result = addFromFile(it, end, NULL, defaultDest, defaultCircuit, defaultSuffix, filename, lineNo); result = addFromFile(it, end, NULL, defaultDest, defaultCircuit, defaultSuffix, filename, lineNo);
}
if (result != RESULT_OK) { if (result != RESULT_OK) {
if (!verbose) { if (!verbose) {
ifs.close(); ifs.close();
@@ -147,9 +148,10 @@ public:
cout << m_lastError << endl; cout << m_lastError << endl;
} }
printErrorPos(cout, row.begin(), end, it, filename, lineNo, result); printErrorPos(cout, row.begin(), end, it, filename, lineNo, result);
} else if (!verbose) } else if (!verbose) {
m_lastError = ""; m_lastError = "";
} }
}
ifs.close(); ifs.close();
return RESULT_OK; return RESULT_OK;
@@ -244,9 +246,9 @@ public:
trim(line); trim(line);
size_t length = line.length(); size_t length = line.length();
if (!quotedText && (length == 0 || line[0] == '#' || (line.length() > 1 && line[0] == '/' && line[1] == '/'))) if (!quotedText && (length == 0 || line[0] == '#' || (line.length() > 1 && line[0] == '/' && line[1] == '/'))) {
continue; // skip empty lines and comments continue; // skip empty lines and comments
}
for (size_t pos = 0; pos < length; pos++) { for (size_t pos = 0; pos < length; pos++) {
char ch = line[pos]; char ch = line[pos];
switch (ch) switch (ch)
@@ -289,9 +291,10 @@ public:
} }
prev = ch; prev = ch;
} }
if (!quotedText) if (!quotedText) {
break; break;
} }
}
string str = field.str(); string str = field.str();
trim(str); trim(str);
if (empty && str.empty()) { if (empty && str.empty()) {
@@ -383,4 +386,4 @@ protected:
}; };
#endif // LIBEBUS_FILEREADER_H_ #endif // LIB_EBUS_FILEREADER_H_
+320 -291
View File
File diff suppressed because it is too large Load Diff
+9 -7
View File
@@ -16,16 +16,18 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef LIBEBUS_MESSAGE_H_ #ifndef LIB_EBUS_MESSAGE_H_
#define LIBEBUS_MESSAGE_H_ #define LIB_EBUS_MESSAGE_H_
#include "data.h"
#include "result.h"
#include "symbol.h"
#include <string> #include <string>
#include <vector> #include <vector>
#include <deque> #include <deque>
#include <map> #include <map>
#include <queue>
#include <functional>
#include "data.h"
#include "result.h"
#include "symbol.h"
/** @file message.h /** @file message.h
* Classes and functions for decoding and encoding of complete messages on the * Classes and functions for decoding and encoding of complete messages on the
@@ -142,7 +144,7 @@ public:
/** /**
* Destructor. * Destructor.
*/ */
virtual ~Message() { if (m_deleteData) delete m_data; } virtual ~Message() { if (m_deleteData) { delete m_data; } }
/** /**
* Calculate the key for the ID. * Calculate the key for the ID.
@@ -1406,4 +1408,4 @@ private:
}; };
#endif // LIBEBUS_MESSAGE_H_ #endif // LIB_EBUS_MESSAGE_H_
+2 -1
View File
@@ -51,8 +51,9 @@ const char* getResultCode(result_t resultCode) {
case RESULT_ERR_SYN: return "ERR: SYN received"; case RESULT_ERR_SYN: return "ERR: SYN received";
default: default:
if (resultCode >= 0) if (resultCode >= 0) {
return "done: unknown result code"; return "done: unknown result code";
}
return "ERR: unknown result code"; return "ERR: unknown result code";
} }
} }
+3 -3
View File
@@ -16,8 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef LIBEBUS_RESULT_H_ #ifndef LIB_EBUS_RESULT_H_
#define LIBEBUS_RESULT_H_ #define LIB_EBUS_RESULT_H_
/** @file result.h /** @file result.h
* Functions, and constants related to execution results. * Functions, and constants related to execution results.
@@ -70,4 +70,4 @@ enum result_t {
*/ */
const char* getResultCode(result_t resultCode); const char* getResultCode(result_t resultCode);
#endif // LIBEBUS_RESULT_H_ #endif // LIB_EBUS_RESULT_H_
+7 -9
View File
@@ -17,9 +17,11 @@
*/ */
#include "symbol.h" #include "symbol.h"
#include "result.h"
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <string>
#include <vector>
#include "result.h"
using namespace std; using namespace std;
@@ -47,8 +49,7 @@ static const unsigned char CRC_LOOKUP_TABLE[] =
}; };
void SymbolString::addAll(const SymbolString& str, bool skipLastSymbol) void SymbolString::addAll(const SymbolString& str, bool skipLastSymbol) {
{
bool addCrc = m_unescapeState == 0; bool addCrc = m_unescapeState == 0;
bool isEscaped = str.m_unescapeState == 0; bool isEscaped = str.m_unescapeState == 0;
vector<unsigned char> data = str.m_data; vector<unsigned char> data = str.m_data;
@@ -64,8 +65,7 @@ void SymbolString::addAll(const SymbolString& str, bool skipLastSymbol)
} }
} }
result_t SymbolString::parseHex(const string& str, const bool isEscaped) result_t SymbolString::parseHex(const string& str, const bool isEscaped) {
{
bool addCrc = m_unescapeState == 0; bool addCrc = m_unescapeState == 0;
for (size_t i = 0; i < str.size(); i += 2) { for (size_t i = 0; i < str.size(); i += 2) {
char* strEnd = NULL; char* strEnd = NULL;
@@ -83,8 +83,7 @@ result_t SymbolString::parseHex(const string& str, const bool isEscaped)
return RESULT_OK; return RESULT_OK;
} }
const string SymbolString::getDataStr(const bool unescape, const bool skipLastSymbol) const string SymbolString::getDataStr(const bool unescape, const bool skipLastSymbol) {
{
stringstream sstr; stringstream sstr;
bool previousEscape = false; bool previousEscape = false;
@@ -111,8 +110,7 @@ const string SymbolString::getDataStr(const bool unescape, const bool skipLastSy
return sstr.str(); return sstr.str();
} }
result_t SymbolString::push_back(const unsigned char value, const bool isEscaped, const bool updateCRC) result_t SymbolString::push_back(const unsigned char value, const bool isEscaped, const bool updateCRC) {
{
if (m_unescapeState == 0) { // store escaped data if (m_unescapeState == 0) { // store escaped data
if (!isEscaped && value == ESC) { if (!isEscaped && value == ESC) {
m_data.push_back(ESC); m_data.push_back(ESC);
+21 -11
View File
@@ -16,14 +16,18 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef LIBEBUS_SYMBOL_H_ #ifndef LIB_EBUS_SYMBOL_H_
#define LIBEBUS_SYMBOL_H_ #define LIB_EBUS_SYMBOL_H_
#include "result.h"
#include <cstring> #include <cstring>
#include <cstdlib> #include <cstdlib>
#include <sstream> #include <sstream>
#include <queue> #include <queue>
#include <string>
#include <vector>
#include "result.h"
using namespace std;
/** @file symbol.h /** @file symbol.h
* Classes, functions, and constants related to symbols on the eBUS. * Classes, functions, and constants related to symbols on the eBUS.
@@ -61,8 +65,6 @@
* non-acknowledge, the receiving slave has to repeat its data once. * non-acknowledge, the receiving slave has to repeat its data once.
*/ */
using namespace std;
static const unsigned char ESC = 0xA9; //!< escape symbol, either followed by 0x00 for the value 0xA9, or 0x01 for the value 0xAA static const unsigned char ESC = 0xA9; //!< escape symbol, either followed by 0x00 for the value 0xA9, or 0x01 for the value 0xAA
static const unsigned char SYN = 0xAA; //!< synchronization symbol static const unsigned char SYN = 0xAA; //!< synchronization symbol
static const unsigned char ACK = 0x00; //!< positive acknowledge static const unsigned char ACK = 0x00; //!< positive acknowledge
@@ -111,7 +113,7 @@ public:
* @param index the index of the symbol to return. * @param index the index of the symbol to return.
* @return the reference to the symbol at the specified index. * @return the reference to the symbol at the specified index.
*/ */
unsigned char& operator[](const size_t index) { if (index >= m_data.size()) m_data.resize(index+1, 0); return m_data[index]; } unsigned char& operator[](const size_t index) { if (index >= m_data.size()) { m_data.resize(index+1, 0); } return m_data[index]; }
/** /**
* Return whether this instance is equal to the other instance. * Return whether this instance is equal to the other instance.
@@ -135,10 +137,18 @@ public:
* 2 if this instance only differs from the other instance in the first byte (the master address). * 2 if this instance only differs from the other instance in the first byte (the master address).
*/ */
int compareMaster(SymbolString& other) { int compareMaster(SymbolString& other) {
if (m_unescapeState!=other.m_unescapeState || m_data.size()!=other.m_data.size()) return 1; if (m_unescapeState != other.m_unescapeState || m_data.size() != other.m_data.size()) {
if (m_data==other.m_data) return 0; return 1;
if (m_data.size()==1) return 2; }
if (equal(m_data.begin()+1, m_data.end()-1, other.m_data.begin()+1)) return 2; if (m_data == other.m_data) {
return 0;
}
if (m_data.size() == 1) {
return 2;
}
if (equal(m_data.begin()+1, m_data.end()-1, other.m_data.begin()+1)) {
return 2;
}
return 1; return 1;
} }
@@ -249,4 +259,4 @@ unsigned char getMasterNumber(unsigned char addr);
*/ */
bool isValidAddress(unsigned char addr, bool allowBroadcast = true); bool isValidAddress(unsigned char addr, bool allowBroadcast = true);
#endif // LIBEBUS_SYMBOL_H_ #endif // LIB_EBUS_SYMBOL_H_
+11 -12
View File
@@ -16,17 +16,18 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "data.h"
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <string>
#include <vector>
#include "data.h"
using namespace std; using namespace std;
static bool error = false; static bool error = false;
void verify(bool expectFailMatch, string type, string input, void verify(bool expectFailMatch, string type, string input,
bool match, string expectStr, string gotStr) bool match, string expectStr, string gotStr) {
{
match = match && expectStr == gotStr; match = match && expectStr == gotStr;
if (expectFailMatch) { if (expectFailMatch) {
if (match) { if (match) {
@@ -45,8 +46,7 @@ void verify(bool expectFailMatch, string type, string input,
} }
} }
int main() int main() {
{
string checks[][5] = { string checks[][5] = {
// entry: definition, decoded value, master data, slave data, flags // entry: definition, decoded value, master data, slave data, flags
// definition: name,part,type[:len][,[divisor|values][,[unit][,[comment]]]] // definition: name,part,type[:len][,[divisor|values][,[unit][,[comment]]]]
@@ -568,7 +568,7 @@ int main()
if (result >= RESULT_OK) { if (result >= RESULT_OK) {
result = fields->read(pt_slaveData, sstr, 0, output, verbosity|(numeric?OF_NUMERIC:0), -1, !output.str().empty()); result = fields->read(pt_slaveData, sstr, 0, output, verbosity|(numeric?OF_NUMERIC:0), -1, !output.str().empty());
} }
if (failedRead) if (failedRead) {
if (result >= RESULT_OK) { if (result >= RESULT_OK) {
cout << " failed read " << fields->getName() << " >" << check[2] << " " << check[3] cout << " failed read " << fields->getName() << " >" << check[2] << " " << check[3]
<< "< error: unexpectedly succeeded" << endl; << "< error: unexpectedly succeeded" << endl;
@@ -577,12 +577,11 @@ int main()
cout << " failed read " << fields->getName() << " >" << check[2] << " " << check[3] cout << " failed read " << fields->getName() << " >" << check[2] << " " << check[3]
<< "< OK" << endl; << "< OK" << endl;
} }
else if (result < RESULT_OK) { } else if (result < RESULT_OK) {
cout << " read " << fields->getName() << " >" << check[2] << " " << check[3] cout << " read " << fields->getName() << " >" << check[2] << " " << check[3]
<< "< error: " << getResultCode(result) << endl; << "< error: " << getResultCode(result) << endl;
error = true; error = true;
} } else {
else {
bool match = strcasecmp(output.str().c_str(), expectStr.c_str()) == 0; bool match = strcasecmp(output.str().c_str(), expectStr.c_str()) == 0;
verify(failedReadMatch, "read", check[2], match, expectStr, output.str()); verify(failedReadMatch, "read", check[2], match, expectStr, output.str());
} }
@@ -590,8 +589,9 @@ int main()
if (verbosity == 0) { if (verbosity == 0) {
istringstream input(expectStr); istringstream input(expectStr);
result = fields->write(input, pt_masterData, writeMstr, 0); result = fields->write(input, pt_masterData, writeMstr, 0);
if (result >= RESULT_OK) if (result >= RESULT_OK) {
result = fields->write(input, pt_slaveData, writeSstr, 0); result = fields->write(input, pt_slaveData, writeSstr, 0);
}
if (failedWrite) { if (failedWrite) {
if (result >= RESULT_OK) { if (result >= RESULT_OK) {
cout << " failed write " << fields->getName() << " >" cout << " failed write " << fields->getName() << " >"
@@ -601,8 +601,7 @@ int main()
cout << " failed write " << fields->getName() << " >" cout << " failed write " << fields->getName() << " >"
<< expectStr << "< OK" << endl; << expectStr << "< OK" << endl;
} }
} } else if (result < RESULT_OK) {
else if (result < RESULT_OK) {
cout << " write " << fields->getName() << " >" << expectStr cout << " write " << fields->getName() << " >" << expectStr
<< "< error: " << getResultCode(result) << endl; << "< error: " << getResultCode(result) << endl;
error = true; error = true;
+8 -8
View File
@@ -16,14 +16,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "device.h"
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include "device.h"
using namespace std; using namespace std;
int main () int main () {
{
Device* device = Device::create("/dev/ttyUSB20", true, false, false); Device* device = Device::create("/dev/ttyUSB20", true, false, false);
if (device == NULL) { if (device == NULL) {
cout << "unable to create device" << endl; cout << "unable to create device" << endl;
@@ -33,27 +32,28 @@ int main ()
if (result != RESULT_OK) { if (result != RESULT_OK) {
cout << "open failed: " << getResultCode(result) << endl; cout << "open failed: " << getResultCode(result) << endl;
} else { } else {
if (!device->isValid()) if (!device->isValid()) {
cout << "device not available." << endl; cout << "device not available." << endl;
}
int count = 0; int count = 0;
while (1) { while (1) {
unsigned char byte = 0; unsigned char byte = 0;
result = device->recv(0, byte); result = device->recv(0, byte);
if (result == RESULT_OK) if (result == RESULT_OK) {
cout << hex << setw(2) << setfill('0') cout << hex << setw(2) << setfill('0')
<< static_cast<unsigned>(byte) << endl; << static_cast<unsigned>(byte) << endl;
}
count++; count++;
} }
device->close(); device->close();
if (!device->isValid()) if (!device->isValid()) {
cout << "close successful." << endl; cout << "close successful." << endl;
} }
}
delete device; delete device;
+5 -5
View File
@@ -16,17 +16,18 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "filereader.h"
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <string>
#include <vector>
#include "filereader.h"
using namespace std; using namespace std;
static bool error = false; static bool error = false;
void verify(bool expectFailMatch, string type, string input, void verify(bool expectFailMatch, string type, string input,
bool match, string expectStr, string gotStr) bool match, string expectStr, string gotStr) {
{
match = match && expectStr == gotStr; match = match && expectStr == gotStr;
if (expectFailMatch) { if (expectFailMatch) {
if (match) { if (match) {
@@ -45,8 +46,7 @@ void verify(bool expectFailMatch, string type, string input,
} }
} }
int main() int main() {
{
istringstream ifs( istringstream ifs(
"line 1 col 1,line 1 col 2,line 1 col 3\n" "line 1 col 1,line 1 col 2,line 1 col 3\n"
"line 2 col 1,\"line 2 col 2\",\"line 2 \"\"col 3\"\"\"\n" "line 2 col 1,\"line 2 col 2\",\"line 2 \"\"col 3\"\"\"\n"
+52 -40
View File
@@ -16,41 +16,43 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "message.h"
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <iomanip> #include <iomanip>
#include <string>
#include <vector>
#include <map>
#include "message.h"
using namespace std; using namespace std;
void verify(bool expectFailMatch, string type, string input, void verify(bool expectFailMatch, string type, string input,
bool match, string expectStr, string gotStr) bool match, string expectStr, string gotStr) {
{
if (expectFailMatch) { if (expectFailMatch) {
if (match) if (match) {
cout << " failed " << type << " match >" << input cout << " failed " << type << " match >" << input
<< "< error: unexpectedly succeeded" << endl; << "< error: unexpectedly succeeded" << endl;
else } else {
cout << " failed " << type << " match >" << input << "< OK" << endl; cout << " failed " << type << " match >" << input << "< OK" << endl;
} }
else if (match) } else if (match) {
cout << " " << type << " match >" << input << "< OK" << endl; cout << " " << type << " match >" << input << "< OK" << endl;
else } else {
cout << " " << type << " match >" << input << "< error: got >" cout << " " << type << " match >" << input << "< error: got >"
<< gotStr << "<, expected >" << expectStr << "<" << endl; << gotStr << "<, expected >" << expectStr << "<" << endl;
} }
}
DataFieldTemplates* templates = NULL; DataFieldTemplates* templates = NULL;
DataFieldTemplates* getTemplates(const string filename) DataFieldTemplates* getTemplates(const string filename) {
{ if (filename == "") { // avoid compiler warning
if (filename=="") // avoid compiler warning
return templates; return templates;
}
return templates; return templates;
} }
int main() int main() {
{
// message: [type],[circuit],name,[comment],[QQ[;QQ]*],[ZZ],[PBSB],[ID],fields... // message: [type],[circuit],name,[comment],[QQ[;QQ]*],[ZZ],[PBSB],[ID],fields...
// field: name,part,type[:len][,[divisor|values][,[unit][,[comment]]]] // field: name,part,type[:len][,[divisor|values][,[unit][,[comment]]]]
// template: name,type[:len][,[divisor|values][,[unit][,[comment]]]] // template: name,type[:len][,[divisor|values][,[unit][,[comment]]]]
@@ -167,17 +169,16 @@ int main()
DataField* fields = NULL; DataField* fields = NULL;
vector<string>::iterator it = entries.begin(); vector<string>::iterator it = entries.begin();
result = DataField::create(it, entries.end(), templates, fields, false, true, false); result = DataField::create(it, entries.end(), templates, fields, false, true, false);
if (result != RESULT_OK) if (result != RESULT_OK) {
cout << "\"" << check[0] << "\": template fields create error: " << getResultCode(result) << endl; cout << "\"" << check[0] << "\": template fields create error: " << getResultCode(result) << endl;
else if (it != entries.end()) { } else if (it != entries.end()) {
cout << "\"" << check[0] << "\": template fields create error: trailing input " << static_cast<unsigned>(entries.end()-it) << endl; cout << "\"" << check[0] << "\": template fields create error: trailing input " << static_cast<unsigned>(entries.end()-it) << endl;
} } else {
else {
cout << "\"" << check[0] << "\": create template OK" << endl; cout << "\"" << check[0] << "\": create template OK" << endl;
result = templates->add(fields, "", true); result = templates->add(fields, "", true);
if (result == RESULT_OK) if (result == RESULT_OK) {
cout << " store template OK" << endl; cout << " store template OK" << endl;
else { } else {
cout << " store template error: " << getResultCode(result) << endl; cout << " store template error: " << getResultCode(result) << endl;
delete fields; delete fields;
} }
@@ -189,24 +190,25 @@ int main()
vector<string>::iterator it = entries.begin(); vector<string>::iterator it = entries.begin();
size_t oldSize = conditions.size(); size_t oldSize = conditions.size();
result = messages->addDefaultFromFile(defaultsRows, entries, it, "", "", "", "no file", 1); result = messages->addDefaultFromFile(defaultsRows, entries, it, "", "", "", "no file", 1);
if (result != RESULT_OK) if (result != RESULT_OK) {
cout << "\"" << check[0] << "\": defaults read error: " << getResultCode(result) << endl; cout << "\"" << check[0] << "\": defaults read error: " << getResultCode(result) << endl;
else if (it != entries.end()) } else if (it != entries.end()) {
cout << "\"" << check[0] << "\": defaults read error: trailing input " << static_cast<unsigned>(entries.end()-it) << endl; cout << "\"" << check[0] << "\": defaults read error: trailing input " << static_cast<unsigned>(entries.end()-it) << endl;
else { } else {
cout << "\"" << check[0] << "\": read defaults OK" << endl; cout << "\"" << check[0] << "\": read defaults OK" << endl;
if (isCondition) { if (isCondition) {
if (conditions.size() == oldSize) { if (conditions.size() == oldSize) {
cout << " create condition error" << endl; cout << " create condition error" << endl;
} else { } else {
result = messages->resolveConditions(); result = messages->resolveConditions();
if (result != RESULT_OK) if (result != RESULT_OK) {
cout << " resolve conditions error: " << getResultCode(result) << " " << messages->getLastError() << endl; cout << " resolve conditions error: " << getResultCode(result) << " " << messages->getLastError() << endl;
else } else {
cout << " resolve conditions OK" << endl; cout << " resolve conditions OK" << endl;
} }
} }
} }
}
continue; continue;
} }
if (isChain) { if (isChain) {
@@ -214,10 +216,11 @@ int main()
string token; string token;
istringstream stream(check[2]); istringstream stream(check[2]);
while (getline(stream, token, VALUE_SEPARATOR)) { while (getline(stream, token, VALUE_SEPARATOR)) {
if (pos >= mstrs.size()) if (pos >= mstrs.size()) {
mstrs.resize(pos+1); mstrs.resize(pos+1);
else if (mstrs[pos]!=NULL) } else if (mstrs[pos] != NULL) {
delete mstrs[pos]; delete mstrs[pos];
}
mstrs[pos] = new SymbolString(false); mstrs[pos] = new SymbolString(false);
result = mstrs[pos]->parseHex(token); result = mstrs[pos]->parseHex(token);
if (result != RESULT_OK) { if (result != RESULT_OK) {
@@ -230,10 +233,11 @@ int main()
stream.str(check[3]); stream.str(check[3]);
stream.clear(); stream.clear();
while (getline(stream, token, VALUE_SEPARATOR)) { while (getline(stream, token, VALUE_SEPARATOR)) {
if (pos >= sstrs.size()) if (pos >= sstrs.size()) {
sstrs.resize(pos+1); sstrs.resize(pos+1);
else if (sstrs[pos]!=NULL) } else if (sstrs[pos] != NULL) {
delete sstrs[pos]; delete sstrs[pos];
}
sstrs[pos] = new SymbolString(false); sstrs[pos] = new SymbolString(false);
result = sstrs[pos]->parseHex(token); result = sstrs[pos]->parseHex(token);
if (result != RESULT_OK) { if (result != RESULT_OK) {
@@ -242,19 +246,22 @@ int main()
} }
pos++; pos++;
} }
if (result != RESULT_OK) if (result != RESULT_OK) {
continue; continue;
}
} else { } else {
if (mstrs[0]!=NULL) if (mstrs[0] != NULL) {
delete mstrs[0]; delete mstrs[0];
}
mstrs[0] = new SymbolString(false); mstrs[0] = new SymbolString(false);
result = mstrs[0]->parseHex(check[2]); result = mstrs[0]->parseHex(check[2]);
if (result != RESULT_OK) { if (result != RESULT_OK) {
cout << "\"" << check[0] << "\": parse \"" << check[2] << "\" error: " << getResultCode(result) << endl; cout << "\"" << check[0] << "\": parse \"" << check[2] << "\" error: " << getResultCode(result) << endl;
continue; continue;
} }
if (sstrs[0]!=NULL) if (sstrs[0] != NULL) {
delete sstrs[0]; delete sstrs[0];
}
sstrs[0] = new SymbolString(false); sstrs[0] = new SymbolString(false);
result = sstrs[0]->parseHex(check[3]); result = sstrs[0]->parseHex(check[3]);
if (result != RESULT_OK) { if (result != RESULT_OK) {
@@ -287,10 +294,11 @@ int main()
result = Message::create(it, entries.end(), &defaultsRows, condition, "no file", templates, deleteMessages); result = Message::create(it, entries.end(), &defaultsRows, condition, "no file", templates, deleteMessages);
} }
if (failedCreate) { if (failedCreate) {
if (result == RESULT_OK) if (result == RESULT_OK) {
cout << "\"" << check[0] << "\": failed create error: unexpectedly succeeded" << endl; cout << "\"" << check[0] << "\": failed create error: unexpectedly succeeded" << endl;
else } else {
cout << "\"" << check[0] << "\": failed create OK" << endl; cout << "\"" << check[0] << "\": failed create OK" << endl;
}
continue; continue;
} }
if (result != RESULT_OK) { if (result != RESULT_OK) {
@@ -327,24 +335,27 @@ int main()
break; break;
} }
} }
if (result != RESULT_OK) if (result != RESULT_OK) {
continue; continue;
}
cout << " map OK" << endl; cout << " map OK" << endl;
message = deleteMessages.front(); message = deleteMessages.front();
deleteMessages.clear(); deleteMessages.clear();
if (onlyMap) if (onlyMap) {
continue; continue;
}
Message* foundMessage = messages->find(*mstrs[0]); Message* foundMessage = messages->find(*mstrs[0]);
if (foundMessage == message) if (foundMessage == message) {
cout << " find OK" << endl; cout << " find OK" << endl;
else if (foundMessage == NULL) } else if (foundMessage == NULL) {
cout << " find error: NULL" << endl; cout << " find error: NULL" << endl;
else } else {
cout << " find error: different" << endl; cout << " find error: different" << endl;
} }
else } else {
message = deleteMessages.front(); message = deleteMessages.front();
} }
}
if (message->isPassive() || decode) { if (message->isPassive() || decode) {
ostringstream output; ostringstream output;
@@ -370,10 +381,11 @@ int main()
SymbolString writeMstr(false); SymbolString writeMstr(false);
result = message->prepareMaster(0xff, writeMstr, input); result = message->prepareMaster(0xff, writeMstr, input);
if (failedPrepare) { if (failedPrepare) {
if (result == RESULT_OK) if (result == RESULT_OK) {
cout << " \"" << inputStr << "\": failed prepare error: unexpectedly succeeded" << endl; cout << " \"" << inputStr << "\": failed prepare error: unexpectedly succeeded" << endl;
else } else {
cout << " \"" << inputStr << "\": failed prepare OK" << endl; cout << " \"" << inputStr << "\": failed prepare OK" << endl;
}
continue; continue;
} }
+4 -5
View File
@@ -16,17 +16,17 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "symbol.h"
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <string>
#include "symbol.h"
using namespace std; using namespace std;
static bool error = false; static bool error = false;
void verify(bool expectFailMatch, string type, string input, void verify(bool expectFailMatch, string type, string input,
bool match, string expectStr, string gotStr) bool match, string expectStr, string gotStr) {
{
match = match && expectStr == gotStr; match = match && expectStr == gotStr;
if (expectFailMatch) { if (expectFailMatch) {
if (match) { if (match) {
@@ -45,8 +45,7 @@ void verify(bool expectFailMatch, string type, string input,
} }
} }
int main(int argc, char** argv) int main(int argc, char** argv) {
{
SymbolString sstr(true); SymbolString sstr(true);
if (argc > 1) { if (argc > 1) {
+1 -2
View File
@@ -27,8 +27,7 @@ static bool clockInitialized = false;
static clock_serv_t clockServ; static clock_serv_t clockServ;
#endif #endif
void clockGettime(struct timespec* t) void clockGettime(struct timespec* t) {
{
#ifdef __MACH__ #ifdef __MACH__
if (!clockInitialized) { if (!clockInitialized) {
clockInitialized = true; clockInitialized = true;
+3 -3
View File
@@ -16,8 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef LIBUTILS_CLOCK_H_ #ifndef LIB_UTILS_CLOCK_H_
#define LIBUTILS_CLOCK_H_ #define LIB_UTILS_CLOCK_H_
#include <time.h> #include <time.h>
@@ -29,4 +29,4 @@
*/ */
void clockGettime(struct timespec* t); void clockGettime(struct timespec* t);
#endif // LIBUTILS_CLOCK_H_ #endif // LIB_UTILS_CLOCK_H_
+12 -22
View File
@@ -57,8 +57,7 @@ static LogLevel s_logLevel = ll_notice;
/** the current log FILE. */ /** the current log FILE. */
static FILE* s_logFile = stdout; static FILE* s_logFile = stdout;
bool setLogFacilities(const char* facilities) bool setLogFacilities(const char* facilities) {
{
char *input = strdup(facilities); char *input = strdup(facilities);
char *opt = (char*)input, *value = NULL; char *opt = (char*)input, *value = NULL;
int newFacilites = 0; int newFacilites = 0;
@@ -80,8 +79,7 @@ bool setLogFacilities(const char* facilities)
return true; return true;
} }
bool getLogFacilities(char* buffer) bool getLogFacilities(char* buffer) {
{
if (s_logFacilites == LF_ALL) { if (s_logFacilites == LF_ALL) {
return strcpy(buffer, facilityNames[lf_COUNT]) != NULL; return strcpy(buffer, facilityNames[lf_COUNT]) != NULL;
} }
@@ -99,8 +97,7 @@ bool getLogFacilities(char* buffer)
return true; return true;
} }
bool setLogLevel(const char* level) bool setLogLevel(const char* level) {
{
char *input = strdup(level); char *input = strdup(level);
char *opt = (char*)input, *value = NULL; char *opt = (char*)input, *value = NULL;
int newLevel = 0; int newLevel = 0;
@@ -117,24 +114,21 @@ bool setLogLevel(const char* level)
return true; return true;
} }
const char* getLogLevel() const char* getLogLevel() {
{
return levelNames[s_logLevel]; return levelNames[s_logLevel];
} }
bool setLogFile(const char* filename) bool setLogFile(const char* filename) {
{
FILE* newFile = fopen(filename, "a"); FILE* newFile = fopen(filename, "a");
if (newFile == NULL) if (newFile == NULL) {
return false; return false;
}
closeLogFile(); closeLogFile();
s_logFile = newFile; s_logFile = newFile;
return true; return true;
} }
void closeLogFile() void closeLogFile() {
{
if (s_logFile != NULL) { if (s_logFile != NULL) {
if (s_logFile != stdout) { if (s_logFile != stdout) {
fclose(s_logFile); fclose(s_logFile);
@@ -143,14 +137,12 @@ void closeLogFile()
} }
} }
bool needsLog(const LogFacility facility, const LogLevel level) bool needsLog(const LogFacility facility, const LogLevel level) {
{
return ((s_logFacilites & (1<<facility)) != 0) return ((s_logFacilites & (1<<facility)) != 0)
&& (s_logLevel >= level); && (s_logLevel >= level);
} }
void logWrite(const char* facility, const char* level, const char* message, va_list ap) void logWrite(const char* facility, const char* level, const char* message, va_list ap) {
{
struct timespec ts; struct timespec ts;
struct tm* tm; struct tm* tm;
clockGettime(&ts); clockGettime(&ts);
@@ -168,16 +160,14 @@ void logWrite(const char* facility, const char* level, const char* message, va_l
} }
} }
void logWrite(const LogFacility facility, const LogLevel level, const char* message, ...) void logWrite(const LogFacility facility, const LogLevel level, const char* message, ...) {
{
va_list ap; va_list ap;
va_start(ap, message); va_start(ap, message);
logWrite(facilityNames[facility], levelNames[level], message, ap); logWrite(facilityNames[facility], levelNames[level], message, ap);
va_end(ap); va_end(ap);
} }
void logWrite(const char* facility, const LogLevel level, const char* message, ...) void logWrite(const char* facility, const LogLevel level, const char* message, ...) {
{
va_list ap; va_list ap;
va_start(ap, message); va_start(ap, message);
logWrite(facility, levelNames[level], message, ap); logWrite(facility, levelNames[level], message, ap);
+3 -3
View File
@@ -16,8 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef LIBUTILS_LOG_H_ #ifndef LIB_UTILS_LOG_H_
#define LIBUTILS_LOG_H_ #define LIB_UTILS_LOG_H_
/** \file log.h */ /** \file log.h */
@@ -136,4 +136,4 @@ void logWrite(const char* facility, const LogLevel level, const char* message, .
/** A macro for a debug message that calls the logging function only if needed. */ /** A macro for a debug message that calls the logging function only if needed. */
#define logOtherDebug(facility, ...) (needsLog(lf_other, ll_debug) ? logWrite(facility, ll_debug, __VA_ARGS__) : void(0)) #define logOtherDebug(facility, ...) (needsLog(lf_other, ll_debug) ? logWrite(facility, ll_debug, __VA_ARGS__) : void(0))
#endif // LIBUTILS_LOG_H_ #endif // LIB_UTILS_LOG_H_
+3 -3
View File
@@ -16,8 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef LIBUTILS_NOTIFY_H_ #ifndef LIB_UTILS_NOTIFY_H_
#define LIBUTILS_NOTIFY_H_ #define LIB_UTILS_NOTIFY_H_
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
@@ -73,6 +73,6 @@ private:
}; };
#endif // LIBUTILS_NOTIFY_H_ #endif // LIB_UTILS_NOTIFY_H_
+11 -9
View File
@@ -16,12 +16,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef LIBUTILS_QUEUE_H_ #ifndef LIB_UTILS_QUEUE_H_
#define LIBUTILS_QUEUE_H_ #define LIB_UTILS_QUEUE_H_
#include <list>
#include <pthread.h> #include <pthread.h>
#include <errno.h> #include <errno.h>
#include <list>
#include "clock.h" #include "clock.h"
/** \file queue.h */ /** \file queue.h */
@@ -91,13 +91,14 @@ public:
clockGettime(&t); clockGettime(&t);
t.tv_sec += timeout; t.tv_sec += timeout;
while (m_queue.empty()) { while (m_queue.empty()) {
if (pthread_cond_timedwait(&m_cond, &m_mutex, &t)==ETIMEDOUT) if (pthread_cond_timedwait(&m_cond, &m_mutex, &t) == ETIMEDOUT) {
break; break;
} }
} }
if (m_queue.empty()) }
if (m_queue.empty()) {
item = NULL; item = NULL;
else { } else {
item = m_queue.front(); item = m_queue.front();
m_queue.pop_front(); m_queue.pop_front();
} }
@@ -138,10 +139,11 @@ public:
{ {
T item; T item;
pthread_mutex_lock(&m_mutex); pthread_mutex_lock(&m_mutex);
if (m_queue.empty()) if (m_queue.empty()) {
item = NULL; item = NULL;
else } else {
item = m_queue.front(); item = m_queue.front();
}
pthread_mutex_unlock(&m_mutex); pthread_mutex_unlock(&m_mutex);
return item; return item;
} }
@@ -158,4 +160,4 @@ private:
}; };
#endif // LIBUTILS_QUEUE_H_ #endif // LIB_UTILS_QUEUE_H_
+9 -11
View File
@@ -17,27 +17,26 @@
*/ */
#include "rotatefile.h" #include "rotatefile.h"
#include "clock.h"
#include <cstdlib>
#include <cstring>
#include <fcntl.h>
#include <fstream>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/file.h> #include <sys/file.h>
#include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <string>
#include "clock.h"
using namespace std; using namespace std;
RotateFile::~RotateFile() RotateFile::~RotateFile() {
{
if (m_stream) { if (m_stream) {
fclose(m_stream); fclose(m_stream);
m_stream = NULL; m_stream = NULL;
} }
} }
bool RotateFile::setEnabled(bool enabled) bool RotateFile::setEnabled(bool enabled) {
{
if (enabled == m_enabled) { if (enabled == m_enabled) {
return false; return false;
} }
@@ -53,8 +52,7 @@ bool RotateFile::setEnabled(bool enabled)
return true; return true;
} }
void RotateFile::write(unsigned char* value, unsigned int size, bool received) void RotateFile::write(unsigned char* value, unsigned int size, bool received) {
{
if (!m_enabled || !m_stream) { if (!m_enabled || !m_stream) {
return; return;
} }
+4 -3
View File
@@ -16,12 +16,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef LIBUTILS_ROTATEFILE_H_ #ifndef LIB_UTILS_ROTATEFILE_H_
#define LIBUTILS_ROTATEFILE_H_ #define LIB_UTILS_ROTATEFILE_H_
#include <unistd.h> #include <unistd.h>
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include <string>
/** @file rotatefile.h /** @file rotatefile.h
* Helpers for writing to rotating files. * Helpers for writing to rotating files.
@@ -91,5 +92,5 @@ private:
}; };
#endif // LIBUTILS_ROTATEFILE_H_ #endif // LIB_UTILS_ROTATEFILE_H_
+6 -11
View File
@@ -17,30 +17,27 @@
*/ */
#include "tcpsocket.h" #include "tcpsocket.h"
#include <cstdlib>
#include <fcntl.h> #include <fcntl.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netdb.h> #include <netdb.h>
#include <string.h> #include <string.h>
#include <cstdlib>
using namespace std; using namespace std;
TCPSocket::TCPSocket(int sfd, struct sockaddr_in* address) : m_sfd(sfd) TCPSocket::TCPSocket(int sfd, struct sockaddr_in* address) : m_sfd(sfd) {
{
char ip[17]; char ip[17];
inet_ntop(AF_INET, (struct in_addr*)&(address->sin_addr.s_addr), ip, (socklen_t)sizeof(ip)-1); inet_ntop(AF_INET, (struct in_addr*)&(address->sin_addr.s_addr), ip, (socklen_t)sizeof(ip)-1);
m_ip = ip; m_ip = ip;
m_port = (uint16_t)ntohs(address->sin_port); m_port = (uint16_t)ntohs(address->sin_port);
} }
bool TCPSocket::isValid() bool TCPSocket::isValid() {
{
return fcntl(m_sfd, F_GETFL) != -1; return fcntl(m_sfd, F_GETFL) != -1;
} }
TCPSocket* TCPClient::connect(const string& server, const uint16_t& port) TCPSocket* TCPClient::connect(const string& server, const uint16_t& port) {
{
struct sockaddr_in address; struct sockaddr_in address;
int ret; int ret;
@@ -76,8 +73,7 @@ TCPSocket* TCPClient::connect(const string& server, const uint16_t& port)
} }
int TCPServer::start() int TCPServer::start() {
{
if (m_listening) { if (m_listening) {
return 0; return 0;
} }
@@ -109,8 +105,7 @@ int TCPServer::start()
return result; return result;
} }
TCPSocket* TCPServer::newSocket() TCPSocket* TCPServer::newSocket() {
{
if (!m_listening) { if (!m_listening) {
return NULL; return NULL;
} }
+4 -4
View File
@@ -16,13 +16,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef LIBUTILS_TCPSOCKET_H_ #ifndef LIB_UTILS_TCPSOCKET_H_
#define LIBUTILS_TCPSOCKET_H_ #define LIB_UTILS_TCPSOCKET_H_
#include <unistd.h> #include <unistd.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <string>
#include <stdint.h> #include <stdint.h>
#include <string>
/** \file tcpsocket.h */ /** \file tcpsocket.h */
@@ -181,5 +181,5 @@ private:
}; };
#endif // LIBUTILS_TCPSOCKET_H_ #endif // LIB_UTILS_TCPSOCKET_H_
+9 -18
View File
@@ -23,22 +23,19 @@
#include "thread.h" #include "thread.h"
#include "clock.h" #include "clock.h"
void* Thread::runThread(void* arg) void* Thread::runThread(void* arg) {
{
((Thread*)arg)->enter(); ((Thread*)arg)->enter();
return NULL; return NULL;
} }
Thread::~Thread() Thread::~Thread() {
{
if (m_started) { if (m_started) {
pthread_cancel(m_threadid); pthread_cancel(m_threadid);
pthread_detach(m_threadid); pthread_detach(m_threadid);
} }
} }
bool Thread::start(const char* name) bool Thread::start(const char* name) {
{
int result = pthread_create(&m_threadid, NULL, runThread, this); int result = pthread_create(&m_threadid, NULL, runThread, this);
@@ -58,8 +55,7 @@ bool Thread::start(const char* name)
return false; return false;
} }
bool Thread::join() bool Thread::join() {
{
int result = -1; int result = -1;
if (m_started) { if (m_started) {
@@ -82,36 +78,31 @@ void Thread::enter() {
WaitThread::WaitThread() WaitThread::WaitThread()
: Thread() : Thread() {
{
pthread_mutex_init(&m_mutex, NULL); pthread_mutex_init(&m_mutex, NULL);
pthread_cond_init(&m_cond, NULL); pthread_cond_init(&m_cond, NULL);
} }
WaitThread::~WaitThread() WaitThread::~WaitThread() {
{
pthread_mutex_destroy(&m_mutex); pthread_mutex_destroy(&m_mutex);
pthread_cond_destroy(&m_cond); pthread_cond_destroy(&m_cond);
} }
void WaitThread::stop() void WaitThread::stop() {
{
pthread_mutex_lock(&m_mutex); pthread_mutex_lock(&m_mutex);
pthread_cond_signal(&m_cond); pthread_cond_signal(&m_cond);
pthread_mutex_unlock(&m_mutex); pthread_mutex_unlock(&m_mutex);
Thread::stop(); Thread::stop();
} }
bool WaitThread::join() bool WaitThread::join() {
{
pthread_mutex_lock(&m_mutex); pthread_mutex_lock(&m_mutex);
pthread_cond_signal(&m_cond); pthread_cond_signal(&m_cond);
pthread_mutex_unlock(&m_mutex); pthread_mutex_unlock(&m_mutex);
return Thread::join(); return Thread::join();
} }
bool WaitThread::Wait(int seconds) bool WaitThread::Wait(int seconds) {
{
struct timespec t; struct timespec t;
clockGettime(&t); clockGettime(&t);
t.tv_sec += seconds; t.tv_sec += seconds;
+3 -3
View File
@@ -16,8 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef LIBUTILS_THREAD_H_ #ifndef LIB_UTILS_THREAD_H_
#define LIBUTILS_THREAD_H_ #define LIB_UTILS_THREAD_H_
#include <pthread.h> #include <pthread.h>
@@ -145,4 +145,4 @@ private:
}; };
#endif // LIBUTILS_THREAD_H_ #endif // LIB_UTILS_THREAD_H_
+33 -36
View File
@@ -21,16 +21,17 @@
#endif #endif
#include <argp.h> #include <argp.h>
#include "tcpsocket.h"
#include <string.h> #include <string.h>
#ifdef HAVE_PPOLL
# include <poll.h>
#endif
#include <cstdio> #include <cstdio>
#include <iostream> #include <iostream>
#include <cstdlib> #include <cstdlib>
#include <sstream> #include <sstream>
#include <string>
#include "tcpsocket.h"
#ifdef HAVE_PPOLL
# include <poll.h>
#endif
using namespace std; using namespace std;
@@ -84,8 +85,7 @@ static const struct argp_option argpoptions[] = {
* @param arg the option argument, or NULL. * @param arg the option argument, or NULL.
* @param state the parsing state. * @param state the parsing state.
*/ */
error_t parse_opt(int key, char *arg, struct argp_state *state) error_t parse_opt(int key, char *arg, struct argp_state *state) {
{
struct options *opt = (struct options*)state->input; struct options *opt = (struct options*)state->input;
char* strEnd = NULL; char* strEnd = NULL;
unsigned int port; unsigned int port;
@@ -116,8 +116,7 @@ error_t parse_opt(int key, char *arg, struct argp_state *state)
return 0; return 0;
} }
string fetchData(TCPSocket* socket, bool& listening) string fetchData(TCPSocket* socket, bool& listening) {
{
char data[1024]; char data[1024];
ssize_t datalen; ssize_t datalen;
ostringstream ostream; ostringstream ostream;
@@ -150,13 +149,13 @@ string fetchData(TCPSocket* socket, bool& listening)
FD_SET(STDIN_FILENO, &checkfds); FD_SET(STDIN_FILENO, &checkfds);
FD_SET(socket->getFD(), &checkfds); FD_SET(socket->getFD(), &checkfds);
maxfd = STDIN_FILENO; maxfd = STDIN_FILENO;
if (socket->getFD()>maxfd) if (socket->getFD() > maxfd) {
maxfd = socket->getFD(); maxfd = socket->getFD();
}
#endif #endif
#endif #endif
while(true) { while(true) {
#ifdef HAVE_PPOLL #ifdef HAVE_PPOLL
// wait for new fd event // wait for new fd event
ret = ppoll(fds, nfds, &tdiff, NULL); ret = ppoll(fds, nfds, &tdiff, NULL);
@@ -198,19 +197,20 @@ string fetchData(TCPSocket* socket, bool& listening)
break; break;
} }
for (int i = 0; i < datalen; i++) for (int i = 0; i < datalen; i++) {
ostream << data[i]; ostream << data[i];
}
string str = ostream.str(); string str = ostream.str();
if (listening) if (listening) {
return str;
if (str.length() >= 2 && str[str.length()-2] == '\n' && str[str.length()-1] == '\n')
return str; return str;
} }
else if (str.length() >= 2 && str[str.length()-2] == '\n' && str[str.length()-1] == '\n') {
return str;
}
} else {
break; break;
} }
else if (newInput) { } else if (newInput) {
getline(cin, message); getline(cin, message);
sendmessage = message+'\n'; sendmessage = message+'\n';
socket->send(sendmessage.c_str(), sendmessage.size()); socket->send(sendmessage.c_str(), sendmessage.size());
@@ -221,7 +221,6 @@ string fetchData(TCPSocket* socket, bool& listening)
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
return ""; return "";
} }
message.clear(); message.clear();
} }
} }
@@ -229,8 +228,7 @@ string fetchData(TCPSocket* socket, bool& listening)
return ostream.str(); return ostream.str();
} }
void connect(const char* host, uint16_t port, char* const *args, int argCount) void connect(const char* host, uint16_t port, char* const *args, int argCount) {
{
TCPClient* client = new TCPClient(); TCPClient* client = new TCPClient();
TCPSocket* socket = client->connect(host, port); TCPSocket* socket = client->connect(host, port);
@@ -247,16 +245,19 @@ void connect(const char* host, uint16_t port, char* const *args, int argCount)
} }
else { else {
for (int i = 0; i < argCount; i++) { for (int i = 0; i < argCount; i++) {
if (i > 0) if (i > 0) {
message += " "; message += " ";
}
bool quote = strchr(args[i], ' ') != NULL && strchr(args[i], '"') == NULL; bool quote = strchr(args[i], ' ') != NULL && strchr(args[i], '"') == NULL;
if (quote) if (quote) {
message += "\""; message += "\"";
}
message += args[i]; message += args[i];
if (quote) if (quote) {
message += "\""; message += "\"";
} }
} }
}
sendmessage = message+'\n'; sendmessage = message+'\n';
socket->send(sendmessage.c_str(), sendmessage.size()); socket->send(sendmessage.c_str(), sendmessage.size());
@@ -273,32 +274,28 @@ void connect(const char* host, uint16_t port, char* const *args, int argCount)
while (listening && !cin.eof()) { while (listening && !cin.eof()) {
string result(fetchData(socket, listening)); string result(fetchData(socket, listening));
cout << result; cout << result;
if (strcasecmp(result.c_str(), "LISTEN STOPPED") == 0) if (strcasecmp(result.c_str(), "LISTEN STOPPED") == 0) {
break; break;
} }
} }
else } else {
cout << fetchData(socket, listening); cout << fetchData(socket, listening);
} }
} while (!once && !cin.eof());
delete socket;
} }
else } while (!once && !cin.eof());
delete socket;
} else {
cout << "error connecting to " << host << ":" << port << endl; cout << "error connecting to " << host << ":" << port << endl;
}
delete client; delete client;
} }
int main(int argc, char* argv[]) int main(int argc, char* argv[]) {
{
struct argp argp = { argpoptions, parse_opt, argpargsdoc, argpdoc, NULL, NULL, NULL }; struct argp argp = { argpoptions, parse_opt, argpargsdoc, argpdoc, NULL, NULL, NULL };
setenv("ARGP_HELP_FMT", "no-dup-args-note", 0); setenv("ARGP_HELP_FMT", "no-dup-args-note", 0);
if (argp_parse(&argp, argc, argv, ARGP_IN_ORDER, NULL, &opt) != 0) if (argp_parse(&argp, argc, argv, ARGP_IN_ORDER, NULL, &opt) != 0) {
return EINVAL; return EINVAL;
}
connect(opt.server, opt.port, opt.args, opt.argCount); connect(opt.server, opt.port, opt.args, opt.argCount);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
+14 -21
View File
@@ -21,13 +21,13 @@
#endif #endif
#include <argp.h> #include <argp.h>
#include "device.h"
#include <unistd.h> #include <unistd.h>
#include <iostream>
#include <string.h> #include <string.h>
#include <iostream>
#include <cstdlib> #include <cstdlib>
#include <fstream> #include <fstream>
#include <iomanip> #include <iomanip>
#include "device.h"
using namespace std; using namespace std;
@@ -85,8 +85,7 @@ static const struct argp_option argpoptions[] = {
* @param arg the option argument, or NULL. * @param arg the option argument, or NULL.
* @param state the parsing state. * @param state the parsing state.
*/ */
error_t parse_opt(int key, char *arg, struct argp_state *state) error_t parse_opt(int key, char *arg, struct argp_state *state) {
{
struct options *opt = (struct options*)state->input; struct options *opt = (struct options*)state->input;
char* strEnd = NULL; char* strEnd = NULL;
switch (key) { switch (key) {
@@ -122,50 +121,44 @@ error_t parse_opt(int key, char *arg, struct argp_state *state)
} }
int main(int argc, char* argv[]) int main(int argc, char* argv[]) {
{
struct argp argp = { argpoptions, parse_opt, argpargsdoc, argpdoc, NULL, NULL, NULL }; struct argp argp = { argpoptions, parse_opt, argpargsdoc, argpdoc, NULL, NULL, NULL };
setenv("ARGP_HELP_FMT", "no-dup-args-note", 0); setenv("ARGP_HELP_FMT", "no-dup-args-note", 0);
if (argp_parse(&argp, argc, argv, ARGP_IN_ORDER, NULL, &opt) != 0) if (argp_parse(&argp, argc, argv, ARGP_IN_ORDER, NULL, &opt) != 0) {
return EINVAL; return EINVAL;
}
Device* device = Device::create(opt.device, false, false, NULL); Device* device = Device::create(opt.device, false, false, NULL);
if (device == NULL) { if (device == NULL) {
cout << "unable to create device " << opt.device << endl; cout << "unable to create device " << opt.device << endl;
return EINVAL; return EINVAL;
} }
result_t result = device->open(); result_t result = device->open();
if (result != RESULT_OK) if (result != RESULT_OK) {
cout << "unable to open " << opt.device << ": " << getResultCode(result) << endl; cout << "unable to open " << opt.device << ": " << getResultCode(result) << endl;
}
if (!device->isValid()) if (!device->isValid()) {
cout << "device " << opt.device << " not available" << endl; cout << "device " << opt.device << " not available" << endl;
else { } else {
cout << "device opened" << endl; cout << "device opened" << endl;
fstream file(opt.dumpFile, ios::in | ios::binary); fstream file(opt.dumpFile, ios::in | ios::binary);
if (file.is_open()) { if (file.is_open()) {
while (true) { while (true) {
unsigned char byte = (unsigned char)file.get(); unsigned char byte = (unsigned char)file.get();
if (file.eof()) if (file.eof()) {
break; break;
}
cout << hex << setw(2) << setfill('0') cout << hex << setw(2) << setfill('0')
<< static_cast<unsigned>(byte) << endl; << static_cast<unsigned>(byte) << endl;
device->send(byte); device->send(byte);
usleep(opt.time); usleep(opt.time);
} }
file.close(); file.close();
} } else {
else
cout << "error opening file " << opt.dumpFile << endl; cout << "error opening file " << opt.dumpFile << endl;
} }
}
delete device; delete device;
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} }