From a98239c4938fec644bda4531a401b33032e34ac5 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Sun, 13 May 2018 15:52:50 +0100 Subject: [PATCH] domoticz: update to 3.9571 and clean up FHS handling Upstream has merged a simplified version of the FHS patch, with a few changes... Scripts are actually configuration. There are examples, but the point is that you write your own. So they should live in the data directory (e.g. /var/lib/domoticz) not in /usr/share/domoticz. The only exception is the dzVents runtime. So.... the upstream patch handles the dzVents runtime bit. Drop the part of our patch which added -scripts, because it can just be based in the userdata directory and we don't need to change that. Ship the default scripts/ directory in /etc/domoticz/scripts, and on startup make a *symlink* to it from /var/lib/domoticz/scripts. Symlink from /etc/domoticz/scripts/dzVents{data,generated_scripts} to temporary directories under /var/lib/domoticz/dzVents so that those directories (which are written to by Domoticz) don't land on the root file system. Anyone with a writeable file system who *wants* the data/ directory to be persistent, can change that. Just as they can change the userdata config option to point to a real file system somewhere. Also drop the renaming of the OpenZWave Config/ directory. It's purely cosmetric so there's no need for us to carry that change. It can go upstream first, if it really offends anyone. Drop the patches which are now merged upstream, and turn off the newly added USE_OPENSSL_STATIC. Add -noupdates to the command line. Finally, gzip the static www files to save space. In the common case, clients will use "Accept-Encodiong: gzip" and Domoticz will serve them as-is. It can also decompress on the fly if it really has to, but now we aren't asking it to *compress* on the fly, which is probably a losing proposition on an OpenWRT box. Signed-off-by: David Woodhouse --- utils/domoticz/Makefile | 44 +- utils/domoticz/files/domoticz.init | 29 +- .../001-Make-compatible-with-boost-1.66.patch | 62 --- utils/domoticz/patches/900_fix-build.patch | 11 - utils/domoticz/patches/901_no-udev.patch | 42 -- .../domoticz/patches/902_disable-libusb.patch | 39 -- utils/domoticz/patches/903_fhs.patch | 407 ------------------ 7 files changed, 55 insertions(+), 579 deletions(-) delete mode 100644 utils/domoticz/patches/001-Make-compatible-with-boost-1.66.patch delete mode 100644 utils/domoticz/patches/900_fix-build.patch delete mode 100644 utils/domoticz/patches/901_no-udev.patch delete mode 100644 utils/domoticz/patches/902_disable-libusb.patch delete mode 100644 utils/domoticz/patches/903_fhs.patch diff --git a/utils/domoticz/Makefile b/utils/domoticz/Makefile index ba240960d..8fc93e5af 100644 --- a/utils/domoticz/Makefile +++ b/utils/domoticz/Makefile @@ -9,13 +9,20 @@ include $(TOPDIR)/rules.mk PKG_NAME:=domoticz PKG_VERSION_MAJOR:=3 -PKG_VERSION_PATCH:=8153 +PKG_VERSION_PATCH:=9571 +PKG_COMMIT:=dfb39a9e739a0a07ab865577ed44e0b6aa9e7bdc PKG_VERSION:=$(PKG_VERSION_MAJOR).$(PKG_VERSION_PATCH) -PKG_RELEASE:=3 +PKG_RELEASE:=1 +ifeq ($(PKG_COMMIT),) PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://github.com/domoticz/domoticz/archive/$(PKG_VERSION)/$(PKG_SOURCE) -PKG_HASH:=5ea8f37f2ef900e9bd17b1b5375e75bfdec4f09001e3e2e0b647a260989d014c +else +PKG_SOURCE:=$(PKG_NAME)-$(PKG_COMMIT).tar.gz +PKG_SOURCE_URL:=https://github.com/domoticz/domoticz/archive/$(PKG_COMMIT)/$(PKG_SOURCE) +PKG_BUILD_DIR:=$(BUILD_DIR)/$(PKG_NAME)-$(PKG_COMMIT) +endif +PKG_HASH:=7e77a8ea87216f65c2f279535eb43d957e22ca14ccebfb1ef2054f9bc797a5c3 PKG_LICENSE:=GPL-3.0 PKG_LICENSE_FILES:=License.txt @@ -60,22 +67,30 @@ CMAKE_OPTIONS += \ -DUSE_STATIC_BOOST=no \ -DUSE_STATIC_LIBSTDCXX=no \ -DUSE_STATIC_OPENZWAVE=no \ - -DUSE_PYTHON=no + -DUSE_OPENSSL_STATIC=no \ + -DUSE_PYTHON=no \ + -DWITH_LIBUSB=no TARGET_CFLAGS+=-flto TARGET_CXXFLAGS+=-DWITH_GPIO -flto define Build/Prepare $(call Build/Prepare/Default) - # Fix APPVERSION to suppress update popup + # Fix APPVERSION/APPDATE since we don't build from a git tree sed -i 's/#define APPVERSION.*/#define APPVERSION $(PKG_VERSION_PATCH)/' \ $(PKG_BUILD_DIR)/appversion.default + COMMITDATE=`tar tvfz $(DL_DIR)/$(PKG_SOURCE) --full-time | sed 's/.* \(20..-..-.. ..:..:..\) domoticz-.*/\1/;q'`; \ + COMMITTS=`date --date="$$$${COMMITDATE}" +%s`; \ + sed -i "s/#define APPDATE.*/#define APPDATE $$$${COMMITTS}/" $(PKG_BUILD_DIR)/appversion.default +ifneq ($(PKG_COMMIT),) + sed -i "s/#define APPHASH.*/#define APPHASH \"$(shell echo $(PKG_COMMIT) | cut -c1-8)\"/" $(PKG_BUILD_DIR)/appversion.default +endif # Remove unwanted scripts cd $(PKG_BUILD_DIR)/scripts && rm -rf \ buienradar_rain_example.pl \ _domoticz_main* \ download_update.sh \ - dzVents/{.gitignore,documentation,examples,generated_scripts} \ + dzVents/{.gitignore,documentation,examples,generated_scripts,data} \ dzVents/runtime/{integration-tests,misc/smoothing.xlsx,tests} \ logrotate/ \ lua_parsers/example* \ @@ -84,26 +99,35 @@ define Build/Prepare readme.txt \ restart_domoticz \ templates/All.Python \ - update_domoticz + update_domoticz \ + domoticz.conf # Remove *.md cd $(PKG_BUILD_DIR) && $(FIND) -name '*.md' -delete endef define Package/domoticz/install - $(INSTALL_DIR) $(1)/etc/config $(1)/etc/hotplug.d/tty $(1)/etc/init.d + $(INSTALL_DIR) $(1)/etc/config $(1)/etc/hotplug.d/tty $(1)/etc/init.d $(1)/etc/domoticz $(INSTALL_BIN) ./files/domoticz.hotplug $(1)/etc/hotplug.d/tty/domoticz $(INSTALL_BIN) ./files/domoticz.init $(1)/etc/init.d/domoticz $(INSTALL_CONF) ./files/domoticz.config $(1)/etc/config/domoticz $(INSTALL_DIR) $(1)/usr/share/domoticz $(1)/usr/bin - $(CP) $(PKG_INSTALL_DIR)/usr/Config $(1)/usr/share/domoticz/openzwave - $(CP) $(PKG_INSTALL_DIR)/usr/scripts $(1)/usr/share/domoticz/ + $(CP) $(PKG_INSTALL_DIR)/usr/dzVents $(1)/usr/share/domoticz/dzVents + $(CP) $(PKG_INSTALL_DIR)/usr/Config $(1)/usr/share/domoticz/Config + $(CP) $(PKG_INSTALL_DIR)/usr/scripts $(1)/etc/domoticz/scripts + ln -sf /var/lib/domoticz/dzVents/generated_scripts $(1)/etc/domoticz/scripts/dzVents + ln -sf /var/lib/domoticz/dzVents/data $(1)/etc/domoticz/scripts/dzVents $(CP) $(PKG_INSTALL_DIR)/usr/www $(1)/usr/share/domoticz/ $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/domoticz $(1)/usr/bin/domoticz + # compress static web content + find $(1)/usr/share/domoticz/www -name "*.css" -exec gzip -9 {} \; + find $(1)/usr/share/domoticz/www -name "*.js" -exec gzip -9 {} \; + find $(1)/usr/share/domoticz/www -name "*.html" -exec sh -c 'grep -q "<\!--#embed" {} || gzip -9 {}' \; endef define Package/domoticz/conffiles /etc/config/domoticz /var/lib/domoticz/ +/etc/domoticz/ endef $(eval $(call BuildPackage,domoticz)) diff --git a/utils/domoticz/files/domoticz.init b/utils/domoticz/files/domoticz.init index 16e986e5e..89aaeae0c 100644 --- a/utils/domoticz/files/domoticz.init +++ b/utils/domoticz/files/domoticz.init @@ -16,16 +16,29 @@ start_domoticz() { config_get ssldhparam "$section" "ssldhparam" config_get sslwww "$section" "sslwww" config_get syslog "$section" "syslog" - config_get userdata "$section" "userdata" + config_get userdata "$section" "userdata" userdata /var/lib/domoticz [ -n "$loglevel" ] && procd_append_param command -loglevel "$loglevel" [ -n "$syslog" ] && procd_append_param command -syslog "$syslog" - [ -n "$userdata" ] && { - mkdir -p "${userdata}/generated_scripts" - chmod -R 0770 "$userdata" - chown -R domoticz:domoticz "$userdata" - procd_append_param command -userdata "$userdata" + + [ -d "${userdata}" ] || { + mkdir -p "${userdata}" + chmod 0770 "$userdata" + chown domoticz:domoticz "$userdata" } + + # By default, ${userdata}/scripts is a symlink to /etc/domoticz/scripts + # and the two dzVents directories under there which Domoticz will actually + # write to at runtime are symlinked back to /var/lib again. + [ -d "${userdata}/scripts" ] || ln -sf /etc/domoticz/scripts "${userdata}/scripts" + for DIR in data generated_scripts; do + [ -d /var/lib/domoticz/dzVents/$DIR ] || { + mkdir -p /var/lib/domoticz/dzVents/$DIR + chown domoticz.domoticz /var/lib/domoticz/dzVents/$DIR + } + done + procd_append_param command -userdata "$userdata" + [ -n "$sslcert" -a "${sslwww:-0}" -gt 0 ] && { procd_append_param command -sslcert "$sslcert" procd_append_param command -sslwww "$sslwww" @@ -39,8 +52,8 @@ start_service() { procd_open_instance procd_set_param command "$PROG" - procd_append_param command -scripts /usr/share/domoticz/scripts/ - procd_append_param command -wwwroot /usr/share/domoticz/www/ + procd_append_param command -noupdates + procd_append_param command -approot /usr/share/domoticz/ config_load "domoticz" config_get_bool disabled "$section" "disabled" 0 diff --git a/utils/domoticz/patches/001-Make-compatible-with-boost-1.66.patch b/utils/domoticz/patches/001-Make-compatible-with-boost-1.66.patch deleted file mode 100644 index 77c183c77..000000000 --- a/utils/domoticz/patches/001-Make-compatible-with-boost-1.66.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 11a29e071019645967ee748d410954ec5f73866f Mon Sep 17 00:00:00 2001 -From: Rob Peters -Date: Wed, 24 Jan 2018 12:03:24 +0100 -Subject: [PATCH] Make compatible with boost 1.66 - ---- - msbuild/domoticz.vcxproj | 2 +- - webserver/proxyclient.cpp | 2 +- - webserver/server.cpp | 4 ++-- - 3 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/msbuild/domoticz.vcxproj b/msbuild/domoticz.vcxproj -index e4aa595..1aa9e7a 100755 ---- a/msbuild/domoticz.vcxproj -+++ b/msbuild/domoticz.vcxproj -@@ -58,7 +58,7 @@ - Use - Level3 - Disabled -- WIN32;ENABLE_PYTHON;_DEBUG;PTW32_STATIC_LIB;WITH_OPENZWAVE;OPENZWAVE_USEDLL;WWW_ENABLE_SSL;_CONSOLE;%(PreprocessorDefinitions) -+ WIN32;ENABLE_PYTHON;_DEBUG;PTW32_STATIC_LIB;WITH_OPENZWAVE;OPENZWAVE_USEDLL;WWW_ENABLE_SSL;_CONSOLE;BOOST_CONFIG_SUPPRESS_OUTDATED_MESSAGE;%(PreprocessorDefinitions) - ./Windows Libraries/Boost/boost_1_63_0;./libusb;../MQTT;..\hardware\openzwave;./Windows Libraries/openssl;./Windows Libraries/Curl;./Windows Libraries/pthread;../hardware/plugins/Include;%(AdditionalIncludeDirectories) - MultiThreadedDebugDLL - false -diff --git a/webserver/proxyclient.cpp b/webserver/proxyclient.cpp -index 203ee61..efc9815 100644 ---- a/webserver/proxyclient.cpp -+++ b/webserver/proxyclient.cpp -@@ -639,7 +639,7 @@ namespace http { - void CProxyManager::StartThread() - { - try { -- boost::asio::ssl::context ctx(io_service, boost::asio::ssl::context::sslv23); -+ boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); - ctx.set_verify_mode(boost::asio::ssl::verify_none); - - proxyclient.reset(new CProxyClient(io_service, ctx, m_pWebEm)); -diff --git a/webserver/server.cpp b/webserver/server.cpp -index 5255aa3..0c1af08 100644 ---- a/webserver/server.cpp -+++ b/webserver/server.cpp -@@ -148,7 +148,7 @@ void server::handle_accept(const boost::system::error_code& e) { - ssl_server::ssl_server(const ssl_server_settings & ssl_settings, request_handler & user_request_handler) : - server_base(ssl_settings, user_request_handler), - settings_(ssl_settings), -- context_(io_service_, ssl_settings.get_ssl_method()) -+ context_(ssl_settings.get_ssl_method()) - { - #ifdef DEBUG_WWW - _log.Log(LOG_STATUS, "[web:%s] create ssl_server using ssl_server_settings : %s", ssl_settings.listening_port.c_str(), ssl_settings.to_string().c_str()); -@@ -161,7 +161,7 @@ ssl_server::ssl_server(const ssl_server_settings & ssl_settings, request_handler - ssl_server::ssl_server(const server_settings & settings, request_handler & user_request_handler) : - server_base(settings, user_request_handler), - settings_(dynamic_cast(settings)), -- context_(io_service_, dynamic_cast(settings).get_ssl_method()) { -+ context_(dynamic_cast(settings).get_ssl_method()) { - #ifdef DEBUG_WWW - _log.Log(LOG_STATUS, "[web:%s] create ssl_server using server_settings : %s", settings.listening_port.c_str(), settings.to_string().c_str()); - #endif --- -2.7.4 - diff --git a/utils/domoticz/patches/900_fix-build.patch b/utils/domoticz/patches/900_fix-build.patch deleted file mode 100644 index b9fbebdcb..000000000 --- a/utils/domoticz/patches/900_fix-build.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -645,8 +645,6 @@ else() - target_link_libraries(domoticz -lrt ${Boost_LIBRARIES} ${ZLIB_LIBRARIES} ${CURL_LIBRARIES} pthread ${LUA_LIBRARIES} ${MQTT_LIBRARIES} ${SQLite_LIBRARIES} ${CMAKE_DL_LIBS} ${TELLDUS_LIBRARIES} ${EXECINFO_LIBRARIES}) - ENDIF() - --ADD_PRECOMPILED_HEADER(domoticz "main/stdafx.h") -- - IF(CMAKE_COMPILER_IS_GNUCXX) - option(USE_STATIC_LIBSTDCXX "Build with static libgcc/libstdc++ libraries" YES) - IF(USE_STATIC_LIBSTDCXX) diff --git a/utils/domoticz/patches/901_no-udev.patch b/utils/domoticz/patches/901_no-udev.patch deleted file mode 100644 index 0ea9dd948..000000000 --- a/utils/domoticz/patches/901_no-udev.patch +++ /dev/null @@ -1,42 +0,0 @@ ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -579,39 +579,6 @@ IF(OpenZWave) - target_link_libraries(domoticz ${OpenZWave}) - include_directories(${CMAKE_SOURCE_DIR}/hardware/openzwave) - add_definitions(-DWITH_OPENZWAVE) -- # open-zwave needs libudev -- IF(CMAKE_SYSTEM_NAME STREQUAL "Darwin") -- set(IOKIT_LIBRARY "-framework IOKit -framework CoreFoundation" CACHE FILEPATH "IOKit framework" FORCE) -- target_link_libraries(domoticz ${IOKIT_LIBRARY}) -- else() -- IF(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD") -- MESSAGE(STATUS "Building on FreeBSD, libudev not needed!") -- FIND_PATH(ICONV_INCLUDE_DIR iconv.h) -- FIND_LIBRARY(ICONV_LIBRARIES NAMES iconv libiconv libiconv-2 c) -- IF(ICONV_INCLUDE_DIR AND ICONV_LIBRARIES) -- SET(ICONV_FOUND TRUE) -- #target_link_libraries(domoticz ${ICONV_INCLUDE_DIR}) -- target_link_libraries(domoticz ${ICONV_LIBRARIES} -lrt) -- message(STATUS ${ICONV_LIBRARIES}) -- else() -- MESSAGE(FATAL_ERROR "libiconv not found on your system") -- ENDIF(ICONV_INCLUDE_DIR AND ICONV_LIBRARIES) -- else() -- find_library(UDEV NAMES libudev.a) -- IF(UDEV) -- message(STATUS ${UDEV}) -- target_link_libraries(domoticz ${UDEV} -lrt -lresolv) -- else() -- find_library(UDEV NAMES libudev.so) -- IF(UDEV) -- message(STATUS ${UDEV}) -- target_link_libraries(domoticz ${UDEV} -lrt -lresolv) -- else() -- MESSAGE(FATAL_ERROR "LIB UDEV not found on your system, see install.txt how to get them installed.\nsudo apt-get install libudev-dev") -- ENDIF(UDEV) -- ENDIF(UDEV) -- ENDIF() -- ENDIF() - else() - MESSAGE(STATUS "==== OpenZWave not found, support disabled!") - ENDIF(OpenZWave) diff --git a/utils/domoticz/patches/902_disable-libusb.patch b/utils/domoticz/patches/902_disable-libusb.patch deleted file mode 100644 index f4f03c3db..000000000 --- a/utils/domoticz/patches/902_disable-libusb.patch +++ /dev/null @@ -1,39 +0,0 @@ ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -521,20 +521,23 @@ else() - MESSAGE(FATAL_ERROR "cURL not found on your system, see install.txt how to get them installed. (for example 'sudo apt-get install curl libcurl4-openssl-dev')") - ENDIF(CURL_FOUND) - --find_path(LIBUSB_INCLUDE_DIR usb.h -- HINTS ${PC_LIBUSB_INCLUDEDIR} ${PC_LIBUSB_INCLUDE_DIRS}) --find_library(LIBUSB_LIBRARY NAMES usb -- HINTS ${PC_LIBUSB_LIBDIR} ${PC_LIBUSB_LIBRARY_DIRS}) --set(LIBUSB_LIBRARIES ${LIBUSB_LIBRARY}) -+option(WITH_LIBUSB "Enable libusb support" NO) -+ if(WITH_LIBUSB) -+ find_path(LIBUSB_INCLUDE_DIR usb.h -+ HINTS ${PC_LIBUSB_INCLUDEDIR} ${PC_LIBUSB_INCLUDE_DIRS}) -+ find_library(LIBUSB_LIBRARY NAMES usb -+ HINTS ${PC_LIBUSB_LIBDIR} ${PC_LIBUSB_LIBRARY_DIRS}) -+ set(LIBUSB_LIBRARIES ${LIBUSB_LIBRARY}) - --find_package_handle_standard_args(LIBUSB DEFAULT_MSG LIBUSB_LIBRARIES LIBUSB_INCLUDE_DIR) --IF(LIBUSB_FOUND) -- MESSAGE(STATUS "LIBUSB found at: ${LIBUSB_LIBRARIES}") -- add_definitions(-DWITH_LIBUSB) -- target_link_libraries(domoticz ${LIBUSB_LIBRARIES}) --else() -- MESSAGE(STATUS "==== LibUSB not found, support for TE923/Voltcraft disabled!") --ENDIF(LIBUSB_FOUND) -+ find_package_handle_standard_args(LIBUSB DEFAULT_MSG LIBUSB_LIBRARIES LIBUSB_INCLUDE_DIR) -+ IF(LIBUSB_FOUND) -+ MESSAGE(STATUS "LIBUSB found at: ${LIBUSB_LIBRARIES}") -+ add_definitions(-DWITH_LIBUSB) -+ target_link_libraries(domoticz ${LIBUSB_LIBRARIES}) -+ else() -+ MESSAGE(STATUS "==== LibUSB not found, support for TE923/Voltcraft disabled!") -+ ENDIF(LIBUSB_FOUND) -+endif(WITH_LIBUSB) - - # - # Find MD5/RMD160/SHA library diff --git a/utils/domoticz/patches/903_fhs.patch b/utils/domoticz/patches/903_fhs.patch deleted file mode 100644 index 11e531af5..000000000 --- a/utils/domoticz/patches/903_fhs.patch +++ /dev/null @@ -1,407 +0,0 @@ -diff --git a/hardware/EvohomeScript.cpp b/hardware/EvohomeScript.cpp -index 5258fc55..0a44e97c 100644 ---- a/hardware/EvohomeScript.cpp -+++ b/hardware/EvohomeScript.cpp -@@ -30,7 +30,7 @@ - - #include - --extern std::string szUserDataFolder; -+extern std::string szScriptsFolder; - - - CEvohomeScript::CEvohomeScript(const int ID) -@@ -143,7 +143,7 @@ void CEvohomeScript::RunScript(const char *pdata, const unsigned char length) - std::string scriptname = OnAction.substr(9); - #if !defined WIN32 - if (scriptname.find("/") != 0) -- scriptname = szUserDataFolder + "scripts/" + scriptname; -+ scriptname = szScriptsFolder + "scripts/" + scriptname; - #endif - std::string scriptparams=""; - //Add parameters -diff --git a/hardware/OpenZWave.cpp b/hardware/OpenZWave.cpp -index 1f5c341c..24db61c9 100644 ---- a/hardware/OpenZWave.cpp -+++ b/hardware/OpenZWave.cpp -@@ -948,7 +948,7 @@ bool COpenZWave::OpenSerialConnector() - - m_nodes.clear(); - m_bNeedSave = false; -- std::string ConfigPath = szStartupFolder + "Config/"; -+ std::string ConfigPath = "/usr/share/domoticz/openzwave/"; - std::string UserPath = ConfigPath; - if (szStartupFolder != szUserDataFolder) - { -diff --git a/main/EventSystem.cpp b/main/EventSystem.cpp -index 4eff02fd..f2b17b97 100644 ---- a/main/EventSystem.cpp -+++ b/main/EventSystem.cpp -@@ -33,9 +33,11 @@ extern "C" { - #endif - } - -+extern std::string szScriptsFolder; - extern std::string szUserDataFolder; - extern http::server::CWebServerHelper m_webservers; - -+static std::string dzv_Dir; - static std::string m_printprefix; - - #ifdef ENABLE_PYTHON -@@ -115,7 +117,6 @@ static const _tJsonMap JsonMap[] = - { NULL, NULL, tString } - }; - -- - CEventSystem::CEventSystem(void) - { - m_stoprequested = false; -@@ -149,7 +150,7 @@ void CEventSystem::StartEventSystem() - GetCurrentScenesGroups(); - GetCurrentUserVariables(); - #ifdef ENABLE_PYTHON -- Plugins::PythonEventsInitialize(szUserDataFolder); -+ Plugins::PythonEventsInitialize(szScriptsFolder); - #endif - - m_thread = boost::shared_ptr(new boost::thread(boost::bind(&CEventSystem::Do_Work, this))); -@@ -179,11 +180,11 @@ void CEventSystem::SetEnabled(const bool bEnabled) - - void CEventSystem::LoadEvents() - { -- std::string dzv_Dir,s; -+ std::string s; - #ifdef WIN32 -- dzv_Dir = szUserDataFolder + "scripts\\dzVents\\generated_scripts\\"; -+ dzv_Dir = szUserDataFolder + "generated_scripts\\"; - #else -- dzv_Dir = szUserDataFolder + "scripts/dzVents/generated_scripts/"; -+ dzv_Dir = szUserDataFolder + "generated_scripts/"; - #endif - boost::unique_lock eventsMutexLock(m_eventsMutex); - _log.Log(LOG_STATUS, "EventSystem: reset all events..."); -@@ -274,18 +275,18 @@ void CEventSystem::LoadEvents() - void CEventSystem::Do_Work() - { - #ifdef WIN32 -- m_lua_Dir = szUserDataFolder + "scripts\\lua\\"; -- m_dzv_Dir = szUserDataFolder + "scripts\\dzVents\\runtime\\"; -+ m_lua_Dir = szScriptsFolder + "lua\\"; -+ m_dzv_Dir = szScriptsFolder + "dzVents\\runtime\\"; - #else -- m_lua_Dir = szUserDataFolder + "scripts/lua/"; -- m_dzv_Dir = szUserDataFolder + "scripts/dzVents/runtime/"; -+ m_lua_Dir = szScriptsFolder + "lua/"; -+ m_dzv_Dir = szScriptsFolder + "dzVents/runtime/"; - #endif - - #ifdef ENABLE_PYTHON - #ifdef WIN32 -- m_python_Dir = szUserDataFolder + "scripts\\python\\"; -+ m_python_Dir = szScriptsFolder + "python\\"; - #else -- m_python_Dir = szUserDataFolder + "scripts/python/"; -+ m_python_Dir = szScriptsFolder + "python/"; - #endif - #endif - m_stoprequested = false; -@@ -1426,9 +1427,9 @@ void CEventSystem::EvaluateEvent(const std::string &reason, const uint64_t Devic - { - std::string dzv_scripts; - #ifdef WIN32 -- dzv_scripts = szUserDataFolder + "scripts\\dzVents\\scripts\\"; -+ dzv_scripts = szScriptsFolder + "dzVents\\scripts\\"; - #else -- dzv_scripts = szUserDataFolder + "scripts/dzVents/scripts/"; -+ dzv_scripts = szScriptsFolder + "dzVents/scripts/"; - #endif - DirectoryListing(FileEntries, dzv_scripts, false, true); - for (itt = FileEntries.begin(); itt != FileEntries.end(); ++itt) -@@ -2404,7 +2405,7 @@ bool CEventSystem::parseBlocklyActions(const std::string &Actions, const std::st - } - #if !defined WIN32 - if (sPath.find("/") != 0) -- sPath = szUserDataFolder + "scripts/" + sPath; -+ sPath = szScriptsFolder + sPath; - #endif - - m_sql.AddTaskItem(_tTaskItem::ExecuteScript(0.2f, sPath, sParam)); -@@ -3508,13 +3509,16 @@ void CEventSystem::EvaluateLua(const std::string &reason, const std::string &fil - { - std::stringstream lua_DirT; - -- lua_DirT << szUserDataFolder << -+ lua_DirT << szScriptsFolder << - #ifdef WIN32 -- "scripts\\dzVents\\"; -+ "dzVents\\"; - #else -- "scripts/dzVents/"; -+ "dzVents/"; - #endif - -+ lua_pushstring(lua_state, "generated_script_path"); -+ lua_pushstring(lua_state, dzv_Dir.c_str()); -+ lua_rawset(lua_state, -3); - lua_pushstring(lua_state, "script_path"); - lua_pushstring(lua_state, lua_DirT.str().c_str()); - lua_rawset(lua_state, -3); -@@ -4695,9 +4699,9 @@ namespace http { - - std::stringstream template_file; - #ifdef WIN32 -- template_file << szUserDataFolder << "scripts\\templates\\" << eventType << "." << interpreter; -+ template_file << szScriptsFolder << "templates\\" << eventType << "." << interpreter; - #else -- template_file << szUserDataFolder << "scripts/templates/" << eventType << "." << interpreter; -+ template_file << szScriptsFolder << "templates/" << eventType << "." << interpreter; - #endif - std::ifstream file; - std::stringstream template_content; -diff --git a/main/EventsPythonModule.cpp b/main/EventsPythonModule.cpp -index f69e7219..2d97562e 100644 ---- a/main/EventsPythonModule.cpp -+++ b/main/EventsPythonModule.cpp -@@ -108,7 +108,7 @@ - - int PythonEventsInitalized = 0; - -- bool PythonEventsInitialize(std::string szUserDataFolder) { -+ bool PythonEventsInitialize(std::string szScriptsFolder) { - - if (!Plugins::Py_LoadLibrary()) - { -@@ -131,9 +131,9 @@ - - std::string ssPath; - #ifdef WIN32 -- ssPath = szUserDataFolder + "scripts\\python\\;"; -+ ssPath = szScriptsFolder + "python\\;"; - #else -- ssPath = szUserDataFolder + "scripts/python/:"; -+ ssPath = szScriptsFolder + "python/:"; - #endif - - std::wstring sPath = std::wstring(ssPath.begin(), ssPath.end()); -diff --git a/main/LuaHandler.cpp b/main/LuaHandler.cpp -index 8fdcb278..c2ad98ff 100644 ---- a/main/LuaHandler.cpp -+++ b/main/LuaHandler.cpp -@@ -22,7 +22,7 @@ extern "C" { - #include "mainworker.h" - #include "../hardware/hardwaretypes.h" - --extern std::string szUserDataFolder; -+extern std::string szScriptsFolder; - - int CLuaHandler::l_domoticz_updateDevice(lua_State* lua_state) - { -@@ -155,9 +155,9 @@ bool CLuaHandler::executeLuaScript(const std::string &script, const std::string - { - std::stringstream lua_DirT; - #ifdef WIN32 -- lua_DirT << szUserDataFolder << "scripts\\lua_parsers\\"; -+ lua_DirT << szScriptsFolder << "lua_parsers\\"; - #else -- lua_DirT << szUserDataFolder << "scripts/lua_parsers/"; -+ lua_DirT << szScriptsFolder << "lua_parsers/"; - #endif - std::string lua_Dir = lua_DirT.str(); - -diff --git a/main/SQLHelper.cpp b/main/SQLHelper.cpp -index 491aa5a2..d529243a 100644 ---- a/main/SQLHelper.cpp -+++ b/main/SQLHelper.cpp -@@ -633,6 +633,7 @@ const char *sqlCreateMobileDevices = - "[LastUpdate] DATETIME DEFAULT(datetime('now', 'localtime'))" - ");"; - -+extern std::string szScriptsFolder; - extern std::string szUserDataFolder; - - CSQLHelper::CSQLHelper(void) -@@ -3683,9 +3684,9 @@ uint64_t CSQLHelper::UpdateValueInt(const int HardwareID, const char* ID, const - //Execute possible script - std::string scriptname; - #ifdef WIN32 -- scriptname = szUserDataFolder + "scripts\\domoticz_main.bat"; -+ scriptname = szScriptsFolder + "domoticz_main.bat"; - #else -- scriptname = szUserDataFolder + "scripts/domoticz_main"; -+ scriptname = szScriptsFolder + "domoticz_main"; - #endif - if (file_exist(scriptname.c_str())) - { -@@ -6641,7 +6642,7 @@ bool CSQLHelper::HandleOnOffAction(const bool bIsOn, const std::string &OnAction - std::string scriptname = OnAction.substr(9); - #if !defined WIN32 - if (scriptname.find("/") != 0) -- scriptname = szUserDataFolder + "scripts/" + scriptname; -+ scriptname = szScriptsFolder + scriptname; - #endif - std::string scriptparams=""; - //Add parameters -@@ -6675,7 +6676,7 @@ bool CSQLHelper::HandleOnOffAction(const bool bIsOn, const std::string &OnAction - std::string scriptname = OffAction.substr(9); - #if !defined WIN32 - if (scriptname.find("/") != 0) -- scriptname = szUserDataFolder + "scripts/" + scriptname; -+ scriptname = szScriptsFolder + scriptname; - #endif - std::string scriptparams = ""; - int pindex = scriptname.find(' '); -diff --git a/main/WebServer.cpp b/main/WebServer.cpp -index f8471791..d2cf10b2 100644 ---- a/main/WebServer.cpp -+++ b/main/WebServer.cpp -@@ -59,6 +59,7 @@ - - #define round(a) ( int ) ( a + .5 ) - -+extern std::string szScriptsFolder; - extern std::string szUserDataFolder; - extern std::string szWWWFolder; - -@@ -2987,9 +2988,9 @@ namespace http { - if (scriptname.find("..") != std::string::npos) - return; - #ifdef WIN32 -- scriptname = szUserDataFolder + "scripts\\" + scriptname; -+ scriptname = szScriptsFolder + scriptname; - #else -- scriptname = szUserDataFolder + "scripts/" + scriptname; -+ scriptname = szScriptsFolder + scriptname; - #endif - if (!file_exist(scriptname.c_str())) - return; -diff --git a/main/domoticz.cpp b/main/domoticz.cpp -index 5ef96f68..52599b14 100644 ---- a/main/domoticz.cpp -+++ b/main/domoticz.cpp -@@ -136,6 +136,7 @@ static const _facilities facilities[] = - }; - std::string logfacname = "user"; - #endif -+std::string szScriptsFolder; - std::string szStartupFolder; - std::string szUserDataFolder; - std::string szWWWFolder; -@@ -696,6 +697,19 @@ int main(int argc, char**argv) - szUserDataFolder = szroot; - } - -+ szScriptsFolder=szStartupFolder; -+ if (cmdLine.HasSwitch("-scripts")) -+ { -+ if (cmdLine.GetArgumentCount("-scripts") != 1) -+ { -+ _log.Log(LOG_ERROR, "Please specify a path for scripts directory"); -+ return 1; -+ } -+ std::string szroot = cmdLine.GetSafeArgument("-scripts", 0, ""); -+ if (szroot.size() != 0) -+ szScriptsFolder = szroot; -+ } -+ - if (cmdLine.HasSwitch("-startupdelay")) - { - if (cmdLine.GetArgumentCount("-startupdelay") != 1) -diff --git a/main/mainworker.cpp b/main/mainworker.cpp -index 803690e1..e89a783b 100644 ---- a/main/mainworker.cpp -+++ b/main/mainworker.cpp -@@ -159,6 +159,7 @@ - - #define round(a) ( int ) ( a + .5 ) - -+extern std::string szScriptsFolder; - extern std::string szStartupFolder; - extern std::string szUserDataFolder; - extern std::string szWWWFolder; -@@ -1473,8 +1474,8 @@ void MainWorker::Do_Work() - m_sql.GetPreferencesVar("ReleaseChannel", nValue); - bool bIsBetaChannel = (nValue != 0); - -- std::string scriptname = szUserDataFolder + "scripts/download_update.sh"; -- std::string strparm = szUserDataFolder; -+ std::string scriptname = szScriptsFolder + "download_update.sh"; -+ std::string strparm = szScriptsFolder; - if (bIsBetaChannel) - strparm += " /beta"; - -diff --git a/notifications/NotificationHTTP.cpp b/notifications/NotificationHTTP.cpp -index decff3b4..632e4e66 100644 ---- a/notifications/NotificationHTTP.cpp -+++ b/notifications/NotificationHTTP.cpp -@@ -6,7 +6,7 @@ - #include "../main/SQLHelper.h" - #include "../main/Logger.h" - --extern std::string szUserDataFolder; -+extern std::string szScriptsFolder; - - CNotificationHTTP::CNotificationHTTP() : CNotificationBase(std::string("http"), OPTIONS_NONE) - { -@@ -105,7 +105,7 @@ bool CNotificationHTTP::SendMessageImplementation( - std::string scriptparams = ""; - #if !defined WIN32 - if (scriptname.find("/") != 0) -- scriptname = szUserDataFolder + "scripts/" + scriptname; -+ scriptname = szScriptsFolder + scriptname; - #endif - //Add parameters - uPos = scriptname.find(" "); -diff --git a/push/GooglePubSubPush.cpp b/push/GooglePubSubPush.cpp -index 359a7d7c..46e489f6 100644 ---- a/push/GooglePubSubPush.cpp -+++ b/push/GooglePubSubPush.cpp -@@ -22,7 +22,7 @@ extern "C" { - using namespace boost::python; - #endif - --extern std::string szUserDataFolder; -+extern std::string szScriptsFolder; - - // this should be filled in by the preprocessor - extern const char * Python_exe; -@@ -231,11 +231,11 @@ void CGooglePubSubPush::DoGooglePubSubPush() - - #ifdef ENABLE_PYTHON_DECAP - #ifdef WIN32 -- python_DirT << szUserDataFolder << "scripts\\python\\"; -- std::string filename = szUserDataFolder + "scripts\\python\\" + "googlepubsub.py"; -+ python_DirT << szScriptsFolder << "python\\"; -+ std::string filename = szScriptsFolder + "python\\" + "googlepubsub.py"; - #else -- python_DirT << szUserDataFolder << "scripts/python/"; -- std::string filename = szUserDataFolder + "scripts/python/" + "googlepubsub.py"; -+ python_DirT << szScriptsFolder << "python/"; -+ std::string filename = szScriptsFolder + "python/" + "googlepubsub.py"; - #endif - - wchar_t * argv[1]; -diff --git a/scripts/dzVents/runtime/dzVents.lua b/scripts/dzVents/runtime/dzVents.lua -index d0dfa869..8370d6a9 100644 ---- a/scripts/dzVents/runtime/dzVents.lua -+++ b/scripts/dzVents/runtime/dzVents.lua -@@ -1,8 +1,9 @@ - local currentPath = globalvariables['script_path'] -+local generatedScriptPath = globalvariables['generated_script_path'] - local triggerReason = globalvariables['script_reason'] - - _G.scriptsFolderPath = currentPath .. 'scripts' -- global --_G.generatedScriptsFolderPath = currentPath .. 'generated_scripts' -- global -+_G.generatedScriptsFolderPath = generatedScriptPath -- global - _G.dataFolderPath = currentPath .. 'data' -- global - - package.path = package.path .. ';' .. currentPath .. '?.lua' -@@ -10,7 +11,7 @@ package.path = package.path .. ';' .. currentPath .. 'runtime/?.lua' - package.path = package.path .. ';' .. currentPath .. 'runtime/device-adapters/?.lua' - package.path = package.path .. ';' .. currentPath .. 'dzVents/?.lua' - package.path = package.path .. ';' .. currentPath .. 'scripts/?.lua' --package.path = package.path .. ';' .. currentPath .. 'generated_scripts/?.lua' -+package.path = package.path .. ';' .. generatedScriptPath .. '?.lua' - package.path = package.path .. ';' .. currentPath .. 'data/?.lua' - - local EventHelpers = require('EventHelpers')