- prepare general way to send (proto) messages. currently only incomming protomessages are forwarded

- begin impl. of json server


Former-commit-id: 8f9237cd57ada1e84dc05e60b9ad723e47fd57b1
This commit is contained in:
redpanther
2016-02-15 18:25:18 +01:00
parent 5dc59344c4
commit b01b5eb005
12 changed files with 287 additions and 104 deletions

View File

@@ -1,66 +1,68 @@
# Define the current source locations
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/hyperion)
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/hyperion)
# Group the headers that go through the MOC compiler
SET(Hyperion_QT_HEADERS
${CURRENT_HEADER_DIR}/Hyperion.h
${CURRENT_SOURCE_DIR}/LinearColorSmoothing.h
)
SET(Hyperion_HEADERS
${CURRENT_HEADER_DIR}/ImageProcessor.h
${CURRENT_HEADER_DIR}/ImageProcessorFactory.h
${CURRENT_HEADER_DIR}/ImageToLedsMap.h
${CURRENT_HEADER_DIR}/LedString.h
${CURRENT_HEADER_DIR}/PriorityMuxer.h
${CURRENT_SOURCE_DIR}/MultiColorTransform.h
)
SET(Hyperion_SOURCES
${CURRENT_SOURCE_DIR}/Hyperion.cpp
${CURRENT_SOURCE_DIR}/ImageProcessor.cpp
${CURRENT_SOURCE_DIR}/ImageProcessorFactory.cpp
${CURRENT_SOURCE_DIR}/LedString.cpp
${CURRENT_SOURCE_DIR}/PriorityMuxer.cpp
${CURRENT_SOURCE_DIR}/ImageToLedsMap.cpp
${CURRENT_SOURCE_DIR}/MultiColorTransform.cpp
${CURRENT_SOURCE_DIR}/LinearColorSmoothing.cpp
)
set(Hyperion_RESOURCES
${CURRENT_SOURCE_DIR}/resource.qrc
)
if(ENABLE_QT5)
QT5_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS})
QT5_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress")
else(ENABLE_QT5)
QT4_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS})
QT4_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress")
endif(ENABLE_QT5)
add_library(hyperion
${Hyperion_HEADERS}
${Hyperion_QT_HEADERS}
${Hyperion_HEADERS_MOC}
${Hyperion_SOURCES}
${Hyperion_RESOURCES_RCC}
)
if(ENABLE_QT5)
qt5_use_modules(hyperion Widgets)
endif(ENABLE_QT5)
target_link_libraries(hyperion
blackborder
hyperion-utils
leddevice
effectengine
serialport
${QT_LIBRARIES}
)
# Define the current source locations
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/hyperion)
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/hyperion)
# Group the headers that go through the MOC compiler
SET(Hyperion_QT_HEADERS
${CURRENT_HEADER_DIR}/Hyperion.h
${CURRENT_HEADER_DIR}/MessageForwarder.h
${CURRENT_SOURCE_DIR}/LinearColorSmoothing.h
)
SET(Hyperion_HEADERS
${CURRENT_HEADER_DIR}/ImageProcessor.h
${CURRENT_HEADER_DIR}/ImageProcessorFactory.h
${CURRENT_HEADER_DIR}/ImageToLedsMap.h
${CURRENT_HEADER_DIR}/LedString.h
${CURRENT_HEADER_DIR}/PriorityMuxer.h
${CURRENT_SOURCE_DIR}/MultiColorTransform.h
)
SET(Hyperion_SOURCES
${CURRENT_SOURCE_DIR}/Hyperion.cpp
${CURRENT_SOURCE_DIR}/ImageProcessor.cpp
${CURRENT_SOURCE_DIR}/ImageProcessorFactory.cpp
${CURRENT_SOURCE_DIR}/LedString.cpp
${CURRENT_SOURCE_DIR}/PriorityMuxer.cpp
${CURRENT_SOURCE_DIR}/ImageToLedsMap.cpp
${CURRENT_SOURCE_DIR}/MultiColorTransform.cpp
${CURRENT_SOURCE_DIR}/LinearColorSmoothing.cpp
${CURRENT_SOURCE_DIR}/MessageForwarder.cpp
)
set(Hyperion_RESOURCES
${CURRENT_SOURCE_DIR}/resource.qrc
)
if(ENABLE_QT5)
QT5_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS})
QT5_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress")
else(ENABLE_QT5)
QT4_WRAP_CPP(Hyperion_HEADERS_MOC ${Hyperion_QT_HEADERS})
QT4_ADD_RESOURCES(Hyperion_RESOURCES_RCC ${Hyperion_RESOURCES} OPTIONS "-no-compress")
endif(ENABLE_QT5)
add_library(hyperion
${Hyperion_HEADERS}
${Hyperion_QT_HEADERS}
${Hyperion_HEADERS_MOC}
${Hyperion_SOURCES}
${Hyperion_RESOURCES_RCC}
)
if(ENABLE_QT5)
qt5_use_modules(hyperion Widgets)
endif(ENABLE_QT5)
target_link_libraries(hyperion
blackborder
hyperion-utils
leddevice
effectengine
serialport
${QT_LIBRARIES}
)

View File

@@ -267,12 +267,39 @@ LedDevice * Hyperion::createColorSmoothing(const Json::Value & smoothingConfig,
}
MessageForwarder * Hyperion::createMessageForwarder(const Json::Value & forwarderConfig)
{
MessageForwarder * forwarder = new MessageForwarder();
if ( ! forwarderConfig.isNull() )
{
if ( ! forwarderConfig["json"].isNull() && forwarderConfig["json"].isArray() )
{
for (const Json::Value& addr : forwarderConfig["json"])
forwarder->addJsonSlave(addr.asString());
}
if ( ! forwarderConfig["proto"].isNull() && forwarderConfig["proto"].isArray() )
{
for (const Json::Value& addr : forwarderConfig["proto"])
forwarder->addProtoSlave(addr.asString());
}
}
return forwarder;
}
MessageForwarder * Hyperion::getForwarder()
{
return _messageForwarder;
}
Hyperion::Hyperion(const Json::Value &jsonConfig) :
_ledString(createLedString(jsonConfig["leds"], createColorOrder(jsonConfig["device"]))),
_muxer(_ledString.leds().size()),
_raw2ledTransform(createLedColorsTransform(_ledString.leds().size(), jsonConfig["color"])),
_device(LedDeviceFactory::construct(jsonConfig["device"])),
_effectEngine(nullptr),
_messageForwarder(createMessageForwarder(jsonConfig["forwarder"])),
_timer()
{
if (!_raw2ledTransform->verifyTransforms())
@@ -314,6 +341,9 @@ Hyperion::~Hyperion()
// delete the color transform
delete _raw2ledTransform;
// delete the message forwarder
delete _messageForwarder;
}
unsigned Hyperion::getLedCount() const

View File

@@ -0,0 +1,34 @@
#include <hyperion/MessageForwarder.h>
MessageForwarder::MessageForwarder() :
_running(false)
{
}
MessageForwarder::~MessageForwarder()
{
}
void MessageForwarder::addJsonSlave(std::string slave)
{
std::cout << slave << std::endl;
}
void MessageForwarder::addProtoSlave(std::string slave)
{
_protoSlaves << QString(slave.c_str());
}
void MessageForwarder::sendMessage()
{
if ( ! _running )
return;
}
QStringList MessageForwarder::getProtoSlaves()
{
return _protoSlaves;
}

View File

@@ -250,8 +250,22 @@ void JsonClientConnection::handleMessage(const std::string &messageString)
handleNotImplemented();
}
void JsonClientConnection::forwardJsonMessage(const Json::Value & message)
{
QTcpSocket client;
client.connectToHost(QHostAddress("127.0.0.1"), 19444);
if ( client.waitForConnected(500) )
{
sendMessage(message,&client);
client.close();
}
}
void JsonClientConnection::handleColorCommand(const Json::Value &message)
{
forwardJsonMessage(message);
// extract parameters
int priority = message["priority"].asInt();
int duration = message.get("duration", -1).asInt();
@@ -289,6 +303,8 @@ void JsonClientConnection::handleColorCommand(const Json::Value &message)
void JsonClientConnection::handleImageCommand(const Json::Value &message)
{
forwardJsonMessage(message);
// extract parameters
int priority = message["priority"].asInt();
int duration = message.get("duration", -1).asInt();
@@ -320,6 +336,8 @@ void JsonClientConnection::handleImageCommand(const Json::Value &message)
void JsonClientConnection::handleEffectCommand(const Json::Value &message)
{
forwardJsonMessage(message);
// extract parameters
int priority = message["priority"].asInt();
int duration = message.get("duration", -1).asInt();
@@ -418,6 +436,8 @@ void JsonClientConnection::handleServerInfoCommand(const Json::Value &)
void JsonClientConnection::handleClearCommand(const Json::Value &message)
{
forwardJsonMessage(message);
// extract parameters
int priority = message["priority"].asInt();
@@ -428,8 +448,10 @@ void JsonClientConnection::handleClearCommand(const Json::Value &message)
sendSuccessReply();
}
void JsonClientConnection::handleClearallCommand(const Json::Value &)
void JsonClientConnection::handleClearallCommand(const Json::Value & message)
{
forwardJsonMessage(message);
// clear priority
_hyperion->clearall();
@@ -530,10 +552,51 @@ void JsonClientConnection::sendMessage(const Json::Value &message)
response.append(serializedReply.c_str(), serializedReply.length());
_socket->write(response.data(), response.length());
_socket->write(response.data(), response.length());
}
}
void JsonClientConnection::sendMessage(const Json::Value & message, QTcpSocket * socket)
{
// serialize message (FastWriter already appends a newline)
std::string serializedMessage = Json::FastWriter().write(message);
// write message
socket->write(serializedMessage.c_str());
if (!socket->waitForBytesWritten())
{
//std::cout << "Error while writing data to host" << std::endl;
return;
}
// read reply data
QByteArray serializedReply;
while (!serializedReply.contains('\n'))
{
// receive reply
if (!socket->waitForReadyRead())
{
//std::cout << "Error while reading data from host" << std::endl;
return;
}
serializedReply += socket->readAll();
}
int bytes = serializedReply.indexOf('\n') + 1; // Find the end of message
// parse reply data
Json::Reader jsonReader;
Json::Value reply;
if (!jsonReader.parse(serializedReply.constData(), serializedReply.constData() + bytes, reply))
{
//std::cout << "Error while parsing reply: invalid json" << std::endl;
return;
}
}
void JsonClientConnection::sendSuccessReply()
{
// create reply

View File

@@ -124,6 +124,7 @@ private:
/// @param message The JSON message to send
///
void sendMessage(const Json::Value & message);
void sendMessage(const Json::Value & message, QTcpSocket * socket);
///
/// Send a standard reply indicating success
@@ -147,6 +148,11 @@ private:
///
void handleWebSocketFrame();
///
/// forward json message
///
void forwardJsonMessage(const Json::Value & message);
private:
///
/// Check if a JSON messag is valid according to a given JSON schema

View File

@@ -20,7 +20,7 @@
// project includes
#include "ProtoClientConnection.h"
ProtoClientConnection::ProtoClientConnection(QTcpSocket *socket, Hyperion * hyperion, QStringList forwardClientList) :
ProtoClientConnection::ProtoClientConnection(QTcpSocket *socket, Hyperion * hyperion) :
QObject(),
_socket(socket),
_imageProcessor(ImageProcessorFactory::getInstance().newImageProcessor()),
@@ -30,22 +30,11 @@ ProtoClientConnection::ProtoClientConnection(QTcpSocket *socket, Hyperion * hype
// connect internal signals and slots
connect(_socket, SIGNAL(disconnected()), this, SLOT(socketClosed()));
connect(_socket, SIGNAL(readyRead()), this, SLOT(readData()));
for (int i = 0; i < forwardClientList.size(); ++i) {
std::cout << "Proto forward to " << forwardClientList.at(i).toLocal8Bit().constData() << std::endl;
ProtoConnection* p = new ProtoConnection("127.0.0.1:19445");
p->setSkipReply(true);
_proxy_connections << p;
}
}
ProtoClientConnection::~ProtoClientConnection()
{
delete _socket;
while (!_proxy_connections.isEmpty())
delete _proxy_connections.takeFirst();
}
void ProtoClientConnection::readData()
@@ -93,8 +82,7 @@ void ProtoClientConnection::socketClosed()
void ProtoClientConnection::handleMessage(const proto::HyperionRequest & message)
{
// forward messages
for (int i = 0; i < _proxy_connections.size(); ++i)
_proxy_connections.at(i)->sendMessage(message);
emit newMessage(&message);
switch (message.command())
{

View File

@@ -30,7 +30,7 @@ public:
/// @param socket The Socket object for this connection
/// @param hyperion The Hyperion server
///
ProtoClientConnection(QTcpSocket * socket, Hyperion * hyperion, QStringList forwardClientList);
ProtoClientConnection(QTcpSocket * socket, Hyperion * hyperion);
///
/// Destructor
@@ -43,6 +43,7 @@ signals:
/// @param connection This connection object
///
void connectionClosed(ProtoClientConnection * connection);
void newMessage(const proto::HyperionRequest * message);
private slots:
///
@@ -125,8 +126,4 @@ private:
/// The buffer used for reading data from the socket
QByteArray _receiveBuffer;
/// Hyperion proto connection object for forwarding
QList<ProtoConnection*> _proxy_connections;
};

View File

@@ -2,17 +2,27 @@
#include <stdexcept>
// project includes
#include <hyperion/MessageForwarder.h>
#include <protoserver/ProtoServer.h>
#include "protoserver/ProtoConnection.h"
#include "ProtoClientConnection.h"
ProtoServer::ProtoServer(Hyperion *hyperion, uint16_t port, QStringList * forwardClientList) :
ProtoServer::ProtoServer(Hyperion *hyperion, uint16_t port) :
QObject(),
_hyperion(hyperion),
_server(),
_openConnections()
{
for (int i = 0; i < forwardClientList->size(); ++i)
_forwardClients << forwardClientList->at(i);
MessageForwarder * forwarder = hyperion->getForwarder();
QStringList slaves = forwarder->getProtoSlaves();
for (int i = 0; i < slaves.size(); ++i) {
std::cout << "Proto forward to " << slaves.at(i).toLocal8Bit().constData() << std::endl;
ProtoConnection* p = new ProtoConnection(slaves.at(i).toLocal8Bit().constData());
p->setSkipReply(true);
_proxy_connections << p;
}
if (!_server.listen(QHostAddress::Any, port))
{
@@ -28,6 +38,9 @@ ProtoServer::~ProtoServer()
foreach (ProtoClientConnection * connection, _openConnections) {
delete connection;
}
while (!_proxy_connections.isEmpty())
delete _proxy_connections.takeFirst();
}
uint16_t ProtoServer::getPort() const
@@ -42,14 +55,22 @@ void ProtoServer::newConnection()
if (socket != nullptr)
{
std::cout << "New proto connection" << std::endl;
ProtoClientConnection * connection = new ProtoClientConnection(socket, _hyperion, _forwardClients);
ProtoClientConnection * connection = new ProtoClientConnection(socket, _hyperion);
_openConnections.insert(connection);
// register slot for cleaning up after the connection closed
connect(connection, SIGNAL(connectionClosed(ProtoClientConnection*)), this, SLOT(closedConnection(ProtoClientConnection*)));
connect(connection, SIGNAL(newMessage(const proto::HyperionRequest*)), this, SLOT(newMessage(const proto::HyperionRequest*)));
}
}
void ProtoServer::newMessage(const proto::HyperionRequest * message)
{
for (int i = 0; i < _proxy_connections.size(); ++i)
_proxy_connections.at(i)->sendMessage(*message);
}
void ProtoServer::closedConnection(ProtoClientConnection *connection)
{
std::cout << "Proto connection closed" << std::endl;