From 3af4919a11b23cfac41e37aa02da8adf9c94f08c Mon Sep 17 00:00:00 2001 From: Johannes Wendel Date: Fri, 14 Jun 2019 19:26:10 +0200 Subject: [PATCH] Added options to server application and did some stuff for the application --- .gitignore | 1 + FlippR-Driver/CMakeLists.txt | 17 -- FlippR-Driver/networking/CMakeLists.txt | 10 +- FlippR-Driver/networking/FlippRServer.cpp | 232 ++++++++++++++++-- FlippR-Driver/networking/FlippRServer.h | 41 ++++ ...cketHandler.cpp => InputSocketHandler.cpp} | 12 +- .../{SocketHandler.h => InputSocketHandler.h} | 7 +- 7 files changed, 270 insertions(+), 50 deletions(-) rename FlippR-Driver/networking/input/{SocketHandler.cpp => InputSocketHandler.cpp} (68%) rename FlippR-Driver/networking/input/{SocketHandler.h => InputSocketHandler.h} (67%) diff --git a/.gitignore b/.gitignore index 81892f6..704ad01 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.idea* cmake-build-debug .idea/* +*__pycache__/* diff --git a/FlippR-Driver/CMakeLists.txt b/FlippR-Driver/CMakeLists.txt index c40cd5e..38470e2 100644 --- a/FlippR-Driver/CMakeLists.txt +++ b/FlippR-Driver/CMakeLists.txt @@ -39,27 +39,10 @@ IF(CROSS_COMPILE) SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) - -# SET(Boost_NO_SYSTEM_PATHS TRUE) -# SET(BOOST_ROOT "$ENV{HOME}/boost_1_64_0/") -# SET(BOOST_INCLUDEDIR "${RPI_ROOT}/rootfs/usr/include//boost_1_64_0/") -# SET(BOOST_LIBRARYDIR "$ENV{HOME}/boost_1_64_0/") - - #SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --sysroot=${CMAKE_FIND_ROOT_PATH}") - #SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} --sysroot=${CMAKE_FIND_ROOT_PATH}") - #SET(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} --sysroot=${CMAKE_FIND_ROOT_PATH}") - - # Search for programs only in the build host directories - #SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) - - # Search for libraries and headers only in the target directories - #SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) - #SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) ENDIF(CROSS_COMPILE) ###################### START_CMAKE ####################### cmake_minimum_required(VERSION 3.0.1) -#cmake_minimum_required(VERSION 3.0.2) project(FlippR-Driver VERSION 0.1.0)# LANGUAGES CXX) #set easylogging flags diff --git a/FlippR-Driver/networking/CMakeLists.txt b/FlippR-Driver/networking/CMakeLists.txt index 634e1b1..f7b8f0b 100644 --- a/FlippR-Driver/networking/CMakeLists.txt +++ b/FlippR-Driver/networking/CMakeLists.txt @@ -3,22 +3,22 @@ project(flippR_driver_networking) set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/${OUTPUT_PATH}/cli) set(SOURCES - input/SocketHandler.cpp + input/InputSocketHandler.cpp output/OutputRequestHandler.cpp output/OutputRequestHandlerFactory.cpp - FlippRServer.cpp - ) + FlippRServer.cpp) add_executable(${PROJECT_NAME} ${SOURCES}) target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/include) +target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/src) target_link_libraries(${PROJECT_NAME} PRIVATE FlippR-Driver) ####################### POCO ############################## -find_package(Poco REQUIRED COMPONENTS Foundation Net JSON ) +find_package(Poco REQUIRED COMPONENTS Foundation Net JSON Util) if(NOT Poco_FOUND) message(FATAL_ERROR, "Could not find libPoco") endif() -target_link_libraries(${PROJECT_NAME} PUBLIC Poco::Foundation Poco::Net Poco::JSON) +target_link_libraries(${PROJECT_NAME} PUBLIC Poco::Foundation Poco::Net Poco::JSON Poco::Util) diff --git a/FlippR-Driver/networking/FlippRServer.cpp b/FlippR-Driver/networking/FlippRServer.cpp index 477e670..5ba160e 100644 --- a/FlippR-Driver/networking/FlippRServer.cpp +++ b/FlippR-Driver/networking/FlippRServer.cpp @@ -4,14 +4,17 @@ #include "FlippRServer.h" #include "output/OutputRequestHandlerFactory.h" - -#include -#include -#include +#include "input/InputDriverFactory.h" +#include "DriverFactory.h" #include #include #include +#include +#include + +#include +#include int main(int argc, char** argv) { @@ -24,28 +27,221 @@ namespace flippR_driver namespace networking { using namespace Poco::Net; +using namespace Poco::Util; +using namespace Poco::JSON; +using namespace Poco; +FlippRServer::FlippRServer() : + help_requested(false), + input_port(9980), + output_port(9981), + input_config("Not set"), + matrix_config("Not set"), + output_pin_config("Not set"), + lamp_config("Not set"), + solenoid_config("Not set"), + sound_config("Not set"), + display_config("Not set") +{ + this->parse_server_config_file(); +} + +void FlippRServer::parse_server_config_file() +{ + std::ifstream config; + + try + { + config.open("server_config.json"); + } + catch(const std::exception e) + { + logger().information("No config file specified."); + return; + } + Parser parser; + Object::Ptr json = parser.parse(config).extract(); + + for(auto &config_json : json->getNames()) + { + handle_config_file(config_json, json->get(config_json)); + } +} + +/** + * Initially called before main. + */ +void FlippRServer::initialize(Application &self) +{ + //Todo May restructure with subsystems + //make this one application and subsystems ServerApplications + + + this->initialize_output_driver(); + //Todo initialize input server + + //https://gist.github.com/NIPE-SYSTEMS/5a06428c0880ed7ff3cc4304be436e3e + ServerApplication::initialize(self); +} + +void FlippRServer::initialize_output_driver() +{ + std::ifstream input_config_stream; + std::ifstream matrix_config_stream; + + try + { + input_config_stream.open(this->input_config); + matrix_config_stream.open(this->matrix_config); + } + catch(const std::exception& e) + { + logger().error(e.what()); + exit(EXIT_FAILURE); + } + + //todo should use DriverFactory from input + this->input_driver = flippR_driver::input::InputDriverFactory::get_InputDriver(input_config_stream, matrix_config_stream); +} int FlippRServer::main(const std::vector& args) { - if (!_helpRequested) - { - unsigned short port = (unsigned short) - config().getInt("HTTPTimeServer.port", 9980); + if(help_requested) + return Application::EXIT_OK; + std::unique_ptr output_server(this->build_output_server()); + output_server->start(); - // todo XDG_RUNTIME_DIR - SocketAddress address("/tmp/flippR_driver/S.flippR_driver"); - ServerSocket svs(address); + std::unique_ptr + + waitForTerminationRequest(); + this->output_driver->deactivate_all_lamps(); + this->output_driver->deactivate_displays(); + output_server->stop(); - HTTPServer srv(new OutputRequestHandlerFactory(), - svs, new HTTPServerParams); - srv.start(); - waitForTerminationRequest(); - srv.stop(); - } return Application::EXIT_OK; } -} + +HTTPServer* FlippRServer::build_output_server() +{ + unsigned short port = (unsigned short) config().getInt("HTTPTimeServer.port", this->output_port); + + // todo XDG_RUNTIME_DIR + SocketAddress address("/tmp/flippR_driver/S.flippR_driver"); + ServerSocket svs(address); + + return new HTTPServer(new OutputRequestHandlerFactory(this->output_driver), svs, new HTTPServerParams); } + + +void FlippRServer::defineOptions(OptionSet& options) +{ + ServerApplication::defineOptions(options); + + options.addOption( + Option("help", "h", "display argument help information") + .required(false) + .repeatable(false) + .callback(OptionCallback( + this, &FlippRServer::handle_help))); + + options.addOption(Option("input-port", "i", "Define the port for the TCP-Input-Server, which represents the flipper inputs. Default 9980") + .required(false) + .repeatable(false) + .callback(OptionCallback(this, &FlippRServer::handle_config_file)) + .argument("input-port", true)); + + options.addOption(Option("output-port", "o", "Define the port for the HTTP-Output-Server, which represents the flipper outputs. Default 9981") + .required(false) + .repeatable(false) + .callback(OptionCallback(this, &FlippRServer::handle_config_file)) + .argument("output-port", true)); + + options.addOption(Option("input-config", "I", "Specify where the input-config file is located. Only needed when not in this folder.") + .required(this->input_config == "Not set") + .repeatable(false) + .callback(OptionCallback(this, &FlippRServer::handle_config_file)) + .argument("input-config", true)); + + options.addOption(Option("matrix-config", "M", "Specify where the matrix-config file is located. Only needed when not in this folder.") + .required(this->matrix_config == "Not set") + .repeatable(false) + .callback(OptionCallback(this, &FlippRServer::handle_config_file)) + .argument("matric-config", true)); + + options.addOption(Option("output-pin-config", "O", "Specify where the matrix-config file is located. Only needed when not in this folder.") + .required(this->output_pin_config == "Not set") + .repeatable(false) + .callback(OptionCallback(this, &FlippRServer::handle_config_file)) + .argument("output-pin-config", true)); + + options.addOption(Option("lamp-config", "L", "Specify where the lamp-config file is located. Only needed when not in this folder.") + .required(this->lamp_config == "Not set") + .repeatable(false) + .callback(OptionCallback(this, &FlippRServer::handle_config_file)) + .argument("lamp-config", true)); + + options.addOption(Option("solenoid-config", "N", "Specify where the solenoid-config file is located. Only needed when not in this folder.") + .required(this->solenoid_config == "Not set") + .repeatable(false) + .callback(OptionCallback(this, &FlippRServer::handle_config_file)) + .argument("solenoid-config", true)); + + options.addOption(Option("sound-config", "S", "Specify where the sound-config file is located. Only needed when not in this folder.") + .required(this->sound_config == "Not set") + .repeatable(false) + .callback(OptionCallback(this, &FlippRServer::handle_config_file)) + .argument("sound-config", true)); + + options.addOption(Option("display-config", "D", "Specify where the display-config file is located. Only needed when not in this folder.") + .required(this->display_config == "Not set") + .repeatable(false) + .callback(OptionCallback(this, &FlippRServer::handle_config_file)) + .argument("display-config", true)); +} + +void FlippRServer::handle_config_file(const std::string &name, const std::string &value) +{ + if(name == "input-config") + this->input_config = value; + else if(name == "matrix-config") + this->matrix_config = value; + else if(name == "output-pin-config") + this->output_pin_config = value; + else if(name == "lamp-config") + this->lamp_config = value; + else if(name == "solenoid-config") + this->solenoid_config = value; + else if(name == "sound-config") + this->sound_config = value; + else if(name == "display-config") + this->display_config = value; + else if(name == "input-port") + this->input_port = std::stoi(value); + else if(name == "output-port") + this->output_port = std::stoi(value); + else + { + logger().information("Configuration \"" + name + "\" is not known."); + return; + } + logger().information("Set " + name + " to " + value); +} + +void FlippRServer::handle_help(const std::string& name, const std::string& value) +{ + Poco::Util::HelpFormatter helpFormatter(options()); + helpFormatter.setCommand(commandName()); + helpFormatter.setUsage("OPTIONS"); + helpFormatter.setHeader( + "The FlippR-Server, appropriate config-files must either be located in the actual folder\ + or the paths must be specified by commandline options. \ + The config file paths as well as the port settings can be specified in a a file server_config.json"); + helpFormatter.format(std::cout); + stopOptionsProcessing(); + help_requested = true; +} + +} +} \ No newline at end of file diff --git a/FlippR-Driver/networking/FlippRServer.h b/FlippR-Driver/networking/FlippRServer.h index 3a603a6..0258cee 100644 --- a/FlippR-Driver/networking/FlippRServer.h +++ b/FlippR-Driver/networking/FlippRServer.h @@ -4,7 +4,12 @@ #ifndef FLIPPR_DRIVER_FLIPPRSERVER_H #define FLIPPR_DRIVER_FLIPPRSERVER_H + +#include "output/OutputDriver.h" +#include "input/InputDriver.h" + #include +#include namespace flippR_driver { @@ -13,7 +18,43 @@ namespace networking class FlippRServer : public Poco::Util::ServerApplication { +public: + FlippRServer(); + int main(const std::vector& args); + + void initialize(Poco::Util::Application& self); + + void defineOptions(Poco::Util::OptionSet& options); + + void handle_set_input_port(const std::string &name, const std::string &port); + void handle_set_output_port(const std::string &name, const std::string &port); + void handle_help(const std::string &name, const std::string &port); + void handle_config_file(const std::string &name, const std::string &value); + +private: + void initialize_output_driver(); + void parse_server_config_file(); + + Poco::Net::HTTPServer* build_output_server(); + + +private: + int input_port; + int output_port; + + bool help_requested; + + std::string input_config; + std::string matrix_config; + std::string output_pin_config; + std::string lamp_config; + std::string solenoid_config; + std::string sound_config; + std::string display_config; + + std::shared_ptr input_driver; + std::shared_ptr output_driver; }; }; diff --git a/FlippR-Driver/networking/input/SocketHandler.cpp b/FlippR-Driver/networking/input/InputSocketHandler.cpp similarity index 68% rename from FlippR-Driver/networking/input/SocketHandler.cpp rename to FlippR-Driver/networking/input/InputSocketHandler.cpp index ba21a68..b199739 100644 --- a/FlippR-Driver/networking/input/SocketHandler.cpp +++ b/FlippR-Driver/networking/input/InputSocketHandler.cpp @@ -5,7 +5,7 @@ * Author: Andreas Schneider, Johannes Wendel, Jonas Zeunert */ -#include "SocketHandler.h" +#include "InputSocketHandler.h" using Poco::Net::StreamSocket; @@ -21,16 +21,14 @@ namespace networking namespace input { -SocketHandler::SocketHandler(StreamSocket streamSocket, std::shared_ptr inputDriver) : +InputSocketHandler::InputSocketHandler(StreamSocket streamSocket, std::shared_ptr inputDriver) : TCPServerConnection(streamSocket), EventHandler(inputDriver) { } -void SocketHandler::run() +void InputSocketHandler::run() { - StreamSocket& streamSocket = socket(); // todo ? - while(true) { Event event = this->queue->pop(); @@ -42,11 +40,11 @@ void SocketHandler::run() std::string str = event.getJsonString(); - streamSocket.sendBytes(str.c_str(), str.length()); + this->socket().sendBytes(str.c_str(), str.length()); } } -void SocketHandler::handle(Event &event) +void InputSocketHandler::handle(Event &event) { this->queue->push(event); } diff --git a/FlippR-Driver/networking/input/SocketHandler.h b/FlippR-Driver/networking/input/InputSocketHandler.h similarity index 67% rename from FlippR-Driver/networking/input/SocketHandler.h rename to FlippR-Driver/networking/input/InputSocketHandler.h index d61f44a..4b24ff4 100644 --- a/FlippR-Driver/networking/input/SocketHandler.h +++ b/FlippR-Driver/networking/input/InputSocketHandler.h @@ -22,16 +22,17 @@ namespace networking { namespace input { -class SocketHandler : public Poco::Net::TCPServerConnection, flippR_driver::input::EventHandler + +class InputSocketHandler : public Poco::Net::TCPServerConnection, flippR_driver::input::EventHandler { public: - SocketHandler(Poco::Net::StreamSocket streamSocket, std::shared_ptr input_driver); + InputSocketHandler(Poco::Net::StreamSocket streamSocket, std::shared_ptr input_driver); void run() override; void handle(flippR_driver::input::Event &event) override; private: - flippR_driver::utility::IBlockingQueue* queue; + utility::IBlockingQueue* queue; }; }