diff --git a/Makefile.am b/Makefile.am index 2bf1f2d5..ef6ef5c0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,4 +1,4 @@ -SUBDIRS = src/lib/ebus src/lib/ebus/test src/lib/utils src/ebusd src/ebusctl +SUBDIRS = src/lib/utils src/lib/ebus src/lib/ebus/test src/ebusd src/ebusctl distclean-local: -rm -rf autom4te.cache diff --git a/README b/README index fe5c6c19..dfc45852 100644 --- a/README +++ b/README @@ -13,6 +13,7 @@ Features * collect data of cycle messages * poll messages and collect received data * write raw data into dump files (for debugging purpose) + * scan ebus to identifies bus participants * available daemon commands: - get fetch data from ebus participant @@ -20,6 +21,10 @@ Features - cyc fetch data from collected cycle messages - hex send given hex value to ebus (ZZPBSBNNDx) + - scan scan kown slave addresses (collected) + - scan full scan all possible slave addresses + - scan result show scanning results + - log areas change log areas - log level change log level @@ -29,15 +34,27 @@ Features - reload reload ebus configuration - stop stop daemon - - quit close connection - help print help page -Dependency ----------- - * glibc +vendor specific configuration files for ebusd +--------------------------------------------- + +See https://github.com/yuhu-/ebus-configuration + + + +ebusctl - client program for ebusd +---------------------------------- + +server commands: + * connect to ebusd (socket) and execute server commands (commands see above) + +local commands: + * 'feed' ebusd with raw data from dump files (or telnet) to ebusd + Build @@ -48,32 +65,6 @@ $ make $ make install -Daemon Configuration --------------------- - -See ./ebusd -h - - -Vendor specific configuration files ------------------------------------ - -See https://github.com/yuhu-/ebus-configuration - - -Tools ------ - -ebusctl - client program for ebusd. - -local commands: - * 'feed' ebusd with raw data from dump files (or telnet) to ebusd - * 'scan' ebus and identifies the participants - -remote commands: - * connect to ebusd (socket) and execute server commands (see above) - -See ./ebusctl -h - For usage and further information take a look on help page. diff --git a/configure.ac b/configure.ac index 37d4ab21..589f43f5 100644 --- a/configure.ac +++ b/configure.ac @@ -3,13 +3,26 @@ AC_INIT([ebusd], [0.5.0], [ebusd@liwest.at], [ebusd], [https://github.com/yuhu-/ AC_PROG_CXX +AC_CHECK_HEADERS([arpa/inet.h \ + dirent.h \ + fcntl.h \ + netdb.h \ + poll.h \ + pthread.h \ + sys/ioctl.h \ + termios.h]) + +AC_CHECK_LIB([pthread], [pthread_setname_np], + AC_DEFINE([HAVE_PTHREAD_SETNAME_NP], [1], ["Define to 1 if pthread has pthread_setname_np"]), + AC_MSG_RESULT([Could not find pthread_setname_np in pthread])) + AC_CONFIG_AUX_DIR([build]) -AC_CONFIG_SRCDIR([src/ebusd/main.cpp]) +AC_CONFIG_SRCDIR([src/ebusd/ebusd.cpp]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_FILES([Makefile + src/lib/utils/Makefile src/lib/ebus/Makefile src/lib/ebus/test/Makefile - src/lib/utils/Makefile src/ebusd/Makefile src/ebusctl/Makefile]) diff --git a/src/ebusctl/ebusctl.cpp b/src/ebusctl/ebusctl.cpp index 5749f7b1..930e6ede 100644 --- a/src/ebusctl/ebusctl.cpp +++ b/src/ebusctl/ebusctl.cpp @@ -17,179 +17,63 @@ * along with ebusd. If not, see http://www.gnu.org/licenses/. */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "appl.h" #include "port.h" #include "decode.h" -#include "appl.h" #include "tcpsocket.h" #include -#include #include #include -#include -#include #include -using namespace libebus; - -Appl& A = Appl::Instance(); +Appl& A = Appl::Instance(true); void define_args() { - A.addArgs("COMMAND {ARGS...}\n\n" - " local commands:\n" - " 'scan' scans the bus and identifies the participants\n\n" - " 'feed' sends a dump file to a local virtual serial device\n" - " (hint: socat -d -d pty,raw,echo=0 pty,raw,echo=0)\n\n" - " remote commands:\n" - " send 'help' to server", 1); + A.setVersion("ebusctl is part of """PACKAGE_STRING""); - A.addItem("p_device", Appl::Param("/dev/ttyUSB60"), "d", "device", - "virtual serial device (/dev/ttyUSB60)", - Appl::type_string, Appl::opt_mandatory); + A.addText(" 'help' show server commands\n\n" + " 'feed' sends a dump file to a local serial device (pts)\n" + " (hint: socat -d -d pty,raw,echo=0 pty,raw,echo=0)\n\n" + "Options:\n"); - A.addItem("p_file", Appl::Param(""), "f", "file", - "dump file with raw data", - Appl::type_string, Appl::opt_mandatory); + A.addOption("device", "d", OptVal("/dev/ttyUSB60"), dt_string, ot_mandatory, + "virtual serial device (/dev/ttyUSB60)"); - A.addItem("p_time", Appl::Param(10000), "t", "time", - "delay between 2 bytes in 'us' (10000)\n", - Appl::type_long, Appl::opt_mandatory); + A.addOption("file", "f", OptVal("/tmp/ebus_dump.bin"),dt_string, ot_mandatory, + "dump file name (/tmp/ebus_dump.bin)"); - A.addItem("p_server", Appl::Param("localhost"), "s", "server", - "name or ip (localhost)", - Appl::type_string, Appl::opt_mandatory); + A.addOption("time", "t", OptVal(10000), dt_long, ot_mandatory, + "delay between 2 bytes in 'us' (10000)\n"); - A.addItem("p_port", Appl::Param(8888), "p", "port", - "port (8888)\n", - Appl::type_int, Appl::opt_mandatory); + A.addOption("server", "s", OptVal("localhost"), dt_string, ot_mandatory, + "name or ip (localhost)"); - A.addItem("p_help", Appl::Param(false), "h", "help", - "print this message", - Appl::type_bool, Appl::opt_none); + A.addOption("port", "p", OptVal(8888), dt_int, ot_mandatory, + "port (8888)\n"); } - -templateT * end(T (&ra)[N]) { return ra + N; } - -const char *sinit[] = {"02", "04", "05", "06", "08", "09", "0A", "0B", "0C", - "0E", "12", "14", "15", "16", "18", "19", "1A", "1B", - "1C", "1D", "1E", "20", "21", "22", "23", "24", "25", - "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", - "2F", "32", "34", "35", "36", "38", "39", "3A", "3B", - "3C", "3D", "3E", "40", "41", "42", "43", "44", "45", - "46", "47", "48", "49", "4A", "4B", "4C", "4D", "4E", - "4F", "50", "51", "52", "53", "54", "55", "56", "57", - "58", "59", "5A", "5B", "5C", "5D", "5E", "5F", "60", - "61", "62", "63", "64", "65", "66", "67", "68", "69", - "6A", "6B", "6C", "6D", "6E", "6F", "72", "74", "75", - "76", "78", "79", "7A", "7B", "7C", "7D", "7E", "80", - "81", "82", "83", "84", "85", "86", "87", "88", "89", - "8A", "8B", "8C", "8D", "8E", "8F", "90", "91", "92", - "93", "94", "95", "96", "97", "98", "99", "9A", "9B", - "9C", "9D", "9E", "9F", "A0", "A1", "A2", "A3", "A4", - "A5", "A6", "A7", "A8", "AB", "AC", "AD", "AE", "AF", - "B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", - "B9", "BA", "BB", "BC", "BD", "BE", "BF", "C0", "C1", - "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "CA", - "CB", "CC", "CD", "CE", "CF", "D0", "D1", "D2", "D3", - "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB", "DC", - "DD", "DE", "DF", "E0", "E1", "E2", "E3", "E4", "E5", - "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", - "EF", "F2", "F4", "F5", "F6", "F8", "F9", "FA", "FB", - "FC", "FD"}; - -static std::vector s(sinit, end(sinit)); - -static std::map manufacturer; - -static void addManufacturer() -{ - manufacturer.insert(std::make_pair("06", "Karl Dungs GmbH")); - manufacturer.insert(std::make_pair("0f", "FH Braunschweig/Wolfenbüttel")); - manufacturer.insert(std::make_pair("10", "TEM AG für Elektronik Intertem Vertriebs AG")); - manufacturer.insert(std::make_pair("11", "Lamberti Elektronik")); - manufacturer.insert(std::make_pair("14", "CEB Compagnie Européenne de Brûleurs S.A.")); - manufacturer.insert(std::make_pair("15", "Landis & Staefa")); - manufacturer.insert(std::make_pair("16", "FERRO Wärmetechnik GmbH & Co.KG")); - manufacturer.insert(std::make_pair("17", "MONDIAL electronic Ges.mbH")); - manufacturer.insert(std::make_pair("18", "Wikon Kommunikationstechnik GmbH")); - manufacturer.insert(std::make_pair("19", "Wolf GmbH")); - manufacturer.insert(std::make_pair("20", "RAWE Electronic GmbH")); - manufacturer.insert(std::make_pair("30", "Satronic AG")); - manufacturer.insert(std::make_pair("40", "ENCON Electronics")); - manufacturer.insert(std::make_pair("50", "G. Kromschröder AG")); - manufacturer.insert(std::make_pair("60", "Eberle Controls GmbH")); - manufacturer.insert(std::make_pair("65", "EBV Elektronikbau")); - manufacturer.insert(std::make_pair("75", "Grässlin GmbH & Co.KG")); - manufacturer.insert(std::make_pair("85", "Motoren und Ventilatoren Landshut GmbH")); - manufacturer.insert(std::make_pair("95", "SIG Berger Lahr GmbH & Co KG")); - manufacturer.insert(std::make_pair("c0", "Toby AG")); - manufacturer.insert(std::make_pair("c5", "Max Weishaupt GmbH")); - manufacturer.insert(std::make_pair("a5", "Theben Zeitschaltautomatik")); - manufacturer.insert(std::make_pair("a7", "Thermowatt s.p.a.")); - manufacturer.insert(std::make_pair("b5", "Joh. Vaillant GmbH & Co.")); -} - -void scanVaillant(TCPSocket* socket, const std::string address) -{ - Decode* help = NULL; - std::ostringstream sstr; - - for (int i = 24; i < 28; i++) { - // build message - std::string message("hex ms "); - message += address; - message += "b50901"; - - std::stringstream ss; - ss << i; - message += ss.str(); - - socket->send(message.c_str(), message.size()); - - char data[256]; - size_t datalen; - - datalen = socket->recv(data, sizeof(data)-1); - data[datalen] = '\0'; - - std::string item(data); - - help = new DecodeSTR(item.substr(18,18)); - sstr << help->decode(); - delete help; - } - - std::cout << " s/n: '" << sstr.str().substr(1,28) << "' item: '" << sstr.str().substr(7,10) << "'"; -} - - int main(int argc, char* argv[]) { - // define Arguments and Application variables + // define arguments and application variables define_args(); - // parse Arguments - if (A.parseArgs(argc, argv) == false) { - A.printArgs(); - exit(EXIT_FAILURE); - } - - // print Help - if (A.getParam("p_help") == true) { - A.printArgs(); - exit(EXIT_SUCCESS); - } + // parse arguments + A.parseArgs(argc, argv); if (strcasecmp(A.getArg(0).c_str(), "feed") == 0) { - std::string dev(A.getParam("p_device")); + std::string dev(A.getOptVal("device")); Port port(dev, true); port.open(); if(port.isOpen() == true) { std::cout << "openPort successful." << std::endl; - std::fstream file(A.getParam("p_file"), std::ios::in | std::ios::binary); + std::fstream file(A.getOptVal("file"), std::ios::in | std::ios::binary); if(file.is_open() == true) { @@ -199,103 +83,52 @@ int main(int argc, char* argv[]) << static_cast(byte) << std::endl; port.send(&byte, 1); - usleep(A.getParam("p_time")); + usleep(A.getOptVal("time")); } file.close(); - } else { - std::cout << "error opening file " << A.getParam("p_file") << std::endl; } + else + std::cout << "error opening file " << A.getOptVal("file") << std::endl; port.close(); if(port.isOpen() == false) std::cout << "closePort successful." << std::endl; - } else { - std::cout << "error opening device " << A.getParam("p_device") << std::endl; - } - - } else { + } else + std::cout << "error opening device " << A.getOptVal("device") << std::endl; + } + else { TCPClient* client = new TCPClient(); - TCPSocket* socket = client->connect(A.getParam("p_server"), A.getParam("p_port")); + TCPSocket* socket = client->connect(A.getOptVal("server"), A.getOptVal("port")); if (socket != NULL) { - - if (strcasecmp(A.getArg(0).c_str(), "scan") == 0) { - addManufacturer(); - - // send command to all slaves - for (size_t i = 0; i < s.size(); i++) { - // build message - std::string message("hex ms "); - message += s[i]; - message += "070400"; - - socket->send(message.c_str(), message.size()); - - char data[1024]; - size_t datalen; - - datalen = socket->recv(data, sizeof(data)-1); - data[datalen] = '\0'; - - // decode answer - if (strncmp(&data[0], "-", 1) != 0) { - std::string item(data); - - std::ostringstream ident; - Decode* help = NULL; - - help = new DecodeSTR(item.substr(18,10)); - ident << help->decode(); - delete help; - - std::cout << s[i] << ": '" << manufacturer.find(item.substr(16,2))->second - << "' ident: '" << std::setw(5) << std::setfill(' ') << ident.str() - << "' sw: '" << item.substr(28,2) - << "." << item.substr(30,2) - << "' hw: '" << item.substr(32,2) - << "." << item.substr(34,2) - << "'"; - - if (item.substr(16,2) == "b5") - scanVaillant(socket, s[i]); - - std::cout << std::endl; - } - - sleep(2); - } - } else { - // build message - std::string message(A.getArg(0)); - for (size_t i = 1; i < A.numArg(); i++) { - message += " "; - message += A.getArg(i); - } - - socket->send(message.c_str(), message.size()); - - char data[1024]; - size_t datalen; - - datalen = socket->recv(data, sizeof(data)-1); - data[datalen] = '\0'; - - std::cout << data; + // build message + std::string message(A.getArg(0)); + for (int i = 1; i < A.numArgs(); i++) { + message += " "; + message += A.getArg(i); } + socket->send(message.c_str(), message.size()); + + char data[1024]; + size_t datalen; + + datalen = socket->recv(data, sizeof(data)-1); + data[datalen] = '\0'; + + std::cout << data; + delete socket; - } else { - std::cout << "error connecting to " << A.getParam("p_server") - << ":" << A.getParam("p_port") << std::endl; } + else + std::cout << "error connecting to " << A.getOptVal("server") + << ":" << A.getOptVal("port") << std::endl; delete client; - } return 0; - } diff --git a/src/ebusd/Makefile.am b/src/ebusd/Makefile.am index 742edf10..e05c74d1 100644 --- a/src/ebusd/Makefile.am +++ b/src/ebusd/Makefile.am @@ -6,16 +6,15 @@ AM_CXXFLAGS = -fpic \ bin_PROGRAMS = ebusd -ebusd_SOURCES = message.h \ - connection.cpp \ - connection.h \ +ebusd_SOURCES = dump.cpp \ + dump.h \ + busloop.cpp \ + busloop.h \ network.cpp \ network.h \ - ebusloop.cpp \ - ebusloop.h \ baseloop.cpp \ baseloop.h \ - main.cpp + ebusd.cpp ebusd_LDADD = $(top_srcdir)/src/lib/utils/libutils.a \ $(top_srcdir)/src/lib/ebus/libebus.a \ diff --git a/src/ebusd/baseloop.cpp b/src/ebusd/baseloop.cpp index c23607fd..8e1fffd9 100644 --- a/src/ebusd/baseloop.cpp +++ b/src/ebusd/baseloop.cpp @@ -22,42 +22,41 @@ #include "logger.h" #include "appl.h" -extern LogInstance& L; +extern Logger& L; extern Appl& A; BaseLoop::BaseLoop() { - // create Commands DB - m_commands = ConfigCommands(A.getParam("p_ebusconfdir"), CSV).getCommands(); - L.log(bas, trace, "ebus configuration dir: %s", A.getParam("p_ebusconfdir")); + // create commands DB + m_commands = ConfigCommands(A.getOptVal("ebusconfdir"), CSV).getCommands(); + L.log(bas, trace, "ebus configuration dir: %s", A.getOptVal("ebusconfdir")); L.log(bas, event, "commands DB: %d ", m_commands->sizeCmdDB()); L.log(bas, event, " cycle DB: %d ", m_commands->sizeCycDB()); - L.log(bas, event, " polling DB: %d ", m_commands->sizePolDB()); + L.log(bas, event, " polling DB: %d ", m_commands->sizePollDB()); - // create EBusLoop - m_ebusloop = new EBusLoop(m_commands); - m_ebusloop->start("ebusloop"); + // create busloop + m_busloop = new BusLoop(m_commands); + m_busloop->start("busloop"); - // create Network - m_network = new Network(A.getParam("p_localhost")); - m_network->addQueue(&m_queue); + // create network + m_network = new Network(A.getOptVal("localhost"), &m_netQueue); m_network->start("network"); } BaseLoop::~BaseLoop() { - // free Network + // free network if (m_network != NULL) delete m_network; - // free EBusLoop - if (m_ebusloop != NULL) { - m_ebusloop->stop(); - m_ebusloop->join(); - delete m_ebusloop; + // free busloop + if (m_busloop != NULL) { + m_busloop->stop(); + m_busloop->join(); + delete m_busloop; } - // free Commands DB + // free commands DB if (m_commands != NULL) delete m_commands; } @@ -68,7 +67,7 @@ void BaseLoop::start() std::string result; // recv new message from client - Message* message = m_queue.remove(); + NetMessage* message = m_netQueue.remove(); std::string data = message->getData(); data.erase(std::remove(data.begin(), data.end(), '\r'), data.end()); @@ -86,10 +85,8 @@ void BaseLoop::start() // send result to client result += '\n'; - Connection* connection = static_cast(message->getSource()); - connection->addResult(Message(result)); - - delete message; + message->setResult(result); + message->sendSignal(); // stop daemon if (strcasecmp(data.c_str(), "STOP") == 0) @@ -132,7 +129,7 @@ std::string BaseLoop::decodeMessage(const std::string& data) // polling data if (strcasecmp(m_commands->getCmdType(index).c_str(), "P") == 0) { // get polldata - polldata = m_commands->getPolData(index); + polldata = m_commands->getPollData(index); if (polldata != "") { // decode data Command* command = new Command(index, (*m_commands)[index], polldata); @@ -148,30 +145,30 @@ std::string BaseLoop::decodeMessage(const std::string& data) break; } - std::string ebusCommand(A.getParam("p_address")); - ebusCommand += m_commands->getEbusCommand(index); - std::transform(ebusCommand.begin(), ebusCommand.end(), ebusCommand.begin(), tolower); + std::string busCommand(A.getOptVal("address")); + busCommand += m_commands->getBusCommand(index); + std::transform(busCommand.begin(), busCommand.end(), busCommand.begin(), tolower); - BusCommand* busCommand = new BusCommand(ebusCommand, false); - L.log(bas, trace, " msg: %s", ebusCommand.c_str()); - // send busCommand - m_ebusloop->addBusCommand(busCommand); - busCommand->waitSignal(); + BusMessage* message = new BusMessage(busCommand, false, false); + L.log(bas, trace, " msg: %s", busCommand.c_str()); + // send message + m_busloop->addMessage(message); + message->waitSignal(); - if (!busCommand->isErrorResult()) { + if (!message->isErrorResult()) { // decode data - Command* command = new Command(index, (*m_commands)[index], busCommand->getMessageStr()); // TODO use getCommand()+getResult() + Command* command = new Command(index, (*m_commands)[index], message->getMessageStr()); // TODO use getCommand()+getResult() // return result result << command->calcResult(cmd); delete command; } else { - L.log(bas, error, " %s", busCommand->getResultCodeCStr()); - result << busCommand->getResultCodeCStr(); + L.log(bas, error, " %s", message->getResultCodeCStr()); + result << message->getResultCodeCStr(); } - delete busCommand; + delete message; } else { result << "ebus command not found"; @@ -189,43 +186,43 @@ std::string BaseLoop::decodeMessage(const std::string& data) if (index >= 0) { - std::string ebusCommand(A.getParam("p_address")); - ebusCommand += m_commands->getEbusCommand(index); + std::string busCommand(A.getOptVal("address")); + busCommand += m_commands->getBusCommand(index); // encode data Command* command = new Command(index, (*m_commands)[index], cmd[3]); std::string value = command->calcData(); if (value[0] != '-') { - ebusCommand += value; + busCommand += value; } else { L.log(bas, error, " %s", value.c_str()); delete command; break; } - std::transform(ebusCommand.begin(), ebusCommand.end(), ebusCommand.begin(), tolower); + std::transform(busCommand.begin(), busCommand.end(), busCommand.begin(), tolower); - BusCommand* busCommand = new BusCommand(ebusCommand, false); - L.log(bas, event, " msg: %s", ebusCommand.c_str()); - // send busCommand - m_ebusloop->addBusCommand(busCommand); - busCommand->waitSignal(); + BusMessage* message = new BusMessage(busCommand, false, false); + L.log(bas, event, " msg: %s", busCommand.c_str()); + // send message + m_busloop->addMessage(message); + message->waitSignal(); - if (!busCommand->isErrorResult()) { + if (!message->isErrorResult()) { // decode result - if (busCommand->getType()==broadcast) + if (message->getType()==broadcast) result << "done"; - else if (busCommand->getMessageStr().substr(busCommand->getMessageStr().length()-8) == "00000000") // TODO use getResult() + else if (message->getMessageStr().substr(message->getMessageStr().length()-8) == "00000000") // TODO use getResult() result << "done"; else result << "error"; } else { - L.log(bas, error, " %s", busCommand->getResultCodeCStr()); - result << busCommand->getResultCodeCStr(); + L.log(bas, error, " %s", message->getResultCodeCStr()); + result << message->getResultCodeCStr(); } - delete busCommand; + delete message; delete command; } else { @@ -269,37 +266,63 @@ std::string BaseLoop::decodeMessage(const std::string& data) } { - std::string ebusCommand(A.getParam("p_address")); + std::string busCommand(A.getOptVal("address")); cmd[1].erase(std::remove_if(cmd[1].begin(), cmd[1].end(), isspace), cmd[1].end()); - ebusCommand += cmd[1]; - std::transform(ebusCommand.begin(), ebusCommand.end(), ebusCommand.begin(), tolower); + busCommand += cmd[1]; + std::transform(busCommand.begin(), busCommand.end(), busCommand.begin(), tolower); - BusCommand* busCommand = new BusCommand(ebusCommand, false); - L.log(bas, trace, " msg: %s", ebusCommand.c_str()); - // send busCommand - m_ebusloop->addBusCommand(busCommand); - busCommand->waitSignal(); + BusMessage* message = new BusMessage(busCommand, false, false); + L.log(bas, trace, " msg: %s", busCommand.c_str()); + // send message + m_busloop->addMessage(message); + message->waitSignal(); - if (busCommand->isErrorResult()) { - L.log(bas, error, " %s", busCommand->getResultCodeCStr()); - result << busCommand->getResultCodeCStr(); + if (message->isErrorResult()) { + L.log(bas, error, " %s", message->getResultCodeCStr()); + result << message->getResultCodeCStr(); } else { - result << busCommand->getMessageStr(); // TODO use getCommand()+getResult() + result << message->getMessageStr(); // TODO use getCommand()+getResult() } - delete busCommand; + delete message; } break; + case scan: + if (cmd.size() == 1) { + m_busloop->scan(); + result << "done"; + break; + } + + if (strcasecmp(cmd[1].c_str(), "FULL") == 0) { + m_busloop->scan(true); + result << "done"; + break; + } + + if (strcasecmp(cmd[1].c_str(), "RESULT") == 0) { + // TODO format scan results + for (size_t i = 0; i < m_commands->sizeScanDB(); i++) + result << m_commands->getScanData(i) << std::endl; + + break; + } + + result << "usage: 'scan'" << std::endl + << " 'scan full'" << std::endl + << " 'scan result'"; + break; + case log: - if (cmd.size () != 3 ) { + if (cmd.size() != 3 ) { result << "usage: 'log areas area,area,..' (areas: bas|net|bus|cyc|all)" << std::endl << " 'log level level' (level: error|event|trace|debug)"; break; } - // ToDo: check for possible areas and level + // TODO: check for possible areas and level if (strcasecmp(cmd[1].c_str(), "AREAS") == 0) { L.getSink(0)->setAreas(calcAreas(cmd[2])); result << "done"; @@ -323,7 +346,7 @@ std::string BaseLoop::decodeMessage(const std::string& data) break; } - m_ebusloop->raw(); + m_busloop->raw(); result << "done"; break; @@ -333,7 +356,7 @@ std::string BaseLoop::decodeMessage(const std::string& data) break; } - m_ebusloop->dump(); + m_busloop->dump(); result << "done"; break; @@ -344,16 +367,16 @@ std::string BaseLoop::decodeMessage(const std::string& data) } { - // create Commands DB - Commands* commands = ConfigCommands(A.getParam("p_ebusconfdir"), CSV).getCommands(); - L.log(bas, trace, "ebus configuration dir: %s", A.getParam("p_ebusconfdir")); + // create commands DB + Commands* commands = ConfigCommands(A.getOptVal("ebusconfdir"), CSV).getCommands(); + L.log(bas, trace, "ebus configuration dir: %s", A.getOptVal("ebusconfdir")); L.log(bas, event, "commands DB: %d ", m_commands->sizeCmdDB()); L.log(bas, event, " cycle DB: %d ", m_commands->sizeCycDB()); - L.log(bas, event, " polling DB: %d ", m_commands->sizePolDB()); + L.log(bas, event, " polling DB: %d ", m_commands->sizePollDB()); delete m_commands; m_commands = commands; - m_ebusloop->newCommands(m_commands); + m_busloop->reload(m_commands); result << "done"; break; @@ -361,18 +384,21 @@ std::string BaseLoop::decodeMessage(const std::string& data) case help: result << "commands:" << std::endl - << " get - fetch ebus data 'get class cmd (sub)'" << std::endl - << " set - set ebus values 'set class cmd value'" << 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 - << " 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 - << " raw - toggle log raw data" << std::endl - << " dump - toggle dump state" << std::endl << std::endl - << " reload - reload ebus configuration" << std::endl << std::endl - << " stop - stop daemon" << std::endl - << " quit - close connection" << std::endl << std::endl - << " help - print this page"; + << " get - fetch ebus data 'get class cmd (sub)'" << std::endl + << " set - set ebus values 'set class cmd value'" << 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 + << " scan - scan ebus kown addresses 'scan'" << std::endl + << " - scan ebus all addresses 'scan full'" << std::endl + << " - show results 'scan result'" << std::endl << 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 + << " raw - toggle log raw data 'raw'" << std::endl + << " dump - toggle dump state 'dump'" << std::endl << std::endl + << " reload - reload ebus configuration 'reload'" << std::endl << std::endl + << " stop - stop daemon 'stop'" << std::endl + << " quit - close connection 'quit'" << std::endl << std::endl + << " help - print this page 'help'"; break; default: diff --git a/src/ebusd/baseloop.h b/src/ebusd/baseloop.h index 9e68555c..bd0f8df6 100644 --- a/src/ebusd/baseloop.h +++ b/src/ebusd/baseloop.h @@ -22,10 +22,7 @@ #include "commands.h" #include "network.h" -#include "ebusloop.h" - -using namespace libebus; - +#include "busloop.h" class BaseLoop { @@ -36,20 +33,21 @@ public: void start(); - void addMessage(Message* message) { m_queue.add(message); } + void addMessage(NetMessage* message) { m_netQueue.add(message); } private: Commands* m_commands; - EBusLoop* m_ebusloop; + BusLoop* m_busloop; Network* m_network; - WQueue m_queue; + WQueue m_netQueue; enum ClientCommand { get, // get ebus data set, // set ebus value cyc, // fetch cycle data hex, // send hex value + scan, // scan ebus log, // logger settings raw, // toggle log raw data dump, // toggle dump state @@ -64,6 +62,7 @@ private: if (strcasecmp(item.c_str(), "SET") == 0) return set; if (strcasecmp(item.c_str(), "CYC") == 0) return cyc; if (strcasecmp(item.c_str(), "HEX") == 0) return hex; + if (strcasecmp(item.c_str(), "SCAN") == 0) return scan; 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; diff --git a/src/ebusd/ebusloop.cpp b/src/ebusd/busloop.cpp similarity index 57% rename from src/ebusd/ebusloop.cpp rename to src/ebusd/busloop.cpp index 6a2f04ab..e7870858 100644 --- a/src/ebusd/ebusloop.cpp +++ b/src/ebusd/busloop.cpp @@ -17,37 +17,84 @@ * along with ebusd. If not, see http://www.gnu.org/licenses/. */ -#include "ebusloop.h" +#include "busloop.h" #include "logger.h" #include "appl.h" +#include -extern LogInstance& L; +extern Logger& L; extern Appl& A; -EBusLoop::EBusLoop(Commands* commands) - : m_commands(commands), m_stop(false), m_lockCounter(0), m_priorRetry(false) +BusMessage::BusMessage(const std::string command, const bool poll, const bool scan) + : m_poll(poll), m_scan(scan), m_command(command), m_result(), m_resultCode(RESULT_OK) { - m_port = new Port(A.getParam("p_device"), A.getParam("p_nodevicecheck")); + unsigned char dstAddress = m_command[1]; + + if (dstAddress == BROADCAST) + m_type = broadcast; + else if (isMaster(dstAddress) == true) + m_type = masterMaster; + else + m_type = masterSlave; + + pthread_mutex_init(&m_mutex, NULL); + pthread_cond_init(&m_cond, NULL); +} + +BusMessage::~BusMessage() +{ + pthread_mutex_destroy(&m_mutex); + pthread_cond_destroy(&m_cond); +} + +const std::string BusMessage::getMessageStr() +{ + std::string result; + + if (m_resultCode >= 0) { + if (m_type == masterSlave) { + result = m_command.getDataStr(); + result += "00"; + result += m_result.getDataStr(); + result += "00"; + } + else + result = "success"; + } + else + result = "error: "+std::string(getResultCodeCStr()); + + return result; +} + + +BusLoop::BusLoop(Commands* commands) + : m_commands(commands), m_stop(false), m_lockCounter(0), + m_priorRetry(false), m_scan(false), m_scanFull(false), m_scanIndex(0) +{ + m_port = new Port(A.getOptVal("device"), A.getOptVal("nodevicecheck")); m_port->open(); if (m_port->isOpen() == false) - L.log(bus, error, "can't open %s", A.getParam("p_device")); + L.log(bus, error, "can't open %s", A.getOptVal("device")); - m_dump = new Dump(A.getParam("p_dumpfile"), A.getParam("p_dumpsize")); - m_dumpState = A.getParam("p_dump"); + m_dump = new Dump(A.getOptVal("dumpfile"), A.getOptVal("dumpsize")); + m_dumpState = A.getOptVal("dump"); - m_logRawData = A.getParam("p_lograwdata"); + m_logRawData = A.getOptVal("lograwdata"); - m_pollInterval = A.getParam("p_pollinterval"); + m_pollInterval = A.getOptVal("pollinterval"); - m_recvTimeout = A.getParam("p_recvtimeout"); + m_recvTimeout = A.getOptVal("recvtimeout"); - m_sendRetries = A.getParam("p_sendretries"); + m_sendRetries = A.getOptVal("sendretries"); - m_lockRetries = A.getParam("p_lockretries"); + m_lockRetries = A.getOptVal("lockretries"); + + m_acquireTime = A.getOptVal("acquiretime"); } -EBusLoop::~EBusLoop() +BusLoop::~BusLoop() { if (m_port->isOpen() == true) m_port->close(); @@ -56,7 +103,7 @@ EBusLoop::~EBusLoop() delete m_dump; } -void* EBusLoop::run() +void* BusLoop::run() { int sendRetries = 0; int lockRetries = 0; @@ -70,15 +117,19 @@ void* EBusLoop::run() if (m_port->isOpen() == true) { ssize_t numBytes; - // add poll command - if (m_commands->sizePolDB() > 0) { + // add poll or scan command + if (m_commands->sizePollDB() > 0 || m_scan == true) { // check polling delta time(&pollEnd); pollDelta = difftime(pollEnd, pollStart); // add new polling command to send if (pollDelta >= m_pollInterval) { - addPollCommand(); + if (m_scan == true) + addScanMessage(); + else + addPollMessage(); + time(&pollStart); } } @@ -95,64 +146,67 @@ void* EBusLoop::run() collectCycData(numBytes); // send command - if (m_sstr.size() == 0 && m_lockCounter == 0 && m_sendBuffer.size() > 0) { + if (m_sstr.size() == 0 && m_lockCounter == 0 && m_busQueue.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()); + BusMessage* message = sendCommand(); + L.log(bus, trace, " %s", message->getMessageStr().c_str()); - if (busCommand->isErrorResult() == true) { + if (message->isErrorResult() == true) { if (sendRetries < m_sendRetries) { sendRetries++; L.log(bus, trace, " send retry %d", sendRetries); - busCommand->setResult(std::string(), RESULT_OK); + message->setResult(std::string(), RESULT_OK); } else { + sendRetries = 0; L.log(bus, event, " send retry failed", sendRetries); - if (busCommand->isPoll() == true) - delete m_sendBuffer.remove(); + if (message->isPoll() == true) + delete m_busQueue.remove(); else - busCommand->sendSignal(); - - sendRetries = 0; + message->sendSignal(); } } else { sendRetries = 0; - if (busCommand->isPoll() == true) { - m_commands->storePolData(busCommand->getMessageStr().c_str()); // TODO use getResult() - delete busCommand; + + if (message->isPoll() == true) { + if (message->isScan() == true) + m_commands->storeScanData(message->getMessageStr().c_str()); + else + m_commands->storePollData(message->getMessageStr().c_str()); // TODO use getResult() + delete message; } else - busCommand->sendSignal(); + message->sendSignal(); } lockRetries = 0; - m_lockCounter = A.getParam("p_lockcounter"); + m_lockCounter = A.getOptVal("lockcounter"); } else if (busResult == RESULT_ERR_BUS_LOST) { L.log(bus, trace, " acquire bus failed"); if (lockRetries >= m_lockRetries) { - L.log(bus, event, " lock bus failed"); - BusCommand* busCommand = m_sendBuffer.remove(); - if (busCommand->isPoll() == true) - delete busCommand; - else - busCommand->sendSignal(); - lockRetries = 0; + L.log(bus, event, " lock bus failed"); + + BusMessage* message = m_busQueue.remove(); + if (message->isPoll() == true) + delete message; + else + message->sendSignal(); } else { lockRetries++; L.log(bus, trace, " lock retry %d", lockRetries); } - m_lockCounter = A.getParam("p_lockcounter"); + m_lockCounter = A.getOptVal("lockcounter"); } } @@ -164,7 +218,7 @@ void* EBusLoop::run() m_port->open(); if (m_port->isOpen() == false) - L.log(bus, error, "can't open %s", A.getParam("p_device")); + L.log(bus, error, "can't open %s", A.getOptVal("device")); } @@ -180,7 +234,7 @@ void* EBusLoop::run() return NULL; } -unsigned char EBusLoop::fetchByte() +unsigned char BusLoop::fetchByte() { unsigned char byte; @@ -196,7 +250,7 @@ unsigned char EBusLoop::fetchByte() return byte; } -void EBusLoop::collectCycData(const int numRecv) +void BusLoop::collectCycData(const int numRecv) { // cycle bytes for (int i = 0; i < numRecv; i++) { @@ -231,33 +285,43 @@ void EBusLoop::collectCycData(const int numRecv) } } -void EBusLoop::analyseCycData() +void BusLoop::analyseCycData() { - L.log(bus, trace, "%s", m_sstr.getDataStr().c_str()); + static bool skipfirst = false; - int index = m_commands->storeCycData(m_sstr.getDataStr()); + if (skipfirst == true) { + L.log(bus, trace, "%s", m_sstr.getDataStr().c_str()); - 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()); + 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()); + } + + // collect Slave address + if (index != -3) + collectSlave(); } + else + skipfirst = true; } -void EBusLoop::addPollCommand() +void BusLoop::addPollMessage() { - int index = m_commands->nextPolCommand(); + int index = m_commands->nextPollCommand(); if (index < 0) { L.log(bus, error, "polling index out of range"); } @@ -269,23 +333,23 @@ void EBusLoop::addPollCommand() tmp += (*m_commands)[index][2]; L.log(bus, event, " polling [%4d] %s", index, tmp.c_str()); - std::string ebusCommand(A.getParam("p_address")); - ebusCommand += m_commands->getEbusCommand(index); - std::transform(ebusCommand.begin(), ebusCommand.end(), ebusCommand.begin(), tolower); + std::string busCommand(A.getOptVal("address")); + busCommand += m_commands->getBusCommand(index); + std::transform(busCommand.begin(), busCommand.end(), busCommand.begin(), tolower); - BusCommand* busCommand = new BusCommand(ebusCommand, true); - L.log(bus, trace, " msg: %s", ebusCommand.c_str()); + BusMessage* message = new BusMessage(busCommand, true, false); + L.log(bus, trace, " msg: %s", busCommand.c_str()); - addBusCommand(busCommand); + addMessage(message); } } -int EBusLoop::acquireBus() +int BusLoop::acquireBus() { unsigned char recvByte, sendByte; ssize_t numRecv, numSend; - sendByte = m_sendBuffer.next()->getCommand()[0]; + sendByte = m_busQueue.next()->getCommand()[0]; // send QQ numSend = m_port->send(&sendByte); @@ -294,6 +358,9 @@ int EBusLoop::acquireBus() return RESULT_ERR_SEND; } + // wait ~4200 usec for receive + usleep(m_acquireTime); + // receive 1 byte - must be QQ numRecv = m_port->recv(0); @@ -334,17 +401,17 @@ int EBusLoop::acquireBus() return RESULT_ERR_EXTRA_DATA; } -BusCommand* EBusLoop::sendCommand() +BusMessage* BusLoop::sendCommand() { unsigned char recvByte; std::string result; SymbolString slaveData; int retval = RESULT_OK; - BusCommand* busCommand = m_sendBuffer.next(); + BusMessage* message = m_busQueue.next(); // send ZZ PB SB NN Dx CRC - SymbolString command = busCommand->getCommand(); + SymbolString command = message->getCommand(); for (size_t i = 1; i < command.size(); i++) { retval = sendByte(command[i]); if (retval < 0) @@ -352,7 +419,7 @@ BusCommand* EBusLoop::sendCommand() } // BC -> send SYN - if (busCommand->getType() == broadcast) { + if (message->getType() == broadcast) { sendByte(SYN); goto on_exit; } @@ -387,7 +454,7 @@ BusCommand* EBusLoop::sendCommand() } // MM -> send SYN - if (busCommand->getType() == masterMaster) { + if (message->getType() == masterMaster) { sendByte(SYN); goto on_exit; } @@ -437,16 +504,16 @@ on_exit: while (m_port->size() != 0) recvByte = fetchByte(); - busCommand->setResult(slaveData, retval); + message->setResult(slaveData, retval); if (retval == RESULT_OK) - return m_sendBuffer.remove(); + return m_busQueue.remove(); else - return busCommand; + return message; } -int EBusLoop::sendByte(const unsigned char sendByte) +int BusLoop::sendByte(const unsigned char sendByte) { unsigned char recvByte; ssize_t numRecv, numSend; @@ -471,7 +538,7 @@ int EBusLoop::sendByte(const unsigned char sendByte) return RESULT_OK; } -int EBusLoop::recvSlaveAck(unsigned char& recvByte) +int BusLoop::recvSlaveAck(unsigned char& recvByte) { ssize_t numRecv; @@ -498,7 +565,7 @@ int EBusLoop::recvSlaveAck(unsigned char& recvByte) return RESULT_OK; } -int EBusLoop::recvSlaveData(SymbolString& result) +int BusLoop::recvSlaveData(SymbolString& result) { unsigned char recvByte, calcCrc = 0; ssize_t numRecv; @@ -544,3 +611,70 @@ int EBusLoop::recvSlaveData(SymbolString& result) return RESULT_OK; } +void BusLoop::collectSlave() +{ + std::vector::iterator it; + + for (int i = 0; i < 2; i++) { + bool found = false; + unsigned char mm = m_sstr[i]; + + if (i == 0) { + if (mm == 0xFF) + mm = 0x04; + else + mm += 0x05; + } + + for (it = m_slave.begin(); it != m_slave.end(); it++) + if ((*it) == mm) + found = true; + + if (found == false && isMaster(mm) == false && mm != BROADCAST) { + m_slave.push_back(mm); + L.log(bus, event, " new slave: %d %02x", m_slave.size(), m_slave.back()); + } + } +} + +void BusLoop::addScanMessage() +{ + std::string busCommand(A.getOptVal("address")); + std::stringstream sstr; + + if (m_scanFull == true) { + for (; m_scanIndex <= 0xFF; m_scanIndex++) { + if (isMaster(m_scanIndex) == false && m_scanIndex != SYN + && m_scanIndex != ESC && m_scanIndex != BROADCAST) { + sstr << std::nouppercase << std::setw(2) << std::setfill('0') + << std::hex << m_scanIndex; + break; + } + } + } + else { + sstr << std::nouppercase << std::setw(2) << std::setfill('0') + << std::hex << static_cast(m_slave[m_scanIndex]); + + if (m_scanIndex+1 >= m_slave.size()) + m_scan = false; + } + + if (m_scanIndex > 0xFF) + m_scan = false; + else { + m_scanIndex++; + + busCommand += sstr.str(); + busCommand += "070400"; + std::transform(busCommand.begin(), busCommand.end(), busCommand.begin(), tolower); + + L.log(bus, event, " scanning address %s", sstr.str().c_str()); + + + BusMessage* message = new BusMessage(busCommand, true, true); + L.log(bus, trace, " msg: %s", busCommand.c_str()); + + addMessage(message); + } +} diff --git a/src/ebusd/ebusloop.h b/src/ebusd/busloop.h similarity index 50% rename from src/ebusd/ebusloop.h rename to src/ebusd/busloop.h index 1605451e..be0f6e04 100644 --- a/src/ebusd/ebusloop.h +++ b/src/ebusd/busloop.h @@ -17,38 +17,77 @@ * along with ebusd. If not, see http://www.gnu.org/licenses/. */ -#ifndef EBUSLOOP_H_ -#define EBUSLOOP_H_ +#ifndef BUSLOOP_H_ +#define BUSLOOP_H_ #include "commands.h" #include "port.h" #include "dump.h" -#include "buscommand.h" #include "wqueue.h" #include "thread.h" +#include "symbol.h" +#include "result.h" /** the maximum time [us] allowed for retrieving a byte from an addressed slave */ #define RECV_TIMEOUT 10000 -using namespace libebus; +enum MessageType { invalid, broadcast, masterMaster, masterSlave }; - -class EBusLoop : public Thread +class BusMessage { public: - EBusLoop(Commands* commands); - ~EBusLoop(); + BusMessage(const std::string command, const bool poll, const bool scan); + ~BusMessage(); + + MessageType getType() const { return m_type; } + bool isPoll() const { return m_poll; } + bool isScan() const { return m_scan; } + + SymbolString getCommand() const { return m_command; } + SymbolString getResult() const { return m_result; } + + bool isErrorResult() const { return m_resultCode < 0; } + const char* getResultCodeCStr() const { return getResultCode(m_resultCode); } + void setResult(const SymbolString result, const int resultCode) + { m_result = result; m_resultCode = resultCode; } + + const std::string getMessageStr(); + + void waitSignal() { pthread_cond_wait(&m_cond, &m_mutex); } // TODO timeout + void sendSignal() { pthread_cond_signal(&m_cond); } + +private: + MessageType m_type; + bool m_poll; + bool m_scan; + SymbolString m_command; + SymbolString m_result; + int m_resultCode; + + pthread_mutex_t m_mutex; + pthread_cond_t m_cond; +}; + + +class BusLoop : public Thread +{ + +public: + BusLoop(Commands* commands); + ~BusLoop(); void* run(); void stop() { m_stop = true; } - void addBusCommand(BusCommand* busCommand) { m_sendBuffer.add(busCommand); } + void addMessage(BusMessage* message) { m_busQueue.add(message); } 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 reload(Commands* commands) { m_commands = commands; } + + void scan(const bool full=false) { m_scan = true; m_scanFull = full; m_scanIndex = 0; } private: Commands* m_commands; @@ -64,24 +103,33 @@ private: int m_lockCounter; bool m_priorRetry; - WQueue m_sendBuffer; + WQueue m_busQueue; SymbolString m_sstr; double m_pollInterval; long m_recvTimeout; int m_sendRetries; int m_lockRetries; + long m_acquireTime; + + std::vector m_slave; + + bool m_scan; + bool m_scanFull; + size_t m_scanIndex; unsigned char fetchByte(); void collectCycData(const int numRecv); void analyseCycData(); - void addPollCommand(); + void addPollMessage(); int acquireBus(); - BusCommand* sendCommand(); + BusMessage* sendCommand(); int sendByte(const unsigned char sendByte); int recvSlaveAck(unsigned char& recvByte); int recvSlaveData(SymbolString& result); + void collectSlave(); + void addScanMessage(); }; -#endif // EBUSLOOP_H_ +#endif // BUSLOOP_H_ diff --git a/src/ebusd/connection.cpp b/src/ebusd/connection.cpp deleted file mode 100644 index f48bfdd5..00000000 --- a/src/ebusd/connection.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) Roland Jax 2012-2014 - * - * 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 "connection.h" -#include "logger.h" -#include - -extern LogInstance& L; - -int Connection::m_count = -1; - -void Connection::addResult(Message message) -{ - Message* tmp = new Message(Message(message)); - m_result.add(tmp); -} - -void* Connection::run() -{ - m_running = true; - - int maxfd; - fd_set checkfds; - struct timeval timeout; - - FD_ZERO(&checkfds); - FD_SET(m_notify.notifyFD(), &checkfds); - FD_SET(m_socket->getFD(), &checkfds); - - (m_notify.notifyFD() > m_socket->getFD()) ? - (maxfd = m_notify.notifyFD()) : (maxfd = m_socket->getFD()); - - for (;;) { - fd_set readfds; - int ret; - - // set select timeout 10 secs - timeout.tv_sec = 10; - timeout.tv_usec = 0; - - // set readfds to inital checkfds - readfds = checkfds; - - ret = select(maxfd + 1, &readfds, NULL, NULL, &timeout); - if (ret == 0) { - continue; - } - - // new data from notify - if (FD_ISSET(m_notify.notifyFD(), &readfds)) - break; - - // new data from socket - if (FD_ISSET(m_socket->getFD(), &readfds)) { - char data[256]; - size_t datalen; - - if (m_socket->isValid() == true) - datalen = m_socket->recv(data, sizeof(data)-1); - else - break; - - // removed closed socket - if (datalen <= 0 || strncasecmp(data, "quit", 4) == 0) - break; - - // send data - data[datalen] = '\0'; - m_data->add(new Message(data, this)); - - // wait for result - L.log(net, debug, "[%08x] wait for result", getID()); - Message* message = m_result.remove(); - - L.log(net, debug, "[%08x] result added", getID()); - std::string result(message->getData()); - - if (m_socket->isValid() == true) - m_socket->send(result.c_str(), result.size()); - else - break; - - delete message; - - } - - } - - delete m_socket; - m_running = false; - L.log(net, trace, "[%08x] connection closed", getID()); - - return NULL; -} - diff --git a/src/ebusd/connection.h b/src/ebusd/connection.h deleted file mode 100644 index 49c0d690..00000000 --- a/src/ebusd/connection.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) Roland Jax 2012-2014 - * - * 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 CONNECTION_H_ -#define CONNECTION_H_ - -#include "tcpsocket.h" -#include "wqueue.h" -#include "notify.h" -#include "thread.h" -#include "message.h" - -class Connection : public Thread -{ - -public: - Connection(TCPSocket* socket, WQueue* data) - : m_socket(socket), m_data(data), m_running(false) { m_count++; } - - ~Connection() { m_count--; } - - void addResult(Message message); - - void* run(); - void stop() const { m_notify.notify(); } - bool isRunning() const { return m_running; } - - pthread_t getID() { return this->self(); } - int numConnections() const { return m_count; } - -private: - TCPSocket* m_socket; - WQueue* m_data; - WQueue m_result; - Notify m_notify; - bool m_running; - - static int m_count; - -}; - -#endif // CONNECTION_H_ diff --git a/src/lib/ebus/dump.cpp b/src/ebusd/dump.cpp similarity index 79% rename from src/lib/ebus/dump.cpp rename to src/ebusd/dump.cpp index 44104f0e..5219c709 100644 --- a/src/lib/ebus/dump.cpp +++ b/src/ebusd/dump.cpp @@ -21,25 +21,22 @@ #include #include -namespace libebus -{ - int Dump::write(const char* byte) { int ret = 0; - std::ofstream fs(m_filename.c_str(), std::ios::out | std::ios::binary | std::ios::app); + std::ofstream fs(m_name.c_str(), std::ios::out | std::ios::binary | std::ios::app); if (fs == 0) return -1; fs.write(byte, 1); - if (fs.tellp() >= m_filesize * 1024) { + if (fs.tellp() >= m_size * 1024) { std::string oldfile; - oldfile += m_filename; + oldfile += m_name; oldfile += ".old"; - ret = rename(m_filename.c_str(), oldfile.c_str()); + ret = rename(m_name.c_str(), oldfile.c_str()); } fs.close(); @@ -47,7 +44,3 @@ int Dump::write(const char* byte) return ret; } - - -} //namespace - diff --git a/src/lib/ebus/dump.h b/src/ebusd/dump.h similarity index 56% rename from src/lib/ebus/dump.h rename to src/ebusd/dump.h index 34418139..812b9002 100644 --- a/src/lib/ebus/dump.h +++ b/src/ebusd/dump.h @@ -17,28 +17,25 @@ * along with ebusd. If not, see http://www.gnu.org/licenses/. */ -#ifndef LIBEBUS_DUMP_H_ -#define LIBEBUS_DUMP_H_ +#ifndef DUMP_H_ +#define DUMP_H_ #include -namespace libebus -{ - /** - * @brief Class for writing raw bytes to binary file. + * @brief class for writing raw bytes to binary file. */ class Dump { 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. + * @brief create a new instance to write dump files. + * @param name the file name of dump file. + * @param size the max. size of the dump file, before switching. */ - Dump(std::string filename, long filesize) - : m_filename(filename), m_filesize(filesize) {} + Dump(std::string name, long size) + : m_name(name), m_size(size) {} /** * @brief write byte to dump file. @@ -48,26 +45,24 @@ public: int write(const char* byte); /** - * @brief setter for dump file name. - * @param filename which will be used for dumping raw bytes. + * @brief set the name of dump file. + * @param name the file name of dump file. */ - void setFilename(const std::string& filename) { m_filename = filename; } + void setName(const std::string& name) { m_name = name; } /** - * @brief setter for max size of dump file. - * @param filesize max. Size of the dump file, before switching. + * @brief set the max size of dump file. + * @param size the max. size of the dump file, before switching. */ - void setFilesize(const long filesize) { m_filesize = filesize; } + void setSize(const long size) { m_size = size; } private: /** the name of dump file*/ - std::string m_filename; + std::string m_name; + /** max. size of dump file */ - long m_filesize; + long m_size; }; - -} //namespace - -#endif // LIBEBUS_DUMP_H_ +#endif // DUMP_H_ diff --git a/src/ebusd/ebusd.cpp b/src/ebusd/ebusd.cpp new file mode 100644 index 00000000..eb98fe9c --- /dev/null +++ b/src/ebusd/ebusd.cpp @@ -0,0 +1,185 @@ +/* + * Copyright (C) Roland Jax 2012-2014 + * + * 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/. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "logger.h" +#include "daemon.h" +#include "appl.h" +#include "baseloop.h" +#include +#include + +Appl& A = Appl::Instance(); +Daemon& D = Daemon::Instance(); +Logger& L = Logger::Instance(); + +BaseLoop* baseloop; + +void define_args() +{ + + A.setVersion(""PACKAGE_STRING""); + + A.addText("Options:\n"); + + A.addOption("address", "a", OptVal("FF"), dt_string, ot_mandatory, + "\tebus device address (FF)"); + + A.addOption("device", "d", OptVal("/dev/ttyUSB0"), dt_string, ot_mandatory, + "\tebus device (serial or network) (/dev/ttyUSB0)"); + + A.addOption("nodevicecheck", "n", OptVal(false), dt_bool, ot_none, + "disable valid ebus device test\n"); + + A.addOption("sendretries", "s", OptVal(2), dt_int, ot_mandatory, + "number retries send ebus command (2)"); + + A.addOption("lockretries", "", OptVal(2), dt_int, ot_mandatory, + "number retries to lock ebus (2)"); + + A.addOption("lockcounter", "", OptVal(5), dt_int, ot_mandatory, + "number of SYN to unlock send function (5)"); + + A.addOption("recvtimeout", "", OptVal(15000), dt_long, ot_mandatory, + "receive timeout in 'us' (15000)"); + + A.addOption("acquiretime", "", OptVal(4200), dt_long, ot_mandatory, + "waiting time for bus acquire in 'us' (4200)\n"); + + A.addOption("pollinterval", "", OptVal(5), dt_int, ot_mandatory, + "polling interval in 's' (5)\n"); + + A.addOption("ebusconfdir", "e", OptVal("/etc/ebusd"), dt_string, ot_mandatory, + "directory for ebus configuration (/etc/ebusd)\n"); + + A.addOption("foreground", "f", OptVal(false), dt_bool, ot_none, + "run in foreground\n"); + + A.addOption("port", "p", OptVal(8888), dt_int, ot_mandatory, + "\tlisten port (8888)"); + + A.addOption("localhost", "", OptVal(false), dt_bool, ot_none, + "listen localhost only\n"); + + A.addOption("logfile", "l", OptVal("/var/log/ebusd.log"), dt_string, ot_mandatory, + "\tlog file name (/var/log/ebusd.log)"); + + A.addOption("logareas", "", OptVal("all"), dt_string, ot_mandatory, + "\tlog areas - bas|net|bus|cyc|all (all)"); + + A.addOption("loglevel", "", OptVal("trace"), dt_string, ot_mandatory, + "\tlog level - error|event|trace|debug (event)"); + + A.addOption("lograwdata", "", OptVal(false), dt_bool, ot_none, + "log raw data (bytes)\n"); + + A.addOption("dump", "D", OptVal(false), dt_bool, ot_none, + "\tenable dump"); + + A.addOption("dumpfile", "", OptVal("/tmp/ebus_dump.bin"), dt_string, ot_mandatory, + "\tdump file name (/tmp/ebus_dump.bin)"); + + A.addOption("dumpsize", "", OptVal(100), dt_long, ot_mandatory, + "\tmax size for dump file in 'kB' (100)\n"); +} + +void shutdown() +{ + // stop threads + delete baseloop; + + // reset all signal handlers to default + signal(SIGHUP, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGTERM, SIG_DFL); + + // delete daemon pid file + if (D.status() == true) + D.stop(); + + // stop logger + L.log(bas, event, "ebusd stopped"); + L.stop(); + L.join(); + + exit(EXIT_SUCCESS); +} + +void signal_handler(int sig) +{ + switch (sig) { + case SIGHUP: + L.log(bas, event, "SIGHUP received"); + break; + case SIGINT: + L.log(bas, event, "SIGINT received"); + shutdown(); + break; + case SIGTERM: + L.log(bas, event, "SIGTERM received"); + shutdown(); + break; + default: + L.log(bas, event, "undefined signal %s", strsignal(sig)); + break; + } +} + +int main(int argc, char* argv[]) +{ + // define arguments and application variables + define_args(); + + // parse arguments + A.parseArgs(argc, argv); + + // make me daemon + if (A.getOptVal("foreground") == true) { + L += new LogConsole(calcAreas(A.getOptVal("logareas")), + calcLevel(A.getOptVal("loglevel")), + "logconsole"); + } else { + D.run("/var/run/ebusd.pid"); + L += new LogFile(calcAreas(A.getOptVal("logareas")), + calcLevel(A.getOptVal("loglevel")), + "logfile", A.getOptVal("logfile")); + } + + // trap signals that we expect to receive + signal(SIGHUP, signal_handler); + signal(SIGINT, signal_handler); + signal(SIGTERM, signal_handler); + + // start logger + L.start("logger"); + // wait for logger be ready + usleep(100000); + L.log(bas, event, "ebusd started"); + + // create baseloop + baseloop = new BaseLoop(); + baseloop->start(); + + // shutdown + shutdown(); +} + diff --git a/src/ebusd/main.cpp b/src/ebusd/main.cpp deleted file mode 100644 index 459c5579..00000000 --- a/src/ebusd/main.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (C) Roland Jax 2012-2014 - * - * 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 "logger.h" -#include "daemon.h" -#include "appl.h" -#include "baseloop.h" -#include - -using namespace libebus; - -Appl& A = Appl::Instance(); -Daemon& D = Daemon::Instance(); -LogInstance& L = LogInstance::Instance(); - -BaseLoop* baseloop; - -void define_args() -{ - A.addArgs("", 0); - - A.addItem("p_address", Appl::Param("FF"), "a", "address", - "\tebus device address (FF)", - Appl::type_string, Appl::opt_mandatory); - - A.addItem("p_device", Appl::Param("/dev/ttyUSB0"), "d", "device", - "\tebus device (serial or network) (/dev/ttyUSB0)", - Appl::type_string, Appl::opt_mandatory); - - A.addItem("p_nodevicecheck", Appl::Param(false), "n", "nodevicecheck", - "disable valid ebus device test\n", - Appl::type_bool, Appl::opt_none); - - A.addItem("p_sendretries", Appl::Param(2), "s", "sendretries", - "number retries send ebus command (2)", - Appl::type_int, Appl::opt_mandatory); - - A.addItem("p_lockretries", Appl::Param(2), "", "lockretries", - "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); - - A.addItem("p_recvtimeout", Appl::Param(15000), "", "recvtimeout", - "receive timeout in 'us' (15000)\n", - Appl::type_long, Appl::opt_mandatory); - - A.addItem("p_pollinterval", Appl::Param(5), "", "pollinterval", - "polling interval in 's' (5)\n", - Appl::type_int, Appl::opt_mandatory); - - A.addItem("p_ebusconfdir", Appl::Param("/etc/ebusd"), "e", "ebusconfdir", - "directory for ebus configuration (/etc/ebusd)\n", - Appl::type_string, Appl::opt_mandatory); - - A.addItem("p_foreground", Appl::Param(false), "f", "foreground", - "run in foreground\n", - Appl::type_bool, Appl::opt_none); - - A.addItem("p_port", Appl::Param(8888), "p", "port", - "\tlisten port (8888)", - Appl::type_int, Appl::opt_mandatory); - - A.addItem("p_localhost", Appl::Param(false), "", "localhost", - "listen localhost only\n", - Appl::type_bool, Appl::opt_none); - - A.addItem("p_logfile", Appl::Param("/var/log/ebusd.log"), "l", "logfile", - "\tlog file name (/var/log/ebusd.log)", - Appl::type_string, Appl::opt_mandatory); - - A.addItem("p_logareas", Appl::Param("all"), "", "logareas", - "\tlog areas - bas|net|bus|cyc|all (all)", - Appl::type_string, Appl::opt_mandatory); - - A.addItem("p_loglevel", Appl::Param("trace"), "", "loglevel", - "\tlog level - error|event|trace|debug (event)", - Appl::type_string, Appl::opt_mandatory); - - A.addItem("p_lograwdata", Appl::Param(false), "", "lograwdata", - "log raw data (bytes)\n", - Appl::type_bool, Appl::opt_none); - - A.addItem("p_dump", Appl::Param(false), "D", "dump", - "\tenable dump", - Appl::type_bool, Appl::opt_none); - - A.addItem("p_dumpfile", Appl::Param("/tmp/ebus_dump.bin"), "", "dumpfile", - "\tdump file name (/tmp/ebus_dump.bin)", - Appl::type_string, Appl::opt_mandatory); - - A.addItem("p_dumpsize", Appl::Param(100), "", "dumpsize", - "\tmax size for dump file in 'kB' (100)\n", - Appl::type_long, Appl::opt_mandatory); - - A.addItem("p_settings", Appl::Param(false), "", "settings", - "\tprint daemon settings\n", - Appl::type_bool, Appl::opt_none); - - A.addItem("p_help", Appl::Param(false), "h", "help", - "\tprint this message", - Appl::type_bool, Appl::opt_none); -} - -void shutdown() -{ - // stop threads - delete baseloop; - - // reset all signal handlers to default - signal(SIGHUP, SIG_DFL); - signal(SIGINT, SIG_DFL); - signal(SIGTERM, SIG_DFL); - - // delete Daemon pid file - if (D.status() == true) - D.stop(); - - // stop Logger - L.log(bas, event, "ebusd stopped"); - L.stop(); - L.join(); - - exit(EXIT_SUCCESS); -} - -void signal_handler(int sig) -{ - switch (sig) { - case SIGHUP: - L.log(bas, event, "SIGHUP received"); - break; - case SIGINT: - L.log(bas, event, "SIGINT received"); - shutdown(); - break; - case SIGTERM: - L.log(bas, event, "SIGTERM received"); - shutdown(); - break; - default: - L.log(bas, event, "undefined signal %s", strsignal(sig)); - break; - } -} - -int main(int argc, char* argv[]) -{ - // define Arguments and Application variables - define_args(); - - // parse Arguments - if (A.parseArgs(argc, argv) == false) { - A.printArgs(); - exit(EXIT_FAILURE); - } - - // print Help - if (A.getParam("p_help") == true) { - A.printArgs(); - exit(EXIT_SUCCESS); - } - - // print Daemon settings - if (A.getParam("p_settings") == true) - A.printSettings(); - - // make me Daemon - if (A.getParam("p_foreground") == true) { - L += new LogConsole(calcAreas(A.getParam("p_logareas")), - calcLevel(A.getParam("p_loglevel")), - "logconsole"); - } else { - D.run("/var/run/ebusd.pid"); - L += new LogFile(calcAreas(A.getParam("p_logareas")), - calcLevel(A.getParam("p_loglevel")), - "logfile", A.getParam("p_logfile")); - } - - // trap Signals that we expect to receive - signal(SIGHUP, signal_handler); - signal(SIGINT, signal_handler); - signal(SIGTERM, signal_handler); - - // start Logger - L.start("logger"); - // wait for Logger be ready - usleep(100000); - L.log(bas, event, "ebusd started"); - - // create BaseLoop - baseloop = new BaseLoop(); - baseloop->start(); - - // shutdown - shutdown(); -} - diff --git a/src/ebusd/network.cpp b/src/ebusd/network.cpp index ee0a649b..99dd0092 100644 --- a/src/ebusd/network.cpp +++ b/src/ebusd/network.cpp @@ -20,19 +20,98 @@ #include "network.h" #include "logger.h" #include "appl.h" +#include +#include -extern LogInstance& L; +extern Logger& L; extern Appl& A; +int Connection::m_ids = 0; -Network::Network(const bool localhost) : m_listening(false), m_running(false) +void* Connection::run() { - if (localhost == true) - m_Server = new TCPServer(A.getParam("p_port"), "127.0.0.1"); - else - m_Server = new TCPServer(A.getParam("p_port"), "0.0.0.0"); + m_running = true; - if (m_Server != NULL && m_Server->start() == 0) + int ret, nfds = 2; + struct pollfd fds[nfds]; + struct timespec tdiff; + + // set select timeout 10 secs + tdiff.tv_sec = 10; + tdiff.tv_nsec = 0; + + memset(fds, 0, sizeof(fds)); + + fds[0].fd = m_notify.notifyFD(); + fds[0].events = POLLIN; + + fds[1].fd = m_socket->getFD(); + fds[1].events = POLLIN; + + for (;;) { + // wait for new fd event + ret = ppoll(fds, nfds, &tdiff, NULL); + + if (ret == 0) { + continue; + } + + // new data from notify + if (fds[0].revents & POLLIN) + break; + + // new data from socket + if (fds[1].revents & POLLIN) { + char data[256]; + size_t datalen; + + if (m_socket->isValid() == true) + datalen = m_socket->recv(data, sizeof(data)-1); + else + break; + + // removed closed socket + if (datalen <= 0 || strcasecmp(data, "QUIT") == 0) + break; + + // send data + data[datalen] = '\0'; + NetMessage message(data); + m_netQueue->add(&message); + + // wait for result + L.log(net, debug, "[%05d] wait for result", getID()); + message.waitSignal(); + + L.log(net, debug, "[%05d] result added", getID()); + std::string result = message.getResult(); + + if (m_socket->isValid() == true) + m_socket->send(result.c_str(), result.size()); + else + break; + + } + + } + + delete m_socket; + m_running = false; + L.log(net, trace, "[%05d] connection closed", getID()); + + return NULL; +} + + +Network::Network(const bool local, WQueue* netQueue) + : m_netQueue(netQueue), m_listening(false), m_running(false) +{ + if (local == true) + m_tcpServer = new TCPServer(A.getOptVal("port"), "127.0.0.1"); + else + m_tcpServer = new TCPServer(A.getOptVal("port"), "0.0.0.0"); + + if (m_tcpServer != NULL && m_tcpServer->start() == 0) m_listening = true; } @@ -50,7 +129,7 @@ Network::~Network() if (m_running == true) stop(); - delete m_Server; + delete m_tcpServer; } void* Network::run() @@ -60,53 +139,50 @@ void* Network::run() m_running = true; - int maxfd; - fd_set checkfds; - struct timeval timeout; + int ret, nfds = 2; + struct pollfd fds[nfds]; + struct timespec tdiff; - FD_ZERO(&checkfds); - FD_SET(m_notify.notifyFD(), &checkfds); - FD_SET(m_Server->getFD(), &checkfds); + // set select timeout 1 secs + tdiff.tv_sec = 1; + tdiff.tv_nsec = 0; - (m_notify.notifyFD() > m_Server->getFD()) ? - (maxfd = m_notify.notifyFD()) : (maxfd = m_Server->getFD()); + memset(fds, 0, sizeof(fds)); + + fds[0].fd = m_notify.notifyFD(); + fds[0].events = POLLIN; + + fds[1].fd = m_tcpServer->getFD(); + fds[1].events = POLLIN; for (;;) { - fd_set readfds; - int ret; + // wait for new fd event + ret = ppoll(fds, nfds, &tdiff, NULL); - // set select timeout 1 secs - timeout.tv_sec = 1; - timeout.tv_usec = 0; - - // set readfds to inital checkfds - readfds = checkfds; - - ret = select(maxfd + 1, &readfds, NULL, NULL, &timeout); if (ret == 0) { cleanConnections(); continue; } // new data from notify - if (FD_ISSET(m_notify.notifyFD(), &readfds)) { + if (fds[0].revents & POLLIN) { m_running = false; break; } // new data from socket - if (FD_ISSET(m_Server->getFD(), &readfds)) { - TCPSocket* socket = m_Server->newSocket(); + if (fds[1].revents & POLLIN) { + TCPSocket* socket = m_tcpServer->newSocket(); if (socket == NULL) continue; - Connection* connection = new Connection(socket, m_queue); + Connection* connection = new Connection(socket, m_netQueue); if (connection == NULL) continue; connection->start("connection"); m_connections.push_back(connection); - L.log(net, trace, "[%08x] connection opened %s", connection->getID(), socket->getIP().c_str()); + L.log(net, trace, "[%05d] connection opened %s", connection->getID(), socket->getIP().c_str()); } } diff --git a/src/ebusd/network.h b/src/ebusd/network.h index fc04ffc7..2f25b46e 100644 --- a/src/ebusd/network.h +++ b/src/ebusd/network.h @@ -20,30 +20,218 @@ #ifndef NETWORK_H_ #define NETWORK_H_ -#include "connection.h" +#include "tcpsocket.h" +#include "wqueue.h" +#include "notify.h" +#include "thread.h" +#include +/** forward declaration for class connection */ +class Connection; + +/** + * @brief class for data/message transfer between connection and baseloop. + */ +class NetMessage +{ + +public: + /** + * @brief constructs a new instance with message and source client address. + * @param data from client. + */ + NetMessage(const std::string data) : m_data(data) + { + pthread_mutex_init(&m_mutex, NULL); + pthread_cond_init(&m_cond, NULL); + } + + /** + * @brief destructor. + */ + ~NetMessage() + { + pthread_mutex_destroy(&m_mutex); + pthread_cond_destroy(&m_cond); + } + + /** + * @brief copy constructor. + * @param src message object for copy. + */ + NetMessage(const NetMessage& src) : m_data(src.m_data) {} + + /** + * @brief get the data string. + * @return the data string. + */ + std::string getData() const { return m_data; } + + /** + * @brief get the result string. + * @return the result string. + */ + std::string getResult() const { return m_result; } + + /** + * @brief set the result string. + * @return the result string. + */ + void setResult(const std::string result) { m_result = result; } + + /** + * @brief wait on notification. + */ + void waitSignal() + { + pthread_mutex_lock(&m_mutex); + + while (m_result.size() == 0) + pthread_cond_wait(&m_cond, &m_mutex); + + pthread_mutex_unlock(&m_mutex); + } + + /** + * @brief send notification. + */ + void sendSignal() + { + pthread_mutex_lock(&m_mutex); + pthread_cond_signal(&m_cond); + pthread_mutex_unlock(&m_mutex); + } + +private: + /** the data string */ + std::string m_data; + + /** the result string */ + std::string m_result; + + /** mutex variable for exclusive lock */ + pthread_mutex_t m_mutex; + + /** condition variable for exclusive lock */ + pthread_cond_t m_cond; + +}; + +/** + * @brief class connection which handle client and baseloop communication. + */ +class Connection : public Thread +{ + +public: + /** + * @brief create a new connection instance. + * @param socket the tcp socket for communication. + * @param netQueue the remote queue for network messages. + */ + Connection(TCPSocket* socket, WQueue* netQueue) + : m_socket(socket), m_netQueue(netQueue), m_running(false) + { m_id = ++m_ids; } + + /** + * @brief endless loop for connection instance. + * @return void pointer. + */ + void* run(); + + /** + * @brief closs active connection. + */ + void stop() const { m_notify.notify(); } + + /** + * @brief status of connection instance. + * @return true if connection is running. + */ + bool isRunning() const { return m_running; } + + /** + * @brief return own connection id. + * @return id of current connection. + */ + int getID() { return m_id; } + +private: + /** the tcp socket instance */ + TCPSocket* m_socket; + + /** remote queue for network messages */ + WQueue* m_netQueue; + + /** notification object for shutdown procedure */ + Notify m_notify; + + /** true if this instance is running */ + bool m_running; + + /** id of current connection*/ + int m_id; + + /** sumary for opened connections */ + static int m_ids; + +}; + +/** + * @brief class network which listening on tcp socket for incoming connections. + */ class Network : public Thread { public: - Network(const bool localhost); + /** + * @brief create a new network instance and listening for incoming connections. + * @param local true to accept connections only for local host. + * @param netQueue the remote queue for network messages. + */ + Network(const bool local, WQueue* netQueue); + + /** + * @brief destructor. + */ ~Network(); - void addQueue(WQueue* queue) { m_queue = queue; } - + /** + * @brief endless loop for network instance. + * @return void pointer. + */ void* run(); + + /** + * @brief shutdown network subsystem. + */ void stop() const { m_notify.notify(); usleep(100000); } private: + /** container for active connections */ std::list m_connections; - WQueue* m_queue; - TCPServer* m_Server; + + /** remote queue for network messages */ + WQueue* m_netQueue; + + /** the tcp server instance */ + TCPServer* m_tcpServer; + + /** notification object for shutdown procedure */ Notify m_notify; + + /** true if this instance is listening */ bool m_listening; + + /** true if this instance is running */ bool m_running; + /** + * @brief clean inactive connections from container. + */ void cleanConnections(); }; #endif // NETWORK_H_ + diff --git a/src/lib/ebus/Makefile.am b/src/lib/ebus/Makefile.am index 64fa53d9..570375bf 100644 --- a/src/lib/ebus/Makefile.am +++ b/src/lib/ebus/Makefile.am @@ -12,16 +12,12 @@ libebus_a_SOURCES = result.cpp \ data.h \ port.cpp \ port.h \ - buscommand.cpp \ - buscommand.h \ command.cpp \ command.h \ commands.cpp \ commands.h \ configfile.cpp \ configfile.h \ - dump.cpp \ - dump.h \ decode.cpp \ decode.h \ encode.cpp \ diff --git a/src/lib/ebus/buscommand.cpp b/src/lib/ebus/buscommand.cpp deleted file mode 100644 index ac822f63..00000000 --- a/src/lib/ebus/buscommand.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) Roland Jax 2012-2014 - * - * 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 "buscommand.h" - -namespace libebus -{ - -BusCommand::BusCommand(const std::string commandStr, const bool isPoll) - : m_isPoll(isPoll), m_command(commandStr), m_result(), m_resultCode(RESULT_OK) -{ - unsigned char dstAddress = m_command[1]; - - if (dstAddress == BROADCAST) - m_type = broadcast; - else if (isMaster(dstAddress) == true) - m_type = masterMaster; - else - m_type = masterSlave; - - pthread_mutex_init(&m_mutex, NULL); - pthread_cond_init(&m_cond, NULL); -} - -BusCommand::~BusCommand() -{ - pthread_mutex_destroy(&m_mutex); - pthread_cond_destroy(&m_cond); -} - -const std::string BusCommand::getMessageStr() -{ - std::string result; - - if (m_resultCode >= 0) { - if (m_type == masterSlave) { - result = m_command.getDataStr(); - result += "00"; - result += m_result.getDataStr(); - result += "00"; - } - else - result = "success"; - } - else - result = "error: "+std::string(getResultCodeCStr()); - - return result; -} - - -} //namespace - diff --git a/src/lib/ebus/buscommand.h b/src/lib/ebus/buscommand.h deleted file mode 100644 index bf06e37d..00000000 --- a/src/lib/ebus/buscommand.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) Roland Jax 2012-2014 - * - * 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_BUSCOMMAND_H_ -#define LIBEBUS_BUSCOMMAND_H_ - -#include "symbol.h" -#include "result.h" - - -namespace libebus -{ - - -enum CommandType { invalid, broadcast, masterMaster, masterSlave }; - -class BusCommand -{ - -public: - BusCommand(const std::string command, const bool isPoll); - ~BusCommand(); - - CommandType getType() const { return m_type; } - bool isPoll() const { return m_isPoll; } - - SymbolString getCommand() const { return m_command; } - SymbolString getResult() const { return m_result; } - - 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(); - - void waitSignal() { pthread_cond_wait(&m_cond, &m_mutex); } // TODO timeout - void sendSignal() { pthread_cond_signal(&m_cond); } - -private: - CommandType m_type; - bool m_isPoll; - SymbolString m_command; - SymbolString m_result; - int m_resultCode; - - pthread_mutex_t m_mutex; - pthread_cond_t m_cond; -}; - - -} //namespace - -#endif // LIBEBUS_BUSCOMMAND_H_ diff --git a/src/lib/ebus/command.cpp b/src/lib/ebus/command.cpp index 8c475d34..795a3740 100644 --- a/src/lib/ebus/command.cpp +++ b/src/lib/ebus/command.cpp @@ -27,10 +27,6 @@ #include #include -namespace libebus -{ - - std::string Command::calcData() { // encode - only first entry will be encoded @@ -340,6 +336,3 @@ void Command::encode(const std::string& data, const std::string& type, delete help; } - -} //namespace - diff --git a/src/lib/ebus/command.h b/src/lib/ebus/command.h index 91bebf53..2c725ce4 100644 --- a/src/lib/ebus/command.h +++ b/src/lib/ebus/command.h @@ -23,10 +23,6 @@ #include #include -namespace libebus -{ - - typedef std::vector cmd_t; typedef cmd_t::const_iterator cmdCI_t; @@ -63,7 +59,4 @@ private: }; - -} //namespace - #endif // LIBEBUS_COMMAND_H_ diff --git a/src/lib/ebus/commands.cpp b/src/lib/ebus/commands.cpp index 855d6e73..dfb0ee28 100644 --- a/src/lib/ebus/commands.cpp +++ b/src/lib/ebus/commands.cpp @@ -25,16 +25,12 @@ #include #include -namespace libebus -{ - - Commands::~Commands() { - for (mapCI_t iter = m_polDB.begin(); iter != m_polDB.end(); ++iter) + for (mapCI_t iter = m_pollDB.begin(); iter != m_pollDB.end(); ++iter) delete iter->second; - m_polDB.clear(); + m_pollDB.clear(); for (mapCI_t iter = m_cycDB.begin(); iter != m_cycDB.end(); ++iter) delete iter->second; @@ -55,7 +51,7 @@ void Commands::addCommand(const cmd_t& command) if (strcasecmp(command[0].c_str(),"P") == 0) { Command* cmd = new Command(m_cmdDB.size()-1, command); - m_polDB.insert(pair_t(m_cmdDB.size()-1, cmd)); + m_pollDB.insert(pair_t(m_cmdDB.size()-1, cmd)); } } @@ -127,7 +123,7 @@ int Commands::findCommand(const std::string& data) const return -1; } -std::string Commands::getEbusCommand(const int index) const +std::string Commands::getBusCommand(const int index) const { cmd_t command = m_cmdDB.at(index); std::string cmd; @@ -163,7 +159,7 @@ int Commands::storeCycData(const std::string& data) const // walk through commands for (; iter != m_cycDB.end(); iter++) { - std::string command = getEbusCommand(iter->first); + std::string command = getBusCommand(iter->first); // skip wrong search string length if (command.length() > search.length()) @@ -188,35 +184,35 @@ std::string Commands::getCycData(int index) const return ""; } -int Commands::nextPolCommand() +int Commands::nextPollCommand() { size_t index = 0; - m_polIndex++; + m_pollIndex++; - if (m_polIndex == m_polDB.size()) - m_polIndex = 0; + if (m_pollIndex == m_pollDB.size()) + m_pollIndex = 0; - mapCI_t iter = m_polDB.begin(); + mapCI_t iter = m_pollDB.begin(); - for (; iter != m_polDB.end(); iter++, index++) - if (index == m_polIndex) + for (; iter != m_pollDB.end(); iter++, index++) + if (index == m_pollIndex) return iter->first; return -1; } -void Commands::storePolData(const std::string& data) const +void Commands::storePollData(const std::string& data) const { // prepare string for searching command std::string search(data.substr(2, 8 + strtol(data.substr(8,2).c_str(), NULL, 16) * 2)); - mapCI_t iter = m_polDB.begin(); + mapCI_t iter = m_pollDB.begin(); // walk through commands - for (; iter != m_polDB.end(); iter++) { + for (; iter != m_pollDB.end(); iter++) { - std::string command = getEbusCommand(iter->first); + std::string command = getBusCommand(iter->first); // skip wrong search string length if (command.length() > search.length()) @@ -228,15 +224,29 @@ void Commands::storePolData(const std::string& data) const } } -std::string Commands::getPolData(int index) const +std::string Commands::getPollData(const int index) const { - mapCI_t iter = m_polDB.find(index); - if (iter != m_polDB.end()) + mapCI_t iter = m_pollDB.find(index); + if (iter != m_pollDB.end()) return iter->second->getData(); else return ""; } +void Commands::storeScanData(const std::string& data) +{ + std::vector::const_iterator iter = m_scanDB.begin(); + bool found = false; + + // walk through scan data + for (; iter != m_scanDB.end(); iter++) + if (data == (*iter)) + found = true; + + if (found == false) + m_scanDB.push_back(data); +} + void Commands::printCommand(const cmd_t& command) const { if (command.size() == 0) @@ -246,6 +256,3 @@ void Commands::printCommand(const cmd_t& command) const std::cout << *i << ';'; } - -} //namespace - diff --git a/src/lib/ebus/commands.h b/src/lib/ebus/commands.h index c43624b1..d927b15c 100644 --- a/src/lib/ebus/commands.h +++ b/src/lib/ebus/commands.h @@ -25,10 +25,6 @@ #include #include -namespace libebus -{ - - typedef std::vector cmdDB_t; typedef cmdDB_t::const_iterator cmdDBCI_t; @@ -40,7 +36,7 @@ class Commands { public: - Commands() : m_polIndex(-1) {} + Commands() : m_pollIndex(-1) {} ~Commands(); void addCommand(const cmd_t& command); @@ -48,33 +44,36 @@ public: std::size_t sizeCmdDB() const { return m_cmdDB.size(); } std::size_t sizeCycDB() const { return m_cycDB.size(); } - std::size_t sizePolDB() const { return m_polDB.size(); } + std::size_t sizePollDB() const { return m_pollDB.size(); } + std::size_t sizeScanDB() const { return m_scanDB.size(); } cmd_t const& operator[](const std::size_t& index) const { return m_cmdDB[index]; } int findCommand(const std::string& data) const; std::string getCmdType(const int index) const { return std::string(m_cmdDB.at(index)[0]); } - std::string getEbusCommand(const int index) const; + std::string getBusCommand(const int index) const; int storeCycData(const std::string& data) const; std::string getCycData(int index) const; - int nextPolCommand(); - void storePolData(const std::string& data) const; - std::string getPolData(int index) const; + int nextPollCommand(); + void storePollData(const std::string& data) const; + std::string getPollData(const int index) const; + + void storeScanData(const std::string& data); + std::string getScanData(const int index) const { return m_scanDB[index]; } private: cmdDB_t m_cmdDB; map_t m_cycDB; - map_t m_polDB; - size_t m_polIndex; + map_t m_pollDB; + size_t m_pollIndex; + std::vector m_scanDB; void printCommand(const cmd_t& command) const; }; - -} //namespace - #endif // LIBEBUS_COMMANDS_H_ + diff --git a/src/lib/ebus/configfile.cpp b/src/lib/ebus/configfile.cpp index 0520580c..f630bac5 100644 --- a/src/lib/ebus/configfile.cpp +++ b/src/lib/ebus/configfile.cpp @@ -22,10 +22,6 @@ #include #include -namespace libebus -{ - - void ConfigFileCSV::parse(std::istream& is, Commands& commands) { std::string line; @@ -132,6 +128,3 @@ void ConfigCommands::addFiles(const std::string path, const std::string extensio closedir(dir); }; - -} //namespace - diff --git a/src/lib/ebus/configfile.h b/src/lib/ebus/configfile.h index 4d5183b1..d800c096 100644 --- a/src/lib/ebus/configfile.h +++ b/src/lib/ebus/configfile.h @@ -24,21 +24,18 @@ #include #include -namespace libebus -{ - /** available file endings / types. */ enum FileType { CSV, XML }; /** - * @brief Base class for config files. + * @brief base class for config files. */ class ConfigFile { public: /** - * @brief Destructor. + * @brief destructor. */ virtual ~ConfigFile() {} @@ -52,14 +49,14 @@ public: }; /** - * @brief Class for CSV config files. + * @brief class for CSV config files. */ class ConfigFileCSV : public ConfigFile { public: /** - * @brief Destructor. + * @brief destructor. */ ~ConfigFileCSV() {} @@ -73,14 +70,14 @@ public: }; /** - * @brief Class for XML config files. + * @brief class for XML config files. */ class ConfigFileXML : public ConfigFile { public: /** - * @brief Destructor. + * @brief destructor. */ ~ConfigFileXML() {} @@ -95,32 +92,32 @@ public: /** - * @brief Class for class Device. + * @brief class for class device. */ class ConfigCommands { public: /** - * @brief Set file type and add recursive files from given path. + * @brief set file type and add recursive files from given path. * @param path to configuration files. - * @param Filetype to parse. + * @param filetype to parse. */ ConfigCommands(const std::string path, const FileType type); /** - * @brief Destructor. + * @brief destructor. */ ~ConfigCommands() { delete m_configfile; } /** * @brief setter for file type. - * @param FileType of files. + * @param filetype of files. */ void setType(const FileType type); /** - * @brief Parse files for commands and store them into commands instance. + * @brief parse files for commands and store them into commands instance. * @return a commands instance */ Commands* getCommands(); @@ -128,10 +125,13 @@ public: 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 m_files; @@ -144,7 +144,5 @@ private: }; - -} //namespace - #endif // LIBEBUS_CONFIGFILE_H_ + diff --git a/src/lib/ebus/data.cpp b/src/lib/ebus/data.cpp old mode 100644 new mode 100755 index 6fe7f592..fd765777 --- a/src/lib/ebus/data.cpp +++ b/src/lib/ebus/data.cpp @@ -29,9 +29,6 @@ #include #include -namespace libebus -{ - /** the known data field types. */ static const dataType_t dataTypes[] = { {"STR",16*8,bt_str, ADJ, ' ', 1, 16, 0, 0}, // >= 1 byte character string filled up with space @@ -895,7 +892,6 @@ result_t ValueListDataField::writeSymbols(std::istringstream& input, return RESULT_ERR_INVALID_ARG; // value assignment not found } - DataFieldSet::~DataFieldSet() { while (m_fields.empty() == false) { @@ -976,6 +972,3 @@ result_t DataFieldSet::write(std::istringstream& input, SymbolString& masterData return RESULT_OK; } - - -} //namespace diff --git a/src/lib/ebus/data.h b/src/lib/ebus/data.h old mode 100644 new mode 100755 index c5635022..ddd21b8e --- a/src/lib/ebus/data.h +++ b/src/lib/ebus/data.h @@ -26,10 +26,6 @@ #include #include -namespace libebus -{ - - /** the message part in which a data field is stored. */ enum PartType { pt_template, // special part type for templates (relative offset) @@ -501,6 +497,4 @@ protected: }; -} //namespace - #endif // LIBEBUS_DATA_H_ diff --git a/src/lib/ebus/decode.cpp b/src/lib/ebus/decode.cpp index e8fd7a9f..49ca9e22 100644 --- a/src/lib/ebus/decode.cpp +++ b/src/lib/ebus/decode.cpp @@ -26,10 +26,6 @@ #include #include -namespace libebus -{ - - Decode::Decode(const std::string& data, const std::string& factor) : m_data(data) { @@ -347,6 +343,3 @@ std::string DecodeTTM::decode() return result.str(); } - -} //namespace - diff --git a/src/lib/ebus/decode.h b/src/lib/ebus/decode.h index d37cefe3..da1d087f 100644 --- a/src/lib/ebus/decode.h +++ b/src/lib/ebus/decode.h @@ -22,10 +22,6 @@ #include -namespace libebus -{ - - class Decode { @@ -285,7 +281,4 @@ public: }; - -} //namespace - #endif // LIBEBUS_DECODE_H_ diff --git a/src/lib/ebus/encode.cpp b/src/lib/ebus/encode.cpp index 76d55015..37d14eb5 100644 --- a/src/lib/ebus/encode.cpp +++ b/src/lib/ebus/encode.cpp @@ -26,10 +26,6 @@ #include #include -namespace libebus -{ - - Encode::Encode(const std::string& data, const std::string& factor) : m_data(data) { @@ -364,6 +360,3 @@ std::string EncodeTTM::encode() return result.str(); } - -} //namespace - diff --git a/src/lib/ebus/encode.h b/src/lib/ebus/encode.h index 7730054b..7d87d45d 100644 --- a/src/lib/ebus/encode.h +++ b/src/lib/ebus/encode.h @@ -22,10 +22,6 @@ #include -namespace libebus -{ - - class Encode { @@ -285,7 +281,4 @@ public: }; - -} //namespace - #endif // LIBEBUS_ENCODE_H_ diff --git a/src/lib/ebus/port.cpp b/src/lib/ebus/port.cpp index c815182b..cf941aa8 100644 --- a/src/lib/ebus/port.cpp +++ b/src/lib/ebus/port.cpp @@ -20,19 +20,11 @@ #include "port.h" #include #include -#include #include #include -#include -#include #include #include -#include - - -namespace libebus -{ - +#include bool Device::isOpen() { @@ -72,18 +64,23 @@ ssize_t Device::recvBytes(const long timeout, size_t maxCount) return -1; // TODO RESULT_ERR_DEVICE if (timeout > 0) { - fd_set readfds; - struct timeval tdiff; + int ret, nfds = 1; + struct pollfd fds[nfds]; + struct timespec tdiff; // set select timeout tdiff.tv_sec = 0; - tdiff.tv_usec = timeout; + tdiff.tv_nsec = timeout*1000; - FD_ZERO(&readfds); - FD_SET(m_fd, &readfds); + memset(fds, 0, sizeof(fds)); - if (select(m_fd + 1, &readfds, NULL, NULL, &tdiff) != 1) - return -2; // TODO RESULT_ERR_TIMEOUT + fds[0].fd = m_fd; + fds[0].events = POLLIN; + + ret = ppoll(fds, nfds, &tdiff, NULL); + + if (ret == -1) return -1; // TODO RESULT_ERR_DEVICE + if (ret == 0) return -2; // TODO RESULT_ERR_TIMEOUT } if (maxCount > sizeof(m_buffer)) @@ -141,7 +138,7 @@ void DeviceSerial::openDevice(const std::string deviceName, const bool noDeviceC newSettings.c_cc[VTIME] = 0; // empty device buffer - tcflush(m_fd, TCIOFLUSH); + tcflush(m_fd, TCIFLUSH); // activate new settings of serial device tcsetattr(m_fd, TCSANOW, &newSettings); @@ -255,8 +252,3 @@ void Port::setType(const DeviceType type) }; }; - -} //namespace - - - diff --git a/src/lib/ebus/port.h b/src/lib/ebus/port.h index 7dc8e53a..213bf5a4 100644 --- a/src/lib/ebus/port.h +++ b/src/lib/ebus/port.h @@ -25,9 +25,6 @@ #include #include -namespace libebus -{ - /** available device types. */ enum DeviceType { SERIAL, NETWORK }; @@ -39,19 +36,19 @@ enum DeviceType { SERIAL, NETWORK }; /** - * @brief Base class for input devices. + * @brief base class for input devices. */ class Device { public: /** - * @brief Constructs a new instance. + * @brief constructs a new instance. */ Device() : m_fd(-1), m_open(false), m_noDeviceCheck(false) {} /** - * @brief Destructor. + * @brief destructor. */ virtual ~Device() {} @@ -74,7 +71,7 @@ public: bool isOpen(); /** - * @brief sendBytes write bytes into opened file descriptor. + * @brief sendBytes write bytes to 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. @@ -83,7 +80,7 @@ public: /** * @brief recvBytes read bytes from opened file descriptor. - * @param timeout max time out for new input data. + * @param timeoutmax time for new input data [usec]. * @param maxCount max size of receive buffer. * @return number of read bytes or -1 if an error has occured. */ @@ -104,12 +101,16 @@ public: 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 m_recvBuffer; + /** receive buffer */ unsigned char m_buffer[MAX_READ_SIZE]; @@ -123,14 +124,14 @@ private: }; /** - * @brief Class for serial input device. + * @brief class for serial input device. */ class DeviceSerial : public Device { public: /** - * @brief Destructor. + * @brief destructor. */ ~DeviceSerial() { closeDevice(); } @@ -153,14 +154,14 @@ private: }; /** - * @brief Class for network input device. + * @brief class for network input device. */ class DeviceNetwork : public Device { public: /** - * @brief Destructor. + * @brief destructor. */ ~DeviceNetwork() { closeDevice(); } @@ -181,21 +182,21 @@ private: }; /** - * @brief Wrapper class for class Device. + * @brief wrapper class for class device. */ class Port { public: /** - * @brief Constructs a new instance and determine device type. + * @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. + * @brief destructor. */ ~Port() { delete m_device; } @@ -248,8 +249,10 @@ public: private: /** the device name */ std::string m_deviceName; + /** the device instance */ Device* m_device; + /** true if device check is disabled */ bool m_noDeviceCheck; @@ -261,7 +264,4 @@ private: }; - -} //namespace - #endif // LIBEBUS_PORT_H_ diff --git a/src/lib/ebus/result.cpp b/src/lib/ebus/result.cpp index 9fa53faf..eeb2787e 100644 --- a/src/lib/ebus/result.cpp +++ b/src/lib/ebus/result.cpp @@ -19,10 +19,7 @@ #include "result.h" -namespace libebus -{ - -const char* getResultCodeCStr(result_t resultCode) { +const char* getResultCode(result_t resultCode) { switch (resultCode) { case RESULT_ERR_SEND: return "ERR_SEND: send error"; case RESULT_ERR_EXTRA_DATA: return "ERR_EXTRA_DATA: received bytes > sent bytes"; @@ -43,5 +40,3 @@ const char* getResultCodeCStr(result_t resultCode) { } } - -} //namespace diff --git a/src/lib/ebus/result.h b/src/lib/ebus/result.h index 0298e62f..df1af2d2 100644 --- a/src/lib/ebus/result.h +++ b/src/lib/ebus/result.h @@ -20,10 +20,6 @@ #ifndef LIBEBUS_RESULT_H_ #define LIBEBUS_RESULT_H_ -namespace libebus -{ - - static const int RESULT_OK = 0; static const int RESULT_BUS_ACQUIRED = 1; // bus successfully acquired @@ -54,9 +50,6 @@ typedef int result_t; * @param resultCode the result code (see RESULT_ constants). * @return the string corresponding to the result code. */ -const char* getResultCodeCStr(result_t resultCode); - - -} //namespace +const char* getResultCode(result_t resultCode); #endif // LIBEBUS_RESULT_H_ diff --git a/src/lib/ebus/symbol.cpp b/src/lib/ebus/symbol.cpp index 05d09ab1..c98027f6 100644 --- a/src/lib/ebus/symbol.cpp +++ b/src/lib/ebus/symbol.cpp @@ -22,9 +22,6 @@ #include #include -namespace libebus -{ - /** * @brief CRC8 lookup table for the polynom 0x9b = x^8 + x^7 + x^4 + x^3 + x^1 + 1. */ @@ -190,4 +187,3 @@ bool isMaster(unsigned char addr) { && ((addrLo == 0x0) || (addrLo == 0x1) || (addrLo == 0x3) || (addrLo == 0x7) || (addrLo == 0xF)); } -} //namespace diff --git a/src/lib/ebus/symbol.h b/src/lib/ebus/symbol.h index a340b930..98b74d3d 100644 --- a/src/lib/ebus/symbol.h +++ b/src/lib/ebus/symbol.h @@ -25,10 +25,6 @@ #include #include -namespace libebus -{ - - static const unsigned char ESC = 0xA9; // escape symbol, either followed by 0x00 for the value 0xA9, or 0x01 for the value 0xAA static const unsigned char SYN = 0xAA; // synchronization symbol static const unsigned char ACK = 0x00; // positive acknowledge @@ -139,7 +135,4 @@ private: */ bool isMaster(unsigned char addr); - -} //namespace - #endif // LIBEBUS_SYMBOL_H_ diff --git a/src/lib/ebus/test/test_commands.cpp b/src/lib/ebus/test/test_commands.cpp index e51ed79b..befbd46a 100644 --- a/src/lib/ebus/test/test_commands.cpp +++ b/src/lib/ebus/test/test_commands.cpp @@ -25,8 +25,6 @@ #include #include -using namespace libebus; - // will be part of cfg csv class void readCSV(std::istream& is, Commands& commands){ std::string line; diff --git a/src/lib/ebus/test/test_configfile.cpp b/src/lib/ebus/test/test_configfile.cpp index ce46f3d5..beac4fb5 100644 --- a/src/lib/ebus/test/test_configfile.cpp +++ b/src/lib/ebus/test/test_configfile.cpp @@ -24,9 +24,6 @@ #include #include -using namespace libebus; - - int main() { std::string dir("test"); diff --git a/src/lib/ebus/test/test_data.cpp b/src/lib/ebus/test/test_data.cpp old mode 100644 new mode 100755 index 2a3c0a96..c38b4d43 --- a/src/lib/ebus/test/test_data.cpp +++ b/src/lib/ebus/test/test_data.cpp @@ -21,8 +21,6 @@ #include #include -using namespace libebus; - void verify(bool expectFailMatch, std::string type, std::string input, bool match, std::string expectStr, std::string gotStr) { @@ -217,7 +215,7 @@ int main() if (result != RESULT_OK) { std::cout << "\"" << check[0] << "\": create error: " - << getResultCodeCStr(result) << std::endl; + << getResultCode(result) << std::endl; continue; } if (fields == NULL) { @@ -256,7 +254,7 @@ int main() << check[2] << "< OK" << std::endl; else if (result != RESULT_OK) { std::cout << " read " << fields->getName() << " >" << check[2] << "< error: " - << getResultCodeCStr(result) << std::endl; + << getResultCode(result) << std::endl; } else { bool match = strcasecmp(output.str().c_str(), expectStr.c_str()) == 0; @@ -276,7 +274,7 @@ int main() } else if (result != RESULT_OK) { std::cout << " write " << fields->getName() << " >" - << expectStr << "< error: " << getResultCodeCStr(result) << std::endl; + << expectStr << "< error: " << getResultCode(result) << std::endl; } else { bool match = mstr == writeMstr && sstr == writeSstr; diff --git a/src/lib/ebus/test/test_decode.cpp b/src/lib/ebus/test/test_decode.cpp index 3da4e9ef..d9df8858 100644 --- a/src/lib/ebus/test/test_decode.cpp +++ b/src/lib/ebus/test/test_decode.cpp @@ -21,10 +21,6 @@ #include #include - -using namespace libebus; - - int main() { Decode* help_dec = NULL; diff --git a/src/lib/ebus/test/test_encode.cpp b/src/lib/ebus/test/test_encode.cpp index f7a65fd4..5cc97abe 100644 --- a/src/lib/ebus/test/test_encode.cpp +++ b/src/lib/ebus/test/test_encode.cpp @@ -21,10 +21,6 @@ #include #include - -using namespace libebus; - - int main() { Encode* help_enc = NULL; diff --git a/src/lib/ebus/test/test_port.cpp b/src/lib/ebus/test/test_port.cpp index 9bdc12cb..2aae9808 100644 --- a/src/lib/ebus/test/test_port.cpp +++ b/src/lib/ebus/test/test_port.cpp @@ -21,8 +21,6 @@ #include #include -using namespace libebus; - int main () { std::string dev("/dev/ttyUSB20"); diff --git a/src/lib/ebus/test/test_symbol.cpp b/src/lib/ebus/test/test_symbol.cpp index b68ef9df..0ca984a7 100644 --- a/src/lib/ebus/test/test_symbol.cpp +++ b/src/lib/ebus/test/test_symbol.cpp @@ -21,8 +21,6 @@ #include #include -using namespace libebus; - int main () { SymbolString sstr = SymbolString("10feb5050427a915aa"); diff --git a/src/lib/utils/Makefile.am b/src/lib/utils/Makefile.am index d10f81d6..3f9640ac 100644 --- a/src/lib/utils/Makefile.am +++ b/src/lib/utils/Makefile.am @@ -4,18 +4,20 @@ AM_CXXFLAGS = -fpic \ noinst_LIBRARIES = libutils.a -libutils_a_SOURCES = wqueue.h \ - notify.h \ - appl.cpp \ +libutils_a_SOURCES = appl.cpp \ appl.h \ daemon.cpp \ daemon.h \ logger.cpp \ logger.h \ + notify.cpp \ + notify.h \ + tcpsocket.cpp \ + tcpsocket.h \ thread.cpp \ thread.h \ - tcpsocket.cpp \ - tcpsocket.h + wqueue.h + distclean-local: -rm -f Makefile.in diff --git a/src/lib/utils/appl.cpp b/src/lib/utils/appl.cpp index 263f9554..628d84d2 100644 --- a/src/lib/utils/appl.cpp +++ b/src/lib/utils/appl.cpp @@ -22,200 +22,229 @@ #include #include -Appl& Appl::Instance() +Appl& Appl::Instance(const bool command) { - static Appl instance; + static Appl instance(command); return instance; } Appl::~Appl() { - m_args.clear(); - m_params.clear(); + m_opts.clear(); + m_optvals.clear(); } -void Appl::addArgs(const std::string argTxt, const int argNum) +void Appl::addText(const char* text) { - m_argTxt = argTxt; - m_argNum = argNum; + opt_t opt; + opt.name = "__text_only__"; + opt.shortname = ""; + opt.datatype = dt_none; + opt.optiontype = ot_none; + opt.description = text; + m_opts.push_back(opt); } -void Appl::addItem(const char* name, Param param, const char* shortname, - const char* longname, const char* description, - Datatype datatype, Optiontype optiontype) +void Appl::addOption(const char* name, const char* shortname, OptVal optval, + DataType datatype, OptionType optiontype, const char* description) { - if (strlen(name) != 0) - m_params[name] = param; + if (strlen(name) != 0) { - if (strlen(longname) != 0) { - Arg arg; - arg.name = name; - arg.shortname = shortname; - arg.longname = longname; - arg.description = description; - arg.datatype = datatype; - arg.optiontype = optiontype; - m_args.push_back(arg); + m_optvals[name] = optval; + + opt_t opt; + opt.name = name; + opt.shortname = shortname; + opt.datatype = datatype; + opt.optiontype = optiontype; + opt.description = description; + m_opts.push_back(opt); } } -void Appl::printArgs() -{ - std::cerr << std::endl << "Usage:" << std::endl << " " - << m_argv[0].substr(m_argv[0].find_last_of("/\\") + 1) << " [OPTIONS...]" ; - - if (m_argTxt.size() != 0) - std::cerr << " " << m_argTxt; - - std::cerr << std::endl << std::endl << "Options:" << std::endl << std::endl; - - for (a_it = m_args.begin(); a_it < m_args.end(); a_it++) { - const char* c = (strlen(a_it->shortname) == 1) ? a_it->shortname : " "; - std::cerr << ((strcmp(c, " ") == 0) ? " " : "-") << c - << " | --" << a_it->longname - << "\t" << a_it->description - << std::endl; - } - - std::cerr << std::endl; -} - -bool Appl::parseArgs(int argc, char* argv[]) +void Appl::parseArgs(int argc, char* argv[]) { std::vector _argv(argv, argv + argc); - m_argc = argc; m_argv = _argv; - for (size_t i = 1; i < m_argc; i++) { + // walk through all arguments + for (int i = 1; i < argc; i++) { // find option with long format '--' - if (m_argv[i].rfind("--") == 0 && m_argv[i].size() > 2) { + if (_argv[i].rfind("--") == 0 && _argv[i].size() > 2) { + // is next item an added argument? - if (i+1 < m_argc && m_argv[i+1].rfind("-", 0) == std::string::npos) { - if (checkArg(m_argv[i].substr(2), m_argv[i+1]) == false) - return false; - } else { - if (checkArg(m_argv[i].substr(2), "") == false) - return false; + if (i+1 < argc && _argv[i+1].rfind("-", 0) == std::string::npos) { + if (checkOption(_argv[i].substr(2), _argv[i+1]) == false) + printHelp(); + } + else { + if (checkOption(_argv[i].substr(2), "") == false) + printHelp(); } // find option with short format '-' - } else if (m_argv[i].rfind("-") == 0 && m_argv[i].size() > 1) { + } else if (_argv[i].rfind("-") == 0 && _argv[i].size() > 1) { // walk through all characters - for (size_t j = 1; j < m_argv[i].size(); j++) { + for (size_t j = 1; j < _argv[i].size(); j++) { // only last charater could have an argument - if (i+1 < m_argc && m_argv[i+1].rfind("-", 0) == std::string::npos - && j+1 == m_argv[i].size()) { - if (checkArg(m_argv[i].substr(j,1), m_argv[i+1]) == false) - return false; - } else { - if (checkArg(m_argv[i].substr(j,1), "") == false) - return false; + if (i+1 < argc && _argv[i+1].rfind("-", 0) == std::string::npos + && j+1 == _argv[i].size()) { + if (checkOption(_argv[i].substr(j,1), _argv[i+1]) == false) + printHelp(); + } + else { + if (checkOption(_argv[i].substr(j,1), "") == false) + printHelp(); } } } } - // check args - if (m_argNum > 0) { - if (m_argc < (m_argNum + 1)) - return false; + // check command + if (m_needCommand == true) { + for (int i = 1; i < argc; i++) { - for (size_t i = 1; i < m_argc; i++) { - - if (m_argv[i].rfind("-", 0) != std::string::npos) { + if (_argv[i].rfind("-", 0) != std::string::npos) { i++; continue; } - m_argValues.push_back(m_argv[i]); + m_arguments.push_back(_argv[i]); } - if (m_argValues.size() < m_argNum) - return false; + if (m_arguments.size() == 0) { + std::cerr << std::endl << "command needed" << std::endl; + printHelp(); + } } - return true; } -void Appl::printSettings() +bool Appl::checkOption(const std::string& option, const std::string& value) { - std::cerr << std::endl << "Settings:" << std::endl; + if (strcmp(option.c_str(), "settings") == 0) + printSettings(); - for (a_it = m_args.begin(); a_it < m_args.end(); a_it++) { - const char* c = (strlen(a_it->shortname) == 1) ? a_it->shortname : " "; - std::cerr << ((strcmp(c, " ") == 0) ? " " : "-") << c - << " | --" << a_it->longname - << " = "; - if (a_it->datatype == type_bool) { - if (getParam(a_it->name) == true) - std::cerr << "yes" << std::endl; - else - std::cerr << "no" << std::endl; - } - else if (a_it->datatype == type_int) { - std::cerr << getParam(a_it->name) << std::endl; - } - else if (a_it->datatype == type_long) { - std::cerr << getParam(a_it->name) << std::endl; - } - else if (a_it->datatype == type_float) { - std::cerr << getParam(a_it->name) << std::endl; - } - else if (a_it->datatype == type_string) { - std::cerr << getParam(a_it->name) << std::endl; - } + if (strcmp(option.c_str(), "v") == 0 || strcmp(option.c_str(), "version") == 0) + printVersion(); - } + if (strcmp(option.c_str(), "h") == 0 || strcmp(option.c_str(), "help") == 0) + printHelp(); - std::cerr << std::endl; -} + for (o_it = m_opts.begin(); o_it < m_opts.end(); o_it++) { + if (o_it->shortname == option || o_it->name == option) { -bool Appl::checkArg(const std::string& name, const std::string& arg) -{ - for (a_it = m_args.begin(); a_it < m_args.end(); a_it++) { - if (a_it->shortname == name || a_it->longname == name) { - if (a_it->optiontype == opt_mandatory && arg.size() == 0) { + // need this option and argument? + if (o_it->optiontype == ot_mandatory && value.size() == 0) { std::cerr << std::endl << "option requires an argument '" - << name << "'" << std::endl; + << option << "'" << std::endl; return false; } - if ((a_it->optiontype == opt_optional && arg.size() != 0) - || a_it->optiontype != opt_optional) - addParam(a_it->name, arg, a_it->datatype); + // add given value to option + if ((o_it->optiontype == ot_optional && value.size() != 0) + || o_it->optiontype != ot_optional) + setOptVal(o_it->name, value, o_it->datatype); return true; } } - std::cerr << m_argv[0].substr(2) << ": Unknown Option -- " << name << std::endl; + std::cerr << std::endl << "unknown option '" << option << "'" << std::endl; return false; } -void Appl::addParam(const char* name, const std::string arg, Datatype datatype) +void Appl::setOptVal(const char* option, const std::string value, DataType datatype) { switch (datatype) { - case type_bool: - m_params[name] = true; + case dt_bool: + m_optvals[option] = true; break; - case type_int: - m_params[name] = strtol(arg.c_str(), NULL, 10); + case dt_int: + m_optvals[option] = strtol(value.c_str(), NULL, 10); break; - case type_long: - m_params[name] = strtol(arg.c_str(), NULL, 10); + case dt_long: + m_optvals[option] = strtol(value.c_str(), NULL, 10); break; - case type_float: - m_params[name] = static_cast(strtod(arg.c_str(), NULL)); + case dt_float: + m_optvals[option] = static_cast(strtod(value.c_str(), NULL)); break; - case type_string: - m_params[name] = arg.c_str(); + case dt_string: + m_optvals[option] = value.c_str(); break; default: break; } } +void Appl::printVersion() +{ + std::cerr << m_version << std::endl; + exit(EXIT_SUCCESS); +} +void Appl::printHelp() +{ + std::cerr << std::endl << "Usage:" << std::endl << " " + << m_argv[0].substr(m_argv[0].find_last_of("/\\") + 1) << " [OPTIONS...]" ; + + if (m_needCommand == true) + std::cerr << " COMMAND {ARGS...}" << std::endl << std::endl; + else + std::cerr << std::endl << std::endl; + + for (o_it = m_opts.begin(); o_it < m_opts.end(); o_it++) { + if (strcmp(o_it->name, "__text_only__") == 0) + std::cerr << o_it->description << std::endl; + else { + const char* c = (strlen(o_it->shortname) == 1) ? o_it->shortname : " "; + std::cerr << ((strcmp(c, " ") == 0) ? " " : "-") << c + << " | --" << o_it->name + << "\t" << o_it->description + << std::endl; + } + } + + std::cerr << " | --settings\n-v | --version\n-h | --help" << std::endl << std::endl; + exit(EXIT_SUCCESS); +} + +void Appl::printSettings() +{ + std::cerr << std::endl << "Settings:" << std::endl << std::endl; + + for (o_it = m_opts.begin(); o_it < m_opts.end(); o_it++) { + if (strcmp(o_it->name, "__text_only__") == 0) + continue; + + const char* c = (strlen(o_it->shortname) == 1) ? o_it->shortname : " "; + std::cerr << ((strcmp(c, " ") == 0) ? " " : "-") << c + << " | --" << o_it->name + << " = "; + if (o_it->datatype == dt_bool) { + if (getOptVal(o_it->name) == true) + std::cerr << "yes" << std::endl; + else + std::cerr << "no" << std::endl; + } + else if (o_it->datatype == dt_int) { + std::cerr << getOptVal(o_it->name) << std::endl; + } + else if (o_it->datatype == dt_long) { + std::cerr << getOptVal(o_it->name) << std::endl; + } + else if (o_it->datatype == dt_float) { + std::cerr << getOptVal(o_it->name) << std::endl; + } + else if (o_it->datatype == dt_string) { + std::cerr << getOptVal(o_it->name) << std::endl; + } + + } + + std::cerr << std::endl; + exit(EXIT_SUCCESS); +} diff --git a/src/lib/utils/appl.h b/src/lib/utils/appl.h index d9684644..2a04bb11 100644 --- a/src/lib/utils/appl.h +++ b/src/lib/utils/appl.h @@ -17,96 +17,187 @@ * along with ebusd. If not, see http://www.gnu.org/licenses/. */ -#ifndef LIBCORE_APPL_H_ -#define LIBCORE_APPL_H_ +#ifndef LIBUTILS_APPL_H_ +#define LIBUTILS_APPL_H_ #include #include #include #include +/** the available data types. */ +enum DataType { + dt_none, // default value + dt_bool, // + dt_int, // + dt_long, // + dt_float, // + dt_string, // +}; + +/** option types. */ +enum OptionType { + ot_none, // default value + ot_optional, // a value is optional + ot_mandatory, // a value is mandatory +}; + +/** structure for defining application options */ +typedef struct opt { + const char* name; + const char* shortname; + const char* description; + DataType datatype; + OptionType optiontype; +} opt_t; + +/** union for option values */ +union OptVal { + bool b; + int i; + long l; + float f; + const char* c; + + OptVal() { memset(this, 0, sizeof(OptVal)); } + OptVal(bool _b) : b(_b) {} + OptVal(int _i) : i(_i) {} + OptVal(long _l) : l(_l) {} + OptVal(float _f) : f(_f) {} + OptVal(const char* _c) : c(_c) {} +}; + + +/** + * @brief class for all kinds of application parameters. + */ class Appl { -private: - struct Option; - public: - enum Datatype { type_none, type_bool, type_int, type_long, type_float, type_string }; - enum Optiontype { opt_none, opt_optional, opt_mandatory }; - - union Param { - bool b; - int i; - long l; - float f; - const char* c; - - Param() { memset(this, 0, sizeof(Param)); } - Param(bool _b) : b(_b) {} - Param(int _i) : i(_i) {} - Param(long _l) : l(_l) {} - Param(float _f) : f(_f) {} - Param(const char* _c) : c(_c) {} - }; - - template - T getParam(const char* name) - { - p_it = m_params.find(name); - return (reinterpret_cast(p_it->second)); - } - - static Appl& Instance(); + /** + * @brief create an instance and return the reference. + * @param command is true if an command is needed. + * @return the reference to instance. + */ + static Appl& Instance(const bool command=false); + /** + * @brief destructor. + */ ~Appl(); - void addArgs(const std::string argTxt, const int argNum); - size_t numArg() const { return m_argValues.size(); } - std::string getArg(const int argNum) const { return m_argValues[argNum]; } + /** + * @brief save application version string. + * @param version string. + */ + void setVersion(const char* version) { m_version = version; } - void addItem(const char* name, Param param, const char* shortname, - const char* longname, const char* description, - Datatype datatype, Optiontype optiontype); + /** + * @brief create new entry of application option only for help page. + * @param text string to print. + */ + void addText(const char* text); - void printArgs(); + /** + * @brief create new entry of application option. + * @param name the long name. + * @param shortname optional short name. + * @param optval value of option. + * @param datatype data type of option value. + * @param optiontype type of given option. + * @param description hint text for help page. + */ + void addOption(const char* name, const char* shortname, OptVal optval, + DataType datatype, OptionType optiontype, const char* description); - bool parseArgs(int argc, char* argv[]); - void printSettings(); + /** + * @brief returns the value of the interested option. + * @param name the interested option. + * @return casted value. + */ + template + T getOptVal(const char* name) + { + ov_it = m_optvals.find(name); + return (reinterpret_cast(ov_it->second)); + } + + /** + * @brief parse application arguments. + * @param argc the number of options. + * @param argv the given options. + */ + void parseArgs(int argc, char* argv[]); + + /** + * @brief returns the number of saved commands and arguments. + * @return number of commands and arguments. + */ + int numArgs() const { return m_arguments.size(); } + + /** + * @brief returns the string of an interested argument (0 = command). + * @param num number of interested argument. + * @return string value. + */ + std::string getArg(const int num) const { return m_arguments[num]; } private: - Appl() {} + /** private constructor - singleton pattern */ + Appl(const bool command) : m_needCommand(command) {} Appl(const Appl&); - Appl& operator= (const Appl&); + Appl& operator=(const Appl&); - struct Arg { - const char* name; - const char* shortname; - const char* longname; - const char* description; - Datatype datatype; - Optiontype optiontype; - }; + /** application options */ + std::vector m_opts; + std::vector::const_iterator o_it; - size_t m_argc; + /** map option - value */ + std::map m_optvals; + std::map::iterator ov_it; + + /** given arguments */ std::vector m_argv; - std::vector m_args; - std::vector::const_iterator a_it; + /** application version string */ + const char* m_version; - std::map m_params; - std::map::iterator p_it; + /** true if the application need a command */ + bool m_needCommand; - std::string m_argTxt; - size_t m_argNum; + /** arguments (argument 0 = command) string */ + std::vector m_arguments; - std::vector m_argValues; + /** + * @brief checks the passed parameter if this is a valid option. + * @param option to check. + * @param value to save if paramter is a valid option. + */ + bool checkOption(const std::string& option, const std::string& value); - bool checkArg(const std::string& name, const std::string& arg); + /** + * @brief save the passed value to option. + * @param option name. + * @param value to save. + * @param datatype of given option. + */ + void setOptVal(const char* option, const std::string value, DataType datatype); - void addParam(const char* name, Param param) { m_params[name] = param; } + /** + * @brief print application version. + */ + void printVersion(); - void addParam(const char* name, const std::string arg, Datatype datatype); + /** + * @brief print help page. + */ + void printHelp(); + + /** + * @brief print used option settings. + */ + void printSettings(); }; -#endif // LIBCORE_APPL_H_ +#endif // LIBUTILS_APPL_H_ diff --git a/src/lib/utils/daemon.cpp b/src/lib/utils/daemon.cpp index 18c35a3e..36ecd155 100644 --- a/src/lib/utils/daemon.cpp +++ b/src/lib/utils/daemon.cpp @@ -32,10 +32,10 @@ Daemon& Daemon::Instance() return instance; } -void Daemon::run(const char* file) +void Daemon::run(const char* pidfile) { m_status = false; - m_pidfile = file; + m_pidfile = pidfile; m_pidfd = 0; pid_t pid; diff --git a/src/lib/utils/daemon.h b/src/lib/utils/daemon.h index 37ac41b3..d7f3fdbd 100644 --- a/src/lib/utils/daemon.h +++ b/src/lib/utils/daemon.h @@ -17,32 +17,66 @@ * along with ebusd. If not, see http://www.gnu.org/licenses/. */ -#ifndef LIBCORE_DAEMON_H_ -#define LIBCORE_DAEMON_H_ +#ifndef LIBUTILS_DAEMON_H_ +#define LIBUTILS_DAEMON_H_ +/** + * @brief class to daemonize a process. + */ class Daemon { public: + /** + * @brief create an instance and return the reference. + * @return the reference to instance. + */ static Daemon& Instance(); - ~Daemon() {} - void run(const char* file); + /** + * @brief daemonize act process. + * @param pidfile the name of the pid file. + */ + void run(const char* pidfile); + + /** + * @brief stop daemon and delete the pid file. + */ void stop() { pidfile_close(); } + + /** + * @brief show actual status if daemonize. + * @return true if process is a daemon. + */ bool status() { return m_status; } private: - bool m_status; - const char* m_pidfile; - int m_pidfd; - + /** private constructor - singleton pattern */ Daemon() {} Daemon(const Daemon&); - Daemon& operator= (const Daemon&); + Daemon& operator=(const Daemon&); + /** status of process; true if we are a daemon */ + bool m_status; + + /** name of the pid file*/ + const char* m_pidfile; + + /** file descriptor of the pid file */ + int m_pidfd; + + /** + * @brief creates a pid file for process. + * @return true if success. + */ bool pidfile_open(); + + /** + * @brief close and delete the pid file. + * @return true if success. + */ bool pidfile_close(); }; -#endif // LIBCORE_DAEMON_H_ +#endif // LIBUTILS_DAEMON_H_ diff --git a/src/lib/utils/logger.cpp b/src/lib/utils/logger.cpp index c6708a7a..706cd129 100644 --- a/src/lib/utils/logger.cpp +++ b/src/lib/utils/logger.cpp @@ -28,7 +28,10 @@ #include #include +/** static char array with logging area names */ static const char* AreaNames[Size_of_Areas] = { "bas", "net", "bus" }; + +/** static char array with logging level names */ static const char* LevelNames[Size_of_Level] = { "error", "event", "trace", "debug" }; int calcAreas(const std::string areas) @@ -66,8 +69,8 @@ int calcLevel(const std::string level) } -LogMessage::LogMessage(const int area, const int level, const std::string text, const Status status) - : m_area(area), m_level(level), m_text(text), m_status(status) +LogMessage::LogMessage(const int area, const int level, const std::string text, const bool running) + : m_area(area), m_level(level), m_text(text), m_running(running) { char time[24]; struct timeval tv; @@ -89,17 +92,17 @@ LogMessage::LogMessage(const int area, const int level, const std::string text, void LogSink::addMessage(const LogMessage& message) { LogMessage* tmp = new LogMessage(LogMessage(message)); - m_queue.add((tmp)); + m_logQueue.add((tmp)); } void* LogSink::run() { while (1) { - LogMessage* message = m_queue.remove(); - if (message->getStatus() == LogMessage::End) { + LogMessage* message = m_logQueue.remove(); + if (message->isRunning() == false) { delete message; - while (m_queue.size() == true) { - LogMessage* message = m_queue.remove(); + while (m_logQueue.size() == true) { + LogMessage* message = m_logQueue.remove(); write(*message); delete message; } @@ -114,8 +117,6 @@ void* LogSink::run() -int LogConsole::m_numInstance = 0; - void LogConsole::write(const LogMessage& message) const { std::cout << message.getTime() << " [" @@ -126,11 +127,9 @@ void LogConsole::write(const LogMessage& message) const -int LogFile::m_numInstance = 0; - void LogFile::write(const LogMessage& message) const { - std::fstream file(m_filename.c_str(), std::ios::out | std::ios::app); + std::fstream file(m_file.c_str(), std::ios::out | std::ios::app); if (file.is_open() == true) { file << message.getTime() << " [" @@ -143,19 +142,19 @@ void LogFile::write(const LogMessage& message) const -LogInstance& LogInstance::Instance() +Logger& Logger::Instance() { - static LogInstance instance; + static Logger instance; return (instance); } -LogInstance::~LogInstance() +Logger::~Logger() { while (m_sinks.empty() == false) *this -= *(m_sinks.begin()); } -LogInstance& LogInstance::operator+= (LogSink* sink) +Logger& Logger::operator+=(LogSink* sink) { sinkCI_t itEnd = m_sinks.end(); sinkCI_t it = std::find(m_sinks.begin(), itEnd, sink); @@ -166,7 +165,7 @@ LogInstance& LogInstance::operator+= (LogSink* sink) return (*this); } -LogInstance& LogInstance::operator-= (const LogSink* sink) +Logger& Logger::operator-=(const LogSink* sink) { sinkCI_t itEnd = m_sinks.end(); sinkCI_t it = std::find(m_sinks.begin(), itEnd, sink); @@ -181,7 +180,7 @@ LogInstance& LogInstance::operator-= (const LogSink* sink) return (*this); } -void LogInstance::log(const int area, const int level, const std::string& data, ...) +void Logger::log(const int area, const int level, const std::string& data, ...) { if (m_running == true) { char* tmp; @@ -190,7 +189,7 @@ void LogInstance::log(const int area, const int level, const std::string& data, if (vasprintf(&tmp, data.c_str(), ap) != -1) { std::string buffer(tmp); - m_messages.add(new LogMessage(LogMessage(area, level, buffer, LogMessage::Run))); + m_logQueue.add(new LogMessage(area, level, buffer)); } va_end(ap); @@ -199,12 +198,12 @@ void LogInstance::log(const int area, const int level, const std::string& data, } -void* LogInstance::run() +void* Logger::run() { m_running = true; while (m_running == true) { - LogMessage* message = m_messages.remove(); + LogMessage* message = m_logQueue.remove(); sinkCI_t iter = m_sinks.begin(); @@ -213,13 +212,15 @@ void* LogInstance::run() if (((*iter)->getAreas() & message->getArea() && (*iter)->getLevel() >= message->getLevel()) - && message->getStatus() == LogMessage::Run) { + && message->isRunning() == true) { (*iter)->addMessage(*message); - } else if (message->getStatus() == LogMessage::End) { + } + else if (message->isRunning() == false) { (*iter)->addMessage(*message); m_running = false; } + } } @@ -229,8 +230,8 @@ void* LogInstance::run() return NULL; } -void LogInstance::stop() +void Logger::stop() { - m_messages.add(new LogMessage(LogMessage(bas, error, "", LogMessage::End))); + m_logQueue.add(new LogMessage(LogMessage(bas, error, "", false))); usleep(100000); } diff --git a/src/lib/utils/logger.h b/src/lib/utils/logger.h index d704e2c1..f8f56b6b 100644 --- a/src/lib/utils/logger.h +++ b/src/lib/utils/logger.h @@ -17,8 +17,8 @@ * along with ebusd. If not, see http://www.gnu.org/licenses/. */ -#ifndef LIBCORE_LOGGER_H_ -#define LIBCORE_LOGGER_H_ +#ifndef LIBUTILS_LOGGER_H_ +#define LIBUTILS_LOGGER_H_ #include "wqueue.h" #include "thread.h" @@ -28,154 +28,295 @@ #include #include -enum Areas { bas=1, net=2, bus=4, all=7, Size_of_Areas=3 }; -enum Level { error=0, event, trace, debug, Size_of_Level }; +/** available types for all subsystems */ +enum AreasType { + bas=1, // basis + net=2, // network + bus=4, // ebus + all=7, // type for all subsystems + Size_of_Areas=3, // number of possible areas +}; +/** available logging levels */ +enum LevelType { + error=0, // + event, // + trace, // + debug, // + Size_of_Level, // number of possible levels +}; + +/** global function to get calculate logging areas */ int calcAreas(const std::string areas); + +/** global function to get calculate logging level */ int calcLevel(const std::string level); - +/** + * @brief class which describes a logging message itself. + */ class LogMessage { public: - enum Status { Run, End }; - - LogMessage(const int area, const int level, const std::string text, const Status status); - - ~LogMessage() {} - - LogMessage(const LogMessage& src) - : m_area(src.m_area), m_level(src.m_level), m_text(src.m_text), - m_status(src.m_status), m_time(src.m_time) {} - - void operator= (const LogMessage& src) - { m_area = src.m_area; m_level = src.m_level; m_text = src.m_text; - m_status = src.m_status; m_time = src.m_time; } + /** + * @brief creates a new logging message. + * @param area the logging area of the message. + * @param level the logging level of the message. + * @param text the logging message. + * @param running the status of logging subsystem. + */ + LogMessage(const int area, const int level, const std::string text, const bool running=true); + /** + * @brief get the logging area. + * @return the logging area. + */ int getArea() const { return (m_area); } + + /** + * @brief get the logging level. + * @return the logging level. + */ int getLevel() const { return(m_level); } + + /** + * @brief get the logging text. + * @return the logging text. + */ std::string getText() const { return (m_text.c_str()); } - Status getStatus() const { return (m_status); } + + /** + * @brief status of logging subsystem. + * @return false if logging subsystem is going down. + */ + bool isRunning() const { return m_running; } + + /** + * @brief get the logging timestamp. + * @return the logging timestamp. + */ std::string getTime() const { return (m_time.c_str()); } private: + /** the logging area */ int m_area; + + /** the logging level */ int m_level; + + /** the logging message */ std::string m_text; - Status m_status; + + /** true if this instance is running */ + bool m_running; + + /** the logging timestamp */ std::string m_time; }; -enum Type { Console, Logfile }; - +/** + * @brief base class for all type of logging sinks. + */ class LogSink : public Thread { public: - LogSink(const int areas, const int level, const Type type, const char* name) - : m_areas(areas), m_level(level), m_type(type), m_name(name) {} - - virtual ~LogSink() {} + /** + * @brief creates a virtual logging sink. + * @param areas the logging areas. + * @param level the logging level. + */ + LogSink(const int areas, const int level) : m_areas(areas), m_level(level) {} + /** + * @brief adds the logging message to internal message queue. + * @param message a reference to logging message. + */ void addMessage(const LogMessage& message); + /** + * @brief endless loop for logging sink instance. + * @return void pointer. + */ void* run(); + /** + * @brief get the logging areas. + * @return the logging areas. + */ int getAreas() const { return (m_areas); } + + /** + * @brief set the logging areas. + * @param areas the logging areas. + */ void setAreas(const int& areas) { m_areas = areas; } + /** + * @brief get the logging level. + * @return the logging level. + */ int getLevel() const { return (m_level); } + + /** + * @brief set the logging level. + * @param level the logging level. + */ void setLevel(const int& level) { m_level = level; } - Type getType() const { return (m_type); } - const char* getName() const { return (m_name.c_str()); } - protected: - WQueue m_queue; + /** queue for logging messages */ + WQueue m_logQueue; private: + /** the logging areas */ int m_areas; - int m_level; - Type m_type; - std::string m_name; + /** the logging level */ + int m_level; + + /** + * @brief virtual function for writing the logging message. + * @param message the logging message. + */ virtual void write(const LogMessage& message) const = 0; }; +/** + * @brief class for console logging sink type. + */ class LogConsole : public LogSink { public: + /** + * @brief creates a console logging sink. + * @param areas the logging areas. + * @param level the logging level. + * @param name the thread name for logging sink. + */ LogConsole(const int areas, const int level, const char* name) - : LogSink(areas, level, Console, name), m_instance(++m_numInstance) - { this->start(name); } - - ~LogConsole() {} + : LogSink(areas, level) { this->start(name); } private: - const int m_instance; - static int m_numInstance; - + /** + * @brief write the logging message to stdout. + * @param message the logging message. + */ void write(const LogMessage& message) const; }; +/** + * @brief class for logfile logging sink type. + */ class LogFile : public LogSink { public: - LogFile(const int areas, const int level, const char* name, const char* filename) - : LogSink(areas, level, Logfile, name), m_filename(filename), m_instance(++m_numInstance) - { this->start(name); } - - ~LogFile() {} + /** + * @brief creates a log file logging sink. + * @param areas the logging areas. + * @param level the logging level. + * @param name the thread name for logging sink. + * @param file the log file. + */ + LogFile(const int areas, const int level, const char* name, const char* file) + : LogSink(areas, level), m_file(file) { this->start(name); } private: - std::string m_filename; - const int m_instance; - static int m_numInstance; + /** the logging file */ + std::string m_file; + /** + * @brief write the logging message to specific log file. + * @param message the logging message. + */ void write(const LogMessage& message) const; }; -class LogInstance : public Thread +/** + * @brief logger base class which provide the logging interface. + */ +class Logger : public Thread { public: - static LogInstance& Instance(); + /** + * @brief create an instance and return the reference. + * @return the reference to instance. + */ + static Logger& Instance(); - ~LogInstance(); + /** + * @brief destructor. + */ + ~Logger(); - LogInstance& operator+= (LogSink* sink); - LogInstance& operator-= (const LogSink* sink); + /** + * @brief adds a logging sink and returns the reference to logger. + * @param pointer of logging sink. + * @return the reference to logger. + */ + Logger& operator+=(LogSink* sink); + /** + * @brief removes a logging sink and returns the reference to logger. + * @param pointer of logging sink. + * @return the reference to logger. + */ + Logger& operator-=(const LogSink* sink); + + /** + * @brief creates a logging message and add them to internal message queue. + * @param area the logging area of the message. + * @param level the logging level of the message. + * @param text the logging message. + * @param ... possible 'variable argument lists'. + */ void log(const int area, const int level, const std::string& text, ...); - int getNumberOfSinks() const { return(m_sinks.size()); } - LogSink* getSink(const int Index) const { return(m_sinks[Index]); } + /** + * @brief returns the sink at the specified index. + * @param index the index of the sink to return. + * @return the sink at the specified index. + */ + LogSink* getSink(const int index) const { return(m_sinks[index]); } + /** + * @brief endless loop for logger instance. + * @return void pointer. + */ void* run(); + /** + * @brief shutdown logger subsystem. + */ void stop(); private: - LogInstance() {} - LogInstance(const LogInstance&); - LogInstance& operator= (const LogInstance&); + /** private constructor - singleton pattern */ + Logger() {} + Logger(const Logger&); + Logger& operator=(const Logger&); + /** typedefs for a vector of type LogSink* */ typedef std::vector sink_t; typedef std::vector::iterator sinkCI_t; + /** vector of available logging sinks */ sink_t m_sinks; - WQueue m_messages; + /** queue for logging messages */ + WQueue m_logQueue; + /** true if this instance is running */ bool m_running; }; -#endif // LIBCORE_LOGGER_H_ +#endif // LIBUTILS_LOGGER_H_ diff --git a/src/ebusd/message.h b/src/lib/utils/notify.cpp similarity index 63% rename from src/ebusd/message.h rename to src/lib/utils/notify.cpp index 8344643e..d9416162 100644 --- a/src/ebusd/message.h +++ b/src/lib/utils/notify.cpp @@ -17,27 +17,26 @@ * along with ebusd. If not, see http://www.gnu.org/licenses/. */ -#ifndef MESSAGE_H_ -#define MESSAGE_H_ +#include "notify.h" -#include - - -class Message +Notify::Notify() { + int pipefd[2]; + int ret = pipe(pipefd); -public: - Message(const std::string data, void* source = NULL) : m_data(data), m_source(source) {} - Message(const Message& src) : m_data(src.m_data), m_source(src.m_source) {} + if (ret == 0) { + m_recvfd = pipefd[0]; + m_sendfd = pipefd[1]; - std::string getData() const { return m_data; } - void* getSource() const { return m_source; } + fcntl(m_sendfd, F_SETFL, O_NONBLOCK); + } -private: - std::string m_data; - void* m_source; +} -}; +Notify::~Notify() +{ + close(m_sendfd); + close(m_recvfd); +} -#endif // MESSAGE_H_ diff --git a/src/lib/utils/notify.h b/src/lib/utils/notify.h index 91909662..188040a1 100644 --- a/src/lib/utils/notify.h +++ b/src/lib/utils/notify.h @@ -17,40 +17,50 @@ * along with ebusd. If not, see http://www.gnu.org/licenses/. */ -#ifndef LIBCORE_NOTIFY_H_ -#define LIBCORE_NOTIFY_H_ +#ifndef LIBUTILS_NOTIFY_H_ +#define LIBUTILS_NOTIFY_H_ #include #include +/** + * @brief class to notify other thread per pipe. + */ class Notify { public: - Notify() - { - int pipefd[2]; - int ret = pipe(pipefd); + /** + * @brief constructs a new instance and do notifying. + */ + Notify(); - if (ret == 0) { - m_recvfd = pipefd[0]; - m_sendfd = pipefd[1]; + /** + * @brief destructor. + */ + ~Notify(); - fcntl(m_sendfd, F_SETFL, O_NONBLOCK); - } + /** + * @brief file descriptor to watch for notify event. + * @return the notification value. + */ + int notifyFD() { return m_recvfd; } - } - virtual ~Notify() { close(m_sendfd); close(m_recvfd); } - - int notifyFD() const { return m_recvfd; } + /** + * @brief write notify event to file descriptor. + * @return result of writing notification. + */ int notify() const { return write(m_sendfd,"1",1); } private: - int m_recvfd; - int m_sendfd; + /** file descriptor to watch */ + int m_recvfd; + + /** file descriptor to notify */ + int m_sendfd; }; -#endif // LIBCORE_NOTIFY_H_ +#endif // LIBUTILS_NOTIFY_H_ diff --git a/src/lib/utils/tcpsocket.cpp b/src/lib/utils/tcpsocket.cpp index 627d0d3c..eb06454e 100644 --- a/src/lib/utils/tcpsocket.cpp +++ b/src/lib/utils/tcpsocket.cpp @@ -19,11 +19,7 @@ #include "tcpsocket.h" #include -#include -#include -#include #include -#include #include #include #include diff --git a/src/lib/utils/tcpsocket.h b/src/lib/utils/tcpsocket.h index 335cfb64..f7861bdb 100644 --- a/src/lib/utils/tcpsocket.h +++ b/src/lib/utils/tcpsocket.h @@ -17,72 +17,155 @@ * along with ebusd. If not, see http://www.gnu.org/licenses/. */ -#ifndef LIBCORE_TCPSOCKET_H_ -#define LIBCORE_TCPSOCKET_H_ +#ifndef LIBUTILS_TCPSOCKET_H_ +#define LIBUTILS_TCPSOCKET_H_ -#include -#include #include #include +/** + * @brief class for low level tcp socket operations. (open, close, send, receive). + */ class TCPSocket { public: + /** grant access for friend classes */ friend class TCPClient; friend class TCPServer; + /** + * @brief destructor. + */ ~TCPSocket() { close(m_sfd); } - ssize_t recv(char* buffer, size_t len) { return read(m_sfd, buffer, len); } + /** + * @brief write bytes to opened file descriptor. + * @param buffer data to send. + * @param len number of bytes to send. + * @return number of written bytes or -1 if an error has occured. + */ ssize_t send(const char* buffer, size_t len) { return write(m_sfd, buffer, len); } + /** + * @brief read bytes from opened file descriptor. + * @param buffer for received bytes. + * @param len size of the receive buffer. + * @return number of read bytes or -1 if an error has occured. + */ + ssize_t recv(char* buffer, size_t len) { return read(m_sfd, buffer, len); } + + /** + * @brief returns the tcp port. + * @return the tcp port. + */ int getPort() const { return m_port; } + + /** + * @brief returns the ip address. + * @return the ip address. + */ std::string getIP() const { return m_ip; } + /** + * @brief returns the file descriptor. + * @return the file descriptor. + */ int getFD() const { return m_sfd; } + + /** + * @brief returns status of file descriptor. + * @return true if file descriptor is valid. + */ bool isValid(); private: + /** file descriptor from tcp socket */ int m_sfd; + + /** port of tcp socket */ int m_port; + + /** ip address of tcp socket */ std::string m_ip; + /** + * @brief private constructor, limited access only for friend classes. + * @param sfd the file desctriptor of tcp socket. + * @param address struct which holds the ip address. + */ TCPSocket(int sfd, struct sockaddr_in* address); }; +/** + * @brief class to initiate a tcp socket connection to a listening server. + */ class TCPClient { public: + /** + * @brief initiate a tcp socket connection to a listening server. + * @param server the server name or ip address to connect. + * @param port the tcp port. + * @return pointer to an opened tcp socket. + */ TCPSocket* connect(const std::string& server, const int& port); -private: - }; +/** + * @brief class for a tcp based network server. + */ class TCPServer { public: + /** + * @brief creates a new instance of a listening tcp server. + * @param port the tcp port. + * @param address the ip address. + */ TCPServer(const int port, const std::string address) : m_lfd(0), m_port(port), m_address(address), m_listening(false) {} + /** + * @brief destructor. + */ ~TCPServer() { if (m_lfd > 0) {close(m_lfd);} } + /** + * @brief start listening of tcp socket. + */ int start(); + + /** + * @brief accept an incomming tcp connection and create a local tcp socket for communication. + * @return pointer to an opened tcp socket. + */ TCPSocket* newSocket(); + /** + * @brief returns the file descriptor. + * @return the file descriptor. + */ int getFD() const { return m_lfd; } private: + /** file descriptor from listening tcp socket */ int m_lfd; + + /** listening tcp port */ int m_port; + + /** listening tcp socket ip address */ std::string m_address; + + /** true if object is already listening */ bool m_listening; }; -#endif // LIBCORE_TCPSOCKET_H_ +#endif // LIBUTILS_TCPSOCKET_H_ diff --git a/src/lib/utils/thread.cpp b/src/lib/utils/thread.cpp index 48dbc250..4ea84136 100644 --- a/src/lib/utils/thread.cpp +++ b/src/lib/utils/thread.cpp @@ -17,11 +17,19 @@ * along with ebusd. If not, see http://www.gnu.org/licenses/. */ +#ifdef HAVE_CONFIG_H +#include +#endif + #include "thread.h" +/** + * @brief static function which will be called on thread startup. + * @return void pointer. + */ static void* runThread(void* arg) { - return ((Thread *)arg)->run(); + return ((Thread*)arg)->run(); } Thread::~Thread() @@ -39,7 +47,11 @@ int Thread::start(const char* name) int result = pthread_create(&m_threadid, NULL, runThread, this); if (result == 0) { + +#ifdef HAVE_PTHREAD_SETNAME_NP pthread_setname_np(m_threadid, name); +#endif + m_running = true; } diff --git a/src/lib/utils/thread.h b/src/lib/utils/thread.h index 913735a3..e18e4062 100644 --- a/src/lib/utils/thread.h +++ b/src/lib/utils/thread.h @@ -17,30 +17,69 @@ * along with ebusd. If not, see http://www.gnu.org/licenses/. */ -#ifndef LIBCORE_THREAD_H_ -#define LIBCORE_THREAD_H_ +#ifndef LIBUTILS_THREAD_H_ +#define LIBUTILS_THREAD_H_ #include +/** + * @brief wrapper class for pthread. + */ class Thread { public: + /** + * @brief constructor. + */ Thread() : m_threadid(0), m_running(false), m_detached(false) {} + + /** + * @brief virtual destructor. + */ virtual ~Thread(); + /** + * @brief create the thread and set name for process list. + * @param name the thread name which show in process list. + * @return value of thread creating. + */ int start(const char* name); + + /** + * @brief join the thread. + * @return value of thread joining. + */ int join(); + + /** + * @brief detach the thread. + * @return value of thread detaching. + */ int detach(); + + /** + * @brief return the thread id. + * @return own thread id. + */ pthread_t self() {return m_threadid; } + /** + * @brief virtul function which must be implemented in derived class. + * @return void pointer. + */ virtual void* run() = 0; private: + /** own thread id */ pthread_t m_threadid; + + /** true if thread is running */ bool m_running; + + /** true if thread is detached */ bool m_detached; }; -#endif // LIBCORE_THREAD_H_ +#endif // LIBUTILS_THREAD_H_ diff --git a/src/lib/utils/wqueue.h b/src/lib/utils/wqueue.h index 0509b87e..468885a4 100644 --- a/src/lib/utils/wqueue.h +++ b/src/lib/utils/wqueue.h @@ -17,28 +17,42 @@ * along with ebusd. If not, see http://www.gnu.org/licenses/. */ -#ifndef LIBCORE_WQUEUE_H_ -#define LIBCORE_WQUEUE_H_ +#ifndef LIBUTILS_WQUEUE_H_ +#define LIBUTILS_WQUEUE_H_ #include #include -template class WQueue +/** + * @brief queue class template for all kinds data types with exclusiv lock. + */ +template +class WQueue { public: + /** + * @brief constructs a new instance. + */ WQueue() { pthread_mutex_init(&m_mutex, NULL); pthread_cond_init(&m_cond, NULL); } + /** + * @brief destructor. + */ ~WQueue() { pthread_mutex_destroy(&m_mutex); pthread_cond_destroy(&m_cond); } + /** + * @brief add a new item to the end of queue. + * @param item to add. + */ void add(T item) { pthread_mutex_lock(&m_mutex); @@ -49,6 +63,10 @@ public: pthread_mutex_unlock(&m_mutex); } + /** + * @brief remove the first item from queue. + * @return the item. + */ T remove() { pthread_mutex_lock(&m_mutex); @@ -64,6 +82,10 @@ public: return item; } + /** + * @brief return the first item from queue without remove. + * @return the item. + */ T next() { pthread_mutex_lock(&m_mutex); @@ -78,6 +100,10 @@ public: return item; } + /** + * @brief the number of entries inside queue. + * @return the size. + */ int size() { pthread_mutex_lock(&m_mutex); @@ -90,10 +116,15 @@ public: } private: + /** the queue itself */ std::list m_queue; + + /** mutex variable for exclusive lock */ pthread_mutex_t m_mutex; + + /** condition variable for exclusive lock */ pthread_cond_t m_cond; }; -#endif // LIBCORE_WQUEUE_H_ +#endif // LIBUTILS_WQUEUE_H_