From 1cc2f72fa2b8963d78fb3eba4aa7cb40284e9c78 Mon Sep 17 00:00:00 2001 From: redPanther Date: Wed, 14 Sep 2016 13:51:28 +0200 Subject: [PATCH] embedded webui + config modification detection (#240) * implement embedded webui * add detection for changed config, later on used for restart hyperion --- assets/webconfig/css/hyperion.css | 2 +- assets/webconfig/index.html | 12 +++++++-- assets/webconfig/js/content_index.js | 6 +++++ assets/webconfig/js/content_leds.js | 2 +- assets/webconfig/js/ui_utils.js | 6 ++--- config/hyperion.config.json.default | 2 -- include/hyperion/Hyperion.h | 5 +++- include/webconfig/WebConfig.h | 2 +- libsrc/effectengine/CMakeLists.txt | 2 +- libsrc/hyperion/Hyperion.cpp | 29 ++++++++++++++++++++++ libsrc/hyperion/hyperion.schema.json | 8 ++---- libsrc/jsonserver/JsonClientConnection.cpp | 2 +- libsrc/webconfig/CMakeLists.txt | 9 +++++++ libsrc/webconfig/StaticFileServing.cpp | 15 +++++++---- libsrc/webconfig/WebConfig.cpp | 26 ++++++++++++++----- libsrc/webconfig/WebConfig.qrc.in | 5 ++++ 16 files changed, 103 insertions(+), 30 deletions(-) create mode 100644 libsrc/webconfig/WebConfig.qrc.in diff --git a/assets/webconfig/css/hyperion.css b/assets/webconfig/css/hyperion.css index dd27a590..6b70adb0 100644 --- a/assets/webconfig/css/hyperion.css +++ b/assets/webconfig/css/hyperion.css @@ -14,7 +14,7 @@ table.borderless td,table.borderless th{border: none !important;} /*Header*/ .navbar-brand{padding: 5px;padding-left:20px;height:60px;} -.sidebar{margin-top:91px;} +.sidebar{margin-top:61px;padding-top:20px;} .dropdown{font-size:18px;} @media (max-width: 767px) {.sidebar{margin-top:0px;}} diff --git a/assets/webconfig/index.html b/assets/webconfig/index.html index 1572de36..334aece1 100644 --- a/assets/webconfig/index.html +++ b/assets/webconfig/index.html @@ -80,7 +80,6 @@
-
@@ -225,7 +224,16 @@ -
+
+ + +
+
diff --git a/assets/webconfig/js/content_index.js b/assets/webconfig/js/content_index.js index dfddef5a..56300107 100644 --- a/assets/webconfig/js/content_index.js +++ b/assets/webconfig/js/content_index.js @@ -20,6 +20,12 @@ $(document).ready( function() { parsedServerInfoJSON = event.response; currentVersion = parsedServerInfoJSON.info.hyperion[0].version; cleanCurrentVersion = currentVersion.replace(/\./g, ''); + + if (parsedServerInfoJSON.info.hyperion[0].config_modified) + $("#hyperion_restart_notify").fadeIn("fast"); + else + $("#hyperion_restart_notify").fadeOut("fast"); + // get active led device var leddevice = parsedServerInfoJSON.info.ledDevices.active; $('#dash_leddevice').html(leddevice); diff --git a/assets/webconfig/js/content_leds.js b/assets/webconfig/js/content_leds.js index f7a3d6f6..d78d51f4 100644 --- a/assets/webconfig/js/content_leds.js +++ b/assets/webconfig/js/content_leds.js @@ -149,7 +149,7 @@ $(document).ready(function() { isCurrentDevice = (server.info.ledDevices.active == $(this).val()); for(var key in parsedConfJSON.device){ - if (key in generalOptions.properties) + if (key != "type" && key in generalOptions.properties) values_general[key] = parsedConfJSON.device[key]; }; grabber_conf_editor.getEditor("root.generalOptions").setValue( values_general ); diff --git a/assets/webconfig/js/ui_utils.js b/assets/webconfig/js/ui_utils.js index d3244bac..65c6957c 100644 --- a/assets/webconfig/js/ui_utils.js +++ b/assets/webconfig/js/ui_utils.js @@ -1,13 +1,13 @@ function bindNavToContent(containerId, fileName, loadNow) { - $("#page-wrapper").off(); + $("#page-content").off(); $(containerId).on("click", function() { - $("#page-wrapper").load("/content/"+fileName+".html"); + $("#page-content").load("/content/"+fileName+".html"); }); if (loadNow) { - $("#page-wrapper").load("/content/"+fileName+".html"); + $("#page-content").load("/content/"+fileName+".html"); } } diff --git a/config/hyperion.config.json.default b/config/hyperion.config.json.default index 994b0313..41f9cbca 100644 --- a/config/hyperion.config.json.default +++ b/config/hyperion.config.json.default @@ -195,8 +195,6 @@ "webConfig" : { "enable" : true, - "document_root" : "/usr/share/hyperion/webconfig", - "port" : 8099 }, "effects" : diff --git a/include/hyperion/Hyperion.h b/include/hyperion/Hyperion.h index 36a66aeb..d93096b1 100644 --- a/include/hyperion/Hyperion.h +++ b/include/hyperion/Hyperion.h @@ -163,6 +163,8 @@ public: ComponentRegister& getComponentRegister() { return _componentRegister; }; + bool configModified(); + public slots: /// /// Writes a single color to all the leds for the given time and priority @@ -386,5 +388,6 @@ private: /// holds the current priority channel that is manualy selected int _currentSourcePriority; - + + QByteArray _configHash; }; diff --git a/include/webconfig/WebConfig.h b/include/webconfig/WebConfig.h index 5e84b8dc..5c4d4e82 100644 --- a/include/webconfig/WebConfig.h +++ b/include/webconfig/WebConfig.h @@ -26,7 +26,7 @@ private: quint16 _port; StaticFileServing* _server; - const std::string WEBCONFIG_DEFAULT_PATH = "/usr/share/hyperion/webconfig"; + const QString WEBCONFIG_DEFAULT_PATH = ":/webconfig"; const quint16 WEBCONFIG_DEFAULT_PORT = 8099; }; diff --git a/libsrc/effectengine/CMakeLists.txt b/libsrc/effectengine/CMakeLists.txt index c50afdcc..53714ee3 100644 --- a/libsrc/effectengine/CMakeLists.txt +++ b/libsrc/effectengine/CMakeLists.txt @@ -38,7 +38,7 @@ CONFIGURE_FILE(${CURRENT_SOURCE_DIR}/EffectEngine.qrc.in ${CMAKE_BINARY_DIR}/Eff SET(EffectEngine_RESOURCES ${CMAKE_BINARY_DIR}/EffectEngine.qrc) QT5_WRAP_CPP(EffectEngineHEADERS_MOC ${EffectEngineQT_HEADERS}) -qt5_add_resources(EffectEngine_RESOURCES_RCC ${EffectEngine_RESOURCES} OPTIONS "-no-compress") +qt5_add_resources(EffectEngine_RESOURCES_RCC ${EffectEngine_RESOURCES} ) # OPTIONS "-no-compress" add_library(effectengine ${EffectEngineHEADERS} diff --git a/libsrc/hyperion/Hyperion.cpp b/libsrc/hyperion/Hyperion.cpp index 0004f948..ced585b4 100644 --- a/libsrc/hyperion/Hyperion.cpp +++ b/libsrc/hyperion/Hyperion.cpp @@ -10,6 +10,8 @@ #include #include #include +#include +#include // JsonSchema include #include @@ -575,6 +577,7 @@ Hyperion::Hyperion(const Json::Value &jsonConfig, const std::string configFile) , _log(Logger::getInstance("Core")) , _hwLedCount(_ledString.leds().size()) , _sourceAutoSelectEnabled(true) + , _configHash() { registerPriority("Off", PriorityMuxer::LOWEST_PRIORITY); @@ -623,6 +626,9 @@ Hyperion::Hyperion(const Json::Value &jsonConfig, const std::string configFile) Debug(_log,"configured leds: %d hw leds: %d", getLedCount(), _hwLedCount); WarningIf(hwLedCount < getLedCount(), _log, "more leds configured than available. check 'ledCount' in 'device' section"); + // initialize hash of current config + configModified(); + // initialize the leds update(); } @@ -648,6 +654,29 @@ unsigned Hyperion::getLedCount() const return _ledString.leds().size(); } + +bool Hyperion::configModified() +{ + QFile f(_configFile.c_str()); + if (f.open(QFile::ReadOnly)) + { + QCryptographicHash hash(QCryptographicHash::Sha1); + if (hash.addData(&f)) + { + if (_configHash.size() == 0) + { + _configHash = hash.result(); + qDebug(_configHash.toHex()); + return false; + } + return _configHash != hash.result(); + } + } + f.close(); + + return false; +} + void Hyperion::registerPriority(const std::string name, const int priority) { Info(_log, "Register new input source named '%s' for priority channel '%d'", name.c_str(), priority ); diff --git a/libsrc/hyperion/hyperion.schema.json b/libsrc/hyperion/hyperion.schema.json index 8bdb5eb3..1b6c8dd1 100644 --- a/libsrc/hyperion/hyperion.schema.json +++ b/libsrc/hyperion/hyperion.schema.json @@ -1000,7 +1000,6 @@ { "type" : "object", "title" : "WebUI - DANGER CHANGES CAN MAKE THE WEBUI UNREACHABLE!", - "required" : true, "properties" : { "enable" : @@ -1009,21 +1008,18 @@ "format": "checkbox", "title" : "Activate", "default" : true, - "required" : true, "propertyOrder" : 1 }, "document_root" : { "type" : "string", - "title" : "Document Root", - "required" : true + "title" : "Document Root" }, "port" : { "type" : "integer", "title" : "Port", - "default" : 8099, - "required" : true + "default" : 8099 } }, "additionalProperties" : false diff --git a/libsrc/jsonserver/JsonClientConnection.cpp b/libsrc/jsonserver/JsonClientConnection.cpp index 8a2c13cc..de0b051f 100644 --- a/libsrc/jsonserver/JsonClientConnection.cpp +++ b/libsrc/jsonserver/JsonClientConnection.cpp @@ -669,9 +669,9 @@ void JsonClientConnection::handleServerInfoCommand(const Json::Value &, const st ver["version"] = HYPERION_VERSION; ver["build"] = HYPERION_BUILD_ID; ver["time"] = __DATE__ " " __TIME__; + ver["config_modified"] = _hyperion->configModified(); info["hyperion"].append(ver); - // send the result sendMessage(result); } diff --git a/libsrc/webconfig/CMakeLists.txt b/libsrc/webconfig/CMakeLists.txt index 59e42e8e..ea707c5c 100644 --- a/libsrc/webconfig/CMakeLists.txt +++ b/libsrc/webconfig/CMakeLists.txt @@ -27,14 +27,23 @@ set(WebConfig_SOURCES ${CURRENT_SOURCE_DIR}/StaticFileServing.cpp ${CURRENT_SOURCE_DIR}/WebConfig.cpp ) +FILE ( GLOB_RECURSE webFiles RELATIVE ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/assets/webconfig/* ) +FOREACH( f ${webFiles} ) + STRING ( REPLACE "../assets/webconfig/" "" fname ${f}) + SET(HYPERION_WEBCONFIG_RES "${HYPERION_WEBCONFIG_RES}\n\t\t${f}") +ENDFOREACH() +CONFIGURE_FILE(${CURRENT_SOURCE_DIR}/WebConfig.qrc.in ${CMAKE_BINARY_DIR}/WebConfig.qrc ) +SET(WebConfig_RESOURCES ${CMAKE_BINARY_DIR}/WebConfig.qrc) qt5_wrap_cpp(WebConfig_HEADERS_MOC ${WebConfig_QT_HEADERS}) +qt5_add_resources(WebConfig_RESOURCES_RCC ${WebConfig_RESOURCES} ) #OPTIONS "-no-compress" add_library(webconfig ${WebConfig_HEADERS} ${WebConfig_QT_HEADERS} ${WebConfig_SOURCES} ${WebConfig_HEADERS_MOC} + ${WebConfig_RESOURCES_RCC} ) qt5_use_modules(webconfig Network) diff --git a/libsrc/webconfig/StaticFileServing.cpp b/libsrc/webconfig/StaticFileServing.cpp index 78ac2bb7..b56ac3ed 100644 --- a/libsrc/webconfig/StaticFileServing.cpp +++ b/libsrc/webconfig/StaticFileServing.cpp @@ -7,14 +7,17 @@ #include #include #include +#include StaticFileServing::StaticFileServing (Hyperion *hyperion, QString baseUrl, quint16 port, QObject * parent) - : QObject (parent) - , _hyperion(hyperion) - , _baseUrl (baseUrl) - , _cgi(hyperion, baseUrl, this) - , _log(Logger::getInstance("WEBSERVER")) + : QObject (parent) + , _hyperion(hyperion) + , _baseUrl (baseUrl) + , _cgi(hyperion, baseUrl, this) + , _log(Logger::getInstance("WEBSERVER")) { + Q_INIT_RESOURCE(WebConfig); + _mimeDb = new QMimeDatabase; _server = new QtHttpServer (this); @@ -26,6 +29,7 @@ StaticFileServing::StaticFileServing (Hyperion *hyperion, QString baseUrl, quint connect (_server, &QtHttpServer::requestNeedsReply, this, &StaticFileServing::onRequestNeedsReply); _server->start (port); + } StaticFileServing::~StaticFileServing () @@ -75,6 +79,7 @@ void StaticFileServing::onRequestNeedsReply (QtHttpRequest * request, QtHttpRepl } return; } + Q_INIT_RESOURCE(WebConfig); QFileInfo info(_baseUrl % "/" % path); if ( path == "/" || path.isEmpty() || ! info.exists() ) diff --git a/libsrc/webconfig/WebConfig.cpp b/libsrc/webconfig/WebConfig.cpp index d702809c..1cc3d64d 100644 --- a/libsrc/webconfig/WebConfig.cpp +++ b/libsrc/webconfig/WebConfig.cpp @@ -1,17 +1,18 @@ #include "webconfig/WebConfig.h" #include "StaticFileServing.h" +#include WebConfig::WebConfig(QObject * parent) : QObject(parent) + , _hyperion(Hyperion::getInstance()) + , _port(WEBCONFIG_DEFAULT_PORT) , _server(nullptr) { - _port = WEBCONFIG_DEFAULT_PORT; - _hyperion = Hyperion::getInstance(); + _baseUrl = WEBCONFIG_DEFAULT_PATH; const Json::Value &config = _hyperion->getJsonConfig(); - _baseUrl = QString::fromStdString(WEBCONFIG_DEFAULT_PATH); - _port = WEBCONFIG_DEFAULT_PORT; - + Logger* log = Logger::getInstance("WEBSERVER"); + bool webconfigEnable = true; if (config.isMember("webConfig")) @@ -19,11 +20,24 @@ WebConfig::WebConfig(QObject * parent) const Json::Value & webconfigConfig = config["webConfig"]; webconfigEnable = webconfigConfig.get("enable", true).asBool(); _port = webconfigConfig.get("port", WEBCONFIG_DEFAULT_PORT).asUInt(); - _baseUrl = QString::fromStdString( webconfigConfig.get("document_root", WEBCONFIG_DEFAULT_PATH).asString() ); + _baseUrl = QString::fromStdString( webconfigConfig.get("document_root", _baseUrl.toStdString()).asString() ); } + if (_baseUrl != ":/webconfig") + { + QFileInfo info(_baseUrl); + if (!info.exists() || !info.isDir()) + { + Error(log, "document_root '%s' is invalid, set to default '%s'", _baseUrl.toUtf8().constData(), WEBCONFIG_DEFAULT_PATH.toUtf8().constData()); + _baseUrl = WEBCONFIG_DEFAULT_PATH; + } + } + + Debug(log, "WebUI initialized, document root: %s", _baseUrl.toUtf8().constData()); if ( webconfigEnable ) + { start(); + } } diff --git a/libsrc/webconfig/WebConfig.qrc.in b/libsrc/webconfig/WebConfig.qrc.in new file mode 100644 index 00000000..e2212432 --- /dev/null +++ b/libsrc/webconfig/WebConfig.qrc.in @@ -0,0 +1,5 @@ + + + ${HYPERION_WEBCONFIG_RES} + +