code style
This commit is contained in:
+145
-148
@@ -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;
|
||||||
|
|||||||
@@ -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_
|
||||||
|
|||||||
@@ -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]++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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_
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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_
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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_
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||||
|
|||||||
@@ -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
@@ -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);
|
||||||
|
|||||||
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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_
|
||||||
|
|||||||
@@ -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";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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_
|
||||||
|
|||||||
@@ -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
@@ -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_
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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_
|
||||||
|
|||||||
@@ -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
@@ -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_
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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_
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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_
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user