316 lines
7.5 KiB
C++
316 lines
7.5 KiB
C++
//
|
|
// Created by rhetenor on 3/6/19.
|
|
//
|
|
|
|
|
|
#include <Poco/Net/HTTPServerResponse.h>
|
|
#include <Poco/Net/HTTPServerRequest.h>
|
|
#include <Poco/Exception.h>
|
|
|
|
#include <string>
|
|
|
|
#include "OutputRequestHandler.h"
|
|
|
|
namespace flippR_driver
|
|
{
|
|
namespace networking
|
|
{
|
|
|
|
using namespace Poco;
|
|
using namespace Poco::Net;
|
|
|
|
OutputRequestHandler::OutputRequestHandler(std::shared_ptr<output::OutputDriver> output_driver) :
|
|
output_driver(output_driver)
|
|
{}
|
|
|
|
/**
|
|
* Handles a REST request with a URI form of:
|
|
*
|
|
* address/{item_type}/[item_name]/[action]/[score]
|
|
*
|
|
* Where
|
|
* {item_type} is either solenoids, lamps, sounds, displays, or one of the two special events: activate and deactivate
|
|
* [item_name] is the string name of an item (optional if you want to get the list of all available items)
|
|
* [action] is the particular action for the item:
|
|
* Solenoids: trigger
|
|
* lamps: activate, deactivate, status
|
|
* sounds: play
|
|
* displays: write_score (for this is the additional optional attribute [score]
|
|
*
|
|
* @param request
|
|
* @param response
|
|
*/
|
|
void OutputRequestHandler::handleRequest(HTTPServerRequest &request,
|
|
HTTPServerResponse &response)
|
|
{
|
|
auto path_segments = getPathSegments(URI(request.getURI()));
|
|
|
|
// fill up vector
|
|
for(int i = path_segments.size(); i < 4; i++)
|
|
{
|
|
path_segments.emplace_back("");
|
|
}
|
|
|
|
std::string item_type = path_segments.at(0);
|
|
std::string item_name = path_segments.at(1);
|
|
std::string action = path_segments.at(2);
|
|
std::string score = path_segments.at(3);
|
|
|
|
if(item_type == "deactivate")
|
|
{
|
|
this->output_driver->deactivate_displays();
|
|
this->output_driver->deactivate_all_lamps();
|
|
this->output_driver->deactivate_all_flipper_relays();
|
|
return;
|
|
}
|
|
|
|
if(item_type == "activate")
|
|
{
|
|
this->output_driver->activate_displays();
|
|
this->output_driver->activate_all_flipper_relays();
|
|
return;
|
|
}
|
|
|
|
response.setContentType("text/json");
|
|
response.setStatus(HTTPServerResponse::HTTP_OK);
|
|
|
|
try
|
|
{
|
|
boost::optional<Poco::JSON::Object> json_response = parseRequest(item_type, item_name, action, score);
|
|
|
|
if(json_response)
|
|
{
|
|
std::ostream& ostr = response.send();
|
|
json_response->stringify(ostr);
|
|
}
|
|
}
|
|
catch(const NotFoundException &e)
|
|
{
|
|
response.setStatusAndReason(HTTPServerResponse::HTTP_NOT_FOUND, e.displayText());
|
|
}
|
|
catch(const Poco::InvalidArgumentException &e)
|
|
{
|
|
response.setStatusAndReason(HTTPServerResponse::HTTP_BAD_REQUEST, e.displayText());
|
|
}
|
|
}
|
|
|
|
boost::optional<Poco::JSON::Object> OutputRequestHandler::parseRequest(const std::string& item_type, const std::string& item_name, const std::string& action, const std::string& score)
|
|
{
|
|
if(item_type == "solenoids")
|
|
{
|
|
return parseSolenoid(item_name, action);
|
|
}
|
|
else if(item_type == "lamps")
|
|
{
|
|
return parseLamp(item_name, action);
|
|
}
|
|
else if(item_type == "sounds")
|
|
{
|
|
return parseSound(item_name, action);
|
|
}
|
|
else if(item_type == "displays")
|
|
{
|
|
return parseDisplay(item_name, action, score);
|
|
}
|
|
else if(item_type == "flippers")
|
|
{
|
|
return parseFlipper(item_name, action);
|
|
}
|
|
else
|
|
{
|
|
throw new Poco::NotFoundException("No item type called " + item_type);
|
|
}
|
|
}
|
|
|
|
boost::optional<Poco::JSON::Object> OutputRequestHandler::parseSolenoid(const std::string& item_name, const std::string& action)
|
|
{
|
|
if(item_name == "")
|
|
{
|
|
Poco::JSON::Object response;
|
|
response.set("solenoids", getItemArray(this->output_driver->get_solenoids()) );
|
|
return response;
|
|
}
|
|
|
|
auto opt_solenoid = this->output_driver->get_solenoid(item_name);
|
|
|
|
if(!opt_solenoid)
|
|
{
|
|
throw new Poco::NotFoundException("No solenoid with name \"" + item_name + "\"!");
|
|
}
|
|
|
|
auto solenoid = opt_solenoid->get();
|
|
|
|
if(action == "trigger")
|
|
{
|
|
solenoid->trigger();
|
|
}
|
|
else
|
|
{
|
|
throw new Poco::NotFoundException("No action with name \"" + action + "\" on solenoids!");
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
boost::optional<Poco::JSON::Object> OutputRequestHandler::parseLamp(const std::string& item_name, const std::string& action)
|
|
{
|
|
if(item_name == "")
|
|
{
|
|
Poco::JSON::Object response;
|
|
response.set("lamps", getItemArray(this->output_driver->get_lamps()) );
|
|
return response;
|
|
}
|
|
|
|
auto opt_lamp = this->output_driver->get_lamp(item_name);
|
|
|
|
if(!opt_lamp)
|
|
{
|
|
throw new Poco::NotFoundException("No lamp with name \"" + item_name + "\"!");
|
|
}
|
|
|
|
auto lamp = opt_lamp->get();
|
|
|
|
if(action == "activate")
|
|
{
|
|
lamp->activate();
|
|
}
|
|
else if(action == "deactivate")
|
|
{
|
|
lamp->deactivate();
|
|
}
|
|
else
|
|
{
|
|
throw new Poco::NotFoundException("No action with name \"" + action + "\" on lamps!");
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
boost::optional<Poco::JSON::Object> OutputRequestHandler::parseSound(const std::string& item_name, const std::string& action)
|
|
{
|
|
if(item_name == "")
|
|
{
|
|
Poco::JSON::Object response;
|
|
response.set("sounds", getItemArray(this->output_driver->get_sounds()) );
|
|
return response;
|
|
}
|
|
|
|
auto opt_sound = this->output_driver->get_sound(item_name);
|
|
|
|
if(!opt_sound)
|
|
{
|
|
throw new Poco::NotFoundException("No sound with name \"" + item_name + "\"!");
|
|
}
|
|
|
|
auto sound = opt_sound->get();
|
|
|
|
if(action == "play")
|
|
{
|
|
sound->play();
|
|
}
|
|
else
|
|
{
|
|
throw new Poco::NotFoundException("No action with name \"" + action + "\" on sounds!");
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
boost::optional<Poco::JSON::Object> OutputRequestHandler::parseDisplay(const std::string& item_name, const std::string& action, const std::string& score)
|
|
{
|
|
if(item_name == "")
|
|
{
|
|
Poco::JSON::Object response;
|
|
response.set("displays", this->output_driver->get_displays());
|
|
return response;
|
|
}
|
|
|
|
uint8_t display_number = std::stoi(item_name);
|
|
auto opt_display = this->output_driver->get_display(display_number);
|
|
|
|
if(!opt_display)
|
|
{
|
|
throw new Poco::NotFoundException("No display with number \"" + item_name + "\"!");
|
|
}
|
|
|
|
auto display = opt_display->get();
|
|
|
|
|
|
if(action == "write_score")
|
|
{
|
|
try
|
|
{
|
|
unsigned int numerical_score = std::stoi(score);
|
|
display->write_score(numerical_score);
|
|
}
|
|
catch(std::invalid_argument &e)
|
|
{
|
|
throw new Poco::InvalidArgumentException("Could not convert " + score + " to a number!\n" + e.what());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
throw new Poco::NotFoundException("No Action with name \"" + action + "\" on sounds!");
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
boost::optional<Poco::JSON::Object> OutputRequestHandler::parseFlipper(const std::string& item_name, const std::string& action)
|
|
{
|
|
if(item_name == "")
|
|
{
|
|
Poco::JSON::Object response;
|
|
response.set("flippers", getItemArray(this->output_driver->get_flippers()) );
|
|
return response;
|
|
}
|
|
|
|
auto opt_flipper = this->output_driver->get_flipper(item_name);
|
|
|
|
if(!opt_flipper)
|
|
{
|
|
throw new Poco::NotFoundException("No flipper with name \"" + item_name + "\"!");
|
|
}
|
|
|
|
auto flipper = opt_flipper->get();
|
|
|
|
if(action == "activate")
|
|
{
|
|
flipper->activate();
|
|
}
|
|
else if(action == "deactivate")
|
|
{
|
|
flipper->deactivate();
|
|
}
|
|
else
|
|
{
|
|
throw new Poco::NotFoundException("No action with name \"" + action + "\" on flippers!");
|
|
}
|
|
|
|
return {};
|
|
}
|
|
|
|
std::vector<std::string> OutputRequestHandler::getPathSegments(Poco::URI uri)
|
|
{
|
|
std::vector<std::string> path_segments;
|
|
uri.getPathSegments(path_segments);
|
|
return path_segments;
|
|
}
|
|
|
|
template<typename T>
|
|
Poco::JSON::Array getItemArray(const std::vector<std::shared_ptr<T>> & items)
|
|
{
|
|
Poco::JSON::Array array;
|
|
for ( auto & item : items )
|
|
{
|
|
Poco::JSON::Object var;
|
|
var.set("name", item->get_name());
|
|
array.add(var);
|
|
}
|
|
return array;
|
|
}
|
|
|
|
}
|
|
}
|
|
|