PageRenderTime 24ms CodeModel.GetById 19ms RepoModel.GetById 1ms app.codeStats 0ms

/scripts/activity.js

https://gitlab.com/smartboxasia/dss-addon-tado
JavaScript | 388 lines | 348 code | 40 blank | 0 comment | 57 complexity | cd0d5eb678efdcc5814271a0ba03e7e1 MD5 | raw file
  1. function storeActivity(activity) {
  2. var id, node;
  3. try {
  4. activity = JSON.parse(activity);
  5. if (activity.id === undefined || activity.id === null) {
  6. id = getId();
  7. } else {
  8. id = activity.id;
  9. unregisterTrigger('entries/' + id);
  10. }
  11. node = Property.getNode('entries');
  12. if (node) {
  13. node.removeChild(id);
  14. }
  15. Property.setSavedProperty('entries/' + id + '/id', id);
  16. Property.setSavedProperty('entries/' + id + '/conditions/enabled', true);
  17. putActionParameter('entries/' + id, activity.action);
  18. putConditionParameter('entries/' + id, activity.conditions);
  19. putTriggerParameter('entries/' + id, activity.triggers);
  20. var action = JSON.stringify(activity.action);
  21. action = encodeURIComponent(action); // FIXME best if this LOC can be removed. see http://imgur.com/a/MeWOk
  22. registerTrigger('/scripts/tado/entries/' + id, 'tado.execute', {
  23. action: action
  24. });
  25. Property.store();
  26. return true;
  27. } catch (e) {
  28. Log.logln('Activity Error: ' + e);
  29. if (e.stack) {
  30. Log.logln(e.stack);
  31. }
  32. node = Property.getNode('entries');
  33. if (node) {
  34. node.removeChild(id); // clear insert activity when error happens
  35. }
  36. Property.store();
  37. return false;
  38. }
  39. }
  40. function getId() {
  41. var id = 0;
  42. var entriesNode = Property.getNode('entries');
  43. if (!entriesNode) {
  44. return id;
  45. }
  46. entriesNode.getChildren().forEach(function(entryNode) {
  47. if (!entryNode.getChild('id')) {
  48. return;
  49. }
  50. var _id = parseInt(entryNode.getChild('id').getValue());
  51. if (isNaN(_id) || _id < id) {
  52. return;
  53. }
  54. id = _id + 1;
  55. });
  56. return id;
  57. }
  58. function putActionParameter(path, action) {
  59. var subPath = path + '/action/';
  60. storeStringParameter(subPath + 'deviceId', action.deviceId);
  61. var setting = action.setting;
  62. var settingPath = subPath + 'setting/';
  63. storeStringParameter(settingPath + 'power', setting.power);
  64. storeStringParameter(settingPath + 'type', setting.type);
  65. if (setting.mode) {
  66. storeStringParameter(settingPath + 'mode', setting.mode);
  67. if (setting.temperature && setting.temperature.celsius) {
  68. storeIntParameter(settingPath + 'temperature/celsius', setting.temperature.celsius);
  69. }
  70. if (setting.fanSpeed) {
  71. storeStringParameter(settingPath + 'fanSpeed', setting.fanSpeed);
  72. }
  73. if (setting.swing) {
  74. storeStringParameter(settingPath + 'swing', setting.swing);
  75. }
  76. }
  77. }
  78. function putConditionParameter(path, conditions) {
  79. if (!conditions) {
  80. return;
  81. }
  82. var subPath = path + '/conditions/';
  83. Property.setSavedProperty(subPath + 'enabled', conditions.enabled === true);
  84. if (conditions.weekdays) {
  85. var val = '';
  86. conditions.weekdays.forEach(function(weekday) {
  87. switch (weekday) {
  88. case 'SU':
  89. val += '0,';
  90. break;
  91. case 'MO':
  92. val += '1,';
  93. break;
  94. case 'TU':
  95. val += '2,';
  96. break;
  97. case 'WE':
  98. val += '3,';
  99. break;
  100. case 'TH':
  101. val += '4,';
  102. break;
  103. case 'FR':
  104. val += '5,';
  105. break;
  106. case 'SA':
  107. val += '6,';
  108. break;
  109. }
  110. });
  111. if (val.length > 0) {
  112. val = val.substr(0, val.length - 1);
  113. Property.setSavedProperty(subPath + 'weekdays', val);
  114. }
  115. }
  116. if (conditions.systemState) {
  117. conditions.systemState.forEach(function(systemState) {
  118. var name = systemState.name;
  119. var value = systemState.value;
  120. if (value === 'true') {
  121. value = true;
  122. }
  123. if (value === 'false') {
  124. value = false;
  125. }
  126. Property.setSavedProperty(subPath + 'states/' + name, value);
  127. });
  128. }
  129. if (conditions.addonStates) {
  130. for (var addonId in conditions.addonStates) {
  131. conditions.addonStates[addonId].forEach(function(addonStates) { // jshint ignore:line
  132. var name = addonStates.name;
  133. var value = addonStates.value;
  134. if (value === true || value === 'true') {
  135. value = 1;
  136. }
  137. if (value === false || value === 'false') {
  138. value = 2;
  139. }
  140. Property.setSavedProperty(subPath + 'addon-states/' + addonId + '/' + name, value);
  141. });
  142. }
  143. }
  144. if (conditions.zoneState) {
  145. conditions.zoneState.forEach(function(zoneState, i) {
  146. checkAndStoreIntParameter(subPath + 'zone-states/' + i + '/zone', zoneState.zone);
  147. checkAndStoreIntParameter(subPath + 'zone-states/' + i + '/group', zoneState.group);
  148. checkAndStoreIntParameter(subPath + 'zone-states/' + i + '/scene', zoneState.scene);
  149. });
  150. }
  151. if (conditions.timeframe) {
  152. conditions.timeframe.forEach(function(timeframe) {
  153. var startBase = timeframe.start.timeBase;
  154. var startOffset = timeframe.start.offset;
  155. var endBase = timeframe.end.timeBase;
  156. var endOffset = timeframe.end.offset;
  157. if (startBase === 'daily' && endBase === 'daily') {
  158. Property.setSavedProperty(subPath + 'time-start', Math.floor(parseInt('' + startOffset) / 3600) + ':' + Math.floor(parseInt('' + startOffset) / 60) % 60 + ':' + Math.floor(parseInt('' + startOffset) % 60));
  159. Property.setSavedProperty(subPath + 'time-end', Math.floor(parseInt('' + endOffset) / 3600) + ':' + Math.floor(parseInt('' + endOffset) / 60) % 60 + ':' + Math.floor(parseInt('' + endOffset) % 60));
  160. }
  161. });
  162. }
  163. }
  164. function putTriggerParameter(path, triggers) {
  165. triggers.forEach(function(trigger, idx) {
  166. var subPath = path + '/triggers/' + (idx + 1) + '/';
  167. switch (trigger.type) {
  168. case 'bus-zone-scene':
  169. case 'zone-scene':
  170. case 'undo-zone-scene':
  171. storeStringParameter(subPath + 'type', trigger.type);
  172. storeIntParameter(subPath + 'zone', trigger.zone);
  173. storeIntParameter(subPath + 'group', trigger.group);
  174. storeIntParameter(subPath + 'scene', trigger.scene);
  175. if (trigger.forced) {
  176. storeBoolParameter(subPath + 'forced', trigger.forced);
  177. }
  178. Property.setSavedProperty(subPath + 'dsuid', -1);
  179. break;
  180. case 'device-msg':
  181. storeStringParameter(subPath + 'type', trigger.type);
  182. storeDSUIDParameter(subPath + 'dsuid', trigger.dsuid, trigger.dsid);
  183. storeIntParameter(subPath + 'msg', trigger.msg);
  184. if (trigger.buttonIndex) {
  185. storeIntParameter(subPath + 'buttonIndex', trigger.buttonIndex);
  186. }
  187. break;
  188. case 'device-action':
  189. storeStringParameter(subPath + 'type', trigger.type);
  190. storeDSUIDParameter(subPath + 'dsuid', trigger.dsuid, trigger.dsid);
  191. storeIntParameter(subPath + 'action', trigger.action);
  192. break;
  193. case 'device-binary-input':
  194. storeStringParameter(subPath + 'type', trigger.type);
  195. storeIntParameter(subPath + 'index', trigger.index);
  196. storeStringParameter(subPath + 'state', trigger.state);
  197. break;
  198. case 'device-scene':
  199. storeStringParameter(subPath + 'type', trigger.type);
  200. storeDSUIDParameter(subPath + 'dsuid', trigger.dsuid, trigger.dsid);
  201. storeIntParameter(subPath + 'scene', trigger.scene);
  202. break;
  203. case 'custom-event':
  204. storeStringParameter(subPath + 'type', trigger.type);
  205. storeIntParameter(subPath + 'event', trigger.event);
  206. break;
  207. case 'device-sensor':
  208. storeStringParameter(subPath + 'type', trigger.type);
  209. storeDSUIDParameter(subPath + 'dsuid', trigger.dsuid, trigger.dsid);
  210. storeStringParameter(subPath + 'eventid', trigger.eventid);
  211. break;
  212. case 'state-change':
  213. storeStringParameter(subPath + 'type', trigger.type);
  214. storeStringParameter(subPath + 'name', trigger.name);
  215. storeStringParameter(subPath + 'state', trigger.state);
  216. break;
  217. case 'addon-state-change':
  218. storeStringParameter(subPath + 'type', trigger.type);
  219. storeStringParameter(subPath + 'addon-id', trigger.addonId);
  220. storeStringParameter(subPath + 'name', trigger.name);
  221. storeStringParameter(subPath + 'state', trigger.state);
  222. break;
  223. }
  224. });
  225. }
  226. function storeStringParameter(path, value) {
  227. Property.setSavedProperty(path, '' + value);
  228. }
  229. function storeIntParameter(path, value) {
  230. if (isNaN(parseInt(value))) {
  231. throw new Error('wrong argument types. path: ' + path + ', value: ' + value);
  232. }
  233. Property.setSavedProperty(path, parseInt(value));
  234. }
  235. function storeBoolParameter(path, value) {
  236. if (typeof(value) === 'boolean') {
  237. Property.setSavedProperty(path, value);
  238. } else if (typeof(value) === 'string') {
  239. value = value === 'true';
  240. Property.setSavedProperty(path, value);
  241. } else {
  242. throw new Error('wrong argument types. path: ' + path + ', value: ' + value);
  243. }
  244. }
  245. function storeDSUIDParameter(path, dsuid, dsid) {
  246. if (typeof(dsuid) === 'string') {
  247. Property.setSavedProperty(path, dsuid);
  248. } else if (typeof(dsid) === 'string') {
  249. Property.setSavedProperty(path, dSID2dSUID(dsid));
  250. } else {
  251. throw new Error('wrong argument types. path: ' + path + ', value: ' + value);
  252. }
  253. }
  254. function dSID2dSUID(dSID) {
  255. try {
  256. var dSUID = dSID.slice(0, 12); // copy the first 6 bytes (12 characters to the new dsuid
  257. dSUID += '00000000'; // insert 4 bytes of 0
  258. dSUID += dSID.slice(12, 24); // append the remaining 6 bytes (12 chars) of the dsid
  259. dSUID += '00'; // finaly add 1 byte of 0
  260. return dSUID;
  261. } catch (e) {
  262. throw new Error('invalid dSID ' + dSID);
  263. }
  264. }
  265. function toggleActivity(ids, enable) {
  266. var success = false;
  267. var entriesNode = Property.getNode('entries');
  268. if (!entriesNode) {
  269. return success;
  270. }
  271. ids = JSON.parse(ids);
  272. ids.forEach(function(id) {
  273. var sanityCheck = Property.getNode('entries/' + id);
  274. if (sanityCheck) {
  275. Property.setSavedProperty('entries/' + id + '/conditions/enabled', enable);
  276. success = true;
  277. }
  278. });
  279. Property.store();
  280. return success;
  281. }
  282. var success = false;
  283. var actions = raisedEvent.parameter.actions;
  284. if (actions === 'save') {
  285. try {
  286. success = storeActivity(raisedEvent.parameter.activity);
  287. } catch (e) {
  288. Log.logln('Error: ' + e.stack);
  289. }
  290. new Event('tado.response', {
  291. actions: 'activity.save',
  292. ok: success
  293. }).raise();
  294. } else if (actions === 'enable') {
  295. try {
  296. success = toggleActivity(raisedEvent.parameter.ids, true);
  297. } catch (e) {
  298. Log.logln('Error: ' + e.stack);
  299. }
  300. new Event('tado.response', {
  301. actions: 'activity.enable',
  302. ok: success
  303. }).raise();
  304. } else if (actions === 'disable') {
  305. try {
  306. success = toggleActivity(raisedEvent.parameter.ids, false);
  307. } catch (e) {
  308. Log.logln('Error: ' + e.stack);
  309. }
  310. new Event('tado.response', {
  311. actions: 'activity.disable',
  312. ok: success
  313. }).raise();
  314. } else if (actions === 'delete') {
  315. try {
  316. var entriesNode = Property.getNode('entries');
  317. if (entriesNode) {
  318. var ids = JSON.parse(raisedEvent.parameter.ids);
  319. ids.forEach(function(id) {
  320. entriesNode.removeChild(id);
  321. unregisterTrigger(entriesNode.getPath() + '/' + id);
  322. success = true;
  323. });
  324. Property.store();
  325. } else {
  326. success = true;
  327. }
  328. } catch (e) {
  329. Log.logln('Error: ' + e.stack);
  330. }
  331. new Event('tado.response', {
  332. actions: 'activity.delete',
  333. ok: success
  334. }).raise();
  335. } else if (actions === 'test') {
  336. try {
  337. new Event('tado.execute', {
  338. action: raisedEvent.parameter.action
  339. }).raise();
  340. success = true;
  341. } catch (e) {
  342. Log.logln('Error: ' + e.stack);
  343. }
  344. new Event('tado.response', {
  345. actions: 'activity.test',
  346. ok: success
  347. }).raise();
  348. }