diff --git a/assets/webconfig/index.html b/assets/webconfig/index.html
index c2f61a19..650d5036 100644
--- a/assets/webconfig/index.html
+++ b/assets/webconfig/index.html
@@ -179,7 +179,10 @@
diff --git a/assets/webconfig/server_scripts/demo.py b/assets/webconfig/server_scripts/demo.py
deleted file mode 100644
index a7d90ed8..00000000
--- a/assets/webconfig/server_scripts/demo.py
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/usr/bin/env python
-
-print ("hello world");
-
-
diff --git a/include/api/JsonAPI.h b/include/api/JsonAPI.h
index ed239eca..c1aa19e4 100644
--- a/include/api/JsonAPI.h
+++ b/include/api/JsonAPI.h
@@ -214,6 +214,13 @@ private:
///
void handleVideoModeCommand(const QJsonObject & message, const QString &command, const int tan);
+ ///
+ /// Handle an incoming JSON Clearall message
+ ///
+ /// @param message the incoming message
+ ///
+ void handleClearallCommand(const QJsonObject & message, const QString &command, const int tan);
+
///
/// Handle an incoming JSON message of unknown type
///
diff --git a/include/hyperion/Hyperion.h b/include/hyperion/Hyperion.h
index d9510067..413e01b5 100644
--- a/include/hyperion/Hyperion.h
+++ b/include/hyperion/Hyperion.h
@@ -208,7 +208,7 @@ public:
/// @param[in] priority The priority of the channel
/// @param[in] component The component of the channel
/// @param[in] origin Who set the channel (CustomString@IP)
- /// @param[in] owner Speicifc owner string, might be empty
+ /// @param[in] owner Specific owner string, might be empty
/// @param[in] smooth_cfg The smooth id to use
///
void registerInput(const int priority, const hyperion::Components& component, const QString& origin = "System", const QString& owner = "", unsigned smooth_cfg = 0);
diff --git a/libsrc/webserver/WebSocketClient.h b/include/webserver/WebSocketClient.h
similarity index 88%
rename from libsrc/webserver/WebSocketClient.h
rename to include/webserver/WebSocketClient.h
index 05bfb1c7..b7a273d9 100644
--- a/libsrc/webserver/WebSocketClient.h
+++ b/include/webserver/WebSocketClient.h
@@ -1,18 +1,16 @@
#pragma once
#include
-#include "WebSocketUtils.h"
+#include "webserver/WebSocketUtils.h"
+#include
class QTcpSocket;
-
-class QtHttpRequest;
-class Hyperion;
class JsonAPI;
class WebSocketClient : public QObject {
Q_OBJECT
public:
- WebSocketClient(QtHttpRequest* request, QTcpSocket* sock, QObject* parent);
+ WebSocketClient(QByteArray socketKey, QTcpSocket* sock, QObject* parent);
struct WebSocketHeader
{
@@ -25,13 +23,13 @@ public:
private:
QTcpSocket* _socket;
+ QByteArray _secWebSocketKey;
Logger* _log;
- Hyperion* _hyperion;
JsonAPI* _jsonAPI;
void getWsFrameHeader(WebSocketHeader* header);
void sendClose(int status, QString reason = "");
- void handleBinaryMessage(QByteArray &data);
+// void handleBinaryMessage(QByteArray &data);
qint64 sendMessage_Raw(const char* data, quint64 size);
qint64 sendMessage_Raw(QByteArray &data);
QByteArray makeFrameHeader(quint8 opCode, quint64 payloadLength, bool lastFrame);
diff --git a/libsrc/webserver/WebSocketUtils.h b/include/webserver/WebSocketUtils.h
similarity index 100%
rename from libsrc/webserver/WebSocketUtils.h
rename to include/webserver/WebSocketUtils.h
diff --git a/libsrc/api/JSONRPC_schema/schema-clearall.json b/libsrc/api/JSONRPC_schema/schema-clearall.json
new file mode 100644
index 00000000..8c88cc6c
--- /dev/null
+++ b/libsrc/api/JSONRPC_schema/schema-clearall.json
@@ -0,0 +1,15 @@
+{
+ "type":"object",
+ "required":true,
+ "properties":{
+ "command": {
+ "type" : "string",
+ "required" : true,
+ "enum" : ["clearall"]
+ },
+ "tan" : {
+ "type" : "integer"
+ }
+ },
+ "additionalProperties": false
+}
diff --git a/libsrc/api/JSONRPC_schema/schema-color.json b/libsrc/api/JSONRPC_schema/schema-color.json
index 316cbe80..754c5ad3 100644
--- a/libsrc/api/JSONRPC_schema/schema-color.json
+++ b/libsrc/api/JSONRPC_schema/schema-color.json
@@ -24,7 +24,7 @@
"type": "string",
"minLength" : 4,
"maxLength" : 20,
- "required": true
+ "required": false
},
"color": {
"type": "array",
diff --git a/libsrc/api/JSONRPC_schema/schema-effect.json b/libsrc/api/JSONRPC_schema/schema-effect.json
index 80a10847..876173f1 100644
--- a/libsrc/api/JSONRPC_schema/schema-effect.json
+++ b/libsrc/api/JSONRPC_schema/schema-effect.json
@@ -24,7 +24,7 @@
"type": "string",
"minLength" : 4,
"maxLength" : 20,
- "required": true
+ "required": false
},
"effect": {
"type": "object",
diff --git a/libsrc/api/JSONRPC_schema/schema-hyperion-classic.json b/libsrc/api/JSONRPC_schema/schema-hyperion-classic.json
new file mode 100644
index 00000000..5421b3aa
--- /dev/null
+++ b/libsrc/api/JSONRPC_schema/schema-hyperion-classic.json
@@ -0,0 +1,12 @@
+{
+ "type":"object",
+ "required":true,
+ "properties":{
+ "command": {
+ "title" : "This schema is used to ensure backward compatibility with hyperion classic",
+ "type" : "string",
+ "required" : false
+ }
+ },
+ "additionalProperties": true
+}
diff --git a/libsrc/api/JSONRPC_schema/schema.json b/libsrc/api/JSONRPC_schema/schema.json
index 9aca8d98..26d77bf9 100644
--- a/libsrc/api/JSONRPC_schema/schema.json
+++ b/libsrc/api/JSONRPC_schema/schema.json
@@ -5,7 +5,7 @@
"command": {
"type" : "string",
"required" : true,
- "enum" : ["color", "image", "effect", "create-effect", "delete-effect", "serverinfo", "clear", "clearall", "adjustment", "sourceselect", "config", "componentstate", "ledcolors", "logging", "processing", "sysinfo", "videomode"]
+ "enum" : ["color", "image", "effect", "create-effect", "delete-effect", "serverinfo", "clear", "clearall", "adjustment", "sourceselect", "config", "componentstate", "ledcolors", "logging", "processing", "sysinfo", "videomode", "transform", "correction" , "temperature"]
}
}
}
diff --git a/libsrc/api/JSONRPC_schemas.qrc b/libsrc/api/JSONRPC_schemas.qrc
index 925566a1..7595d1ee 100644
--- a/libsrc/api/JSONRPC_schemas.qrc
+++ b/libsrc/api/JSONRPC_schemas.qrc
@@ -6,6 +6,7 @@
JSONRPC_schema/schema-serverinfo.json
JSONRPC_schema/schema-sysinfo.json
JSONRPC_schema/schema-clear.json
+ JSONRPC_schema/schema-clearall.json
JSONRPC_schema/schema-adjustment.json
JSONRPC_schema/schema-effect.json
JSONRPC_schema/schema-create-effect.json
@@ -17,5 +18,9 @@
JSONRPC_schema/schema-logging.json
JSONRPC_schema/schema-processing.json
JSONRPC_schema/schema-videomode.json
+
+ JSONRPC_schema/schema-hyperion-classic.json
+ JSONRPC_schema/schema-hyperion-classic.json
+ JSONRPC_schema/schema-hyperion-classic.json
diff --git a/libsrc/api/JsonAPI.cpp b/libsrc/api/JsonAPI.cpp
index 3bb10240..0a3b1393 100644
--- a/libsrc/api/JsonAPI.cpp
+++ b/libsrc/api/JsonAPI.cpp
@@ -13,6 +13,7 @@
#include
#include
#include
+#include
// hyperion includes
#include
@@ -104,6 +105,14 @@ void JsonAPI::handleMessage(const QString& messageString)
else if (command == "logging") handleLoggingCommand (message, command, tan);
else if (command == "processing") handleProcessingCommand (message, command, tan);
else if (command == "videomode") handleVideoModeCommand (message, command, tan);
+
+ // BEGIN | The following commands are derecated but used to ensure backward compatibility with hyperion Classic remote control
+ else if (command == "clearall") handleClearallCommand(message, command, tan);
+ else if (command == "transform" || command == "correction" || command == "temperature")
+ sendErrorReply("The command " + command + "is deprecated, please use the Hyperion Web Interface to configure");
+ // END
+
+ // handle not implemented commands
else handleNotImplemented ();
}
@@ -114,7 +123,7 @@ void JsonAPI::handleColorCommand(const QJsonObject& message, const QString& comm
// extract parameters
int priority = message["priority"].toInt();
int duration = message["duration"].toInt(-1);
- QString origin = message["origin"].toString() + "@"+_peerAddress;
+ QString origin = message["origin"].toString("Empty") + "@"+_peerAddress;
std::vector colorData(_hyperion->getLedCount());
const QJsonArray & jsonColor = message["color"].toArray();
@@ -185,7 +194,7 @@ void JsonAPI::handleEffectCommand(const QJsonObject &message, const QString &com
int priority = message["priority"].toInt();
int duration = message["duration"].toInt(-1);
QString pythonScript = message["pythonScript"].toString();
- QString origin = message["origin"].toString() + "@"+_peerAddress;
+ QString origin = message["origin"].toString("Empty") + "@"+_peerAddress;
const QJsonObject & effect = message["effect"].toObject();
const QString & effectName = effect["name"].toString();
const QString & data = message["imageData"].toString("").toUtf8();
@@ -463,6 +472,46 @@ void JsonAPI::handleServerInfoCommand(const QJsonObject& message, const QString&
}
info["sessions"] = sessions;
+ // BEGIN | The following entries are derecated but used to ensure backward compatibility with hyperion Classic remote control
+ // TODO Output the real transformation information instead of default
+
+ // host name
+ info["hostname"] = QHostInfo::localHostName();
+
+ // transform information (default values)
+ QJsonArray transformArray;
+ for (const QString& transformId : _hyperion->getAdjustmentIds())
+ {
+ QJsonObject transform;
+ QJsonArray blacklevel, whitelevel, gamma, threshold;
+
+ transform["id"] = transformId;
+ transform["saturationGain"] = 1.0;
+ transform["valueGain"] = 1.0;
+ transform["saturationLGain"] = 1.0;
+ transform["luminanceGain"] = 1.0;
+ transform["luminanceMinimum"] = 0.0;
+
+ for (int i = 0; i < 3; i++ )
+ {
+ blacklevel.append(0.0);
+ whitelevel.append(1.0);
+ gamma.append(2.50);
+ threshold.append(0.0);
+ }
+
+ transform.insert("blacklevel", blacklevel);
+ transform.insert("whitelevel", whitelevel);
+ transform.insert("gamma", gamma);
+ transform.insert("threshold", threshold);
+
+ transformArray.append(transform);
+ }
+
+ info["transform"] = transformArray;
+
+ // END
+
sendSuccessDataReply(QJsonDocument(info), command, tan);
// AFTER we send the info, the client might want to subscribe to future updates
@@ -845,6 +894,16 @@ void JsonAPI::handleVideoModeCommand(const QJsonObject& message, const QString &
sendSuccessReply(command, tan);
}
+void JsonAPI::handleClearallCommand(const QJsonObject& message, const QString& command, const int tan)
+{
+ emit forwardJsonMessage(message);
+
+ // clear priority
+ _hyperion->clearall();
+
+ // send reply
+ sendSuccessReply(command, tan);
+}
void JsonAPI::handleNotImplemented()
{
diff --git a/libsrc/jsonserver/JsonClientConnection.cpp b/libsrc/jsonserver/JsonClientConnection.cpp
index 8fd2b630..692de9a9 100644
--- a/libsrc/jsonserver/JsonClientConnection.cpp
+++ b/libsrc/jsonserver/JsonClientConnection.cpp
@@ -6,9 +6,13 @@
#include
#include
+// websocket includes
+#include "webserver/WebSocketClient.h"
+
JsonClientConnection::JsonClientConnection(QTcpSocket *socket)
: QObject()
, _socket(socket)
+ , _websocketClient(nullptr)
, _receiveBuffer()
, _log(Logger::getInstance("JSONCLIENTCONNECTION"))
{
@@ -23,21 +27,37 @@ JsonClientConnection::JsonClientConnection(QTcpSocket *socket)
void JsonClientConnection::readRequest()
{
_receiveBuffer += _socket->readAll();
- // raw socket data, handling as usual
- int bytes = _receiveBuffer.indexOf('\n') + 1;
- while(bytes > 0)
+
+ // might be an old hyperion classic handshake request or raw socket data
+ if(_receiveBuffer.contains("Upgrade: websocket"))
{
- // create message string
- QString message(QByteArray(_receiveBuffer.data(), bytes));
+ if(_websocketClient == Q_NULLPTR)
+ {
+ // disconnect this slot from socket for further requests
+ disconnect(_socket, &QTcpSocket::readyRead, this, &JsonClientConnection::readRequest);
+ int start = _receiveBuffer.indexOf("Sec-WebSocket-Key") + 19;
+ QByteArray header(_receiveBuffer.mid(start, _receiveBuffer.indexOf("\r\n", start) - start).data());
+ _websocketClient = new WebSocketClient(header, _socket, this);
+ }
+ }
+ else
+ {
+ // raw socket data, handling as usual
+ int bytes = _receiveBuffer.indexOf('\n') + 1;
+ while(bytes > 0)
+ {
+ // create message string
+ QString message(QByteArray(_receiveBuffer.data(), bytes));
- // remove message data from buffer
- _receiveBuffer = _receiveBuffer.mid(bytes);
+ // remove message data from buffer
+ _receiveBuffer = _receiveBuffer.mid(bytes);
- // handle message
- _jsonAPI->handleMessage(message);
+ // handle message
+ _jsonAPI->handleMessage(message);
- // try too look up '\n' again
- bytes = _receiveBuffer.indexOf('\n') + 1;
+ // try too look up '\n' again
+ bytes = _receiveBuffer.indexOf('\n') + 1;
+ }
}
}
diff --git a/libsrc/jsonserver/JsonClientConnection.h b/libsrc/jsonserver/JsonClientConnection.h
index 57944275..0434bc5d 100644
--- a/libsrc/jsonserver/JsonClientConnection.h
+++ b/libsrc/jsonserver/JsonClientConnection.h
@@ -10,9 +10,10 @@
class JsonAPI;
class QTcpSocket;
+class WebSocketClient;
///
-/// The Connection object created by \a JsonServer when a new connection is establshed
+/// The Connection object created by \a JsonServer when a new connection is established
///
class JsonClientConnection : public QObject
{
@@ -41,6 +42,7 @@ private slots:
private:
QTcpSocket* _socket;
+ WebSocketClient* _websocketClient;
/// new instance of JsonAPI
JsonAPI * _jsonAPI;
diff --git a/libsrc/webserver/QtHttpClientWrapper.cpp b/libsrc/webserver/QtHttpClientWrapper.cpp
index e162e014..04e22be3 100644
--- a/libsrc/webserver/QtHttpClientWrapper.cpp
+++ b/libsrc/webserver/QtHttpClientWrapper.cpp
@@ -4,8 +4,8 @@
#include "QtHttpReply.h"
#include "QtHttpServer.h"
#include "QtHttpHeader.h"
-#include "WebSocketClient.h"
#include "WebJsonRpc.h"
+#include "webserver/WebSocketClient.h"
#include
#include
@@ -120,7 +120,7 @@ void QtHttpClientWrapper::onClientDataReceived (void) {
{
// disconnect this slot from socket for further requests
disconnect(m_sockClient, &QTcpSocket::readyRead, this, &QtHttpClientWrapper::onClientDataReceived);
- m_websocketClient = new WebSocketClient(m_currentRequest, m_sockClient, this);
+ m_websocketClient = new WebSocketClient(m_currentRequest->getHeader(QtHttpHeader::SecWebSocketKey), m_sockClient, this);
}
break;
}
diff --git a/libsrc/webserver/WebSocketClient.cpp b/libsrc/webserver/WebSocketClient.cpp
index c45b1882..ebbfda52 100644
--- a/libsrc/webserver/WebSocketClient.cpp
+++ b/libsrc/webserver/WebSocketClient.cpp
@@ -1,4 +1,4 @@
-#include "WebSocketClient.h"
+#include "webserver/WebSocketClient.h"
// hyperion includes
#include
@@ -7,25 +7,23 @@
#include
// qt includes
-#include "QtHttpRequest.h"
-#include "QtHttpHeader.h"
#include
#include
#include
#include
+#include
-WebSocketClient::WebSocketClient(QtHttpRequest* request, QTcpSocket* sock, QObject* parent)
+
+WebSocketClient::WebSocketClient(QByteArray socketKey, QTcpSocket* sock, QObject* parent)
: QObject(parent)
, _socket(sock)
+ , _secWebSocketKey(socketKey)
, _log(Logger::getInstance("WEBSOCKET"))
- , _hyperion(Hyperion::getInstance())
{
// connect socket; disconnect handled from QtHttpServer
connect(_socket, &QTcpSocket::readyRead , this, &WebSocketClient::handleWebSocketFrame);
- // QtHttpRequest contains all headers for handshake
- QByteArray secWebSocketKey = request->getHeader(QtHttpHeader::SecWebSocketKey);
- const QString client = request->getClientInfo().clientAddress.toString();
+ const QString client = sock->peerAddress().toString();
// Json processor
_jsonAPI = new JsonAPI(client, _log, this);
@@ -34,8 +32,8 @@ WebSocketClient::WebSocketClient(QtHttpRequest* request, QTcpSocket* sock, QObje
Debug(_log, "New connection from %s", QSTRING_CSTR(client));
// do handshake
- secWebSocketKey += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
- QByteArray hash = QCryptographicHash::hash(secWebSocketKey, QCryptographicHash::Sha1).toBase64();
+ _secWebSocketKey += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
+ QByteArray hash = QCryptographicHash::hash(_secWebSocketKey, QCryptographicHash::Sha1).toBase64();
QString data
= QString("HTTP/1.1 101 Switching Protocols\r\n")
@@ -225,6 +223,7 @@ void WebSocketClient::sendClose(int status, QString reason)
_socket->close();
}
+/*
void WebSocketClient::handleBinaryMessage(QByteArray &data)
{
//uint8_t priority = data.at(0);
@@ -243,9 +242,10 @@ void WebSocketClient::handleBinaryMessage(QByteArray &data)
image.resize(width, height);
memcpy(image.memptr(), data.data()+4, imgSize);
- //_hyperion->registerInput();
- //_hyperion->setInputImage(priority, image, duration_s*1000);
+ _hyperion->registerInput();
+ _hyperion->setInputImage(priority, image, duration_s*1000);
}
+*/
qint64 WebSocketClient::sendMessage(QJsonObject obj)
{
diff --git a/src/hyperion-remote/JsonConnection.cpp b/src/hyperion-remote/JsonConnection.cpp
index d9e81d24..0d0abdfd 100644
--- a/src/hyperion-remote/JsonConnection.cpp
+++ b/src/hyperion-remote/JsonConnection.cpp
@@ -587,7 +587,9 @@ QJsonObject JsonConnection::sendMessage(const QJsonObject & message)
QJsonDocument reply = QJsonDocument::fromJson(serializedReply ,&error);
if (error.error != QJsonParseError::NoError)
{
- throw std::runtime_error("Error while parsing reply: invalid json");
+ throw std::runtime_error(
+ std::string("Error while parsing json reply: ")
+ + error.errorString().toStdString() );
}
return reply.object();