diff --git a/utils/domoticz/Makefile b/utils/domoticz/Makefile index d8dee8139..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,21 +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_CXXFLAGS+=-DWITH_GPIO +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* \ @@ -83,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.config b/utils/domoticz/files/domoticz.config index b300f3f2d..870701c05 100644 --- a/utils/domoticz/files/domoticz.config +++ b/utils/domoticz/files/domoticz.config @@ -5,6 +5,7 @@ config domoticz # option sslcert '/path/to/ssl.crt' # option sslkey '/path/to/ssl.key' # option sslpass 'passphrase' + # option ssldhparam '/path/to/dhparam.pem' option sslwww '0' # CAUTION - by default, /var is not persistent accross reboots # Don't forget the trailing / - domoticz requires it diff --git a/utils/domoticz/files/domoticz.hotplug b/utils/domoticz/files/domoticz.hotplug index 7138175ef..3cd8651c1 100644 --- a/utils/domoticz/files/domoticz.hotplug +++ b/utils/domoticz/files/domoticz.hotplug @@ -28,7 +28,7 @@ add() { chgrp domoticz "/dev/$DEVICENAME" chmod g+rw "/dev/$DEVICENAME" - [ -n "$symlink" ] && ln -s "/dev/$DEVICENAME" "/dev/$symlink" + [ -n "$symlink" ] && ln -sf "/dev/$DEVICENAME" "/dev/$symlink" } remove() { diff --git a/utils/domoticz/files/domoticz.init b/utils/domoticz/files/domoticz.init index 26e0c42d4..89aaeae0c 100644 --- a/utils/domoticz/files/domoticz.init +++ b/utils/domoticz/files/domoticz.init @@ -13,23 +13,38 @@ start_domoticz() { config_get sslcert "$section" "sslcert" config_get sslkey "$section" "sslkey" config_get sslpass "$section" "sslpass" + 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" [ -n "$sslkey" ] && procd_append_param command -sslkey "$sslkey" [ -n "$sslpass" ] && procd_append_param command -sslpass "$sslpass" + [ -n "$ssldhparam" ] && procd_append_param command -ssldhparam "$ssldhparam" } || procd_append_param command -sslwww 0 } @@ -37,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/101_onkyo_pr2386.patch b/utils/domoticz/patches/101_onkyo_pr2386.patch new file mode 100644 index 000000000..ce624428f --- /dev/null +++ b/utils/domoticz/patches/101_onkyo_pr2386.patch @@ -0,0 +1,250 @@ +From 86a4fe7e28952f969609cfb52afae06b40aa273e Mon Sep 17 00:00:00 2001 +From: David Woodhouse +Date: Sat, 12 May 2018 15:11:29 +0100 +Subject: [PATCH] Add generic CustomCommand handling for scripts + +The Onkyo-specific support in JSON and dzVents isn't really sufficient, +because it (quite rightly) needs authentication. But dzVents just assumes +it can make unauthenticated calls to localhost:8080, and doesn't work. + +I've been working around this by spawning an external script to invoke +curl, but *that* only works over HTTPS not HTTP for some reason (without +HTTPS I just get an 'Unauthorized' response). And that takes literally +*seconds* to work, on the slow machine I'm using. + +Fix it up so that the script command arrays can have a 'CustomCommand', +done generically so that it can easily cover devices other than Onkyo. +--- + .../runtime/device-adapters/onkyo_device.lua | 4 +- + hardware/DomoticzHardware.cpp | 5 ++ + hardware/DomoticzHardware.h | 1 + + hardware/OnkyoAVTCP.cpp | 4 ++ + hardware/OnkyoAVTCP.h | 1 + + main/EventSystem.cpp | 57 +++++++++++++++++++ + main/EventSystem.h | 1 + + main/SQLHelper.cpp | 4 ++ + main/SQLHelper.h | 15 ++++- + 9 files changed, 88 insertions(+), 4 deletions(-) + +diff --git a/dzVents/runtime/device-adapters/onkyo_device.lua b/dzVents/runtime/device-adapters/onkyo_device.lua +index ec74841f..8222fe6b 100644 +--- a/dzVents/runtime/device-adapters/onkyo_device.lua ++++ b/dzVents/runtime/device-adapters/onkyo_device.lua +@@ -17,9 +17,7 @@ return { + process = function (device, data, domoticz, utils, adapterManager) + + function device.onkyoEISCPCommand(cmd) +- local url = domoticz.settings['Domoticz url'] .. +- '/json.htm?param=onkyoeiscpcommand&type=command&idx=' .. device.id .. '&action=' .. tostring (cmd) +- return domoticz.openURL(url) ++ return TimedCommand(domoticz, 'CustomCommand:' .. device.id, tostring(cmd), 'device') + end + end + } +diff --git a/hardware/DomoticzHardware.cpp b/hardware/DomoticzHardware.cpp +index 7aad167b..75db53c0 100644 +--- a/hardware/DomoticzHardware.cpp ++++ b/hardware/DomoticzHardware.cpp +@@ -36,6 +36,11 @@ CDomoticzHardwareBase::~CDomoticzHardwareBase() + { + } + ++bool CDomoticzHardwareBase::CustomCommand(const uint64_t idx, const std::string &sCommand) ++{ ++ return false; ++} ++ + bool CDomoticzHardwareBase::Start() + { + m_iHBCounter = 0; +diff --git a/hardware/DomoticzHardware.h b/hardware/DomoticzHardware.h +index a8790f91..660fc2de 100644 +--- a/hardware/DomoticzHardware.h ++++ b/hardware/DomoticzHardware.h +@@ -16,6 +16,7 @@ public: + bool Start(); + bool Stop(); + virtual bool WriteToHardware(const char *pdata, const unsigned char length)=0; ++ virtual bool CustomCommand(const uint64_t idx, const std::string &sCommand); + + void EnableOutputLog(const bool bEnableLog); + +diff --git a/hardware/OnkyoAVTCP.cpp b/hardware/OnkyoAVTCP.cpp +index 88766032..9f386c01 100644 +--- a/hardware/OnkyoAVTCP.cpp ++++ b/hardware/OnkyoAVTCP.cpp +@@ -676,6 +676,10 @@ void OnkyoAVTCP::ParseData(const unsigned char *pData, int Len) + m_pPartialPkt = new_partial; + } + ++bool OnkyoAVTCP::CustomCommand(const uint64_t idx, const std::string &sCommand) ++{ ++ return SendPacket(sCommand.c_str()); ++} + + //Webserver helpers + namespace http { +diff --git a/hardware/OnkyoAVTCP.h b/hardware/OnkyoAVTCP.h +index 90dbce51..133f4876 100644 +--- a/hardware/OnkyoAVTCP.h ++++ b/hardware/OnkyoAVTCP.h +@@ -21,6 +21,7 @@ private: + int m_retrycntr; + bool StartHardware(); + bool StopHardware(); ++ bool CustomCommand(uint64_t idx, const std::string &sCommand); + unsigned char *m_pPartialPkt; + int m_PPktLen; + void ReceiveMessage(const char *pData, int Len); +diff --git a/main/EventSystem.cpp b/main/EventSystem.cpp +index cdd3968b..19562d37 100644 +--- a/main/EventSystem.cpp ++++ b/main/EventSystem.cpp +@@ -2481,6 +2481,21 @@ bool CEventSystem::parseBlocklyActions(const _tEventItem &item) + actionsDone = true; + continue; + } ++ else if (deviceName.find("CustomCommand:") == 0) ++ { ++ int idx = atoi(deviceName.substr(14).c_str()); ++ float afterTimerSeconds = 0; ++ size_t aFind = doWhat.find(" AFTER "); ++ if ((aFind > 0) && (aFind != std::string::npos)) { ++ std::string delayString = doWhat.substr(aFind + 7); ++ afterTimerSeconds = static_cast(atof(delayString.c_str())); ++ doWhat = doWhat.substr(0, aFind); ++ StripQuotes(doWhat); ++ } ++ m_sql.AddTaskItem(_tTaskItem::CustomCommand(afterTimerSeconds, idx, doWhat)); ++ actionsDone = true; ++ continue; ++ } + else + { + _log.Log(LOG_ERROR, "EventSystem: Unknown action sequence! (%s)", csubstr.c_str()); +@@ -2623,6 +2638,19 @@ bool CEventSystem::PythonScheduleEvent(std::string ID, const std::string &Action + return false; + } + ++ return true; ++ } else if(ID.find("CustomCommand:") == 0) { ++ int idx = atoi(ID.substr(14).c_str()); ++ std::string doWhat = std::string(Action); ++ float afterTimerSeconds = 0; ++ size_t aFind = Action.find(" AFTER "); ++ if ((aFind > 0) && (aFind != std::string::npos)) { ++ std::string delayString = doWhat.substr(aFind + 7); ++ doWhat = doWhat.substr(0, aFind); ++ afterTimerSeconds = static_cast(atof(delayString.c_str())); ++ StripQuotes(doWhat); ++ } ++ m_sql.AddTaskItem(_tTaskItem::CustomCommand(afterTimerSeconds, idx, doWhat)); + return true; + } + return ScheduleEvent(ID, Action,eventName); +@@ -3540,6 +3568,20 @@ bool CEventSystem::processLuaCommand(lua_State *lua_state, const std::string &fi + return false; + } + } ++ else if (lCommand.find("CustomCommand:") == 0) ++ { ++ int idx = atoi(lCommand.substr(14).c_str()); ++ std::string luaString = lua_tostring(lua_state, -1); ++ float afterTimerSeconds = 0; ++ size_t aFind = luaString.find(" AFTER "); ++ if ((aFind > 0) && (aFind != std::string::npos)) { ++ std::string delayString = luaString.substr(aFind + 7); ++ afterTimerSeconds = static_cast(atof(delayString.c_str())); ++ luaString = luaString.substr(0, aFind); ++ StripQuotes(luaString); ++ } ++ m_sql.AddTaskItem(_tTaskItem::CustomCommand(afterTimerSeconds, idx, luaString)); ++ } + else + { + if (ScheduleEvent(lua_tostring(lua_state, -2), lua_tostring(lua_state, -1), filename)) { +@@ -3557,6 +3599,21 @@ void CEventSystem::report_errors(lua_State *L, int status, std::string filename) + } + } + ++bool CEventSystem::CustomCommand(const uint64_t idx, const std::string &sCommand) ++{ ++ std::vector > result; ++ result = m_sql.safe_query("SELECT H.ID FROM DeviceStatus DS, Hardware H WHERE (DS.ID=='%u') AND (DS.HardwareID == H.ID)", idx); ++ if (result.size() != 1) ++ return false; ++ ++ int HardwareID = atoi(result[0][0].c_str()); ++ CDomoticzHardwareBase *pHardware = m_mainworker.GetHardware(HardwareID); ++ if (!pHardware) ++ return false; ++ ++ return pHardware->CustomCommand(idx, sCommand); ++} ++ + void CEventSystem::UpdateDevice(const uint64_t idx, const int nValue, const std::string &sValue, const int Protected, const bool bEventTrigger) + { + //Get device parameters +diff --git a/main/EventSystem.h b/main/EventSystem.h +index d154c4e8..cfebe2cc 100644 +--- a/main/EventSystem.h ++++ b/main/EventSystem.h +@@ -131,6 +131,7 @@ public: + bool GetEventTrigger(const uint64_t ulDevID, const _eReason reason, const bool bEventTrigger); + void SetEventTrigger(const uint64_t ulDevID, const _eReason reason, const float fDelayTime); + void UpdateDevice(const uint64_t idx, const int nValue, const std::string &sValue, const int Protected, const bool bEventTrigger = false); ++ bool CustomCommand(const uint64_t idx, const std::string &sCommand); + + void TriggerURL(const std::string &result, const std::vector &headerData, const std::string &callback); + +diff --git a/main/SQLHelper.cpp b/main/SQLHelper.cpp +index 7a46f021..0ea71d54 100644 +--- a/main/SQLHelper.cpp ++++ b/main/SQLHelper.cpp +@@ -3401,6 +3401,10 @@ void CSQLHelper::Do_Work() + { + m_mainworker.m_eventsystem.UpdateDevice(itt->_idx, itt->_nValue, itt->_sValue, itt->_HardwareID, (itt->_switchtype ? true : false)); + } ++ else if (itt->_ItemType == TITEM_CUSTOM_COMMAND) ++ { ++ m_mainworker.m_eventsystem.CustomCommand(itt->_idx, itt->_command); ++ } + + ++itt; + } +diff --git a/main/SQLHelper.h b/main/SQLHelper.h +index c0d40580..8ad60e3d 100644 +--- a/main/SQLHelper.h ++++ b/main/SQLHelper.h +@@ -49,7 +49,8 @@ enum _eTaskItemType + TITEM_SEND_NOTIFICATION, + TITEM_SET_SETPOINT, + TITEM_SEND_IFTTT_TRIGGER, +- TITEM_UPDATEDEVICE ++ TITEM_UPDATEDEVICE, ++ TITEM_CUSTOM_COMMAND, + }; + + struct _tTaskItem +@@ -261,6 +262,18 @@ struct _tTaskItem + tItem._sValue = varvalue; + tItem._command = mode; + tItem._sUntil = until; ++ ++ if (DelayTime) ++ getclock(&tItem._DelayTimeBegin); ++ return tItem; ++ } ++ static _tTaskItem CustomCommand(const float DelayTime, const uint64_t idx, const std::string &cmdstr) ++ { ++ _tTaskItem tItem; ++ tItem._ItemType = TITEM_CUSTOM_COMMAND; ++ tItem._DelayTime = DelayTime; ++ tItem._idx = idx; ++ tItem._command = cmdstr; + if (DelayTime) + getclock(&tItem._DelayTimeBegin); + return tItem; +-- +2.17.0 + 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')