Files
flippr-code/FlippR-Driver/networking/FlippRServer.cpp
Johannes Wendel e90c3f6695 made compiling
2019-06-14 19:28:09 +02:00

246 lines
7.7 KiB
C++

//
// Created by rhetenor on 5/21/19.
//
#include "FlippRServer.h"
#include "output/OutputRequestHandlerFactory.h"
#include "DriverFactory.h"
#include <Poco/Net/SocketAddress.h>
#include <Poco/Net/ServerSocket.h>
#include <Poco/Net/HTTPServer.h>
#include <Poco/Util/HelpFormatter.h>
#include <Poco/JSON/Parser.h>
#include <iostream>
#include <fstream>
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<Object::Ptr>();
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<std::string>& args)
{
if(help_requested)
return Application::EXIT_OK;
std::unique_ptr<HTTPServer> output_server(this->build_output_server());
output_server->start();
std::unique_ptr<TCPServer>
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<FlippRServer>(
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<FlippRServer>(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<FlippRServer>(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<FlippRServer>(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<FlippRServer>(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<FlippRServer>(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<FlippRServer>(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<FlippRServer>(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<FlippRServer>(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<FlippRServer>(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;
}
}
}