restored OUtputPinController

This commit is contained in:
Jonas Zeunert
2019-05-06 21:31:17 +02:00
parent bc583a5a92
commit 1b90bf7518
12 changed files with 103 additions and 9 deletions

View File

@@ -0,0 +1,23 @@
cmake_minimum_required(VERSION 3.6.2)
project(flippR_driver_networking)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_SOURCE_DIR}/${OUTPUT_PATH}/cli)
set(SOURCES
input/SocketHandler.cpp
output/OutputRequestHandler.cpp
output/OutputRequestHandlerFactory.cpp
)
add_executable(${PROJECT_NAME} ${SOURCES})
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/include)
target_link_libraries(${PROJECT_NAME} PRIVATE FlippR-Driver)
####################### POCO ##############################
find_package(Poco REQUIRED COMPONENTS Foundation Net JSON )
if(NOT Poco_FOUND)
message(FATAL_ERROR, "Could not find libPoco")
endif()
target_link_libraries(${PROJECT_NAME} PUBLIC Poco::Foundation Poco::Net Poco::JSON)

View File

@@ -0,0 +1,59 @@
/*
* SocketConnection.cpp
*
* Created on: Jun 13, 2018
* Author: Andreas Schneider, Johannes Wendel, Jonas Zeunert
*/
#include "SocketHandler.h"
using Poco::Net::StreamSocket;
using Poco::Net::TCPServerConnection;
using flippR_driver::input::InputDriver;
using flippR_driver::input::detail::EventHandler;
using flippR_driver::input::Event;
namespace flippR_driver
{
namespace utility
{
namespace networking
{
namespace input
{
SocketHandler::SocketHandler(StreamSocket streamSocket, std::shared_ptr<InputDriver> inputDriver) :
TCPServerConnection(streamSocket),
EventHandler(inputDriver)
{
}
void SocketHandler::run()
{
StreamSocket& streamSocket = socket();
while(true)
{
Event event = this->queue->pop();
if(event.name == "END")
{
return;
}
std::string str = event.getJsonString();
streamSocket.sendBytes(str.c_str(), str.length());
}
}
void SocketHandler::handle(Event &event)
{
this->queue->push(event);
}
}
}
}
}

View File

@@ -0,0 +1,44 @@
/*
* SocketConnection.h
*
* Created on: Jun 13, 2018
* Author: Andreas Schneider, Johannes Wendel, Jonas Zeunert
*/
#ifndef FLIPPR_CODE_INPUTSOCKETCONNECTION_H
#define FLIPPR_CODE_INPUTSOCKETCONNECTION_H
#include <Poco/Net/TCPServerConnection.h>
#include "utility/IBlockingQueue.h"
#include "input/InputDriver.h"
#include "input/detail/EventHandler.h"
#include "input/Event.h"
namespace flippR_driver
{
namespace utility
{
namespace networking
{
namespace input
{
class SocketHandler : public Poco::Net::TCPServerConnection, flippR_driver::input::detail::EventHandler
{
public:
SocketHandler(Poco::Net::StreamSocket streamSocket, std::shared_ptr<flippR_driver::input::InputDriver> input_driver);
void run() override;
void handle(flippR_driver::input::Event &event) override;
private:
flippR_driver::utility::IBlockingQueue<flippR_driver::input::Event>* queue;
};
}
}
}
}
#endif //FLIPPR_CODE_INPUTSOCKETCONNECTION_H

View File

@@ -0,0 +1,21 @@
//
// Created by rhetenor on 4/15/19.
//
#include <Poco/Net/HTTPServerParams.h>
#include "OutputHTTPServer.h"
#include "OutputRequestHandlerFactory.h"
namespace flippR_driver
{
namespace utility
{
using namespace Poco::Net;
OutputHTTPServer::OutputHTTPServer(std::shared_ptr<output::OutputDriver> output_driver, Socket &socket) :
HTTPServer(new OutputRequestHandlerFactory(output_driver), socket, new HTTPServerParams())
{}
}
}

View File

@@ -0,0 +1,28 @@
//
// Created by rhetenor on 4/15/19.
//
#ifndef FLIPPR_CODE_OUTPUTHTTPSERVER_H
#define FLIPPR_CODE_OUTPUTHTTPSERVER_H
#include <Poco/Net/HTTPServer.h>
#include <Poco/Net/Socket.h>
#include "output/OutputDriver.h"
namespace flippR_driver
{
namespace utility
{
class OutputHTTPServer : public Poco::Net::HTTPServer
{
public:
explicit OutputHTTPServer(std::shared_ptr<output::OutputDriver> output_driver, Poco::Net::Socket &socket);
};
}
}
#endif //FLIPPR_CODE_OUTPUTHTTPSERVER_H

View File

@@ -0,0 +1,260 @@
//
// 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 utility
{
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();
return;
}
if(item_type == "activate")
{
this->output_driver->activate_displays();
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
{
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", 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", 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", 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 {};
}
std::vector<std::string> OutputRequestHandler::getPathSegments(Poco::URI uri)
{
std::vector<std::string> path_segments;
uri.getPathSegments(path_segments);
return path_segments;
}
}
}

View File

@@ -0,0 +1,48 @@
//
// Created by rhetenor on 3/6/19.
//
#ifndef FLIPPR_CODE_OUTPUTREQUESTHANDLER_H
#define FLIPPR_CODE_OUTPUTREQUESTHANDLER_H
#include <Poco/Net/HTTPRequestHandler.h>
#include <Poco/URI.h>
#include <Poco/JSON/JSON.h>
#include <memory>
#include <boost/optional.hpp>
#include <Poco/JSON/Object.h>
#include "output/OutputDriver.h"
namespace flippR_driver
{
namespace utility
{
class OutputRequestHandler : public Poco::Net::HTTPRequestHandler
{
public:
OutputRequestHandler(std::shared_ptr<output::OutputDriver> output_driver);
void handleRequest(Poco::Net::HTTPServerRequest &request, Poco::Net::HTTPServerResponse &response) override;
private:
boost::optional<Poco::JSON::Object> parseRequest(const std::string& item_type, const std::string& item_name, const std::string& action, const std::string& score = 0);
boost::optional<Poco::JSON::Object> parseSolenoid(const std::string& item_name, const std::string& action);
boost::optional<Poco::JSON::Object> parseLamp(const std::string& item_name, const std::string& action);
boost::optional<Poco::JSON::Object> parseSound(const std::string& item_name, const std::string& action);
boost::optional<Poco::JSON::Object> parseDisplay(const std::string& item_name, const std::string& action, const std::string& score);
std::vector<std::string> getPathSegments(Poco::URI uri);
private:
std::shared_ptr<output::OutputDriver> output_driver;
};
}
}
#endif //FLIPPR_CODE_OUTPUTREQUESTHANDLER_H

View File

@@ -0,0 +1,24 @@
//
// Created by rhetenor on 4/15/19.
//
#include "OutputRequestHandlerFactory.h"
#include "OutputRequestHandler.h"
namespace flippR_driver
{
namespace utility
{
using namespace Poco::Net;
OutputRequestHandlerFactory::OutputRequestHandlerFactory(std::shared_ptr<output::OutputDriver> output_driver) :
output_driver(output_driver)
{}
HTTPRequestHandler *OutputRequestHandlerFactory::createRequestHandler(const HTTPServerRequest &request)
{
return new OutputRequestHandler(this->output_driver);
}
}
}

View File

@@ -0,0 +1,31 @@
//
// Created by rhetenor on 4/15/19.
//
#ifndef FLIPPR_CODE_OUTPUTREQUESTHANDLERFACTORY_H
#define FLIPPR_CODE_OUTPUTREQUESTHANDLERFACTORY_H
#include <Poco/Net/HTTPRequestHandlerFactory.h>
#include <memory>
#include "output/OutputDriver.h"
namespace flippR_driver
{
namespace utility
{
class OutputRequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory
{
public:
explicit OutputRequestHandlerFactory(std::shared_ptr<output::OutputDriver> output_driver);
Poco::Net::HTTPRequestHandler* createRequestHandler(const Poco::Net::HTTPServerRequest& request) override;
private:
std::shared_ptr<output::OutputDriver> output_driver;
};
}
}
#endif //FLIPPR_CODE_OUTPUTREQUESTHANDLERFACTORY_H