diff --git a/.gitignore b/.gitignore index e7550bf9..1edd1881 100644 --- a/.gitignore +++ b/.gitignore @@ -12,17 +12,14 @@ Makefile.in *.o *.dirstamp /src/ebusd/ebusd -/src/ebusctl/ebusctl +/src/tools/ebusctl +/src/tools/ebusfeed /src/lib/utils/libutils.a /src/lib/ebus/libebus.a -/src/lib/ebus/test/test_bus /src/lib/ebus/test/test_port -/src/lib/ebus/test/test_configfile -/src/lib/ebus/test/test_commands -/src/lib/ebus/test/test_decode -/src/lib/ebus/test/test_encode /src/lib/ebus/test/test_symbol /src/lib/ebus/test/test_data +/src/lib/ebus/test/test_message /docs/Doxyfile /docs/doxyfile.stamp /docs/html diff --git a/ChangeLog b/ChangeLog index e758e4da..0fa7276b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,275 +1 @@ -ebusd - ChangeLog ------------------ - -2014-10-28 Roland Jax -* libebus project merged into ebusd project. - -2014-10-21 Roland Jax -* class EBusLoop: recvBuffer removed. - -2014-10-09 Roland Jax -* class BaseLoop, EBusLoop: polling functionality implemented. -* Version changed from 0.3.0 to 0.4.0 - -2014-10-06 Roland Jax -* class CYCData deleted; functionality is moved into libebus. - -2014-10-03 Roland Jax -* class Logger: minor name changes. -* class CYCData: delCommands fixed. -* class BaseLoop: config option added. (config reload implemented) - -2014-10-02 Roland Jax -* class Network splitted into classes Network and Connection. -* class Message separated from class BaseLoop. -* global Objects (network, commands, ebusloop, cycdata) relocated into - new global Object baseloop. -* class BaseLoop: log option reworked (logarea -> logareas; loglevel -> log level). - -2014-06-26 Roland Jax -* ebusdump merged into ebusctl. - -2014-06-25 Roland Jax -* ebusctl added (includes ebusd_scan and ebusd_send) -* Version changed from 0.2.1 to 0.3.0 - -2014-06-22 Roland Jax -* 'stop' daemon command added. - -2014-06-03 Roland Jax -* ebusd_send, ebusd_scan added. -* class Appl: program arguments parsing improved. -* directories utils->lib and tools->tool renamed. -* Version changed from 0.2.0 to 0.2.1 - -2014-05-11 Roland Jax -* ebus-daemon merged into ebusd. - -2014-05-11 Roland Jax -* Beta-Test for ebus-daemon started. - -2014-01-09 Roland Jax -* Initial commit. - ---- - -2014-03-16: -* Specific vaillant data type "ttm" (time table minutes) added. - (thx hendrikw / KNX Forum) - -2014-02-21: -* fix crash: Create a local copy of the string. (thx Hannes Gredler) -* Some cosmetic changes. - -2014-02-20: -* Missing void declarations in various function parameter added. -* New branch "socket" created. -* Improved ebus device handling to use tcp based device too. - -2014-01-22: -* autogen.sh modified. - -2014-01-05: -* Missing daemon option -n (nodevicecheck) fixed. - -2013-12-07: -* Vaillant configuration files for VWx Heat Pumps added. - -2013-12-04: -* Vaillant configuration files for VR 60/3 added. -* Vaillant configuration files for VR 90/3 changed. -* Vaillant configuration files for CI (Control Interface) added. - -2013-12-02: -* Vaillant configuration files for VPM 30/35 W added. -* Vaillant configuration files for VR 90/3 added. - -2013-12-01: -* New branch "newDataTypes" created. -* More data types (char, int, long, float) added. -* Vaillant configuration filse for VPM 20 S added. - -2013-11-29: -* New daemon option nodevicecheck added. - -2013-11-19: -* Data type of struct commands.s_type changed from integer to char[2]. Possible - data types are: BR, MM, MS. (BroadCast, MasterMaster, MasterSlave) -* Wolf configuration files converted to new version. -* README fixed. - -2013-11-06: -* Specific vaillant data type "ulg" (unsigned long) added. - -2013-09-20: -* Removed unnecessary spaces located behind last return value. (thx JuMi2006 / KNX Forum) -* Removed more unneeded space characters. (thx JuMi2006 / KNX Forum) - -2013-09-04: -* Fixed eb_recv_data_get function. (Replaced strncpy with memcpy.) - -2013-08-26: -* Modified hex decode routine. (To set start/end point of data bytes.) -* Some cosmetic changes. - -2013-05-28: -* Modified timeout statement, too force serial device reconnect. (thx aloz77 / KNX Forum) - -2013-05-27: -* Added timeout to select at main_loop. (thx aloz77 / KNX Forum) - -2013-05-25: -* Modified hex Dump (EBH) for active sent messages. (thx Fry / KNX Forum) -* Changed telnet connecting log level info from L_NET to L_DBG. -* Added ability to reopen temporary removed serial device. (thx aloz77 / KNX Forum) - Attention: If the serial device is removed, network socket will be closed too. -* Removed data output format for executed commands. (thx JuMi2006 / KNX Forum) - -2013-05-24: -* Added hex type to eb_cmd_encode_value function. (thx Fry / KNX Forum) - -2013-05-17: -* Modified eb_serial_valid function and usage. (thx aloz77 / KNX Forum) - -2013-05-16: -* Added ability to restrict tcp connection to localhost. (thx aloz77 / KNX Forum) -* Added skip of negative sleep time while waiting for QQ byte. (thx aloz77 / KNX Forum) - -2013-05-05: -* Added function checks whether the FD is still a valid serial device. - -2013-04-27: -* Improved csv files read in a way that ebus parts are not case sensitive. -* Added eb_cmd_uppercase function. - -2013-04-17: -* Changed error messages from daemon startup vom E_ERR to E_ALL. - -2013-04-09: -* Extended signal handler to fit with logrotate / logging facility. -* Added ebusd.logrotate.d file too contrib. -* Added gentoo ebusd.init.d and ebusd.conf.d scripts. -* Reverted logging functions too old behavior. - -2013-04-08: -* Logging functions changed so it fits together with the behavior of logrotate. -* Fixed function eb_cmd_search_com_id so it compares class length too. - -2013-03-28: -* Fixed daemon crash if some spaces was found behind command (without subcommands.) - -2013-03-16: -* Fixed slave message CRC check for cyc messages. - -2013-03-15: -* Improved cyc commands data handling so all parts from message could be decoded. -* Added new parameter d_part to element configuration part. -* Updated documantation. -* ebusd.init script (debian) slightly modified. - -2013-03-06: -* Fixed extension for command files in configuration. A point is not necessary. - -2013-03-03: -* Added debian init script ebusd.init to contrib. -* Fixed autogen.sh that it worked properly with bourne shell. - -2013-03-01: -* Added new directory doc with some usefull documentation. -* Added an example command csv file into contrib directory. -* Changed width of class string from 5 to 20. - -2013-02-28: -* Added loglevel as telnet command to change logging level at runtime. -* Moved eb_cmd* functions from ebus-bus file to new ebus-cmd file. -* Added many explicit casts to remove compiler warnings. - -2013-02-27: -* Fixed memory leak in eb_raw_print_hex twice. -* Added new config parameter print_size to adjust number of bytes at output stream. - -2013-02-25: -* Fixed possible memory leaks in eb_raw_print_hex and eb_search_cyc - -2013-02-22: -* Added too each client answer (no need of special config for putty) -* Minor print cosmetic with cyc commands on Master Slave types - -2013-02-21: -* Improved decoding of cyc commands to all ebus message types. -* Added function eb_cyc_data_process to decode all cyc ebus message types. -* Removed hex bitmask of logging output. -* Fixed uninitialized buffer in eb_cyc_data_recv. - -2013-02-19: -* Added some usefull description of ebusd to README - -2013-02-18: -* Changed name of functions for message handling from eb_send_cmd to eb_msg_execute. -* Changed name of eb_msg_search_hex function to eb_msg_search_cyc. - -2013-02-17: -* Added csv tool to print command configuration. -* Added decoding of cyc commands. -* Fixed daemon crash when telnet command window closed without quit signal. -* Split dat (date) decode format into bda (bcd) and hda (hex). -* Split tim (time) decode format into bti (bcd) and hti (hex). -* Added internal buffer for cyc data, so cyc commands can be used like get/set - to fetch last data. - -2013-02-16: -* Structure for commands improved so only one structure for GET/SET/CYC is needed -* Possible formats for GET / SET (asc, bcd, d1b, d1c, d2b, d2c, dat, tim) -* Commands with format hex will return undecoded data. -* Added d_valid to structure. It will be used to check answers with given items. -* Added functions to decode/encode date and time to library. -* Changed CSV file struture to fit new data structure. - -2013-02-10: -* Changed decode datatype from int to bcd -* Added bcd, d2b and d2c too available SET commands -* Changed CSV file structur - move comment on position 4 - -2013-02-09: -* Upgrade the send ability for ebus SET commands. (only d1b and d1c) - -2013-02-06: -* Fixed increase length of ebus command from 20 to 30 -* Fixed set initiale value of crclen before escape in eb_send_data_prepare() -* Fixed eb_msg_decode_result() do strtok on local copy from r_pos. Maybe - we don't wont do modife the original value. -* Fixed compare strlen of given command with command from csv file too. -* Added send_retry parameter (2=default) to daemon configuration. - -2013-02-04: -* Add the ability to send commands via telnet to daemon - (This ist just implemented for GET and a few ebus commands for response) -* The telnet commands will collected into a message buffer. - If the cycle buffer is free, only one command is sent. - -2013-02-01: -* Added functions to read ebus command files and load them into nested - structure. This will be used to send and decode ebus messages. -* Try to read daemon configuration file at daemon directory too. -* ebus files splitted into ebus-decode and ebus-bus part. -* Moved log.* from src to lib directory and build liblog.a - -2013-01-25: -* Added autogen.sh script in main dir. Just type ./autogen.sh for build all. -* Logging functions changed from level to class system. The advantage of this - system is that different classes can be easily mixed together. - There are now 8 classes: INF, NOT, WAR, ERR, DBG, EBH, EBS, NET - and ALL for just all messages. - -2013-01-24: -* Added new directory contrib with daemon configuration file -* Added functions with cfg_ prefix (utils). These parse - the daemon configuration file and set parameters. - Priority of given configuration by: - 1. commandline argurments - 2. configuration file - 3. default configuration (hard coded) - -2013-01-17: -* Initial release -* Prepare Source to compile with GNU Autotools +https://github.com/yuhu-/ebusd/commits/master diff --git a/Makefile.am b/Makefile.am index d4638cc4..d2178823 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,7 +3,7 @@ SUBDIRS = docs \ src/lib/ebus \ src/lib/ebus/test \ src/ebusd \ - src/ebusctl + src/tools distclean-local: -rm -rf autom4te.cache diff --git a/NEWS b/NEWS index a5297fe9..3032a631 100644 --- a/NEWS +++ b/NEWS @@ -1,112 +1 @@ -ebusd - NEWS ------------- - -2014-10-09 Roland Jax -* Polling ability implemented. -* Reload function for ebus configuration added. -* Version changed from 0.3.0 to 0.4.0 - -2014-08-05 Roland Jax -* Vendor specific configuration files removed. - -2014-06-26 Roland Jax -* ebusctl added (includes ebusd_scan and ebusd_send) -* ebusdump merged into ebusctl. -* Version changed from 0.2.1 to 0.3.0 - -2014-06-03 Roland Jax -* ebusd_send, ebusd_scan added. -* Version changed from 0.2.0 to 0.2.1 - -2014-05-11 Roland Jax -* ebus-daemon merged into ebusd. - -2014-05-11 Roland Jax -* Beta-Test for ebus-daemon started. - ---- - -2014-03-16: -* Specific vaillant data type "ttm" (time table minutes) added. - (thx hendrikw / KNX Forum) - -2014-02-21: -* Improved ebus device handling to use tcp based device too. - -2013-11-19: -* Data type of struct commands.s_type changed from integer to char[2]. - -2013-11-14: -* Initial commit on github. - -2013-11-06: -* Specific vaillant data type "ulg" (unsigned long) added. - -2013-05-25: -* Added ability to reopen temporary removed serial device. (thx aloz77 / KNX Forum) - -2013-05-16: -* Added ability to restrict tcp connection to localhost. (thx aloz77 / KNX Forum) - -2013-04-27: -* Improved csv files read in a way that ebus parts are not case sensitive. - -2013-04-09: -* Extended signal handler to fit with logrotate / logging facility. - -2013-04-08: -* Logging functions changed so it fits together with the behavior of logrotate. - -2013-03-15: -* Improved cyc commands data handling so all parts from message could be decoded. - -2013-03-03: -* Added debian init script ebusd.init to contrib. - -2013-03-01: -* Added documentation and an example command csv file. - -2013-02-28: -* Added loglevel as telnet command to change logging level at runtime. - -2013-02-27: -* Added new config parameter print_size to adjust number of bytes at output stream. - -2013-02-22: -* Changed client answer code so normal telnet client can handle it - -2013-02-21: -* Improved decoding of cyc commands to all ebus message types. - -2013-02-19: -* Added some usefull description of ebusd to README - -2013-02-17: -* Added csv tool to print command configuration. -* Added deconding of cyc commands. - -2013-02-16: -* Structure for commands improved so only one structure for GET/SET/CYC is needed -* Possible formats for GET / SET (asc, bcd, d1b, d1c, d2b, d2c, dat, tim) - -2013-02-06: -* Fixed some malfunctions of command decode function -* Added parameter send_retry so the daemon can try x times to send command - -2013-02-04: -* Added the ability to send commands via telnet to daemon - (This ist just added for GET and a few ebus commands for response) - -2013-02-01: -* Added functions to read ebus command files - -2013-01-25: -* Added autogen.sh script in main dir -* Logging functions changed from level to class system - -2013-01-24: -* Added example daemon configuration file -* Added functions for parsing daemon configuration file - -2013-01-17: -* Prepare Source to compile with GNU Autotools +https://github.com/yuhu-/ebusd/releases diff --git a/README b/README index dfc45852..1c555bb7 100644 --- a/README +++ b/README @@ -1,5 +1,5 @@ -ebusd - README --------------- +ebusd +----- The ebusd provides a communication interface to the energy bus (ebus) which is used in various heating systems. @@ -8,12 +8,11 @@ which is used in various heating systems. Features -------- - * send and receive ebus commands for all ebus message types - (message types are: Broadcast, Master-Master and Master-Slave) - * collect data of cycle messages - * poll messages and collect received data - * write raw data into dump files (for debugging purpose) + * send and receive ebus commands + * collect data of cycle commands + * poll commands and collect received data * scan ebus to identifies bus participants + * dump raw data into binary files * available daemon commands: - get fetch data from ebus participant @@ -45,16 +44,11 @@ vendor specific configuration files for ebusd See https://github.com/yuhu-/ebus-configuration +Tools +----- -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 - + * 'ebusctl' is a tcp socket client for ebusd. + * 'ebusfeed' is a tool to feed ebusd with raw data from dump files. Build diff --git a/configure.ac b/configure.ac index e49a1449..29e73282 100644 --- a/configure.ac +++ b/configure.ac @@ -29,7 +29,7 @@ AC_CONFIG_FILES([Makefile src/lib/ebus/Makefile src/lib/ebus/test/Makefile src/ebusd/Makefile - src/ebusctl/Makefile]) + src/tools/Makefile]) AC_CHECK_PROGS([HAVE_DOXYGEN], [doxygen]) if test -z "$HAVE_DOXYGEN"; @@ -41,7 +41,7 @@ AM_CONDITIONAL([HAVE_DOXYGEN], [test -n "$HAVE_DOXYGEN"]) AM_INIT_AUTOMAKE([1.11 -Wall -Werror foreign]) -AM_PROG_AR +m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) AC_PROG_RANLIB AC_OUTPUT diff --git a/src/ebusctl/ebusctl.cpp b/src/ebusctl/ebusctl.cpp deleted file mode 100644 index 6ada8b46..00000000 --- a/src/ebusctl/ebusctl.cpp +++ /dev/null @@ -1,136 +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/. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "appl.h" -#include "port.h" -#include "data.h" -#include "tcpsocket.h" -#include -#include -#include -#include - -using namespace std; - -Appl& A = Appl::Instance(true); - -void define_args() -{ - A.setVersion("ebusctl is part of """PACKAGE_STRING""); - - 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.addOption("device", "d", OptVal("/dev/ttyUSB60"), dt_string, ot_mandatory, - "virtual serial device (/dev/ttyUSB60)"); - - A.addOption("file", "f", OptVal("/tmp/ebus_dump.bin"),dt_string, ot_mandatory, - "dump file name (/tmp/ebus_dump.bin)"); - - A.addOption("time", "t", OptVal(10000), dt_long, ot_mandatory, - "delay between 2 bytes in 'us' (10000)\n"); - - A.addOption("server", "s", OptVal("localhost"), dt_string, ot_mandatory, - "name or ip (localhost)"); - - A.addOption("port", "p", OptVal(8888), dt_int, ot_mandatory, - "port (8888)\n"); -} - -int main(int argc, char* argv[]) -{ - // define arguments and application variables - define_args(); - - // parse arguments - A.parseArgs(argc, argv); - - if (strcasecmp(A.getArg(0).c_str(), "feed") == 0) { - string dev(A.getOptVal("device")); - Port port(dev, true, false, NULL, false, "", 1); - - port.open(); - if(port.isOpen() == true) { - cout << "openPort successful." << endl; - - fstream file(A.getOptVal("file"), ios::in | ios::binary); - - if (file.is_open() == true) { - - while (file.eof() == false) { - unsigned char byte = file.get(); - cout << hex << setw(2) << setfill('0') - << static_cast(byte) << endl; - - port.send(&byte, 1); - usleep(A.getOptVal("time")); - } - - file.close(); - } - else - cout << "error opening file " << A.getOptVal("file") << endl; - - port.close(); - if(port.isOpen() == false) - cout << "closePort successful." << endl; - } else - cout << "error opening device " << A.getOptVal("device") << endl; - } - else { - - TCPClient* client = new TCPClient(); - TCPSocket* socket = client->connect(A.getOptVal("server"), A.getOptVal("port")); - - if (socket != NULL) { - // build message - 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'; - - cout << data; - - delete socket; - } - else - cout << "error connecting to " << A.getOptVal("server") - << ":" << A.getOptVal("port") << endl; - - delete client; - } - - return 0; -} - diff --git a/src/ebusd/Makefile.am b/src/ebusd/Makefile.am old mode 100644 new mode 100755 index 5d060fb6..e4d02e6f --- a/src/ebusd/Makefile.am +++ b/src/ebusd/Makefile.am @@ -16,7 +16,8 @@ ebusd_SOURCES = bushandler.cpp \ ebusd_LDADD = $(top_srcdir)/src/lib/utils/libutils.a \ $(top_srcdir)/src/lib/ebus/libebus.a \ - -lpthread -lrt + -lpthread + -lrt distclean-local: -rm -f Makefile.in diff --git a/src/ebusd/network.cpp b/src/ebusd/network.cpp index 324c6bd7..4b36ad78 100644 --- a/src/ebusd/network.cpp +++ b/src/ebusd/network.cpp @@ -115,7 +115,7 @@ void Connection::run() break; // removed closed socket - if (datalen <= 0 || strcasecmp(data, "QUIT") == 0) + if (datalen <= 0 || strncasecmp(data, "QUIT", 4) == 0) break; // send data diff --git a/src/lib/ebus/port.cpp b/src/lib/ebus/port.cpp index 97e32ea3..abccd666 100644 --- a/src/lib/ebus/port.cpp +++ b/src/lib/ebus/port.cpp @@ -147,20 +147,19 @@ unsigned char Device::getByte() result_t DeviceSerial::openDevice(const string deviceName, const bool noDeviceCheck) { m_noDeviceCheck = noDeviceCheck; - - termios newSettings; - + struct termios newSettings; m_open = false; - // open file descriptor from serial device + // open file descriptor m_fd = open(deviceName.c_str(), O_RDWR | O_NOCTTY); - if (m_fd < 0) + if (m_fd < 0 || isatty(m_fd) == 0) return RESULT_ERR_NOTFOUND; - // save current settings of serial device + // save current settings tcgetattr(m_fd, &m_oldSettings); + // create new settings memset(&newSettings, '\0', sizeof(newSettings)); newSettings.c_cflag |= (B2400 | CS8 | CLOCAL | CREAD); @@ -176,7 +175,7 @@ result_t DeviceSerial::openDevice(const string deviceName, const bool noDeviceCh tcflush(m_fd, TCIFLUSH); // activate new settings of serial device - tcsetattr(m_fd, TCSANOW, &newSettings); + tcsetattr(m_fd, TCSAFLUSH, &newSettings); // set serial device into blocking mode fcntl(m_fd, F_SETFL, fcntl(m_fd, F_GETFL) & ~O_NONBLOCK); diff --git a/src/lib/ebus/port.h b/src/lib/ebus/port.h index a81fdb28..abd2d55d 100644 --- a/src/lib/ebus/port.h +++ b/src/lib/ebus/port.h @@ -110,13 +110,13 @@ public: ssize_t sizeRecvBuffer() const { return m_recvBuffer.size(); } protected: - /** if of file descriptor */ + /** file descriptor from input device */ int m_fd; - /** state of device*/ + /** true if device is opened */ bool m_open; - /** state of device check */ + /** true if device check is disabled */ bool m_noDeviceCheck; /** queue for received bytes */ diff --git a/src/lib/utils/appl.cpp b/src/lib/utils/appl.cpp index c87d2a38..6a62c344 100644 --- a/src/lib/utils/appl.cpp +++ b/src/lib/utils/appl.cpp @@ -24,9 +24,9 @@ using namespace std; -Appl& Appl::Instance(const bool command) +Appl& Appl::Instance(const bool command, const bool argument) { - static Appl instance(command); + static Appl instance(command, argument); return instance; } @@ -107,22 +107,17 @@ void Appl::parseArgs(int argc, char* argv[]) } // check command - if (m_needCommand == true) { - for (int i = 1; i < argc; i++) { + for (int i = 1; i < argc; i++) { - if (_argv[i].rfind("-", 0) != string::npos) { - i++; - continue; - } + if (_argv[i].rfind("-", 0) != string::npos) { + i++; + continue; + } + if (m_command.size() == 0) + m_command = _argv[i]; + else m_arguments.push_back(_argv[i]); - } - - if (m_arguments.size() == 0) { - cerr << endl << "command needed" << endl; - printHelp(); - } } - } bool Appl::checkOption(const string& option, const string& value) @@ -130,7 +125,7 @@ bool Appl::checkOption(const string& option, const string& value) if (strcmp(option.c_str(), "settings") == 0) printSettings(); - if (strcmp(option.c_str(), "v") == 0 || strcmp(option.c_str(), "version") == 0) + if (strcmp(option.c_str(), "version") == 0) printVersion(); if (strcmp(option.c_str(), "h") == 0 || strcmp(option.c_str(), "help") == 0) @@ -196,8 +191,11 @@ void Appl::printHelp() cerr << endl << "Usage:" << endl << " " << m_argv[0].substr(m_argv[0].find_last_of("/\\") + 1) << " [OPTIONS...]" ; - if (m_needCommand == true) - cerr << " COMMAND {ARGS...}" << endl << endl; + if (m_withCommand == true) + if (m_withArgument == true) + cerr << " COMMAND {ARGS...}" << endl << endl; + else + cerr << " COMMAND" << endl << endl; else cerr << endl << endl; @@ -213,7 +211,7 @@ void Appl::printHelp() } } - cerr << " | --settings\n-v | --version\n-h | --help" << endl << endl; + cerr << endl << " | --settings\n | --version\n-h | --help" << endl << endl; exit(EXIT_SUCCESS); } diff --git a/src/lib/utils/appl.h b/src/lib/utils/appl.h index 7b88f2e8..1804049e 100644 --- a/src/lib/utils/appl.h +++ b/src/lib/utils/appl.h @@ -118,9 +118,10 @@ public: /** * @brief create an instance and return the reference. * @param command is true if an command is needed. + * @param argument is true if command could have an argument. * @return the reference to instance. */ - static Appl& Instance(const bool command=false); + static Appl& Instance(const bool command=false, const bool argument=false); /** * @brief destructor. @@ -175,26 +176,57 @@ public: * @return number of commands and arguments. */ int numArgs() const { return m_arguments.size(); } - /** - * @brief returns the string of an interested argument (0 = command). + * @brief returns the string of an interested argument. * @param num number of interested argument. - * @return string value. + * @return the argument string. */ string getArg(const int num) const { return m_arguments[num]; } + /** + * @brief returns the string of given command. + * @return the command string. + */ + string getCommand() const { return m_command; } + + /** + * @brief returns the string of given command. + * @return the command string. + */ + bool missingCommand() const { return (m_command.size() == 0 ? true : false); } + private: - /** private constructor - singleton pattern */ - Appl(const bool command) : m_needCommand(command) {} + /** + * @brief private construtor. + * @param command is true if an command is needed. + * @param argument is true if command could have an argument. + */ + Appl(const bool command, const bool argument) + : m_withCommand(command), m_withArgument(argument) {} + + /** + * @brief private copy construtor. + * @param reference to an instance. + */ Appl(const Appl&); + + /** + * @brief private = operator. + * @param reference to an instance. + * @return reference to instance. + */ Appl& operator=(const Appl&); /** application options */ vector m_opts; + + /** application options iterator */ vector::const_iterator o_it; /** map option - value */ map m_optvals; + + /** map option - value iterator */ map::iterator ov_it; /** given arguments */ @@ -203,10 +235,16 @@ private: /** application version string */ const char* m_version; - /** true if the application need a command */ - bool m_needCommand; + /** true if the application could have a command */ + bool m_withCommand; - /** arguments (argument 0 = command) string */ + /** true if the command could have an argument */ + bool m_withArgument; + + /** command (argument 0 = command) string */ + string m_command; + + /** arguments (argument >= 1) string */ vector m_arguments; /** diff --git a/src/lib/utils/daemon.h b/src/lib/utils/daemon.h index d7f3fdbd..9b4b7788 100644 --- a/src/lib/utils/daemon.h +++ b/src/lib/utils/daemon.h @@ -51,9 +51,22 @@ public: bool status() { return m_status; } private: - /** private constructor - singleton pattern */ + /** + * @brief private construtor. + */ Daemon() {} + + /** + * @brief private copy construtor. + * @param reference to an instance. + */ Daemon(const Daemon&); + + /** + * @brief private = operator. + * @param reference to an instance. + * @return reference to instance. + */ Daemon& operator=(const Daemon&); /** status of process; true if we are a daemon */ diff --git a/src/lib/utils/logger.h b/src/lib/utils/logger.h index 7e3a3c08..daf2d75f 100644 --- a/src/lib/utils/logger.h +++ b/src/lib/utils/logger.h @@ -302,13 +302,28 @@ public: virtual void stop(); private: - /** private constructor - singleton pattern */ + /** + * @brief private construtor. + */ Logger() {} + + /** + * @brief private copy construtor. + * @param reference to an instance. + */ Logger(const Logger&); + + /** + * @brief private = operator. + * @param reference to an instance. + * @return reference to instance. + */ Logger& operator=(const Logger&); /** typedefs for a vector of type LogSink* */ typedef vector sink_t; + + /** typedefs for a vector of type LogSink* iterator */ typedef vector::iterator sinkCI_t; /** vector of available logging sinks */ diff --git a/src/lib/utils/tcpsocket.h b/src/lib/utils/tcpsocket.h index e8ba2d55..4b4e10ba 100644 --- a/src/lib/utils/tcpsocket.h +++ b/src/lib/utils/tcpsocket.h @@ -32,8 +32,10 @@ class TCPSocket { public: - /** grant access for friend classes */ + /** grant access for friend class TCPClient */ friend class TCPClient; + + /** grant access for friend class TCPServer */ friend class TCPServer; /** diff --git a/src/ebusctl/Makefile.am b/src/tools/Makefile.am similarity index 63% rename from src/ebusctl/Makefile.am rename to src/tools/Makefile.am index 5b5088ce..5c0a025a 100755 --- a/src/ebusctl/Makefile.am +++ b/src/tools/Makefile.am @@ -4,13 +4,19 @@ AM_CXXFLAGS = -fpic \ -I$(top_srcdir)/src/lib/utils \ -I$(top_srcdir)/src/lib/ebus -bin_PROGRAMS = ebusctl +bin_PROGRAMS = ebusctl \ + ebusfeed ebusctl_SOURCES = ebusctl.cpp ebusctl_LDADD = $(top_srcdir)/src/lib/utils/libutils.a \ $(top_srcdir)/src/lib/ebus/libebus.a +ebusfeed_SOURCES = ebusfeed.cpp + +ebusfeed_LDADD = $(top_srcdir)/src/lib/utils/libutils.a \ + $(top_srcdir)/src/lib/ebus/libebus.a + distclean-local: -rm -f Makefile.in -rm -rf .libs diff --git a/src/tools/ebusctl.cpp b/src/tools/ebusctl.cpp new file mode 100644 index 00000000..53bbbebb --- /dev/null +++ b/src/tools/ebusctl.cpp @@ -0,0 +1,195 @@ +/* + * 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 "appl.h" +#include "tcpsocket.h" +#include +#include +#include + +using namespace std; + +Appl& A = Appl::Instance(true, true); + +void define_args() +{ + A.setVersion("ebusctl is part of """PACKAGE_STRING""); + + A.addText(" 'ebusctl' is a tcp socket client for ebusd.\n\n" + "Command: 'help' show available ebusd commands.\n\n" + "Options:\n"); + + A.addOption("server", "s", OptVal("localhost"), dt_string, ot_mandatory, + "name or ip (localhost)"); + + A.addOption("port", "p", OptVal(8888), dt_int, ot_mandatory, + "port (8888)"); + +} + +enum CommandType { + ct_open, + ct_exit, + ct_help, + ct_invalid +}; + +CommandType getCase(const string& item) +{ + if (strcasecmp(item.c_str(), "OPEN") == 0) return ct_open; + if (strcasecmp(item.c_str(), "EXIT") == 0) return ct_exit; + if (strcasecmp(item.c_str(), "HELP") == 0) return ct_help; + + return ct_invalid; +} + +bool connect(const char* host, int port, bool once=true) +{ + + TCPClient* client = new TCPClient(); + TCPSocket* socket = client->connect(host, port); + + if (socket != NULL) { + + do { + string message; + + if (once == false) { + cout << host << ": "; + getline(cin, message); + } + else { + message = A.getCommand(); + for (int i = 0; i < A.numArgs(); i++) { + message += " "; + message += A.getArg(i); + } + } + + socket->send(message.c_str(), message.size()); + + if (strncasecmp(message.c_str(), "QUIT", 4) != 0 && strncasecmp(message.c_str(), "STOP", 4) != 0) { + + char data[1024]; + size_t datalen; + + datalen = socket->recv(data, sizeof(data)-1); + data[datalen] = '\0'; + + cout << data; + } + else + break; + + } while (once == false); + + delete socket; + + } + else + cout << "error connecting to " << host << ":" << port << endl; + + delete client; + + if (once == false) + return false; + + return true; +} + +int main(int argc, char* argv[]) +{ + // define arguments and application variables + define_args(); + + // parse arguments + A.parseArgs(argc, argv); + + if (A.missingCommand() == true) { + cout << "interactive mode started." << endl; + + bool running = true; + + do { + string input, token; + vector cmd; + + cout << "$: "; + getline(cin, input); + + // prepare input + istringstream stream(input); + while (getline(stream, token, ' ') != 0) + cmd.push_back(token); + + if (cmd.size() == 0) + cout << "command missing" << endl; + + switch (getCase(cmd[0])) { + case ct_invalid: + cout << "command not found" << endl; + break; + + case ct_open: + { + bool ret = true; + cout << "connect to..." << endl; + if (cmd.size() == 1) + ret = connect(A.getOptVal("server"), A.getOptVal("port"), false); + else if (cmd.size() == 2) + ret = connect(cmd[1].c_str(), A.getOptVal("port"), false); + else if (cmd.size() == 3) + ret = connect(cmd[1].c_str(), atoi(cmd[2].c_str()), false); + else + cout << "open [host [port]]" << endl; + + running = ret; + } + + break; + + case ct_exit: + running = false; + break; + + case ct_help: + cout << "commands:" << endl + << " open - open connection to ebusd 'open [host [port]]'" << endl + << " exit - exit ebusctl" << endl + << " help - print this page" << endl; + break; + + default: + break; + } + + } while (running == true); + + exit(EXIT_SUCCESS); + } + + connect(A.getOptVal("server"), A.getOptVal("port")); + + exit(EXIT_SUCCESS); +} + diff --git a/src/tools/ebusfeed.cpp b/src/tools/ebusfeed.cpp new file mode 100644 index 00000000..d4330e5d --- /dev/null +++ b/src/tools/ebusfeed.cpp @@ -0,0 +1,104 @@ +/* + * 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 "appl.h" +#include "port.h" +#include +#include +#include +#include + +using namespace std; + +Appl& A = Appl::Instance(true); + +void define_args() +{ + A.setVersion("ebusfeed is part of """PACKAGE_STRING""); + + A.addText(" 'ebusfeed' sends a dump file to a local serial device (pts)\n\n" + " Usage: 1. 'socat -d -d pty,raw,echo=0 pty,raw,echo=0'\n" + " 2. create symbol links to appropriate devices\n" + " for example: 'ln -s /dev/pts/2 /dev/ttyUSB60'\n" + " 'ln -s /dev/pts/3 /dev/ttyUSB20'\n" + " 3. start ebusd: 'ebusd -f -d /dev/ttyUSB20'\n" + " 4. start ebusfeed: 'ebusfeed /path/to/ebus_dump.bin'\n\n" + "Command: '/path/to/ebus_dump.bin'\n\n" + "Options:\n"); + + A.addOption("device", "d", OptVal("/dev/ttyUSB60"), dt_string, ot_mandatory, + "virtual serial device (/dev/ttyUSB60)"); + + A.addOption("time", "t", OptVal(10000), dt_long, ot_mandatory, + "delay between 2 bytes in 'us' (10000)"); + +} + +int main(int argc, char* argv[]) +{ + // define arguments and application variables + define_args(); + + // parse arguments + A.parseArgs(argc, argv); + + if (A.missingCommand() == true) { + cout << "ebus dump file is required." << endl; + exit(EXIT_FAILURE); + } + + string dev(A.getOptVal("device")); + Port port(dev, true, false, NULL, false, "", 1); + + port.open(); + if(port.isOpen() == true) { + cout << "openPort successful." << endl; + + fstream file(A.getCommand().c_str(), ios::in | ios::binary); + + if (file.is_open() == true) { + + while (file.eof() == false) { + unsigned char byte = file.get(); + cout << hex << setw(2) << setfill('0') + << static_cast(byte) << endl; + + port.send(&byte, 1); + usleep(A.getOptVal("time")); + } + + file.close(); + } + else + cout << "error opening file " << A.getOptVal("file") << endl; + + port.close(); + if(port.isOpen() == false) + cout << "closePort successful." << endl; + } else + cout << "error opening device " << A.getOptVal("device") << endl; + + + exit(EXIT_SUCCESS); +} +