remove protobuf

This commit is contained in:
Paulchen-Panther 2018-12-30 16:43:22 +01:00
parent 2a77f6f012
commit 559311e18c
No known key found for this signature in database
GPG Key ID: D45BA68A28471D4A
20 changed files with 6 additions and 1325 deletions

3
.gitmodules vendored
View File

@ -1,6 +1,3 @@
[submodule "dependencies/external/protobuf"]
path = dependencies/external/protobuf
url = https://github.com/hyperion-project/protobuf.git
[submodule "dependencies/external/rpi_ws281x"]
path = dependencies/external/rpi_ws281x
url = https://github.com/hyperion-project/rpi_ws281x.git

View File

@ -22,7 +22,6 @@ SET ( DEFAULT_OSX OFF )
SET ( DEFAULT_X11 OFF )
SET ( DEFAULT_WS281XPWM OFF )
SET ( DEFAULT_USE_SHARED_AVAHI_LIBS ON )
SET ( DEFAULT_USE_SYSTEM_PROTO_LIBS OFF )
SET ( DEFAULT_USE_SYSTEM_FLATBUFFERS_LIBS OFF )
SET ( DEFAULT_TESTS OFF )
@ -161,9 +160,6 @@ option(ENABLE_PROFILER "enable profiler capabilities - not for release code" OFF
message(STATUS "ENABLE_PROFILER = ${ENABLE_PROFILER}")
SET ( PROTOBUF_INSTALL_BIN_DIR ${CMAKE_BINARY_DIR}/proto )
SET ( PROTOBUF_INSTALL_LIB_DIR ${CMAKE_BINARY_DIR}/proto )
SET ( FLATBUFFERS_INSTALL_BIN_DIR ${CMAKE_BINARY_DIR}/flatbuf )
SET ( FLATBUFFERS_INSTALL_LIB_DIR ${CMAKE_BINARY_DIR}/flatbuf )

View File

@ -47,7 +47,7 @@
"dashboard_infobox_label_latesthyp" : "Aktuellste Hyperion Version:",
"dashboard_infobox_label_platform" : "Plattform:",
"dashboard_infobox_label_instance" : "Instanz:",
"dashboard_infobox_label_ports" : "Ports (json|proto):",
"dashboard_infobox_label_ports" : "Port flatbuf:",
"dashboard_infobox_message_updatewarning" : "Eine aktuellere Version von Hyperion ist verfügbar! (V$1)",
"dashboard_infobox_message_updatesuccess" : "Du nutzt die aktuellste Version von Hyperion.",
"dashboard_infobox_label_statush" : "Hyperion Status:",
@ -166,6 +166,7 @@
"conf_network_proto_intro" : "Der PROTO-Port dieser Hyperion-Instanz, wird genutzt für \"Bildstreams\" (HyperionScreenCap, Kodi Adddon, ...)",
"conf_network_bobl_intro" : "Boblight Empfänger",
"conf_network_udpl_intro" : "UDP Empfänger",
"conf_network_fbs_intro" : "Google Flatbuffers Empfänger. Wird genutzt für schnellen Bildempfang.",
"conf_network_forw_intro" : "Leite alles an eine zweite Hyperion Instanz weiter, diese kann dann mit einer anderen LED Steuerung genutzt werden",
"conf_logging_label_intro" : "Überprüfe die Meldungen im Prokotoll um zu erfahren was Hyperion gerade beschäftigt. Je nach eingestellter Protokoll-Stufe siehst du mehr oder weniger Informationen.",
"conf_logging_btn_pbupload" : "Bericht für Supportanfrage hochladen",
@ -562,7 +563,7 @@
"edt_conf_fw_proto_expl" : "Ein Proto Ziel pro Zeile. Bestehend aus IP:PORT (Beispiel: 127.0.0.1:19447)",
"edt_conf_fw_proto_itemtitle" : "Proto Ziel",
"edt_conf_js_heading_title" : "JSON Server",
"edt_conf_ps_heading_title" : "PROTO Server",
"edt_conf_fbs_heading_title" : "Flatbuffers Server",
"edt_conf_bobls_heading_title" : "Boblight Server",
"edt_conf_udpl_heading_title" : "UDP Listener",
"edt_conf_udpl_address_title" : "Adresse",

View File

@ -47,7 +47,7 @@
"dashboard_infobox_label_latesthyp" : "Latest Hyperion version:",
"dashboard_infobox_label_platform" : "Platform:",
"dashboard_infobox_label_instance" : "Instance:",
"dashboard_infobox_label_ports" : "Ports (json|proto):",
"dashboard_infobox_label_ports" : "Port flatbuf:",
"dashboard_infobox_message_updatewarning" : "A newer version of Hyperion is available! ($1)",
"dashboard_infobox_message_updatesuccess" : "You run the latest version of Hyperion.",
"dashboard_infobox_label_statush" : "Hyperion status:",
@ -166,6 +166,7 @@
"conf_network_proto_intro" : "The PROTO-Port of this Hyperion instance, used for picture streams (HyperionScreenCap, Kodi Adddon, ...)",
"conf_network_bobl_intro" : "Receiver for Boblight",
"conf_network_udpl_intro" : "Receiver for UDP",
"conf_network_fbs_intro" : "Google Flatbuffers Receiver. Used for fast image transmission.",
"conf_network_forw_intro" : "Forward all input to a second Hyperion instance which could be driven with another led controller",
"conf_logging_label_intro" : "Area to check log messages, depending on loglevel setting you see more or less information.",
"conf_logging_btn_pbupload" : "Upload report for support request",
@ -563,7 +564,7 @@
"edt_conf_fw_proto_expl" : "One proto target per line. Contains IP:PORT (Example: 127.0.0.1:19447)",
"edt_conf_fw_proto_itemtitle" : "Proto target",
"edt_conf_js_heading_title" : "JSON Server",
"edt_conf_ps_heading_title" : "PROTO Server",
"edt_conf_fbs_heading_title" : "Flatbuffers Server",
"edt_conf_bobls_heading_title" : "Boblight Server",
"edt_conf_udpl_heading_title" : "UDP Listener",
"edt_conf_udpl_address_title" : "Address",

View File

@ -16,11 +16,6 @@ $(document).ready( function() {
$('#conf_cont_json').append(createOptPanel('fa-sitemap', $.i18n("edt_conf_js_heading_title"), 'editor_container_jsonserver', 'btn_submit_jsonserver'));
$('#conf_cont_json').append(createHelpTable(schema.jsonServer.properties, $.i18n("edt_conf_js_heading_title")));
//protoserver
$('#conf_cont').append(createRow('conf_cont_proto'))
$('#conf_cont_proto').append(createOptPanel('fa-sitemap', $.i18n("edt_conf_ps_heading_title"), 'editor_container_protoserver', 'btn_submit_protoserver'));
$('#conf_cont_proto').append(createHelpTable(schema.protoServer.properties, $.i18n("edt_conf_ps_heading_title")));
//flatbufserver
$('#conf_cont').append(createRow('conf_cont_flatbuf'))
$('#conf_cont_flatbuf').append(createOptPanel('fa-sitemap', $.i18n("edt_conf_fbs_heading_title"), 'editor_container_fbserver', 'btn_submit_fbserver'));
@ -48,7 +43,6 @@ $(document).ready( function() {
{
$('#conf_cont').addClass('row');
$('#conf_cont').append(createOptPanel('fa-sitemap', $.i18n("edt_conf_js_heading_title"), 'editor_container_jsonserver', 'btn_submit_jsonserver'));
$('#conf_cont').append(createOptPanel('fa-sitemap', $.i18n("edt_conf_ps_heading_title"), 'editor_container_protoserver', 'btn_submit_protoserver'));
$('#conf_cont').append(createOptPanel('fa-sitemap', $.i18n("edt_conf_fbs_heading_title"), 'editor_container_fbserver', 'btn_submit_fbserver'));
$('#conf_cont').append(createOptPanel('fa-sitemap', $.i18n("edt_conf_bobls_heading_title"), 'editor_container_boblightserver', 'btn_submit_boblightserver'));
$('#conf_cont').append(createOptPanel('fa-sitemap', $.i18n("edt_conf_udpl_heading_title"), 'editor_container_udplistener', 'btn_submit_udplistener'));
@ -69,19 +63,6 @@ $(document).ready( function() {
requestWriteConfig(conf_editor_json.getValue());
});
//protobuffer
conf_editor_proto = createJsonEditor('editor_container_protoserver', {
protoServer : schema.protoServer
}, true, true);
conf_editor_proto.on('change',function() {
conf_editor_proto.validate().length ? $('#btn_submit_protoserver').attr('disabled', true) : $('#btn_submit_protoserver').attr('disabled', false);
});
$('#btn_submit_protoserver').off().on('click',function() {
requestWriteConfig(conf_editor_proto.getValue());
});
//flatbuffer
conf_editor_fbs = createJsonEditor('editor_container_fbserver', {
flatbufServer : schema.flatbufServer
@ -141,7 +122,6 @@ $(document).ready( function() {
if(showOptHelp)
{
createHint("intro", $.i18n('conf_network_json_intro'), "editor_container_jsonserver");
createHint("intro", $.i18n('conf_network_proto_intro'), "editor_container_protoserver");
createHint("intro", $.i18n('conf_network_fbs_intro'), "editor_container_fbserver");
createHint("intro", $.i18n('conf_network_bobl_intro'), "editor_container_boblightserver");
createHint("intro", $.i18n('conf_network_udpl_intro'), "editor_container_udplistener");

View File

@ -231,13 +231,6 @@
"port" : 19444
},
/// The configuration of the Protobuffer server which enables the Protobuffer remote interface
/// * port : Port at which the protobuffer server is started
"protoServer" :
{
"port" : 19445
},
/// The configuration of the Flatbuffer server which enables the Flatbuffer remote interface
/// * port : Port at which the flatbuffer server is started
"flatbufServer" :

View File

@ -130,11 +130,6 @@
"port" : 19444
},
"protoServer" :
{
"port" : 19445
},
"flatbufServer" :
{
"enable" : true,

View File

@ -50,107 +50,3 @@ function(compile_flattbuffer_schema SRC_FBS OUTPUT_DIR)
"${SRC_FBS}"
DEPENDS flatc)
endfunction()
set(USE_SYSTEM_PROTO_LIBS ${DEFAULT_USE_SYSTEM_PROTO_LIBS} CACHE BOOL "use protobuf library from system")
if (USE_SYSTEM_PROTO_LIBS)
find_package(Protobuf REQUIRED)
include_directories(${PROTOBUF_INCLUDE_DIRS})
else ()
set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared protobuf library")
add_subdirectory(external/protobuf)
if(CMAKE_CROSSCOMPILING)
# when crosscompiling import the protoc executable targets from a file generated by a native build
option(IMPORT_PROTOC "Protoc export file (protoc_export.cmake) from a native build" "IMPORT_PROTOC-FILE_NOT_FOUND")
include(${IMPORT_PROTOC})
else()
# export the protoc compiler so it can be used when cross compiling
export(TARGETS protoc_compiler FILE "${CMAKE_BINARY_DIR}/protoc_export.cmake")
endif()
# define the include for the protobuf library at the parent scope
set(PROTOBUF_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/external/protobuf/src")
set(PROTOBUF_INCLUDE_DIRS ${PROTOBUF_INCLUDE_DIRS} PARENT_SCOPE)
# define the protoc executable at the parent scope
get_property(PROTOBUF_PROTOC_EXECUTABLE TARGET protoc_compiler PROPERTY LOCATION)
set(PROTOBUF_PROTOC_EXECUTABLE ${PROTOBUF_PROTOC_EXECUTABLE} PARENT_SCOPE)
endif()
message(STATUS "Using protobuf compiler: " ${PROTOBUF_PROTOC_EXECUTABLE})
#=============================================================================
# Copyright 2009 Kitware, Inc.
# Copyright 2009-2011 Philip Lowman <philip@yhbt.com>
# Copyright 2008 Esben Mose Hansen, Ange Optimization ApS
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
function(PROTOBUF_GENERATE_CPP SRCS HDRS)
if(NOT ARGN)
message(SEND_ERROR "Error: PROTOBUF_GENERATE_CPP() called without any proto files")
return()
endif()
if(PROTOBUF_GENERATE_CPP_APPEND_PATH)
# Create an include path for each file specified
foreach(FIL ${ARGN})
get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
get_filename_component(ABS_PATH ${ABS_FIL} PATH)
list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
if(${_contains_already} EQUAL -1)
list(APPEND _protobuf_include_path -I ${ABS_PATH})
endif()
endforeach()
else()
set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR})
endif()
if(DEFINED PROTOBUF_IMPORT_DIRS)
foreach(DIR ${PROTOBUF_IMPORT_DIRS})
get_filename_component(ABS_PATH ${DIR} ABSOLUTE)
list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
if(${_contains_already} EQUAL -1)
list(APPEND _protobuf_include_path -I ${ABS_PATH})
endif()
endforeach()
endif()
if(CMAKE_CROSSCOMPILING OR USE_SYSTEM_PROTO_LIBS)
set(PROTOC_DEPENDENCY ${PROTOBUF_PROTOC_EXECUTABLE})
else()
set(PROTOC_DEPENDENCY protoc_compiler)
endif()
set(${SRCS})
set(${HDRS})
foreach(FIL ${ARGN})
get_filename_component(ABS_FIL ${FIL} ABSOLUTE)
get_filename_component(FIL_WE ${FIL} NAME_WE)
list(APPEND ${SRCS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc")
list(APPEND ${HDRS} "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h")
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.cc"
"${CMAKE_CURRENT_BINARY_DIR}/${FIL_WE}.pb.h"
COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
ARGS --cpp_out ${CMAKE_CURRENT_BINARY_DIR} ${_protobuf_include_path} ${ABS_FIL}
DEPENDS ${ABS_FIL} ${PROTOC_DEPENDENCY}
COMMENT "Running C++ protocol buffer compiler on ${FIL}"
VERBATIM
)
endforeach()
set_source_files_properties(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)
set(${SRCS} ${${SRCS}} PARENT_SCOPE)
set(${HDRS} ${${HDRS}} PARENT_SCOPE)
endfunction()

@ -1 +0,0 @@
Subproject commit adce8a99fdab90f290d659b6b3bf2d09b721e24a

View File

@ -1,127 +0,0 @@
#pragma once
// Qt includes
#include <QString>
#include <QColor>
#include <QImage>
#include <QTcpSocket>
#include <QTimer>
#include <QMap>
// hyperion util
#include <utils/Image.h>
#include <utils/ColorRgb.h>
#include <utils/VideoMode.h>
#include <utils/Logger.h>
#include <message.pb.h>
///
/// Connection class to setup an connection to the hyperion server and execute commands
///
class ProtoConnection : public QObject
{
Q_OBJECT
public:
///
/// Constructor
///
/// @param address The address of the Hyperion server (for example "192.168.0.32:19444)
///
ProtoConnection(const QString & address);
///
/// Destructor
///
~ProtoConnection();
/// Do not read reply messages from Hyperion if set to true
void setSkipReply(bool skip);
///
/// Set all leds to the specified color
///
/// @param color The color
/// @param priority The priority
/// @param duration The duration in milliseconds
///
void setColor(const ColorRgb & color, int priority, int duration = 1);
///
/// Set the leds according to the given image (assume the image is stretched to the display size)
///
/// @param image The image
/// @param priority The priority
/// @param duration The duration in milliseconds
///
void setImage(const Image<ColorRgb> & image, int priority, int duration = -1);
///
/// Clear the given priority channel
///
/// @param priority The priority
///
void clear(int priority);
///
/// Clear all priority channels
///
void clearAll();
///
/// Send a command message and receive its reply
///
/// @param message The message to send
///
void sendMessage(const proto::HyperionRequest & message);
private slots:
/// Try to connect to the Hyperion host
void connectToHost();
///
/// Slot called when new data has arrived
///
void readData();
signals:
///
/// emits when a new videoMode was requested from proto client
///
void setVideoMode(const VideoMode videoMode);
private:
///
/// Parse a reply message
///
/// @param reply The received reply
///
/// @return true if the reply indicates success
///
bool parseReply(const proto::HyperionReply & reply);
private:
/// The TCP-Socket with the connection to the server
QTcpSocket _socket;
/// Host address
QString _host;
/// Host port
uint16_t _port;
/// Skip receiving reply messages from Hyperion if set
bool _skipReply;
QTimer _timer;
QAbstractSocket::SocketState _prevSocketState;
/// The buffer used for reading data from the socket
QByteArray _receiveBuffer;
Logger * _log;
};

View File

@ -1,41 +0,0 @@
// Qt includes
#include <QObject>
// hyperion includes
#include <utils/Image.h>
#include <utils/ColorRgb.h>
#include <utils/VideoMode.h>
// hyperion proto includes
#include "protoserver/ProtoConnection.h"
/// This class handles callbacks from the V4L2 and X11 grabber
class ProtoConnectionWrapper : public QObject
{
Q_OBJECT
public:
ProtoConnectionWrapper(const QString &address, int priority, int duration_ms, bool skipProtoReply);
virtual ~ProtoConnectionWrapper();
signals:
///
/// Forwarding new videoMode
///
void setVideoMode(const VideoMode videoMode);
public slots:
/// Handle a single image
/// @param image The image to process
void receiveImage(const Image<ColorRgb> & image);
private:
/// Priority for calls to Hyperion
const int _priority;
/// Duration for color calls to Hyperion
const int _duration_ms;
/// Hyperion proto connection object
ProtoConnection _connection;
};

View File

@ -1,98 +0,0 @@
#pragma once
// system includes
#include <cstdint>
// Qt includes
#include <QSet>
#include <QList>
#include <QStringList>
#include <QJsonDocument>
// hyperion includes
#include <utils/Image.h>
#include <utils/ColorRgb.h>
#include <utils/VideoMode.h>
#include <utils/Logger.h>
#include <utils/Components.h>
// settings
#include <utils/settings.h>
// forward decl
class ProtoClientConnection;
class ProtoConnection;
class QTcpServer;
class Hyperion;
class BonjourServiceRegister;
namespace proto {
class HyperionRequest;
}
///
/// This class creates a TCP server which accepts connections wich can then send
/// in Protocol Buffer encoded commands. This interface to Hyperion is used by
/// hyperion-remote to control the leds
///
class ProtoServer : public QObject
{
Q_OBJECT
public:
///
/// ProtoServer constructor
/// @param config the configuration
///
ProtoServer(const QJsonDocument& config);
~ProtoServer();
///
/// @return the port number on which this TCP listens for incoming connections
///
uint16_t getPort() const;
public slots:
///
/// @brief Handle settings update from Hyperion Settingsmanager emit or this constructor
/// @param type settingyType from enum
/// @param config configuration object
///
void handleSettingsUpdate(const settings::type& type, const QJsonDocument& config);
private slots:
///
/// Slot which is called when a client tries to create a new connection
///
void newConnection();
///
/// Slot which is called when a client closes a connection
/// @param connection The Connection object which is being closed
///
void closedConnection(ProtoClientConnection * connection);
private:
/// Hyperion instance
Hyperion * _hyperion;
/// The TCP server object
QTcpServer * _server;
/// List with open connections
QSet<ProtoClientConnection *> _openConnections;
/// Logger instance
Logger * _log;
/// Service register
BonjourServiceRegister * _serviceRegister = nullptr;
uint16_t _port = 0;
/// Start server
void start();
/// Stop server
void stop();
};

View File

@ -1,18 +0,0 @@
{
"type" : "object",
"required" : true,
"title" : "edt_conf_ps_heading_title",
"properties" :
{
"port" :
{
"type" : "integer",
"required" : true,
"title" : "edt_conf_general_port_title",
"minimum" : 1024,
"maximum" : 65535,
"default" : 19445
}
},
"additionalProperties" : false
}

View File

@ -1,48 +0,0 @@
# Define the current source locations
set(CURRENT_HEADER_DIR ${CMAKE_SOURCE_DIR}/include/protoserver)
set(CURRENT_SOURCE_DIR ${CMAKE_SOURCE_DIR}/libsrc/protoserver)
include_directories(
${CMAKE_CURRENT_BINARY_DIR}
${PROTOBUF_INCLUDE_DIRS}
)
set(ProtoServer_PROTOS ${CURRENT_SOURCE_DIR}/message.proto )
protobuf_generate_cpp(ProtoServer_PROTO_SRCS ProtoServer_PROTO_HDRS ${ProtoServer_PROTOS} )
### Split protoclient from protoserver as protoserver relates to HyperionDaemon and standalone capture binarys can't link to it
add_library(protoclient
${CURRENT_HEADER_DIR}/ProtoConnection.h
${CURRENT_SOURCE_DIR}/ProtoConnection.cpp
${CURRENT_HEADER_DIR}/ProtoConnectionWrapper.h
${CURRENT_SOURCE_DIR}/ProtoConnectionWrapper.cpp
${CURRENT_SOURCE_DIR}/ProtoClientConnection.h
${CURRENT_SOURCE_DIR}/ProtoClientConnection.cpp
${ProtoServer_PROTO_SRCS}
${ProtoServer_PROTO_HDRS}
)
add_library(protoserver
${CURRENT_HEADER_DIR}/ProtoServer.h
${CURRENT_SOURCE_DIR}/ProtoServer.cpp
)
# disable warnings for auto generatet proto files, we can't change the files ....
SET_SOURCE_FILES_PROPERTIES ( ${ProtoServer_PROTO_SRCS} ${ProtoServer_PROTO_HDRS} ${ProtoServer_PROTOS} PROPERTIES COMPILE_FLAGS -w )
target_link_libraries(protoclient
hyperion
hyperion-utils
protobuf
Qt5::Gui
)
target_link_libraries(protoserver
hyperion
hyperion-utils
protoclient
Qt5::Gui
)

View File

@ -1,255 +0,0 @@
// system includes
#include <stdexcept>
#include <cassert>
// stl includes
#include <iostream>
#include <sstream>
#include <iterator>
// Qt includes
#include <QRgb>
#include <QResource>
#include <QDateTime>
#include <QHostInfo>
// hyperion util includes
#include "utils/ColorRgb.h"
// Hyperion includes
#include <hyperion/Hyperion.h>
// project includes
#include "ProtoClientConnection.h"
ProtoClientConnection::ProtoClientConnection(QTcpSocket *socket)
: QObject()
, _socket(socket)
, _hyperion(Hyperion::getInstance())
, _receiveBuffer()
, _priority(-1)
, _clientAddress(QHostInfo::fromName(socket->peerAddress().toString()).hostName())
{
// connect internal signals and slots
connect(_socket, SIGNAL(disconnected()), this, SLOT(socketClosed()));
connect(_socket, SIGNAL(readyRead()), this, SLOT(readData()));
}
ProtoClientConnection::~ProtoClientConnection()
{
delete _socket;
}
void ProtoClientConnection::readData()
{
_receiveBuffer += _socket->readAll();
// check if we can read a message size
if (_receiveBuffer.size() <= 4)
{
return;
}
// read the message size
uint32_t messageSize =
((_receiveBuffer[0]<<24) & 0xFF000000) |
((_receiveBuffer[1]<<16) & 0x00FF0000) |
((_receiveBuffer[2]<< 8) & 0x0000FF00) |
((_receiveBuffer[3] ) & 0x000000FF);
// check if we can read a complete message
if ((uint32_t) _receiveBuffer.size() < messageSize + 4)
{
return;
}
// read a message
proto::HyperionRequest message;
if (!message.ParseFromArray(_receiveBuffer.data() + 4, messageSize))
{
sendErrorReply("Unable to parse message");
}
// handle the message
handleMessage(message);
// remove message data from buffer
_receiveBuffer = _receiveBuffer.mid(messageSize + 4);
}
void ProtoClientConnection::socketClosed()
{
_hyperion->clear(_priority);
emit connectionClosed(this);
}
void ProtoClientConnection::setVideoMode(const VideoMode videoMode)
{
int video_Mode = (int)videoMode;
proto::HyperionReply vMode;
// create proto message
vMode.set_type(proto::HyperionReply::VIDEO);
vMode.set_video(video_Mode);
// send message
sendMessage(vMode);
}
void ProtoClientConnection::handleMessage(const proto::HyperionRequest & message)
{
// forward messages
emit newMessage(&message);
switch (message.command())
{
case proto::HyperionRequest::COLOR:
if (!message.HasExtension(proto::ColorRequest::colorRequest))
{
sendErrorReply("Received COLOR command without ColorRequest");
break;
}
handleColorCommand(message.GetExtension(proto::ColorRequest::colorRequest));
break;
case proto::HyperionRequest::IMAGE:
if (!message.HasExtension(proto::ImageRequest::imageRequest))
{
sendErrorReply("Received IMAGE command without ImageRequest");
break;
}
handleImageCommand(message.GetExtension(proto::ImageRequest::imageRequest));
break;
case proto::HyperionRequest::CLEAR:
if (!message.HasExtension(proto::ClearRequest::clearRequest))
{
sendErrorReply("Received CLEAR command without ClearRequest");
break;
}
handleClearCommand(message.GetExtension(proto::ClearRequest::clearRequest));
break;
case proto::HyperionRequest::CLEARALL:
handleClearallCommand();
break;
default:
handleNotImplemented();
}
}
void ProtoClientConnection::handleColorCommand(const proto::ColorRequest &message)
{
// extract parameters
int priority = message.priority();
int duration = message.has_duration() ? message.duration() : -1;
ColorRgb color;
color.red = qRed(message.rgbcolor());
color.green = qGreen(message.rgbcolor());
color.blue = qBlue(message.rgbcolor());
// make sure the prio is registered before setColor()
if(priority != _priority)
{
_hyperion->clear(_priority);
_hyperion->registerInput(priority, hyperion::COMP_PROTOSERVER, "proto@"+_clientAddress);
_priority = priority;
}
// set output
_hyperion->setColor(_priority, color, duration);
// send reply
sendSuccessReply();
}
void ProtoClientConnection::handleImageCommand(const proto::ImageRequest &message)
{
// extract parameters
int priority = message.priority();
int duration = message.has_duration() ? message.duration() : -1;
int width = message.imagewidth();
int height = message.imageheight();
const std::string & imageData = message.imagedata();
// make sure the prio is registered before setInput()
if(priority != _priority)
{
_hyperion->clear(_priority);
_hyperion->registerInput(priority, hyperion::COMP_PROTOSERVER, "proto@"+_clientAddress);
_priority = priority;
}
// check consistency of the size of the received data
if ((int) imageData.size() != width*height*3)
{
sendErrorReply("Size of image data does not match with the width and height");
return;
}
// create ImageRgb
Image<ColorRgb> image(width, height);
memcpy(image.memptr(), imageData.c_str(), imageData.size());
_hyperion->setInputImage(_priority, image, duration);
// send reply
sendSuccessReply();
}
void ProtoClientConnection::handleClearCommand(const proto::ClearRequest &message)
{
// extract parameters
int priority = message.priority();
// clear priority
//_hyperion->clear(priority);
// send reply
sendSuccessReply();
}
void ProtoClientConnection::handleClearallCommand()
{
// clear priority
//_hyperion->clearall();
// send reply
sendSuccessReply();
}
void ProtoClientConnection::handleNotImplemented()
{
sendErrorReply("Command not implemented");
}
void ProtoClientConnection::sendMessage(const google::protobuf::Message &message)
{
std::string serializedReply = message.SerializeAsString();
uint32_t size = serializedReply.size();
uint8_t sizeData[] = {uint8_t(size >> 24), uint8_t(size >> 16), uint8_t(size >> 8), uint8_t(size)};
_socket->write((const char *) sizeData, sizeof(sizeData));
_socket->write(serializedReply.data(), serializedReply.length());
_socket->flush();
}
void ProtoClientConnection::sendSuccessReply()
{
// create reply
proto::HyperionReply reply;
reply.set_type(proto::HyperionReply::REPLY);
reply.set_success(true);
// send reply
sendMessage(reply);
}
void ProtoClientConnection::sendErrorReply(const std::string &error)
{
// create reply
proto::HyperionReply reply;
reply.set_type(proto::HyperionReply::REPLY);
reply.set_success(false);
reply.set_error(error);
// send reply
sendMessage(reply);
}

View File

@ -1,138 +0,0 @@
#pragma once
// stl includes
#include <string>
// Qt includes
#include <QByteArray>
#include <QTcpSocket>
#include <QStringList>
#include <QString>
//Utils includes
#include <utils/VideoMode.h>
// proto includes
#include "message.pb.h"
#include "protoserver/ProtoConnection.h"
class Hyperion;
///
/// The Connection object created by a ProtoServer when a new connection is establshed
///
class ProtoClientConnection : public QObject
{
Q_OBJECT
public:
///
/// Constructor
/// @param socket The Socket object for this connection
/// @param hyperion The Hyperion server
///
ProtoClientConnection(QTcpSocket * socket);
///
/// Destructor
///
~ProtoClientConnection();
public slots:
///
/// Send video mode message to connected client
///
void setVideoMode(const VideoMode videoMode);
signals:
///
/// Signal which is emitted when the connection is being closed
/// @param connection This connection object
///
void connectionClosed(ProtoClientConnection * connection);
void newMessage(const proto::HyperionRequest * message);
private slots:
///
/// Slot called when new data has arrived
///
void readData();
///
/// Slot called when this connection is being closed
///
void socketClosed();
private:
///
/// Handle an incoming Proto message
///
/// @param message the incoming message as string
///
void handleMessage(const proto::HyperionRequest &message);
///
/// Handle an incoming Proto Color message
///
/// @param message the incoming message
///
void handleColorCommand(const proto::ColorRequest & message);
///
/// Handle an incoming Proto Image message
///
/// @param message the incoming message
///
void handleImageCommand(const proto::ImageRequest & message);
///
/// Handle an incoming Proto Clear message
///
/// @param message the incoming message
///
void handleClearCommand(const proto::ClearRequest & message);
///
/// Handle an incoming Proto Clearall message
///
void handleClearallCommand();
///
/// Handle an incoming Proto message of unknown type
///
void handleNotImplemented();
///
/// Send a message to the connected client
///
/// @param message The Proto message to send
///
void sendMessage(const google::protobuf::Message &message);
///
/// Send a standard reply indicating success
///
void sendSuccessReply();
///
/// Send an error message back to the client
///
/// @param error String describing the error
///
void sendErrorReply(const std::string & error);
private:
/// The TCP-Socket that is connected tot the Proto-client
QTcpSocket * _socket;
/// Link to Hyperion for writing led-values to a priority channel
Hyperion * _hyperion;
/// The buffer used for reading data from the socket
QByteArray _receiveBuffer;
int _priority;
/// address of client
QString _clientAddress;
};

View File

@ -1,239 +0,0 @@
// stl includes
#include <stdexcept>
// Qt includes
#include <QRgb>
// protoserver includes
#include "protoserver/ProtoConnection.h"
ProtoConnection::ProtoConnection(const QString & address) :
_socket(),
_skipReply(false),
_prevSocketState(QAbstractSocket::UnconnectedState),
_log(Logger::getInstance("PROTOCONNECTION"))
{
QStringList parts = address.split(":");
if (parts.size() != 2)
{
throw std::runtime_error(QString("PROTOCONNECTION ERROR: Wrong address: Unable to parse address (%1)").arg(address).toStdString());
}
_host = parts[0];
bool ok;
_port = parts[1].toUShort(&ok);
if (!ok)
{
throw std::runtime_error(QString("PROTOCONNECTION ERROR: Wrong port: Unable to parse the port number (%1)").arg(parts[1]).toStdString());
}
// try to connect to host
Info(_log, "Connecting to Hyperion: %s:%d", _host.toStdString().c_str(), _port);
connectToHost();
// start the connection timer
_timer.setInterval(5000);
_timer.setSingleShot(false);
connect(&_timer,SIGNAL(timeout()), this, SLOT(connectToHost()));
connect(&_socket, SIGNAL(readyRead()), this, SLOT(readData()));
_timer.start();
}
ProtoConnection::~ProtoConnection()
{
_timer.stop();
_socket.close();
}
void ProtoConnection::readData()
{
_receiveBuffer += _socket.readAll();
// check if we can read a message size
if (_receiveBuffer.size() <= 4)
{
return;
}
// read the message size
uint32_t messageSize =
((_receiveBuffer[0]<<24) & 0xFF000000) |
((_receiveBuffer[1]<<16) & 0x00FF0000) |
((_receiveBuffer[2]<< 8) & 0x0000FF00) |
((_receiveBuffer[3] ) & 0x000000FF);
// check if we can read a complete message
if ((uint32_t) _receiveBuffer.size() < messageSize + 4)
{
return;
}
// read a message
proto::HyperionReply reply;
if (!reply.ParseFromArray(_receiveBuffer.data() + 4, messageSize))
{
Error(_log, "Unable to parse message");
return;
}
parseReply(reply);
// remove message data from buffer
_receiveBuffer = _receiveBuffer.mid(messageSize + 4);
}
void ProtoConnection::setSkipReply(bool skip)
{
_skipReply = skip;
}
void ProtoConnection::setColor(const ColorRgb & color, int priority, int duration)
{
proto::HyperionRequest request;
request.set_command(proto::HyperionRequest::COLOR);
proto::ColorRequest * colorRequest = request.MutableExtension(proto::ColorRequest::colorRequest);
colorRequest->set_rgbcolor((color.red << 16) | (color.green << 8) | color.blue);
colorRequest->set_priority(priority);
colorRequest->set_duration(duration);
// send command message
sendMessage(request);
}
void ProtoConnection::setImage(const Image<ColorRgb> &image, int priority, int duration)
{
proto::HyperionRequest request;
request.set_command(proto::HyperionRequest::IMAGE);
proto::ImageRequest * imageRequest = request.MutableExtension(proto::ImageRequest::imageRequest);
imageRequest->set_imagedata(image.memptr(), image.width() * image.height() * 3);
imageRequest->set_imagewidth(image.width());
imageRequest->set_imageheight(image.height());
imageRequest->set_priority(priority);
imageRequest->set_duration(duration);
// send command message
sendMessage(request);
}
void ProtoConnection::clear(int priority)
{
proto::HyperionRequest request;
request.set_command(proto::HyperionRequest::CLEAR);
proto::ClearRequest * clearRequest = request.MutableExtension(proto::ClearRequest::clearRequest);
clearRequest->set_priority(priority);
// send command message
sendMessage(request);
}
void ProtoConnection::clearAll()
{
proto::HyperionRequest request;
request.set_command(proto::HyperionRequest::CLEARALL);
// send command message
sendMessage(request);
}
void ProtoConnection::connectToHost()
{
// try connection only when
if (_socket.state() == QAbstractSocket::UnconnectedState)
{
_socket.connectToHost(_host, _port);
//_socket.waitForConnected(1000);
}
}
void ProtoConnection::sendMessage(const proto::HyperionRequest &message)
{
// print out connection message only when state is changed
if (_socket.state() != _prevSocketState )
{
switch (_socket.state() )
{
case QAbstractSocket::UnconnectedState:
Info(_log, "No connection to Hyperion: %s:%d", _host.toStdString().c_str(), _port);
break;
case QAbstractSocket::ConnectedState:
Info(_log, "Connected to Hyperion: %s:%d", _host.toStdString().c_str(), _port);
break;
default:
Debug(_log, "Connecting to Hyperion: %s:%d", _host.toStdString().c_str(), _port);
break;
}
_prevSocketState = _socket.state();
}
if (_socket.state() != QAbstractSocket::ConnectedState)
{
return;
}
// We only get here if we are connected
// serialize message (FastWriter already appends a newline)
std::string serializedMessage = message.SerializeAsString();
int length = serializedMessage.size();
const uint8_t header[] = {
uint8_t((length >> 24) & 0xFF),
uint8_t((length >> 16) & 0xFF),
uint8_t((length >> 8) & 0xFF),
uint8_t((length ) & 0xFF)};
// write message
int count = 0;
count += _socket.write(reinterpret_cast<const char *>(header), 4);
count += _socket.write(reinterpret_cast<const char *>(serializedMessage.data()), length);
if (!_socket.waitForBytesWritten())
{
Error(_log, "Error while writing data to host");
return;
}
}
bool ProtoConnection::parseReply(const proto::HyperionReply &reply)
{
bool success = false;
switch (reply.type())
{
case proto::HyperionReply::REPLY:
{
if (!_skipReply)
{
if (!reply.success())
{
if (reply.has_error())
{
throw std::runtime_error("PROTOCONNECTION ERROR: " + reply.error());
}
else
{
throw std::runtime_error("PROTOCONNECTION ERROR: No error info");
}
}
else
{
success = true;
}
}
break;
}
case proto::HyperionReply::VIDEO:
{
int video = reply.has_video() ? reply.video() : 0;
VideoMode vMode = (VideoMode)video;
emit setVideoMode(vMode);
break;
}
}
return success;
}

View File

@ -1,23 +0,0 @@
// protoserver includes
#include "protoserver/ProtoConnectionWrapper.h"
ProtoConnectionWrapper::ProtoConnectionWrapper(const QString &address,
int priority,
int duration_ms,
bool skipProtoReply)
: _priority(priority)
, _duration_ms(duration_ms)
, _connection(address)
{
_connection.setSkipReply(skipProtoReply);
connect(&_connection, SIGNAL(setVideoMode(VideoMode)), this, SIGNAL(setVideoMode(VideoMode)));
}
ProtoConnectionWrapper::~ProtoConnectionWrapper()
{
}
void ProtoConnectionWrapper::receiveImage(const Image<ColorRgb> & image)
{
_connection.setImage(image, _priority, _duration_ms);
}

View File

@ -1,110 +0,0 @@
// system includes
#include <stdexcept>
// qt incl
#include <QTcpServer>
#include <QJsonObject>
// project includes
#include <protoserver/ProtoServer.h>
#include "protoserver/ProtoConnection.h"
#include "ProtoClientConnection.h"
#include <bonjour/bonjourserviceregister.h>
#include <hyperion/ComponentRegister.h>
ProtoServer::ProtoServer(const QJsonDocument& config)
: QObject()
, _server(new QTcpServer(this))
, _openConnections()
, _log(Logger::getInstance("PROTOSERVER"))
{
Debug(_log,"Instance created");
connect( _server, SIGNAL(newConnection()), this, SLOT(newConnection()));
handleSettingsUpdate(settings::PROTOSERVER, config);
}
ProtoServer::~ProtoServer()
{
foreach (ProtoClientConnection * connection, _openConnections) {
delete connection;
}
}
void ProtoServer::start()
{
if(_server->isListening())
return;
if (!_server->listen(QHostAddress::Any, _port))
{
Error(_log,"Could not bind to port '%d', please use an available port",_port);
return;
}
Info(_log, "Started on port %d", _port);
if(_serviceRegister == nullptr)
{
_serviceRegister = new BonjourServiceRegister(this);
_serviceRegister->registerService("_hyperiond-proto._tcp", _port);
}
else if( _serviceRegister->getPort() != _port)
{
delete _serviceRegister;
_serviceRegister = new BonjourServiceRegister(this);
_serviceRegister->registerService("_hyperiond-proto._tcp", _port);
}
}
void ProtoServer::stop()
{
if(!_server->isListening())
return;
_server->close();
Info(_log, "Stopped");
}
void ProtoServer::handleSettingsUpdate(const settings::type& type, const QJsonDocument& config)
{
if(type == settings::PROTOSERVER)
{
QJsonObject obj = config.object();
if(obj["port"].toInt() != _port)
{
_port = obj["port"].toInt();
stop();
start();
}
}
}
uint16_t ProtoServer::getPort() const
{
return _port;
}
void ProtoServer::newConnection()
{
while(_server->hasPendingConnections())
{
if(QTcpSocket * socket = _server->nextPendingConnection())
{
Debug(_log, "New connection");
ProtoClientConnection * connection = new ProtoClientConnection(socket);
_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::closedConnection(ProtoClientConnection *connection)
{
Debug(_log, "Connection closed");
_openConnections.remove(connection);
// schedule to delete the connection object
connection->deleteLater();
}

View File

@ -1,80 +0,0 @@
package proto;
message HyperionRequest {
enum Command {
COLOR = 1;
IMAGE = 2;
CLEAR = 3;
CLEARALL = 4;
}
// command specification
required Command command = 1;
// extensions to define all specific requests
extensions 10 to 100;
}
message ColorRequest {
extend HyperionRequest {
optional ColorRequest colorRequest = 10;
}
// priority to use when setting the color
required int32 priority = 1;
// integer value containing the rgb color (0x00RRGGBB)
required int32 RgbColor = 2;
// duration of the request (negative results in infinite)
optional int32 duration = 3;
}
message ImageRequest {
extend HyperionRequest {
optional ImageRequest imageRequest = 11;
}
// priority to use when setting the image
required int32 priority = 1;
// width of the image
required int32 imagewidth = 2;
// height of the image
required int32 imageheight = 3;
// image data
required bytes imagedata = 4;
// duration of the request (negative results in infinite)
optional int32 duration = 5;
}
message ClearRequest {
extend HyperionRequest {
optional ClearRequest clearRequest = 12;
}
// priority which need to be cleared
required int32 priority = 1;
}
message HyperionReply {
enum Type {
REPLY = 1;
VIDEO = 2;
}
// Identifies which field is filled in.
required Type type = 1;
// flag indication success or failure
optional bool success = 2;
// string indicating the reason for failure (if applicable)
optional string error = 3;
// Proto Messages for video mode
optional int32 video = 4;
}