You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

250 lines
9.0 KiB

  1. From 86a4fe7e28952f969609cfb52afae06b40aa273e Mon Sep 17 00:00:00 2001
  2. From: David Woodhouse <dwmw2@infradead.org>
  3. Date: Sat, 12 May 2018 15:11:29 +0100
  4. Subject: [PATCH] Add generic CustomCommand handling for scripts
  5. The Onkyo-specific support in JSON and dzVents isn't really sufficient,
  6. because it (quite rightly) needs authentication. But dzVents just assumes
  7. it can make unauthenticated calls to localhost:8080, and doesn't work.
  8. I've been working around this by spawning an external script to invoke
  9. curl, but *that* only works over HTTPS not HTTP for some reason (without
  10. HTTPS I just get an 'Unauthorized' response). And that takes literally
  11. *seconds* to work, on the slow machine I'm using.
  12. Fix it up so that the script command arrays can have a 'CustomCommand',
  13. done generically so that it can easily cover devices other than Onkyo.
  14. ---
  15. .../runtime/device-adapters/onkyo_device.lua | 4 +-
  16. hardware/DomoticzHardware.cpp | 5 ++
  17. hardware/DomoticzHardware.h | 1 +
  18. hardware/OnkyoAVTCP.cpp | 4 ++
  19. hardware/OnkyoAVTCP.h | 1 +
  20. main/EventSystem.cpp | 57 +++++++++++++++++++
  21. main/EventSystem.h | 1 +
  22. main/SQLHelper.cpp | 4 ++
  23. main/SQLHelper.h | 15 ++++-
  24. 9 files changed, 88 insertions(+), 4 deletions(-)
  25. diff --git a/dzVents/runtime/device-adapters/onkyo_device.lua b/dzVents/runtime/device-adapters/onkyo_device.lua
  26. index ec74841f..8222fe6b 100644
  27. --- a/dzVents/runtime/device-adapters/onkyo_device.lua
  28. +++ b/dzVents/runtime/device-adapters/onkyo_device.lua
  29. @@ -17,9 +17,7 @@ return {
  30. process = function (device, data, domoticz, utils, adapterManager)
  31. function device.onkyoEISCPCommand(cmd)
  32. - local url = domoticz.settings['Domoticz url'] ..
  33. - '/json.htm?param=onkyoeiscpcommand&type=command&idx=' .. device.id .. '&action=' .. tostring (cmd)
  34. - return domoticz.openURL(url)
  35. + return TimedCommand(domoticz, 'CustomCommand:' .. device.id, tostring(cmd), 'device')
  36. end
  37. end
  38. }
  39. diff --git a/hardware/DomoticzHardware.cpp b/hardware/DomoticzHardware.cpp
  40. index 7aad167b..75db53c0 100644
  41. --- a/hardware/DomoticzHardware.cpp
  42. +++ b/hardware/DomoticzHardware.cpp
  43. @@ -36,6 +36,11 @@ CDomoticzHardwareBase::~CDomoticzHardwareBase()
  44. {
  45. }
  46. +bool CDomoticzHardwareBase::CustomCommand(const uint64_t idx, const std::string &sCommand)
  47. +{
  48. + return false;
  49. +}
  50. +
  51. bool CDomoticzHardwareBase::Start()
  52. {
  53. m_iHBCounter = 0;
  54. diff --git a/hardware/DomoticzHardware.h b/hardware/DomoticzHardware.h
  55. index a8790f91..660fc2de 100644
  56. --- a/hardware/DomoticzHardware.h
  57. +++ b/hardware/DomoticzHardware.h
  58. @@ -16,6 +16,7 @@ public:
  59. bool Start();
  60. bool Stop();
  61. virtual bool WriteToHardware(const char *pdata, const unsigned char length)=0;
  62. + virtual bool CustomCommand(const uint64_t idx, const std::string &sCommand);
  63. void EnableOutputLog(const bool bEnableLog);
  64. diff --git a/hardware/OnkyoAVTCP.cpp b/hardware/OnkyoAVTCP.cpp
  65. index 88766032..9f386c01 100644
  66. --- a/hardware/OnkyoAVTCP.cpp
  67. +++ b/hardware/OnkyoAVTCP.cpp
  68. @@ -676,6 +676,10 @@ void OnkyoAVTCP::ParseData(const unsigned char *pData, int Len)
  69. m_pPartialPkt = new_partial;
  70. }
  71. +bool OnkyoAVTCP::CustomCommand(const uint64_t idx, const std::string &sCommand)
  72. +{
  73. + return SendPacket(sCommand.c_str());
  74. +}
  75. //Webserver helpers
  76. namespace http {
  77. diff --git a/hardware/OnkyoAVTCP.h b/hardware/OnkyoAVTCP.h
  78. index 90dbce51..133f4876 100644
  79. --- a/hardware/OnkyoAVTCP.h
  80. +++ b/hardware/OnkyoAVTCP.h
  81. @@ -21,6 +21,7 @@ private:
  82. int m_retrycntr;
  83. bool StartHardware();
  84. bool StopHardware();
  85. + bool CustomCommand(uint64_t idx, const std::string &sCommand);
  86. unsigned char *m_pPartialPkt;
  87. int m_PPktLen;
  88. void ReceiveMessage(const char *pData, int Len);
  89. diff --git a/main/EventSystem.cpp b/main/EventSystem.cpp
  90. index cdd3968b..19562d37 100644
  91. --- a/main/EventSystem.cpp
  92. +++ b/main/EventSystem.cpp
  93. @@ -2481,6 +2481,21 @@ bool CEventSystem::parseBlocklyActions(const _tEventItem &item)
  94. actionsDone = true;
  95. continue;
  96. }
  97. + else if (deviceName.find("CustomCommand:") == 0)
  98. + {
  99. + int idx = atoi(deviceName.substr(14).c_str());
  100. + float afterTimerSeconds = 0;
  101. + size_t aFind = doWhat.find(" AFTER ");
  102. + if ((aFind > 0) && (aFind != std::string::npos)) {
  103. + std::string delayString = doWhat.substr(aFind + 7);
  104. + afterTimerSeconds = static_cast<float>(atof(delayString.c_str()));
  105. + doWhat = doWhat.substr(0, aFind);
  106. + StripQuotes(doWhat);
  107. + }
  108. + m_sql.AddTaskItem(_tTaskItem::CustomCommand(afterTimerSeconds, idx, doWhat));
  109. + actionsDone = true;
  110. + continue;
  111. + }
  112. else
  113. {
  114. _log.Log(LOG_ERROR, "EventSystem: Unknown action sequence! (%s)", csubstr.c_str());
  115. @@ -2623,6 +2638,19 @@ bool CEventSystem::PythonScheduleEvent(std::string ID, const std::string &Action
  116. return false;
  117. }
  118. + return true;
  119. + } else if(ID.find("CustomCommand:") == 0) {
  120. + int idx = atoi(ID.substr(14).c_str());
  121. + std::string doWhat = std::string(Action);
  122. + float afterTimerSeconds = 0;
  123. + size_t aFind = Action.find(" AFTER ");
  124. + if ((aFind > 0) && (aFind != std::string::npos)) {
  125. + std::string delayString = doWhat.substr(aFind + 7);
  126. + doWhat = doWhat.substr(0, aFind);
  127. + afterTimerSeconds = static_cast<float>(atof(delayString.c_str()));
  128. + StripQuotes(doWhat);
  129. + }
  130. + m_sql.AddTaskItem(_tTaskItem::CustomCommand(afterTimerSeconds, idx, doWhat));
  131. return true;
  132. }
  133. return ScheduleEvent(ID, Action,eventName);
  134. @@ -3540,6 +3568,20 @@ bool CEventSystem::processLuaCommand(lua_State *lua_state, const std::string &fi
  135. return false;
  136. }
  137. }
  138. + else if (lCommand.find("CustomCommand:") == 0)
  139. + {
  140. + int idx = atoi(lCommand.substr(14).c_str());
  141. + std::string luaString = lua_tostring(lua_state, -1);
  142. + float afterTimerSeconds = 0;
  143. + size_t aFind = luaString.find(" AFTER ");
  144. + if ((aFind > 0) && (aFind != std::string::npos)) {
  145. + std::string delayString = luaString.substr(aFind + 7);
  146. + afterTimerSeconds = static_cast<float>(atof(delayString.c_str()));
  147. + luaString = luaString.substr(0, aFind);
  148. + StripQuotes(luaString);
  149. + }
  150. + m_sql.AddTaskItem(_tTaskItem::CustomCommand(afterTimerSeconds, idx, luaString));
  151. + }
  152. else
  153. {
  154. if (ScheduleEvent(lua_tostring(lua_state, -2), lua_tostring(lua_state, -1), filename)) {
  155. @@ -3557,6 +3599,21 @@ void CEventSystem::report_errors(lua_State *L, int status, std::string filename)
  156. }
  157. }
  158. +bool CEventSystem::CustomCommand(const uint64_t idx, const std::string &sCommand)
  159. +{
  160. + std::vector<std::vector<std::string> > result;
  161. + result = m_sql.safe_query("SELECT H.ID FROM DeviceStatus DS, Hardware H WHERE (DS.ID=='%u') AND (DS.HardwareID == H.ID)", idx);
  162. + if (result.size() != 1)
  163. + return false;
  164. +
  165. + int HardwareID = atoi(result[0][0].c_str());
  166. + CDomoticzHardwareBase *pHardware = m_mainworker.GetHardware(HardwareID);
  167. + if (!pHardware)
  168. + return false;
  169. +
  170. + return pHardware->CustomCommand(idx, sCommand);
  171. +}
  172. +
  173. void CEventSystem::UpdateDevice(const uint64_t idx, const int nValue, const std::string &sValue, const int Protected, const bool bEventTrigger)
  174. {
  175. //Get device parameters
  176. diff --git a/main/EventSystem.h b/main/EventSystem.h
  177. index d154c4e8..cfebe2cc 100644
  178. --- a/main/EventSystem.h
  179. +++ b/main/EventSystem.h
  180. @@ -131,6 +131,7 @@ public:
  181. bool GetEventTrigger(const uint64_t ulDevID, const _eReason reason, const bool bEventTrigger);
  182. void SetEventTrigger(const uint64_t ulDevID, const _eReason reason, const float fDelayTime);
  183. void UpdateDevice(const uint64_t idx, const int nValue, const std::string &sValue, const int Protected, const bool bEventTrigger = false);
  184. + bool CustomCommand(const uint64_t idx, const std::string &sCommand);
  185. void TriggerURL(const std::string &result, const std::vector<std::string> &headerData, const std::string &callback);
  186. diff --git a/main/SQLHelper.cpp b/main/SQLHelper.cpp
  187. index 7a46f021..0ea71d54 100644
  188. --- a/main/SQLHelper.cpp
  189. +++ b/main/SQLHelper.cpp
  190. @@ -3401,6 +3401,10 @@ void CSQLHelper::Do_Work()
  191. {
  192. m_mainworker.m_eventsystem.UpdateDevice(itt->_idx, itt->_nValue, itt->_sValue, itt->_HardwareID, (itt->_switchtype ? true : false));
  193. }
  194. + else if (itt->_ItemType == TITEM_CUSTOM_COMMAND)
  195. + {
  196. + m_mainworker.m_eventsystem.CustomCommand(itt->_idx, itt->_command);
  197. + }
  198. ++itt;
  199. }
  200. diff --git a/main/SQLHelper.h b/main/SQLHelper.h
  201. index c0d40580..8ad60e3d 100644
  202. --- a/main/SQLHelper.h
  203. +++ b/main/SQLHelper.h
  204. @@ -49,7 +49,8 @@ enum _eTaskItemType
  205. TITEM_SEND_NOTIFICATION,
  206. TITEM_SET_SETPOINT,
  207. TITEM_SEND_IFTTT_TRIGGER,
  208. - TITEM_UPDATEDEVICE
  209. + TITEM_UPDATEDEVICE,
  210. + TITEM_CUSTOM_COMMAND,
  211. };
  212. struct _tTaskItem
  213. @@ -261,6 +262,18 @@ struct _tTaskItem
  214. tItem._sValue = varvalue;
  215. tItem._command = mode;
  216. tItem._sUntil = until;
  217. +
  218. + if (DelayTime)
  219. + getclock(&tItem._DelayTimeBegin);
  220. + return tItem;
  221. + }
  222. + static _tTaskItem CustomCommand(const float DelayTime, const uint64_t idx, const std::string &cmdstr)
  223. + {
  224. + _tTaskItem tItem;
  225. + tItem._ItemType = TITEM_CUSTOM_COMMAND;
  226. + tItem._DelayTime = DelayTime;
  227. + tItem._idx = idx;
  228. + tItem._command = cmdstr;
  229. if (DelayTime)
  230. getclock(&tItem._DelayTimeBegin);
  231. return tItem;
  232. --
  233. 2.17.0