mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
added skeleton for the json connection server
This commit is contained in:
parent
2c97353a11
commit
16c260b3dc
36
include/jsonserver/JsonServer.h
Normal file
36
include/jsonserver/JsonServer.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// system includes
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
// Qt includes
|
||||||
|
#include <QTcpServer>
|
||||||
|
#include <QSet>
|
||||||
|
|
||||||
|
// Hyperion includes
|
||||||
|
#include <hyperion/Hyperion.h>
|
||||||
|
|
||||||
|
class JsonClientConnection;
|
||||||
|
|
||||||
|
class JsonServer : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
JsonServer(Hyperion * hyperion, uint16_t port = 19444);
|
||||||
|
~JsonServer();
|
||||||
|
|
||||||
|
uint16_t getPort() const;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void newConnection();
|
||||||
|
|
||||||
|
void closedConnection(JsonClientConnection * connection);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Hyperion * _hyperion;
|
||||||
|
|
||||||
|
QTcpServer _server;
|
||||||
|
|
||||||
|
QSet<JsonClientConnection *> _openConnections;
|
||||||
|
};
|
@ -4,4 +4,5 @@ SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include)
|
|||||||
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc)
|
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc)
|
||||||
|
|
||||||
add_subdirectory(hyperion)
|
add_subdirectory(hyperion)
|
||||||
|
add_subdirectory(jsonserver)
|
||||||
add_subdirectory(utils)
|
add_subdirectory(utils)
|
||||||
|
36
libsrc/jsonserver/CMakeLists.txt
Normal file
36
libsrc/jsonserver/CMakeLists.txt
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
|
||||||
|
# Define the current source locations
|
||||||
|
SET(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/jsonserver)
|
||||||
|
SET(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/jsonserver)
|
||||||
|
|
||||||
|
# Group the headers that go through the MOC compiler
|
||||||
|
SET(JsonServer_QT_HEADERS
|
||||||
|
${CURRENT_HEADER_DIR}/JsonServer.h
|
||||||
|
${CURRENT_SOURCE_DIR}/JsonClientConnection.h
|
||||||
|
)
|
||||||
|
|
||||||
|
SET(JsonServer_HEADERS
|
||||||
|
)
|
||||||
|
|
||||||
|
SET(JsonServer_SOURCES
|
||||||
|
${CURRENT_SOURCE_DIR}/JsonServer.cpp
|
||||||
|
${CURRENT_SOURCE_DIR}/JsonClientConnection.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
qt4_wrap_cpp(JsonServer_HEADERS_MOC ${JsonServer_QT_HEADERS})
|
||||||
|
|
||||||
|
add_library(jsonserver
|
||||||
|
${JsonServer_HEADERS}
|
||||||
|
${JsonServer_QT_HEADERS}
|
||||||
|
${JsonServer_HEADERS_MOC}
|
||||||
|
${JsonServer_SOURCES}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(jsonserver
|
||||||
|
hyperion
|
||||||
|
jsoncpp)
|
||||||
|
|
||||||
|
qt4_use_modules(jsonserver
|
||||||
|
Core
|
||||||
|
Gui
|
||||||
|
Network)
|
77
libsrc/jsonserver/JsonClientConnection.cpp
Normal file
77
libsrc/jsonserver/JsonClientConnection.cpp
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
// stl includes
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "JsonClientConnection.h"
|
||||||
|
|
||||||
|
JsonClientConnection::JsonClientConnection(QTcpSocket *socket) :
|
||||||
|
QObject(),
|
||||||
|
_socket(socket)
|
||||||
|
{
|
||||||
|
connect(_socket, SIGNAL(disconnected()), this, SLOT(socketClosed()));
|
||||||
|
connect(_socket, SIGNAL(readyRead()), this, SLOT(readData()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
JsonClientConnection::~JsonClientConnection()
|
||||||
|
{
|
||||||
|
delete _socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonClientConnection::readData()
|
||||||
|
{
|
||||||
|
_receiveBuffer += _socket->readAll();
|
||||||
|
|
||||||
|
int bytes = _receiveBuffer.indexOf('\n') + 1;
|
||||||
|
if (bytes != 0)
|
||||||
|
{
|
||||||
|
// create message string
|
||||||
|
std::string message(_receiveBuffer.data(), bytes);
|
||||||
|
|
||||||
|
// remove message data from buffer
|
||||||
|
_receiveBuffer = _receiveBuffer.mid(bytes);
|
||||||
|
|
||||||
|
// handle message
|
||||||
|
handleMessage(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonClientConnection::socketClosed()
|
||||||
|
{
|
||||||
|
emit connectionClosed(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonClientConnection::handleMessage(const std::string &message)
|
||||||
|
{
|
||||||
|
Json::Reader reader;
|
||||||
|
Json::Value messageRoot;
|
||||||
|
if (!reader.parse(message, messageRoot, false))
|
||||||
|
{
|
||||||
|
sendErrorReply("Error while parsing json: " + reader.getFormattedErrorMessages());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleNotImplemented(messageRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonClientConnection::handleNotImplemented(const Json::Value & message)
|
||||||
|
{
|
||||||
|
sendErrorReply("Command not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonClientConnection::sendMessage(const Json::Value &message)
|
||||||
|
{
|
||||||
|
Json::FastWriter writer;
|
||||||
|
std::string serializedReply = writer.write(message);
|
||||||
|
_socket->write(serializedReply.data(), serializedReply.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonClientConnection::sendErrorReply(const std::string &error)
|
||||||
|
{
|
||||||
|
// create reply
|
||||||
|
Json::Value reply;
|
||||||
|
reply["success"] = false;
|
||||||
|
reply["error"] = error;
|
||||||
|
|
||||||
|
// send reply
|
||||||
|
sendMessage(reply);
|
||||||
|
}
|
39
libsrc/jsonserver/JsonClientConnection.h
Normal file
39
libsrc/jsonserver/JsonClientConnection.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// stl includes
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// Qt includes
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QTcpSocket>
|
||||||
|
|
||||||
|
// jsoncpp includes
|
||||||
|
#include <json/json.h>
|
||||||
|
|
||||||
|
class JsonClientConnection : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
JsonClientConnection(QTcpSocket * socket);
|
||||||
|
~JsonClientConnection();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void connectionClosed(JsonClientConnection * connection);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void readData();
|
||||||
|
void socketClosed();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void handleMessage(const std::string & message);
|
||||||
|
void handleNotImplemented(const Json::Value & message);
|
||||||
|
|
||||||
|
void sendMessage(const Json::Value & message);
|
||||||
|
void sendErrorReply(const std::string & error);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QTcpSocket * _socket;
|
||||||
|
|
||||||
|
QByteArray _receiveBuffer;
|
||||||
|
};
|
57
libsrc/jsonserver/JsonServer.cpp
Normal file
57
libsrc/jsonserver/JsonServer.cpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
// system includes
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
// project includes
|
||||||
|
#include <jsonserver/JsonServer.h>
|
||||||
|
#include "JsonClientConnection.h"
|
||||||
|
|
||||||
|
JsonServer::JsonServer(Hyperion *hyperion, uint16_t port) :
|
||||||
|
QObject(),
|
||||||
|
_hyperion(hyperion),
|
||||||
|
_server(),
|
||||||
|
_openConnections()
|
||||||
|
{
|
||||||
|
if (!_server.listen(QHostAddress::Any, port))
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Json server could not bind to port");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set trigger for incoming connections
|
||||||
|
connect(&_server, SIGNAL(newConnection()), this, SLOT(newConnection()));
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonServer::~JsonServer()
|
||||||
|
{
|
||||||
|
foreach (JsonClientConnection * connection, _openConnections) {
|
||||||
|
delete connection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t JsonServer::getPort() const
|
||||||
|
{
|
||||||
|
return _server.serverPort();
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonServer::newConnection()
|
||||||
|
{
|
||||||
|
std::cout << "New incoming json connection" << std::endl;
|
||||||
|
QTcpSocket * socket = _server.nextPendingConnection();
|
||||||
|
|
||||||
|
if (socket != nullptr)
|
||||||
|
{
|
||||||
|
JsonClientConnection * connection = new JsonClientConnection(socket);
|
||||||
|
_openConnections.insert(connection);
|
||||||
|
|
||||||
|
// register slot for cleaning up after the connection closed
|
||||||
|
connect(connection, SIGNAL(connectionClosed(JsonClientConnection*)), this, SLOT(closedConnection(JsonClientConnection*)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void JsonServer::closedConnection(JsonClientConnection *connection)
|
||||||
|
{
|
||||||
|
std::cout << "Json connection closed" << std::endl;
|
||||||
|
_openConnections.remove(connection);
|
||||||
|
|
||||||
|
// schedule to delete the connection object
|
||||||
|
connection->deleteLater();
|
||||||
|
}
|
@ -6,7 +6,8 @@ add_executable(hyperiond
|
|||||||
hyperion-d.cpp)
|
hyperion-d.cpp)
|
||||||
|
|
||||||
target_link_libraries(hyperiond
|
target_link_libraries(hyperiond
|
||||||
hyperion)
|
hyperion
|
||||||
|
jsonserver)
|
||||||
|
|
||||||
# Find the libPNG
|
# Find the libPNG
|
||||||
find_package(PNG QUIET)
|
find_package(PNG QUIET)
|
||||||
|
@ -9,6 +9,9 @@
|
|||||||
#include <hyperion/DispmanxWrapper.h>
|
#include <hyperion/DispmanxWrapper.h>
|
||||||
#include <hyperion/Hyperion.h>
|
#include <hyperion/Hyperion.h>
|
||||||
|
|
||||||
|
// JsonServer includes
|
||||||
|
#include <jsonserver/JsonServer.h>
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
// Initialising QCoreApplication
|
// Initialising QCoreApplication
|
||||||
@ -16,9 +19,9 @@ int main(int argc, char** argv)
|
|||||||
std::cout << "QCoreApplication initialised" << std::endl;
|
std::cout << "QCoreApplication initialised" << std::endl;
|
||||||
|
|
||||||
// Select config and schema file
|
// Select config and schema file
|
||||||
const std::string homeDir = getenv("RASPILIGHT_HOME");
|
//const std::string homeDir = getenv("RASPILIGHT_HOME");
|
||||||
const std::string schemaFile = homeDir + "/hyperion.schema.json";
|
const std::string schemaFile = "hyperion.schema.json";
|
||||||
const std::string configFile = homeDir + "/hyperion.config.json";
|
const std::string configFile = "hyperion.config.json";
|
||||||
|
|
||||||
// Load configuration and check against the schema at the same time
|
// Load configuration and check against the schema at the same time
|
||||||
Json::Value config;
|
Json::Value config;
|
||||||
@ -36,6 +39,9 @@ int main(int argc, char** argv)
|
|||||||
dispmanx.start();
|
dispmanx.start();
|
||||||
std::cout << "Frame grabber created and started" << std::endl;
|
std::cout << "Frame grabber created and started" << std::endl;
|
||||||
|
|
||||||
|
JsonServer jsonServer(&hyperion);
|
||||||
|
std::cout << "Json server created and started on port " << jsonServer.getPort() << std::endl;
|
||||||
|
|
||||||
app.exec();
|
app.exec();
|
||||||
std::cout << "Application closed" << std::endl;
|
std::cout << "Application closed" << std::endl;
|
||||||
}
|
}
|
||||||
|
@ -210,16 +210,15 @@ void JsonConnection::setTransform(ColorTransformValues *threshold, ColorTransfor
|
|||||||
|
|
||||||
Json::Value JsonConnection::sendMessage(const Json::Value & message)
|
Json::Value JsonConnection::sendMessage(const Json::Value & message)
|
||||||
{
|
{
|
||||||
|
// serialize message (FastWriter already appends a newline)
|
||||||
|
std::string serializedMessage = Json::FastWriter().write(message);
|
||||||
|
|
||||||
// print command if requested
|
// print command if requested
|
||||||
if (_printJson)
|
if (_printJson)
|
||||||
{
|
{
|
||||||
std::cout << "Command: " << message << std::endl;
|
std::cout << "Command: " << serializedMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
// serialize message (FastWriter already appends a newline
|
|
||||||
Json::FastWriter jsonWriter;
|
|
||||||
std::string serializedMessage = jsonWriter.write(message);
|
|
||||||
|
|
||||||
// write message
|
// write message
|
||||||
_socket.write(serializedMessage.c_str());
|
_socket.write(serializedMessage.c_str());
|
||||||
if (!_socket.waitForBytesWritten())
|
if (!_socket.waitForBytesWritten())
|
||||||
@ -241,6 +240,12 @@ Json::Value JsonConnection::sendMessage(const Json::Value & message)
|
|||||||
}
|
}
|
||||||
int bytes = serializedReply.indexOf('\n') + 1; // Find the end of message
|
int bytes = serializedReply.indexOf('\n') + 1; // Find the end of message
|
||||||
|
|
||||||
|
// print reply if requested
|
||||||
|
if (_printJson)
|
||||||
|
{
|
||||||
|
std::cout << "Reply: " << std::string(serializedReply.data(), bytes);
|
||||||
|
}
|
||||||
|
|
||||||
// parse reply data
|
// parse reply data
|
||||||
Json::Reader jsonReader;
|
Json::Reader jsonReader;
|
||||||
Json::Value reply;
|
Json::Value reply;
|
||||||
@ -249,12 +254,6 @@ Json::Value JsonConnection::sendMessage(const Json::Value & message)
|
|||||||
throw std::runtime_error("Error while parsing reply: invalid json");
|
throw std::runtime_error("Error while parsing reply: invalid json");
|
||||||
}
|
}
|
||||||
|
|
||||||
// print reply if requested
|
|
||||||
if (_printJson)
|
|
||||||
{
|
|
||||||
std::cout << "Reply:" << reply << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,12 +270,12 @@ bool JsonConnection::parseReply(const Json::Value &reply)
|
|||||||
}
|
}
|
||||||
catch (const std::runtime_error &)
|
catch (const std::runtime_error &)
|
||||||
{
|
{
|
||||||
// Some json paring error: ignore and set parsing error
|
// Some json parsing error: ignore and set parsing error
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!success)
|
if (!success)
|
||||||
{
|
{
|
||||||
throw std::runtime_error("Error while paring reply: " + reason);
|
throw std::runtime_error("Error while executing command: " + reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
|
Loading…
Reference in New Issue
Block a user