Merge branch 'master' of git://github.com/yuhu-/ebusd
Conflicts: src/lib/ebus/symbol.h
This commit is contained in:
+11
-10
@@ -11,14 +11,15 @@ Makefile.in
|
|||||||
.deps/
|
.deps/
|
||||||
*.o
|
*.o
|
||||||
*.dirstamp
|
*.dirstamp
|
||||||
/src/libcore/libcore.a
|
|
||||||
/src/libebus/libebus.a
|
|
||||||
/src/ebusd/ebusd
|
/src/ebusd/ebusd
|
||||||
/src/tools/ebusctl
|
/src/ebusctl/ebusctl
|
||||||
/src/test/test_bus
|
/src/lib/utils/libutils.a
|
||||||
/src/test/test_port
|
/src/lib/ebus/libebus.a
|
||||||
/src/test/test_configfile
|
/src/lib/ebus/test/test_bus
|
||||||
/src/test/test_commands
|
/src/lib/ebus/test/test_port
|
||||||
/src/test/test_decode
|
/src/lib/ebus/test/test_configfile
|
||||||
/src/test/test_encode
|
/src/lib/ebus/test/test_commands
|
||||||
/src/test/test_symbol
|
/src/lib/ebus/test/test_decode
|
||||||
|
/src/lib/ebus/test/test_encode
|
||||||
|
/src/lib/ebus/test/test_symbol
|
||||||
|
/src/lib/ebus/test/test_data
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
SUBDIRS = src/libebus src/test src/libcore src/ebusd src/tools
|
SUBDIRS = src/lib/ebus src/lib/ebus/test src/lib/utils src/ebusd src/ebusctl
|
||||||
|
|
||||||
distclean-local:
|
distclean-local:
|
||||||
-rm -rf autom4te.cache
|
-rm -rf autom4te.cache
|
||||||
|
|||||||
+4
-4
@@ -7,11 +7,11 @@ AC_CONFIG_AUX_DIR([build])
|
|||||||
AC_CONFIG_SRCDIR([src/ebusd/main.cpp])
|
AC_CONFIG_SRCDIR([src/ebusd/main.cpp])
|
||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_HEADERS([config.h])
|
||||||
AC_CONFIG_FILES([Makefile
|
AC_CONFIG_FILES([Makefile
|
||||||
src/libebus/Makefile
|
src/lib/ebus/Makefile
|
||||||
src/test/Makefile
|
src/lib/ebus/test/Makefile
|
||||||
src/libcore/Makefile
|
src/lib/utils/Makefile
|
||||||
src/ebusd/Makefile
|
src/ebusd/Makefile
|
||||||
src/tools/Makefile])
|
src/ebusctl/Makefile])
|
||||||
|
|
||||||
AM_INIT_AUTOMAKE([1.11 -Wall -Werror foreign])
|
AM_INIT_AUTOMAKE([1.11 -Wall -Werror foreign])
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
AM_CXXFLAGS = -fpic \
|
||||||
|
-Wall \
|
||||||
|
-Wextra \
|
||||||
|
-I$(top_srcdir)/src/lib/utils \
|
||||||
|
-I$(top_srcdir)/src/lib/ebus
|
||||||
|
|
||||||
|
bin_PROGRAMS = ebusctl
|
||||||
|
|
||||||
|
ebusctl_SOURCES = ebusctl.cpp
|
||||||
|
|
||||||
|
ebusctl_LDADD = $(top_srcdir)/src/lib/utils/libutils.a \
|
||||||
|
$(top_srcdir)/src/lib/ebus/libebus.a
|
||||||
|
|
||||||
|
distclean-local:
|
||||||
|
-rm -f Makefile.in
|
||||||
|
-rm -rf .libs
|
||||||
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
AM_CXXFLAGS = -fpic \
|
AM_CXXFLAGS = -fpic \
|
||||||
-Wall \
|
-Wall \
|
||||||
-Wextra \
|
-Wextra \
|
||||||
-I$(top_srcdir)/src/libcore \
|
-I$(top_srcdir)/src/lib/utils \
|
||||||
-I$(top_srcdir)/src/libebus
|
-I$(top_srcdir)/src/lib/ebus
|
||||||
|
|
||||||
bin_PROGRAMS = ebusd
|
bin_PROGRAMS = ebusd
|
||||||
|
|
||||||
@@ -17,8 +17,8 @@ ebusd_SOURCES = message.h \
|
|||||||
baseloop.h \
|
baseloop.h \
|
||||||
main.cpp
|
main.cpp
|
||||||
|
|
||||||
ebusd_LDADD = $(top_srcdir)/src/libcore/libcore.a \
|
ebusd_LDADD = $(top_srcdir)/src/lib/utils/libutils.a \
|
||||||
$(top_srcdir)/src/libebus/libebus.a \
|
$(top_srcdir)/src/lib/ebus/libebus.a \
|
||||||
-lpthread
|
-lpthread
|
||||||
|
|
||||||
distclean-local:
|
distclean-local:
|
||||||
|
|||||||
+24
-14
@@ -149,7 +149,7 @@ std::string BaseLoop::decodeMessage(const std::string& data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string ebusCommand(A.getParam<const char*>("p_address"));
|
std::string ebusCommand(A.getParam<const char*>("p_address"));
|
||||||
ebusCommand += m_commands->getEbusCommand(index);
|
ebusCommand += m_commands->getEbusCommand(index, false);
|
||||||
std::transform(ebusCommand.begin(), ebusCommand.end(), ebusCommand.begin(), tolower);
|
std::transform(ebusCommand.begin(), ebusCommand.end(), ebusCommand.begin(), tolower);
|
||||||
|
|
||||||
BusCommand* busCommand = new BusCommand(ebusCommand, false);
|
BusCommand* busCommand = new BusCommand(ebusCommand, false);
|
||||||
@@ -190,7 +190,7 @@ std::string BaseLoop::decodeMessage(const std::string& data)
|
|||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
|
|
||||||
std::string ebusCommand(A.getParam<const char*>("p_address"));
|
std::string ebusCommand(A.getParam<const char*>("p_address"));
|
||||||
ebusCommand += m_commands->getEbusCommand(index);
|
ebusCommand += m_commands->getEbusCommand(index, false);
|
||||||
|
|
||||||
// encode data
|
// encode data
|
||||||
Command* command = new Command(index, (*m_commands)[index], cmd[3]);
|
Command* command = new Command(index, (*m_commands)[index], cmd[3]);
|
||||||
@@ -292,17 +292,6 @@ std::string BaseLoop::decodeMessage(const std::string& data)
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case dump:
|
|
||||||
if (cmd.size() != 2) {
|
|
||||||
result << "usage: 'dump state' (state: on|off)";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcasecmp(cmd[1].c_str(), "ON") == 0) m_ebusloop->dump(true);
|
|
||||||
if (strcasecmp(cmd[1].c_str(), "OFF") == 0) m_ebusloop->dump(false);
|
|
||||||
result << "done";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case log:
|
case log:
|
||||||
if (cmd.size () != 3 ) {
|
if (cmd.size () != 3 ) {
|
||||||
result << "usage: 'log areas area,area,..' (areas: bas|net|bus|cyc|all)" << std::endl
|
result << "usage: 'log areas area,area,..' (areas: bas|net|bus|cyc|all)" << std::endl
|
||||||
@@ -328,6 +317,26 @@ std::string BaseLoop::decodeMessage(const std::string& data)
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case raw:
|
||||||
|
if (cmd.size() != 1) {
|
||||||
|
result << "usage: 'raw'";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ebusloop->raw();
|
||||||
|
result << "done";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case dump:
|
||||||
|
if (cmd.size() != 1) {
|
||||||
|
result << "usage: 'dump'";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ebusloop->dump();
|
||||||
|
result << "done";
|
||||||
|
break;
|
||||||
|
|
||||||
case reload:
|
case reload:
|
||||||
if (cmd.size() != 1) {
|
if (cmd.size() != 1) {
|
||||||
result << "usage: 'reload'";
|
result << "usage: 'reload'";
|
||||||
@@ -356,9 +365,10 @@ std::string BaseLoop::decodeMessage(const std::string& data)
|
|||||||
<< " set - set ebus values 'set class cmd value'" << std::endl
|
<< " set - set ebus values 'set class cmd value'" << std::endl
|
||||||
<< " cyc - fetch cycle data 'cyc class cmd (sub)'" << std::endl
|
<< " cyc - fetch cycle data 'cyc class cmd (sub)'" << std::endl
|
||||||
<< " hex - send given hex value 'hex type value' (value: ZZPBSBNNDx)" << std::endl << std::endl
|
<< " hex - send given hex value 'hex type value' (value: ZZPBSBNNDx)" << std::endl << std::endl
|
||||||
<< " dump - change dump state 'dump state' (state: on|off)" << std::endl << std::endl
|
|
||||||
<< " log - change log areas 'log areas area,area,..' (areas: bas|net|bus|cyc|all)" << std::endl
|
<< " log - change log areas 'log areas area,area,..' (areas: bas|net|bus|cyc|all)" << std::endl
|
||||||
<< " - change log level 'log level level' (level: error|event|trace|debug)" << std::endl << std::endl
|
<< " - change log level 'log level level' (level: error|event|trace|debug)" << std::endl << std::endl
|
||||||
|
<< " raw - toggle log raw data" << std::endl
|
||||||
|
<< " dump - toggle dump state" << std::endl << std::endl
|
||||||
<< " reload - reload ebus configuration" << std::endl << std::endl
|
<< " reload - reload ebus configuration" << std::endl << std::endl
|
||||||
<< " stop - stop daemon" << std::endl
|
<< " stop - stop daemon" << std::endl
|
||||||
<< " quit - close connection" << std::endl << std::endl
|
<< " quit - close connection" << std::endl << std::endl
|
||||||
|
|||||||
+13
-11
@@ -46,16 +46,17 @@ private:
|
|||||||
WQueue<Message*> m_queue;
|
WQueue<Message*> m_queue;
|
||||||
|
|
||||||
enum ClientCommand {
|
enum ClientCommand {
|
||||||
get, // get ebus data
|
get, // get ebus data
|
||||||
set, // set ebus value
|
set, // set ebus value
|
||||||
cyc, // fetch cycle data
|
cyc, // fetch cycle data
|
||||||
hex, // send hex value
|
hex, // send hex value
|
||||||
dump, // change dump state
|
log, // logger settings
|
||||||
log, // logger settings
|
raw, // toggle log raw data
|
||||||
reload, // reload ebus configuration
|
dump, // toggle dump state
|
||||||
help, // print commands
|
reload, // reload ebus configuration
|
||||||
notfound
|
help, // print commands
|
||||||
};
|
notfound
|
||||||
|
};
|
||||||
|
|
||||||
ClientCommand getCase(const std::string& item)
|
ClientCommand getCase(const std::string& item)
|
||||||
{
|
{
|
||||||
@@ -63,8 +64,9 @@ private:
|
|||||||
if (strcasecmp(item.c_str(), "SET") == 0) return set;
|
if (strcasecmp(item.c_str(), "SET") == 0) return set;
|
||||||
if (strcasecmp(item.c_str(), "CYC") == 0) return cyc;
|
if (strcasecmp(item.c_str(), "CYC") == 0) return cyc;
|
||||||
if (strcasecmp(item.c_str(), "HEX") == 0) return hex;
|
if (strcasecmp(item.c_str(), "HEX") == 0) return hex;
|
||||||
if (strcasecmp(item.c_str(), "DUMP") == 0) return dump;
|
|
||||||
if (strcasecmp(item.c_str(), "LOG") == 0) return log;
|
if (strcasecmp(item.c_str(), "LOG") == 0) return log;
|
||||||
|
if (strcasecmp(item.c_str(), "RAW") == 0) return raw;
|
||||||
|
if (strcasecmp(item.c_str(), "DUMP") == 0) return dump;
|
||||||
if (strcasecmp(item.c_str(), "RELOAD") == 0) return reload;
|
if (strcasecmp(item.c_str(), "RELOAD") == 0) return reload;
|
||||||
if (strcasecmp(item.c_str(), "HELP") == 0) return help;
|
if (strcasecmp(item.c_str(), "HELP") == 0) return help;
|
||||||
|
|
||||||
|
|||||||
+459
-146
@@ -24,207 +24,520 @@
|
|||||||
extern LogInstance& L;
|
extern LogInstance& L;
|
||||||
extern Appl& A;
|
extern Appl& A;
|
||||||
|
|
||||||
EBusLoop::EBusLoop(Commands* commands) : m_commands(commands), m_stop(false)
|
EBusLoop::EBusLoop(Commands* commands)
|
||||||
|
: m_commands(commands), m_stop(false), m_lockCounter(0), m_priorRetry(false)
|
||||||
{
|
{
|
||||||
m_deviceName = A.getParam<const char*>("p_device");
|
m_port = new Port(A.getParam<const char*>("p_device"), A.getParam<bool>("p_nodevicecheck"));
|
||||||
|
m_port->open();
|
||||||
|
|
||||||
m_bus = new Bus(m_deviceName,
|
if (m_port->isOpen() == false)
|
||||||
A.getParam<bool>("p_nodevicecheck"),
|
L.log(bus, error, "can't open %s", A.getParam<const char*>("p_device"));
|
||||||
A.getParam<long>("p_recvtimeout"),
|
|
||||||
A.getParam<const char*>("p_dumpfile"),
|
|
||||||
A.getParam<long>("p_dumpsize"),
|
|
||||||
A.getParam<bool>("p_dump"));
|
|
||||||
|
|
||||||
m_retries = A.getParam<int>("p_retries");
|
m_dump = new Dump(A.getParam<const char*>("p_dumpfile"), A.getParam<long>("p_dumpsize"));
|
||||||
|
m_dumpState = A.getParam<bool>("p_dump");
|
||||||
|
|
||||||
m_lookbusretries = A.getParam<int>("p_lookbusretries");
|
m_logRawData = A.getParam<bool>("p_lograwdata");
|
||||||
|
|
||||||
m_pollInterval = A.getParam<int>("p_pollinterval");
|
m_pollInterval = A.getParam<int>("p_pollinterval");
|
||||||
|
|
||||||
m_logAutoSyn = A.getParam<bool>("p_logautosyn");
|
m_recvTimeout = A.getParam<long>("p_recvtimeout");
|
||||||
|
|
||||||
m_bus->connect();
|
m_sendRetries = A.getParam<int>("p_sendretries");
|
||||||
|
|
||||||
if (m_bus->isConnected() == false)
|
m_lockRetries = A.getParam<int>("p_lockretries");
|
||||||
L.log(bus, error, "can't open %s", m_deviceName.c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EBusLoop::~EBusLoop()
|
EBusLoop::~EBusLoop()
|
||||||
{
|
{
|
||||||
m_bus->disconnect();
|
if (m_port->isOpen() == true)
|
||||||
|
m_port->close();
|
||||||
|
|
||||||
if (m_bus->isConnected() == true)
|
delete m_port;
|
||||||
L.log(bus, error, "error during disconnect.");
|
delete m_dump;
|
||||||
|
|
||||||
delete m_bus;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void* EBusLoop::run()
|
void* EBusLoop::run()
|
||||||
{
|
{
|
||||||
int busResult;
|
int sendRetries = 0;
|
||||||
int retries = 0;
|
int lockRetries = 0;
|
||||||
int lookbusretries = 0;
|
|
||||||
bool busCommandActive = false;
|
|
||||||
|
|
||||||
// polling
|
// polling
|
||||||
time_t pollStart, pollEnd;
|
time_t pollStart, pollEnd;
|
||||||
time(&pollStart);
|
time(&pollStart);
|
||||||
double pollDelta = 0.0;
|
double pollDelta;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (m_bus->isConnected() == true) {
|
if (m_port->isOpen() == true) {
|
||||||
|
ssize_t numBytes;
|
||||||
|
|
||||||
// work on bus
|
// add poll command
|
||||||
busResult = m_bus->proceed();
|
|
||||||
|
|
||||||
// new cyc message arrived
|
|
||||||
if (busResult == RESULT_SYN || busResult == RESULT_BUS_LOCKED) {
|
|
||||||
SymbolString data = m_bus->getCycData();
|
|
||||||
|
|
||||||
if (data.size() == 0 && m_logAutoSyn == true)
|
|
||||||
L.log(bus, trace, "aa");
|
|
||||||
|
|
||||||
if (data.size() != 0) {
|
|
||||||
L.log(bus, trace, "%s", data.getDataStr().c_str());
|
|
||||||
|
|
||||||
int index = m_commands->storeCycData(data.getDataStr());
|
|
||||||
|
|
||||||
if (index == -1) {
|
|
||||||
L.log(bus, debug, " command not found");
|
|
||||||
|
|
||||||
} else if (index == -2) {
|
|
||||||
L.log(bus, debug, " no commands defined");
|
|
||||||
|
|
||||||
} else if (index == -3) {
|
|
||||||
L.log(bus, debug, " search skipped - string too short");
|
|
||||||
|
|
||||||
} else {
|
|
||||||
std::string tmp;
|
|
||||||
tmp += (*m_commands)[index][1];
|
|
||||||
tmp += " ";
|
|
||||||
tmp += (*m_commands)[index][2];
|
|
||||||
L.log(bus, event, " cycle [%d] %s", index, tmp.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (busResult == RESULT_BUS_LOCKED)
|
|
||||||
L.log(bus, trace, "bus locked");
|
|
||||||
}
|
|
||||||
|
|
||||||
// add new bus command to send
|
|
||||||
if (busResult == RESULT_SYN && busCommandActive == false && m_sendBuffer.size() != 0) {
|
|
||||||
BusCommand* busCommand = m_sendBuffer.remove();
|
|
||||||
L.log(bus, debug, " msg: %s", busCommand->getCommand().getDataStr().c_str());
|
|
||||||
m_bus->addCommand(busCommand);
|
|
||||||
L.log(bus, debug, " addCommand success");
|
|
||||||
busCommandActive = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add new polling command
|
|
||||||
if (m_commands->sizePolDB() > 0) {
|
if (m_commands->sizePolDB() > 0) {
|
||||||
// check polling delta
|
// check polling delta
|
||||||
time(&pollEnd);
|
time(&pollEnd);
|
||||||
pollDelta = difftime(pollEnd, pollStart);
|
pollDelta = difftime(pollEnd, pollStart);
|
||||||
|
|
||||||
// add new polling command to send
|
// add new polling command to send
|
||||||
if (busResult == RESULT_SYN && busCommandActive == false && pollDelta >= m_pollInterval) {
|
if (pollDelta >= m_pollInterval) {
|
||||||
L.log(bus, trace, "polling Intervall reached");
|
addPollCommand();
|
||||||
|
|
||||||
int index = m_commands->nextPolCommand();
|
|
||||||
if (index < 0) {
|
|
||||||
L.log(bus, error, "polling index out of range");
|
|
||||||
time(&pollStart);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string tmp;
|
|
||||||
tmp += (*m_commands)[index][1];
|
|
||||||
tmp += " ";
|
|
||||||
tmp += (*m_commands)[index][2];
|
|
||||||
L.log(bus, event, " polling [%d] %s", index, tmp.c_str());
|
|
||||||
|
|
||||||
std::string ebusCommand(A.getParam<const char*>("p_address"));
|
|
||||||
ebusCommand += m_commands->getEbusCommand(index);
|
|
||||||
std::transform(ebusCommand.begin(), ebusCommand.end(), ebusCommand.begin(), tolower);
|
|
||||||
|
|
||||||
BusCommand* busCommand = new BusCommand(ebusCommand, true);
|
|
||||||
L.log(bus, trace, " msg: %s", ebusCommand.c_str());
|
|
||||||
|
|
||||||
m_bus->addCommand(busCommand);
|
|
||||||
L.log(bus, debug, " addCommand success");
|
|
||||||
busCommandActive = true;
|
|
||||||
|
|
||||||
time(&pollStart);
|
time(&pollStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// send bus command
|
// read device - no timeout needed (AUTO-SYN)
|
||||||
if (busResult == RESULT_BUS_ACQUIRED && busCommandActive == true) {
|
numBytes = m_port->recv(0);
|
||||||
L.log(bus, trace, " getBus success");
|
|
||||||
lookbusretries = 0;
|
|
||||||
BusCommand* busCommand = m_bus->sendCommand();
|
|
||||||
L.log(bus, trace, " %s", busCommand->getMessageStr().c_str());
|
|
||||||
|
|
||||||
if (busCommand->isErrorResult() == true && retries < m_retries) {
|
if (numBytes < 0) {
|
||||||
retries++;
|
L.log(bus, error, " ERR_DEVICE: generic device error");
|
||||||
L.log(bus, trace, " retry number: %d", retries);
|
continue;
|
||||||
busCommand->setResult(std::string(), RESULT_OK);
|
}
|
||||||
m_bus->addCommand(busCommand);
|
|
||||||
} else {
|
// cycle bytes
|
||||||
retries = 0;
|
collectCycData(numBytes);
|
||||||
if (busCommand->isPoll() == true) {
|
|
||||||
// only save correct results
|
// send command
|
||||||
if (busCommand->isErrorResult() == false)
|
if (m_sstr.size() == 0 && m_lockCounter == 0 && m_sendBuffer.size() > 0) {
|
||||||
|
// acquire Bus
|
||||||
|
int busResult = acquireBus();
|
||||||
|
|
||||||
|
// send bus command
|
||||||
|
if (busResult == RESULT_BUS_ACQUIRED) {
|
||||||
|
BusCommand* busCommand = sendCommand();
|
||||||
|
L.log(bus, trace, " %s", busCommand->getMessageStr().c_str());
|
||||||
|
|
||||||
|
if (busCommand->isErrorResult() == true) {
|
||||||
|
if (sendRetries < m_sendRetries) {
|
||||||
|
sendRetries++;
|
||||||
|
L.log(bus, trace, " send retry %d", sendRetries);
|
||||||
|
busCommand->setResult(std::string(), RESULT_OK);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sendRetries = 0;
|
||||||
|
if (busCommand->isPoll() == true)
|
||||||
|
delete m_sendBuffer.remove();
|
||||||
|
else
|
||||||
|
busCommand->sendSignal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sendRetries = 0;
|
||||||
|
if (busCommand->isPoll() == true) {
|
||||||
m_commands->storePolData(busCommand->getMessageStr().c_str()); // TODO use getResult()
|
m_commands->storePolData(busCommand->getMessageStr().c_str()); // TODO use getResult()
|
||||||
|
delete busCommand;
|
||||||
delete busCommand;
|
}
|
||||||
} else {
|
else
|
||||||
busCommand->sendSignal();
|
busCommand->sendSignal();
|
||||||
}
|
}
|
||||||
|
|
||||||
busCommandActive = false;
|
lockRetries = 0;
|
||||||
|
m_lockCounter = A.getParam<int>("p_lockcounter");
|
||||||
}
|
}
|
||||||
}
|
else if (busResult == RESULT_ERR_BUS_LOST) {
|
||||||
|
L.log(bus, trace, " acquire bus failed");
|
||||||
|
|
||||||
// get bus retry
|
if (lockRetries >= m_lockRetries) {
|
||||||
if (busResult == RESULT_BUS_PRIOR_RETRY)
|
L.log(bus, event, " lock bus failed");
|
||||||
L.log(bus, trace, " getBus prior retry");
|
BusCommand* busCommand = m_sendBuffer.remove();
|
||||||
|
if (busCommand->isPoll() == true)
|
||||||
|
delete busCommand;
|
||||||
|
else
|
||||||
|
busCommand->sendSignal();
|
||||||
|
|
||||||
if (busResult == RESULT_ERR_BUS_LOST) {
|
lockRetries = 0;
|
||||||
L.log(bus, trace, " getBus failure");
|
|
||||||
if (lookbusretries >= m_lookbusretries) {
|
|
||||||
L.log(bus, event, " getBus failed - command deleted");
|
|
||||||
BusCommand* busCommand = m_bus->delCommand();
|
|
||||||
if (busCommand->isPoll() == true) {
|
|
||||||
delete busCommand;
|
|
||||||
} else {
|
|
||||||
busCommand->sendSignal();
|
|
||||||
}
|
}
|
||||||
lookbusretries = 0;
|
else {
|
||||||
busCommandActive = false;
|
lockRetries++;
|
||||||
}else {
|
L.log(bus, trace, " lock retry %d", lockRetries);
|
||||||
lookbusretries++;
|
}
|
||||||
|
|
||||||
|
m_lockCounter = A.getParam<int>("p_lockcounter");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (busResult == RESULT_ERR_SEND)
|
}
|
||||||
L.log(bus, event, " getBus send error");
|
else {
|
||||||
|
// TODO: define max reopen
|
||||||
} else {
|
|
||||||
sleep(10);
|
sleep(10);
|
||||||
m_bus->connect();
|
m_port->open();
|
||||||
|
|
||||||
|
if (m_port->isOpen() == false)
|
||||||
|
L.log(bus, error, "can't open %s", A.getParam<const char*>("p_device"));
|
||||||
|
|
||||||
if (m_bus->isConnected() == false)
|
|
||||||
L.log(bus, error, "can't open %s", m_deviceName.c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_stop == true) {
|
if (m_stop == true) {
|
||||||
m_bus->disconnect();
|
if (m_port->isOpen() == true)
|
||||||
|
m_port->close();
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned char EBusLoop::fetchByte()
|
||||||
|
{
|
||||||
|
unsigned char byte;
|
||||||
|
|
||||||
|
// fetch byte
|
||||||
|
byte = m_port->byte();
|
||||||
|
|
||||||
|
if (m_dumpState == true)
|
||||||
|
m_dump->write((const char*) &byte);
|
||||||
|
|
||||||
|
if (m_logRawData == true)
|
||||||
|
L.log(bus, event, "%02x", byte);
|
||||||
|
|
||||||
|
return byte;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EBusLoop::collectCycData(const int numRecv)
|
||||||
|
{
|
||||||
|
// cycle bytes
|
||||||
|
for (int i = 0; i < numRecv; i++) {
|
||||||
|
|
||||||
|
// fetch byte
|
||||||
|
unsigned char byte = fetchByte();
|
||||||
|
|
||||||
|
if (byte == SYN) {
|
||||||
|
|
||||||
|
// analyse cycle data
|
||||||
|
if (m_sstr.size() > 0) {
|
||||||
|
|
||||||
|
analyseCycData();
|
||||||
|
|
||||||
|
if (m_sstr.size() == 1 && m_lockCounter == 0 && m_priorRetry == false)
|
||||||
|
m_lockCounter++;
|
||||||
|
|
||||||
|
else if (m_lockCounter > 0)
|
||||||
|
m_lockCounter--;
|
||||||
|
|
||||||
|
m_sstr.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (m_lockCounter > 0)
|
||||||
|
m_lockCounter--;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// collect cycle data
|
||||||
|
else
|
||||||
|
m_sstr.push_back(byte, true, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EBusLoop::analyseCycData()
|
||||||
|
{
|
||||||
|
L.log(bus, trace, "%s", m_sstr.getDataStr().c_str());
|
||||||
|
|
||||||
|
int index = m_commands->storeCycData(m_sstr.getDataStr());
|
||||||
|
|
||||||
|
if (index == -1) {
|
||||||
|
L.log(bus, debug, " command not found");
|
||||||
|
}
|
||||||
|
else if (index == -2) {
|
||||||
|
L.log(bus, debug, " no commands defined");
|
||||||
|
}
|
||||||
|
else if (index == -3) {
|
||||||
|
L.log(bus, debug, " search skipped - string too short");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::string tmp;
|
||||||
|
tmp += (*m_commands)[index][1];
|
||||||
|
tmp += " ";
|
||||||
|
tmp += (*m_commands)[index][2];
|
||||||
|
L.log(bus, event, " cycle [%4d] %s", index, tmp.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EBusLoop::addPollCommand()
|
||||||
|
{
|
||||||
|
int index = m_commands->nextPolCommand();
|
||||||
|
if (index < 0) {
|
||||||
|
L.log(bus, error, "polling index out of range");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// TODO: implement as methode from class commands?
|
||||||
|
std::string tmp;
|
||||||
|
tmp += (*m_commands)[index][1];
|
||||||
|
tmp += " ";
|
||||||
|
tmp += (*m_commands)[index][2];
|
||||||
|
L.log(bus, event, " polling [%4d] %s", index, tmp.c_str());
|
||||||
|
|
||||||
|
std::string ebusCommand(A.getParam<const char*>("p_address"));
|
||||||
|
ebusCommand += m_commands->getEbusCommand(index, false);
|
||||||
|
std::transform(ebusCommand.begin(), ebusCommand.end(), ebusCommand.begin(), tolower);
|
||||||
|
|
||||||
|
BusCommand* busCommand = new BusCommand(ebusCommand, true);
|
||||||
|
L.log(bus, trace, " msg: %s", ebusCommand.c_str());
|
||||||
|
|
||||||
|
addBusCommand(busCommand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int EBusLoop::acquireBus()
|
||||||
|
{
|
||||||
|
unsigned char recvByte, sendByte;
|
||||||
|
ssize_t numRecv, numSend;
|
||||||
|
|
||||||
|
sendByte = m_sendBuffer.next()->getCommand()[0];
|
||||||
|
|
||||||
|
// send QQ
|
||||||
|
numSend = m_port->send(&sendByte);
|
||||||
|
if (numSend <= 0) {
|
||||||
|
L.log(bus, error, " ERR_SEND: send error");
|
||||||
|
return RESULT_ERR_SEND;
|
||||||
|
}
|
||||||
|
|
||||||
|
// receive 1 byte - must be QQ
|
||||||
|
numRecv = m_port->recv(0);
|
||||||
|
|
||||||
|
if (numRecv < 0) {
|
||||||
|
L.log(bus, error, " ERR_DEVICE: generic device error");
|
||||||
|
return RESULT_ERR_DEVICE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (numRecv == 1) {
|
||||||
|
// fetch byte
|
||||||
|
recvByte = fetchByte();
|
||||||
|
|
||||||
|
// compare sent and received byte
|
||||||
|
if (sendByte == recvByte) {
|
||||||
|
L.log(bus, trace, " bus acquired");
|
||||||
|
return RESULT_BUS_ACQUIRED;
|
||||||
|
}
|
||||||
|
|
||||||
|
// collect cycle data
|
||||||
|
if (recvByte != SYN)
|
||||||
|
m_sstr.push_back(recvByte, true, false);
|
||||||
|
|
||||||
|
// compare prior nibble for retry
|
||||||
|
if ((sendByte & 0x0F) == (recvByte & 0x0F)) {
|
||||||
|
m_priorRetry = true;
|
||||||
|
L.log(bus, trace, " bus prior retry");
|
||||||
|
return RESULT_BUS_PRIOR_RETRY;
|
||||||
|
}
|
||||||
|
|
||||||
|
L.log(bus, error, " ERR_BUS_LOST: lost bus arbitration");
|
||||||
|
return RESULT_ERR_BUS_LOST;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cycle bytes
|
||||||
|
collectCycData(numRecv);
|
||||||
|
|
||||||
|
L.log(bus, error, " ERR_EXTRA_DATA: received bytes > sent bytes");
|
||||||
|
return RESULT_ERR_EXTRA_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
BusCommand* EBusLoop::sendCommand()
|
||||||
|
{
|
||||||
|
unsigned char recvByte;
|
||||||
|
std::string result;
|
||||||
|
SymbolString slaveData;
|
||||||
|
int retval = RESULT_OK;
|
||||||
|
|
||||||
|
BusCommand* busCommand = m_sendBuffer.next();
|
||||||
|
|
||||||
|
// send ZZ PB SB NN Dx CRC
|
||||||
|
SymbolString command = busCommand->getCommand();
|
||||||
|
for (size_t i = 1; i < command.size(); i++) {
|
||||||
|
retval = sendByte(command[i]);
|
||||||
|
if (retval < 0)
|
||||||
|
goto on_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// BC -> send SYN
|
||||||
|
if (busCommand->getType() == broadcast) {
|
||||||
|
sendByte(SYN);
|
||||||
|
goto on_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// receive ACK
|
||||||
|
retval = recvSlaveAck(recvByte);
|
||||||
|
if (retval < 0)
|
||||||
|
goto on_exit;
|
||||||
|
|
||||||
|
// is slave ACK negative?
|
||||||
|
if (recvByte == NAK) {
|
||||||
|
|
||||||
|
// send QQ ZZ PB SB NN Dx CRC again
|
||||||
|
for (size_t i = 0; i < command.size(); i++) {
|
||||||
|
retval = sendByte(command[i]);
|
||||||
|
if (retval < 0)
|
||||||
|
goto on_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// receive ACK
|
||||||
|
retval = recvSlaveAck(recvByte);
|
||||||
|
if (retval < 0)
|
||||||
|
goto on_exit;
|
||||||
|
|
||||||
|
// is slave ACK negative?
|
||||||
|
if (recvByte == NAK) {
|
||||||
|
sendByte(SYN);
|
||||||
|
L.log(bus, error, " ERR_NAK: NAK received");
|
||||||
|
retval = RESULT_ERR_NAK;
|
||||||
|
goto on_exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MM -> send SYN
|
||||||
|
if (busCommand->getType() == masterMaster) {
|
||||||
|
sendByte(SYN);
|
||||||
|
goto on_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// receive NN, Dx, CRC
|
||||||
|
retval = recvSlaveData(slaveData);
|
||||||
|
|
||||||
|
// are calculated and received CRC equal?
|
||||||
|
if (retval == RESULT_ERR_CRC) {
|
||||||
|
|
||||||
|
// send NAK
|
||||||
|
retval = sendByte(NAK);
|
||||||
|
if (retval < 0)
|
||||||
|
goto on_exit;
|
||||||
|
|
||||||
|
// receive NN, Dx, CRC
|
||||||
|
slaveData.clear();
|
||||||
|
retval = recvSlaveData(slaveData);
|
||||||
|
|
||||||
|
// are calculated and received CRC equal?
|
||||||
|
if (retval == RESULT_ERR_CRC) {
|
||||||
|
|
||||||
|
// send NAK
|
||||||
|
retval = sendByte(NAK);
|
||||||
|
if (retval >= 0)
|
||||||
|
retval = RESULT_ERR_CRC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retval < 0)
|
||||||
|
goto on_exit;
|
||||||
|
|
||||||
|
// send ACK
|
||||||
|
retval = sendByte(ACK);
|
||||||
|
if (retval == -1) {
|
||||||
|
L.log(bus, error, " ERR_ACK: ACK error");
|
||||||
|
retval = RESULT_ERR_ACK;
|
||||||
|
goto on_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// MS -> send SYN
|
||||||
|
sendByte(SYN);
|
||||||
|
|
||||||
|
on_exit:
|
||||||
|
|
||||||
|
// empty receive buffer
|
||||||
|
while (m_port->size() != 0)
|
||||||
|
recvByte = fetchByte();
|
||||||
|
|
||||||
|
busCommand->setResult(slaveData, retval);
|
||||||
|
|
||||||
|
if (retval == RESULT_OK)
|
||||||
|
return m_sendBuffer.remove();
|
||||||
|
else
|
||||||
|
return busCommand;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int EBusLoop::sendByte(const unsigned char sendByte)
|
||||||
|
{
|
||||||
|
unsigned char recvByte;
|
||||||
|
ssize_t numRecv, numSend;
|
||||||
|
|
||||||
|
numSend = m_port->send(&sendByte);
|
||||||
|
|
||||||
|
// receive 1 byte - must be equal
|
||||||
|
numRecv = m_port->recv(RECV_TIMEOUT);
|
||||||
|
|
||||||
|
if (numSend != numRecv) {
|
||||||
|
L.log(bus, error, " ERR_EXTRA_DATA: received bytes > sent bytes");
|
||||||
|
return RESULT_ERR_EXTRA_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
recvByte = fetchByte();
|
||||||
|
|
||||||
|
if (sendByte != recvByte) {
|
||||||
|
L.log(bus, error, " ERR_SEND: send error");
|
||||||
|
return RESULT_ERR_SEND;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RESULT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int EBusLoop::recvSlaveAck(unsigned char& recvByte)
|
||||||
|
{
|
||||||
|
ssize_t numRecv;
|
||||||
|
|
||||||
|
// receive ACK
|
||||||
|
numRecv = m_port->recv(m_recvTimeout);
|
||||||
|
|
||||||
|
if (numRecv > 1) {
|
||||||
|
L.log(bus, error, " ERR_EXTRA_DATA: received bytes > sent bytes");
|
||||||
|
return RESULT_ERR_EXTRA_DATA;
|
||||||
|
}
|
||||||
|
else if (numRecv < 0) {
|
||||||
|
L.log(bus, error, " ERR_TIMEOUT: read timeout");
|
||||||
|
return RESULT_ERR_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
recvByte = fetchByte();
|
||||||
|
|
||||||
|
// is received byte SYN?
|
||||||
|
if (recvByte == SYN) {
|
||||||
|
L.log(bus, error, " ERR_SYN: SYN received");
|
||||||
|
return RESULT_ERR_SYN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RESULT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int EBusLoop::recvSlaveData(SymbolString& result)
|
||||||
|
{
|
||||||
|
unsigned char recvByte, calcCrc = 0;
|
||||||
|
ssize_t numRecv;
|
||||||
|
size_t NN = 0;
|
||||||
|
bool updateCrc = true;
|
||||||
|
int retval = 0;
|
||||||
|
|
||||||
|
for (size_t i = 0, needed = 1; i < needed; i++) {
|
||||||
|
numRecv = m_port->recv(RECV_TIMEOUT);
|
||||||
|
if (numRecv < 0) {
|
||||||
|
L.log(bus, error, " ERR_TIMEOUT: read timeout");
|
||||||
|
return RESULT_ERR_TIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
recvByte = fetchByte();
|
||||||
|
retval = result.push_back(recvByte, true, updateCrc);
|
||||||
|
if (retval < 0)
|
||||||
|
return retval;
|
||||||
|
|
||||||
|
if (retval == RESULT_IN_ESC)
|
||||||
|
needed++;
|
||||||
|
else if (result.size() == 1) { // NN received
|
||||||
|
NN = result[0];
|
||||||
|
needed += NN;
|
||||||
|
}
|
||||||
|
else if (NN > 0 && result.size() == 1+NN) {// all data received
|
||||||
|
updateCrc = false;
|
||||||
|
calcCrc = result.getCRC();
|
||||||
|
needed++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retval == RESULT_IN_ESC) {
|
||||||
|
L.log(bus, error, " ERR_ESC: invalid escape sequence received");
|
||||||
|
return RESULT_ERR_ESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateCrc == true || calcCrc != result[result.size()-1]) {
|
||||||
|
L.log(bus, error, " ERR_CRC: CRC error");
|
||||||
|
return RESULT_ERR_CRC;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RESULT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
+34
-7
@@ -20,11 +20,16 @@
|
|||||||
#ifndef EBUSLOOP_H_
|
#ifndef EBUSLOOP_H_
|
||||||
#define EBUSLOOP_H_
|
#define EBUSLOOP_H_
|
||||||
|
|
||||||
#include "bus.h"
|
|
||||||
#include "commands.h"
|
#include "commands.h"
|
||||||
|
#include "port.h"
|
||||||
|
#include "dump.h"
|
||||||
|
#include "buscommand.h"
|
||||||
#include "wqueue.h"
|
#include "wqueue.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
|
|
||||||
|
/** the maximum time [us] allowed for retrieving a byte from an addressed slave */
|
||||||
|
#define RECV_TIMEOUT 10000
|
||||||
|
|
||||||
using namespace libebus;
|
using namespace libebus;
|
||||||
|
|
||||||
|
|
||||||
@@ -40,20 +45,42 @@ public:
|
|||||||
|
|
||||||
void addBusCommand(BusCommand* busCommand) { m_sendBuffer.add(busCommand); }
|
void addBusCommand(BusCommand* busCommand) { m_sendBuffer.add(busCommand); }
|
||||||
|
|
||||||
void dump(const bool dumpState) { m_bus->setDumpState(dumpState); }
|
void dump() { m_dumpState == true ? m_dumpState = false : m_dumpState = true ; }
|
||||||
|
void raw() { m_logRawData == true ? m_logRawData = false : m_logRawData = true ; }
|
||||||
|
|
||||||
void newCommands(Commands* commands) { m_commands = commands; }
|
void newCommands(Commands* commands) { m_commands = commands; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Commands* m_commands;
|
Commands* m_commands;
|
||||||
std::string m_deviceName;
|
Port* m_port;
|
||||||
Bus* m_bus;
|
|
||||||
|
Dump* m_dump;
|
||||||
|
bool m_dumpState;
|
||||||
|
|
||||||
|
bool m_logRawData;
|
||||||
|
|
||||||
bool m_stop;
|
bool m_stop;
|
||||||
|
|
||||||
|
int m_lockCounter;
|
||||||
|
bool m_priorRetry;
|
||||||
|
|
||||||
WQueue<BusCommand*> m_sendBuffer;
|
WQueue<BusCommand*> m_sendBuffer;
|
||||||
int m_retries;
|
SymbolString m_sstr;
|
||||||
int m_lookbusretries;
|
|
||||||
double m_pollInterval;
|
double m_pollInterval;
|
||||||
bool m_logAutoSyn;
|
long m_recvTimeout;
|
||||||
|
int m_sendRetries;
|
||||||
|
int m_lockRetries;
|
||||||
|
|
||||||
|
unsigned char fetchByte();
|
||||||
|
void collectCycData(const int numRecv);
|
||||||
|
void analyseCycData();
|
||||||
|
void addPollCommand();
|
||||||
|
int acquireBus();
|
||||||
|
BusCommand* sendCommand();
|
||||||
|
int sendByte(const unsigned char sendByte);
|
||||||
|
int recvSlaveAck(unsigned char& recvByte);
|
||||||
|
int recvSlaveData(SymbolString& result);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+10
-6
@@ -47,12 +47,16 @@ void define_args()
|
|||||||
"disable valid ebus device test\n",
|
"disable valid ebus device test\n",
|
||||||
Appl::type_bool, Appl::opt_none);
|
Appl::type_bool, Appl::opt_none);
|
||||||
|
|
||||||
A.addItem("p_retries", Appl::Param(2), "r", "retries",
|
A.addItem("p_sendretries", Appl::Param(2), "s", "sendretries",
|
||||||
"\tnumber retries send ebus command (2)",
|
"number retries send ebus command (2)",
|
||||||
Appl::type_int, Appl::opt_mandatory);
|
Appl::type_int, Appl::opt_mandatory);
|
||||||
|
|
||||||
A.addItem("p_lookbusretries", Appl::Param(2), "", "lookbusretries",
|
A.addItem("p_lockretries", Appl::Param(2), "", "lockretries",
|
||||||
"number retries to look ebus (2)",
|
"number retries to lock ebus (2)",
|
||||||
|
Appl::type_int, Appl::opt_mandatory);
|
||||||
|
|
||||||
|
A.addItem("p_lockcounter", Appl::Param(5), "", "lockcounter",
|
||||||
|
"number of SYN to unlock send function (5)",
|
||||||
Appl::type_int, Appl::opt_mandatory);
|
Appl::type_int, Appl::opt_mandatory);
|
||||||
|
|
||||||
A.addItem("p_recvtimeout", Appl::Param(15000), "", "recvtimeout",
|
A.addItem("p_recvtimeout", Appl::Param(15000), "", "recvtimeout",
|
||||||
@@ -91,8 +95,8 @@ void define_args()
|
|||||||
"\tlog level - error|event|trace|debug (event)",
|
"\tlog level - error|event|trace|debug (event)",
|
||||||
Appl::type_string, Appl::opt_mandatory);
|
Appl::type_string, Appl::opt_mandatory);
|
||||||
|
|
||||||
A.addItem("p_logautosyn", Appl::Param(false), "", "logautosyn",
|
A.addItem("p_lograwdata", Appl::Param(false), "", "lograwdata",
|
||||||
"log AUTO-SYN bytes\n",
|
"log raw data (bytes)\n",
|
||||||
Appl::type_bool, Appl::opt_none);
|
Appl::type_bool, Appl::opt_none);
|
||||||
|
|
||||||
A.addItem("p_dump", Appl::Param(false), "D", "dump",
|
A.addItem("p_dump", Appl::Param(false), "D", "dump",
|
||||||
|
|||||||
@@ -14,8 +14,6 @@ libebus_a_SOURCES = result.cpp \
|
|||||||
port.h \
|
port.h \
|
||||||
buscommand.cpp \
|
buscommand.cpp \
|
||||||
buscommand.h \
|
buscommand.h \
|
||||||
bus.cpp \
|
|
||||||
bus.h \
|
|
||||||
command.cpp \
|
command.cpp \
|
||||||
command.h \
|
command.h \
|
||||||
commands.cpp \
|
commands.cpp \
|
||||||
@@ -22,7 +22,6 @@
|
|||||||
namespace libebus
|
namespace libebus
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
BusCommand::BusCommand(const std::string commandStr, const bool isPoll)
|
BusCommand::BusCommand(const std::string commandStr, const bool isPoll)
|
||||||
: m_isPoll(isPoll), m_command(commandStr), m_result(), m_resultCode(RESULT_OK)
|
: m_isPoll(isPoll), m_command(commandStr), m_result(), m_resultCode(RESULT_OK)
|
||||||
{
|
{
|
||||||
@@ -34,6 +33,7 @@ BusCommand::BusCommand(const std::string commandStr, const bool isPoll)
|
|||||||
m_type = masterMaster;
|
m_type = masterMaster;
|
||||||
else
|
else
|
||||||
m_type = masterSlave;
|
m_type = masterSlave;
|
||||||
|
|
||||||
pthread_mutex_init(&m_mutex, NULL);
|
pthread_mutex_init(&m_mutex, NULL);
|
||||||
pthread_cond_init(&m_cond, NULL);
|
pthread_cond_init(&m_cond, NULL);
|
||||||
}
|
}
|
||||||
@@ -44,11 +44,6 @@ BusCommand::~BusCommand()
|
|||||||
pthread_cond_destroy(&m_cond);
|
pthread_cond_destroy(&m_cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* BusCommand::getResultCodeCStr()
|
|
||||||
{
|
|
||||||
return libebus::getResultCodeCStr(m_resultCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string BusCommand::getMessageStr()
|
const std::string BusCommand::getMessageStr()
|
||||||
{
|
{
|
||||||
std::string result;
|
std::string result;
|
||||||
@@ -59,9 +54,9 @@ const std::string BusCommand::getMessageStr()
|
|||||||
result += "00";
|
result += "00";
|
||||||
result += m_result.getDataStr();
|
result += m_result.getDataStr();
|
||||||
result += "00";
|
result += "00";
|
||||||
} else {
|
|
||||||
result = "success";
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
result = "success";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
result = "error: "+std::string(getResultCodeCStr());
|
result = "error: "+std::string(getResultCodeCStr());
|
||||||
@@ -34,17 +34,22 @@ class BusCommand
|
|||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BusCommand(const std::string commandStr, const bool isPoll);
|
BusCommand(const std::string command, const bool isPoll);
|
||||||
~BusCommand();
|
~BusCommand();
|
||||||
|
|
||||||
CommandType getType() const { return m_type; }
|
CommandType getType() const { return m_type; }
|
||||||
bool isPoll() const { return m_isPoll; }
|
bool isPoll() const { return m_isPoll; }
|
||||||
|
|
||||||
SymbolString getCommand() const { return m_command; }
|
SymbolString getCommand() const { return m_command; }
|
||||||
bool isErrorResult() const { return m_resultCode < 0; }
|
|
||||||
const char* getResultCodeCStr();
|
|
||||||
SymbolString getResult() const { return m_result; }
|
SymbolString getResult() const { return m_result; }
|
||||||
void setResult(const SymbolString result, const int resultCode) { m_result = result; m_resultCode = resultCode; }
|
|
||||||
|
bool isErrorResult() const { return m_resultCode < 0; }
|
||||||
|
const char* getResultCodeCStr() const { return libebus::getResultCodeCStr(m_resultCode); }
|
||||||
|
void setResult(const SymbolString result, const int resultCode)
|
||||||
|
{ m_result = result; m_resultCode = resultCode; }
|
||||||
|
|
||||||
const std::string getMessageStr();
|
const std::string getMessageStr();
|
||||||
|
|
||||||
void waitSignal() { pthread_cond_wait(&m_cond, &m_mutex); } // TODO timeout
|
void waitSignal() { pthread_cond_wait(&m_cond, &m_mutex); } // TODO timeout
|
||||||
void sendSignal() { pthread_cond_signal(&m_cond); }
|
void sendSignal() { pthread_cond_signal(&m_cond); }
|
||||||
|
|
||||||
@@ -127,15 +127,20 @@ int Commands::findCommand(const std::string& data) const
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Commands::getEbusCommand(const int index) const
|
std::string Commands::getEbusCommand(const int index, const bool cycle) const
|
||||||
{
|
{
|
||||||
cmd_t command = m_cmdDB.at(index);
|
cmd_t command = m_cmdDB.at(index);
|
||||||
std::string cmd(command[5]);
|
std::string cmd;
|
||||||
cmd += command[6];
|
|
||||||
std::stringstream sstr;
|
std::stringstream sstr;
|
||||||
|
|
||||||
|
if (cycle == true)
|
||||||
|
cmd += command[4]; // QQ
|
||||||
|
|
||||||
|
cmd += command[5]; // ZZ
|
||||||
|
cmd += command[6]; // PBSB
|
||||||
sstr << std::setw(2) << std::hex << std::setfill('0') << command[7];
|
sstr << std::setw(2) << std::hex << std::setfill('0') << command[7];
|
||||||
cmd += sstr.str();
|
cmd += sstr.str(); // NN
|
||||||
cmd += command[8];
|
cmd += command[8]; // Dx
|
||||||
|
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
@@ -158,7 +163,7 @@ int Commands::storeCycData(const std::string& data) const
|
|||||||
// walk through commands
|
// walk through commands
|
||||||
for (; iter != m_cycDB.end(); iter++) {
|
for (; iter != m_cycDB.end(); iter++) {
|
||||||
|
|
||||||
std::string command = getEbusCommand(iter->first);
|
std::string command = getEbusCommand(iter->first, true);
|
||||||
|
|
||||||
// skip wrong search string length
|
// skip wrong search string length
|
||||||
if (command.length() > search.length())
|
if (command.length() > search.length())
|
||||||
@@ -211,7 +216,7 @@ void Commands::storePolData(const std::string& data) const
|
|||||||
// walk through commands
|
// walk through commands
|
||||||
for (; iter != m_polDB.end(); iter++) {
|
for (; iter != m_polDB.end(); iter++) {
|
||||||
|
|
||||||
std::string command = getEbusCommand(iter->first);
|
std::string command = getEbusCommand(iter->first, false);
|
||||||
|
|
||||||
// skip wrong search string length
|
// skip wrong search string length
|
||||||
if (command.length() > search.length())
|
if (command.length() > search.length())
|
||||||
@@ -56,7 +56,7 @@ public:
|
|||||||
|
|
||||||
std::string getCmdType(const int index) const { return std::string(m_cmdDB.at(index)[0]); }
|
std::string getCmdType(const int index) const { return std::string(m_cmdDB.at(index)[0]); }
|
||||||
std::string getEbusType(const int index) const { return std::string(m_cmdDB.at(index)[4]); }
|
std::string getEbusType(const int index) const { return std::string(m_cmdDB.at(index)[4]); }
|
||||||
std::string getEbusCommand(const int index) const;
|
std::string getEbusCommand(const int index, const bool cycle) const;
|
||||||
|
|
||||||
int storeCycData(const std::string& data) const;
|
int storeCycData(const std::string& data) const;
|
||||||
std::string getCycData(int index) const;
|
std::string getCycData(int index) const;
|
||||||
@@ -26,7 +26,7 @@ namespace libebus
|
|||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
void ConfigFileCSV::readFile(std::istream& is, Commands& commands)
|
void ConfigFileCSV::parse(std::istream& is, Commands& commands)
|
||||||
{
|
{
|
||||||
std::string line;
|
std::string line;
|
||||||
|
|
||||||
@@ -50,9 +50,9 @@ void ConfigFileCSV::readFile(std::istream& is, Commands& commands)
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void ConfigFileXML::readFile(std::istream& is, Commands& commands)
|
void ConfigFileXML::parse(std::istream& is, Commands& commands)
|
||||||
{
|
{
|
||||||
; // ToDo: Implamantion for xml files
|
; // ToDo: Implementation for xml files
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -91,7 +91,7 @@ Commands* ConfigCommands::getCommands()
|
|||||||
std::fstream file((*i).c_str(), std::ios::in);
|
std::fstream file((*i).c_str(), std::ios::in);
|
||||||
|
|
||||||
if(file.is_open() == true) {
|
if(file.is_open() == true) {
|
||||||
m_configfile->readFile(file, *commands);
|
m_configfile->parse(file, *commands);
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,150 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) Roland Jax 2012-2014 <ebusd@liwest.at>
|
||||||
|
*
|
||||||
|
* This file is part of ebusd.
|
||||||
|
*
|
||||||
|
* ebusd is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* ebusd is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with ebusd. If not, see http://www.gnu.org/licenses/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIBEBUS_CONFIGFILE_H_
|
||||||
|
#define LIBEBUS_CONFIGFILE_H_
|
||||||
|
|
||||||
|
#include "commands.h"
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace libebus
|
||||||
|
{
|
||||||
|
|
||||||
|
/** available file endings / types. */
|
||||||
|
enum FileType { CSV, XML };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Base class for config files.
|
||||||
|
*/
|
||||||
|
class ConfigFile
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Destructor.
|
||||||
|
*/
|
||||||
|
virtual ~ConfigFile() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief read input stream and stored data into commands
|
||||||
|
* @param is open input stream for reading.
|
||||||
|
* @param commands object as datastore.
|
||||||
|
*/
|
||||||
|
virtual void parse(std::istream& is, Commands& commands) = 0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Class for CSV config files.
|
||||||
|
*/
|
||||||
|
class ConfigFileCSV : public ConfigFile
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Destructor.
|
||||||
|
*/
|
||||||
|
~ConfigFileCSV() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief read input stream and stored data into commands
|
||||||
|
* @param is open input stream for reading.
|
||||||
|
* @param commands object as datastore.
|
||||||
|
*/
|
||||||
|
void parse(std::istream& is, Commands& commands);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Class for XML config files.
|
||||||
|
*/
|
||||||
|
class ConfigFileXML : public ConfigFile
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Destructor.
|
||||||
|
*/
|
||||||
|
~ConfigFileXML() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief read input stream and stored data into commands
|
||||||
|
* @param is open input stream for reading.
|
||||||
|
* @param commands object as datastore.
|
||||||
|
*/
|
||||||
|
void parse(std::istream& is, Commands& commands);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Class for class Device.
|
||||||
|
*/
|
||||||
|
class ConfigCommands
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Set file type and add recursive files from given path.
|
||||||
|
* @param path to configuration files.
|
||||||
|
* @param Filetype to parse.
|
||||||
|
*/
|
||||||
|
ConfigCommands(const std::string path, const FileType type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destructor.
|
||||||
|
*/
|
||||||
|
~ConfigCommands() { delete m_configfile; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief setter for file type.
|
||||||
|
* @param FileType of files.
|
||||||
|
*/
|
||||||
|
void setType(const FileType type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Parse files for commands and store them into commands instance.
|
||||||
|
* @return a commands instance
|
||||||
|
*/
|
||||||
|
Commands* getCommands();
|
||||||
|
|
||||||
|
private:
|
||||||
|
/** the configfile instance */
|
||||||
|
ConfigFile* m_configfile;
|
||||||
|
/** main path for configuration files */
|
||||||
|
std::string m_path;
|
||||||
|
/** valid file extension */
|
||||||
|
std::string m_extension;
|
||||||
|
/** vector of configuration files */
|
||||||
|
std::vector<std::string> m_files;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief parse path for given file extension.
|
||||||
|
* @param path to configuration files.
|
||||||
|
* @param extension with file type.
|
||||||
|
*/
|
||||||
|
void addFiles(const std::string path, const std::string extension);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} //namespace
|
||||||
|
|
||||||
|
#endif // LIBEBUS_CONFIGFILE_H_
|
||||||
@@ -25,21 +25,44 @@
|
|||||||
namespace libebus
|
namespace libebus
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Class for writing raw bytes to binary file.
|
||||||
|
*/
|
||||||
class Dump
|
class Dump
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Create a new instance to write dump files.
|
||||||
|
* @param filename which will be used for dumping raw bytes.
|
||||||
|
* @param filesize max. Size of the dump file, before switching.
|
||||||
|
*/
|
||||||
Dump(std::string filename, long filesize)
|
Dump(std::string filename, long filesize)
|
||||||
: m_filename(filename), m_filesize(filesize) {}
|
: m_filename(filename), m_filesize(filesize) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief write byte to dump file.
|
||||||
|
* @param byte to write
|
||||||
|
* @return -1 if dump file cannot opened or renaming of dump file failed.
|
||||||
|
*/
|
||||||
int write(const char* byte);
|
int write(const char* byte);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief setter for dump file name.
|
||||||
|
* @param filename which will be used for dumping raw bytes.
|
||||||
|
*/
|
||||||
void setFilename(const std::string& filename) { m_filename = filename; }
|
void setFilename(const std::string& filename) { m_filename = filename; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief setter for max size of dump file.
|
||||||
|
* @param filesize max. Size of the dump file, before switching.
|
||||||
|
*/
|
||||||
void setFilesize(const long filesize) { m_filesize = filesize; }
|
void setFilesize(const long filesize) { m_filesize = filesize; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/** the name of dump file*/
|
||||||
std::string m_filename;
|
std::string m_filename;
|
||||||
|
/** max. size of dump file */
|
||||||
long m_filesize;
|
long m_filesize;
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -60,7 +60,7 @@ bool Device::isValid()
|
|||||||
ssize_t Device::sendBytes(const unsigned char* buffer, size_t nbytes)
|
ssize_t Device::sendBytes(const unsigned char* buffer, size_t nbytes)
|
||||||
{
|
{
|
||||||
if (isValid() == false)
|
if (isValid() == false)
|
||||||
return -1;
|
return -1; // TODO RESULT_ERR_DEVICE
|
||||||
|
|
||||||
// write bytes to device
|
// write bytes to device
|
||||||
return write(m_fd, buffer, nbytes);
|
return write(m_fd, buffer, nbytes);
|
||||||
@@ -86,18 +86,16 @@ ssize_t Device::recvBytes(const long timeout, size_t maxCount)
|
|||||||
return -2; // TODO RESULT_ERR_TIMEOUT
|
return -2; // TODO RESULT_ERR_TIMEOUT
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t bytes_read = sizeof(m_buffer);
|
|
||||||
if (maxCount > sizeof(m_buffer))
|
if (maxCount > sizeof(m_buffer))
|
||||||
maxCount = sizeof(m_buffer);
|
maxCount = sizeof(m_buffer);
|
||||||
|
|
||||||
|
|
||||||
// read bytes from device
|
// read bytes from device
|
||||||
bytes_read = read(m_fd, m_buffer, maxCount);
|
ssize_t nbytes = read(m_fd, m_buffer, maxCount);
|
||||||
|
|
||||||
for (int i = 0; i < bytes_read; i++)
|
for (int i = 0; i < nbytes; i++)
|
||||||
m_recvBuffer.push(m_buffer[i]);
|
m_recvBuffer.push(m_buffer[i]);
|
||||||
|
|
||||||
return bytes_read;
|
return nbytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char Device::getByte()
|
unsigned char Device::getByte()
|
||||||
@@ -0,0 +1,267 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) Roland Jax 2012-2014 <ebusd@liwest.at>
|
||||||
|
*
|
||||||
|
* This file is part of ebusd.
|
||||||
|
*
|
||||||
|
* ebusd is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* ebusd is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with ebusd. If not, see http://www.gnu.org/licenses/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIBEBUS_PORT_H_
|
||||||
|
#define LIBEBUS_PORT_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <queue>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
namespace libebus
|
||||||
|
{
|
||||||
|
|
||||||
|
/** available device types. */
|
||||||
|
enum DeviceType { SERIAL, NETWORK };
|
||||||
|
|
||||||
|
/** max bytes write to bus. */
|
||||||
|
#define MAX_WRITE_SIZE 1
|
||||||
|
|
||||||
|
/** max size of receive buffer. */
|
||||||
|
#define MAX_READ_SIZE 100
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Base class for input devices.
|
||||||
|
*/
|
||||||
|
class Device
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Constructs a new instance.
|
||||||
|
*/
|
||||||
|
Device() : m_fd(-1), m_open(false), m_noDeviceCheck(false) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destructor.
|
||||||
|
*/
|
||||||
|
virtual ~Device() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief virtual open function for opening file descriptor
|
||||||
|
* @param deviceName to determine device type.
|
||||||
|
* @param noDeviceCheck en-/disable device check.
|
||||||
|
*/
|
||||||
|
virtual void openDevice(const std::string deviceName, const bool noDeviceCheck) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief virtual close function for closing opened file descriptor
|
||||||
|
*/
|
||||||
|
virtual void closeDevice() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief connection state of device.
|
||||||
|
* @return true if device is open
|
||||||
|
*/
|
||||||
|
bool isOpen();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief sendBytes write bytes into opened file descriptor.
|
||||||
|
* @param buffer data to send.
|
||||||
|
* @param nbytes number of bytes to send.
|
||||||
|
* @return number of written bytes or -1 if an error has occured.
|
||||||
|
*/
|
||||||
|
ssize_t sendBytes(const unsigned char* buffer, size_t nbytes);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief recvBytes read bytes from opened file descriptor.
|
||||||
|
* @param timeout max time out for new input data.
|
||||||
|
* @param maxCount max size of receive buffer.
|
||||||
|
* @return number of read bytes or -1 if an error has occured.
|
||||||
|
*/
|
||||||
|
ssize_t recvBytes(const long timeout, size_t maxCount);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief fetch first byte from receive buffer.
|
||||||
|
* @return first byte (raw)
|
||||||
|
*/
|
||||||
|
unsigned char getByte();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief get current size (bytes) of the receive buffer.
|
||||||
|
* @return number of bytes in queued.
|
||||||
|
*/
|
||||||
|
ssize_t sizeRecvBuffer() const { return m_recvBuffer.size(); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/** if of file descriptor */
|
||||||
|
int m_fd;
|
||||||
|
/** state of device*/
|
||||||
|
bool m_open;
|
||||||
|
/** state of device check */
|
||||||
|
bool m_noDeviceCheck;
|
||||||
|
/** queue for received bytes */
|
||||||
|
std::queue<unsigned char> m_recvBuffer;
|
||||||
|
/** receive buffer */
|
||||||
|
unsigned char m_buffer[MAX_READ_SIZE];
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* @brief system check if opened file descriptor is valid
|
||||||
|
* @return true if file descriptor is valid
|
||||||
|
*/
|
||||||
|
bool isValid();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Class for serial input device.
|
||||||
|
*/
|
||||||
|
class DeviceSerial : public Device
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Destructor.
|
||||||
|
*/
|
||||||
|
~DeviceSerial() { closeDevice(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief open function for opening file descriptor
|
||||||
|
* @param deviceName to determine device type.
|
||||||
|
* @param noDeviceCheck en-/disable device check.
|
||||||
|
*/
|
||||||
|
void openDevice(const std::string deviceName, const bool noDeviceCheck);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief close function for closing opened file descriptor
|
||||||
|
*/
|
||||||
|
void closeDevice();
|
||||||
|
|
||||||
|
private:
|
||||||
|
/** save settings from serial device */
|
||||||
|
termios m_oldSettings;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Class for network input device.
|
||||||
|
*/
|
||||||
|
class DeviceNetwork : public Device
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Destructor.
|
||||||
|
*/
|
||||||
|
~DeviceNetwork() { closeDevice(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief open function for opening file descriptor
|
||||||
|
* @param deviceName to determine device type.
|
||||||
|
* @param noDeviceCheck en-/disable device check.
|
||||||
|
*/
|
||||||
|
void openDevice(const std::string deviceName, const bool noDeviceCheck);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief close opened file descriptor
|
||||||
|
*/
|
||||||
|
void closeDevice();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Wrapper class for class Device.
|
||||||
|
*/
|
||||||
|
class Port
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Constructs a new instance and determine device type.
|
||||||
|
* @param deviceName to determine device type.
|
||||||
|
* @param noDeviceCheck en-/disable device check.
|
||||||
|
*/
|
||||||
|
Port(const std::string deviceName, const bool noDeviceCheck);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Destructor.
|
||||||
|
*/
|
||||||
|
~Port() { delete m_device; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief open device
|
||||||
|
*/
|
||||||
|
void open() { m_device->openDevice(m_deviceName, m_noDeviceCheck); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief close device
|
||||||
|
*/
|
||||||
|
void close() { m_device->closeDevice(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief connection state of device.
|
||||||
|
* @return true if device is open
|
||||||
|
*/
|
||||||
|
bool isOpen() { return m_device->isOpen(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief send write bytes into opened file descriptor.
|
||||||
|
* @param buffer data to send.
|
||||||
|
* @param nbytes number of bytes to send.
|
||||||
|
* @return number of written bytes or -1 if an error has occured.
|
||||||
|
*/
|
||||||
|
ssize_t send(const unsigned char* buffer, size_t nbytes = MAX_WRITE_SIZE)
|
||||||
|
{ return m_device->sendBytes(buffer, nbytes); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief recv read bytes from opened file descriptor.
|
||||||
|
* @param timeout max time out for new input data.
|
||||||
|
* @param maxCount max size of receive buffer.
|
||||||
|
* @return number of read bytes or -1 if an error has occured.
|
||||||
|
*/
|
||||||
|
ssize_t recv(const long timeout, size_t maxCount = MAX_READ_SIZE)
|
||||||
|
{ return m_device->recvBytes(timeout, maxCount); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief fetch first byte from receive buffer.
|
||||||
|
* @return first byte (raw)
|
||||||
|
*/
|
||||||
|
unsigned char byte() { return m_device->getByte(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief get current size (bytes) of the receive buffer.
|
||||||
|
* @return number of bytes in queued.
|
||||||
|
*/
|
||||||
|
ssize_t size() const { return m_device->sizeRecvBuffer(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
/** the device name */
|
||||||
|
std::string m_deviceName;
|
||||||
|
/** the device instance */
|
||||||
|
Device* m_device;
|
||||||
|
/** true if device check is disabled */
|
||||||
|
bool m_noDeviceCheck;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief internal setter for device type.
|
||||||
|
* @param type of device
|
||||||
|
*/
|
||||||
|
void setType(const DeviceType type);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} //namespace
|
||||||
|
|
||||||
|
#endif // LIBEBUS_PORT_H_
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) John Baier 2012-2014 <ebusd@johnm.de>
|
* Copyright (C) John Baier 2014 <ebusd@johnm.de>
|
||||||
*
|
*
|
||||||
* This file is part of ebusd.
|
* This file is part of ebusd.
|
||||||
*
|
*
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) John Baier 2012-2014 <ebusd@johnm.de>
|
* Copyright (C) John Baier 2014 <ebusd@johnm.de>
|
||||||
*
|
*
|
||||||
* This file is part of ebusd.
|
* This file is part of ebusd.
|
||||||
*
|
*
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) John Baier 2012-2014 <ebusd@johnm.de>
|
* Copyright (C) John Baier 2014 <ebusd@johnm.de>
|
||||||
*
|
*
|
||||||
* This file is part of ebusd.
|
* This file is part of ebusd.
|
||||||
*
|
*
|
||||||
@@ -79,15 +79,13 @@ const std::string SymbolString::getDataStr(const bool unescape)
|
|||||||
for (size_t i = 0; i < m_data.size(); i++) {
|
for (size_t i = 0; i < m_data.size(); i++) {
|
||||||
unsigned char value = m_data[i];
|
unsigned char value = m_data[i];
|
||||||
if (m_unescapeState == 0 && unescape == true && previousEscape == true) {
|
if (m_unescapeState == 0 && unescape == true && previousEscape == true) {
|
||||||
if (value == 0x00) {
|
if (value == 0x00)
|
||||||
sstr << "a9"; // ESC
|
sstr << "a9"; // ESC
|
||||||
}
|
else if (value == 0x01)
|
||||||
else if (value == 0x01) {
|
|
||||||
sstr << "aa"; // SYN
|
sstr << "aa"; // SYN
|
||||||
}
|
else
|
||||||
else {
|
|
||||||
sstr << "XX"; // invalid escape sequence
|
sstr << "XX"; // invalid escape sequence
|
||||||
}
|
|
||||||
previousEscape = false;
|
previousEscape = false;
|
||||||
}
|
}
|
||||||
else if (m_unescapeState == 0 && unescape == true && value == ESC) {
|
else if (m_unescapeState == 0 && unescape == true && value == ESC) {
|
||||||
@@ -123,9 +121,9 @@ int SymbolString::push_back(const unsigned char value, const bool isEscaped, con
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_data.push_back(value);
|
m_data.push_back(value);
|
||||||
if (updateCRC) {
|
if (updateCRC)
|
||||||
addCRC(value);
|
addCRC(value);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return RESULT_OK;
|
return RESULT_OK;
|
||||||
}
|
}
|
||||||
@@ -149,9 +147,9 @@ int SymbolString::push_back(const unsigned char value, const bool isEscaped, con
|
|||||||
return RESULT_OK;
|
return RESULT_OK;
|
||||||
}
|
}
|
||||||
else if (m_unescapeState != 1) {
|
else if (m_unescapeState != 1) {
|
||||||
if (updateCRC) {
|
if (updateCRC)
|
||||||
addCRC(value);
|
addCRC(value);
|
||||||
}
|
|
||||||
if (value == 0x00) {
|
if (value == 0x00) {
|
||||||
m_data.push_back(ESC);
|
m_data.push_back(ESC);
|
||||||
m_unescapeState = 1;
|
m_unescapeState = 1;
|
||||||
@@ -165,15 +163,15 @@ int SymbolString::push_back(const unsigned char value, const bool isEscaped, con
|
|||||||
return RESULT_ERR_ESC; // invalid escape sequence
|
return RESULT_ERR_ESC; // invalid escape sequence
|
||||||
}
|
}
|
||||||
else if (value == ESC) {
|
else if (value == ESC) {
|
||||||
if (updateCRC) {
|
if (updateCRC)
|
||||||
addCRC(value);
|
addCRC(value);
|
||||||
}
|
|
||||||
m_unescapeState = 2;
|
m_unescapeState = 2;
|
||||||
return RESULT_IN_ESC;
|
return RESULT_IN_ESC;
|
||||||
}
|
}
|
||||||
if (updateCRC) {
|
if (updateCRC)
|
||||||
addCRC(value);
|
addCRC(value);
|
||||||
}
|
|
||||||
m_data.push_back(value);
|
m_data.push_back(value);
|
||||||
return RESULT_OK;
|
return RESULT_OK;
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) John Baier 2012-2014 <ebusd@johnm.de>
|
* Copyright (C) John Baier 2014 <ebusd@johnm.de>
|
||||||
*
|
*
|
||||||
* This file is part of ebusd.
|
* This file is part of ebusd.
|
||||||
*
|
*
|
||||||
@@ -41,6 +41,7 @@ static const unsigned char BROADCAST = 0xFE; // the broadcast destination addres
|
|||||||
*/
|
*/
|
||||||
class SymbolString
|
class SymbolString
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Creates a new unescaped empty instance.
|
* @brief Creates a new unescaped empty instance.
|
||||||
@@ -81,7 +82,7 @@ public:
|
|||||||
* @param other the other instance.
|
* @param other the other instance.
|
||||||
* @return true if this instance is equal to the other instance (i.e. both escaped or both unescaped and same symbols).
|
* @return true if this instance is equal to the other instance (i.e. both escaped or both unescaped and same symbols).
|
||||||
*/
|
*/
|
||||||
bool operator==(SymbolString other) { return m_unescapeState==other.m_unescapeState && m_data==other.m_data; }
|
bool operator==(SymbolString other) { return (m_unescapeState==0)==(other.m_unescapeState==0) && m_data==other.m_data; }
|
||||||
/**
|
/**
|
||||||
* @brief Appends a the symbol to the end of the symbol string and escapes/unescapes it if necessary.
|
* @brief Appends a the symbol to the end of the symbol string and escapes/unescapes it if necessary.
|
||||||
* @param value the symbol to append.
|
* @param value the symbol to append.
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
AM_CXXFLAGS = -fpic \
|
||||||
|
-Wall \
|
||||||
|
-Wextra \
|
||||||
|
-I$(top_srcdir)/src/lib/ebus
|
||||||
|
|
||||||
|
noinst_PROGRAMS = test_port \
|
||||||
|
test_symbol \
|
||||||
|
test_data \
|
||||||
|
test_commands \
|
||||||
|
test_configfile \
|
||||||
|
test_decode \
|
||||||
|
test_encode
|
||||||
|
|
||||||
|
test_port_SOURCES = test_port.cpp
|
||||||
|
test_port_LDADD = $(top_srcdir)/src/lib/ebus/libebus.a
|
||||||
|
|
||||||
|
test_symbol_SOURCES = test_symbol.cpp
|
||||||
|
test_symbol_LDADD = $(top_srcdir)/src/lib/ebus/libebus.a
|
||||||
|
|
||||||
|
test_data_SOURCES = test_data.cpp
|
||||||
|
test_data_LDADD = $(top_srcdir)/src/lib/ebus/libebus.a
|
||||||
|
|
||||||
|
test_commands_SOURCES = test_commands.cpp
|
||||||
|
test_commands_LDADD = $(top_srcdir)/src/lib/ebus/libebus.a
|
||||||
|
|
||||||
|
test_configfile_SOURCES = test_configfile.cpp
|
||||||
|
test_configfile_LDADD = $(top_srcdir)/src/lib/ebus/libebus.a
|
||||||
|
|
||||||
|
test_decode_SOURCES = test_decode.cpp
|
||||||
|
test_decode_LDADD = $(top_srcdir)/src/lib/ebus/libebus.a
|
||||||
|
|
||||||
|
test_encode_SOURCES = test_encode.cpp
|
||||||
|
test_encode_LDADD = $(top_srcdir)/src/lib/ebus/libebus.a
|
||||||
|
|
||||||
|
distclean-local:
|
||||||
|
-rm -f Makefile.in
|
||||||
|
-rm -rf .libs
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) John Baier 2012-2014 <ebusd@johnm.de>
|
* Copyright (C) John Baier 2014 <ebusd@johnm.de>
|
||||||
*
|
*
|
||||||
* This file is part of ebusd.
|
* This file is part of ebusd.
|
||||||
*
|
*
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
AM_CXXFLAGS = -fpic \
|
||||||
|
-Wall \
|
||||||
|
-Wextra
|
||||||
|
|
||||||
|
noinst_LIBRARIES = libutils.a
|
||||||
|
|
||||||
|
libutils_a_SOURCES = wqueue.h \
|
||||||
|
notify.h \
|
||||||
|
appl.cpp \
|
||||||
|
appl.h \
|
||||||
|
daemon.cpp \
|
||||||
|
daemon.h \
|
||||||
|
logger.cpp \
|
||||||
|
logger.h \
|
||||||
|
thread.cpp \
|
||||||
|
thread.h \
|
||||||
|
tcpsocket.cpp \
|
||||||
|
tcpsocket.h
|
||||||
|
|
||||||
|
distclean-local:
|
||||||
|
-rm -f Makefile.in
|
||||||
@@ -62,7 +62,7 @@ void Appl::addItem(const char* name, Param param, const char* shortname,
|
|||||||
void Appl::printArgs()
|
void Appl::printArgs()
|
||||||
{
|
{
|
||||||
std::cerr << std::endl << "Usage:" << std::endl << " "
|
std::cerr << std::endl << "Usage:" << std::endl << " "
|
||||||
<< m_argv[0].substr(2) << " [OPTIONS...]" ;
|
<< m_argv[0].substr(m_argv[0].find_last_of("/\\") + 1) << " [OPTIONS...]" ;
|
||||||
|
|
||||||
if (m_argTxt.size() != 0)
|
if (m_argTxt.size() != 0)
|
||||||
std::cerr << " " << m_argTxt;
|
std::cerr << " " << m_argTxt;
|
||||||
@@ -64,6 +64,20 @@ public:
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
T next()
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&m_mutex);
|
||||||
|
|
||||||
|
while (m_queue.size() == 0)
|
||||||
|
pthread_cond_wait(&m_cond, &m_mutex);
|
||||||
|
|
||||||
|
T item = m_queue.front();
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&m_mutex);
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
int size()
|
int size()
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&m_mutex);
|
pthread_mutex_lock(&m_mutex);
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
AM_CXXFLAGS = -fpic \
|
|
||||||
-Wall \
|
|
||||||
-Wextra
|
|
||||||
|
|
||||||
noinst_LIBRARIES = libcore.a
|
|
||||||
|
|
||||||
libcore_a_SOURCES = wqueue.h \
|
|
||||||
notify.h \
|
|
||||||
appl.cpp \
|
|
||||||
appl.h \
|
|
||||||
daemon.cpp \
|
|
||||||
daemon.h \
|
|
||||||
logger.cpp \
|
|
||||||
logger.h \
|
|
||||||
thread.cpp \
|
|
||||||
thread.h \
|
|
||||||
tcpsocket.cpp \
|
|
||||||
tcpsocket.h
|
|
||||||
|
|
||||||
distclean-local:
|
|
||||||
-rm -f Makefile.in
|
|
||||||
@@ -1,388 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) Roland Jax 2012-2014 <ebusd@liwest.at>
|
|
||||||
*
|
|
||||||
* This file is part of ebusd.
|
|
||||||
*
|
|
||||||
* ebusd is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* ebusd is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with ebusd. If not, see http://www.gnu.org/licenses/.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "bus.h"
|
|
||||||
#include <iostream>
|
|
||||||
#include <iomanip>
|
|
||||||
|
|
||||||
namespace libebus
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
Bus::Bus(const std::string deviceName, const bool noDeviceCheck, const long recvTimeout,
|
|
||||||
const std::string dumpFile, const long dumpSize, const bool dumpState)
|
|
||||||
: m_sstr(), m_recvTimeout(recvTimeout), m_dumpState(dumpState),
|
|
||||||
m_busLocked(false), m_busPriorRetry(false)
|
|
||||||
{
|
|
||||||
m_port = new Port(deviceName, noDeviceCheck);
|
|
||||||
m_dump = new Dump(dumpFile, dumpSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
Bus::~Bus()
|
|
||||||
{
|
|
||||||
if (isConnected() == true)
|
|
||||||
disconnect();
|
|
||||||
|
|
||||||
delete m_port;
|
|
||||||
delete m_dump;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Bus::printBytes() const
|
|
||||||
{
|
|
||||||
unsigned char byte;
|
|
||||||
ssize_t bytes_read;
|
|
||||||
|
|
||||||
bytes_read = m_port->recv(0);
|
|
||||||
|
|
||||||
for (int i = 0; i < bytes_read; i++) {
|
|
||||||
byte = m_port->byte();
|
|
||||||
std::cout << std::nouppercase << std::hex << std::setw(2)
|
|
||||||
<< std::setfill('0') << static_cast<unsigned>(byte);
|
|
||||||
if (byte == SYN)
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int Bus::proceed()
|
|
||||||
{
|
|
||||||
unsigned char byte_recv;
|
|
||||||
ssize_t bytes_recv;
|
|
||||||
|
|
||||||
// fetch new message and get bus
|
|
||||||
if (m_sendBuffer.size() != 0 && m_sstr.size() == 0) {
|
|
||||||
BusCommand* busCommand = m_sendBuffer.front();
|
|
||||||
return getBus(busCommand->getCommand()[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// wait for new data
|
|
||||||
bytes_recv = m_port->recv(0);
|
|
||||||
|
|
||||||
if (bytes_recv < 0)
|
|
||||||
return RESULT_ERR_DEVICE;
|
|
||||||
|
|
||||||
for (int i = 0; i < bytes_recv; i++) {
|
|
||||||
|
|
||||||
// fetch next byte
|
|
||||||
byte_recv = recvByte();
|
|
||||||
|
|
||||||
// store byte
|
|
||||||
return proceedCycData(byte_recv); // TODO what if more than one byte was received?
|
|
||||||
}
|
|
||||||
|
|
||||||
return RESULT_SYN;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Bus::proceedCycData(const unsigned char byte)
|
|
||||||
{
|
|
||||||
if (byte != SYN) {
|
|
||||||
m_sstr.push_back(byte, true, false);
|
|
||||||
if (m_busLocked == true)
|
|
||||||
m_busLocked = false;
|
|
||||||
|
|
||||||
return RESULT_DATA;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (byte == SYN && m_sstr.size() != 0) {
|
|
||||||
// lock bus after SYN-BYTE-SYN Sequence
|
|
||||||
if (m_sstr.size() == 1 && m_busPriorRetry == false)
|
|
||||||
m_busLocked = true;
|
|
||||||
|
|
||||||
m_cycBuffer.push(m_sstr);
|
|
||||||
m_sstr.clear();
|
|
||||||
|
|
||||||
if (m_busLocked == true)
|
|
||||||
return RESULT_BUS_LOCKED;
|
|
||||||
}
|
|
||||||
|
|
||||||
return RESULT_SYN;
|
|
||||||
}
|
|
||||||
|
|
||||||
SymbolString Bus::getCycData()
|
|
||||||
{
|
|
||||||
SymbolString data;
|
|
||||||
|
|
||||||
if (m_cycBuffer.empty() == false) {
|
|
||||||
data = m_cycBuffer.front();
|
|
||||||
m_cycBuffer.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Bus::getBus(const unsigned char byte_sent)
|
|
||||||
{
|
|
||||||
unsigned char byte_recv;
|
|
||||||
ssize_t bytes_sent, bytes_recv;
|
|
||||||
|
|
||||||
// send QQ
|
|
||||||
bytes_sent = m_port->send(&byte_sent, 1);
|
|
||||||
if (bytes_sent <= 0)
|
|
||||||
return RESULT_ERR_SEND;
|
|
||||||
|
|
||||||
// receive 1 byte - must be QQ
|
|
||||||
bytes_recv = m_port->recv(0, 1);
|
|
||||||
|
|
||||||
if (bytes_recv < 0)
|
|
||||||
return RESULT_ERR_DEVICE;
|
|
||||||
|
|
||||||
// fetch next byte
|
|
||||||
byte_recv = recvByte();
|
|
||||||
|
|
||||||
// compare sent and received byte
|
|
||||||
if (bytes_recv == 1 && byte_sent == byte_recv) {
|
|
||||||
m_busPriorRetry = false;
|
|
||||||
return RESULT_BUS_ACQUIRED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// store byte
|
|
||||||
int ret = proceedCycData(byte_recv);
|
|
||||||
if (ret >= 0)
|
|
||||||
return ret;
|
|
||||||
// TODO this needs to be re-designed with above proceedCycData()
|
|
||||||
// compare prior nibble for retry
|
|
||||||
if (bytes_recv == 1 && (byte_sent & 0x0F) == (byte_recv & 0x0F)) {
|
|
||||||
m_busPriorRetry = true;
|
|
||||||
return RESULT_BUS_PRIOR_RETRY;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_busLocked = true;
|
|
||||||
return RESULT_ERR_BUS_LOST;
|
|
||||||
}
|
|
||||||
|
|
||||||
BusCommand* Bus::sendCommand()
|
|
||||||
{
|
|
||||||
unsigned char byte_recv;
|
|
||||||
ssize_t bytes_recv;
|
|
||||||
std::string result;
|
|
||||||
SymbolString slaveData;
|
|
||||||
int retval = RESULT_OK;
|
|
||||||
|
|
||||||
BusCommand* busCommand = m_sendBuffer.front();
|
|
||||||
m_sendBuffer.pop();
|
|
||||||
|
|
||||||
// send ZZ PB SB NN Dx CRC
|
|
||||||
SymbolString command = busCommand->getCommand();
|
|
||||||
for (size_t i = 1; i < command.size(); i++) {
|
|
||||||
retval = sendByte(command[i]);
|
|
||||||
if (retval < 0)
|
|
||||||
goto on_exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// BC -> send SYN
|
|
||||||
if (busCommand->getType() == broadcast) {
|
|
||||||
sendByte(SYN);
|
|
||||||
goto on_exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// receive ACK
|
|
||||||
bytes_recv = m_port->recv(m_recvTimeout);
|
|
||||||
if (bytes_recv > 1) {
|
|
||||||
retval = RESULT_ERR_EXTRA_DATA;
|
|
||||||
goto on_exit;
|
|
||||||
} else if (bytes_recv < 0) {
|
|
||||||
retval = RESULT_ERR_TIMEOUT;
|
|
||||||
goto on_exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte_recv = recvByte();
|
|
||||||
|
|
||||||
// is received byte SYN?
|
|
||||||
if (byte_recv == SYN) {
|
|
||||||
retval = RESULT_ERR_SYN;
|
|
||||||
goto on_exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// is slave ACK negative?
|
|
||||||
if (byte_recv == NAK) {
|
|
||||||
|
|
||||||
// send QQ ZZ PB SB NN Dx CRC again
|
|
||||||
for (size_t i = 0; i < command.size(); i++) {
|
|
||||||
retval = sendByte(command[i]);
|
|
||||||
if (retval < 0)
|
|
||||||
goto on_exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// receive ACK
|
|
||||||
bytes_recv = m_port->recv(m_recvTimeout);
|
|
||||||
if (bytes_recv > 1) {
|
|
||||||
retval = RESULT_ERR_EXTRA_DATA;
|
|
||||||
goto on_exit;
|
|
||||||
} else if (bytes_recv < 0) {
|
|
||||||
retval = RESULT_ERR_TIMEOUT;
|
|
||||||
goto on_exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte_recv = recvByte();
|
|
||||||
|
|
||||||
// is received byte SYN?
|
|
||||||
if (byte_recv == SYN) {
|
|
||||||
retval = RESULT_ERR_SYN;
|
|
||||||
goto on_exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// is slave ACK negative?
|
|
||||||
if (byte_recv == NAK) {
|
|
||||||
retval = sendByte(SYN);
|
|
||||||
if (retval == 0)
|
|
||||||
retval = RESULT_ERR_NAK;
|
|
||||||
|
|
||||||
goto on_exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MM -> send SYN
|
|
||||||
if (busCommand->getType() == masterMaster) {
|
|
||||||
sendByte(SYN);
|
|
||||||
goto on_exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// receive NN, Dx, CRC
|
|
||||||
retval = recvSlaveDataAndCRC(slaveData);
|
|
||||||
|
|
||||||
// are calculated and received CRC equal?
|
|
||||||
if (retval == RESULT_ERR_CRC) {
|
|
||||||
|
|
||||||
// send NAK
|
|
||||||
retval = sendByte(NAK);
|
|
||||||
if (retval < 0)
|
|
||||||
goto on_exit;
|
|
||||||
|
|
||||||
// receive NN, Dx, CRC
|
|
||||||
slaveData.clear();
|
|
||||||
retval = recvSlaveDataAndCRC(slaveData);
|
|
||||||
|
|
||||||
// are calculated and received CRC equal?
|
|
||||||
if (retval == RESULT_ERR_CRC) {
|
|
||||||
|
|
||||||
// send NAK
|
|
||||||
retval = sendByte(NAK);
|
|
||||||
if (retval >= 0)
|
|
||||||
retval = RESULT_ERR_CRC;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (retval < 0)
|
|
||||||
goto on_exit;
|
|
||||||
|
|
||||||
// send ACK
|
|
||||||
retval = sendByte(ACK);
|
|
||||||
if (retval == -1) {
|
|
||||||
retval = RESULT_ERR_ACK;
|
|
||||||
goto on_exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// MS -> send SYN
|
|
||||||
sendByte(SYN);
|
|
||||||
|
|
||||||
on_exit:
|
|
||||||
|
|
||||||
// empty receive buffer
|
|
||||||
while (m_port->size() != 0)
|
|
||||||
byte_recv = recvByte();
|
|
||||||
|
|
||||||
busCommand->setResult(slaveData, retval);
|
|
||||||
return busCommand;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
BusCommand* Bus::delCommand()
|
|
||||||
{
|
|
||||||
BusCommand* busCommand = m_sendBuffer.front();
|
|
||||||
m_sendBuffer.pop();
|
|
||||||
|
|
||||||
busCommand->setResult(SymbolString(), RESULT_ERR_BUS_LOST);
|
|
||||||
return busCommand;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Bus::sendByte(const unsigned char byte_sent)
|
|
||||||
{
|
|
||||||
unsigned char byte_recv;
|
|
||||||
ssize_t bytes_sent, bytes_recv;
|
|
||||||
|
|
||||||
bytes_sent = m_port->send(&byte_sent, 1);
|
|
||||||
|
|
||||||
// receive 1 byte - must be equal
|
|
||||||
bytes_recv = m_port->recv(RECV_TIMEOUT);
|
|
||||||
if (bytes_sent != bytes_recv)
|
|
||||||
return RESULT_ERR_EXTRA_DATA;
|
|
||||||
|
|
||||||
byte_recv = recvByte();
|
|
||||||
|
|
||||||
if (byte_sent != byte_recv)
|
|
||||||
return RESULT_ERR_SEND;
|
|
||||||
|
|
||||||
return RESULT_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned char Bus::recvByte()
|
|
||||||
{
|
|
||||||
unsigned char byte_recv;
|
|
||||||
|
|
||||||
// fetch byte
|
|
||||||
byte_recv = m_port->byte();
|
|
||||||
|
|
||||||
if (m_dumpState == true)
|
|
||||||
m_dump->write((const char*) &byte_recv);
|
|
||||||
|
|
||||||
return byte_recv;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Bus::recvSlaveDataAndCRC(SymbolString& result)
|
|
||||||
{
|
|
||||||
unsigned char byte_recv, crc_calc = 0;
|
|
||||||
ssize_t bytes_recv;
|
|
||||||
size_t NN = 0;
|
|
||||||
bool updateCrc = true;
|
|
||||||
int retval = 0;
|
|
||||||
|
|
||||||
for (size_t i = 0, needed = 1; i < needed; i++) {
|
|
||||||
bytes_recv = m_port->recv(RECV_TIMEOUT, 1);
|
|
||||||
if (bytes_recv < 0)
|
|
||||||
return RESULT_ERR_TIMEOUT;
|
|
||||||
|
|
||||||
byte_recv = recvByte();
|
|
||||||
retval = result.push_back(byte_recv, true, updateCrc);
|
|
||||||
if (retval < 0)
|
|
||||||
return retval;
|
|
||||||
|
|
||||||
if (retval == RESULT_IN_ESC)
|
|
||||||
needed++;
|
|
||||||
else if (result.size() == 1) { // NN received
|
|
||||||
NN = result[0];
|
|
||||||
needed += NN;
|
|
||||||
}
|
|
||||||
else if (NN > 0 && result.size() == 1+NN) {// all data received
|
|
||||||
updateCrc = false;
|
|
||||||
crc_calc = result.getCRC();
|
|
||||||
needed++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (retval == RESULT_IN_ESC)
|
|
||||||
return RESULT_ERR_ESC;
|
|
||||||
|
|
||||||
if (updateCrc || crc_calc != result[result.size()-1])
|
|
||||||
return RESULT_ERR_CRC;
|
|
||||||
|
|
||||||
return RESULT_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} //namespace
|
|
||||||
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) Roland Jax 2012-2014 <ebusd@liwest.at>
|
|
||||||
*
|
|
||||||
* This file is part of ebusd.
|
|
||||||
*
|
|
||||||
* ebusd is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* ebusd is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with ebusd. If not, see http://www.gnu.org/licenses/.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LIBEBUS_BUS_H_
|
|
||||||
#define LIBEBUS_BUS_H_
|
|
||||||
|
|
||||||
#include "symbol.h"
|
|
||||||
#include "result.h"
|
|
||||||
#include "port.h"
|
|
||||||
#include "dump.h"
|
|
||||||
#include "buscommand.h"
|
|
||||||
#include <cstring>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <sstream>
|
|
||||||
#include <queue>
|
|
||||||
|
|
||||||
namespace libebus
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
// the maximum time allowed for retrieving a byte from an addressed slave
|
|
||||||
#define RECV_TIMEOUT 10000
|
|
||||||
|
|
||||||
class Bus
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
Bus(const std::string deviceName, const bool noDeviceCheck, const long recvTimeout,
|
|
||||||
const std::string dumpFile, const long dumpSize, const bool dumpState);
|
|
||||||
~Bus();
|
|
||||||
|
|
||||||
void connect() { m_port->open(); }
|
|
||||||
void disconnect() { if (m_port->isOpen() == true) m_port->close(); }
|
|
||||||
bool isConnected() { return m_port->isOpen(); }
|
|
||||||
|
|
||||||
void printBytes() const;
|
|
||||||
|
|
||||||
int proceed();
|
|
||||||
SymbolString getCycData();
|
|
||||||
|
|
||||||
void addCommand(BusCommand* busCommand) { m_sendBuffer.push(busCommand); }
|
|
||||||
|
|
||||||
int getBus(const unsigned char byte);
|
|
||||||
BusCommand* sendCommand();
|
|
||||||
BusCommand* delCommand();
|
|
||||||
|
|
||||||
void setDumpState(const bool dumpState) { m_dumpState = dumpState; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
Port* m_port;
|
|
||||||
SymbolString m_sstr;
|
|
||||||
std::queue<SymbolString> m_cycBuffer;
|
|
||||||
std::queue<BusCommand*> m_sendBuffer;
|
|
||||||
|
|
||||||
const long m_recvTimeout;
|
|
||||||
|
|
||||||
Dump* m_dump;
|
|
||||||
bool m_dumpState;
|
|
||||||
|
|
||||||
bool m_busLocked;
|
|
||||||
bool m_busPriorRetry;
|
|
||||||
|
|
||||||
int proceedCycData(const unsigned char byte);
|
|
||||||
int sendByte(const unsigned char byte_sent);
|
|
||||||
unsigned char recvByte();
|
|
||||||
int recvSlaveDataAndCRC(SymbolString& result);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} //namespace
|
|
||||||
|
|
||||||
#endif // LIBEBUS_BUS_H_
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) Roland Jax 2012-2014 <ebusd@liwest.at>
|
|
||||||
*
|
|
||||||
* This file is part of ebusd.
|
|
||||||
*
|
|
||||||
* ebusd is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* ebusd is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with ebusd. If not, see http://www.gnu.org/licenses/.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LIBEBUS_CONFIGFILE_H_
|
|
||||||
#define LIBEBUS_CONFIGFILE_H_
|
|
||||||
|
|
||||||
#include "commands.h"
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace libebus
|
|
||||||
{
|
|
||||||
|
|
||||||
enum FileType { CSV, XML };
|
|
||||||
|
|
||||||
class ConfigFile
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
virtual ~ConfigFile() {}
|
|
||||||
|
|
||||||
virtual void readFile(std::istream& is, Commands& commands) = 0;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class ConfigFileCSV : public ConfigFile
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
~ConfigFileCSV() {}
|
|
||||||
|
|
||||||
void readFile(std::istream& is, Commands& commands);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class ConfigFileXML : public ConfigFile
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
~ConfigFileXML() {}
|
|
||||||
|
|
||||||
void readFile(std::istream& is, Commands& commands);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class ConfigCommands
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
ConfigCommands(const std::string path, const FileType type);
|
|
||||||
~ConfigCommands() { delete m_configfile; }
|
|
||||||
|
|
||||||
void setType(const FileType type);
|
|
||||||
Commands* getCommands();
|
|
||||||
|
|
||||||
private:
|
|
||||||
ConfigFile* m_configfile;
|
|
||||||
std::string m_path;
|
|
||||||
std::string m_extension;
|
|
||||||
std::vector<std::string> m_files;
|
|
||||||
|
|
||||||
void addFiles(const std::string path, const std::string extension);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} //namespace
|
|
||||||
|
|
||||||
#endif // LIBEBUS_CONFIGFILE_H_
|
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) Roland Jax 2012-2014 <ebusd@liwest.at>
|
|
||||||
*
|
|
||||||
* This file is part of ebusd.
|
|
||||||
*
|
|
||||||
* ebusd is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* ebusd is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with ebusd. If not, see http://www.gnu.org/licenses/.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef LIBEBUS_PORT_H_
|
|
||||||
#define LIBEBUS_PORT_H_
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <queue>
|
|
||||||
#include <termios.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
namespace libebus
|
|
||||||
{
|
|
||||||
|
|
||||||
enum DeviceType { SERIAL, NETWORK };
|
|
||||||
|
|
||||||
#define MAX_READ_SIZE 100
|
|
||||||
|
|
||||||
class Device
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
Device() : m_fd(-1), m_open(false), m_noDeviceCheck(false) {}
|
|
||||||
virtual ~Device() {}
|
|
||||||
|
|
||||||
virtual void openDevice(const std::string deviceName, const bool noDeviceCheck) = 0;
|
|
||||||
virtual void closeDevice() = 0;
|
|
||||||
bool isOpen();
|
|
||||||
|
|
||||||
ssize_t sendBytes(const unsigned char* buffer, size_t nbytes);
|
|
||||||
ssize_t recvBytes(const long timeout, size_t maxCount);
|
|
||||||
|
|
||||||
unsigned char getByte();
|
|
||||||
ssize_t sizeRecvBuffer() const { return m_recvBuffer.size(); }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
int m_fd;
|
|
||||||
bool m_open;
|
|
||||||
bool m_noDeviceCheck;
|
|
||||||
std::queue<unsigned char> m_recvBuffer;
|
|
||||||
unsigned char m_buffer[MAX_READ_SIZE];
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool isValid();
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class DeviceSerial : public Device
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
~DeviceSerial() { closeDevice(); }
|
|
||||||
|
|
||||||
void openDevice(const std::string deviceName, const bool noDeviceCheck);
|
|
||||||
void closeDevice();
|
|
||||||
|
|
||||||
private:
|
|
||||||
termios m_oldSettings;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
class DeviceNetwork : public Device
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
~DeviceNetwork() { closeDevice(); }
|
|
||||||
|
|
||||||
void openDevice(const std::string deviceName, const bool noDeviceCheck);
|
|
||||||
void closeDevice();
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class Port
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
Port(const std::string deviceName, const bool noDeviceCheck);
|
|
||||||
~Port() { delete m_device; }
|
|
||||||
|
|
||||||
void open() { m_device->openDevice(m_deviceName, m_noDeviceCheck); }
|
|
||||||
void close() { m_device->closeDevice(); }
|
|
||||||
bool isOpen() { return m_device->isOpen(); }
|
|
||||||
|
|
||||||
ssize_t send(const unsigned char* buffer, size_t nbytes)
|
|
||||||
{ return m_device->sendBytes(buffer, nbytes); }
|
|
||||||
ssize_t recv(const long timeout, size_t maxCount=MAX_READ_SIZE) { return m_device->recvBytes(timeout, maxCount); }
|
|
||||||
|
|
||||||
unsigned char byte() { return m_device->getByte(); }
|
|
||||||
ssize_t size() const { return m_device->sizeRecvBuffer(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string m_deviceName;
|
|
||||||
Device* m_device;
|
|
||||||
bool m_noDeviceCheck;
|
|
||||||
|
|
||||||
void setType(const DeviceType type);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} //namespace
|
|
||||||
|
|
||||||
#endif // LIBEBUS_PORT_H_
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
AM_CXXFLAGS = -fpic \
|
|
||||||
-Wall \
|
|
||||||
-Wextra \
|
|
||||||
-I$(top_srcdir)/src/libebus
|
|
||||||
|
|
||||||
noinst_PROGRAMS = test_port \
|
|
||||||
test_symbol \
|
|
||||||
test_data \
|
|
||||||
test_bus \
|
|
||||||
test_commands \
|
|
||||||
test_configfile \
|
|
||||||
test_decode \
|
|
||||||
test_encode
|
|
||||||
|
|
||||||
test_port_SOURCES = test_port.cpp
|
|
||||||
test_port_LDADD = $(top_srcdir)/src/libebus/libebus.a
|
|
||||||
|
|
||||||
test_symbol_SOURCES = test_symbol.cpp
|
|
||||||
test_symbol_LDADD = $(top_srcdir)/src/libebus/libebus.a
|
|
||||||
|
|
||||||
test_data_SOURCES = test_data.cpp
|
|
||||||
test_data_LDADD = $(top_srcdir)/src/libebus/libebus.a
|
|
||||||
|
|
||||||
test_bus_SOURCES = test_bus.cpp
|
|
||||||
test_bus_LDADD = $(top_srcdir)/src/libebus/libebus.a
|
|
||||||
|
|
||||||
test_commands_SOURCES = test_commands.cpp
|
|
||||||
test_commands_LDADD = $(top_srcdir)/src/libebus/libebus.a
|
|
||||||
|
|
||||||
test_configfile_SOURCES = test_configfile.cpp
|
|
||||||
test_configfile_LDADD = $(top_srcdir)/src/libebus/libebus.a
|
|
||||||
|
|
||||||
test_decode_SOURCES = test_decode.cpp
|
|
||||||
test_decode_LDADD = $(top_srcdir)/src/libebus/libebus.a
|
|
||||||
|
|
||||||
test_encode_SOURCES = test_encode.cpp
|
|
||||||
test_encode_LDADD = $(top_srcdir)/src/libebus/libebus.a
|
|
||||||
|
|
||||||
distclean-local:
|
|
||||||
-rm -f Makefile.in
|
|
||||||
-rm -rf .libs
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) Roland Jax 2012-2014 <ebusd@liwest.at>
|
|
||||||
*
|
|
||||||
* This file is part of ebusd.
|
|
||||||
*
|
|
||||||
* ebusd is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* ebusd is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with ebusd. If not, see http://www.gnu.org/licenses/.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "bus.h"
|
|
||||||
#include <iostream>
|
|
||||||
#include <iomanip>
|
|
||||||
|
|
||||||
using namespace libebus;
|
|
||||||
|
|
||||||
int main ()
|
|
||||||
{
|
|
||||||
Bus bus("/dev/ttyUSB0", true, 15000, "/tmp/dump_bus.bin", 100, false);
|
|
||||||
|
|
||||||
bus.connect();
|
|
||||||
|
|
||||||
if (bus.isConnected() == true)
|
|
||||||
std::cout << "connect successful." << std::endl;
|
|
||||||
|
|
||||||
int cout = 0;
|
|
||||||
|
|
||||||
while (cout++ < 1000) {
|
|
||||||
if (bus.isConnected() == true) {
|
|
||||||
bus.printBytes();
|
|
||||||
} else {
|
|
||||||
sleep(5);
|
|
||||||
bus.connect();
|
|
||||||
|
|
||||||
if (bus.isConnected() == false)
|
|
||||||
std::cout << "can't open /dev/ttyUSB0" << std::endl;
|
|
||||||
else
|
|
||||||
std::cout << "reconnect successful." << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bus.disconnect();
|
|
||||||
|
|
||||||
if (bus.isConnected() == false)
|
|
||||||
std::cout << "disconnect successful." << std::endl;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
AM_CXXFLAGS = -fpic \
|
|
||||||
-Wall \
|
|
||||||
-Wextra \
|
|
||||||
-I$(top_srcdir)/src/libcore \
|
|
||||||
-I$(top_srcdir)/src/libebus
|
|
||||||
|
|
||||||
bin_PROGRAMS = ebusctl
|
|
||||||
|
|
||||||
ebusctl_SOURCES = ebusctl.cpp
|
|
||||||
|
|
||||||
ebusctl_LDADD = $(top_srcdir)/src/libcore/libcore.a \
|
|
||||||
$(top_srcdir)/src/libebus/libebus.a
|
|
||||||
|
|
||||||
distclean-local:
|
|
||||||
-rm -f Makefile.in
|
|
||||||
-rm -rf .libs
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user