// // Created by rhetenor on 5/21/19. // #include "FlippRServer.h" #include "output/OutputRequestHandlerFactory.h" #include "DriverFactory.h" #include #include #include #include #include #include #include int main(int argc, char** argv) { flippR_driver::networking::FlippRServer app; return app.run(argc, argv); } 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::get_InputDriver(input_config_stream, matrix_config_stream); } int FlippRServer::main(const std::vector& args) { if(help_requested) return Application::EXIT_OK; std::unique_ptr output_server(this->build_output_server()); output_server->start(); std::unique_ptr waitForTerminationRequest(); this->output_driver->deactivate_all_lamps(); this->output_driver->deactivate_displays(); output_server->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; } } }